addForm.vue 20 KB

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