recursive.vue 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. <!-- 已废弃 -->
  2. <template>
  3. <div v-for="(list, levelIndex) in treeList" :key="`select${levelIndex}`">
  4. <div v-if="levelIndex < props.defaultOpen">
  5. <span v-for="(item, itemIndex) in list" :key="item.id">
  6. <span
  7. v-if="itemIndex + 1 <= num"
  8. class="mx-3"
  9. :class="{'act': calcAct(item.id, levelIndex)}"
  10. style="line-height: 32px;"
  11. @click="handleNext(item, levelIndex)"
  12. >{{ item.name }}</span>
  13. </span>
  14. <!-- 其他 -->
  15. <span v-if="list?.length > num" class="mx-3" style="line-height: 32px;">其他</span>
  16. </div>
  17. <div v-else class="embedded">
  18. <span
  19. v-for="item in list" :key="item.id"
  20. class="mx-3"
  21. :class="{'act': calcAct(item.id, levelIndex)}"
  22. style="line-height: 32px;"
  23. @click="handleNext(item, levelIndex)"
  24. >{{ item.name }}</span>
  25. </div>
  26. </div>
  27. <!-- <div>
  28. <div v-for="(item, index) in treeList" :key="`select${index}`">
  29. <div :class="{'embedded': index + 1 > props.defaultOpen }">
  30. <template v-for="(val, listIndex) in item" :key="`val${listIndex}`">
  31. <span v-if="listIndex < num" class="mx-3" style="line-height: 32px;" @click="handleNext(val, index)">{{ val.name }}</span>
  32. </template>
  33. </div>
  34. <span v-for="(item, index) in props.items" :key="item.id">
  35. <span v-if="index < num" class="mx-3" :class="{'act': calcAct(item)}" style="line-height: 32px;" @click="handleClick(item, index)">{{ item.name }}</span>
  36. </span>
  37. <template v-if="underAndEqual">
  38. <span v-if="props.items?.length >= num" @click="handleClick(props.items, 'other')">其他</span>
  39. </template>
  40. </div>
  41. <template v-if="children?.length">
  42. <v-divider v-if="outweigh" class="mx-2"></v-divider>
  43. <recursive ref="childRef" :defaultOpen="props.defaultOpen" :items="children" :parentId="itemId" v-model="modelValueDeep"></recursive>
  44. </template>
  45. </div> -->
  46. </template>
  47. <script setup>
  48. import { reactive, ref } from 'vue'
  49. // import recursive from './recursive'
  50. // import { useRoute, useRouter } from 'vue-router'
  51. defineOptions({ name:'common-components-areaTree-recursive'})
  52. const emits = defineEmits('input')
  53. // const route = useRoute(); const router = useRouter()
  54. // const checked = reactive({})
  55. // console.log('to:/recruit/position-> query', route.query)
  56. // if (Object.keys(route.query).length) {
  57. // Object.keys(route.query).forEach(_e => {
  58. // checked[_e]
  59. // })
  60. // }
  61. const num = 10
  62. // const childRef = ref(null)
  63. const props = defineProps({
  64. items: Object,
  65. defaultOpen: {
  66. type: Number,
  67. default: 3
  68. },
  69. parentId: {
  70. type: [Number, String],
  71. default: -1
  72. }
  73. })
  74. const idChecked = reactive([])
  75. const getIdChecked = (item, levelIndex) => {
  76. if (!idChecked[levelIndex]) idChecked[levelIndex] = [] // 不存在初始化为空
  77. if (levelIndex < props.defaultOpen) {
  78. idChecked[levelIndex] = [ item.id ]
  79. } else {
  80. const findIndex = idChecked[levelIndex]?.length ? idChecked[levelIndex].findIndex(j => j === item.id) : -1
  81. if (findIndex !== -1) {
  82. idChecked[levelIndex].splice(findIndex, 1) // 删除
  83. } else {
  84. idChecked[levelIndex].push(item.id) // 添加
  85. }
  86. }
  87. // console.log('idChecked', idChecked)
  88. }
  89. const treeList = ref([
  90. [...props.items]
  91. ])
  92. const handleNext = (item, index, stopExpand) => { // stopExpand:不展开下级
  93. getIdChecked(item, index)
  94. if (!stopExpand &&item.children && item.children.length) {
  95. treeList.value[index + 1] = item.children
  96. treeList.value.splice(index + 2, treeList.value.length)
  97. } else {
  98. treeList.value.splice(index + 1, treeList.value.length)
  99. }
  100. }
  101. if (props.defaultOpen > 0) {
  102. for (let index = 0; index < props.defaultOpen; index++) {
  103. if (treeList.value?.length && treeList.value[index]?.length && treeList.value[index][0]) {
  104. const stopExpand = (index + 1) === props.defaultOpen
  105. handleNext(treeList.value[index][0], index, stopExpand)
  106. }
  107. }
  108. emits('input', idChecked)
  109. }
  110. const calcAct = (id, levelIndex) => {
  111. if (!id) return false
  112. if (Array.isArray(idChecked) && Array.isArray(idChecked[levelIndex])) {
  113. const index = idChecked[levelIndex].findIndex(itemToCheck => itemToCheck=== id)
  114. return index !== -1 ? true : false; // 如果找到返回索引,否则返回 false
  115. }
  116. else return false
  117. }
  118. // const modelValueDeep = ref([])
  119. // let itemId = ref(0)
  120. // let currentRowType = ref(0)
  121. // let actIndex = ref(0)
  122. // let currentRow = reactive({ id: -1})
  123. // let children = ref([])
  124. // const rowExtend = (item) => {
  125. // if (item) {
  126. // currentRow = item
  127. // itemId.value = currentRow.id || 0
  128. // currentRowType.value = currentRow.type || 0
  129. // } else {
  130. // currentRow = { id: -1 }
  131. // itemId.value = -1
  132. // currentRowType.value = 0
  133. // }
  134. // }
  135. // // 选中回显
  136. // const checkedFun = (item) => {
  137. // const key = 'type' + item.type
  138. // let typeChecked = checked[key] || (checked[key] = []) // 不存在初始化为空
  139. // if (item.type <= props.defaultOpen) {
  140. // typeChecked.length = 0 // 清空数组
  141. // typeChecked.push({ id: item.id, name: item.name })
  142. // } else {
  143. // // 多选
  144. // const index = typeChecked.findIndex(itemToCheck => itemToCheck.id === item.id)
  145. // if (index !== -1) {
  146. // typeChecked.splice(index, 1) // 删除
  147. // } else {
  148. // typeChecked.push({ id: item.id, name: item.name }) // 添加
  149. // }
  150. // }
  151. // }
  152. // const idChecked = ref([])
  153. // const getIdChecked = (item) => {
  154. // const { name, id } = item
  155. // // if (item.type <= props.defaultOpen) {
  156. // // idChecked.value = [{ name, id }]
  157. // // } else {
  158. // // const index = idChecked.value.findIndex(j => j.id === item.id)
  159. // // if (index !== -1) {
  160. // // idChecked.value.splice(index, 1) // 删除
  161. // // } else {
  162. // // idChecked.value.push({ name, id }) // 添加
  163. // // }
  164. // // }
  165. // // 提交已选中的给areaCascader-index组件
  166. // // const params = { [`type${item.type}`]: idChecked.value }
  167. // emits('update:modelValue', [...props.modelValue, {name, id}])
  168. // // console.log('params', props.value)
  169. // }
  170. // const init = () => {
  171. // if (props.items?.length) {
  172. // const item = props.items[0]
  173. // // 设置激活样式
  174. // actIndex.value = 0
  175. // if (item.type - 0 <= props.defaultOpen) getIdChecked(item)
  176. // // 显示子级数据
  177. // if (item.type - 0 < props.defaultOpen) {
  178. // children.value = item.children
  179. // } else {
  180. // children.value = []
  181. // }
  182. // rowExtend(item)
  183. // } else {
  184. // rowExtend(null)
  185. // }
  186. // }
  187. // 监听
  188. // watch(
  189. // () => props.parentId,
  190. // () => {
  191. // // 函数
  192. // init()
  193. // },
  194. // { immediate: true },
  195. // { deep: true }
  196. // )
  197. // watch(
  198. // () => props.modelValue,
  199. // (val) => {
  200. // console.log('val', val)
  201. // },
  202. // { immediate: true },
  203. // { deep: true }
  204. // )
  205. // 点击事件
  206. // const handleClick = (item) => {
  207. // // console.log(item, index)
  208. // const { name, id } = item
  209. // emits('update:modelValue', [...props.modelValue, { name, id }])
  210. // // if (index === 'other') return
  211. // // else {
  212. // // actIndex.value = index
  213. // // if (item.children?.length) {
  214. // // if (item.type - 0 > props.defaultOpen - 1) { // 下一级是多选的情况下(props.defaultOpen的上一级)
  215. // // const i = { id: 0, name: '不限', type: currentRowType.value + 1, parentId: item.parentId, children: [] }
  216. // // children.value = [i, ...item.children]
  217. // // }
  218. // // else children.value = item.children
  219. // // } else children.value = []
  220. // // rowExtend(item) // 相关属性
  221. // // getIdChecked(item) // 加入checked
  222. // // // const key = `type${currentRowType.value}`
  223. // // // const query = { [`type${currentRowType.value}`]: idChecked.value.join('_') }
  224. // // // router.push({ path: route.path, query })
  225. // // }
  226. // }
  227. // // 设置激活样式
  228. // const calcActFun = (item) => {
  229. // // 首先确保 item 有 id 属性
  230. // if (!item?.id) {
  231. // return false
  232. // }
  233. // // 计算 key
  234. // const key = 'type' + item.type
  235. // // 尝试从 checked 对象中获取对应的数组
  236. // const typeChecked = checked[key]
  237. // // 如果 typeChecked 存在并且是一个数组,则查找索引
  238. // if (Array.isArray(typeChecked)) {
  239. // const index = typeChecked.findIndex(itemToCheck => itemToCheck.id === item.id)
  240. // return index !== -1 ? true : false; // 如果找到返回索引,否则返回 false
  241. // }
  242. // // 如果 typeChecked 不存在或不是一个数组,返回 false
  243. // return false
  244. // }
  245. // 设置激活样式
  246. // const calcAct = (item) => {
  247. // // 首先确保 item 有 id 属性
  248. // if (!item?.id) {
  249. // return false
  250. // }
  251. // if (Array.isArray(idChecked.value)) {
  252. // const index = idChecked.value.findIndex(itemToCheck => itemToCheck.id=== item.id)
  253. // return index !== -1 ? true : false; // 如果找到返回索引,否则返回 false
  254. // }
  255. // }
  256. // const outweigh = computed(() => (currentRowType.value > props.defaultOpen))
  257. // const underAndEqual = computed(() => (currentRowType.value <= props.defaultOpen))
  258. </script>
  259. <style lang="scss" scoped>
  260. .text666 {
  261. // color: #666666;
  262. border-right: 1px solid #666666;
  263. }
  264. .text333 {
  265. color: #333333;
  266. }
  267. .act {
  268. color: var(--v-primary-base);
  269. }
  270. span {
  271. span { cursor: pointer; }
  272. cursor: pointer;
  273. &:hover {
  274. color: var(--v-primary-lighten2);
  275. }
  276. }
  277. .embedded {
  278. padding: 4px;
  279. background-color: #f8f8f8;
  280. border-radius: 5px;
  281. }
  282. </style>