inleft
2022-03-01 88f419df77ade235ea5e5e24be204842a24b7b33
commit | author | age
9bcb19 1 <template>
I 2   <a-modal
3     title="新增菜单"
4     :width="1000"
5     :visible="visible"
6     :confirmLoading="confirmLoading"
7     @ok="handleSubmit"
8     @cancel="handleCancel"
9     :destroyOnClose="true"
10   >
11     <a-spin :spinning="formLoading">
12       <a-form :form="form" >
13
14         <a-row :gutter="24">
15           <a-col :md="12" :sm="24">
16             <a-form-item
17               label="菜单名称"
18               :labelCol="labelCol"
19               :wrapperCol="wrapperCol"
20               hasFeedback
21             >
22               <a-input placeholder="请输入菜单名称" v-decorator="['name',{rules: [{required: true, min: 1, message: '请输入菜单名称!'}]}]" />
23             </a-form-item>
24           </a-col>
25           <a-col :md="12" :sm="24">
26             <a-form-item
27               style="width: 100%"
28               :labelCol="labelCol"
29               :wrapperCol="wrapperCol"
30               label="菜单编号"
31               hasFeedback
32             >
33               <a-input placeholder="请输入菜单编号" v-decorator="['code', {rules: [{required: true, min: 1, message: '请输入菜单编号!'}]}]" />
34             </a-form-item>
35           </a-col>
36         </a-row>
37
38         <a-row :gutter="24">
39           <a-col :md="12" :sm="24">
40             <a-form-item
41               :labelCol="labelCol"
42               :wrapperCol="wrapperCol"
43               label="所属应用"
44               has-feedback
45             >
46               <a-select style="width: 100%" placeholder="请选择应用分类" v-decorator="['application', {rules: [{ required: true, message: '请选择应用分类!' }]}]" >
47                 <a-select-option v-for="(item,index) in appData" :key="index" :value="item.code" @click="changeApplication(item.code)">{{ item.name }}</a-select-option>
48               </a-select>
49             </a-form-item>
50           </a-col>
51           <a-col :md="12" :sm="24">
52             <a-form-item
53               :labelCol="labelCol"
54               :wrapperCol="wrapperCol"
55               label="菜单层级"
56             >
57               <a-radio-group v-decorator="['type',{rules: [{ required: true, message: '请选择菜单层级!' }]}]" >
58                 <a-radio v-for="(item,index) in typeData" :key="index" :value="item.code" @click="meneTypeFunc(item.code)">{{ item.value }}</a-radio>
59               </a-radio-group>
60             </a-form-item>
61           </a-col>
62         </a-row>
63
64         <a-row :gutter="24">
65           <a-col :md="12" :sm="24">
66             <div v-show="pidShow">
67               <a-form-item
68                 :labelCol="labelCol"
69                 :wrapperCol="wrapperCol"
70                 label="父级菜单"
71                 has-feedback
72               >
73                 <a-tree-select
74                   v-decorator="['pid', {rules: [{ required: true, message: '请选择父级菜单!' }]}]"
75                   style="width: 100%"
76                   :dropdownStyle="{ maxHeight: '300px', overflow: 'auto' }"
77                   :treeData="menuTreeData"
78                   placeholder="请选择父级菜单"
79                   treeDefaultExpandAll
80                 >
81                   <span slot="title" slot-scope="{ id }">{{ id }}
82                   </span>
83                 </a-tree-select>
84               </a-form-item>
85             </div>
86             <div v-show="redirectShow">
87               <a-form-item
88                 :labelCol="labelCol"
89                 :wrapperCol="wrapperCol"
90               >
91                 <span slot="label">
92                   <a-tooltip title="如需打开首页加载此目录下菜单,请填写加载菜单路由,设为首页后其他设置的主页将被替代">
93                     <a-icon type="question-circle-o" />
94                   </a-tooltip>&nbsp;
95                   重定向
96                 </span>
97                 <a-input prop="redirect" placeholder="请输入重定向地址" v-decorator="['redirect']" />
98               </a-form-item>
99             </div>
100           </a-col>
101           <a-col :md="12" :sm="24">
102             <a-form-item
103               :labelCol="labelCol"
104               :wrapperCol="wrapperCol"
105             >
106               <span slot="label">
107                 <a-tooltip title="按钮:无,菜单:内链、外链、组件">
108                   <a-icon type="question-circle-o" />
109                 </a-tooltip>&nbsp;
110                 打开方式
111               </span>
112               <a-radio-group :disabled="openTypeDisabled" v-decorator="['openType',{rules: [{ required: true, message: '请选择打开方式!' }]}]">
113                 <a-radio v-for="(item,index) in openTypeData" :key="index" :value="item.code" @click="meneOpenTypeFunc(item.code)">{{ item.value }}</a-radio>
114               </a-radio-group>
115             </a-form-item>
116
117           </a-col>
118         </a-row>
119
120         <a-divider />
121
122         <a-row :gutter="24" >
123           <a-col :md="12" :sm="24">
124             <div v-show="componentShow">
125               <a-form-item
126                 :labelCol="labelCol"
127                 :wrapperCol="wrapperCol"
128                 hasFeedback
129               >
130                 <span slot="label">
131                   <a-tooltip title="前端vue组件 views文件夹下路径,例:system/menu/index。注:目录级填写:RouteView(不带面包屑),PageView(带面包屑),菜单级内链打开http链接填写:Iframe">
132                     <a-icon type="question-circle-o" />
133                   </a-tooltip>&nbsp;
134                   前端组件
135                 </span>
136                 <a-input placeholder="请输入前端组件" :disabled="componentDisabled" prop="component" v-decorator="['component',{rules: [{required: componentRequired, message: '请输入前端组件'}]}]"/><!-- ,{rules: [{required: componentRequired, min: 1, message: '请输入前端组件!'}]}  -->
137               </a-form-item>
138             </div>
139           </a-col>
140           <a-col :md="12" :sm="24">
141             <div v-show="routerShow">
142               <a-form-item
143                 :labelCol="labelCol"
144                 :wrapperCol="wrapperCol"
145                 hasFeedback
146               >
147                 <span slot="label">
148                   <a-tooltip title="浏览器显示的URL,例:/menu,对应打开页面为菜单页面">
149                     <a-icon type="question-circle-o" />
150                   </a-tooltip>&nbsp;
151                   路由地址
152                 </span>
153                 <a-input placeholder="请输入路由" v-decorator="['router', {rules: [{required: routerRequired, message: '请输入路由!'}]}]" />
154               </a-form-item>
155             </div>
156             <div v-show="permissionShow">
157               <a-form-item
158                 :labelCol="labelCol"
159                 :wrapperCol="wrapperCol"
160                 label="权限标识"
161                 hasFeedback
162               >
163                 <a-input placeholder="请输入权限标识" v-decorator="['permission', {rules: [{required: permissionRequired, message: '请输入权限标识!'}]}]" />
164               </a-form-item>
165             </div>
166           </a-col>
167         </a-row>
168
169         <a-row :gutter="24">
170           <a-col :md="12" :sm="24">
171             <div v-show="linkShow" >
172               <a-form-item
173                 :labelCol="labelCol"
174                 :wrapperCol="wrapperCol"
175                 hasFeedback
176               >
177                 <span slot="label">
178                   <a-tooltip title="当选择了需要内链或外链打开的选项,此处输入要打开的链接地址,例:https://www.xiaonuo.vip">
179                     <a-icon type="question-circle-o" />
180                   </a-tooltip>&nbsp;
181                   内外链地址
182                 </span>
183                 <a-input placeholder="请输入内链打开地址" :disabled="linkDisabled" v-decorator="['link', {rules: [{required: linkRequired, message: '请输入权限标识!'}]}]" />
184               </a-form-item>
185             </div>
186           </a-col>
187           <a-col :md="12" :sm="24">
188             <div v-show="iconShow" >
189               <a-form-item
190                 :labelCol="labelCol"
191                 :wrapperCol="wrapperCol"
192                 label="图标"
193               >
194                 <a-input placeholder="请选择图标" disabled="disabled" v-decorator="['icon']" >
195                   <a-icon slot="addonAfter" @click="openIconSele()" type="setting" />
196                 </a-input>
197               </a-form-item>
198             </div>
199           </a-col>
200         </a-row>
201
202         <a-row :gutter="24">
203           <a-col :md="12" :sm="24">
204             <a-form-item
205               :labelCol="labelCol"
206               :wrapperCol="wrapperCol"
207             >
208               <span slot="label">
209                 <a-tooltip title="系统权重:菜单可分配给任何角色,业务权重:菜单对超级管理员不可见">
210                   <a-icon type="question-circle-o" />
211                 </a-tooltip>&nbsp;
212                 权重
213               </span>
214               <a-radio-group v-decorator="['weight']">
215                 <a-radio v-for="(item,index) in weightData" :key="index" :value="item.code" >{{ item.value }}</a-radio>
216               </a-radio-group>
217             </a-form-item>
218           </a-col>
219           <a-col :md="12" :sm="24">
220             <a-form-item
221               :labelCol="labelCol"
222               :wrapperCol="wrapperCol"
223               label="是否可见"
224             >
225               <a-switch id="visible" checkedChildren="是" unCheckedChildren="否" v-decorator="['visible', { valuePropName: 'checked' }]"/><!-- defaultChecked -->
226             </a-form-item>
227           </a-col>
228         </a-row>
229
230         <a-row :gutter="24">
231           <a-col :md="12" :sm="24">
232             <a-form-item
233               :labelCol="labelCol"
234               :wrapperCol="wrapperCol"
235               label="排序"
236             >
237               <a-input-number style="width: 100%" v-decorator="['sort', { initialValue: 100 }]" :min="1" :max="1000" />
238             </a-form-item>
239           </a-col>
240           <a-col :md="12" :sm="24">
241             <a-form-item
242               :labelCol="labelCol"
243               :wrapperCol="wrapperCol"
244               label="备注"
245               hasFeedback
246             >
247               <a-input placeholder="请输入备注" v-decorator="['remark']"></a-input>
248             </a-form-item>
249           </a-col>
250         </a-row>
251
252       </a-form>
253     </a-spin>
254     <a-modal
255       :width="850"
256       :visible="visibleIcon"
257       @cancel="handleCancelIcon"
258       footer=""
259       :mask="false"
260       :closable="false"
261       :destroyOnClose="true"
262     >
263       <icon-selector v-model="currentSelectedIcon" @change="handleIconChange"/>
264     </a-modal>
265   </a-modal>
266 </template>
267
268 <script>
269   import { getAppList } from '@/api/modular/system/appManage'
270   import { getMenuTree, sysMenuAdd } from '@/api/modular/system/menuManage'
271   import IconSelector from '@/components/IconSelector'
272   import { sysDictTypeDropDown } from '@/api/modular/system/dictManage'
273   export default {
274     components: { IconSelector },
275
276     data () {
277       return {
278         labelCol: {
279           xs: { span: 24 },
280           sm: { span: 6 }
281         },
282         wrapperCol: {
283           xs: { span: 24 },
284           sm: { span: 16 }
285         },
286         visibleIcon: false,
287         visible: false,
288         confirmLoading: false,
289         appData: [],
290         menuTreeData: [],
291         redirectShow: true,
292         componentShow: true,
293         componentDisabled: false,
294         componentRequired: true,
295         routerRequired: true,
296         routerShow: true,
297         iconShow: true,
298         openTypeShow: true,
299         pidShow: true,
300         permissionShow: true,
301         permissionRequired: true,
302         // 图标组件
303         currentSelectedIcon: 'pause-circle',
304         typeData: [],
305         openTypeData: [],
306         weightData: [],
307         formLoading: true,
308         linkShow: true,
309         openTypeDisabled: false,
310         openTypeDefault: [],
311         openType: '',
312         linkRequired: true,
313         linkDisabled: false,
314         type: '',
315         form: this.$form.createForm(this)
316       }
317     },
318
319     methods: {
320       // 打开页面初始化
321       add (type) {
322         this.visible = true
323         // 图标
324         this.currentSelectedIcon = type
325
326         // 默认选中菜单项,并初始化
327         this.form.getFieldDecorator('type', { valuePropName: 'checked', initialValue: '1' })
328         this.meneTypeFunc('1')
329
330         // 默认选中的单选框
331         // this.form.getFieldDecorator('type',{valuePropName:'checked',initialValue:'1'})
332         this.form.getFieldDecorator('weight', { valuePropName: 'checked', initialValue: '2' })
333         this.form.getFieldDecorator('visible', { initialValue: true })
334
335         // 获取系统应用列表
336         this.getSysApplist()
337         this.sysDictTypeDropDown()
338       },
339
340       /**
341        * 获取字典数据
342        */
343       sysDictTypeDropDown () {
344         this.formLoading = true
345         // 菜单类型
346         sysDictTypeDropDown({ code: 'menu_type' }).then((res) => {
347           this.typeData = res.data
348         })
349         // 权重
350         sysDictTypeDropDown({ code: 'menu_weight' }).then((res) => {
351           this.weightData = res.data
352         })
353         // 内外链
354         sysDictTypeDropDown({ code: 'open_type' }).then((res) => {
355           this.openTypeData = res.data
356           this.formLoading = false
357         })
358       },
359
360       getSysApplist () {
361         return getAppList().then((res) => {
362           if (res.success) {
363             this.appData = res.data
364           } else {
365             this.$message.warning(res.message)
366           }
367         })
368       },
369       changeApplication (value) {
370         getMenuTree({ 'application': value }).then((res) => {
371           if (res.success) {
372             this.form.resetFields(`pid`, [])
373             this.menuTreeData = [{
374               'id': '-1',
375               'parentId': '0',
376               'title': '顶级',
377               'value': '0',
378               'pid': '0',
379               'children': res.data
380             }]
381           } else {
382             this.$message.warning(res.message)
383           }
384         })
385       },
386
387       /**
388        * 选择菜单类型执行初始化表单变量
389        */
390       meneTypeFunc (type) {
391         this.type = type
392         // eslint-disable-next-line eqeqeq
393         if (type == '0' || type == '1') {
394           // 内外链地址显示,给空值
395           this.linkShow = true
396           this.form.resetFields(`link`, [])
397           // 图标选择显示
398           this.iconShow = true
399           // 路由必填,设置空值,并显示
400           this.routerRequired = true
401           this.form.getFieldDecorator('router', { initialValue: '' })
402           this.routerShow = true
403           // 权限标识框隐藏,选填,给空值
404           this.permissionShow = false
405           this.permissionRequired = false
406           this.form.getFieldDecorator('permission', { initialValue: '' })
407           // 打开方式设置为组件 ,禁用选择方式
408           this.openType = '1'
409           this.form.getFieldDecorator('openType', { initialValue: this.openType = '1' })
410           this.openTypeDisabled = false
411         }
412         // eslint-disable-next-line eqeqeq
413         if (type == '0') {
414           // 重定向展示,并给空
415           this.redirectShow = true
416           this.form.resetFields(`redirect`, [])
417           // 组件默认为显示,设置可输入,给默认组件 PageView,验证必填
418           this.componentShow = true
419           this.componentDisabled = false
420           this.form.getFieldDecorator('component', { initialValue: 'PageView' })
421           this.componentRequired = true
422           // 父级初始化顶级,并将其隐藏
423           this.form.getFieldDecorator('pid', { initialValue: '0' })
424           this.pidShow = false
425         } else {
426           // eslint-disable-next-line eqeqeq
427           if (type == '1') {
428             // 组件可以手输,取消值
429             this.componentDisabled = false
430             this.form.getFieldDecorator('component', { initialValue: '' })
431           }
432           // 重定向输入隐藏,并给空值
433           this.redirectShow = false
434           this.form.getFieldDecorator('redirect', { initialValue: '' })
435           // 父级选择放开
436           this.pidShow = true
437         }
438         // eslint-disable-next-line eqeqeq
439         if (type == '2') {
440           // 组件设置不填,不可输入,并给空(手输的跟设置的)
441           this.componentRequired = false
442           this.componentDisabled = true
443           this.form.resetFields(`component`, [])
444           this.form.getFieldDecorator('component', { initialValue: '' })
445           // 路由选填,设置空值,并隐藏
446           this.routerRequired = true
447           this.form.getFieldDecorator('router', { initialValue: '' })
448           this.routerShow = false
449           // 内外链地址隐藏,给空值
450           this.linkShow = false
451           this.form.getFieldDecorator('link', { initialValue: '' })
452           // 权限标识框显示,必填,给空值
453           this.permissionShow = true
454           this.permissionRequired = true
455           this.form.getFieldDecorator('permission', { initialValue: '' })
456           // 图标选择隐藏,并给空
457           this.iconShow = false
458           this.form.getFieldDecorator('icon', { initialValue: '' })
459           // 打开方式设置为无 ,禁用选择方式
460           this.openType = '0'
461           this.form.getFieldDecorator('openType', { initialValue: this.openType })
462           this.openTypeDisabled = true
463           // 取消icon
464           this.form.getFieldDecorator('icon', { initialValue: '' })
465         }
466         this.meneOpenTypeFunc(this.openType)
467       },
468
469       /**
470        * 选择打开方式执行方法
471        */
472       meneOpenTypeFunc (openType) {
473          this.form.resetFields(`openType`, openType)
474          // eslint-disable-next-line eqeqeq
475          if (openType == '2' || openType == '3') {
476            // 点击内外链的时候保留原值,其他清空
477            if (this.linkDisabled === false) {
478              this.form.resetFields(`link`, [])
479            }
480             // 设置内外链可手输,加验证
481            this.linkDisabled = false
482            this.linkRequired = true
483          } else {
484             // 设置内外链不可手输,取消值,取消验证
485             this.linkDisabled = true
486             this.form.resetFields(`link`, [])
487             this.linkRequired = false
488          }
489          // 另起一个分支
490         // eslint-disable-next-line eqeqeq
491         if (openType == '3') {
492           this.componentRequired = false
493           this.componentDisabled = true
494           this.form.resetFields(`component`, [])
495           this.form.getFieldDecorator('component', { initialValue: '' })
496         } else {
497           this.componentRequired = true
498           // eslint-disable-next-line eqeqeq
499           if (this.type == '1' || this.type == '2') {
500             this.form.getFieldDecorator('component', { initialValue: '' })
501           } else {
502             this.form.resetFields(`component`, [])
503             this.form.getFieldDecorator('component', { initialValue: 'PageView' })
504           }
505           // eslint-disable-next-line eqeqeq
506           if (openType == '2') {
507             // 组件设置为 iframe
508             this.form.resetFields(`component`, [])
509             this.form.getFieldDecorator('component', { initialValue: 'Iframe' })
510           }
511         }
512         // eslint-disable-next-line eqeqeq
513         if (this.type == '2') {
514           // eslint-disable-next-line eqeqeq
515           if (openType == '0') {
516             this.componentRequired = false
517             this.routerRequired = false
518           }
519         }
520       },
521
522       openIconSele () {
523         this.visibleIcon = true
524       },
525       handleIconChange (icon) {
526         this.form.getFieldDecorator('icon', { initialValue: icon })
527         this.visibleIcon = false
528       },
529       handleCancelIcon () {
530         this.visibleIcon = false
531       },
532       handleSubmit () {
533         const { form: { validateFields } } = this
534         this.confirmLoading = true
535         validateFields((errors, values) => {
536           if (!errors) {
537             if (values.visible) {
538               values.visible = 'Y'
539             } else {
540               values.visible = 'N'
541             }
542             sysMenuAdd(values).then((res) => {
543               this.confirmLoading = false
544               if (res.success) {
545                 this.$message.success('新增成功')
546                 this.$emit('ok', values)
547                 this.handleCancel()
548               } else {
549                 this.$message.error('新增失败:' + res.message)
550               }
551             }).finally((res) => {
552               this.confirmLoading = false
553             })
554           } else {
555             this.confirmLoading = false
556           }
557         })
558       },
559       handleCancel () {
560         this.form.resetFields()
561         this.confirmLoading = false
562         this.visible = false
563       }
564     }
565
566   }
567 </script>