index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  1. <template>
  2. <div class="userStyleMenus">
  3. <!-- 搜索 -->
  4. <FixedNav class="formSearch" :height="200">
  5. <div class="searchInput">
  6. <span>菜单名:</span>
  7. <el-input v-model="formInline.permissionName" maxlength="20" placeholder="请输入菜单名" />
  8. </div>
  9. <el-button type="primary" plain @click="search">查询</el-button>
  10. <el-button type="info" plain @click="clear">重置</el-button>
  11. <el-button type="success" plain @click="add(1)">新增父级目录</el-button>
  12. <el-button type="success" plain @click="add(2)">新增子级菜单</el-button>
  13. <el-button type="success" plain @click="add(3)">新增子级按钮</el-button>
  14. <el-button type="success" plain @click="syncMenu()">同步菜单</el-button>
  15. </FixedNav>
  16. <!-- 表 格 default-expand-all -->
  17. <div class="tableBox">
  18. <el-table
  19. ref="menuList" :data="tableData" style="width: 100%; margin-bottom: 20px" row-key="permissionId"
  20. border
  21. :header-cell-style="{ background: '#EEF3FF', color: '#333333' }"
  22. :tree-props="{ children: 'childs', hasChildren: 'hasChildren' }" @select="select" @select-all="selectAll"
  23. @selection-change="handleSelectionChange"
  24. >
  25. <el-table-column type="selection" width="55" />
  26. <el-table-column prop="permissionName" label="菜单名称" />
  27. <el-table-column label="图标">
  28. <template slot-scope="scope">
  29. <div>
  30. <i :class="scope.row.icon" />
  31. </div>
  32. </template>
  33. </el-table-column>
  34. <el-table-column prop="permission" label="菜单标识" />
  35. <el-table-column prop="createTime" label="创建时间" />
  36. <el-table-column label="操作" show-overflow-tooltip>
  37. <template slot-scope="scope">
  38. <div class="btnList">
  39. <el-button type="text" @click="edit(scope.row)">编辑</el-button>
  40. <el-button type="text" @click="del(scope.row)">删除</el-button>
  41. </div>
  42. </template>
  43. </el-table-column>
  44. </el-table>
  45. <div class="fenye">
  46. <el-pagination
  47. :current-page="currentPage" :page-sizes="[10, 20, 50, 100]" :page-size="10"
  48. layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange"
  49. @current-change="handleCurrentChange"
  50. />
  51. </div>
  52. </div>
  53. <!-- *************对话框开始************* -->
  54. <el-dialog
  55. :title="userState ? '新增菜单' : '修改菜单'" :visible.sync="addFormDialog" width="30%" center
  56. :close-on-click-modal="false"
  57. >
  58. <!-- 新增角色 -->
  59. <div>
  60. <el-form ref="ruleForm" :model="addForm" label-width="80px" :rules="userRules">
  61. <el-form-item label="父节点ID">
  62. <el-input v-model="addForm.permissionPid" maxlength="20" :disabled="true" placeholder="请输入角色名称" />
  63. </el-form-item>
  64. <el-form-item label="菜单名称" prop="permissionName">
  65. <el-input v-model="addForm.permissionName" maxlength="20" placeholder="请输入菜单名称" />
  66. </el-form-item>
  67. <el-form-item label="菜单路径" prop="permission">
  68. <el-input v-model="addForm.permission" maxlength="100" placeholder="请输入菜单路径" />
  69. </el-form-item>
  70. <el-form-item label="图标地址" prop="icon">
  71. <el-input v-model="addForm.icon" :prefix-icon="addForm.icon" placeholder="请输入图片地址" @focus="getFocus" />
  72. </el-form-item>
  73. <el-form-item label="菜单描述">
  74. <el-input v-model="addForm.describe" maxlength="60" placeholder="请输入菜单描述" />
  75. </el-form-item>
  76. <el-form-item label="排序值" prop="sort">
  77. <el-input
  78. v-model="addForm.sort" maxlength="9" placeholder="请输入排序值"
  79. oninput="value=value.replace(/[^\d]/g,'')"
  80. />
  81. </el-form-item>
  82. <el-form-item label="权限类型" prop="resourceType">
  83. <el-select v-model="addForm.resourceType" placeholder="请选择活动区域">
  84. <el-option label="菜单" value="menu" />
  85. <el-option label="按钮" value="button" />
  86. <el-option label="目录" value="catalog" />
  87. </el-select>
  88. </el-form-item>
  89. </el-form>
  90. </div>
  91. <span slot="footer" class="dialog-footer">
  92. <el-button @click="addFormDialog = false">取 消</el-button>
  93. <el-button type="primary" @click="addForm_enter('ruleForm')">确 定</el-button>
  94. </span>
  95. </el-dialog>
  96. <!-- *************同步菜单对话框开始************* -->
  97. <el-dialog :title="'同步菜单'" :visible.sync="syncMenuDialog" width="30%" center :close-on-click-modal="false">
  98. <!-- 新增角色 -->
  99. <div>
  100. <el-form ref="syncMenuForm" :model="syncMenuForm" label-width="80px" :rules="syncMenuRules">
  101. <el-form-item label="同步范围" prop="syncAll">
  102. <el-radio-group v-model="syncMenuForm.syncAll">
  103. <el-radio :label="true">同步所有</el-radio>
  104. <el-radio :label="false">同步指定商家</el-radio>
  105. </el-radio-group>
  106. </el-form-item>
  107. <el-form-item label="删除菜单">
  108. <el-checkbox v-model="syncMenuForm.delMenu" />
  109. </el-form-item>
  110. <el-form-item v-if="syncMenuForm.syncAll == false" label="商家账号">
  111. <el-input v-model="syncMenuForm.syncBusinessUsername" maxlength="20" placeholder="请输入商家账号" />
  112. </el-form-item>
  113. </el-form>
  114. </div>
  115. <span slot="footer" class="dialog-footer">
  116. <el-button @click="syncMenuDialog = false">取 消</el-button>
  117. <el-button type="primary" :loading="loading" @click="submitSyncMenu('syncMenuForm')">确 定</el-button>
  118. </span>
  119. </el-dialog>
  120. <Icons :dialog-visible="iconVisible" @choose="chooseIcon" @close="iconVisible = false" />
  121. </div>
  122. </template>
  123. <script>
  124. import {
  125. businessTabsGetAll,
  126. businessTabsAdd,
  127. businessTabsGetById,
  128. businessTabsUpdate,
  129. businessTabsDelete,
  130. businessGetMaxSort,
  131. businessSyncMenu
  132. } from '@/api/setup'
  133. import Icons from './Icons'
  134. import { Message } from 'element-ui'
  135. import FixedNav from '@/components/FixedNav/index.vue'
  136. export default {
  137. // import引入的组件需要注入到对象中才能使用
  138. components: {
  139. Icons,
  140. FixedNav
  141. },
  142. data() {
  143. // 这里存放数据
  144. return {
  145. formInline: {
  146. permissionName: '', // 搜索字段
  147. page: '1', // 当前页
  148. pageSize: '10' // 每页记录数
  149. },
  150. total: 1,
  151. tableData: [],
  152. currentPage: 1,
  153. userState: 1,
  154. addForm: {
  155. permissionPid: '', // 父节点id
  156. permissionName: '', // 权限名称
  157. permissionUri: '', // URI
  158. permission: '', // 组件
  159. icon: '', // 图标地址
  160. describe: '', // 描述
  161. resourceType: 'menu', // 权限类型 menu-菜单 button-按钮 catalog-目录
  162. sort: '' // 排序值
  163. },
  164. syncMenuForm: {
  165. syncAll: false,
  166. syncBusinessUsername: '',
  167. delMenu: false
  168. },
  169. addFormDialog: false,
  170. syncMenuDialog: false,
  171. userRules: {
  172. permissionName: [
  173. { required: true, message: '请输入权限名称', trigger: 'blur' }
  174. ],
  175. permission: [
  176. { required: true, message: '请输入菜单路径', trigger: 'blur' }
  177. ],
  178. resourceType: [
  179. { required: true, message: '请选择活动区域', trigger: 'change' }
  180. ],
  181. sort: [ { required: true, message: '请输入菜单路径', trigger: 'blur' } ],
  182. icon: [ { required: true, message: '请输入图标地址', trigger: 'blur' } ]
  183. },
  184. syncMenuRules: {},
  185. iconVisible: false,
  186. multipleSelection: [],
  187. loading: false
  188. }
  189. },
  190. mounted() {
  191. this.getAll(this.formInline)
  192. },
  193. // 方法集合
  194. methods: {
  195. handleSelectionChange(val) {
  196. // console.dir(this.$refs.menuList.selection)
  197. // const sel = this.extract(val)
  198. this.multipleSelection = val
  199. // console.dir(this.$refs.menuList)
  200. },
  201. setChildren(children, type) {
  202. // 编辑多个子层级
  203. children.map((j) => {
  204. this.toggleSelection(j, type)
  205. if (j.childs) {
  206. this.setChildren(j.childs, type)
  207. }
  208. })
  209. },
  210. // 选中父节点时,子节点一起选中取消
  211. select(selection, row) {
  212. if (selection.some((el) => row.permissionId === el.permissionId)) {
  213. if (row.childs) {
  214. // row.childList.map(j => {
  215. // this.toggleSelection(j, true)
  216. // })
  217. // 解决子组件没有被勾选到
  218. this.setChildren(row.childs, true)
  219. }
  220. } else if (row.childs) {
  221. // row.childList.map(j => {
  222. // this.toggleSelection(j, false)
  223. // })
  224. this.setChildren(row.childs, false)
  225. }
  226. },
  227. toggleSelection(row, select) {
  228. if (row) {
  229. this.$nextTick(() => {
  230. this.$refs.menuList && this.$refs.menuList.toggleRowSelection(row, select)
  231. })
  232. }
  233. },
  234. // 选择全部
  235. selectAll(selection) {
  236. // tabledata第一层只要有在selection里面就是全选
  237. const isSelect = selection.some((el) => {
  238. const tableDataIds = this.tableData.map((j) => j.permissionId)
  239. return tableDataIds.includes(el.permissionId)
  240. })
  241. // tableDate第一层只要有不在selection里面就是全不选
  242. const isCancel = !this.tableData.every((el) => {
  243. const selectIds = selection.map((j) => j.permissionId)
  244. return selectIds.includes(el.permissionId)
  245. })
  246. console.log(isSelect, 'isSelect')
  247. if (isSelect) {
  248. selection.map((el) => {
  249. if (el.childs) {
  250. // el.childList.map(j => {
  251. // this.toggleSelection(j, true)
  252. // })
  253. // 解决子组件没有被勾选到
  254. this.setChildren(el.childs, true)
  255. }
  256. })
  257. }
  258. if (isCancel) {
  259. this.tableData.map((el) => {
  260. if (el.childs) {
  261. // el.childList.map(j => {
  262. // this.toggleSelection(j, false)
  263. // })
  264. // 解决子组件没有被勾选到
  265. this.setChildren(el.childs, false)
  266. }
  267. })
  268. }
  269. this.$emit('handleSelect', this.tableData)
  270. },
  271. handleSizeChange(val) {
  272. this.formInline.pageSize = val
  273. this.getAll(this.formInline)
  274. },
  275. handleCurrentChange(val) {
  276. this.formInline.page = val
  277. this.getAll(this.formInline)
  278. },
  279. // 查询
  280. search() {
  281. this.total = 1
  282. this.formInline.page = 1
  283. this.getAll(this.formInline)
  284. },
  285. // 清除
  286. clear() {
  287. this.formInline = {
  288. permissionName: '', // 搜索字段
  289. page: '1', // 当前页
  290. pageSize: '10' // 每页记录数
  291. }
  292. this.getAll(this.formInline)
  293. },
  294. // 新增角色
  295. add(index) {
  296. this.userState = 1
  297. businessGetMaxSort().then((res) => {
  298. if (index === 1) {
  299. if (this.multipleSelection.length >= 1) {
  300. this.$message({
  301. message: '请勿选择节点进行操作'
  302. })
  303. return
  304. }
  305. this.addForm = {
  306. permissionPid: '', // 父节点id
  307. permissionName: '', // 权限名称
  308. permissionUri: '', // URI
  309. permission: '', // 组件
  310. icon: '', // 图标地址
  311. describe: '', // 描述
  312. resourceType: 'catalog', // 权限类型 menu-菜单 button-按钮 catalog-目录
  313. sort: parseInt(res.data) // 排序值
  314. }
  315. this.addFormDialog = true
  316. } else if (index === 2) {
  317. if (this.multipleSelection.length === 0) {
  318. this.$message({
  319. message: '请选择父节点'
  320. })
  321. return
  322. }
  323. if (this.multipleSelection[0].permissionPid !== 0) {
  324. this.$message({
  325. message: '请选择父节点进行操作'
  326. })
  327. return
  328. }
  329. this.addForm = {
  330. permissionPid: this.multipleSelection[0].permissionId, // 父节点id
  331. permissionName: '', // 权限名称
  332. permissionUri: '', // URI
  333. permission: '', // 组件
  334. icon: '', // 图标地址
  335. describe: '', // 描述
  336. resourceType: 'menu', // 权限类型 menu-菜单 button-按钮 catalog-目录
  337. sort: parseInt(res.data) // 排序值
  338. }
  339. this.addFormDialog = true
  340. } else if (index === 3) {
  341. if (this.multipleSelection.length === 0) {
  342. this.$message({
  343. message: '请选择子节点'
  344. })
  345. return
  346. }
  347. if (
  348. this.multipleSelection[0].permissionPid === 0 &&
  349. this.multipleSelection[0].childs.length !== 0
  350. ) {
  351. this.$message({
  352. message: '请勿选择父节点进行操作'
  353. })
  354. return
  355. }
  356. this.addForm = {
  357. permissionPid: this.multipleSelection[0].permissionId, // 父节点id
  358. permissionName: '', // 权限名称
  359. permissionUri: '', // URI
  360. permission: '', // 组件
  361. icon: 'el-icon-minus', // 图标地址
  362. describe: '', // 描述
  363. resourceType: 'button', // 权限类型 menu-菜单 button-按钮 catalog-目录
  364. sort: parseInt(res.data) // 排序值
  365. }
  366. this.addFormDialog = true
  367. }
  368. })
  369. },
  370. syncMenu() {
  371. if (this.multipleSelection.length === 0) {
  372. this.$message({
  373. message: '请选择要同步的节点'
  374. })
  375. return
  376. }
  377. this.syncMenuForm.syncAll = true
  378. this.syncMenuForm.syncBusinessUsername = ''
  379. this.syncMenuForm.delMenu = false
  380. this.syncMenuDialog = true
  381. },
  382. submitSyncMenu(syncMenuForm) {
  383. const that = this
  384. this.$refs[syncMenuForm].validate((valid) => {
  385. if (valid) {
  386. if (that.syncMenuForm.syncAll === false && that.syncMenuForm.syncBusinessUsername === '') {
  387. this.$message({
  388. message: '请输入要同步的商家账号'
  389. })
  390. return
  391. }
  392. this.loading = true
  393. businessSyncMenu(Object.assign({}, this.syncMenuForm, { syncMenu: this.multipleSelection })).then((res) => {
  394. if (res.code === '') {
  395. this.$message({
  396. message: '同步成功',
  397. type: 'success'
  398. })
  399. }
  400. this.loading = false
  401. this.syncMenuDialog = false
  402. })
  403. .catch((error) => {
  404. if (error && error.message.includes('timeout')) {
  405. Message({
  406. message: '后台正在异步处理,请关注商家端菜单变化',
  407. type: 'error',
  408. duration: 2 * 1000
  409. })
  410. }
  411. this.loading = false
  412. this.syncMenuDialog = false
  413. })
  414. }
  415. })
  416. },
  417. // 确认新增角色
  418. addForm_enter(ruleForm) {
  419. this.$refs[ruleForm].validate((valid) => {
  420. if (valid) {
  421. if (this.userState) {
  422. businessTabsAdd(this.addForm).then((res) => {
  423. if (res.code === '') {
  424. this.$message({
  425. message: '新增成功',
  426. type: 'success'
  427. })
  428. }
  429. this.getAll(this.formInline)
  430. this.addFormDialog = false
  431. })
  432. } else {
  433. businessTabsUpdate(this.addForm).then((res) => {
  434. if (res.code === '') {
  435. this.$message({
  436. message: '修改成功',
  437. type: 'success'
  438. })
  439. }
  440. this.getAll(this.formInline)
  441. this.addFormDialog = false
  442. })
  443. }
  444. } else {
  445. console.log('error submit!!')
  446. return false
  447. }
  448. })
  449. },
  450. // 编辑角色
  451. edit(row) {
  452. this.userState = 0
  453. this.addFormDialog = true
  454. businessTabsGetById({ permissionId: row.permissionId }).then((res) => {
  455. this.addForm = res.data
  456. // this.addForm.roleIds = [1];
  457. })
  458. },
  459. // 删除角色
  460. async del(row) {
  461. const res = await businessTabsDelete({ permissionId: row.permissionId })
  462. if (res.code === '') {
  463. this.$message({
  464. message: '删除成功',
  465. type: 'success'
  466. })
  467. }
  468. this.getAll(this.formInline)
  469. },
  470. // 组件传回值
  471. chooseIcon(icon) {
  472. this.addForm.icon = icon
  473. this.iconVisible = false
  474. },
  475. getFocus() {
  476. this.iconVisible = true
  477. },
  478. // 初始化查询所有数据
  479. async getAll(formInline) {
  480. const res = await businessTabsGetAll(formInline)
  481. this.tableData = res.data.list
  482. this.total = res.data.total
  483. }
  484. }
  485. }
  486. </script>
  487. <style lang='scss' scoped>
  488. //@import url(); 引入公共css类
  489. @import url("../../../styles/elDialog.scss");
  490. .userStyleMenus {
  491. .formSearch {
  492. padding: 20px 30px;
  493. display: flex;
  494. .searchInput {
  495. margin-right: 20px;
  496. display: flex;
  497. align-items: center;
  498. span {
  499. min-width: 80px;
  500. }
  501. }
  502. }
  503. .tableBox {
  504. margin: 0 20px 20px;
  505. }
  506. }
  507. </style>