insertPositionTipInEditor.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. <template>
  2. <div
  3. class="insert-position-tip"
  4. @dragenter="onDragEnter"
  5. @dragover="onDragOver"
  6. @dragleave="onDragLeave"
  7. @drop="onDrop"
  8. :style="{
  9. marginLeft: marginLeft,
  10. }"
  11. >
  12. {{positionDebug}}
  13. </div>
  14. </template>
  15. <script>
  16. import { mapGetters } from "vuex";
  17. import { deepClone } from "@/utils/other.js";
  18. export default {
  19. props: {
  20. index: {
  21. type: Number,
  22. required: true,
  23. },
  24. positionDebug: {
  25. type: String,
  26. default: '',
  27. },
  28. indentLevel: {
  29. type: Number,
  30. default: 1,
  31. },
  32. topologyLevel: {
  33. type: Number,
  34. default: 1,
  35. },
  36. parentNode: {
  37. type: Object,
  38. default: null,
  39. },
  40. },
  41. computed: {
  42. ...mapGetters({
  43. info: 'info',
  44. dragInfo: 'editorNavDragInfo',
  45. }),
  46. marginLeft() {
  47. return (this.indentLevel - 1) * 12 + 'px'
  48. },
  49. },
  50. methods: {
  51. canDrop() {
  52. switch (this.dragInfo.type) {
  53. case 'scene': // 被拖拽的是场景
  54. if (this.topologyLevel === 1) {
  55. // console.log('情况1:被拖拽的是场景,拖拽到一级分组列表');
  56. return false
  57. } else if (this.topologyLevel === 2) {
  58. // console.log('情况2:被拖拽的是场景,拖拽到一级分组中');
  59. if (this.parentNode.children.length === 0) { // 如果目标一级分组内容显示是空的,即其下只有一个(内容肯定是空的)默认二级分组
  60. return true
  61. } else { // 如果目标一级分组之下显示了内容,则肯定是显示了二级分组。
  62. return false
  63. }
  64. } else if (this.topologyLevel === 3) {
  65. // console.log('情况3:被拖拽的是场景,拖拽到二级分组中');
  66. return true
  67. } else {
  68. console.error('情况4:不该出现');
  69. return false
  70. }
  71. case 'topologyGroupLevel2': // 被拖拽的是拓扑结构中二级分组
  72. if (this.topologyLevel === 1) {
  73. // console.log('情况5:被拖拽的是拓扑结构中二级分组,拖拽到一级分组列表');
  74. return true
  75. } else if (this.topologyLevel === 2) {
  76. // console.log('情况6:被拖拽的是拓扑结构中二级分组,拖拽到一级分组中');
  77. return true
  78. } else if (this.topologyLevel === 3) {
  79. if (this.indentLevel === 2) {
  80. // console.log('情况7:被拖拽的是拓扑结构中二级分组,拖拽到隐藏的默认二级分组中');
  81. return true
  82. } else {
  83. // console.log('情况8:被拖拽的是拓扑结构中二级分组,拖拽到普通的二级分组中');
  84. return false
  85. }
  86. } else {
  87. console.error('情况9:不该出现');
  88. return false
  89. }
  90. case 'topologyGroupLevel1': // 被拖拽的是拓扑结构中一级分组
  91. if (this.topologyLevel === 1) {
  92. // console.log('情况10:被拖拽的是拓扑结构中一级分组,拖拽到一级分组列表');
  93. return true
  94. } else if (this.topologyLevel === 2) { // 拖拽到一级分组中
  95. if (this.dragInfo.node.children.length === 1 && this.dragInfo.node.children[0].name === '默认二级分组') {
  96. // console.log('情况11:被拖拽的一级分组只有一个隐藏的默认二级分组,拖拽到一级分组中');
  97. return true
  98. } else {
  99. // console.log('情况12:被拖拽的一级分组并非只有一个隐藏的默认二级分组,拖拽到一级分组中');
  100. return false
  101. }
  102. } else if (this.topologyLevel === 3) { // 拖拽到二级分组中
  103. if (this.indentLevel === 2) { // 拖拽到隐藏的默认二级分组中
  104. if (this.dragInfo.node.children.length === 1 && this.dragInfo.node.children[0].name === '默认二级分组') {
  105. if (this.dragInfo.node.children[0].id === this.parentNode.id) {
  106. // console.log('情况13:被拖拽的一级分组只有一个隐藏的默认二级分组,拖拽到自身的默认二级分组中');
  107. return false
  108. } else {
  109. // console.log('情况14:被拖拽的一级分组只有一个隐藏的默认二级分组,拖拽到另一个一级分组中隐藏的默认二级分组中');
  110. return true
  111. }
  112. } else {
  113. // console.log('情况15:被拖拽的一级分组并非只有一个隐藏的默认二级分组,拖拽到隐藏的默认二级分组中');
  114. return false
  115. }
  116. } else {
  117. // console.log('情况16:被拖拽的是拓扑结构中一级分组,拖拽到普通二级分组中')
  118. return false
  119. }
  120. } else {
  121. console.error('情况17:不该出现');
  122. return false
  123. }
  124. default:
  125. console.error('情况18:不该出现');
  126. return false
  127. }
  128. },
  129. onDragEnter(e) {
  130. if (!this.canDrop()) {
  131. return
  132. } else {
  133. e.preventDefault()
  134. e.target.style.backgroundColor = '#0076f6'
  135. e.dataTransfer.dropEffect = 'move'
  136. }
  137. },
  138. onDragOver(e) {
  139. if (!this.canDrop()) {
  140. return
  141. } else {
  142. e.preventDefault()
  143. e.dataTransfer.dropEffect = 'move'
  144. }
  145. },
  146. onDragLeave(e) {
  147. // e.preventDefault()
  148. e.target.style.backgroundColor = ''
  149. },
  150. onDrop(e) {
  151. // e.preventDefault()
  152. e.target.style.backgroundColor = ''
  153. switch (this.dragInfo.type) {
  154. case 'scene': // 被拖拽的是场景
  155. {
  156. if (this.topologyLevel === 2) {
  157. // console.log('情况2:被拖拽的是场景,拖拽到一级分组中。只有一种可能:目标一级分组内容显示是空的,即其下只有一个(内容肯定是空的)默认二级分组。')
  158. /**
  159. * 找到被拖拽的场景
  160. */
  161. const draggedNode = this.info.scenes.find((item) => {
  162. return item.id === this.dragInfo.node.id
  163. })
  164. /**
  165. * 找到目标一级分组
  166. */
  167. const targetGroupLevel1 = this.info.catalogRoot.find((item) => {
  168. return item.id === this.parentNode.id
  169. })
  170. console.log(targetGroupLevel1);
  171. /**
  172. * 找到目标一级分组下辖的默认二级分组
  173. */
  174. const targetGroupLevel2 = this.info.catalogs.find((item) => {
  175. console.log(item.id);
  176. return item.id === targetGroupLevel1.children[0]
  177. })
  178. /**
  179. * 被拖拽的场景的所属二级分组记录修改
  180. */
  181. draggedNode.category = targetGroupLevel2.id
  182. } else if (this.topologyLevel === 3) {
  183. // console.log('情况3:被拖拽的是场景,插入到二级分组中')
  184. /**
  185. * 确定要插入的分组中各场景应有的weight(从1开始递增,小的先显示)
  186. */
  187. const belongGroupCopy = deepClone(this.parentNode.children)
  188. const draggedNodeCopy = deepClone(this.dragInfo.node)
  189. draggedNodeCopy.isCopy = true
  190. belongGroupCopy.splice(this.index, 0, draggedNodeCopy)
  191. const toDeleteIndex = belongGroupCopy.findIndex((item) => {
  192. return (item.id === this.dragInfo.node.id && !item.isCopy)
  193. })
  194. if (toDeleteIndex >= 0) {
  195. belongGroupCopy.splice(toDeleteIndex, 1)
  196. }
  197. for (let [index, elem] of belongGroupCopy.entries()) {
  198. elem.weight = index + 1
  199. }
  200. /**
  201. * 真正修改场景原始数据的weight和所属分组
  202. */
  203. for (const eachSceneCopy of belongGroupCopy) {
  204. for (const eachScene of this.info.scenes) {
  205. if (eachSceneCopy.id === eachScene.id) {
  206. this.$set( eachScene, 'weight', eachSceneCopy.weight )
  207. }
  208. if (this.dragInfo.node.id === eachScene.id) {
  209. eachScene.category = this.parentNode.id // 注意category拼写!
  210. }
  211. }
  212. }
  213. }
  214. }
  215. break;
  216. case 'topologyGroupLevel2': // 被拖拽的是拓扑结构中二级分组
  217. if (this.topologyLevel === 1) {
  218. // console.log('情况5:被拖拽的是拓扑结构中二级分组,拖拽到一级分组列表');
  219. /**
  220. * 在拖拽到的位置新增一个一级分组,name是原二级分组的name;唯一child的id赋值为被拖拽的二级分组的id
  221. */
  222. const newGroupLevel1 = {
  223. id: 'r_' + this.$randomWord(true, 8, 8),
  224. name: this.dragInfo.node.name,
  225. children: [this.dragInfo.node.id],
  226. }
  227. this.info.catalogRoot.splice(this.index, 0, newGroupLevel1)
  228. // 被拖拽的二级分组名称改为“默认二级分组”;
  229. const draggedGroup = this.info.catalogs.find((item) => {
  230. return item.id === this.dragInfo.node.id
  231. })
  232. draggedGroup.name = '默认二级分组'
  233. /**
  234. * 被拖拽的二级分组原属的一级分组的children中,删除【被拖拽的二级分组对应的元素】
  235. */
  236. const parentGroup = this.info.catalogRoot.find((item) => {
  237. return item.id === this.dragInfo.node.parentId
  238. })
  239. const idxToDelete = parentGroup.children.findIndex((id) => {
  240. return id === this.dragInfo.node.id
  241. })
  242. parentGroup.children.splice(idxToDelete, 1)
  243. // 如果被拖拽的二级分组原属的一级分组中没有任何二级分组了,则新增一个默认二级分组
  244. if (parentGroup.children.length === 0) {
  245. let newGroupLevel2Id = 'c_' + this.$randomWord(true, 8, 8)
  246. parentGroup.children.push(newGroupLevel2Id)
  247. this.info.catalogs.push({
  248. id: newGroupLevel2Id,
  249. name: '默认二级分组',
  250. })
  251. }
  252. break;
  253. } else if (this.topologyLevel === 2) {
  254. // console.log('情况6:被拖拽的是拓扑结构中二级分组,拖拽到一级分组中');
  255. // 找到原属一级分组
  256. const originalParentGroup = this.info.catalogRoot.find((item) => {
  257. return item.id === this.dragInfo.node.parentId
  258. })
  259. // 找到原属一级分组children中那个二级分组条目,并做上待删除记号
  260. const originalGroupIndex = originalParentGroup.children.findIndex((eachLevel2Id) => {
  261. return eachLevel2Id === this.dragInfo.node.id
  262. })
  263. originalParentGroup.children[originalGroupIndex] += '__need__delete__'
  264. // 找到要插入的一级分组
  265. const targetGroup = this.info.catalogRoot.find((item) => {
  266. return item.id === this.parentNode.id
  267. })
  268. // 把被拖拽的二级分组的id插进去
  269. targetGroup.children.splice(this.index, 0, this.dragInfo.node.id)
  270. // 把原来那个二级分组条目删除
  271. this.$nextTick(() => {
  272. const toDeleteIndex = originalParentGroup.children.findIndex((eachLevel2Id) => {
  273. return eachLevel2Id.toString().endsWith('__need__delete__')
  274. })
  275. originalParentGroup.children.splice(toDeleteIndex, 1)
  276. })
  277. // 如果被拖拽的二级分组原属的一级分组中没有任何二级分组了,则新增一个默认二级分组
  278. if (originalParentGroup.children.length === 0) {
  279. let newGroupLevel2Id = 'c_' + this.$randomWord(true, 8, 8)
  280. originalParentGroup.children.push(newGroupLevel2Id)
  281. this.info.catalogs.push({
  282. id: newGroupLevel2Id,
  283. name: '默认二级分组',
  284. })
  285. }
  286. } else if (this.topologyLevel === 3) {
  287. // console.log('情况7:被拖拽的是拓扑结构中二级分组,拖拽到隐藏的默认二级分组中');
  288. // 找到拖拽到的二级分组所属的一级分组
  289. const targetGroupLevel1 = this.info.catalogRoot.find((item) => {
  290. return item.id === this.parentNode.parentId
  291. })
  292. // 新增一个child条目,对应被拖拽的二级分组
  293. targetGroupLevel1.children.push(this.dragInfo.node.id)
  294. // 找到被拖拽的二级分组原属的一级分组
  295. const originalGroupLevel1 = this.info.catalogRoot.find((item) => {
  296. return item.id === this.dragInfo.node.parentId
  297. })
  298. // 删除这个二级分组条目
  299. const idxToDelete = originalGroupLevel1.children.findIndex((id) => {
  300. return id === this.dragInfo.node.id
  301. })
  302. originalGroupLevel1.children.splice(idxToDelete, 1)
  303. // 如果被拖拽的二级分组原属的一级分组中没有任何二级分组了,则新增一个默认二级分组
  304. if (originalGroupLevel1.children.length === 0) {
  305. let newGroupLevel2Id = 'c_' + this.$randomWord(true, 8, 8)
  306. originalGroupLevel1.children.push(newGroupLevel2Id)
  307. this.info.catalogs.push({
  308. id: newGroupLevel2Id,
  309. name: '默认二级分组',
  310. })
  311. }
  312. }
  313. break;
  314. case 'topologyGroupLevel1': // 被拖拽的是拓扑结构中一级分组
  315. if (this.topologyLevel === 1) {
  316. // console.log('情况10:被拖拽的是拓扑结构中一级分组,拖拽到一级分组列表');
  317. // 在一级分组列表中找到这个一级分组条目
  318. let originalGroupIndex = this.info.catalogRoot.findIndex((item) => {
  319. return item.id === this.dragInfo.node.id
  320. })
  321. // 复制这个一级分组条目
  322. const groupCopy = deepClone(this.info.catalogRoot[originalGroupIndex])
  323. // 旧的一级分组条目加上待删除标记
  324. this.info.catalogRoot[originalGroupIndex].__need__delete__ = true
  325. // 插入新的一级分组条目
  326. this.info.catalogRoot.splice(this.index, 0 , groupCopy)
  327. // 在一级分组列表中再次找到要删除的一级分组条目
  328. originalGroupIndex = this.info.catalogRoot.findIndex((item) => {
  329. return item.__need__delete__
  330. })
  331. // 删除旧的一级分组条目
  332. this.info.catalogRoot.splice(originalGroupIndex, 1)
  333. } else if (this.topologyLevel === 2) {
  334. // console.log('情况11:被拖拽的一级分组只有一个隐藏的默认二级分组,拖拽到一级分组中');
  335. // 默认二级分组改名成原一级分组的名字
  336. const groupLevel2 = this.info.catalogs.find((item) => {
  337. return item.id === this.dragInfo.node.children[0].id
  338. })
  339. groupLevel2.name = this.dragInfo.node.name
  340. // 拖拽到的一级分组中新增一个child,对应那个二级分组
  341. const targetGroupLevel1 = this.info.catalogRoot.find((item) => {
  342. return item.id === this.parentNode.id
  343. })
  344. targetGroupLevel1.children.splice(this.index, 0, this.dragInfo.node.children[0].id)
  345. // 删除原一级分组
  346. const originalGroupLevel1Idx = this.info.catalogRoot.findIndex((item) => {
  347. return item.id === this.dragInfo.node.id
  348. })
  349. this.info.catalogRoot.splice(originalGroupLevel1Idx, 1)
  350. } else if (this.topologyLevel === 3) {
  351. // console.log('情况14:被拖拽的一级分组只有一个隐藏的默认二级分组,拖拽到另一个一级分组中隐藏的默认二级分组中');
  352. // 找到被拖拽的一级分组索引
  353. const originalGroupLevel1Idx = this.info.catalogRoot.findIndex((item) => {
  354. return item.id === this.dragInfo.node.id
  355. })
  356. // 找到被拖拽的一级分组下辖的默认二级分组的完整数据条目
  357. const groupLevel2 = this.info.catalogs.find((item) => {
  358. return item.id === this.info.catalogRoot[originalGroupLevel1Idx].children[0]
  359. })
  360. // 被拖拽的一级分组下辖默认二级分组的名称改为与父亲同名
  361. groupLevel2.name = this.info.catalogRoot[originalGroupLevel1Idx].name
  362. // 找到拖拽到的二级分组所属的一级分组
  363. const targetGroupLevel1 = this.info.catalogRoot.find((item) => {
  364. return item.id === this.parentNode.parentId
  365. })
  366. // 新增一个child条目,对应被拖拽的一级分组下辖的默认二级分组
  367. targetGroupLevel1.children.push(groupLevel2.id)
  368. // 删除被拖拽的一级分组
  369. this.info.catalogRoot.splice(originalGroupLevel1Idx, 1)
  370. }
  371. break;
  372. default:
  373. break;
  374. }
  375. }
  376. }
  377. }
  378. </script>
  379. <style lang="less" scoped>
  380. .insert-position-tip {
  381. height: 1px;
  382. box-sizing: content-box;
  383. padding-top: 8px;
  384. padding-bottom: 8px;
  385. margin-top: -5px;
  386. margin-bottom: -5px;
  387. position: relative;
  388. z-index: 1;
  389. background-clip: content-box;
  390. color: transparent;
  391. // background-color: red;
  392. }
  393. </style>