menu-edit.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. <!-- 编辑弹窗 -->
  2. <template>
  3. <ele-modal
  4. width="720px"
  5. :visible="visible"
  6. :close-on-click-modal="false"
  7. custom-class="ele-dialog-form"
  8. :title="isUpdate ? '修改菜单' : '添加菜单'"
  9. @update:visible="updateVisible"
  10. :maxable="true"
  11. >
  12. <el-form ref="form" :model="form" :rules="rules" label-width="100px">
  13. <el-row>
  14. <el-col :span="12">
  15. <el-form-item label="上级菜单:">
  16. <ele-tree-select
  17. clearable
  18. v-model="form.parentId"
  19. :data="menuList"
  20. label-key="name"
  21. value-key="id"
  22. default-expand-all
  23. placeholder="请选择上级菜单"
  24. />
  25. </el-form-item>
  26. </el-col>
  27. <el-col :span="12">
  28. <el-form-item label="菜单名称:" prop="name">
  29. <el-input
  30. clearable
  31. v-model="form.name"
  32. placeholder="请输入菜单名称"
  33. />
  34. </el-form-item>
  35. </el-col>
  36. <el-col :span="24">
  37. <el-form-item label="菜单来源:" prop="source">
  38. <el-radio-group v-model="form.source" @input="sourceChange">
  39. <el-radio :label="1">内部地址</el-radio>
  40. <el-radio :label="2">外部地址</el-radio>
  41. </el-radio-group>
  42. </el-form-item>
  43. </el-col>
  44. <el-col :span="12">
  45. <el-form-item label="路由地址:" prop="url">
  46. <el-input
  47. :disabled="form.source == 2"
  48. clearable
  49. v-model="form.url"
  50. placeholder="请输入路由地址"
  51. />
  52. </el-form-item>
  53. </el-col>
  54. <el-col :span="12">
  55. <el-form-item
  56. :label="form.source == 1 ? '组件地址' : '外链地址'"
  57. :prop="form.source == 2 ? 'component' : ''"
  58. >
  59. <el-input
  60. clearable
  61. v-model="form.component"
  62. :placeholder="
  63. form.source == 1 ? '请输入组件地址' : '请输入外链地址'
  64. "
  65. />
  66. </el-form-item>
  67. </el-col>
  68. <el-col :span="12">
  69. <el-form-item label="权限编码:" prop="permissionCode">
  70. <el-input
  71. clearable
  72. v-model="form.permissionCode"
  73. placeholder="请输入路由地址"
  74. />
  75. </el-form-item>
  76. </el-col>
  77. <el-col :span="12">
  78. <el-form-item v-if="form.rootId != 99999" label="菜单图标:">
  79. <ele-icon-picker
  80. v-model="form.icon"
  81. placeholder="请选择菜单图标"
  82. :disabled="form.type === 2"
  83. />
  84. </el-form-item>
  85. <el-form-item v-if="form.rootId == 99999" label="菜单图标:">
  86. <el-input
  87. clearable
  88. v-model="form.icon"
  89. placeholder="请输入pda图标"
  90. />
  91. </el-form-item>
  92. </el-col>
  93. <el-col :span="12">
  94. <el-form-item label="密级:" prop="secretLevel">
  95. <el-select v-model="form.secretLevel" style="width: 100%">
  96. <el-option
  97. v-for="item in secretLevelList()"
  98. :key="item.value"
  99. :label="item.label"
  100. :value="item.value"
  101. ></el-option>
  102. </el-select>
  103. </el-form-item>
  104. </el-col>
  105. <el-col :span="12">
  106. <el-form-item label="排序号:" prop="sort">
  107. <el-input-number
  108. :min="0"
  109. v-model="form.sort"
  110. placeholder="请输入排序号"
  111. controls-position="right"
  112. class="ele-fluid ele-text-left"
  113. />
  114. </el-form-item>
  115. </el-col>
  116. <el-col :span="12">
  117. <el-form-item label="菜单类型:" prop="type">
  118. <el-radio-group v-model="form.type" @change="onMenuTypeChange">
  119. <el-radio :label="1">菜单</el-radio>
  120. <el-radio :label="2">按钮</el-radio>
  121. </el-radio-group>
  122. </el-form-item>
  123. </el-col>
  124. </el-row>
  125. <!-- <div style="margin: 6px 0 28px 0">
  126. <el-divider />
  127. </div> -->
  128. </el-form>
  129. <template v-slot:footer>
  130. <el-button @click="updateVisible(false)">取消</el-button>
  131. <el-button type="primary" :loading="loading" @click="save">
  132. 保存
  133. </el-button>
  134. </template>
  135. </ele-modal>
  136. </template>
  137. <script>
  138. import { EleIconPicker } from 'ele-admin';
  139. import { saveOrUpdate } from '@/api/system/menu';
  140. import { secretLevelList } from '@/enum/dict';
  141. export default {
  142. components: { EleIconPicker },
  143. props: {
  144. // 弹窗是否打开
  145. visible: Boolean,
  146. // 修改回显的数据
  147. data: Object,
  148. // 上级菜单id
  149. parentId: [Number, String],
  150. // 全部菜单数据
  151. menuList: Array
  152. },
  153. data() {
  154. const defaultForm = {
  155. id: null,
  156. parentId: '',
  157. name: '',
  158. type: 1,
  159. source: 1,
  160. icon: '',
  161. url: '/',
  162. component: '',
  163. sort: null,
  164. rootId: null,
  165. permissionCode: 1,
  166. secretLevel: 1
  167. };
  168. return {
  169. defaultForm,
  170. // 表单数据
  171. form: { ...defaultForm },
  172. // 表单验证规则
  173. rules: {
  174. name: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }],
  175. sort: [{ required: true, message: '请输入排序号', trigger: 'blur' }],
  176. url: [{ required: true, message: '请输入菜单路由', trigger: 'blur' }],
  177. component: [
  178. { required: true, message: '请输入组件地址', trigger: 'blur' }
  179. ],
  180. type: [{ required: true, message: '请选择菜单类型', trigger: 'blur' }]
  181. },
  182. // 提交状态
  183. loading: false,
  184. // 是否是修改
  185. isUpdate: false
  186. };
  187. },
  188. computed: {
  189. // pathPlaceholder() {
  190. // return this.form.openType === 2 ? '请输入外链地址' : '请输入路由地址';
  191. // },
  192. // componentPlaceholder() {
  193. // return this.form.openType === 1 ? '请输入内链地址' : '请输入组件路径';
  194. // },
  195. // // 是否开启响应式布局
  196. // styleResponsive() {
  197. // return this.$store.state.theme.styleResponsive;
  198. // }
  199. },
  200. methods: {
  201. secretLevelList() {
  202. return secretLevelList;
  203. },
  204. sourceChange(e) {
  205. if (e == 2) {
  206. this.form.url =
  207. '/sourceLink' + Math.floor(10000 + Math.random() * 90000);
  208. } else {
  209. this.form.url = '/';
  210. }
  211. },
  212. /* 保存编辑 */
  213. save() {
  214. this.$refs.form.validate((valid) => {
  215. if (!valid) {
  216. return false;
  217. }
  218. this.loading = true;
  219. const data = {
  220. ...this.form,
  221. // menuType 对应的值与后端不一致在前端处理
  222. // type: this.form.type === 2 ? 1 : 0,
  223. parentId: this.form.parentId || 0
  224. };
  225. // const saveOrUpdate = this.isUpdate ? updateMenu : addMenu;
  226. if (!this.isUpdate) {
  227. delete data.id;
  228. }
  229. saveOrUpdate(data)
  230. .then((res) => {
  231. this.loading = false;
  232. if (this.isUpdate) {
  233. this.$message.success('菜单编辑成功');
  234. } else {
  235. this.$message.success('菜单新增成功');
  236. }
  237. this.updateVisible(false);
  238. this.$emit('done');
  239. })
  240. .catch((e) => {
  241. this.loading = false;
  242. // this.$message.error(e.message);
  243. });
  244. });
  245. },
  246. /* 更新visible */
  247. updateVisible(value) {
  248. this.$emit('update:visible', value);
  249. },
  250. /* menuType选择改变 */
  251. onMenuTypeChange() {
  252. // if (this.form.menuType === 0) {
  253. // this.form.authority = null;
  254. // this.form.openType = 0;
  255. // this.form.component = null;
  256. // } else if (this.form.menuType === 1) {
  257. // if (this.form.openType === 2) {
  258. // this.form.authority = null;
  259. // }
  260. // } else {
  261. // this.form.openType = 0;
  262. // this.form.icon = null;
  263. // this.form.path = null;
  264. // this.form.component = null;
  265. // this.form.hide = 0;
  266. // }
  267. },
  268. /* openType选择改变 */
  269. onOpenTypeChange() {
  270. if (this.form.openType === 2) {
  271. this.form.component = null;
  272. this.form.authority = null;
  273. }
  274. }
  275. /* 判断是否是外链 */
  276. // isUrl(url) {
  277. // return !!(
  278. // url &&
  279. // (url.startsWith('http://') ||
  280. // url.startsWith('https://') ||
  281. // url.startsWith('//'))
  282. // );
  283. // },
  284. /* 判断是否是目录 */
  285. // isDirectory(d) {
  286. // return !!d.children?.length && !d.component;
  287. // }
  288. },
  289. watch: {
  290. visible(visible) {
  291. if (visible) {
  292. if (this.data) {
  293. // const isInnerLink = this.isUrl(this.data.component) ? 1 : 0;
  294. // menuType 对应的值与后端不一致在前端处理
  295. // const menuType =
  296. // this.data.type === 1
  297. // ? 2
  298. // : this.isDirectory(this.data)
  299. // ? 0
  300. // : 1;
  301. this.$util.assignObject(this.form, {
  302. ...this.data,
  303. // openType: this.isUrl(this.data.path) ? 2 : isInnerLink,
  304. parentId: this.data.parentId == 0 ? '' : this.data.parentId ?? ''
  305. });
  306. this.isUpdate = true;
  307. // this.sourceChange(this.form.source);
  308. } else {
  309. this.form.parentId = this.parentId ?? '';
  310. this.isUpdate = false;
  311. }
  312. } else {
  313. this.$refs.form.clearValidate();
  314. this.form = { ...this.defaultForm };
  315. // this.sourceChange(this.form.source);
  316. }
  317. }
  318. }
  319. };
  320. </script>