阅行客电子档案
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

423 lines
15 KiB

3 years ago
2 years ago
2 years ago
3 years ago
3 years ago
2 years ago
2 years ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
2 years ago
3 years ago
2 years ago
2 years ago
2 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
2 years ago
3 years ago
3 years ago
2 years ago
3 years ago
  1. <template>
  2. <div class="app-container">
  3. <div class="container-main" style="justify-content: flex-start;">
  4. <!--侧边部门数据-->
  5. <div class="elect-cont-right">
  6. <!--工具栏-->
  7. <div class="head-container">
  8. <div v-if="crud.props.searchToggle" class="head-search">
  9. <!-- 搜索 -->
  10. <el-input v-model="query.blurry" size="small" clearable placeholder="输入角色名称搜索" prefix-icon="el-icon-search" style="width: 200px;" class="filter-item" @clear="crud.toQuery" @keyup.enter.native="crud.toQuery" />
  11. <date-range-picker v-model="blurryTime" class="date-item" />
  12. <rrOperation />
  13. </div>
  14. <crudOperation :permission="permission">
  15. <template v-slot:right>
  16. <el-button :loading="crud.downloadLoading" size="mini" :disabled="crud.selections.length === 0" @click="doExport(crud.selections)">
  17. <i class="iconfont icon-daochu" />
  18. 导出
  19. </el-button>
  20. </template>
  21. </crudOperation>
  22. </div>
  23. <div class="container-right">
  24. <span class="right-top-line" />
  25. <span class="left-bottom-line" />
  26. <!-- 表单渲染 -->
  27. <el-dialog append-to-body :close-on-click-modal="false" :before-close="crud.cancelCU" :visible.sync="crud.status.cu > 0" :title="crud.status.title" class="dialog-middle">
  28. <span class="dialog-right-top" />
  29. <span class="dialog-left-bottom" />
  30. <div class="setting-dialog">
  31. <el-form ref="form" :inline="true" :model="form" :rules="rules" size="small" label-width="85px">
  32. <el-form-item label="角色名称" prop="name">
  33. <el-input v-model="form.name" />
  34. </el-form-item>
  35. <el-form-item label="描述信息" prop="description">
  36. <el-input v-model="form.description" rows="5" type="textarea" />
  37. </el-form-item>
  38. </el-form>
  39. <div slot="footer" class="dialog-footer">
  40. <el-button type="text" @click="crud.cancelCU">取消</el-button>
  41. <el-button :loading="crud.status.cu === 2" type="primary" @click="crud.submitCU">确定</el-button>
  42. </div>
  43. </div>
  44. </el-dialog>
  45. <!-- table -->
  46. <el-table ref="table" v-loading="crud.loading" highlight-current-row style="width: 100%;" :data="crud.data" @selection-change="crud.selectionChangeHandler" @current-change="handleCurrentChange">
  47. <el-table-column type="selection" align="center" width="55" />
  48. <el-table-column prop="name" label="角色名称" />
  49. <!-- <el-table-column prop="dataScope" label="数据权限" /> -->
  50. <!-- <el-table-column prop="level" label="角色级别" /> -->
  51. <el-table-column :show-overflow-tooltip="true" prop="description" label="描述信息" />
  52. <el-table-column prop="users" label="人数" align="center">
  53. <template slot-scope="scope">
  54. <div>{{ scope.row.users.length }}</div>
  55. </template>
  56. </el-table-column>
  57. <el-table-column :show-overflow-tooltip="true" prop="createTime" label="创建日期">
  58. <template slot-scope="scope">
  59. <div>{{ scope.row.createTime | parseTime }}</div>
  60. </template>
  61. </el-table-column>
  62. <!-- <el-table-column v-if="checkPer(['admin','roles:edit','roles:del'])" label="操作" width="130px" align="center" fixed="right">
  63. <template slot-scope="scope">
  64. <udOperation
  65. v-if="scope.row.level >= level"
  66. :data="scope.row"
  67. :permission="permission"
  68. />
  69. </template>
  70. </el-table-column> -->
  71. </el-table>
  72. <!--分页组件-->
  73. <pagination />
  74. </div>
  75. </div>
  76. <div class="elect-cont-left role-cont-left" style="margin: 0 0 0 20px;">
  77. <div class="container-left">
  78. <span class="right-top-line" />
  79. <span class="left-bottom-line" />
  80. <div slot="header" class="tree-tab">
  81. <el-tooltip class="item" effect="dark" content="选择指定角色分配菜单" placement="top">
  82. <span :class="['role-span', {'role-tab-active': roleTabIndex == 0}]" @click="changeActiveTab(0)">菜单分配</span>
  83. </el-tooltip>
  84. <el-tooltip class="item" effect="dark" content="选择指定角色分配全宗范围" placement="top">
  85. <span :class="['role-span', {'role-tab-active': roleTabIndex == 1}]" @click="changeActiveTab(1)">全宗范围</span>
  86. </el-tooltip>
  87. <!-- v-permission="['admin','roles:edit']" -->
  88. <el-button
  89. :disabled="!showButton"
  90. :loading="treeLoading"
  91. size="mini"
  92. @click="saveMenu"
  93. >保存</el-button>
  94. </div>
  95. <el-tree
  96. v-show="roleTabIndex == 0"
  97. ref="menu"
  98. lazy
  99. :data="menus"
  100. :default-checked-keys="menuIds"
  101. :load="getMenuDatas"
  102. :props="defaultProps"
  103. check-strictly
  104. accordion
  105. show-checkbox
  106. node-key="id"
  107. @check="menuChange"
  108. />
  109. <!-- :load="getFondsDatas" -->
  110. <el-tree
  111. v-show="roleTabIndex == 1"
  112. ref="fonds"
  113. :data="fondsAllData"
  114. :default-checked-keys="fondIds"
  115. :props="defaultFondsProps"
  116. default-expand-all
  117. show-checkbox
  118. node-key="id"
  119. @check="fondsChange"
  120. >
  121. <template slot-scope="{ node }">
  122. <el-tooltip :content="node.label" placement="top-end" effect="dark">
  123. <span>{{ node.label }}</span>
  124. </el-tooltip>
  125. </template>
  126. </el-tree>
  127. </div>
  128. </div>
  129. </div>
  130. </div>
  131. </template>
  132. <script>
  133. import crudRoles from '@/api/system/role'
  134. import { FetchFondsAll } from '@/api/system/fonds'
  135. import { getMenusTree, getChild } from '@/api/system/menu'
  136. import CRUD, { presenter, header, form, crud } from '@crud/crud'
  137. import rrOperation from '@crud/RR.operation'
  138. import crudOperation from '@crud/CRUD.operation'
  139. import pagination from '@crud/Pagination'
  140. import DateRangePicker from '@/components/DateRangePicker'
  141. import { exportFile } from '@/utils/index'
  142. import qs from 'qs'
  143. import { mapGetters } from 'vuex'
  144. const defaultForm = { id: null, name: null, description: null, dataScope: null }
  145. export default {
  146. name: 'Role',
  147. components: { pagination, crudOperation, rrOperation, DateRangePicker },
  148. cruds() {
  149. return CRUD({ title: '角色', url: 'api/role/initRoleList', crudMethod: { ...crudRoles }, optShow: {
  150. add: true,
  151. edit: true,
  152. del: true,
  153. reset: true,
  154. download: false,
  155. group: false
  156. }})
  157. },
  158. mixins: [presenter(), header(), form(defaultForm), crud()],
  159. data() {
  160. return {
  161. defaultProps: { children: 'children', label: 'label', isLeaf: 'leaf' },
  162. defaultFondsProps: { children: 'children', label: 'fondsName' },
  163. // dateScopes: ['全部', '本级', '自定义'], level: 3,
  164. currentId: 0, treeLoading: false, showButton: false,
  165. menus: [], menuIds: [],
  166. fondDatas: [], fondIds: [],
  167. // depts: [], deptDatas: [], // 多选时使用
  168. permission: {
  169. add: ['admin', 'roles:add'],
  170. edit: ['admin', 'roles:edit'],
  171. del: ['admin', 'roles:del']
  172. },
  173. rules: {
  174. name: [
  175. { required: true, message: '请输入名称', trigger: 'blur' }
  176. ],
  177. permission: [
  178. { required: true, message: '请输入权限', trigger: 'blur' }
  179. ]
  180. },
  181. roleTabIndex: 0,
  182. blurryTime: null,
  183. fondsAllData: [],
  184. getFondsChecked: []
  185. }
  186. },
  187. computed: {
  188. ...mapGetters([
  189. 'baseApi'
  190. ])
  191. },
  192. created() {
  193. },
  194. mounted() {
  195. FetchFondsAll().then(res => {
  196. const resArr = []
  197. resArr.push({ fondsName: '全宗选择', id: 0, isChecked: false, children: [] })
  198. if (resArr[0].id === 0) {
  199. res.forEach(item => {
  200. resArr[0].children.push({
  201. fondsName: item.fondsName,
  202. id: item.id
  203. })
  204. })
  205. }
  206. this.fondsAllData = resArr
  207. console.log(this.fondsAllData)
  208. })
  209. },
  210. methods: {
  211. changeActiveTab(index) {
  212. this.roleTabIndex = index
  213. },
  214. getMenuDatas(node, resolve) {
  215. setTimeout(() => {
  216. getMenusTree(node.data.id ? node.data.id : 0).then(res => {
  217. resolve(res)
  218. })
  219. }, 100)
  220. },
  221. getFondsDatas(node, resolve) {
  222. if (node.level === 0) {
  223. return resolve([{ fondsName: '全宗选择', id: 0, isChecked: false }])
  224. }
  225. if (node.level > 1) return resolve([])
  226. resolve(this.fondsAllData)
  227. },
  228. [CRUD.HOOK.beforeRefresh]() {
  229. if (this.blurryTime) {
  230. this.crud.query.startTime = this.blurryTime[0]
  231. this.crud.query.endTime = this.blurryTime[1]
  232. }
  233. },
  234. [CRUD.HOOK.afterRefresh]() {
  235. this.$refs.menu.setCheckedKeys([])
  236. this.$refs.fonds.setCheckedKeys([])
  237. },
  238. // 新增前初始化部门信息
  239. [CRUD.HOOK.beforeToAdd](crud, form) {
  240. form.menus = null
  241. form.fondDatas = null
  242. },
  243. // 编辑前初始化自定义数据权限的部门信息
  244. [CRUD.HOOK.beforeToEdit](crud, form) {
  245. // 将角色的菜单清空,避免日志入库数据过长
  246. form.menus = null
  247. form.fondDatas = null
  248. },
  249. // 提交前做的操作
  250. [CRUD.HOOK.afterValidateCU](crud) {
  251. },
  252. // 触发单选
  253. handleCurrentChange(val) {
  254. if (val) {
  255. const _this = this
  256. // 清空菜单的选中
  257. this.$refs.menu.setCheckedKeys([])
  258. this.$refs.fonds.setCheckedKeys([])
  259. // 保存当前的角色id
  260. this.currentId = val.id
  261. console.log('val', val)
  262. console.log('this.currentId', this.currentId)
  263. // 初始化默认选中的key
  264. this.menuIds = []
  265. this.fondIds = []
  266. val.menus.forEach(function(data) {
  267. _this.menuIds.push(data.id)
  268. })
  269. if (val.fonds) {
  270. // if (this.fondsAllData.length === val.fonds.length) {
  271. // _this.fondIds.push(0)
  272. // }
  273. val.fonds.forEach(function(data) {
  274. _this.fondIds.push(data.id)
  275. })
  276. }
  277. this.showButton = true
  278. }
  279. },
  280. doExport(data) {
  281. crud.downloadLoading = true
  282. this.$confirm('此操作将导出所选数据' + '<span>你是否还要继续?</span>', '提示', {
  283. confirmButtonText: '继续',
  284. cancelButtonText: '取消',
  285. type: 'warning',
  286. dangerouslyUseHTMLString: true
  287. }).then(() => {
  288. const ids = []
  289. data.forEach(val => {
  290. ids.push(val.id)
  291. })
  292. const params = {
  293. 'roleIds': ids
  294. }
  295. exportFile(this.baseApi + '/api/role/exportRole?' + qs.stringify(params, { indices: false }))
  296. }).catch(() => {
  297. })
  298. },
  299. menuChange(menu) {
  300. // 获取该节点的所有子节点,id 包含自身
  301. getChild(menu.id).then(childIds => {
  302. console.log(childIds)
  303. // 判断是否在 menuIds 中,如果存在则删除,否则添加
  304. if (this.menuIds.indexOf(menu.id) !== -1) {
  305. for (let i = 0; i < childIds.length; i++) {
  306. const index = this.menuIds.indexOf(childIds[i])
  307. if (index !== -1) {
  308. this.menuIds.splice(index, 1)
  309. }
  310. }
  311. } else {
  312. for (let i = 0; i < childIds.length; i++) {
  313. const index = this.menuIds.indexOf(childIds[i])
  314. if (index === -1) {
  315. this.menuIds.push(childIds[i])
  316. }
  317. }
  318. }
  319. this.$refs.menu.setCheckedKeys(this.menuIds)
  320. })
  321. },
  322. fondsChange(fonds) {
  323. console.log(this.$refs.fonds.getCheckedKeys())
  324. this.fondIds = this.$refs.fonds.getCheckedKeys()
  325. // if (fonds.id === 0) {
  326. // fonds.isChecked = !fonds.isChecked
  327. // this.fondIds.push(fonds.id)
  328. // this.fondsAllData.forEach(childIds => {
  329. // if (fonds.isChecked) {
  330. // const index = this.fondIds.indexOf(childIds.id)
  331. // if (index !== -1) {
  332. // this.fondIds.splice(index, 1)
  333. // }
  334. // this.fondIds.push(childIds.id)
  335. // } else {
  336. // this.fondIds = []
  337. // }
  338. // })
  339. // } else {
  340. // if (this.fondIds.indexOf(fonds.id) !== -1) {
  341. // const index = this.fondIds.indexOf(fonds.id)
  342. // if (index !== -1) {
  343. // this.fondIds.splice(index, 1)
  344. // }
  345. // } else {
  346. // const index = this.fondIds.indexOf(fonds.id)
  347. // if (index === -1) {
  348. // this.fondIds.push(fonds.id)
  349. // }
  350. // }
  351. // }
  352. // this.$refs.fonds.setCheckedKeys(this.fondIds)
  353. },
  354. // 保存菜单
  355. saveMenu() {
  356. this.treeLoading = true
  357. if (this.roleTabIndex === 0) {
  358. const role = { id: this.currentId, menus: [] }
  359. // 得到已选中的 key 值
  360. this.menuIds.forEach(function(id) {
  361. const menu = { id: id }
  362. role.menus.push(menu)
  363. })
  364. crudRoles.editMenu(role).then(() => {
  365. this.$message({ message: '保存成功', type: 'success', offset: 8 })
  366. this.treeLoading = false
  367. this.update()
  368. }).catch(err => {
  369. this.treeLoading = false
  370. console.log(err.response.data.message)
  371. })
  372. } else {
  373. const params = { id: this.currentId, fonds: [] }
  374. // 得到已选中的 key 值
  375. this.fondIds.forEach(function(id, index) {
  376. if (id !== 0) {
  377. const fondsArray = { id: id }
  378. params.fonds.push(fondsArray)
  379. }
  380. })
  381. crudRoles.editFonds(params).then(() => {
  382. this.$message({ message: '保存成功', type: 'success', offset: 8 })
  383. this.treeLoading = false
  384. this.update()
  385. }).catch(err => {
  386. console.log(err.response.data.message)
  387. this.treeLoading = false
  388. })
  389. }
  390. },
  391. // 改变数据
  392. update() {
  393. // 无刷新更新 表格数据
  394. crudRoles.get(this.currentId).then(res => {
  395. for (let i = 0; i < this.crud.data.length; i++) {
  396. if (res.menus[i].id === this.crud.data[i].menus.id) {
  397. this.crud.data[i] = res
  398. break
  399. }
  400. if (res.fonds.id === this.crud.data[i].fonds.id) {
  401. this.crud.data[i] = res
  402. break
  403. }
  404. }
  405. })
  406. }
  407. }
  408. }
  409. </script>
  410. <style lang="scss" scoped>
  411. ::v-deep .el-tree .el-tree-node__children .el-tooltip{
  412. width: 150px;
  413. font-size: 14px;
  414. color: #545b65;
  415. white-space: nowrap;
  416. overflow: hidden;
  417. text-overflow: ellipsis;
  418. }
  419. </style>