tm-tree.vue 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. <template>
  2. <view class="tm-tree ">
  3. <view v-for="(item, index) in list_c" :key="index">
  4. <view :class="['text-size-s', 'py-16 ml-32']">
  5. <view v-if="!item.isDir" class=" flex-start">
  6. <view v-if="!read" @click.stop="changeCheckboxItem(item)" class="pr-12">
  7. <tm-checkbox :fllowTheme="fllowTheme" :color="color_tmeme" :disabled="item['disabled']" dense
  8. v-model="item.checked"></tm-checkbox>
  9. </view>
  10. <view class="flex-start">
  11. <view v-if="item['icon']" class="pr-10">
  12. <tm-icons :fllowTheme="fllowTheme" :color="color_tmeme" dense :name="item['icon']"
  13. :size="32"></tm-icons>
  14. </view>
  15. <text :class="[`text-${item.checked ? color_tmeme : black_tmeme ? 'grey' : 'black'}`]"
  16. class="text-size-n">{{ item["title"]||item["text"] }}</text>
  17. </view>
  18. </view>
  19. <view v-if="item.isDir" class="">
  20. <view @click.stop="groupOpenChange(item)" class="flex-between">
  21. <view class="flex-start">
  22. <tm-icons :fllowTheme="fllowTheme" :color="color_tmeme"
  23. :name="item.openDir ? dirIconList[1] : dirIconList[0]" :size="32"></tm-icons>
  24. <view v-if="!read && mode=='multi'" @click.stop="changeCheckboxGroupItem(item)" class="px-12">
  25. <tm-checkbox :icon="item['dirType']==3?'icon-minus':'icon-check'"
  26. :fllowTheme="fllowTheme" :color="color_tmeme" :disabled="item['disabled']" dense
  27. v-model="item.checked"></tm-checkbox>
  28. </view>
  29. <text
  30. :class="[`text-${item.checked ? color_tmeme : black_tmeme ? 'grey' : 'black'}`, black_tmeme ? 'bk' : '']"
  31. class="text-size-n">
  32. {{ item["title"]||item["text"] }}
  33. </text>
  34. </view>
  35. </view>
  36. <view v-if="item.openDir && item['children'].length > 0" class="ml-24 flex-shrink border-l-1 "
  37. :class="[black_tmeme ? 'bk' : '']" style="border-left-style: dotted;">
  38. <tm-tree :mode="mode" :read="read" :fllowTheme="fllowTheme" :color="color_tmeme"
  39. :dirOpenIcon="dirIconList[1]" :dirCloseIcon="dirIconList[0]" @changePrarent="changePrarent"
  40. :list="item['children']" :prarent="item" @praentclear="preantchangClearChecked"></tm-tree>
  41. </view>
  42. </view>
  43. </view>
  44. </view>
  45. </view>
  46. </template>
  47. <script>
  48. /**
  49. * 树状结构
  50. * @property {Array} list = [] 默认数据列表。
  51. * @property {Array} defalut-value = [] 默认选中的项,通过id的集合。
  52. * @property {String} dirCloseIcon = [] 默认 'icon-caret-right',关闭后的图标
  53. * @property {String} dirOpenIcon = [] 默认 'icon-sort-down',打开后的图标
  54. * @property {String} color = [] 默认 'primary',主题色
  55. * @property {String} mode = [multi|radio] 默认 'multi',多选或单选模式。
  56. * @property {Boolean|String} read = [] 默认 false,是否只读,作为目录展示
  57. */
  58. import tmCheckbox from '@/tm-vuetify/components/tm-checkbox/tm-checkbox.vue';
  59. import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
  60. import tmTree from '@/tm-vuetify/components/tm-tree/tm-tree.vue';
  61. export default {
  62. name: 'tm-tree',
  63. components: {
  64. tmCheckbox,
  65. tmTree,
  66. tmIcons
  67. },
  68. props: {
  69. list: {
  70. type: Array,
  71. default: () => {
  72. return [];
  73. }
  74. },
  75. defalutValue: {
  76. type: Array,
  77. default: () => []
  78. },
  79. dirCloseIcon: {
  80. type: String,
  81. default: 'icon-caret-right'
  82. },
  83. dirOpenIcon: {
  84. type: String,
  85. default: 'icon-sort-down'
  86. },
  87. color: {
  88. type: String,
  89. default: 'primary'
  90. },
  91. //外部不允许使用。
  92. prarent: {
  93. type: Object,
  94. default: () => null
  95. },
  96. // 跟随主题色的改变而改变。
  97. fllowTheme: {
  98. type: Boolean | String,
  99. default: true
  100. },
  101. // 是否开启暗黑模式
  102. black: {
  103. type: String | Boolean,
  104. default: null
  105. },
  106. read: {
  107. type: Boolean | String,
  108. default: false
  109. },
  110. mode:{
  111. type:String,
  112. default:'multi' //radio 单选 multi多选
  113. }
  114. },
  115. watch: {
  116. list: {
  117. deep: true,
  118. handler() {
  119. this.list_c = this.list;
  120. }
  121. }
  122. },
  123. computed: {
  124. black_tmeme: function() {
  125. if (this.black !== null) return this.black;
  126. return this.$tm.vx.state().tmVuetify.black;
  127. },
  128. color_tmeme: function() {
  129. if (this.$tm.vx.state().tmVuetify.color !== null && this.$tm.vx.state().tmVuetify.color && this
  130. .fllowTheme) {
  131. return this.$tm.vx.state().tmVuetify.color;
  132. }
  133. return this.color;
  134. },
  135. dirIconList: function() {
  136. return [this.dirCloseIcon, this.dirOpenIcon];
  137. },
  138. list_c: {
  139. get() {
  140. return this.listData;
  141. },
  142. set(val) {
  143. this.chulilist(val);
  144. let rulst = this.getCheckedArray();
  145. this.$emit('change', rulst);
  146. }
  147. }
  148. },
  149. data() {
  150. return {
  151. showContent: true,
  152. listData: []
  153. };
  154. },
  155. mounted() {
  156. this.list_c = this.list;
  157. this.setDefaultSelectedKey();
  158. },
  159. methods: {
  160. groupOpenChange(item) {
  161. if (item['disabled'] === true) return;
  162. this.$nextTick(function() {
  163. let p = !item.openDir;
  164. this.list_c = this.setChildListData(this.list_c, item, 'openDir', !item.openDir);
  165. });
  166. },
  167. // 子项目点击选中切换。
  168. changeCheckboxItem(item) {
  169. if (item['disabled'] === true || this.prarent?.disabled === true) return;
  170. this.$nextTick(function() {
  171. this.list_c = this.setChildListData(this.list_c, item, 'checked', item.checked);
  172. if(this.mode=="radio"){
  173. this.clearChecked()
  174. item.checked = true;
  175. this.$emit('praentclear',item);
  176. if(!this.prarent){
  177. this.preantchangClearChecked(item)
  178. }
  179. return;
  180. }
  181. this.$nextTick(function() {
  182. if (this.prarent) {
  183. //递归修改父节点。
  184. let p = {
  185. ...this.prarent
  186. };
  187. p.children = [...this.list_c];
  188. let prenatKeyArray = this.getChildrenKeyToArray(p, 'checked');
  189. let isAllChecked = true; //是否全部选中。
  190. let isAllChecked_min = true; //是否半选中。
  191. let isAllCheckedAr_all_true = prenatKeyArray.filter((el, eindex) => {
  192. return el == true;
  193. })
  194. let isAllCheckedAr_all_false = prenatKeyArray.filter((el, eindex) => {
  195. return el == false;
  196. })
  197. isAllChecked = isAllCheckedAr_all_true.length === prenatKeyArray.length ?
  198. true : false;
  199. isAllChecked_min = isAllCheckedAr_all_true.length > 0 &&
  200. isAllCheckedAr_all_false.length > 0 ? true : false;
  201. p['children'] = this.checkAllChildren(p['children']);
  202. if (isAllChecked) {
  203. p['dirType'] = 2;
  204. }
  205. if (isAllChecked_min) {
  206. p['dirType'] = 3;
  207. }
  208. if (isAllCheckedAr_all_true.length == 0) {
  209. p['dirType'] = 1;
  210. }
  211. isAllChecked = isAllChecked_min || isAllChecked ? true : false;
  212. p['checked'] = isAllChecked;
  213. // let prenatKeyArray = this.getChildrenKeyToArray(p, 'checked');
  214. // let isAllChecked = true;
  215. // for (let i = 0; i < prenatKeyArray.length; i++) {
  216. // if (prenatKeyArray[i] === false) {
  217. // isAllChecked = false;
  218. // break;
  219. // }
  220. // }
  221. // p.checked = isAllChecked;
  222. this.$emit('changePrarent', p);
  223. }else{
  224. }
  225. });
  226. });
  227. },
  228. //收到子节点修改父节点的请求。
  229. changePrarent(item) {
  230. this.$nextTick(function() {
  231. let index = this.list_c.findIndex(ix => ix.id === item.id);
  232. this.list_c.splice(index, 1, item);
  233. if (this.prarent) {
  234. if (item['disabled'] === true) return;
  235. if (this.prarent['disabled'] === true) return;
  236. // 再反递归,修改它的上一级,一直类推到第一级。
  237. let p = {
  238. ...this.prarent
  239. };
  240. p.children = [...this.list_c];
  241. let prenatKeyArray = this.getChildrenKeyToArray(p, 'checked');
  242. let isAllChecked = true; //是否全部选中。
  243. let isAllChecked_min = true; //是否半选中。
  244. let isAllCheckedAr_all_true = prenatKeyArray.filter((el, eindex) => {
  245. return el == true;
  246. })
  247. let isAllCheckedAr_all_false = prenatKeyArray.filter((el, eindex) => {
  248. return el == false;
  249. })
  250. isAllChecked = isAllCheckedAr_all_true.length === prenatKeyArray.length ? true : false;
  251. isAllChecked_min = isAllCheckedAr_all_true.length > 0 && isAllCheckedAr_all_false.length >
  252. 0 ? true : false;
  253. p['children'] = this.checkAllChildren(p['children']);
  254. if (isAllChecked) {
  255. p['dirType'] = 2;
  256. }
  257. if (isAllChecked_min) {
  258. p['dirType'] = 3;
  259. }
  260. if (isAllCheckedAr_all_true.length == 0) {
  261. p['dirType'] = 1;
  262. }
  263. isAllChecked = isAllChecked_min || isAllChecked ? true : false;
  264. p['checked'] = isAllChecked;
  265. this.$emit('changePrarent', p);
  266. } else {
  267. // 第一级。
  268. let rulst = this.getCheckedArray();
  269. this.$emit('change', rulst);
  270. }
  271. });
  272. },
  273. //收到子节点请求清空所有选择,并设置某个属性
  274. preantchangClearChecked(item){
  275. if(!this.prarent){
  276. this.clearChecked();
  277. if(item){
  278. let t = this
  279. if(typeof item == 'object' && !Array.isArray(item)){
  280. setTimeout(function(){
  281. t.setDefaultSelectedKey([item.id])
  282. },150)
  283. }else if(typeof item == 'object' && Array.isArray(item)){
  284. setTimeout(function(){
  285. t.setDefaultSelectedKey([...item])
  286. },150)
  287. }
  288. }
  289. }else{
  290. this.$emit('praentclear',item);
  291. }
  292. },
  293. //设置某一个key的属性。
  294. /**
  295. * @param {Object} list 目标数组
  296. * @param {Object} item 待修改的对象(根据item.id修改)
  297. * @param {Object} key 待修改的字段名称
  298. * @param {Object} value 待修改的字段变量。
  299. */
  300. setChildListData(list, item, key, value) {
  301. let parar = [...list];
  302. function ch(objAr) {
  303. let p = [];
  304. if (typeof objAr == 'object' && Array.isArray(objAr)) {
  305. for (let i = 0; i < objAr.length; i++) {
  306. p.push(ch(objAr[i]));
  307. }
  308. return p;
  309. } else if (typeof objAr === 'object') {
  310. let children = objAr['children'];
  311. if (typeof children === 'object' && Array.isArray(children) && children.length>0) {
  312. let xg = {};
  313. if (item.id === objAr.id) {
  314. if(key=='checked'){
  315. if(objAr['disabled']!==true){
  316. xg[key] = value;
  317. }
  318. }else{
  319. xg[key] = value;
  320. }
  321. }
  322. return {
  323. ...objAr,
  324. checked: objAr['checked'] || false,
  325. isDir: objAr['isDir'] || true,
  326. openDir: objAr['openDir'] || false,
  327. dirType: objAr['dirType'] || 1,
  328. children: ch(children),
  329. ...xg
  330. };
  331. } else {
  332. let xg = {};
  333. if (item.id === objAr.id) {
  334. if(objAr!='checked'){
  335. if(item['disabled']!==true){
  336. xg[key] = value;
  337. }
  338. }else{
  339. xg[key] = value;
  340. }
  341. }
  342. let isDir = false;
  343. if (typeof objAr['isDir'] === 'boolean') isDir = objAr['isDir'];
  344. if (typeof objAr['children'] === 'object' && Array.isArray(objAr['children']) && children.length>0) {
  345. if (objAr['children'].length > 0) {
  346. isDir = true;
  347. }
  348. }
  349. return {
  350. ...objAr,
  351. isDir: isDir || false,
  352. checked: objAr['checked'] || false,
  353. ...xg
  354. };
  355. }
  356. }
  357. }
  358. return ch(parar);
  359. },
  360. //通过key的唯一属性取得子集。
  361. /**
  362. * @param {Object} item 目标数组
  363. * @param {Object} key 筛选的字段名称
  364. * @param {Object} value 筛选的的字段变量。
  365. */
  366. getChildren(item, key, value) {
  367. let parar = [...item];
  368. function ch(objAr) {
  369. let p = null;
  370. if (typeof objAr == 'object' && Array.isArray(objAr) && objAr.length>0) {
  371. for (let i = 0; i < objAr.length; i++) {
  372. p = ch(objAr[i]);
  373. if (p) {
  374. break;
  375. }
  376. }
  377. return p;
  378. } else if (typeof objAr === 'object') {
  379. let children = objAr['children'];
  380. if (typeof children === 'object' && Array.isArray(children) && children.length>0) {
  381. if (objAr[key] == value) {
  382. return objAr;
  383. }
  384. p = ch(objAr.children);
  385. if (p) {
  386. return p;
  387. }
  388. return false;
  389. } else {
  390. if (objAr[key] == value) {
  391. return objAr;
  392. }
  393. return false;
  394. }
  395. }
  396. }
  397. return ch(parar);
  398. },
  399. //取得子集下所有相同属性的集合。根据指定key的变量条件取得。
  400. getChildrenKeyToArrayByvalue(item, quereyKey, key, value) {
  401. function ch(objAr) {
  402. let p = [];
  403. if (typeof objAr == 'object' && Array.isArray(objAr)&& objAr.length>0) {
  404. for (let i = 0; i < objAr.length; i++) {
  405. p.push(...ch(objAr[i]));
  406. }
  407. return p;
  408. } else if (typeof objAr === 'object') {
  409. let children = objAr['children'];
  410. if (typeof children === 'object' && Array.isArray(children)&& children.length>0) {
  411. if (objAr[key] === value) {
  412. return [objAr[quereyKey], ...ch(children)];
  413. }
  414. return [];
  415. } else {
  416. if (objAr[key] === value) {
  417. return [objAr[quereyKey]];
  418. }
  419. return [];
  420. }
  421. }
  422. }
  423. let ru = [];
  424. //添加父节点。
  425. if (item[key] === value) {
  426. ru.push(item[quereyKey]);
  427. }
  428. if(typeof item =='object' && Array.isArray() && item?.children.lenght>0){
  429. let parar = [...item];
  430. ru = [...ru, ...ch(parar)];
  431. }
  432. if(typeof item =='object' && !Array.isArray()&& Array.isArray(item?.children)){
  433. let parar = [...item?.children];
  434. ru = [...ru, ...ch(parar)];
  435. }
  436. if(typeof item?.id == 'underfined'){
  437. return []
  438. }
  439. return ru;
  440. },
  441. //取得子集下所有相同属性的集合。
  442. getChildrenKeyToArray(item, key) {
  443. let parar = [...item.children];
  444. function ch(objAr) {
  445. let p = [];
  446. if (typeof objAr == 'object' && Array.isArray(objAr)&& objAr.length>0) {
  447. for (let i = 0; i < objAr.length; i++) {
  448. p.push(...ch(objAr[i]));
  449. }
  450. return p;
  451. } else if (typeof objAr === 'object') {
  452. let children = objAr['children'];
  453. if (typeof children === 'object' && Array.isArray(children)&& children.length>0) {
  454. return [objAr[key], ...ch(children)];
  455. } else {
  456. return [objAr[key]];
  457. }
  458. }
  459. }
  460. return ch(parar);
  461. },
  462. //打开某一项目录。通过id进行控制打开。
  463. /**
  464. * @param {Object} id 目录id,如果不是目录,不会执行。
  465. * @param {Object} dirType 打开类型:true,打开,close关闭。
  466. */
  467. __openDir(id, dirType = true) {
  468. //子节点不允许操作此函数。
  469. if (this.prarent == null) {
  470. let children = this.getChildren(this.list_c, 'id', id);
  471. if (children['isDir']) {
  472. children['openDir'] = dirType;
  473. this.setDirListData(children, 'openDir', dirType);
  474. }
  475. }
  476. },
  477. //打开所有折叠.
  478. __openAll(){
  479. // this.setDirListData(this.list_c, 'openDir', true);
  480. for(let i=0;i<this.list_c.length;i++){
  481. this.__openDir(this.list_c[i].id,true)
  482. }
  483. },
  484. //获取当前列表数据。子级不能调用。
  485. __getListdata() {
  486. if (this.prarent) return [];
  487. return this.list_c;
  488. },
  489. //添加数据。子级不可调用。
  490. //注意:如果提供的id是dir则在其子集中添加数据。因此如果想在本级添加数据需要提供父级id.
  491. //如果提供的id不是目录id,那么会自动创建它的子集。
  492. __addData(id, data = null) {
  493. if (this.prarent) return [];
  494. if (!data || typeof data != 'object') return;
  495. //不提供id默认在根目录添加数据追加。
  496. if (typeof id === 'undefined' || id == null || id == '') {
  497. let cp = uni.$tm.deepClone(this.list_c);
  498. cp.push(...data);
  499. this.list_c = cp;
  500. } else {
  501. let ps = uni.$tm.deepClone(this.list_c);
  502. for (let i = 0; i < ps.length; i++) {
  503. let children = this.getChildren(ps, 'id', id);
  504. //如果是目录,向其子集添加数据。
  505. if (children['isDir']) {
  506. children['children'].push(...data);
  507. this.list_c = this.setChildListData(ps, children, 'children', children['children']);
  508. //不是目录。它没有子集。创建子集。
  509. } else {
  510. children = {
  511. ...children,
  512. isDir: true,
  513. children: [...data]
  514. };
  515. ps = this.setChildListData(ps, children, 'isDir', true);
  516. ps = this.setChildListData(ps, children, 'children', children['children']);
  517. this.list_c = ps;
  518. }
  519. if (children) {
  520. break;
  521. }
  522. }
  523. }
  524. },
  525. // 项目父节点击选中切换。
  526. changeCheckboxGroupItem(item) {
  527. if (item['disabled'] === true) return;
  528. let t = this;
  529. t.setDirListData(item, 'checked', item.checked);
  530. if (t.prarent) {
  531. let p = {
  532. ...t.prarent
  533. };
  534. p.children = [...t.list_c];
  535. let prenatKeyArray = this.getChildrenKeyToArray(p, 'checked');
  536. let isAllChecked = true; //是否全部选中。
  537. let isAllChecked_min = true; //是否半选中。
  538. let isAllCheckedAr_all_true = prenatKeyArray.filter((el, eindex) => {
  539. return el == true;
  540. })
  541. let isAllCheckedAr_all_false = prenatKeyArray.filter((el, eindex) => {
  542. return el == false;
  543. })
  544. isAllChecked = isAllCheckedAr_all_true.length === prenatKeyArray.length ? true : false;
  545. isAllChecked_min = isAllCheckedAr_all_true.length > 0 && isAllCheckedAr_all_false.length > 0 ? true :
  546. false;
  547. p['children'] = this.checkAllChildren(p['children']);
  548. if (isAllChecked) {
  549. p['dirType'] = 2;
  550. }
  551. if (isAllChecked_min) {
  552. p['dirType'] = 3;
  553. }
  554. if (isAllCheckedAr_all_true.length == 0) {
  555. p['dirType'] = 1;
  556. }
  557. isAllChecked = isAllChecked_min || isAllChecked ? true : false;
  558. p['checked'] = isAllChecked;
  559. // let prenatKeyArray = t.getChildrenKeyToArray(p, 'checked');
  560. // let isAllChecked = true;
  561. // for (let i = 0; i < prenatKeyArray.length; i++) {
  562. // if (prenatKeyArray[i] === false) {
  563. // isAllChecked = false;
  564. // break;
  565. // }
  566. // }
  567. // p.checked = isAllChecked;
  568. t.$emit('changePrarent', p);
  569. }else{
  570. this.$nextTick(function(){
  571. this.list_c = this.checkAllChildren(this.list_c)
  572. })
  573. }
  574. },
  575. //设置dir下,所有子集相同的属性。
  576. setDirListData(item, key, value, callback) {
  577. let parar = uni.$tm.deepClone(item);
  578. function ch(objAr) {
  579. let p = [];
  580. if (typeof objAr == 'object' && Array.isArray(objAr)&& objAr.length>0) {
  581. for (let i = 0; i < objAr.length; i++) {
  582. p.push(ch(objAr[i]));
  583. }
  584. return p;
  585. } else if (typeof objAr === 'object') {
  586. let children = objAr['children'];
  587. if (typeof children === 'object' && Array.isArray(children)&& children.length>0) {
  588. let xg = {};
  589. if(key=='checked'){
  590. if(objAr['disabled']!==true){
  591. xg[key] = value;
  592. }
  593. }else{
  594. xg[key] = value;
  595. }
  596. return {
  597. ...objAr,
  598. checked: objAr['checked'] || false,
  599. isDir: objAr['isDir'] || true,
  600. openDir: objAr['openDir'] || false,
  601. dirType: objAr['dirType'] || 1,
  602. children: ch(children),
  603. ...xg
  604. };
  605. } else {
  606. let xg = {};
  607. if(key=='checked'){
  608. if(objAr['disabled']!==true){
  609. xg[key] = value;
  610. }
  611. }else{
  612. xg[key] = value;
  613. }
  614. return {
  615. ...objAr,
  616. isDir: objAr['isDir'] || false,
  617. checked: objAr['checked'] || false,
  618. ...xg
  619. };
  620. }
  621. }
  622. }
  623. let ts = ch(parar.children);
  624. let new_list = this.setChildListData(this.list_c, item, 'children', ts);
  625. this.list_c = [...new_list];
  626. if (callback) {
  627. callback();
  628. }
  629. },
  630. chulilist(list) {
  631. let parar = [...list];
  632. //dirType=1,未选中,2选中,3有选中,有未选中的
  633. function ch(objAr) {
  634. let p = [];
  635. if (typeof objAr == 'object' && Array.isArray(objAr)&& objAr.length>0) {
  636. for (let i = 0; i < objAr.length; i++) {
  637. p.push(ch(objAr[i]));
  638. }
  639. return p;
  640. } else if (typeof objAr === 'object') {
  641. let children = objAr['children'];
  642. if (typeof children === 'object' && Array.isArray(children)&& children.length>0) {
  643. return {
  644. ...objAr,
  645. checked: objAr['checked'] || false,
  646. isDir: objAr['isDir'] || true,
  647. dirType: objAr['dirType'] || 1,
  648. openDir: objAr['openDir'] || false,
  649. children: ch(children)
  650. };
  651. } else {
  652. return {
  653. ...objAr,
  654. isDir: objAr['isDir'] || false,
  655. checked: objAr['checked'] || false
  656. };
  657. }
  658. }
  659. }
  660. this.listData = ch(parar);
  661. },
  662. // 获取所有选中的条目指定条件的属性。id
  663. /**
  664. * @param {Object} key 需要取得的字段名称。 默认是id
  665. * @param {Object} quereyKey 条件查询的字段。默认是checked即选中的条目字段
  666. * @param {Object} value 条件查询的字段的变量。默认是true即选中的条目值
  667. */
  668. getCheckedArray(key, quereyKey, value) {
  669. key = typeof key === 'undefined' ? 'id' : key;
  670. quereyKey = typeof quereyKey === 'undefined' ? 'checked' : quereyKey;
  671. value = typeof value === 'undefined' ? true : value;
  672. if (this.prarent) return;
  673. let ps = uni.$tm.deepClone(this.list_c);
  674. let rulst = [];
  675. for (let i = 0; i < ps.length; i++) {
  676. let idArray = this.getChildrenKeyToArrayByvalue(ps[i], key, quereyKey, value);
  677. rulst.push(...idArray);
  678. }
  679. return rulst;
  680. },
  681. setDirListDataBySync(item, key, value) {
  682. let parar = uni.$tm.deepClone(item);
  683. function ch(objAr) {
  684. let p = [];
  685. if (typeof objAr == 'object' && Array.isArray(objAr)&& objAr.length>0) {
  686. for (let i = 0; i < objAr.length; i++) {
  687. p.push(ch(objAr[i]));
  688. }
  689. return p;
  690. } else if (typeof objAr === 'object') {
  691. let children = objAr['children'];
  692. if (typeof children === 'object' && Array.isArray(children)&& children.length>0) {
  693. let xg = {};
  694. if(key=='checked'){
  695. if(objAr['disabled']!==true){
  696. xg[key] = value;
  697. }
  698. }else{
  699. xg[key] = value;
  700. }
  701. return {
  702. ...objAr,
  703. checked: objAr['checked'] || false,
  704. isDir: objAr['isDir'] || true,
  705. openDir: objAr['openDir'] || false,
  706. dirType: objAr['dirType'] || 1,
  707. children: ch(children),
  708. ...xg
  709. };
  710. } else {
  711. let xg = {};
  712. if(key=='checked'){
  713. if(objAr['disabled']!==true){
  714. xg[key] = value;
  715. }
  716. }else{
  717. xg[key] = value;
  718. }
  719. return {
  720. ...objAr,
  721. isDir: objAr['isDir'] || false,
  722. checked: objAr['checked'] || false,
  723. ...xg
  724. };
  725. }
  726. }
  727. }
  728. let ts = ch(parar.children);
  729. let new_list = this.setChildListData(this.list_c, item, 'children', ts);
  730. this.list_c = [...new_list];
  731. },
  732. //清空所有选择。
  733. clearChecked() {
  734. let ps = uni.$tm.deepClone(this.list_c);
  735. for (let i = 0; i < ps.length; i++) {
  736. ps[i].checked = false;
  737. ps[i].dirType = 1;
  738. let new_list = this.setChildListData(this.list_c, ps[i], 'checked', ps[i].checked);
  739. this.list_c = [...new_list];
  740. this.setDirListDataBySync(ps[i], 'checked', false);
  741. }
  742. },
  743. //选中所有选择。
  744. seletedAll() {
  745. let ps = uni.$tm.deepClone(this.list_c);
  746. for (let i = 0; i < ps.length; i++) {
  747. ps[i].checked = true;
  748. let new_list = this.setChildListData(this.list_c, ps[i], 'checked', ps[i].checked);
  749. this.list_c = [...new_list];
  750. this.setDirListDataBySync(ps[i], 'checked', true);
  751. }
  752. this.$nextTick(function() {
  753. this.list_c = this.setDirListDataBySyncToDir(this.list_c, 'dirType', 2)
  754. })
  755. },
  756. //给定一个数组设置它下面所有dir目录(只设置目录,不含其子级)相同的属性。
  757. setDirListDataBySyncToDir(list, key, value) {
  758. let new_list = uni.$tm.deepClone(list);
  759. function ch(objAr) {
  760. let p = [];
  761. if (typeof objAr == 'object' && Array.isArray(objAr)&& objAr.length>0) {
  762. for (let i = 0; i < objAr.length; i++) {
  763. p.push(ch(objAr[i]));
  764. }
  765. return p;
  766. } else if (typeof objAr === 'object') {
  767. let children = objAr['children'];
  768. if (typeof children === 'object' && Array.isArray(children)&& children.length>0) {
  769. let xg = {};
  770. if(objAr!='checked'){
  771. if(objAr['disabled']!==true){
  772. xg[key] = value;
  773. }
  774. }else{
  775. xg[key] = value;
  776. }
  777. return {
  778. ...objAr,
  779. checked: objAr['checked'] || false,
  780. isDir: objAr['isDir'] || true,
  781. openDir: objAr['openDir'] || false,
  782. dirType: objAr['dirType'] || 1,
  783. children: ch(children),
  784. ...xg
  785. };
  786. } else {
  787. let xg = {};
  788. // xg[key] = value;
  789. return {
  790. ...objAr,
  791. isDir: objAr['isDir'] || false,
  792. checked: objAr['checked'] || false,
  793. ...xg
  794. };
  795. }
  796. }
  797. }
  798. for (let i = 0; i < new_list.length; i++) {
  799. let parar = new_list[i];
  800. parar[key] = value
  801. parar['children'] = ch(parar.children);
  802. }
  803. return new_list;
  804. },
  805. //给定一个数组设置它下面所有项目相同的属性。
  806. setDirListDataBySyncToItem(list, item, key, value) {
  807. let parar = uni.$tm.deepClone(item);
  808. function ch(objAr) {
  809. let p = [];
  810. if (typeof objAr == 'object' && Array.isArray(objAr)&& objAr.length>0) {
  811. for (let i = 0; i < objAr.length; i++) {
  812. p.push(ch(objAr[i]));
  813. }
  814. return p;
  815. } else if (typeof objAr === 'object') {
  816. let children = objAr['children'];
  817. if (typeof children === 'object' && Array.isArray(children)&& children.length>0) {
  818. let xg = {};
  819. if(objAr!='checked'){
  820. if(objAr['disabled']!==true){
  821. xg[key] = value;
  822. }
  823. }else{
  824. xg[key] = value;
  825. }
  826. return {
  827. ...objAr,
  828. checked: objAr['checked'] || false,
  829. isDir: objAr['isDir'] || true,
  830. openDir: objAr['openDir'] || false,
  831. dirType: objAr['dirType'] || 1,
  832. children: ch(children),
  833. ...xg
  834. };
  835. } else {
  836. let xg = {};
  837. if(objAr!='checked'){
  838. if(objAr['disabled']!==true){
  839. xg[key] = value;
  840. }
  841. }else{
  842. xg[key] = value;
  843. }
  844. return {
  845. ...objAr,
  846. isDir: objAr['isDir'] || false,
  847. checked: objAr['checked'] || false,
  848. ...xg
  849. };
  850. }
  851. }
  852. }
  853. let ts = ch(parar.children);
  854. let new_list = this.setChildListData(list, item, 'children', ts);
  855. return new_list;
  856. },
  857. //检查选择情况。
  858. checkAllChildren(o_item) {
  859. let t = this;
  860. // 检查各个子集的选择情况。
  861. // this.changePrarent(children)
  862. // 再反递归,修改它的上一级,一直类推到第一级。
  863. let otem = uni.$tm.deepClone(o_item);
  864. let ls = [];
  865. for (let j = 0; j < otem.length; j++) {
  866. let pr = otem[j];
  867. if (pr['isDir']) {
  868. let prenatKeyArray = t.getChildrenKeyToArray(pr, 'checked');
  869. let isAllChecked = true; //是否全部选中。
  870. let isAllChecked_min = true; //是否半选中。
  871. let isAllCheckedAr_all_true = prenatKeyArray.filter((el, eindex) => {
  872. return el == true;
  873. })
  874. let isAllCheckedAr_all_false = prenatKeyArray.filter((el, eindex) => {
  875. return el == false;
  876. })
  877. isAllChecked = isAllCheckedAr_all_true.length === prenatKeyArray.length ? true : false;
  878. isAllChecked_min = isAllCheckedAr_all_true.length > 0 && isAllCheckedAr_all_false.length > 0 ?
  879. true : false;
  880. pr['children'] = t.checkAllChildren(pr['children']);
  881. if (isAllChecked) {
  882. pr['dirType'] = 2;
  883. }
  884. if (isAllChecked_min) {
  885. pr['dirType'] = 3;
  886. }
  887. if (isAllCheckedAr_all_true.length == 0) {
  888. pr['dirType'] = 1;
  889. }
  890. isAllChecked = isAllChecked_min || isAllChecked ? true : false;
  891. pr['checked'] = isAllChecked;
  892. }
  893. ls.push(pr)
  894. }
  895. return ls;
  896. },
  897. setDefaultSelectedKey(defaultValue) {
  898. let t = this;
  899. if (!defaultValue) {
  900. defaultValue = this.defalutValue;
  901. }
  902. let rulst = defaultValue;
  903. if (this.prarent == null) {
  904. //清空所有选择。
  905. // this.clearChecked();
  906. let ps = uni.$tm.deepClone(this.list_c);
  907. for (let i = 0; i < rulst.length; i++) {
  908. let children = this.getChildren(ps, 'id', rulst[i]);
  909. children['checked'] = true;
  910. if (children['isDir']) {
  911. let index = ps.findIndex(ix => ix.id === children.id);
  912. // this.list_c.splice(index, 1, children);
  913. // this.changeCheckboxGroupItem(children)
  914. ps = this.setDirListDataBySyncToItem(ps, children, 'checked', children.checked);
  915. } else {
  916. ps = this.setChildListData(ps, children, 'checked', children.checked);
  917. }
  918. }
  919. let pc = [];
  920. ps = this.checkAllChildren(ps);
  921. this.$nextTick(function() {
  922. this.list_c = ps;
  923. });
  924. }
  925. }
  926. }
  927. };
  928. </script>
  929. <style lang="scss"></style>