index.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. <!--
  2. - Copyright (c) 2018-2025, lengleng All rights reserved.
  3. -
  4. - Redistribution and use in source and binary forms, with or without
  5. - modification, are permitted provided that the following conditions are met:
  6. -
  7. - Redistributions of source code must retain the above copyright notice,
  8. - this list of conditions and the following disclaimer.
  9. - Redistributions in binary form must reproduce the above copyright
  10. - notice, this list of conditions and the following disclaimer in the
  11. - documentation and/or other materials provided with the distribution.
  12. - Neither the name of the pig4cloud.com developer nor the names of its
  13. - contributors may be used to endorse or promote products derived from
  14. - this software without specific prior written permission.
  15. - Author: lengleng (wangiegie@gmail.com)
  16. -->
  17. <template>
  18. <div class="app-container calendar-list-container">
  19. <basic-container>
  20. <div class="filter-container">
  21. <el-button-group>
  22. <el-button type="primary"
  23. v-if="menuManager_btn_add"
  24. icon="plus"
  25. @click="handlerAdd">添加
  26. </el-button>
  27. <el-button type="primary"
  28. v-if="menuManager_btn_edit"
  29. icon="edit"
  30. @click="handlerEdit">编辑
  31. </el-button>
  32. <el-button type="primary"
  33. v-if="menuManager_btn_del"
  34. icon="delete"
  35. @click="handleDelete">删除
  36. </el-button>
  37. </el-button-group>
  38. </div>
  39. <el-row>
  40. <el-col :span="8"
  41. style='margin-top:15px;'>
  42. <el-tree class="filter-tree"
  43. node-key="id"
  44. highlight-current
  45. :data="treeData"
  46. :default-expanded-keys="aExpandedKeys"
  47. :filter-node-method="filterNode"
  48. :props="defaultProps"
  49. @node-click="getNodeData"
  50. @node-expand="nodeExpand"
  51. @node-collapse="nodeCollapse">
  52. </el-tree>
  53. </el-col>
  54. <el-col :span="16"
  55. style='margin-top:15px;'>
  56. <el-card class="box-card">
  57. <el-form :label-position="labelPosition"
  58. label-width="80px"
  59. :model="form"
  60. :rules="rules"
  61. ref="form">
  62. <el-form-item label="父级节点"
  63. prop="parentId">
  64. <el-input v-model="form.parentId"
  65. :disabled="true"
  66. placeholder="请输入父级节点"></el-input>
  67. </el-form-item>
  68. <el-form-item label="节点ID"
  69. prop="menuId">
  70. <el-input v-model="form.menuId" type="number"
  71. :disabled="formEdit || formStatus === 'update'"
  72. placeholder="请输入节点ID"></el-input>
  73. </el-form-item>
  74. <el-form-item label="标题"
  75. prop="name">
  76. <el-input v-model="form.name"
  77. :disabled="formEdit"
  78. placeholder="请输入标题"></el-input>
  79. </el-form-item>
  80. <el-form-item label="类型"
  81. prop="type">
  82. <el-select class="filter-item"
  83. v-model="form.type"
  84. :disabled="formEdit"
  85. placeholder="请输入资源请求类型">
  86. <el-option v-for="item in typeOptions"
  87. :key="item"
  88. :label="item | typeFilter"
  89. :value="item"></el-option>
  90. </el-select>
  91. </el-form-item>
  92. <el-form-item label="权限标识"
  93. prop="permission" v-if="form.type === '1'">
  94. <el-input v-model="form.permission"
  95. :disabled="formEdit"
  96. placeholder="请输入权限标识"></el-input>
  97. </el-form-item>
  98. <el-form-item label="图标" v-if="form.type === '0'"
  99. prop="icon">
  100. <avue-icon-select v-model="form.icon"
  101. :iconList="iconList"
  102. :disabled="formEdit"
  103. placeholder="请输入图标"></avue-icon-select>
  104. </el-form-item>
  105. <el-form-item label="排序" v-if="form.type === '0'"
  106. prop="sort">
  107. <el-input type="number"
  108. v-model="form.sort"
  109. :disabled="formEdit"
  110. placeholder="请输入排序"></el-input>
  111. </el-form-item>
  112. <el-form-item label="前端组件" v-if="form.type === '0'"
  113. prop="component">
  114. <el-input v-model="form.component"
  115. :disabled="formEdit"
  116. placeholder="请输入描述"></el-input>
  117. </el-form-item>
  118. <el-form-item label="前端地址" v-if="form.type === '0'"
  119. prop="component">
  120. <el-input v-model="form.path"
  121. :disabled="formEdit"
  122. placeholder="iframe嵌套地址"></el-input>
  123. </el-form-item>
  124. <el-form-item label="路由缓冲" v-if="form.type === '0'"
  125. prop="component">
  126. <el-switch v-model="form.keepAlive"
  127. :disabled="formEdit"
  128. active-color="#13ce66"
  129. inactive-color="#ff4949"
  130. :active-value='"0"'
  131. :inactive-value='"1"'>
  132. </el-switch>
  133. </el-form-item>
  134. <el-form-item v-if="formStatus === 'update'">
  135. <el-button type="primary"
  136. @click="update">更新
  137. </el-button>
  138. <el-button @click="onCancel">取消</el-button>
  139. </el-form-item>
  140. <el-form-item v-if="formStatus === 'create'">
  141. <el-button type="primary"
  142. @click="create">保存
  143. </el-button>
  144. <el-button @click="onCancel">取消</el-button>
  145. </el-form-item>
  146. </el-form>
  147. </el-card>
  148. </el-col>
  149. </el-row>
  150. </basic-container>
  151. </div>
  152. </template>
  153. <script>
  154. import {addObj, delObj, fetchMenuTree, getObj, putObj} from "@/api/admin/menu";
  155. import {mapGetters} from "vuex";
  156. import iconList from "@/const/iconList";
  157. export default {
  158. name: "menu",
  159. data() {
  160. return {
  161. iconList: iconList,
  162. list: null,
  163. total: null,
  164. formEdit: true,
  165. formAdd: true,
  166. formStatus: "",
  167. showElement: false,
  168. typeOptions: ["0", "1"],
  169. listQuery: {
  170. name: undefined
  171. },
  172. treeData: [],
  173. oExpandedKey: {
  174. // key (from tree id) : expandedOrNot boolean
  175. },
  176. oTreeNodeChildren: {
  177. // id1 : [children] (from tree node id1)
  178. // id2 : [children] (from tree node id2)
  179. },
  180. aExpandedKeys: [],
  181. defaultProps: {
  182. children: "children",
  183. label: "name"
  184. },
  185. labelPosition: "right",
  186. form: {
  187. permission: undefined,
  188. name: undefined,
  189. menuId: undefined,
  190. parentId: undefined,
  191. icon: undefined,
  192. sort: undefined,
  193. component: undefined,
  194. type: undefined,
  195. path: undefined
  196. },
  197. currentId: -1,
  198. menuManager_btn_add: false,
  199. menuManager_btn_edit: false,
  200. menuManager_btn_del: false,
  201. rules: {
  202. menuId: [{required: true, message: '节点ID不合法', trigger: 'blur'}],
  203. name: [{required: true, message: '标题不合法', trigger: 'blur'}],
  204. type: [{required: true, message: '标题不合法', trigger: 'blur'}],
  205. }
  206. };
  207. },
  208. filters: {
  209. typeFilter(type) {
  210. const typeMap = {
  211. 0: "菜单",
  212. 1: "按钮"
  213. };
  214. return typeMap[type];
  215. }
  216. },
  217. created() {
  218. this.getList();
  219. this.menuManager_btn_add = this.permissions["sys_menu_add"];
  220. this.menuManager_btn_edit = this.permissions["sys_menu_edit"];
  221. this.menuManager_btn_del = this.permissions["sys_menu_del"];
  222. },
  223. computed: {
  224. ...mapGetters(["elements", "permissions"])
  225. },
  226. methods: {
  227. getList() {
  228. fetchMenuTree(this.listQuery).then(response => {
  229. this.treeData = response.data.data;
  230. });
  231. },
  232. filterNode(value, data) {
  233. if (!value) return true;
  234. return data.label.indexOf(value) !== -1;
  235. },
  236. nodeExpand(data) {
  237. let aChildren = data.children;
  238. if (aChildren.length > 0) {
  239. this.oExpandedKey[data.id] = true;
  240. this.oTreeNodeChildren[data.id] = aChildren;
  241. }
  242. this.setExpandedKeys();
  243. },
  244. nodeCollapse(data) {
  245. this.oExpandedKey[data.id] = false;
  246. // 如果有子节点
  247. this.treeRecursion(this.oTreeNodeChildren[data.id], oNode => {
  248. this.oExpandedKey[oNode.id] = false;
  249. });
  250. this.setExpandedKeys();
  251. },
  252. setExpandedKeys() {
  253. let oTemp = this.oExpandedKey;
  254. this.aExpandedKeys = [];
  255. for (let sKey in oTemp) {
  256. if (oTemp[sKey]) {
  257. this.aExpandedKeys.push(parseInt(sKey));
  258. }
  259. }
  260. },
  261. treeRecursion(aChildren, fnCallback) {
  262. if (aChildren) {
  263. for (let i = 0; i < aChildren.length; ++i) {
  264. let oNode = aChildren[i];
  265. fnCallback && fnCallback(oNode);
  266. this.treeRecursion(oNode.children, fnCallback);
  267. }
  268. }
  269. },
  270. getNodeData(data) {
  271. if (!this.formEdit) {
  272. this.formStatus = "update";
  273. }
  274. getObj(data.id).then(response => {
  275. this.form = response.data.data;
  276. });
  277. this.currentId = data.id;
  278. this.showElement = true;
  279. },
  280. handlerEdit() {
  281. if (this.form.menuId) {
  282. this.formEdit = false;
  283. this.formStatus = "update";
  284. }
  285. },
  286. handlerAdd() {
  287. this.resetForm();
  288. this.formEdit = false;
  289. this.formStatus = "create";
  290. },
  291. handleDelete() {
  292. this.$confirm("此操作将永久删除, 是否继续?", "提示", {
  293. confirmButtonText: "确定",
  294. cancelButtonText: "取消",
  295. type: "warning"
  296. }).then(() => {
  297. delObj(this.currentId).then(() => {
  298. this.getList();
  299. this.resetForm();
  300. this.onCancel();
  301. this.$notify({
  302. title: "成功",
  303. message: "删除成功",
  304. type: "success",
  305. duration: 2000
  306. });
  307. });
  308. });
  309. },
  310. update() {
  311. this.$refs.form.validate((valid) => {
  312. if (valid) {
  313. putObj(this.form).then(() => {
  314. this.getList();
  315. this.formEdit = false
  316. this.$notify({
  317. title: "成功",
  318. message: "更新成功",
  319. type: "success",
  320. duration: 2000
  321. });
  322. });
  323. }
  324. });
  325. },
  326. create() {
  327. this.$refs.form.validate((valid) => {
  328. if (valid) {
  329. addObj(this.form).then(() => {
  330. this.getList();
  331. this.formEdit = false
  332. this.$notify({
  333. title: "成功",
  334. message: "创建成功",
  335. type: "success",
  336. duration: 2000
  337. });
  338. });
  339. }
  340. });
  341. },
  342. onCancel() {
  343. this.formEdit = true;
  344. this.formStatus = "";
  345. },
  346. resetForm() {
  347. this.form = {
  348. permission: undefined,
  349. name: undefined,
  350. menuId: undefined,
  351. parentId: this.currentId,
  352. icon: undefined,
  353. sort: undefined,
  354. component: undefined,
  355. type: undefined,
  356. path: undefined
  357. };
  358. }
  359. }
  360. };
  361. </script>