index.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. <template>
  2. <el-container>
  3. <el-main class="page-main">
  4. <el-card>
  5. <el-container>
  6. <el-header height="120">
  7. <el-form ref="searchForm" :size="size" label-position="left" label-width="80px">
  8. <el-row :gutter="20">
  9. <el-col :span="6">
  10. <el-form-item label="名称:" class="notice-input" label-width="60px">
  11. <el-input
  12. v-model="dataQuery.name"
  13. placeholder="请输入名称"
  14. clearable
  15. @keyup.enter.native="search"
  16. />
  17. </el-form-item>
  18. </el-col>
  19. <el-col :span="6">
  20. <el-form-item label="编码:" class="notice-input" label-width="60px">
  21. <el-input
  22. v-model="dataQuery.code"
  23. placeholder="请输入编码"
  24. clearable
  25. @keyup.enter.native="search"
  26. />
  27. </el-form-item>
  28. </el-col>
  29. <el-col :span="12" style="text-align: right">
  30. <el-form-item>
  31. <el-button type="primary" icon="el-icon-search" :size="size" @click="search">查询</el-button>
  32. <el-button icon="el-icon-refresh" :size="size" @click="resetFields">重置</el-button>
  33. <export-button :api="this.$api.sysRole.page" :columns="tableColumns" :data-query="dataQuery" name="roles.xlsx" />
  34. </el-form-item>
  35. </el-col>
  36. </el-row>
  37. <el-row>
  38. <el-button type="primary" icon="el-icon-plus" :size="size" @click="create">新建</el-button>
  39. <el-button :size="size" @click="deleteBatch">批量删除</el-button>
  40. </el-row>
  41. </el-form>
  42. </el-header>
  43. <el-main>
  44. <sheet
  45. ref="qtable"
  46. :api="this.$api.sysRole.page"
  47. :columns="tableColumns"
  48. :data-query="dataQuery"
  49. :operates="operates"
  50. :float-type="'right'"
  51. :select-type="'selection'"
  52. />
  53. </el-main>
  54. </el-container>
  55. </el-card>
  56. </el-main>
  57. <el-dialog :title="dialogStatus==='create'?'新建角色':'编辑角色'" :visible.sync="dialogVisible" width="60%" @close="dialogClose">
  58. <el-form ref="dataForm" :size="size" :rules="rules" :model="temp" label-width="85px">
  59. <el-form-item label="角色名:" prop="name">
  60. <el-input v-model="temp.name" :size="size" placeholder="请输入角色名" />
  61. </el-form-item>
  62. <el-form-item label="编码:" prop="code">
  63. <el-input v-model="temp.code" :size="size" placeholder="请输入编码" />
  64. </el-form-item>
  65. <el-form-item label="后台首页:" prop="index_component">
  66. <el-input v-model="temp.index_component" :size="size" placeholder="请输入后台首页" />
  67. </el-form-item>
  68. <el-form-item label="APP首页:" prop="app_index">
  69. <el-input v-model="temp.app_index" :size="size" placeholder="请输入APP首页" />
  70. </el-form-item>
  71. <el-form-item v-if="dialogStatus=='update'" label prop="code">
  72. <el-tabs v-model="activeName" @tab-click="handleTabsClick">
  73. <el-tab-pane label="后台菜单" name="first">
  74. <tree-transfer
  75. :title="transferTitle"
  76. :from_data="fromData"
  77. :to_data="selectMenu"
  78. :default-checked-keys="selectedArray"
  79. :default-props="defaultProps"
  80. check-strictly="true"
  81. :mode="mode"
  82. height="350px"
  83. filter
  84. open-all
  85. @addBtn="changeMenu"
  86. @removeBtn="changeMenu"
  87. />
  88. </el-tab-pane>
  89. <el-tab-pane label="APP功能" name="second">
  90. <tree-transfer
  91. :title="transferTitle"
  92. :from_data="appFunfromData"
  93. :to_data="selectAppFun"
  94. :default-checked-keys="selectedAppFunArray"
  95. :default-props="defaultProps"
  96. check-strictly="true"
  97. :mode="mode"
  98. height="350px"
  99. filter
  100. open-all
  101. @addBtn="changeAppFun"
  102. @removeBtn="changeAppFun"
  103. />
  104. </el-tab-pane>
  105. </el-tabs>
  106. </el-form-item>
  107. </el-form>
  108. <footer slot="footer" class="dialog-footer">
  109. <el-button :size="size" @click="dialogVisible = false">取 消</el-button>
  110. <el-button
  111. :size="size"
  112. type="primary"
  113. @click="dialogStatus==='create'?createData():updateData()"
  114. >确 定</el-button>
  115. </footer>
  116. </el-dialog>
  117. </el-container>
  118. </template>
  119. <script>
  120. import { mapGetters } from 'vuex'
  121. import { deepClone } from '@/utils/index'
  122. import Sheet from '@/components/Sheet'
  123. import treeTransfer from 'el-tree-transfer'
  124. import ExportButton from '@/components/ExportButton'
  125. export default {
  126. name: 'Role',
  127. components: {
  128. Sheet,
  129. treeTransfer,
  130. ExportButton
  131. },
  132. data() {
  133. return {
  134. menu: [],
  135. activeName: 'first',
  136. role_id: '',
  137. fromData: [],
  138. selectMenu: [],
  139. selectedArray: [],
  140. appFunfromData: [],
  141. selectAppFun: [],
  142. selectedAppFunArray: [],
  143. transferTitle: ['Source', 'Target'],
  144. tableColumns: [
  145. {
  146. prop: 'name',
  147. label: '名称',
  148. align: 'center',
  149. minWidth: 180,
  150. maxWidth: 220
  151. },
  152. {
  153. prop: 'code',
  154. label: '编码',
  155. align: 'center',
  156. minWidth: 150,
  157. maxWidth: 180
  158. }
  159. ],
  160. operates: {
  161. list: [
  162. {
  163. label: '编辑',
  164. show: true,
  165. type: 'primary',
  166. method: row => {
  167. this.edit(row)
  168. }
  169. },
  170. {
  171. label: '删除',
  172. show: true,
  173. type: 'danger',
  174. method: row => {
  175. this.deleteData(row)
  176. }
  177. }
  178. ],
  179. width: 150
  180. },
  181. dataQuery: {
  182. page: 1,
  183. rows: 10,
  184. name: '',
  185. code: ''
  186. },
  187. rules: {
  188. name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
  189. code: [{ required: true, message: '请输入编码', trigger: 'blur' }],
  190. index_component: [
  191. { required: true, message: '请输入后台组件', trigger: 'blur' }
  192. ],
  193. app_index: [
  194. { required: true, message: '请输入app首页', trigger: 'blur' }
  195. ]
  196. },
  197. temp: {
  198. id: undefined,
  199. name: '',
  200. code: '',
  201. index_component: '',
  202. app_index: ''
  203. },
  204. mode: 'transfer',
  205. defaultProps: {
  206. children: 'nodes',
  207. label: 'name',
  208. value: 'id',
  209. key: 'id'
  210. },
  211. dataLoading: false,
  212. dialogStatus: '',
  213. dialogVisible: false
  214. }
  215. },
  216. computed: {
  217. ...mapGetters(['size', 'minMainHeight'])
  218. },
  219. created() {},
  220. methods: {
  221. handleTabsClick(tab, event) {},
  222. getRoleMenuTree(role_id) {
  223. Promise.all([this.$api.sysMenu.tree(), this.$api.sysRole.roleMenuTree({ role_id: role_id })]).then(res => {
  224. this.fromData = res[0].data
  225. this.selectMenu = res[1].data
  226. this.selectedArray = []
  227. this.selectMenu.forEach(item => {
  228. const subSelectId = this.getEndNodes(item)
  229. this.selectedArray = this.selectedArray.concat(subSelectId)
  230. })
  231. })
  232. },
  233. getRoleAppFun(role_id) {
  234. Promise.all([this.$api.sysAppFun.tree(), this.$api.sysRole.roleAppFunTree({ role_id: role_id })]).then(res => {
  235. this.appFunfromData = res[0].data
  236. this.selectAppFun = res[1].data
  237. this.selectedAppFunArray = []
  238. this.selectAppFun.forEach(item => {
  239. const subSelectId = this.getEndNodes(item)
  240. this.selectedAppFunArray = this.selectedAppFunArray.concat(
  241. subSelectId
  242. )
  243. })
  244. })
  245. },
  246. getEndNodes(tree) {
  247. let array = []
  248. tree.nodes.forEach(node => {
  249. if (node.nodes === null || node.nodes.length === 0) {
  250. array.push(node.id)
  251. } else {
  252. array = array.concat(this.getEndNodes(node))
  253. }
  254. })
  255. return array
  256. },
  257. changeMenu(fromData, toData, obj) {
  258. let menu_ids = []
  259. toData.forEach(item => {
  260. const submenus = this.treeToArray(item, 'id')
  261. menu_ids = menu_ids.concat(submenus)
  262. })
  263. this.menu = menu_ids
  264. this.$api.system
  265. .AddRoleMenu({ role_id: this.role_id, menu_ids: menu_ids })
  266. .then(res => {
  267. this.getRoleMenuTree(this.role_id)
  268. })
  269. },
  270. changeAppFun(fromData, toData, obj) {
  271. let app_fun_ids = []
  272. toData.forEach(item => {
  273. const subAppFuns = this.treeToArray(item, 'id')
  274. app_fun_ids = app_fun_ids.concat(subAppFuns)
  275. })
  276. this.$api.app_fun
  277. .AddRoleAppFun({ role_id: this.role_id, app_fun_ids: app_fun_ids })
  278. .then(res => {
  279. this.getAppFunTree(this.role_id)
  280. })
  281. },
  282. treeToArray(data, key) {
  283. let array = []
  284. if (key !== undefined) {
  285. array.push(data[key])
  286. } else {
  287. array.push(data)
  288. }
  289. if (data.nodes === null || data.nodes.length === 0) {
  290. return array
  291. }
  292. data.nodes.forEach(item => {
  293. if (item.nodes != null && item.nodes.length > 0) {
  294. array = array.concat(this.treeToArray(item, key))
  295. } else {
  296. if (key !== undefined) {
  297. array.push(item[key])
  298. } else {
  299. array.push(item)
  300. }
  301. }
  302. })
  303. return array
  304. },
  305. createData() {
  306. this.$refs['dataForm'].validate(valid => {
  307. if (valid) {
  308. this.$api.system.AddRole(this.temp).then(res => {
  309. this.dialogVisible = false
  310. if (res.code === 200) {
  311. this.$message({
  312. message: '创建成功',
  313. type: 'success'
  314. })
  315. this.$refs.qtable.getData()
  316. } else {
  317. this.$message({
  318. message: '创建失败',
  319. type: 'error'
  320. })
  321. }
  322. })
  323. }
  324. })
  325. },
  326. updateData() {
  327. if (this.menu.length === 0) {
  328. this.$message.error('最少选择一个菜单,加入到已选择项中')
  329. return
  330. }
  331. this.$refs['dataForm'].validate(valid => {
  332. if (valid) {
  333. const postData = Object.assign({}, this.temp)
  334. console.log(postData)
  335. this.$api.system.UpdateRole(postData).then(res => {
  336. if (res.code === 200) {
  337. this.dialogVisible = false
  338. this.$message({
  339. message: '修改成功',
  340. type: 'success'
  341. })
  342. this.$refs.qtable.getData()
  343. } else {
  344. this.dialogVisible = false
  345. this.$message({
  346. message: '修改失败',
  347. type: 'error'
  348. })
  349. }
  350. })
  351. }
  352. })
  353. },
  354. deleteData(row) {
  355. this.$confirm('确认删除?', '提示', {
  356. type: 'warning'
  357. })
  358. .then(() => {
  359. this.$api.system.DelRole([{ id: row.id }]).then(res => {
  360. if (res.code === 200) {
  361. this.$refs.qtable.getData()
  362. this.$message({
  363. message: '删除成功',
  364. type: 'success'
  365. })
  366. } else {
  367. this.$message({
  368. message: '删除失败',
  369. type: 'error'
  370. })
  371. }
  372. })
  373. })
  374. .catch(() => {})
  375. },
  376. deleteBatch() {
  377. const ids = []
  378. this.$refs.qtable.multipleSelection.forEach(row => {
  379. ids.push({ id: row.id })
  380. })
  381. this.$confirm('确认批量删除选中数据吗?', '提示', {
  382. type: 'warning'
  383. })
  384. .then(() => {
  385. this.$api.system.DelRole(ids).then(res => {
  386. if (res.code === 200) {
  387. this.$refs.qtable.getData()
  388. this.$message({
  389. message: '删除成功',
  390. type: 'success'
  391. })
  392. } else {
  393. this.$message({
  394. message: '删除失败',
  395. type: 'error'
  396. })
  397. }
  398. })
  399. })
  400. .catch(() => {})
  401. },
  402. search() {
  403. this.$refs.qtable.getData()
  404. },
  405. resetFields() {
  406. this.$refs['searchForm'].resetFields()
  407. },
  408. dialogClose() {
  409. this.$refs['dataForm'].resetFields()
  410. },
  411. create() {
  412. this.dialogStatus = 'create'
  413. this.dialogVisible = true
  414. this.$nextTick(() => {
  415. this.$refs['dataForm'].clearValidate()
  416. })
  417. },
  418. edit(row) {
  419. this.dialogStatus = 'update'
  420. this.dialogVisible = true
  421. this.$nextTick(() => {
  422. this.$refs['dataForm'].clearValidate()
  423. this.temp = deepClone(row)
  424. this.role_id = row.id
  425. this.getRoleMenuTree(this.role_id)
  426. this.getRoleAppFun(this.role_id)
  427. })
  428. }
  429. }
  430. }
  431. </script>
  432. <style scoped lang="scss">
  433. </style>