code.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. import search from './search/index.vue'
  2. /*
  3. * 已兼容h5和小程序端,其它端没测试过,估计问题不大,只需要改一下传值的方式
  4. *
  5. * 如有问题可以加qq:122720267
  6. *
  7. * 使用该插件的朋友请给个好评,或者到git start一下
  8. * git地址:https://github.com/LSZ579/xiaolu-tree-plugin.git
  9. * 插件市场地址: https://ext.dcloud.net.cn/plugin?id=2423
  10. *
  11. */
  12. export default {
  13. name: "treeComponent",
  14. data() {
  15. return {
  16. isre: false,
  17. tree: Object.freeze(this.treeNone),
  18. newNum: 0,
  19. oldNum: 0,
  20. catchTreeNone: [...this.treeNone],
  21. tree_stack: [1],
  22. searchResult: [],
  23. newCheckList: this.checkList,
  24. scrollLeft: 999,
  25. nodePathArray: []
  26. }
  27. },
  28. components: {
  29. search
  30. },
  31. computed: {
  32. isSelect() {
  33. return (item) => {
  34. const checkList = this.newCheckList
  35. if (checkList.length == 0) {
  36. this.props.checkStrictly ? (item.bx = 0, item.qx = 0) : ''
  37. return false
  38. }
  39. const i = checkList.findIndex(e => {
  40. return item[this.keyCode] == e[this.keyCode]
  41. }) > -1
  42. return i && !item.qx
  43. }
  44. },
  45. radioSelect() {
  46. const list = this.newCheckList
  47. return (item) => {
  48. return list.length > 0 && item[this.keyCode] == list[0][this.keyCode]
  49. }
  50. },
  51. keyCode() {
  52. return this.keyValue
  53. }
  54. },
  55. created() {
  56. this.Init()
  57. },
  58. methods: {
  59. // 初始化
  60. Init() {
  61. if (this.newCheckList.length !== 0) {
  62. let {
  63. tree_stack,
  64. props,
  65. catchTreeNone,
  66. newCheckList
  67. } = this
  68. if (props.multiple) {
  69. if (props.checkStrictly) {
  70. this.checkAllChoose();
  71. }
  72. } else {
  73. this.getNodeRoute(catchTreeNone, newCheckList[0][this.keyCode])
  74. let arr = this.nodePathArray.reverse()
  75. console.log(arr)
  76. if (arr.length == 0) return
  77. this.tree_stack = tree_stack.concat(arr);
  78. this.tree = this.tree_stack[this.tree_stack.length - 1].children;
  79. }
  80. }
  81. },
  82. // 点击项目处理
  83. handleClick(item, index) {
  84. let children = item[this.props.children]
  85. if (index > -1 && children && children.length > 0) {
  86. this.toChildren(item)
  87. } else if (this.props.multiple) {
  88. this.checkboxChange(item, index, item.bx, item.qx)
  89. } else {
  90. this.checkbox(item, index)
  91. }
  92. },
  93. // 获取路径
  94. getPath() {
  95. const {
  96. keyCode,
  97. tree_stack,
  98. props
  99. } = this
  100. const path = [...tree_stack].map(e => {
  101. const item = Object.assign({}, e)
  102. delete item[props.children]
  103. return item
  104. })
  105. return path.slice(1, path.length) || []
  106. },
  107. //多选
  108. async checkboxChange(item, index, bx, qx) {
  109. let that = this;
  110. const {
  111. props
  112. } = that
  113. if (!props.multiple) return;
  114. let findIdex = that.newCheckList.findIndex(e => item[this.keyCode] == e[this.keyCode]);
  115. const path = this.getPath()
  116. if (findIdex > -1) { //反选
  117. if (props.checkStrictly) { //关联子级
  118. if (item.user) { //用户
  119. that.newCheckList.splice(findIdex, 1)
  120. } else { //非用户,取消所有下一级
  121. that.getIdBydelete(item.children)
  122. }
  123. } else {
  124. that.newCheckList.splice(findIdex, 1)
  125. }
  126. } else { //选中
  127. if (!item.user && props.checkStrictly) { //选中下一级
  128. if (qx || bx) { //取消下级
  129. await that.getIdBydelete(item.children);
  130. item.qx = 0;
  131. item.bx = 0;
  132. } else {
  133. item.qx = 1;
  134. item.bx = 0;
  135. const {
  136. id,
  137. name,
  138. user
  139. } = item
  140. const newObj = {
  141. id,
  142. name,
  143. user
  144. }
  145. const pathList = this.tree_stack.length === 1 ? [newObj, ...path] : [...path, newObj]
  146. await that.chooseChild(item.children, pathList);
  147. }
  148. this.$forceUpdate()
  149. return
  150. }
  151. that.newCheckList.push({ ...item,
  152. path
  153. });
  154. }
  155. },
  156. // 取消下一级的选中
  157. getIdBydelete(arr) {
  158. arr.forEach(e => {
  159. if (e.user) {
  160. for (var i = 0; i < this.newCheckList.length; i++) {
  161. if (e[this.keyCode] == this.newCheckList[i][this.keyCode]) {
  162. this.newCheckList.splice(i, 1)
  163. break;
  164. }
  165. }
  166. } else {
  167. this.getIdBydelete(e.children)
  168. }
  169. })
  170. },
  171. // 关联下一级,选中
  172. chooseChild(arr, path) {
  173. let that = this;
  174. const oldPath = [...path]
  175. for (var i = 0, len = arr.length; i < len; i++) {
  176. let item = arr[i];
  177. if (item.user) {
  178. that.newCheckList.push({ ...item,
  179. path: oldPath
  180. })
  181. } else {
  182. const newItem = { ...item
  183. }
  184. delete newItem[that.props.children]
  185. const newPath = [...oldPath, newItem]
  186. that.chooseChild(item.children, newPath)
  187. }
  188. }
  189. },
  190. // (tree为目标树,targetId为目标节点id)
  191. getNodeRoute(tree, targetId) {
  192. for (let index = 0; index < tree.length; index++) {
  193. if (tree[index].children) {
  194. let endRecursiveLoop = this.getNodeRoute(tree[index].children, targetId)
  195. if (endRecursiveLoop) {
  196. this.nodePathArray.push(tree[index])
  197. return true
  198. }
  199. }
  200. if (tree[index][this.keyCode] === targetId) {
  201. return true
  202. }
  203. }
  204. },
  205. //单选
  206. checkbox(item, index) {
  207. const path = this.getPath()
  208. this.$set(this, 'newCheckList', [{ ...item,
  209. path
  210. }])
  211. },
  212. //到下一级
  213. toChildren(item) {
  214. if (item.user) return
  215. var that = this;
  216. uni.showLoading({
  217. title: '加载中'
  218. })
  219. let children = that.props.children;
  220. if (!item.user && item[children].length > 0 && !(that.tree_stack[0][this.keyCode] == item[this.keyCode])) {
  221. that.tree = item[children];
  222. that.tree_stack.push(item);
  223. }
  224. this.$nextTick(() => {
  225. uni.hideLoading()
  226. this.scrollLeft += 200;
  227. })
  228. if (this.props.checkStrictly) this.checkAllChoose();
  229. },
  230. //搜索
  231. confirmSearch(val) {
  232. this.searchResult = []
  233. this.search(this.catchTreeNone, val)
  234. this.isre = true
  235. this.tree_stack.splice(1, 1000)
  236. uni.showLoading({
  237. title: '正在查找'
  238. })
  239. setTimeout(() => {
  240. this.tree = this.searchResult
  241. uni.hideLoading()
  242. }, 300)
  243. },
  244. search(data, keyword) {
  245. var that = this
  246. let children = that.props.children
  247. for (var i = 0, len = data.length; i < len; i++) {
  248. if (data[i].name.indexOf(keyword) >= 0) {
  249. that.searchResult.push(data[i])
  250. }
  251. if (!data[i].user && data[i][children].length > 0) {
  252. that.search(data[i][children], keyword)
  253. }
  254. }
  255. },
  256. checkAllChoose() {
  257. let o = false,
  258. t = true;
  259. this.tree.forEach((e, i) => {
  260. if (!e.user) {
  261. e.qx = o;
  262. e.bx = o;
  263. this.computAllNumber(e.children);
  264. // console.log(this.newNum,this.oldNum)
  265. if (this.newNum != 0 && this.oldNum != 0) {
  266. if (this.newNum == this.oldNum) {
  267. e.qx = t;
  268. e.bx = o;
  269. } else {
  270. e.qx = o;
  271. e.bx = t;
  272. }
  273. }
  274. if (this.newNum != 0 && this.oldNum == 0) {
  275. this.$set(this.tree[i], 'bx', o);
  276. this.$set(this.tree[i], 'qx', o);
  277. }
  278. this.$forceUpdate()
  279. this.newNum = 0
  280. this.oldNum = 0
  281. }
  282. })
  283. },
  284. computAllNumber(arr) {
  285. for (let j = 0; j < arr.length; j++) {
  286. var e = arr[j];
  287. this.checkSum(e[this.keyCode])
  288. if (e.user) {
  289. this.newNum++;
  290. } else {
  291. this.computAllNumber(e.children)
  292. }
  293. }
  294. },
  295. checkSum(id) {
  296. for (let i = 0; i < this.newCheckList.length; i++) {
  297. if (id == this.newCheckList[i][this.keyCode]) {
  298. this.oldNum++;
  299. break
  300. }
  301. }
  302. },
  303. //返回其它层
  304. backTree(item, index) {
  305. let that = this,
  306. tree_stack = that.tree_stack,
  307. max = 10000;
  308. if (index === -1) {
  309. that.tree = that.catchTreeNone
  310. that.tree_stack.splice(1, max)
  311. that.isre = false
  312. that.$refs.sea.clears()
  313. } else if (index === -2) {
  314. that.tree = that.searchResult
  315. that.tree_stack.splice(1, max)
  316. } else {
  317. if (tree_stack.length - index > 2) {
  318. tree_stack.forEach((item, i) => {
  319. if (i > index) {
  320. that.tree_stack.splice(i, max)
  321. }
  322. })
  323. } else if (index !== tree_stack.length - 1) {
  324. that.tree_stack.splice(tree_stack.length - 1, 1)
  325. }
  326. that.tree = item[that.props.children]
  327. }
  328. if (this.props.checkStrictly) this.checkAllChoose();
  329. this.$forceUpdate()
  330. },
  331. backConfirm() {
  332. this.$emit('sendValue', this.newCheckList, 'back')
  333. }
  334. },
  335. props: {
  336. treeNone: {
  337. type: Array,
  338. default: () => {
  339. return []
  340. }
  341. },
  342. //是否开启选中
  343. isCheck: {
  344. type: Boolean,
  345. default: () => {
  346. return false
  347. }
  348. },
  349. checkList: {
  350. type: Array,
  351. default: () => []
  352. },
  353. parentList: {
  354. type: Array,
  355. default: () => []
  356. },
  357. searchIf: {
  358. type: Boolean,
  359. default: () => true
  360. },
  361. keyValue: {
  362. type: String,
  363. default: 'id',
  364. },
  365. props: {
  366. type: Object,
  367. default: () => {
  368. return {
  369. label: 'name',
  370. children: 'children',
  371. multiple: false,
  372. checkStrictly: false, //不关联
  373. }
  374. }
  375. }
  376. },
  377. }