catalog.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. <template>
  2. <div class="container">
  3. <div class="main-box container-box">
  4. <div class="inner-left" style="overflow: hidden">
  5. <div class="button-list">
  6. <el-button type="primary" @click="firstMenu" plain
  7. >添加一级目录</el-button
  8. >
  9. <el-button type="primary" @click="addMenu" plain
  10. >添加子目录</el-button
  11. >
  12. <el-button type="primary" @click="delMenu" plain>删除</el-button>
  13. <el-dropdown
  14. @command="treeAction"
  15. trigger="click"
  16. style="margin-left: 15px"
  17. >
  18. <el-button type="primary" plain>
  19. 树操作<i class="el-icon-arrow-down el-icon--right"></i>
  20. </el-button>
  21. <el-dropdown-menu slot="dropdown">
  22. <el-dropdown-item :command="1">全部展开</el-dropdown-item>
  23. <el-dropdown-item :command="2">全部关闭</el-dropdown-item>
  24. </el-dropdown-menu>
  25. </el-dropdown>
  26. </div>
  27. <div class="choice-style">
  28. <div class="ant-alert-info ant-alert">
  29. <i style="color: #1890ff" class="el-icon-warning"></i>当前选择:{{
  30. actionName
  31. }}
  32. <span class="canel-style" @click="canelChoice" v-show="actionName"
  33. >取消选择</span
  34. >
  35. </div>
  36. </div>
  37. <div style="margin: 10px 0">
  38. <el-input
  39. placeholder="请输入内容"
  40. v-model="filterText"
  41. class="input-with-select"
  42. clearable
  43. @change="
  44. () => {
  45. if (!filterText) {
  46. searchMenu();
  47. }
  48. }
  49. "
  50. >
  51. <el-button
  52. slot="append"
  53. @click="searchMenu"
  54. icon="el-icon-search"
  55. ></el-button>
  56. </el-input>
  57. </div>
  58. <div
  59. v-loading="loading"
  60. style="height: calc(100% - 200px); overflow-y: scroll"
  61. >
  62. <el-tree
  63. ref="catalogTree"
  64. class="tree-line"
  65. :expand-on-click-node="true"
  66. :auto-expand-parent="true"
  67. :default-expand-all="true"
  68. :props="defaultProps"
  69. :data="menuList"
  70. @node-click="nodeClick"
  71. :filter-node-method="filterNode"
  72. node-key="id"
  73. >
  74. <span class="custom-tree-node" slot-scope="{ node }">
  75. <span>
  76. <span style="color: #009cff" class="iconfont icon-wenjianjia"></span>
  77. <!-- <span
  78. v-if="
  79. node.data.hasOwnProperty('children') &&
  80. node.data.children.length > 0
  81. "
  82. style="color: #009cff"
  83. class="iconfont icon-wenjianjia"
  84. ></span> -->
  85. <!-- <span
  86. v-else
  87. style="color: #fdb441"
  88. class="iconfont icon-wenjian"
  89. ></span> -->
  90. <span
  91. :style="
  92. node.data.hasOwnProperty('parent')
  93. ? 'font-size:14px;padding-left:5px'
  94. : 'font-size:12px;padding-left:5px'
  95. "
  96. >{{ node.data.title }}</span
  97. >
  98. </span>
  99. </span>
  100. </el-tree>
  101. </div>
  102. <div class="tree-action"></div>
  103. </div>
  104. <div class="inner-right">
  105. <div v-if="actionName">
  106. <div class="choice-style" style="width: 80%; margin: 15px auto">
  107. <div class="ant-alert-info ant-alert">
  108. <i style="color: #1890ff" class="el-icon-warning"></i>请编辑信息
  109. </div>
  110. </div>
  111. <el-form
  112. :model="formData"
  113. :rules="rules"
  114. ref="ruleForm"
  115. label-width="100px"
  116. class="demo-ruleForm"
  117. style="width: 80%; margin: 50px auto"
  118. >
  119. <el-form-item label="目录名称" prop="title">
  120. <el-input
  121. v-model="formData.title"
  122. placeholder="请输入标题"
  123. ></el-input>
  124. </el-form-item>
  125. <el-form-item
  126. prop="parentId"
  127. v-if="actionName != 'add'"
  128. label="父级编码"
  129. >
  130. <el-input
  131. disabled
  132. v-model="formData.parentId"
  133. placeholder="请输入父级编码"
  134. ></el-input>
  135. </el-form-item>
  136. <el-form-item
  137. label="父级名称"
  138. v-if="actionName != 'add'"
  139. prop="parentName"
  140. >
  141. <el-input
  142. disabled
  143. v-model="formData.parentName"
  144. readonly
  145. placeholder="请输入父级名称"
  146. ></el-input>
  147. </el-form-item>
  148. <el-form-item label="操作人" prop="createName">
  149. <el-input
  150. v-model="formData.createName"
  151. readonly
  152. placeholder="请输入操作人"
  153. ></el-input>
  154. </el-form-item>
  155. <el-form-item>
  156. <el-button type="primary" @click="submitForm('ruleForm')">{{
  157. subType
  158. }}</el-button>
  159. <el-button @click="resetForm('ruleForm')">取消</el-button>
  160. </el-form-item>
  161. </el-form>
  162. </div>
  163. <div v-else style="text-align: center">
  164. <img src="../../../assets/404.png" alt="" />
  165. <div>请先选择一个目录</div>
  166. </div>
  167. </div>
  168. </div>
  169. </div>
  170. </template>
  171. <script>
  172. export default {
  173. data() {
  174. return {
  175. loading: false,
  176. defaultExpand: true,
  177. functionCode: "",
  178. filterText: "", // tree搜索value
  179. actionName: "", // 当前选择节点名称
  180. menuList: [], // tree数据源
  181. checkedMenu: [], // 选中节点的functionCode
  182. checkedNodes: [], // 选中节点的node值
  183. roleData: "", // 某一条数据
  184. formData: {
  185. id: "",
  186. title: "",
  187. createName: JSON.parse(sessionStorage.userInfo).loginName,
  188. createId: JSON.parse(sessionStorage.userInfo).loginNo,
  189. orgName: JSON.parse(sessionStorage.userInfo).groupName,
  190. orgId: JSON.parse(sessionStorage.userInfo).groupId,
  191. parentId: "",
  192. parentName: "",
  193. },
  194. defaultProps: {
  195. children: "children",
  196. label: "title",
  197. },
  198. rules: {
  199. title: [{ required: true, message: "请输入标题", trigger: "change" }],
  200. parentId: [
  201. { required: false, message: "请选择父级编码", trigger: "change" },
  202. ],
  203. },
  204. subType: "",
  205. };
  206. },
  207. methods: {
  208. async submitForm(formName) {
  209. let valid = await this.$refs[formName].validate().catch((err) => err);
  210. if (valid) {
  211. this.$http({
  212. url:
  213. this.subType == "保存"
  214. ? "/satisfy/qacatalog/add"
  215. : "/satisfy/qacatalog/update",
  216. method: "post",
  217. headers: {
  218. "Content-Type": "application/json",
  219. },
  220. data: this.formData,
  221. }).then((res) => {
  222. if (res.data.result == 0) {
  223. this.$message({
  224. type: "success",
  225. message: res.data.desc,
  226. });
  227. this.actionName = "";
  228. this.getData();
  229. }
  230. });
  231. } else {
  232. console.log("error submit!!");
  233. return false;
  234. }
  235. },
  236. resetForm(formName) {
  237. this.actionName = "";
  238. this.$refs[formName].resetFields();
  239. },
  240. addMenu() {
  241. if (!this.actionName) {
  242. this.$message("请先点击选中要增加菜单的位置");
  243. } else {
  244. this.subType = "保存";
  245. this.formData.parentId = this.formData.id;
  246. this.formData.parentName = this.formData.title;
  247. this.formData.title = "";
  248. this.formData.id = "";
  249. }
  250. },
  251. treeAction(val) {
  252. val == 1 ? (this.defaultExpand = true) : (this.defaultExpand = false);
  253. for (let i = 0; i < this.$refs.catalogTree.store._getAllNodes().length; i++) {
  254. this.$refs.catalogTree.store._getAllNodes()[i].expanded = this.defaultExpand;
  255. }
  256. },
  257. canelChoice() {
  258. this.actionName = "";
  259. this.formData.title = "";
  260. },
  261. delMenu() {
  262. if (!this.formData.id) {
  263. this.$message("请先点击选中要删除的菜单");
  264. } else {
  265. this.$confirm("即将删除此条数据, 是否删除?", "提示", {
  266. confirmButtonText: "确定",
  267. cancelButtonText: "取消",
  268. type: "warning",
  269. })
  270. .then(() => {
  271. this.$http({
  272. url: "/satisfy/qacatalog/del",
  273. method: "post",
  274. headers: {
  275. "Content-Type": "application/json",
  276. },
  277. data: {
  278. id: this.formData.id,
  279. },
  280. }).then((res) => {
  281. if (res.data.result == 0) {
  282. this.$notify({
  283. title: "成功",
  284. message: res.data.desc,
  285. type: "success",
  286. });
  287. this.actionName = "";
  288. this.getData();
  289. }
  290. });
  291. })
  292. .catch(() => {});
  293. }
  294. },
  295. // 添加一级菜单
  296. firstMenu() {
  297. this.actionName = "add";
  298. this.subType = "保存";
  299. this.formData.title = "";
  300. this.formData.parentId = "";
  301. this.formData.parentName = "";
  302. this.formData.id = "";
  303. },
  304. // 搜索按钮事件
  305. searchMenu() {
  306. this.$refs.tree.filter(this.filterText);
  307. },
  308. // tree过滤方法
  309. filterNode(value, data) {
  310. if (!value) return true;
  311. return data.functionName.indexOf(value) !== -1;
  312. },
  313. // 点击树节点事件
  314. nodeClick(a, b, c, d) {
  315. let nodeData = JSON.parse(JSON.stringify(b.data));
  316. this.formData.title = nodeData.title;
  317. this.formData.parentId = nodeData.parentId;
  318. this.formData.parentName = nodeData.parentName;
  319. this.formData.id = nodeData.id;
  320. delete Object["children"];
  321. this.actionName = nodeData.title;
  322. this.subType = "修改";
  323. },
  324. closeDialog() {
  325. this.actionName = "";
  326. this.getTreeData({});
  327. },
  328. // 树形图 复选框监听事件
  329. checkChange(a, b, c, d) {
  330. this.checkedNodes = b.checkedNodes;
  331. },
  332. getData() {
  333. this.$http({
  334. url: "/satisfy/qacatalog/queryList",
  335. method: "post",
  336. headers: {
  337. "Content-Type": "application/json",
  338. },
  339. data: {},
  340. }).then((res) => {
  341. this.menuList = res.data;
  342. });
  343. },
  344. },
  345. mounted() {
  346. this.getData();
  347. },
  348. };
  349. </script>
  350. <style lang="scss" scoped>
  351. .container {
  352. background-color: #f0f2f5;
  353. .el-col {
  354. background-color: white;
  355. padding: 0 20px;
  356. }
  357. .container-box {
  358. padding: 0;
  359. margin-top: 0;
  360. height: 100%;
  361. }
  362. .main-box {
  363. overflow: hidden;
  364. display: flex;
  365. > div {
  366. background-color: white;
  367. }
  368. .inner-left {
  369. width: 40%;
  370. padding: 0 20px;
  371. .canel-style {
  372. color: #1890ff;
  373. cursor: pointer;
  374. padding-left: 10px;
  375. }
  376. }
  377. .inner-right {
  378. width: 58%;
  379. margin-left: 2%;
  380. overflow-y: auto;
  381. }
  382. }
  383. }
  384. .el-button + .el-button {
  385. margin-left: 20px;
  386. }
  387. .button-list {
  388. padding: 30px 0 10px 0;
  389. }
  390. .choice-style {
  391. background: rgb(255, 255, 255);
  392. }
  393. .tree-action {
  394. bottom: 0;
  395. width: 100%;
  396. // border-top: 1px solid #e8e8e8;
  397. padding: 10px 16px;
  398. text-align: left;
  399. left: 0;
  400. background: #fff;
  401. border-radius: 0 0 2px 2px;
  402. }
  403. .tree-line {
  404. .el-tree-node__content {
  405. padding-left: 0 !important;
  406. }
  407. .el-tree-node__expand-icon.is-leaf {
  408. display: none !important;
  409. }
  410. .el-tree-node {
  411. position: relative;
  412. padding-left: 16px; // 缩进量
  413. }
  414. .el-tree-node__children {
  415. padding-left: 16px; // 缩进量
  416. }
  417. // 竖线
  418. .el-tree-node::before {
  419. content: "";
  420. height: 100%;
  421. width: 1px;
  422. position: absolute;
  423. left: -3px;
  424. top: -17px;
  425. border-width: 1px;
  426. border-left: 1px dashed #52627c;
  427. }
  428. // 当前层最后一个节点的竖线高度固定
  429. .el-tree-node:last-child::before {
  430. height: 38px; // 可以自己调节到合适数值
  431. }
  432. // 横线
  433. .el-tree-node::after {
  434. content: "";
  435. width: 24px;
  436. height: 20px;
  437. position: absolute;
  438. left: -3px;
  439. top: 20px;
  440. border-width: 1px;
  441. border-top: 1px dashed #52627c;
  442. }
  443. // 去掉最顶层的虚线,放最下面样式才不会被上面的覆盖了
  444. & > .el-tree-node::after {
  445. border-top: none;
  446. }
  447. & > .el-tree-node::before {
  448. border-left: none;
  449. }
  450. // 展开关闭的icon
  451. .el-tree-node__expand-icon {
  452. font-size: 16px;
  453. // 叶子节点(无子节点)
  454. &.is-leaf {
  455. color: transparent;
  456. // display: none; // 也可以去掉
  457. }
  458. }
  459. }
  460. .ant-alert-info {
  461. background-color: #e6f7ff;
  462. border: 1px solid #91d5ff;
  463. }
  464. .ant-alert {
  465. box-sizing: border-box;
  466. margin: 0;
  467. padding: 0;
  468. color: rgb(0, 0, 0);
  469. font-size: 14px;
  470. font-variant: tabular-nums;
  471. line-height: 1.5;
  472. list-style: none;
  473. font-feature-settings: "tnum";
  474. position: relative;
  475. padding: 8px 15px 8px 37px;
  476. word-wrap: break-word;
  477. border-radius: 4px;
  478. }
  479. </style>