@netang/quasar 0.2.32 → 0.2.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. package/.editorconfig +12 -12
  2. package/_docs/docs/components/field-table.md +58 -58
  3. package/_docs/docs/components/field-tree.md +21 -21
  4. package/_docs/docs/components/table.md +24 -24
  5. package/_docs/docs/utils/table.md +196 -196
  6. package/components/column-title/index.vue +38 -38
  7. package/components/data/index.vue +20 -20
  8. package/components/dialog/img-viewer/index.vue +697 -697
  9. package/components/dialog/index.vue +387 -387
  10. package/components/dragger/index.vue +203 -203
  11. package/components/drawer/index.vue +303 -303
  12. package/components/editor-code/index.vue +328 -328
  13. package/components/empty/index.vue +82 -82
  14. package/components/field-date/index.vue +860 -860
  15. package/components/field-date/methods.js +100 -100
  16. package/components/field-table/index.vue +1483 -1483
  17. package/components/field-text/index.vue +166 -166
  18. package/components/field-tree/index.vue +755 -755
  19. package/components/img/index.vue +279 -279
  20. package/components/input-number/index.vue +560 -560
  21. package/components/list-menu/index.vue +149 -149
  22. package/components/list-menu-item/index.vue +79 -79
  23. package/components/mixed-table/index.vue +532 -532
  24. package/components/mixed-table-splitter/index.vue +377 -377
  25. package/components/power-page/index.vue +96 -96
  26. package/components/price/index.vue +188 -188
  27. package/components/private/components/index.js +11 -11
  28. package/components/private/components/move-to-tree/index.vue +154 -154
  29. package/components/private/edit-power-data/index.vue +846 -846
  30. package/components/private/table-visible-columns-button/index.vue +114 -114
  31. package/components/render/index.vue +123 -123
  32. package/components/search/index.vue +231 -231
  33. package/components/search-item/index.vue +210 -210
  34. package/components/select/index.vue +177 -177
  35. package/components/splitter/index.vue +422 -422
  36. package/components/table/index.vue +513 -513
  37. package/components/table-column-fixed/index.vue +110 -110
  38. package/components/table-pagination/index.vue +192 -192
  39. package/components/table-summary/index.vue +107 -107
  40. package/components/thumbnail/index.vue +72 -72
  41. package/components/toolbar/index.vue +150 -150
  42. package/components/tree/index.vue +1728 -1728
  43. package/components/tree/virtual-scroll.vue +41 -41
  44. package/components/uploader/index.vue +196 -196
  45. package/components/uploader-query/index.vue +945 -945
  46. package/components/value-format/index.vue +274 -274
  47. package/components/virtual-scroll/index.vue +136 -136
  48. package/configs/area3.js +1 -1
  49. package/docs/404.html +33 -33
  50. package/docs/assets/404.html-60b35caa.js +1 -1
  51. package/docs/assets/404.html-d1e63d77.js +1 -1
  52. package/docs/assets/alert.html-b2a2a72f.js +5 -5
  53. package/docs/assets/alert.html-ba46d137.js +1 -1
  54. package/docs/assets/app-9f30aa4b.js +6 -6
  55. package/docs/assets/area.html-01b9b58d.js +42 -42
  56. package/docs/assets/area.html-9a4fce6a.js +1 -1
  57. package/docs/assets/arr.html-145d27e7.js +1 -1
  58. package/docs/assets/arr.html-674e65ab.js +11 -11
  59. package/docs/assets/auth.html-579fa830.js +1 -1
  60. package/docs/assets/auth.html-8544ed95.js +8 -8
  61. package/docs/assets/bus.html-c71254aa.js +1 -1
  62. package/docs/assets/bus.html-dc7d3d19.js +6 -6
  63. package/docs/assets/column-title.html-c735cb5a.js +3 -3
  64. package/docs/assets/column-title.html-e9316762.js +1 -1
  65. package/docs/assets/confirm.html-ddfdc27f.js +10 -10
  66. package/docs/assets/confirm.html-ef3e2bef.js +1 -1
  67. package/docs/assets/copy.html-d20345b6.js +1 -1
  68. package/docs/assets/copy.html-ef8c8571.js +13 -13
  69. package/docs/assets/data.html-6432175d.js +30 -30
  70. package/docs/assets/data.html-a3b05d5b.js +1 -1
  71. package/docs/assets/dialog.html-1f698e5a.js +1 -1
  72. package/docs/assets/dialog.html-62902b83.js +68 -68
  73. package/docs/assets/dialog.html-baea77c9.js +1 -1
  74. package/docs/assets/dialog.html-bb082fc4.js +1 -1
  75. package/docs/assets/dict.html-1311da3d.js +23 -23
  76. package/docs/assets/dict.html-b96fbf0c.js +1 -1
  77. package/docs/assets/dictOptions.html-7c4f40a5.js +1 -1
  78. package/docs/assets/dictOptions.html-fb99d175.js +5 -5
  79. package/docs/assets/dragger.html-668d3efa.js +1 -1
  80. package/docs/assets/dragger.html-749d585a.js +1 -1
  81. package/docs/assets/editor-code.html-6ab26ea9.js +1 -1
  82. package/docs/assets/editor-code.html-d196205d.js +1 -1
  83. package/docs/assets/empty.html-1c139131.js +1 -1
  84. package/docs/assets/empty.html-1e9c441d.js +1 -1
  85. package/docs/assets/field-date.html-069fdb13.js +1 -1
  86. package/docs/assets/field-date.html-ad204aa9.js +1 -1
  87. package/docs/assets/field-table.html-ce480f03.js +1 -1
  88. package/docs/assets/field-table.html-d9236160.js +1 -1
  89. package/docs/assets/field-text.html-7277c62f.js +1 -1
  90. package/docs/assets/field-text.html-ccb4cecf.js +1 -1
  91. package/docs/assets/field-tree.html-519bfb45.js +1 -1
  92. package/docs/assets/field-tree.html-fdc748d6.js +1 -1
  93. package/docs/assets/form.html-2b562c37.js +2 -2
  94. package/docs/assets/form.html-75104cd5.js +1 -1
  95. package/docs/assets/framework-204010b2.js +5 -5
  96. package/docs/assets/getData.html-990e3787.js +1 -1
  97. package/docs/assets/getData.html-bb72025f.js +34 -34
  98. package/docs/assets/getFile.html-42368004.js +1 -1
  99. package/docs/assets/getFile.html-99abd054.js +3 -3
  100. package/docs/assets/getImage.html-3429c5a1.js +1 -1
  101. package/docs/assets/getImage.html-4d886d83.js +3 -3
  102. package/docs/assets/getTime.html-7435f922.js +1 -1
  103. package/docs/assets/getTime.html-b37f49eb.js +20 -20
  104. package/docs/assets/img.html-7d1da657.js +1 -1
  105. package/docs/assets/img.html-fbea1105.js +1 -1
  106. package/docs/assets/index.html-1695dd7c.js +1 -1
  107. package/docs/assets/index.html-65a4aa67.js +1 -1
  108. package/docs/assets/index.html-7b98d5bd.js +1 -1
  109. package/docs/assets/index.html-c01f2648.js +1 -1
  110. package/docs/assets/input-number.html-0b250d2a.js +1 -1
  111. package/docs/assets/input-number.html-a8eb0378.js +1 -1
  112. package/docs/assets/list-menu-item.html-7f1b4611.js +1 -1
  113. package/docs/assets/list-menu-item.html-84ed5ab8.js +1 -1
  114. package/docs/assets/list-menu.html-28b4163f.js +1 -1
  115. package/docs/assets/list-menu.html-cb6ba95b.js +1 -1
  116. package/docs/assets/loading.html-dae9e39d.js +6 -6
  117. package/docs/assets/loading.html-dc74c9e6.js +1 -1
  118. package/docs/assets/notify.html-e6c4c514.js +1 -1
  119. package/docs/assets/notify.html-f2c4d914.js +8 -8
  120. package/docs/assets/power-page.html-32e02f82.js +1 -1
  121. package/docs/assets/power-page.html-485e77da.js +1 -1
  122. package/docs/assets/power.html-d258cc19.js +93 -93
  123. package/docs/assets/power.html-e490bd32.js +1 -1
  124. package/docs/assets/previewImage.html-6a6b4245.js +1 -1
  125. package/docs/assets/previewImage.html-c5b7e945.js +2 -2
  126. package/docs/assets/price.html-1882c548.js +19 -19
  127. package/docs/assets/price.html-94d3f5be.js +1 -1
  128. package/docs/assets/price.html-d213df0f.js +1 -1
  129. package/docs/assets/price.html-deaf880f.js +1 -1
  130. package/docs/assets/render.html-8efcbdd4.js +1 -1
  131. package/docs/assets/render.html-df228e38.js +1 -1
  132. package/docs/assets/rule.html-2cd57fc2.js +13 -13
  133. package/docs/assets/rule.html-61662001.js +1 -1
  134. package/docs/assets/ruleValid.html-04fe2552.js +1 -1
  135. package/docs/assets/ruleValid.html-e0a776af.js +14 -14
  136. package/docs/assets/search-0782d0d1.svg +1 -1
  137. package/docs/assets/search-item.html-3f75394c.js +1 -1
  138. package/docs/assets/search-item.html-4e942ecd.js +1 -1
  139. package/docs/assets/search.html-2807043e.js +1 -1
  140. package/docs/assets/search.html-c24f8806.js +1 -1
  141. package/docs/assets/select.html-00d0607c.js +1 -1
  142. package/docs/assets/select.html-de7731f5.js +1 -1
  143. package/docs/assets/splitter.html-56f51a70.js +1 -1
  144. package/docs/assets/splitter.html-f5c836d7.js +1 -1
  145. package/docs/assets/style-161e43ab.css +1 -1
  146. package/docs/assets/symbols.html-a6aea4bf.js +1 -1
  147. package/docs/assets/symbols.html-b1f65bad.js +21 -21
  148. package/docs/assets/table-column-fixed.html-3a69e7b2.js +1 -1
  149. package/docs/assets/table-column-fixed.html-e763c38b.js +1 -1
  150. package/docs/assets/table-pagination.html-236934d3.js +1 -1
  151. package/docs/assets/table-pagination.html-c37ee2ac.js +1 -1
  152. package/docs/assets/table-splitter.html-07eab15c.js +1 -1
  153. package/docs/assets/table-splitter.html-7670ee65.js +1 -1
  154. package/docs/assets/table-summary.html-04db434f.js +1 -1
  155. package/docs/assets/table-summary.html-943c65a0.js +1 -1
  156. package/docs/assets/table.html-36253ad7.js +1 -1
  157. package/docs/assets/table.html-7f9c5d1b.js +38 -38
  158. package/docs/assets/table.html-93d53dc8.js +1 -1
  159. package/docs/assets/table.html-ac99b9cb.js +1 -1
  160. package/docs/assets/thumbnail.html-bab1976b.js +1 -1
  161. package/docs/assets/thumbnail.html-eb64e5e8.js +1 -1
  162. package/docs/assets/timestamp.html-4e54f79b.js +13 -13
  163. package/docs/assets/timestamp.html-d0e1b88a.js +1 -1
  164. package/docs/assets/toast.html-58ecbe21.js +1 -1
  165. package/docs/assets/toast.html-c9b9d36b.js +6 -6
  166. package/docs/assets/toolbar.html-83d9f97c.js +1 -1
  167. package/docs/assets/toolbar.html-ff7b8c92.js +1 -1
  168. package/docs/assets/tree.html-d07cbe79.js +23 -23
  169. package/docs/assets/tree.html-ea04193e.js +1 -1
  170. package/docs/assets/uploader-query.html-05590718.js +1 -1
  171. package/docs/assets/uploader-query.html-3175bac5.js +1 -1
  172. package/docs/assets/uploader.html-36da4394.js +2 -2
  173. package/docs/assets/uploader.html-6b5f3079.js +1 -1
  174. package/docs/assets/uploader.html-b9340b57.js +1 -1
  175. package/docs/assets/uploader.html-bc1c22e3.js +1 -1
  176. package/docs/assets/value-format.html-8ae3d47d.js +1 -1
  177. package/docs/assets/value-format.html-afa99b3d.js +1 -1
  178. package/docs/components/column-title.html +35 -35
  179. package/docs/components/data.html +62 -62
  180. package/docs/components/dialog.html +33 -33
  181. package/docs/components/dragger.html +33 -33
  182. package/docs/components/editor-code.html +33 -33
  183. package/docs/components/empty.html +33 -33
  184. package/docs/components/field-date.html +33 -33
  185. package/docs/components/field-table.html +33 -33
  186. package/docs/components/field-text.html +33 -33
  187. package/docs/components/field-tree.html +33 -33
  188. package/docs/components/img.html +33 -33
  189. package/docs/components/input-number.html +33 -33
  190. package/docs/components/list-menu-item.html +33 -33
  191. package/docs/components/list-menu.html +33 -33
  192. package/docs/components/power-page.html +33 -33
  193. package/docs/components/price.html +33 -33
  194. package/docs/components/render.html +33 -33
  195. package/docs/components/search-item.html +33 -33
  196. package/docs/components/search.html +33 -33
  197. package/docs/components/select.html +33 -33
  198. package/docs/components/splitter.html +33 -33
  199. package/docs/components/table-column-fixed.html +33 -33
  200. package/docs/components/table-pagination.html +33 -33
  201. package/docs/components/table-splitter.html +33 -33
  202. package/docs/components/table-summary.html +33 -33
  203. package/docs/components/table.html +33 -33
  204. package/docs/components/thumbnail.html +33 -33
  205. package/docs/components/toolbar.html +33 -33
  206. package/docs/components/uploader-query.html +33 -33
  207. package/docs/components/uploader.html +33 -33
  208. package/docs/components/value-format.html +33 -33
  209. package/docs/css/index.css +3 -3
  210. package/docs/index.html +33 -33
  211. package/docs/utils/alert.html +37 -37
  212. package/docs/utils/area.html +74 -74
  213. package/docs/utils/arr.html +43 -43
  214. package/docs/utils/auth.html +40 -40
  215. package/docs/utils/bus.html +38 -38
  216. package/docs/utils/confirm.html +42 -42
  217. package/docs/utils/copy.html +45 -45
  218. package/docs/utils/dialog.html +100 -100
  219. package/docs/utils/dict.html +55 -55
  220. package/docs/utils/dictOptions.html +37 -37
  221. package/docs/utils/form.html +34 -34
  222. package/docs/utils/getData.html +66 -66
  223. package/docs/utils/getFile.html +35 -35
  224. package/docs/utils/getImage.html +35 -35
  225. package/docs/utils/getTime.html +52 -52
  226. package/docs/utils/index.html +33 -33
  227. package/docs/utils/loading.html +38 -38
  228. package/docs/utils/notify.html +40 -40
  229. package/docs/utils/power.html +125 -125
  230. package/docs/utils/previewImage.html +34 -34
  231. package/docs/utils/price.html +51 -51
  232. package/docs/utils/rule.html +45 -45
  233. package/docs/utils/ruleValid.html +46 -46
  234. package/docs/utils/symbols.html +53 -53
  235. package/docs/utils/table.html +70 -70
  236. package/docs/utils/timestamp.html +45 -45
  237. package/docs/utils/toast.html +38 -38
  238. package/docs/utils/tree.html +55 -55
  239. package/docs/utils/uploader.html +34 -34
  240. package/package.json +25 -25
  241. package/sass/common.scss +184 -184
  242. package/sass/index.scss +12 -12
  243. package/sass/line.scss +39 -39
  244. package/sass/quasar/btn.scss +46 -46
  245. package/sass/quasar/common.scss +3 -3
  246. package/sass/quasar/drawer.scss +6 -6
  247. package/sass/quasar/field.scss +259 -259
  248. package/sass/quasar/loading.scss +6 -6
  249. package/sass/quasar/table.scss +168 -168
  250. package/sass/quasar/toolbar.scss +22 -22
  251. package/sass/variables.scss +140 -140
  252. package/store/index.js +29 -29
  253. package/utils/$auth.js +128 -128
  254. package/utils/$form.js +72 -72
  255. package/utils/$power.js +1494 -1494
  256. package/utils/$render.js +75 -75
  257. package/utils/$rule.js +13 -13
  258. package/utils/$ruleValid.js +10 -10
  259. package/utils/$search.js +416 -416
  260. package/utils/$table.js +1351 -1348
  261. package/utils/$tree.js +682 -682
  262. package/utils/alert.js +12 -12
  263. package/utils/area.js +400 -400
  264. package/utils/arr.js +51 -51
  265. package/utils/bus.js +6 -6
  266. package/utils/config.js +66 -66
  267. package/utils/confirm.js +11 -11
  268. package/utils/copy.js +30 -30
  269. package/utils/dialog.js +36 -36
  270. package/utils/dict.js +21 -21
  271. package/utils/dictOptions.js +28 -28
  272. package/utils/getData.js +88 -88
  273. package/utils/getFile.js +67 -67
  274. package/utils/getImage.js +276 -276
  275. package/utils/getTime.js +113 -113
  276. package/utils/index.js +67 -67
  277. package/utils/loading.js +15 -15
  278. package/utils/notify.js +13 -13
  279. package/utils/play.js +40 -40
  280. package/utils/previewImage.js +14 -14
  281. package/utils/price.js +18 -18
  282. package/utils/symbols.js +18 -18
  283. package/utils/timestamp.js +18 -18
  284. package/utils/toast.js +13 -13
  285. package/utils/uploader.js +2114 -2114
  286. package/utils/useAuth.js +30 -30
  287. package/utils/useFileUrl.js +26 -26
  288. package/utils/useRouter.js +47 -47
  289. package/utils/useSearch.js +587 -562
package/utils/$tree.js CHANGED
@@ -1,682 +1,682 @@
1
- import $n_has from 'lodash/has'
2
- import $n_get from 'lodash/get'
3
- import $n_isNil from 'lodash/isNil'
4
- import $n_findIndex from 'lodash/findIndex'
5
- import $n_cloneDeep from 'lodash/cloneDeep'
6
-
7
- import $n_router from '@netang/utils/vue/router'
8
-
9
- import $n_isValidArray from '@netang/utils/isValidArray'
10
- import $n_isValidObject from '@netang/utils/isValidObject'
11
- import $n_isValidString from '@netang/utils/isValidString'
12
- import $n_hasId from '@netang/utils/hasId'
13
- import $n_http from '@netang/utils/http'
14
- import $n_run from '@netang/utils/run'
15
- import $n_storage from '@netang/utils/storage'
16
-
17
- import $n_toast from './toast'
18
- import $n_confirm from './confirm'
19
- import $n_alert from './alert'
20
-
21
- import { isRef, watch, inject, ref, computed } from 'vue'
22
-
23
- import { NPowerKey } from './symbols'
24
-
25
- /**
26
- * 获取节点
27
- */
28
- function getTreeNode(data, nodeId) {
29
- for (const item of data) {
30
-
31
- if (item.id === nodeId) {
32
- return item
33
- }
34
-
35
- // 如果是父节点
36
- if (item.children.length) {
37
- const res = getTreeNode(item.children, nodeId)
38
- if (res) {
39
- return res
40
- }
41
- }
42
- }
43
-
44
- return false
45
- }
46
-
47
- /**
48
- * 获取子节点
49
- */
50
- function getChildren(data, callback) {
51
- for (const item of data) {
52
- if ($n_run(callback)(item) === false) {
53
- return false
54
- }
55
- // 如果是父节点
56
- if (item.children.length) {
57
- const res = getChildren(item.children, callback)
58
- if (res === false) {
59
- return false
60
- }
61
- }
62
- }
63
- return true
64
- }
65
-
66
- /**
67
- * 创建树实例
68
- */
69
- function create(options) {
70
-
71
- const {
72
- // 路由路径
73
- path,
74
- // 路由参数
75
- query,
76
- // 树节点列表
77
- nodes,
78
- // 树展开节点
79
- expanded,
80
- // 菜单参数
81
- menu: menuOptions,
82
- // 初始表单数据
83
- initFormData,
84
- // 表单数据
85
- formData,
86
- // 重新加载
87
- reload,
88
- // 是否开启展开节点缓存
89
- cache,
90
- } = Object.assign({
91
- // 路由路径
92
- path: '',
93
- // 路由参数
94
- query: {},
95
- // 菜单参数
96
- menu: {},
97
- // 是否开启展开节点缓存
98
- cache: false,
99
- }, options)
100
-
101
- // 获取权限注入
102
- const $power = $n_has(options, '$power') ? options.$power : inject(NPowerKey)
103
- const hasPowr = !! $power
104
-
105
- // 获取权限路由
106
- const $route = $n_isValidString(path) ?
107
- // 如果为自定义路由
108
- $n_router.resolve({
109
- path,
110
- query,
111
- })
112
- // 否则获取当前路由
113
- : (hasPowr ? $power.getRoute() : $n_router.getRoute())
114
-
115
- // 权限按钮
116
- const powerBtns = hasPowr ? $power.powerBtns : ref([])
117
-
118
- // 是否有展开节点
119
- const hasExpanded = ! $n_isNil(expanded) && isRef(expanded)
120
-
121
- // 如果开启展开节点缓存
122
- if (hasExpanded && cache) {
123
-
124
- // 设置树展开节点初始缓存
125
- expanded.value = getExpandedCache(expanded.value)
126
-
127
- /**
128
- * 监听树展开节点
129
- */
130
- watch(expanded, function(val) {
131
- // 设置树展开节点缓存
132
- setExpandedCache(val)
133
- })
134
- }
135
-
136
- // 获取菜单状态
137
- const menuStatus = computed(function() {
138
-
139
- const o = Object.assign({
140
- updateName: 'update',
141
- moveName: 'move',
142
- copyName: 'copy',
143
- deleteName: 'realdel',
144
- statusName: 'status'
145
- }, menuOptions)
146
-
147
- const maps = {}
148
- maps[o.updateName] = 'update'
149
- maps[o.moveName] = 'move'
150
- maps[o.copyName] = 'copy'
151
- maps[o.deleteName] = 'delete'
152
- maps[o.statusName] = 'status'
153
-
154
- const allPowerBtn = {}
155
- for (const item of powerBtns.value) {
156
- if ($n_has(maps, $n_get(item, 'name'))) {
157
- allPowerBtn[maps[item.name]] = item
158
- }
159
- }
160
-
161
- return {
162
- all: $n_isValidObject(allPowerBtn),
163
- update: $n_has(allPowerBtn, 'update'),
164
- move: $n_has(allPowerBtn, 'move'),
165
- copy: $n_has(allPowerBtn, 'copy'),
166
- delete: $n_has(allPowerBtn, 'delete'),
167
- status: $n_has(allPowerBtn, 'status'),
168
- allPowerBtn,
169
- }
170
- })
171
-
172
- /**
173
- * 获取节点
174
- */
175
- function getNode(nodeId) {
176
- return getTreeNode(nodes.value, nodeId)
177
- }
178
-
179
- /**
180
- * 格式化节点
181
- */
182
- function formatNode(attr) {
183
-
184
- // 设置属性
185
- attr = Object.assign({}, attr)
186
-
187
- return {
188
- attr,
189
- id: attr.id,
190
- label: attr.title,
191
- children: [],
192
- }
193
- }
194
-
195
- /**
196
- * 更新节点
197
- */
198
- function updateNode(data) {
199
-
200
- // 获取 id
201
- const id = $n_get(formData.value, 'id')
202
-
203
- // 更新表单数据
204
- formData.value = Object.assign({}, formData.value, data)
205
-
206
- // 获取节点数据
207
- const nodeItem = getNode(data.id)
208
-
209
- // 如果为更新节点
210
- if (id) {
211
- if (nodeItem) {
212
- Object.assign(nodeItem, {
213
- attr: Object.assign({}, formData.value),
214
- label: formData.value.title,
215
- })
216
- }
217
-
218
- // 否则为新增节点
219
- } else if (
220
- // 如果为新增节点
221
- $n_get(data, 'id')
222
- // 没有节点存在
223
- && ! nodeItem
224
- ) {
225
- // 获取父级节点
226
- const parentNodeItem = getNode(formData.value.pid)
227
- if (! parentNodeItem) {
228
- return
229
- }
230
-
231
- // 新增节点
232
- parentNodeItem.children.push(formatNode(formData.value))
233
- }
234
- }
235
-
236
- /**
237
- * 删除节点
238
- */
239
- function deleteNode({ id, attr }) {
240
-
241
- // 获取父节点数据
242
- const parentNodeItem = getNode(attr.pid)
243
- if (! parentNodeItem) {
244
- return
245
- }
246
-
247
- // 获取节点索引
248
- const nodeIndex = $n_findIndex(parentNodeItem.children, { id })
249
- if (nodeIndex > -1) {
250
- parentNodeItem.children.splice(nodeIndex, 1)
251
- }
252
- }
253
-
254
- /**
255
- * 确认菜单
256
- */
257
- function confirmMenu(callback) {
258
- // 确认框
259
- $n_confirm({
260
- message: '确认要执行该操作吗?',
261
- })
262
- // 点击确认执行
263
- .onOk(callback)
264
- }
265
-
266
- /**
267
- * 菜单点击
268
- */
269
- function menuClick(options) {
270
-
271
- // 参数
272
- const o = Object.assign({
273
- // 菜单类型
274
- type: '',
275
- // 节点
276
- node: null,
277
- }, options)
278
-
279
- // 菜单类型
280
- switch (o.type) {
281
-
282
- // 添加下级
283
- case 'update':
284
- // 更新表单数据
285
- formData.value = Object.assign({}, initFormData, {
286
- pid: o.node.attr.id,
287
- })
288
- break
289
-
290
- // 复制
291
- case 'copy':
292
- // 确认菜单
293
- confirmMenu(async function() {
294
-
295
- if (! $n_get(menuStatus.value, 'allPowerBtn.copy.url')) {
296
- console.error('没有找到复制地址')
297
- return
298
- }
299
-
300
- // 复制的当前节点的属性
301
- const newAttr = Object.assign({}, o.node.attr, {
302
- title: '【复制】' + o.node.attr.title,
303
- })
304
-
305
- // 复制列表
306
- const copyLists = [ newAttr ]
307
-
308
- // 是否复制叶子节点
309
- const isLeafNode = ! o.node.children.length
310
-
311
- // 如果复制的是父级节点
312
- if (! isLeafNode) {
313
- getChildren(o.node.children, function(item) {
314
- copyLists.push(item.attr)
315
- })
316
- }
317
-
318
- // 请求 - 复制
319
- const { status, data: res } = await $n_http({
320
- url: menuStatus.value.allPowerBtn.copy.url,
321
- data: {
322
- data: copyLists,
323
- },
324
- })
325
- if (! status) {
326
- return
327
- }
328
-
329
- // 如果复制的是叶子节点
330
- if (isLeafNode) {
331
-
332
- // 如果返回了 id
333
- if ($n_hasId(res)) {
334
-
335
- // 更新数据
336
- Object.assign(newAttr, res)
337
-
338
- // 获取该叶子节点的父级节点
339
- const parentNodeItem = getNode(newAttr.pid)
340
- if (! parentNodeItem) {
341
- return
342
- }
343
-
344
- // 新增节点
345
- parentNodeItem.children.push(formatNode(newAttr))
346
-
347
- // 否则重新加载列表
348
- } else {
349
- reload()
350
- }
351
-
352
- // 否则重新加载列表
353
- } else {
354
- reload()
355
- }
356
-
357
- // 轻提示
358
- $n_toast({
359
- type: 'positive',
360
- message: '复制成功',
361
- })
362
- })
363
- break
364
-
365
- // 删除
366
- case 'delete':
367
-
368
- // 如果有子节点
369
- if (o.node.children.length) {
370
- // 提示框
371
- $n_alert({
372
- message: '请先删除该节点下的子节点',
373
- })
374
- return
375
- }
376
-
377
- if (! $n_get(menuStatus.value, 'allPowerBtn.delete.url')) {
378
- console.error('没有找到删除地址')
379
- return
380
- }
381
-
382
- // 确认菜单
383
- confirmMenu(async function() {
384
-
385
- // 请求 - 删除
386
- const { status } = await $n_http({
387
- url: menuStatus.value.allPowerBtn.delete.url,
388
- data: {
389
- id: o.node.id,
390
- },
391
- })
392
- if (! status) {
393
- return
394
- }
395
-
396
- // 删除节点
397
- deleteNode(o.node)
398
-
399
- // 轻提示
400
- $n_toast({
401
- type: 'positive',
402
- message: '删除成功',
403
- })
404
- })
405
- break
406
-
407
- // 全部禁用
408
- case 'statusDisable':
409
- // 全部正常
410
- case 'statusNormal':
411
-
412
- if (! $n_get(menuStatus.value, 'allPowerBtn.status.url')) {
413
- console.error('没有找到状态地址')
414
- return
415
- }
416
-
417
- // 确认菜单
418
- confirmMenu(async function() {
419
-
420
- // 设置状态 ids
421
- const statusIds = [ o.node.id ]
422
-
423
- // 新状态
424
- const newStatus = o.type === 'statusNormal' ? 1 : 0
425
-
426
- // 是否叶子节点
427
- const isLeafNode = ! o.node.children.length
428
-
429
- // 如果复制的是父级节点
430
- if (! isLeafNode) {
431
- getChildren(o.node.children, function(item) {
432
- statusIds.push(item.id)
433
- })
434
- }
435
-
436
- // 请求 - 全部禁用/正常
437
- const { status } = await $n_http({
438
- url: menuStatus.value.allPowerBtn.status.url,
439
- data: {
440
- // ids
441
- ids: statusIds,
442
- // 新状态值
443
- status: newStatus,
444
- },
445
- })
446
- if (! status) {
447
- return
448
- }
449
-
450
- // 设置当前节点状态
451
- o.node.attr.status = newStatus
452
-
453
- // 如果是父级节点
454
- if (! isLeafNode) {
455
- getChildren(o.node.children, function(item) {
456
- item.attr.status = newStatus
457
- })
458
- }
459
-
460
- // 轻提示
461
- $n_toast({
462
- type: 'positive',
463
- message: '恭喜您,操作成功',
464
- })
465
- })
466
- break
467
- }
468
- }
469
-
470
- /**
471
- * 获取展开节点缓存
472
- */
473
- function getExpandedCache(defaultValue = []) {
474
- // 获取展开节点缓存
475
- const res = $n_storage.get('tree_expanded_' + $route.fullPath)
476
- return $n_isValidArray(res) ? res : defaultValue
477
- }
478
-
479
- /**
480
- * 设置展开节点缓存
481
- */
482
- function setExpandedCache(expanded) {
483
- // 设置展开节点缓存(永久缓存)
484
- $n_storage.set('tree_expanded_' + $route.fullPath, expanded, 0)
485
- }
486
-
487
- /**
488
- * 展开全部
489
- */
490
- function expandAll() {
491
-
492
- // 展开节点 ids
493
- const ids = []
494
-
495
- function getChildren(data) {
496
- for (const { id, children } of data) {
497
- ids.push(id)
498
- if ($n_isValidArray(children)) {
499
- getChildren(children)
500
- }
501
- }
502
- }
503
-
504
- if ($n_isValidArray(nodes.value)) {
505
- getChildren(nodes.value)
506
- }
507
-
508
- // 设置展开节点数组
509
- expanded.value = ids
510
- }
511
-
512
- /**
513
- * 收起全部
514
- */
515
- function collapseAll() {
516
- // 设置展开节点数组
517
- expanded.value = [0]
518
- }
519
-
520
- /**
521
- * 判断节点能否被拖拽
522
- */
523
- function allowDrag(draggingNode) {
524
- return $n_hasId(draggingNode.id)
525
- }
526
-
527
- /**
528
- * 拖拽时判定目标节点能否被放置, type 参数: top / inner / bottom / none ( 目标节点上方 / 目标节点内部 / 目标节点下方 / 无任何操作 )
529
- */
530
- function allowDrop(draggingNode, dropNode, dropType) {
531
- return dropType === 'inner'
532
- || $n_hasId(dropNode.id)
533
- }
534
-
535
- /**
536
- * 树节点拖拽结束
537
- */
538
- async function nodeDragEnd(draggingNode, dropNode, dropType, doDrop) {
539
- if (dropType !== 'none') {
540
-
541
- if (! $n_get(menuStatus.value, 'allPowerBtn.move.url')) {
542
-
543
- // 提示框
544
- $n_alert({
545
- message: '没有找到移动地址',
546
- })
547
-
548
- return
549
- }
550
-
551
- // 克隆当前树列表数据
552
- const nodesClone = $n_cloneDeep(nodes.value)
553
-
554
- // 开始拖拽
555
- const children = doDrop()
556
- if (children === false) {
557
- return
558
- }
559
-
560
- // 修改拖拽节点的父级 id
561
- draggingNode.attr.pid =
562
- // 如果拖动节点 在 目标节点的 内部
563
- dropType === 'inner' ?
564
- // 将拖动节点的 pid 改为 目标节点的 id
565
- dropNode.attr.id
566
- // 将拖动节点的 pid 改为 目标节点的 pid
567
- : dropNode.attr.pid
568
-
569
- // 移动列表
570
- const moveLists = []
571
-
572
- // 当前拖拽节点在新列表中的索引
573
- let dropIndex = $n_findIndex(children, e => e.id === draggingNode.id)
574
- if (dropIndex > -1) {
575
-
576
- // if (
577
- // // 如果拖拽到目标节点下方
578
- // dropType === 'bottom'
579
- // // 并且拖拽节点当前的位置不是第一个
580
- // && dropIndex > 0
581
- // ) {
582
- // dropIndex--
583
- // }
584
- // for (let i = dropIndex; i < children.length; i++) {
585
- // const { attr } = children[i]
586
- // attr.sort = i + 1
587
- // moveLists.push({
588
- // id: attr.id,
589
- // pid: attr.pid,
590
- // sort: attr.sort,
591
- // })
592
- // }
593
-
594
- for (let i = 0, len = children.length; i < len; i++) {
595
- const { attr } = children[i]
596
-
597
- // 新排序号
598
- const newSort = i + 1
599
-
600
- if (
601
- i >= dropIndex
602
- || newSort !== attr.sort
603
- ) {
604
- attr.sort = newSort
605
- moveLists.push({
606
- id: attr.id,
607
- pid: attr.pid,
608
- sort: attr.sort,
609
- })
610
- }
611
- }
612
-
613
- // 如果有移动列表
614
- if (moveLists.length) {
615
-
616
- // 请求 - 移动
617
- const { status } = await $n_http({
618
- url: menuStatus.value.allPowerBtn.move.url,
619
- data: {
620
- data: moveLists,
621
- },
622
- })
623
-
624
- // 移动成功
625
- if (status) {
626
- return
627
- }
628
- }
629
- }
630
-
631
- // 移动失败, 还原数据
632
- nodes.value = nodesClone
633
- }
634
- }
635
-
636
- return {
637
- // 当前路由全路径
638
- routeFullPath: $route.fullPath,
639
- // 当前路由路径
640
- routePath: $route.path,
641
- // 当前路由参数
642
- routeQuery: $route.query,
643
- // 菜单状态
644
- menuStatus,
645
- // 获取当前路由
646
- getRoute() {
647
- return $route
648
- },
649
- // 获取节点
650
- getNode,
651
- // 更新节点
652
- updateNode,
653
- // 删除节点
654
- deleteNode,
655
- // 菜单点击
656
- menuClick,
657
- // 获取展开节点缓存
658
- getExpandedCache,
659
- // 设置展开节点缓存
660
- setExpandedCache,
661
- // 展开全部
662
- expandAll,
663
- // 收起全部
664
- collapseAll,
665
- // 判断节点能否被拖拽
666
- allowDrag,
667
- // 拖拽时判定目标节点能否被放置, type 参数: top / inner / bottom / none ( 目标节点上方 / 目标节点内部 / 目标节点下方 / 无任何操作 )
668
- allowDrop,
669
- // 树节点拖拽结束
670
- nodeDragEnd,
671
- }
672
- }
673
-
674
- /**
675
- * 树业务
676
- */
677
- const $tree = {
678
- // 创建树实例
679
- create,
680
- }
681
-
682
- export default $tree
1
+ import $n_has from 'lodash/has'
2
+ import $n_get from 'lodash/get'
3
+ import $n_isNil from 'lodash/isNil'
4
+ import $n_findIndex from 'lodash/findIndex'
5
+ import $n_cloneDeep from 'lodash/cloneDeep'
6
+
7
+ import $n_router from '@netang/utils/vue/router'
8
+
9
+ import $n_isValidArray from '@netang/utils/isValidArray'
10
+ import $n_isValidObject from '@netang/utils/isValidObject'
11
+ import $n_isValidString from '@netang/utils/isValidString'
12
+ import $n_hasId from '@netang/utils/hasId'
13
+ import $n_http from '@netang/utils/http'
14
+ import $n_run from '@netang/utils/run'
15
+ import $n_storage from '@netang/utils/storage'
16
+
17
+ import $n_toast from './toast'
18
+ import $n_confirm from './confirm'
19
+ import $n_alert from './alert'
20
+
21
+ import { isRef, watch, inject, ref, computed } from 'vue'
22
+
23
+ import { NPowerKey } from './symbols'
24
+
25
+ /**
26
+ * 获取节点
27
+ */
28
+ function getTreeNode(data, nodeId) {
29
+ for (const item of data) {
30
+
31
+ if (item.id === nodeId) {
32
+ return item
33
+ }
34
+
35
+ // 如果是父节点
36
+ if (item.children.length) {
37
+ const res = getTreeNode(item.children, nodeId)
38
+ if (res) {
39
+ return res
40
+ }
41
+ }
42
+ }
43
+
44
+ return false
45
+ }
46
+
47
+ /**
48
+ * 获取子节点
49
+ */
50
+ function getChildren(data, callback) {
51
+ for (const item of data) {
52
+ if ($n_run(callback)(item) === false) {
53
+ return false
54
+ }
55
+ // 如果是父节点
56
+ if (item.children.length) {
57
+ const res = getChildren(item.children, callback)
58
+ if (res === false) {
59
+ return false
60
+ }
61
+ }
62
+ }
63
+ return true
64
+ }
65
+
66
+ /**
67
+ * 创建树实例
68
+ */
69
+ function create(options) {
70
+
71
+ const {
72
+ // 路由路径
73
+ path,
74
+ // 路由参数
75
+ query,
76
+ // 树节点列表
77
+ nodes,
78
+ // 树展开节点
79
+ expanded,
80
+ // 菜单参数
81
+ menu: menuOptions,
82
+ // 初始表单数据
83
+ initFormData,
84
+ // 表单数据
85
+ formData,
86
+ // 重新加载
87
+ reload,
88
+ // 是否开启展开节点缓存
89
+ cache,
90
+ } = Object.assign({
91
+ // 路由路径
92
+ path: '',
93
+ // 路由参数
94
+ query: {},
95
+ // 菜单参数
96
+ menu: {},
97
+ // 是否开启展开节点缓存
98
+ cache: false,
99
+ }, options)
100
+
101
+ // 获取权限注入
102
+ const $power = $n_has(options, '$power') ? options.$power : inject(NPowerKey)
103
+ const hasPowr = !! $power
104
+
105
+ // 获取权限路由
106
+ const $route = $n_isValidString(path) ?
107
+ // 如果为自定义路由
108
+ $n_router.resolve({
109
+ path,
110
+ query,
111
+ })
112
+ // 否则获取当前路由
113
+ : (hasPowr ? $power.getRoute() : $n_router.getRoute())
114
+
115
+ // 权限按钮
116
+ const powerBtns = hasPowr ? $power.powerBtns : ref([])
117
+
118
+ // 是否有展开节点
119
+ const hasExpanded = ! $n_isNil(expanded) && isRef(expanded)
120
+
121
+ // 如果开启展开节点缓存
122
+ if (hasExpanded && cache) {
123
+
124
+ // 设置树展开节点初始缓存
125
+ expanded.value = getExpandedCache(expanded.value)
126
+
127
+ /**
128
+ * 监听树展开节点
129
+ */
130
+ watch(expanded, function(val) {
131
+ // 设置树展开节点缓存
132
+ setExpandedCache(val)
133
+ })
134
+ }
135
+
136
+ // 获取菜单状态
137
+ const menuStatus = computed(function() {
138
+
139
+ const o = Object.assign({
140
+ updateName: 'update',
141
+ moveName: 'move',
142
+ copyName: 'copy',
143
+ deleteName: 'realdel',
144
+ statusName: 'status'
145
+ }, menuOptions)
146
+
147
+ const maps = {}
148
+ maps[o.updateName] = 'update'
149
+ maps[o.moveName] = 'move'
150
+ maps[o.copyName] = 'copy'
151
+ maps[o.deleteName] = 'delete'
152
+ maps[o.statusName] = 'status'
153
+
154
+ const allPowerBtn = {}
155
+ for (const item of powerBtns.value) {
156
+ if ($n_has(maps, $n_get(item, 'name'))) {
157
+ allPowerBtn[maps[item.name]] = item
158
+ }
159
+ }
160
+
161
+ return {
162
+ all: $n_isValidObject(allPowerBtn),
163
+ update: $n_has(allPowerBtn, 'update'),
164
+ move: $n_has(allPowerBtn, 'move'),
165
+ copy: $n_has(allPowerBtn, 'copy'),
166
+ delete: $n_has(allPowerBtn, 'delete'),
167
+ status: $n_has(allPowerBtn, 'status'),
168
+ allPowerBtn,
169
+ }
170
+ })
171
+
172
+ /**
173
+ * 获取节点
174
+ */
175
+ function getNode(nodeId) {
176
+ return getTreeNode(nodes.value, nodeId)
177
+ }
178
+
179
+ /**
180
+ * 格式化节点
181
+ */
182
+ function formatNode(attr) {
183
+
184
+ // 设置属性
185
+ attr = Object.assign({}, attr)
186
+
187
+ return {
188
+ attr,
189
+ id: attr.id,
190
+ label: attr.title,
191
+ children: [],
192
+ }
193
+ }
194
+
195
+ /**
196
+ * 更新节点
197
+ */
198
+ function updateNode(data) {
199
+
200
+ // 获取 id
201
+ const id = $n_get(formData.value, 'id')
202
+
203
+ // 更新表单数据
204
+ formData.value = Object.assign({}, formData.value, data)
205
+
206
+ // 获取节点数据
207
+ const nodeItem = getNode(data.id)
208
+
209
+ // 如果为更新节点
210
+ if (id) {
211
+ if (nodeItem) {
212
+ Object.assign(nodeItem, {
213
+ attr: Object.assign({}, formData.value),
214
+ label: formData.value.title,
215
+ })
216
+ }
217
+
218
+ // 否则为新增节点
219
+ } else if (
220
+ // 如果为新增节点
221
+ $n_get(data, 'id')
222
+ // 没有节点存在
223
+ && ! nodeItem
224
+ ) {
225
+ // 获取父级节点
226
+ const parentNodeItem = getNode(formData.value.pid)
227
+ if (! parentNodeItem) {
228
+ return
229
+ }
230
+
231
+ // 新增节点
232
+ parentNodeItem.children.push(formatNode(formData.value))
233
+ }
234
+ }
235
+
236
+ /**
237
+ * 删除节点
238
+ */
239
+ function deleteNode({ id, attr }) {
240
+
241
+ // 获取父节点数据
242
+ const parentNodeItem = getNode(attr.pid)
243
+ if (! parentNodeItem) {
244
+ return
245
+ }
246
+
247
+ // 获取节点索引
248
+ const nodeIndex = $n_findIndex(parentNodeItem.children, { id })
249
+ if (nodeIndex > -1) {
250
+ parentNodeItem.children.splice(nodeIndex, 1)
251
+ }
252
+ }
253
+
254
+ /**
255
+ * 确认菜单
256
+ */
257
+ function confirmMenu(callback) {
258
+ // 确认框
259
+ $n_confirm({
260
+ message: '确认要执行该操作吗?',
261
+ })
262
+ // 点击确认执行
263
+ .onOk(callback)
264
+ }
265
+
266
+ /**
267
+ * 菜单点击
268
+ */
269
+ function menuClick(options) {
270
+
271
+ // 参数
272
+ const o = Object.assign({
273
+ // 菜单类型
274
+ type: '',
275
+ // 节点
276
+ node: null,
277
+ }, options)
278
+
279
+ // 菜单类型
280
+ switch (o.type) {
281
+
282
+ // 添加下级
283
+ case 'update':
284
+ // 更新表单数据
285
+ formData.value = Object.assign({}, initFormData, {
286
+ pid: o.node.attr.id,
287
+ })
288
+ break
289
+
290
+ // 复制
291
+ case 'copy':
292
+ // 确认菜单
293
+ confirmMenu(async function() {
294
+
295
+ if (! $n_get(menuStatus.value, 'allPowerBtn.copy.url')) {
296
+ console.error('没有找到复制地址')
297
+ return
298
+ }
299
+
300
+ // 复制的当前节点的属性
301
+ const newAttr = Object.assign({}, o.node.attr, {
302
+ title: '【复制】' + o.node.attr.title,
303
+ })
304
+
305
+ // 复制列表
306
+ const copyLists = [ newAttr ]
307
+
308
+ // 是否复制叶子节点
309
+ const isLeafNode = ! o.node.children.length
310
+
311
+ // 如果复制的是父级节点
312
+ if (! isLeafNode) {
313
+ getChildren(o.node.children, function(item) {
314
+ copyLists.push(item.attr)
315
+ })
316
+ }
317
+
318
+ // 请求 - 复制
319
+ const { status, data: res } = await $n_http({
320
+ url: menuStatus.value.allPowerBtn.copy.url,
321
+ data: {
322
+ data: copyLists,
323
+ },
324
+ })
325
+ if (! status) {
326
+ return
327
+ }
328
+
329
+ // 如果复制的是叶子节点
330
+ if (isLeafNode) {
331
+
332
+ // 如果返回了 id
333
+ if ($n_hasId(res)) {
334
+
335
+ // 更新数据
336
+ Object.assign(newAttr, res)
337
+
338
+ // 获取该叶子节点的父级节点
339
+ const parentNodeItem = getNode(newAttr.pid)
340
+ if (! parentNodeItem) {
341
+ return
342
+ }
343
+
344
+ // 新增节点
345
+ parentNodeItem.children.push(formatNode(newAttr))
346
+
347
+ // 否则重新加载列表
348
+ } else {
349
+ reload()
350
+ }
351
+
352
+ // 否则重新加载列表
353
+ } else {
354
+ reload()
355
+ }
356
+
357
+ // 轻提示
358
+ $n_toast({
359
+ type: 'positive',
360
+ message: '复制成功',
361
+ })
362
+ })
363
+ break
364
+
365
+ // 删除
366
+ case 'delete':
367
+
368
+ // 如果有子节点
369
+ if (o.node.children.length) {
370
+ // 提示框
371
+ $n_alert({
372
+ message: '请先删除该节点下的子节点',
373
+ })
374
+ return
375
+ }
376
+
377
+ if (! $n_get(menuStatus.value, 'allPowerBtn.delete.url')) {
378
+ console.error('没有找到删除地址')
379
+ return
380
+ }
381
+
382
+ // 确认菜单
383
+ confirmMenu(async function() {
384
+
385
+ // 请求 - 删除
386
+ const { status } = await $n_http({
387
+ url: menuStatus.value.allPowerBtn.delete.url,
388
+ data: {
389
+ id: o.node.id,
390
+ },
391
+ })
392
+ if (! status) {
393
+ return
394
+ }
395
+
396
+ // 删除节点
397
+ deleteNode(o.node)
398
+
399
+ // 轻提示
400
+ $n_toast({
401
+ type: 'positive',
402
+ message: '删除成功',
403
+ })
404
+ })
405
+ break
406
+
407
+ // 全部禁用
408
+ case 'statusDisable':
409
+ // 全部正常
410
+ case 'statusNormal':
411
+
412
+ if (! $n_get(menuStatus.value, 'allPowerBtn.status.url')) {
413
+ console.error('没有找到状态地址')
414
+ return
415
+ }
416
+
417
+ // 确认菜单
418
+ confirmMenu(async function() {
419
+
420
+ // 设置状态 ids
421
+ const statusIds = [ o.node.id ]
422
+
423
+ // 新状态
424
+ const newStatus = o.type === 'statusNormal' ? 1 : 0
425
+
426
+ // 是否叶子节点
427
+ const isLeafNode = ! o.node.children.length
428
+
429
+ // 如果复制的是父级节点
430
+ if (! isLeafNode) {
431
+ getChildren(o.node.children, function(item) {
432
+ statusIds.push(item.id)
433
+ })
434
+ }
435
+
436
+ // 请求 - 全部禁用/正常
437
+ const { status } = await $n_http({
438
+ url: menuStatus.value.allPowerBtn.status.url,
439
+ data: {
440
+ // ids
441
+ ids: statusIds,
442
+ // 新状态值
443
+ status: newStatus,
444
+ },
445
+ })
446
+ if (! status) {
447
+ return
448
+ }
449
+
450
+ // 设置当前节点状态
451
+ o.node.attr.status = newStatus
452
+
453
+ // 如果是父级节点
454
+ if (! isLeafNode) {
455
+ getChildren(o.node.children, function(item) {
456
+ item.attr.status = newStatus
457
+ })
458
+ }
459
+
460
+ // 轻提示
461
+ $n_toast({
462
+ type: 'positive',
463
+ message: '恭喜您,操作成功',
464
+ })
465
+ })
466
+ break
467
+ }
468
+ }
469
+
470
+ /**
471
+ * 获取展开节点缓存
472
+ */
473
+ function getExpandedCache(defaultValue = []) {
474
+ // 获取展开节点缓存
475
+ const res = $n_storage.get('tree_expanded_' + $route.fullPath)
476
+ return $n_isValidArray(res) ? res : defaultValue
477
+ }
478
+
479
+ /**
480
+ * 设置展开节点缓存
481
+ */
482
+ function setExpandedCache(expanded) {
483
+ // 设置展开节点缓存(永久缓存)
484
+ $n_storage.set('tree_expanded_' + $route.fullPath, expanded, 0)
485
+ }
486
+
487
+ /**
488
+ * 展开全部
489
+ */
490
+ function expandAll() {
491
+
492
+ // 展开节点 ids
493
+ const ids = []
494
+
495
+ function getChildren(data) {
496
+ for (const { id, children } of data) {
497
+ ids.push(id)
498
+ if ($n_isValidArray(children)) {
499
+ getChildren(children)
500
+ }
501
+ }
502
+ }
503
+
504
+ if ($n_isValidArray(nodes.value)) {
505
+ getChildren(nodes.value)
506
+ }
507
+
508
+ // 设置展开节点数组
509
+ expanded.value = ids
510
+ }
511
+
512
+ /**
513
+ * 收起全部
514
+ */
515
+ function collapseAll() {
516
+ // 设置展开节点数组
517
+ expanded.value = [0]
518
+ }
519
+
520
+ /**
521
+ * 判断节点能否被拖拽
522
+ */
523
+ function allowDrag(draggingNode) {
524
+ return $n_hasId(draggingNode.id)
525
+ }
526
+
527
+ /**
528
+ * 拖拽时判定目标节点能否被放置, type 参数: top / inner / bottom / none ( 目标节点上方 / 目标节点内部 / 目标节点下方 / 无任何操作 )
529
+ */
530
+ function allowDrop(draggingNode, dropNode, dropType) {
531
+ return dropType === 'inner'
532
+ || $n_hasId(dropNode.id)
533
+ }
534
+
535
+ /**
536
+ * 树节点拖拽结束
537
+ */
538
+ async function nodeDragEnd(draggingNode, dropNode, dropType, doDrop) {
539
+ if (dropType !== 'none') {
540
+
541
+ if (! $n_get(menuStatus.value, 'allPowerBtn.move.url')) {
542
+
543
+ // 提示框
544
+ $n_alert({
545
+ message: '没有找到移动地址',
546
+ })
547
+
548
+ return
549
+ }
550
+
551
+ // 克隆当前树列表数据
552
+ const nodesClone = $n_cloneDeep(nodes.value)
553
+
554
+ // 开始拖拽
555
+ const children = doDrop()
556
+ if (children === false) {
557
+ return
558
+ }
559
+
560
+ // 修改拖拽节点的父级 id
561
+ draggingNode.attr.pid =
562
+ // 如果拖动节点 在 目标节点的 内部
563
+ dropType === 'inner' ?
564
+ // 将拖动节点的 pid 改为 目标节点的 id
565
+ dropNode.attr.id
566
+ // 将拖动节点的 pid 改为 目标节点的 pid
567
+ : dropNode.attr.pid
568
+
569
+ // 移动列表
570
+ const moveLists = []
571
+
572
+ // 当前拖拽节点在新列表中的索引
573
+ let dropIndex = $n_findIndex(children, e => e.id === draggingNode.id)
574
+ if (dropIndex > -1) {
575
+
576
+ // if (
577
+ // // 如果拖拽到目标节点下方
578
+ // dropType === 'bottom'
579
+ // // 并且拖拽节点当前的位置不是第一个
580
+ // && dropIndex > 0
581
+ // ) {
582
+ // dropIndex--
583
+ // }
584
+ // for (let i = dropIndex; i < children.length; i++) {
585
+ // const { attr } = children[i]
586
+ // attr.sort = i + 1
587
+ // moveLists.push({
588
+ // id: attr.id,
589
+ // pid: attr.pid,
590
+ // sort: attr.sort,
591
+ // })
592
+ // }
593
+
594
+ for (let i = 0, len = children.length; i < len; i++) {
595
+ const { attr } = children[i]
596
+
597
+ // 新排序号
598
+ const newSort = i + 1
599
+
600
+ if (
601
+ i >= dropIndex
602
+ || newSort !== attr.sort
603
+ ) {
604
+ attr.sort = newSort
605
+ moveLists.push({
606
+ id: attr.id,
607
+ pid: attr.pid,
608
+ sort: attr.sort,
609
+ })
610
+ }
611
+ }
612
+
613
+ // 如果有移动列表
614
+ if (moveLists.length) {
615
+
616
+ // 请求 - 移动
617
+ const { status } = await $n_http({
618
+ url: menuStatus.value.allPowerBtn.move.url,
619
+ data: {
620
+ data: moveLists,
621
+ },
622
+ })
623
+
624
+ // 移动成功
625
+ if (status) {
626
+ return
627
+ }
628
+ }
629
+ }
630
+
631
+ // 移动失败, 还原数据
632
+ nodes.value = nodesClone
633
+ }
634
+ }
635
+
636
+ return {
637
+ // 当前路由全路径
638
+ routeFullPath: $route.fullPath,
639
+ // 当前路由路径
640
+ routePath: $route.path,
641
+ // 当前路由参数
642
+ routeQuery: $route.query,
643
+ // 菜单状态
644
+ menuStatus,
645
+ // 获取当前路由
646
+ getRoute() {
647
+ return $route
648
+ },
649
+ // 获取节点
650
+ getNode,
651
+ // 更新节点
652
+ updateNode,
653
+ // 删除节点
654
+ deleteNode,
655
+ // 菜单点击
656
+ menuClick,
657
+ // 获取展开节点缓存
658
+ getExpandedCache,
659
+ // 设置展开节点缓存
660
+ setExpandedCache,
661
+ // 展开全部
662
+ expandAll,
663
+ // 收起全部
664
+ collapseAll,
665
+ // 判断节点能否被拖拽
666
+ allowDrag,
667
+ // 拖拽时判定目标节点能否被放置, type 参数: top / inner / bottom / none ( 目标节点上方 / 目标节点内部 / 目标节点下方 / 无任何操作 )
668
+ allowDrop,
669
+ // 树节点拖拽结束
670
+ nodeDragEnd,
671
+ }
672
+ }
673
+
674
+ /**
675
+ * 树业务
676
+ */
677
+ const $tree = {
678
+ // 创建树实例
679
+ create,
680
+ }
681
+
682
+ export default $tree