role.vue 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. <template>
  2. <view class="container">
  3. <view class="safe-area-inset-bottom">
  4. <rider-curd
  5. v-model="form"
  6. :option="option"
  7. :data="list"
  8. :rules="rules"
  9. :readonly.sync="readonly"
  10. @search="onSearch"
  11. @action-click="onActionClick"
  12. @submit="onSubmit"
  13. @del="onRemove"
  14. ref="crud"
  15. >
  16. <template #form>
  17. <u-form-item label="角色名称" prop="roleName" :label-width="option.labelWidth || 160" required>
  18. <u-input v-model="form.roleName" :disabled="readonly" placeholder="角色名称" />
  19. </u-form-item>
  20. <u-form-item label="上级角色" prop="parentId" :label-width="option.labelWidth || 160">
  21. <u-input
  22. v-model="formLabel.parentName"
  23. placeholder="上级角色"
  24. type="select"
  25. @click="
  26. () => {
  27. if (!readonly) $refs.treePicker._show()
  28. }
  29. "
  30. />
  31. </u-form-item>
  32. <u-form-item label="角色别名" prop="roleAlias" required :label-width="option.labelWidth || 160">
  33. <u-input v-model="form.roleAlias" :disabled="readonly" placeholder="角色别名" />
  34. </u-form-item>
  35. <u-form-item label="角色排序" prop="sort" required :label-width="option.labelWidth || 160">
  36. <u-input v-model="form.sort" :disabled="readonly" type="number" placeholder="角色排序" />
  37. </u-form-item>
  38. </template>
  39. <template #loadmore>
  40. <u-loadmore :status="loadStatus" @loadmore="getList()" />
  41. </template>
  42. </rider-curd>
  43. </view>
  44. <!-- 上级角色tree -->
  45. <rider-tree
  46. ref="treePicker"
  47. :range="roleTreeList"
  48. @cancel="$refs.treePicker._hide()"
  49. @confirm="onTreeConfirm"
  50. idKey="id"
  51. nameKey="title"
  52. :multiple="false"
  53. :cascade="false"
  54. :foldAll="false"
  55. confirmColor="#4E7FF9"
  56. cancelColor="#757575"
  57. title="上级角色"
  58. titleColor="#757575"
  59. ></rider-tree>
  60. <!-- 菜单权限 -->
  61. <rider-tree
  62. ref="menuPicker"
  63. :range="menuTreeList"
  64. @cancel="$refs.menuPicker._hide()"
  65. @confirm="onMenuConfirm"
  66. idKey="id"
  67. nameKey="title"
  68. :multiple="true"
  69. :cascade="true"
  70. :foldAll="true"
  71. confirmColor="#4E7FF9"
  72. cancelColor="#757575"
  73. title="菜单权限"
  74. titleColor="#757575"
  75. ></rider-tree>
  76. </view>
  77. </template>
  78. <script>
  79. import riderCurd from '@/components/rider-crud/index'
  80. import riderTree from '@/components/rider-crud/components/tree-picker'
  81. import { getList, add, update, remove, roleTree, menuTree, menuTreeKey, grant } from '@/api/system/role.js'
  82. import { tenantSelect } from '@/api/system/tenant.js'
  83. import { getDicLabel } from '@/components/rider-crud/util/tool.js'
  84. export default {
  85. components: { riderCurd, riderTree },
  86. data() {
  87. return {
  88. checkedSwitch: false,
  89. form: {},
  90. formLabel: {},
  91. list: [],
  92. params: {
  93. current: 1,
  94. size: 10
  95. },
  96. readonly: false, // 查看时控制表单只读
  97. loadStatus: 'loadmore', // 列表加载状态
  98. option: {
  99. navTitle: '角色管理', //标题
  100. manageBtn: true, // 右上角管理按钮,默认不显示
  101. searchShow: true, //是否显示搜索,默认不显示
  102. labelWidth: 160, //form表单lable宽度, 默认160,单位rpx
  103. column: [
  104. {
  105. label: '角色名称',
  106. prop: 'roleName'
  107. },
  108. {
  109. label: '所属租户',
  110. prop: 'tenantName'
  111. },
  112. {
  113. label: '角色别名',
  114. prop: 'roleAlias'
  115. },
  116. {
  117. label: '角色排序',
  118. prop: 'sort'
  119. }
  120. ],
  121. actions: [
  122. {
  123. name: '编辑', // 操作名称
  124. icon: 'edit-pen', //操作图标,有图标文字不显示
  125. color: '#333', // 字体颜色
  126. fontsize: 30, //字体大小,单位rpx
  127. width: 40, // 宽度,单位px
  128. background: '#fff' // 菜单按钮背景色
  129. },
  130. {
  131. name: '删除',
  132. icon: 'trash',
  133. color: '#333',
  134. fontsize: 30,
  135. width: 40,
  136. background: '#fff'
  137. },
  138. {
  139. name: '菜单权限',
  140. icon: 'setting',
  141. color: '#333',
  142. fontsize: 30,
  143. width: 40,
  144. background: '#fff'
  145. }
  146. ]
  147. },
  148. rules: {
  149. roleName: [{ required: true, message: '请输入角色名称', trigger: 'blur' }],
  150. roleAlias: [{ required: true, message: '请输入角色别名', trigger: 'blur' }],
  151. sort: [{ required: true, message: '请输入角色排序', trigger: 'blur', type: 'number' }]
  152. },
  153. tenantList: [],
  154. roleTreeList: [],
  155. menuTreeList: [],
  156. menuCheckIds: [],
  157. roleIds: null
  158. }
  159. },
  160. onReady() {
  161. this.getTenant().then(() => {
  162. this.getList(true)
  163. })
  164. },
  165. onPullDownRefresh() {
  166. this.getList(true)
  167. },
  168. onReachBottom() {
  169. if (this.loadStatus == 'nomore') return
  170. this.getList()
  171. },
  172. methods: {
  173. // 获取列表
  174. getList(override = false) {
  175. if (override) {
  176. this.params.current = 1
  177. }
  178. const { size } = this.params
  179. getList(this.params)
  180. .then(res => {
  181. const records = res.data
  182. if (records.length < size) this.loadStatus = 'nomore'
  183. else this.loadStatus = 'loadmore'
  184. if (override) {
  185. this.list = records
  186. } else {
  187. this.list = this.list.concat(records)
  188. }
  189. if (this.list && this.list.length > 0) {
  190. this.list = this.filterList(this.list)
  191. }
  192. this.params.current++
  193. uni.stopPullDownRefresh()
  194. })
  195. .catch(err => {
  196. uni.stopPullDownRefresh()
  197. })
  198. },
  199. filterList(list) {
  200. if (!list || list.length == 0) return list
  201. list.forEach(e => {
  202. e.tenantName = getDicLabel(e.tenantId, this.tenantList, { label: 'tenantName', value: 'tenantId' })
  203. if (e.children) this.filterList(e.children)
  204. })
  205. return list
  206. },
  207. // 租户类型
  208. getTenant() {
  209. return new Promise(resolve => {
  210. roleTree().then(res => {
  211. this.roleTreeList = res.data
  212. })
  213. tenantSelect().then(res => {
  214. this.tenantList = res.data
  215. resolve()
  216. })
  217. })
  218. },
  219. // 获取菜单权限内容
  220. getMenu(roleIds) {
  221. menuTreeKey({ roleIds }).then(res => {
  222. this.menuCheckIds = res.data.menu
  223. })
  224. menuTree().then(res => {
  225. this.recursion(this.menuCheckIds, res.data.menu)
  226. this.menuTreeList = res.data.menu
  227. setTimeout(() => {
  228. this.$refs.menuPicker._show()
  229. }, 10)
  230. })
  231. },
  232. // 递归
  233. recursion(arr, menu) {
  234. menu.forEach(e => {
  235. if (arr.includes(e.id)) e.checked = true
  236. if (e.hasChildren || (e.children && e.children.length > 0)) {
  237. this.recursion(arr, e.children)
  238. }
  239. })
  240. },
  241. // 菜单权限勾选回调
  242. onMenuConfirm(e) {
  243. let arr = []
  244. e.forEach(e => {
  245. arr.push(e.id)
  246. })
  247. const params = {
  248. apiScopeIds: [],
  249. dataScopeIds: [],
  250. roleIds: [this.roleIds],
  251. menuIds: arr
  252. }
  253. grant(params).then(res => {
  254. uni.showToast({
  255. icon: 'none',
  256. title: '操作成功'
  257. })
  258. })
  259. },
  260. //机构选择回调
  261. onTreeConfirm(e) {
  262. this.$set(this.form, 'parentId', e[0].id)
  263. this.$set(this.formLabel, 'parentName', e[0].name)
  264. },
  265. // 搜索 (自行配置搜索内容)
  266. onSearch(val) {
  267. this.params = {
  268. current: 1,
  269. size: 10,
  270. roleName: val
  271. }
  272. this.getList(true)
  273. },
  274. // 左滑按钮点击
  275. onActionClick({ index, data, action, done }) {
  276. const { name } = action
  277. console.log(name, index)
  278. switch (name) {
  279. case '新增':
  280. done()
  281. break
  282. case '删除':
  283. this.onRemove(data.id)
  284. break
  285. case '查看':
  286. this.readonly = true
  287. case '编辑':
  288. this.$set(this.formLabel, 'parentName', data.parentName)
  289. done()
  290. break
  291. case '菜单权限':
  292. this.roleIds = data.id
  293. this.getMenu(data.id)
  294. break
  295. }
  296. if (['删除', '编辑'].includes(name)) this.$refs['crud'].hideChildren()
  297. },
  298. // 删除
  299. onRemove(id) {
  300. uni.showModal({
  301. title: '确定要删除吗?',
  302. success: action => {
  303. if (action.confirm) {
  304. remove(id).then(() => {
  305. uni.showToast({
  306. title: '删除成功',
  307. icon: 'none'
  308. })
  309. setTimeout(() => {
  310. this.$refs['crud'].allCheckHide(false)
  311. }, 100)
  312. // #ifdef APP
  313. this.getList(true)
  314. // #endif
  315. // #ifndef APP
  316. uni.startPullDownRefresh({})
  317. // #endif
  318. })
  319. }
  320. }
  321. })
  322. },
  323. // 表单提交
  324. onSubmit(form, action, unloading, done) {
  325. if (action == '新增') {
  326. add(form)
  327. .then(res => {
  328. uni.showToast({
  329. title: '新增成功',
  330. icon: 'none'
  331. })
  332. // this.category = ''
  333. done()
  334. uni.startPullDownRefresh({})
  335. })
  336. .catch(() => {
  337. unloading()
  338. })
  339. } else if (action == '编辑') {
  340. update(form)
  341. .then(res => {
  342. uni.showToast({
  343. title: '编辑成功',
  344. icon: 'none'
  345. })
  346. // this.category = ''
  347. done()
  348. uni.startPullDownRefresh({})
  349. })
  350. .catch(() => {
  351. unloading()
  352. })
  353. }
  354. }
  355. }
  356. }
  357. </script>
  358. <style>
  359. page {
  360. background: #f6f6f6;
  361. }
  362. </style>
  363. <style lang="scss" scoped>
  364. .nav-right {
  365. color: #fff;
  366. font-size: 28rpx;
  367. font-weight: normal;
  368. padding-right: 24rpx;
  369. }
  370. </style>