child-node.tsx 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import { defineComponent } from 'vue';
  2. import styles from './index.module.less';
  3. import { Cell, Collapse, CollapseItem } from 'vant';
  4. import iconNoCheck from './image/icon-nocheck.png';
  5. import iconImm from './image/icon-imm.png';
  6. import iconCheck from './image/icon-check.png';
  7. import iconCheckDisabled from './image/icon-check-disabled.png';
  8. export const onMenuChange = (item: any, status?: string) => {
  9. if (item.status === 'disabled') {
  10. return;
  11. }
  12. // 判断父级元素
  13. if (status) {
  14. item.status = status;
  15. } else {
  16. if (item.status === 'disabled') {
  17. return;
  18. }
  19. if (item.status === 'checked') {
  20. item.status = 'nochecked';
  21. } else {
  22. item.status = 'checked';
  23. }
  24. }
  25. if (Array.isArray(item.materialList)) {
  26. // console.log(item.status, 'item.status', status);
  27. item.materialList.forEach((material: any) => {
  28. if (material.status === 'disabled') {
  29. return;
  30. }
  31. if (item.status === 'nochecked') {
  32. material.status = 'nochecked';
  33. } else {
  34. material.status = 'checked';
  35. }
  36. });
  37. }
  38. if (Array.isArray(item.children)) {
  39. item.children.forEach((child: any) => {
  40. onMenuChange(child, item.status);
  41. });
  42. }
  43. };
  44. export const onParentChangeStatus = (parent: any, childName = 'children') => {
  45. let arrLength = 0;
  46. let checkedLength = 0;
  47. let indeterminateLength = 0;
  48. if (parent.materialList && parent.materialList.length > 0) {
  49. parent.materialList.forEach((item: any) => {
  50. if (item.status !== 'disabled') {
  51. arrLength += 1;
  52. }
  53. if (item.status === 'checked') {
  54. checkedLength += 1;
  55. }
  56. });
  57. }
  58. if (Array.isArray(parent[childName])) {
  59. parent[childName].forEach((item: any) => {
  60. if (item.status !== 'disabled') {
  61. arrLength += 1;
  62. }
  63. if (item.status === 'checked') {
  64. checkedLength += 1;
  65. }
  66. if (item.status === 'indeterminate') {
  67. indeterminateLength += 1;
  68. }
  69. });
  70. }
  71. if (checkedLength >= arrLength) {
  72. parent.status = 'checked';
  73. } else if (checkedLength > 0) {
  74. parent.status = 'indeterminate';
  75. } else {
  76. parent.status = 'nochecked';
  77. }
  78. // 只能目录才会大于0,素材是不会有
  79. if (indeterminateLength > 0) {
  80. parent.status = 'indeterminate';
  81. }
  82. };
  83. const ChildNode = defineComponent({
  84. name: 'child-node',
  85. props: {
  86. list: {
  87. type: Array,
  88. default: () => []
  89. },
  90. collapse: {
  91. type: String,
  92. default: ''
  93. }
  94. },
  95. emits: ['update:collapse', 'menuChange', 'materialChange'],
  96. setup(props, { emit }) {
  97. return () => (
  98. <Collapse
  99. modelValue={props.collapse}
  100. onUpdate:modelValue={(val: any) => {
  101. emit('update:collapse', val);
  102. }}
  103. border={false}
  104. accordion>
  105. {props.list?.map((point: any) => (
  106. <CollapseItem
  107. clickable={false}
  108. center
  109. class={styles.collapseChild}
  110. name={point.id}>
  111. {{
  112. title: () => (
  113. <div
  114. class={[
  115. styles.itemTitle,
  116. props.collapse === point.id ? styles.itemTitleActive : ''
  117. ]}>
  118. <i class={[styles.arrow]}></i>
  119. {point.name}
  120. </div>
  121. ),
  122. default: () => (
  123. <>
  124. {Array.isArray(point?.materialList) &&
  125. point.materialList.map((n: any) => (
  126. <Cell>
  127. {{
  128. title: () => n.name,
  129. value: () => (
  130. <img
  131. src={
  132. n.status === 'disabled'
  133. ? iconCheckDisabled
  134. : n.status === 'checked'
  135. ? iconCheck
  136. : iconNoCheck
  137. }
  138. class={[styles.radioBtn]}
  139. onClick={(e: any) => {
  140. e.stopPropagation();
  141. if (n.status === 'disabled') {
  142. return;
  143. }
  144. if (n.status === 'checked') {
  145. n.status = 'nochecked';
  146. } else {
  147. n.status = 'checked';
  148. }
  149. onParentChangeStatus(point);
  150. emit('menuChange');
  151. }}
  152. />
  153. )
  154. }}
  155. </Cell>
  156. ))}
  157. {Array.isArray(point?.children) && (
  158. <ChildNode
  159. list={point.children}
  160. collapse={point.collapse}
  161. onUpdate:collapse={val => {
  162. point.collapse = val;
  163. }}
  164. onMenuChange={() => {
  165. onParentChangeStatus(point);
  166. emit('menuChange');
  167. }}
  168. />
  169. )}
  170. </>
  171. ),
  172. 'right-icon': () => (
  173. <img
  174. src={
  175. point.status === 'indeterminate'
  176. ? iconImm
  177. : point.status === 'disabled'
  178. ? iconCheckDisabled
  179. : point.status === 'checked'
  180. ? iconCheck
  181. : iconNoCheck
  182. }
  183. class={[styles.radioBtn]}
  184. onClick={(e: any) => {
  185. e.stopPropagation();
  186. onMenuChange(point);
  187. emit('menuChange');
  188. }}
  189. />
  190. )
  191. }}
  192. </CollapseItem>
  193. ))}
  194. </Collapse>
  195. );
  196. }
  197. });
  198. export default ChildNode;