QuestionFolderDialog.vue 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <template>
  2. <el-dialog
  3. custom-class="side-dialog"
  4. :visible.sync="modalIsShow"
  5. :title="title"
  6. width="600px"
  7. :modal="false"
  8. :close-on-click-modal="false"
  9. :close-on-press-escape="false"
  10. append-to-body
  11. @open="visibleChange"
  12. >
  13. <el-tree
  14. class="folder-tree"
  15. :data="folderTree"
  16. node-key="id"
  17. default-expand-all
  18. :expand-on-click-node="false"
  19. :props="defaultProps"
  20. @node-click="nodeClick"
  21. >
  22. <span slot-scope="{ node, data }">
  23. <i class="icon icon-files-act node-icon"></i>
  24. <span v-if="data.id === 'none'" class="node-form">
  25. <el-form
  26. ref="modalFormComp"
  27. :model="modalForm"
  28. :rules="rules"
  29. size="mini"
  30. :show-message="false"
  31. inline
  32. >
  33. <el-form-item prop="name">
  34. <el-input
  35. v-model="modalForm.name"
  36. placeholder="请输入文件夹名称"
  37. clearable
  38. ></el-input>
  39. </el-form-item>
  40. <el-form-item>
  41. <el-button
  42. type="primary"
  43. icon="el-icon-check"
  44. @click="toCreateFolder"
  45. ></el-button>
  46. <el-button
  47. type="danger"
  48. icon="el-icon-close"
  49. @click="toRemoveFolder(node, data)"
  50. ></el-button>
  51. </el-form-item>
  52. </el-form>
  53. </span>
  54. <span
  55. v-else
  56. :class="['node-cont', { 'is-active': curNodeData.id === data.id }]"
  57. >{{ node.label }}</span
  58. >
  59. </span>
  60. </el-tree>
  61. <div slot="footer" class="box-justify">
  62. <el-button
  63. v-if="isEdit"
  64. type="primary"
  65. :disabled="curNodeData.level >= MAX_FOLDER_LEVEL"
  66. @click="toAddFolder"
  67. >新建文件夹</el-button
  68. >
  69. <div>
  70. <el-button v-if="!isEdit" type="primary" @click="confirm"
  71. >确定</el-button
  72. >
  73. <el-button @click="cancel">取消</el-button>
  74. </div>
  75. </div>
  76. </el-dialog>
  77. </template>
  78. <script>
  79. export default {
  80. name: "QuestionFolderDialog",
  81. props: {
  82. folderId: {
  83. type: [String, Number],
  84. default: "",
  85. },
  86. isEdit: {
  87. type: Boolean,
  88. default: true,
  89. },
  90. },
  91. data() {
  92. return {
  93. modalIsShow: false,
  94. MAX_FOLDER_LEVEL: 3,
  95. folderTree: [
  96. {
  97. id: "1",
  98. parent: null,
  99. name: "根目录",
  100. children: [
  101. {
  102. id: "101",
  103. parent: "1",
  104. name: "2021-2022第一学期期末考试用",
  105. },
  106. {
  107. id: "102",
  108. parent: "1",
  109. name: "2021-2022第二学期期末考试用",
  110. },
  111. ],
  112. },
  113. ],
  114. defaultProps: {
  115. label: "name",
  116. },
  117. curNodeData: {},
  118. modalForm: {
  119. name: "",
  120. },
  121. rules: {
  122. name: [
  123. {
  124. required: true,
  125. message: "请输入文件夹名称",
  126. trigger: "change",
  127. },
  128. ],
  129. },
  130. };
  131. },
  132. computed: {
  133. title() {
  134. return this.isEdit ? "新建文件夹" : "选择文件夹";
  135. },
  136. },
  137. methods: {
  138. visibleChange() {
  139. if (this.folderId && !this.isEdit) {
  140. this.curNodeData = this.findNodeById(this.folderId);
  141. }
  142. },
  143. cancel() {
  144. this.modalIsShow = false;
  145. },
  146. open() {
  147. this.modalIsShow = true;
  148. },
  149. nodeClick(data) {
  150. if (data.id === "none" || data.id === this.curNodeData.id) return;
  151. this.clearPreNewNode();
  152. this.$nextTick(() => {
  153. this.curNodeData = this.findNodeById(data.id);
  154. });
  155. },
  156. findNodeById(id) {
  157. let curNode = null;
  158. const findNode = (data, level) => {
  159. if (curNode) return;
  160. level++;
  161. data.forEach((item) => {
  162. if (curNode) return;
  163. if (item.id === id) {
  164. curNode = item;
  165. curNode.level = level;
  166. return;
  167. }
  168. if (item.children && item.children.length)
  169. findNode(item.children, level);
  170. });
  171. };
  172. findNode(this.folderTree, 0);
  173. return curNode || {};
  174. },
  175. clearPreNewNode() {
  176. const removePreNewChild = (data) => {
  177. data = data.filter((item) => item.id !== "none");
  178. return data.map((item) => {
  179. if (item.children && item.children.length)
  180. item.children = removePreNewChild(item.children);
  181. return item;
  182. });
  183. };
  184. this.folderTree = removePreNewChild(this.folderTree);
  185. },
  186. toAddFolder() {
  187. if (!this.curNodeData.id) {
  188. this.$message.error("请先选择文件夹!");
  189. return;
  190. }
  191. if (this.curNodeData.level >= this.MAX_FOLDER_LEVEL) {
  192. this.$message.error(`最多允许${this.MAX_FOLDER_LEVEL}级目录`);
  193. return;
  194. }
  195. if (
  196. this.curNodeData.children &&
  197. this.curNodeData.children.find((item) => item.id === "none")
  198. ) {
  199. this.$message.closeAll();
  200. this.$message.error("有未创建完成的目录!");
  201. return;
  202. }
  203. const newChild = { id: "none", name: "", parentId: this.curNodeData.id };
  204. if (!this.curNodeData.children) {
  205. this.$set(this.curNodeData, "children", []);
  206. }
  207. this.curNodeData.children.push(newChild);
  208. this.modalForm = { name: "" };
  209. },
  210. async toCreateFolder() {
  211. const valid = await this.$refs.modalFormComp.validate().catch(() => {});
  212. if (!valid) return;
  213. },
  214. toRemoveFolder(node, data) {
  215. const parent = node.parent;
  216. const children = parent.data.children || parent.data;
  217. const index = children.findIndex((d) => d.id === data.id);
  218. children.splice(index, 1);
  219. },
  220. confirm() {
  221. if (!this.curNodeData.id) {
  222. this.$message.error("请选择文件夹!");
  223. return;
  224. }
  225. this.$emit("selected", this.curNodeData);
  226. },
  227. },
  228. };
  229. </script>