Roles.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. <script setup lang="ts">
  2. import {
  3. User_Power_List,
  4. User_Sys_List,
  5. User_Power_Get,
  6. User_Power_Add,
  7. User_Power_Del,
  8. User_Power_Edit,
  9. User_Power_Edit_Menu
  10. } from '@/api/role/index'
  11. import { GlobalStore } from '@/stores/index'
  12. import { ref, reactive, nextTick } from 'vue'
  13. import Drawer from '@/components/Drawer/index.vue'
  14. import Dialog from '@/components/dialog/Dialog.vue'
  15. import { ElTree } from 'element-plus'
  16. import TableBase from '@/components/TableBase/index.vue'
  17. import type { FormInstance, FormRules } from 'element-plus'
  18. import type { ColumnProps } from '@/components/TableBase/interface/index'
  19. import { Edit, Delete, Operation } from '@element-plus/icons-vue'
  20. import { ElNotification, ElMessageBox, ElMessage } from 'element-plus'
  21. interface InSys {
  22. T_sys: string
  23. T_name: string
  24. children: any
  25. checkList: string[]
  26. }
  27. const menuMap = new Map()
  28. const isNew = ref(true)
  29. let currentVal: any = {}
  30. const SysList = ref<InSys[]>([])
  31. const globalStore = GlobalStore()
  32. const formLabelWidth = ref('100px')
  33. const ruleFormRef = ref<FormInstance>()
  34. const dialog = ref<InstanceType<typeof Dialog> | null>(null)
  35. const drawerRef = ref<InstanceType<typeof Drawer> | null>(null)
  36. const TableRef = ref<InstanceType<typeof TableBase> | null>(null)
  37. const initParam = {
  38. User_tokey: globalStore.GET_User_tokey,
  39. T_name: ''
  40. }
  41. const DialogOpen = async (row: any) => {
  42. currentVal = row
  43. await getSysList()
  44. dialog.value?.DialogOpen()
  45. }
  46. const columns: ColumnProps[] = [
  47. { type: 'index', label: '#', width: 80 },
  48. { prop: 'T_name', label: '姓名' },
  49. { prop: 'T_id', label: 'id' },
  50. { prop: 'operation', label: '操作', width: 200, fixed: 'right' }
  51. ]
  52. const getSysList = async () => {
  53. const { Data } = await User_Sys_List({ User_tokey: globalStore.GET_User_tokey })
  54. SysList.value = Data as InSys[]
  55. const promises = []
  56. for (let item of SysList.value) {
  57. promises.push(getMenuList(item.T_sys))
  58. }
  59. Promise.all(promises).then(res => {
  60. const menuListTemporary: any[] = []
  61. res.forEach((item: any) => {
  62. const { Children, T_permission } = item.Data.Menu[0]
  63. item.Data.Menu[0].children = Children
  64. if (['/account', 'mangage', '/salary', '/stock'].includes(T_permission)) {
  65. item.Data.Menu[0].father = true
  66. menuMap.set(T_permission, { code: item.code, children: [] })
  67. }
  68. if (item.Data.Menu_checked) {
  69. getPermissionArr(item.Data)
  70. }
  71. menuListTemporary.push(item.Data.Menu[0])
  72. })
  73. menuList.value = menuListTemporary
  74. setCheckedTreeKeys(permissionArr.value)
  75. console.log(permissionArr.value)
  76. })
  77. }
  78. const getMenuList = async (code: string) => {
  79. const res: any = await User_Power_Get({ User_tokey: globalStore.GET_User_tokey, T_code: code, T_id: currentVal.T_id })
  80. return {
  81. code,
  82. ...res
  83. }
  84. }
  85. const permissionArr = ref<string[]>([])
  86. const getPermissionArr = (menu: any) => {
  87. const { Menu, Menu_checked } = menu
  88. const { Children, T_permission } = Menu[0]
  89. getCurrentFlatMenu(Children, Menu_checked, T_permission)
  90. }
  91. const getCurrentFlatMenu = (children: any[], arr: number[], permission: string) => {
  92. const fatherMenu = menuMap.get(permission)
  93. children.forEach((item: any) => {
  94. const index = arr.findIndex((num: any) => num === item.Id)
  95. if (item.Children) {
  96. getCurrentFlatMenu(item.Children, arr, permission)
  97. }
  98. if (index !== -1 && !item.Children) {
  99. permissionArr.value.push(item.T_permission)
  100. fatherMenu.children.push(item)
  101. }
  102. })
  103. }
  104. const setCheckedTreeKeys = (arr: string[]) => treeRef.value?.setCheckedKeys(arr, true)
  105. // 添加角色
  106. type Fn = () => void
  107. const form = reactive({
  108. name: '',
  109. id: ''
  110. })
  111. const rules = reactive<FormRules>({
  112. name: [{ required: true, message: '请输入角色名称', trigger: 'blur' }]
  113. })
  114. const callbackDrawer = (done: Fn) => {
  115. resetForm(ruleFormRef.value)
  116. done()
  117. }
  118. const openDrawer = (type: string, row?: any) => {
  119. isNew.value = type === 'new' ? true : false
  120. nextTick(() => {
  121. !isNew.value && ((form.name = row.T_name), (form.id = row.T_id))
  122. })
  123. drawerRef.value?.openDrawer()
  124. }
  125. const resetForm = (formEl: FormInstance | undefined) => {
  126. if (!formEl) return
  127. formEl.resetFields()
  128. }
  129. const AddUserName = (formEl: FormInstance | undefined) => {
  130. if (!formEl) return
  131. formEl.validate(async valid => {
  132. if (valid) {
  133. let res: any = {}
  134. if (isNew.value) {
  135. res = await User_Power_Add({ User_tokey: globalStore.GET_User_tokey, T_name: form.name })
  136. } else {
  137. res = await User_Power_Edit({ User_tokey: globalStore.GET_User_tokey, T_name: form.name, T_id: form.id })
  138. }
  139. if (res.Code === 200) {
  140. ElNotification.success({
  141. title: '添加角色',
  142. message: '添加成功!',
  143. position: 'bottom-right'
  144. })
  145. nextTick(() => {
  146. drawerRef.value?.closeDrawer()
  147. TableRef.value?.getTableList()
  148. resetForm(ruleFormRef.value)
  149. isNew.value = true
  150. })
  151. }
  152. } else {
  153. return false
  154. }
  155. })
  156. }
  157. // 删除
  158. const UserDelete = (row: any) => {
  159. ElMessageBox.confirm('您确定要删除吗?', '警告', {
  160. confirmButtonText: '确定',
  161. cancelButtonText: '取消',
  162. type: 'warning'
  163. })
  164. .then(async () => {
  165. const res: any = await User_Power_Del({ User_tokey: globalStore.GET_User_tokey, T_id: row.T_id })
  166. if (res.Code === 200) {
  167. ElMessage.success('删除成功!')
  168. nextTick(() => {
  169. TableRef.value?.getTableList()
  170. })
  171. }
  172. })
  173. .catch(() => {
  174. ElMessage.warning('取消成功!')
  175. })
  176. }
  177. // 搜索
  178. const search = ref('')
  179. const searchHandle = () => {
  180. initParam.T_name = search.value
  181. TableRef.value?.searchTable()
  182. }
  183. // 重写角色权限
  184. const treeRef = ref<InstanceType<typeof ElTree>>()
  185. const menuList = ref<any[]>([])
  186. /**
  187. * 返回拼接的 M + Id
  188. * @param children 菜单数组
  189. */
  190. const getMontageRole = (children: any[]) => {
  191. let result = ''
  192. const getChildIds = (node: any) => {
  193. if (!node.Children) {
  194. return `M${node.Id}|`
  195. }
  196. let ids = node.Children.map((child: any) => {
  197. return getChildIds(child)
  198. })
  199. return `M${node.Id}|${ids.join('')}`
  200. }
  201. children.forEach((item: any) => {
  202. result += getChildIds(item)
  203. })
  204. return result
  205. }
  206. /**
  207. * 提交
  208. */
  209. const append = async (data: any) => {
  210. const currentMenu = menuMap.get(data.T_permission)
  211. console.log(menuMap)
  212. const { code, children } = currentMenu
  213. let T_menu = getMontageRole(children)
  214. console.log(children)
  215. const params = {
  216. User_tokey: globalStore.GET_User_tokey,
  217. T_id: currentVal.T_id,
  218. T_code: code,
  219. T_menu
  220. }
  221. // const res = await User_Power_Edit_Menu(params)
  222. // if (res.Code === 200) {
  223. // ElMessage.success('修改成功!')
  224. // // dialog.value?.DialogClose()
  225. // }
  226. }
  227. let fatherData: any = {}
  228. const checkChange = (data: any, check: boolean) => {
  229. let fatherData = menuMap.get(data.T_permission)
  230. if (['/base'].includes(data.T_permission)) {
  231. fatherData = menuMap.get('/stock')
  232. }
  233. if (check) {
  234. console.log(data, fatherData)
  235. }
  236. // console.log(data, check)
  237. // if (father) {
  238. // fatherData = data
  239. // fatherCheckHandle(data.Children, father, check)
  240. // // console.log(father)
  241. // return
  242. // }
  243. // const prevFather = menuMap.get(fatherData.T_permission)
  244. // console.log(fatherData, prevFather)
  245. // const children = prevFather?.children
  246. // // console.log(children)
  247. // if (check) {
  248. // console.log(children)
  249. // prevFather.children.push(data)
  250. // }
  251. // if (!father && !check) {
  252. // const index = children.findIndex((item: any) => item.T_permission === data.T_permission)
  253. // if (index !== -1) {
  254. // console.log('-1')
  255. // children.splice(index, 1)
  256. // }
  257. // }
  258. }
  259. /**
  260. * 处理点击父级 tree 时的处理
  261. */
  262. const fatherCheckHandle = (children: any[], father: any, check: boolean) => {
  263. if (check) {
  264. children.forEach((item: any) => {
  265. if (item.Children) {
  266. if (father.children.findIndex((child: any) => item.T_permission === child.T_permission) === -1) {
  267. father.children.push(item)
  268. fatherCheckHandle(item.Children, father, check)
  269. }
  270. } else {
  271. if (father.children.findIndex((child: any) => item.T_permission === child.T_permission) === -1) {
  272. console.log('push3')
  273. father.children.push(item)
  274. }
  275. }
  276. })
  277. }
  278. }
  279. /**
  280. * dialog 关闭回调
  281. */
  282. const dialogCloseCallback = () => {
  283. nextTick(() => {
  284. menuMap.clear()
  285. permissionArr.value = []
  286. fatherData = {}
  287. })
  288. }
  289. </script>
  290. <template>
  291. <div class="roles">
  292. <TableBase ref="TableRef" :columns="columns" :requestApi="User_Power_List" :initParam="initParam">
  293. <template #table-header>
  294. <div class="input-suffix">
  295. <el-row :gutter="20" style="margin-bottom: 0">
  296. <el-col :span="12">
  297. <span class="inline-flex items-center">角色名:</span>
  298. <el-input v-model="search" type="text" class="w-50 m-2" />
  299. <el-button type="primary" @click="searchHandle">搜索</el-button>
  300. </el-col>
  301. <el-col :span="6" :offset="6"><el-button type="primary" @click="openDrawer('new')">添加</el-button></el-col>
  302. </el-row>
  303. </div>
  304. </template>
  305. <template #right="{ row }">
  306. <el-button link type="primary" size="small" :icon="Edit" @click="openDrawer('edit', row)">编辑</el-button>
  307. <el-button link type="success" size="small" :icon="Operation" @click="DialogOpen(row)">权限</el-button>
  308. <el-button link type="danger" size="small" :icon="Delete" @click="UserDelete(row)">删除</el-button>
  309. </template>
  310. </TableBase>
  311. <Dialog ref="dialog" width="50%" :handleClose="dialogCloseCallback">
  312. <template #header>
  313. <h3>编辑权限</h3>
  314. </template>
  315. <transition appear name="fade" mode="out-in">
  316. <el-tree
  317. ref="treeRef"
  318. :data="menuList"
  319. show-checkbox
  320. node-key="T_permission"
  321. :expand-on-click-node="false"
  322. :props="{ label: 'T_name', children: 'Children' }"
  323. @check-change="checkChange"
  324. >
  325. <template #default="{ data }">
  326. <div
  327. class="custom-tree-node"
  328. :style="{ 'border-bottom': data.Children && data.father ? ' 1px solid #ddd' : '' }"
  329. >
  330. <span>{{ data.T_name }}</span>
  331. <span v-if="data.Children && data.father">
  332. <el-button type="primary" size="small" @click="append(data)">提交</el-button>
  333. </span>
  334. </div>
  335. </template>
  336. <template #empty>
  337. <el-empty></el-empty>
  338. </template>
  339. </el-tree>
  340. </transition>
  341. </Dialog>
  342. <Drawer ref="drawerRef" :handleClose="callbackDrawer">
  343. <template #header="{ params }">
  344. <h4 :id="params.titleId" :class="params.titleClass">{{ isNew ? '添加' : '编辑' }} - 角色</h4>
  345. </template>
  346. <el-form ref="ruleFormRef" :model="form" :rules="rules">
  347. <el-form-item label="角色名:" :label-width="formLabelWidth" prop="name">
  348. <el-input v-model="form.name" type="text" autocomplete="off" placeholder="请输入角色名称" />
  349. </el-form-item>
  350. <el-form-item :label-width="formLabelWidth">
  351. <el-button v-if="isNew" color="#626aef" @click="AddUserName(ruleFormRef)">添加</el-button>
  352. <el-button v-else color="#626aef" @click="AddUserName(ruleFormRef)">修改</el-button>
  353. </el-form-item>
  354. </el-form>
  355. </Drawer>
  356. </div>
  357. </template>
  358. <style scoped lang="scss">
  359. @import './index.scss';
  360. @import '@/styles/var.scss';
  361. .roles {
  362. @include f-direction;
  363. }
  364. /* fade */
  365. .fade-leave-active,
  366. .fade-enter-active {
  367. transition: all 1s;
  368. }
  369. .fade-enter-from {
  370. opacity: 0;
  371. transition: all 1s;
  372. transform: translateY(-60px);
  373. }
  374. .fade-leave-to {
  375. opacity: 0;
  376. transition: all 1s;
  377. transform: translateY(60px);
  378. }
  379. </style>