LeftList.vue 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <template>
  2. <div>
  3. <el-tree
  4. class="treebox"
  5. :data="treeData"
  6. :props="defaultProps"
  7. :accordion="false"
  8. ref="folderTreeRef"
  9. :highlight-current="true"
  10. :current-node-key="curNode"
  11. :filter-node-method="filterNode"
  12. node-key="id"
  13. :default-expand-all="false"
  14. :default-expanded-keys="curArr"
  15. >
  16. <template #default="{ node, data }">
  17. <span
  18. class="custom-tree-node row-context"
  19. :class="{ alive: data.id == collectDir }"
  20. @click="checkoutNode(node, data)"
  21. @click.right="rightFn(node, data, $event)"
  22. >
  23. <img :src="setImg(data.remark)" alt="" />
  24. <span class="node_title">{{ node.label }}</span>
  25. <span class="fileNum">{{
  26. data.remark.fileNum > 99 ? "99+" : data.remark.fileNum
  27. }}</span>
  28. </span>
  29. </template>
  30. </el-tree>
  31. </div>
  32. </template>
  33. <script setup>
  34. import {
  35. ref,
  36. computed,
  37. reactive,
  38. defineComponent,
  39. watch,
  40. toRaw,
  41. onMounted,
  42. defineExpose,
  43. onDeactivated,
  44. onBeforeMount,
  45. } from "vue";
  46. import { ElMessage } from "element-plus";
  47. import documents from "@/api/document/document";
  48. import { getDir } from "@/api/biz/dir.js";
  49. import { setListImg } from "@/utils/index.js";
  50. const { proxy } = getCurrentInstance();
  51. const props = defineProps({
  52. spaceType: {
  53. type: Number,
  54. default: 0,
  55. },
  56. ListtreeData: {
  57. type: Array,
  58. default: () => [],
  59. },
  60. searchFolderTree: {
  61. type: String,
  62. default: "",
  63. },
  64. collectId: {
  65. type: Number,
  66. default: 0,
  67. },
  68. });
  69. const emit = defineEmits(["listfolderClick", "treeRClick"]);
  70. const treeData = ref();
  71. console.log("treeData", treeData.value);
  72. const curArr = ref([]); //默认展开一级目录
  73. const folderTreeRef = ref();
  74. const curNode = ref();
  75. const topId = ref(); //顶层的id
  76. const collectDir = ref();
  77. const defaultProps = ref({
  78. label: "label",
  79. value: "id",
  80. remark: "remark",
  81. disable: false,
  82. });
  83. //获取文件树
  84. function getFileTree() {
  85. documents.fileTree(props.spaceType).then((res) => {
  86. res.disabled = true;
  87. treeData.value = [res];
  88. function getAllNodeIds(nodes) {
  89. nodes.forEach((node) => {
  90. if (node.remark) {
  91. node.remark = JSON.parse(node.remark);
  92. }
  93. if (node.children && node.children.length > 0) {
  94. getAllNodeIds(node.children);
  95. }
  96. });
  97. return nodes;
  98. }
  99. // 调用递归函数获取所有节点的 id
  100. getAllNodeIds(treeData.value);
  101. // console.log("treedataarr", arr);
  102. // console.log("treeData", treeData.value);
  103. });
  104. }
  105. const checkoutNode = async (node, data) => {
  106. // console.log("treeData", treeData.value);
  107. // console.log("node", node);
  108. collectDir.value = null;
  109. curNode.value = node.data.id;
  110. // console.log("curNode.value", curNode.value);
  111. // console.log("data", data);
  112. let thisNode;
  113. function getLevel2(nodes) {
  114. if (nodes?.level === 2) {
  115. // console.log(2);
  116. // console.log("nodes", nodes);
  117. thisNode = toRaw(nodes);
  118. } else {
  119. if (!nodes.parent) {
  120. return;
  121. }
  122. // console.log("level", nodes.level);
  123. getLevel2(nodes.parent);
  124. }
  125. }
  126. getLevel2(node);
  127. // console.log("thisNode", thisNode);
  128. // console.log("node", node);
  129. const res = await getDir(data.id);
  130. let resThis;
  131. if (thisNode) {
  132. resThis = await getDir(thisNode.data.id);
  133. }
  134. emit("listfolderClick", res.data, resThis?.data);
  135. // console.log("res", res);
  136. // console.log("resThis", resThis);
  137. };
  138. const setImg = (remark) => {
  139. return setListImg(remark);
  140. };
  141. const getTopDir = async () => {
  142. curArr.value = [];
  143. const res = await documents.getTop(props.spaceType);
  144. // console.log("topres", res);
  145. curArr.value.push(res.dirId);
  146. curArr.value.push(props.collectId);
  147. console.log("curArr", curArr.value);
  148. topId.value = res.dirId;
  149. return;
  150. };
  151. const rightFn = async (node, data, e) => {
  152. // console.log("node", node);
  153. // console.log("data", data);
  154. // console.log("e", e);
  155. //如果是二级及以后(node.level >= 3)的节点 需要判断父级是不是组织目录来确定是否显示编辑
  156. if (node.level === 1) return;
  157. if (node.level == 2) {
  158. const res = await getDir(data.id);
  159. emit("treeRClick", res.data, null, e);
  160. } else {
  161. const res = await getDir(data.id);
  162. const fRes = await getDir(node.parent.data.id);
  163. if (fRes.data.dirType == "2") {
  164. // 父级是组织 不可以编辑
  165. emit("treeRClick", res.data, null, e);
  166. } else {
  167. emit("treeRClick", res.data, null, e);
  168. }
  169. // console.log("fRes", fRes);
  170. }
  171. };
  172. /** 通过条件过滤节点 */
  173. const filterNode = (value, data) => {
  174. if (!value) return true;
  175. return data.label.indexOf(value) !== -1;
  176. };
  177. watch(
  178. () => props.ListtreeData,
  179. (newValue, oldValue) => {
  180. treeData.value = newValue;
  181. // 记录当前展开的节点
  182. let nodesMap = folderTreeRef.value?.store.nodesMap;
  183. // console.log("nodesMap", nodesMap);
  184. // console.log("curNode.value", curNode.value);
  185. let expandedNodes = [];
  186. if (nodesMap) {
  187. expandedNodes = Object.keys(nodesMap).filter(
  188. (key) => nodesMap[key].expanded
  189. );
  190. } else {
  191. expandedNodes.push(topId.value);
  192. }
  193. // console.log("expandedNodes", expandedNodes);
  194. // 把这当从服务器拉取数据
  195. treeData.value = JSON.parse(JSON.stringify(newValue));
  196. // 更新数据后, 有过滤条件的执行过滤, 没有的还原之前的展开状态
  197. setTimeout(() => {
  198. if (props.searchFolderTree !== "") {
  199. folderTreeRef.value?.filter(props.searchFolderTree);
  200. } else {
  201. expandedNodes.forEach((key) => (nodesMap[key].expanded = true));
  202. }
  203. folderTreeRef.value?.setCurrentKey(curNode.value);
  204. }, 0);
  205. },
  206. {
  207. immediate: true,
  208. deep: true,
  209. }
  210. );
  211. /** 根据名称筛选部门树 */
  212. watch(
  213. () => props.searchFolderTree,
  214. (newValue, oldValue) => {
  215. // console.log("watch", newValue);
  216. folderTreeRef.value?.filter(newValue);
  217. // proxy.$refs["folderTreeRef"].filter(newValue);
  218. },
  219. {
  220. immediate: true,
  221. deep: true,
  222. }
  223. );
  224. watch(
  225. () => props.collectId,
  226. (newValue, oldValue) => {
  227. // console.log("watch", newValue);
  228. collectDir.value = newValue;
  229. curArr.value.push(newValue);
  230. // proxy.$refs["folderTreeRef"].filter(newValue);
  231. },
  232. {
  233. immediate: true,
  234. deep: true,
  235. }
  236. );
  237. onMounted(() => {
  238. getTopDir();
  239. // collectDir.value = props.collectId;
  240. // getFileTree();
  241. });
  242. </script>
  243. <style lang="scss" scoped>
  244. .treebox {
  245. width: 100%;
  246. overflow-y: auto;
  247. position: relative;
  248. }
  249. // .row-context {
  250. // background: #f4f9ff;
  251. // width: auto;
  252. // border: 1px solid #4a97eb;
  253. // padding: 5px 5px 5px 0;
  254. // }
  255. .custom-tree-node {
  256. width: 100%;
  257. height: 36px;
  258. display: flex;
  259. align-items: center;
  260. padding: 16px 0;
  261. img {
  262. width: 26px;
  263. height: 26px;
  264. object-fit: cover;
  265. }
  266. .node_title {
  267. font-size: 14px;
  268. line-height: 22px;
  269. margin-left: 5px;
  270. max-width: 150px;
  271. /*第一步: 溢出隐藏 */
  272. overflow: hidden;
  273. /* 第二步:让文本不会换行, 在同一行继续 */
  274. white-space: nowrap;
  275. /* 第三步:用省略号来代表未显示完的文本 */
  276. text-overflow: ellipsis;
  277. font-family: Inter-Medium;
  278. }
  279. .fileNum {
  280. position: absolute;
  281. right: 10%;
  282. font-size: 14px;
  283. line-height: 22px;
  284. font-weight: 500;
  285. color: #06286c;
  286. }
  287. }
  288. .alive {
  289. background-color: #f5f7f9;
  290. }
  291. :deep(.el-tree-node__content) {
  292. height: 36px;
  293. }
  294. // 箭头
  295. :deep(.el-tree .el-icon svg) {
  296. //原有的箭头 去掉
  297. display: none !important;
  298. height: 0;
  299. width: 0;
  300. }
  301. :deep(.el-tree-node__expand-icon) {
  302. //引入的图标(图片)size大小 => 树节点前的预留空间大小
  303. font-size: 16px;
  304. }
  305. //图标是否旋转,如果是箭头类型的,可以设置旋转90度。如果是两张图片,则设为0
  306. :deep(.el-tree .el-tree-node__expand-icon.expanded) {
  307. -webkit-transform: rotate(0deg);
  308. transform: rotate(0deg);
  309. }
  310. :deep(.el-tree .el-tree-node__expand-icon:before) {
  311. // 未展开的节点
  312. background: url("@/assets/images/listShow/arrow_right.png") no-repeat 0 1px !important;
  313. content: "";
  314. display: block;
  315. width: 18px;
  316. height: 18px;
  317. }
  318. :deep(.el-tree .el-tree-node__expand-icon.expanded:before) {
  319. //展开的节点
  320. background: url("@/assets/images/listShow/row_btm.png") no-repeat 0 0 !important;
  321. content: "";
  322. display: block;
  323. width: 18px;
  324. height: 18px;
  325. margin-top: 4px;
  326. }
  327. :deep(.el-tree .is-leaf.el-tree-node__expand-icon::before) {
  328. //叶子节点(不显示图标)
  329. display: block;
  330. background: none !important;
  331. content: "";
  332. width: 18px;
  333. height: 18px;
  334. }
  335. :deep(.el-tree-node) {
  336. min-width: 100% !important;
  337. width: fit-content !important;
  338. }
  339. </style>