User.vue 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. <script setup lang="tsx">
  2. import { reactive, ref, unref } from 'vue'
  3. import {
  4. getUserRole,
  5. addUserRole,
  6. putUserRole,
  7. delUserRole,
  8. putUserRoleStatus
  9. } from '@/api/system/department'
  10. import { AddAdmins } from '@/api/system/department/types'
  11. import { useTable } from '@/hooks/web/useTable'
  12. import { useI18n } from '@/hooks/web/useI18n'
  13. import { Table, TableColumn } from '@/components/Table'
  14. import { ElMessage, ElMessageBox, ElSwitch, ElTag, ElDivider } from 'element-plus'
  15. import { Search } from '@/components/Search'
  16. import { FormSchema } from '@/components/Form'
  17. import { ContentWrap } from '@/components/ContentWrap'
  18. import Write from './components/Write.vue'
  19. import Detail from './components/Detail.vue'
  20. import { Dialog } from '@/components/Dialog'
  21. import { BaseButton } from '@/components/Button'
  22. const { t } = useI18n()
  23. const { tableRegister, tableState, tableMethods } = useTable({
  24. fetchDataApi: async () => {
  25. const res = await getUserRole({
  26. ...searchParams.value,
  27. page: unref(currentPage) || 1,
  28. limit: unref(pageSize) || 10
  29. })
  30. return {
  31. list:
  32. res.data.list.map((ee) => {
  33. ee.isStatus = ee.status === 1 ? true : false
  34. ee.roles = ee.roles.split(',')
  35. return ee
  36. }) || [],
  37. total: res.data.count || 0
  38. }
  39. }
  40. })
  41. const { dataList, loading, total, currentPage, pageSize } = tableState
  42. const { getList } = tableMethods
  43. const tableColumns = reactive<TableColumn[]>([
  44. {
  45. field: 'id',
  46. label: 'ID',
  47. width: 80
  48. },
  49. {
  50. field: 'account',
  51. label: '账号',
  52. width: 100
  53. },
  54. {
  55. field: 'phone',
  56. label: '电话',
  57. width: 120
  58. },
  59. {
  60. field: 'real_name',
  61. label: '姓名',
  62. width: 120
  63. },
  64. {
  65. field: 'roles',
  66. label: '权限',
  67. minWidth: 80,
  68. slots: {
  69. default: (data: any) => {
  70. return (
  71. <>
  72. {data.row.roles.map((item) => (
  73. <ElTag class={'mr-2'}>{item}</ElTag>
  74. ))}
  75. </>
  76. )
  77. }
  78. }
  79. },
  80. {
  81. field: '_add_time',
  82. label: '创建时间',
  83. width: 160
  84. },
  85. {
  86. field: 'status',
  87. label: t('menu.status'),
  88. align: 'center',
  89. headerAlign: 'center',
  90. width: 80,
  91. slots: {
  92. default: (data: any) => {
  93. return (
  94. <>
  95. <ElSwitch
  96. inlinePrompt
  97. activeText="启用"
  98. inactiveText="禁用"
  99. v-model={data.row.isStatus}
  100. onChange={() => putUserStatus(data.row)}
  101. ></ElSwitch>
  102. </>
  103. )
  104. }
  105. }
  106. },
  107. {
  108. field: 'action',
  109. label: t('userDemo.action'),
  110. width: 160,
  111. fixed: 'right',
  112. align: 'center',
  113. headerAlign: 'center',
  114. slots: {
  115. default: (data: any) => {
  116. const row = data.row
  117. return (
  118. <>
  119. <BaseButton link size="small" type="primary" onClick={() => action(row, 'edit')}>
  120. {t('exampleDemo.edit')}
  121. </BaseButton>
  122. <ElDivider direction="vertical" />
  123. <BaseButton link size="small" type="success" onClick={() => action(row, 'detail')}>
  124. {t('exampleDemo.detail')}
  125. </BaseButton>
  126. <ElDivider direction="vertical" />
  127. <BaseButton link size="small" type="danger" onClick={() => delAction(row)}>
  128. {t('exampleDemo.del')}
  129. </BaseButton>
  130. </>
  131. )
  132. }
  133. }
  134. }
  135. ])
  136. const searchSchema = reactive<FormSchema[]>([
  137. {
  138. field: 'status',
  139. label: t('menu.status'),
  140. component: 'Select',
  141. componentProps: {
  142. options: [
  143. {
  144. label: '全部',
  145. value: ''
  146. },
  147. {
  148. label: t('userDemo.disable'),
  149. value: 0
  150. },
  151. {
  152. label: t('userDemo.enable'),
  153. value: 1
  154. }
  155. ]
  156. }
  157. },
  158. {
  159. field: 'name',
  160. label: '搜索',
  161. component: 'Input',
  162. value: '',
  163. componentProps: {
  164. placeholder: '请输入姓名或者账号'
  165. }
  166. }
  167. ])
  168. const searchParams = ref<{ status: number | string; name?: string }>({ status: '', name: '' })
  169. const setSearchParams = (data: any) => {
  170. searchParams.value = data
  171. getList()
  172. }
  173. const dialogVisible = ref(false)
  174. const dialogTitle = ref('')
  175. const currentRow = ref()
  176. const actionType = ref('')
  177. const writeRef = ref<ComponentRef<typeof Write>>()
  178. const saveLoading = ref(false)
  179. const action = (row: any, type: string) => {
  180. dialogTitle.value = t(type === 'edit' ? 'exampleDemo.edit' : 'exampleDemo.detail')
  181. actionType.value = type
  182. currentRow.value = {
  183. id: row.id,
  184. account: row.account, //账号
  185. real_name: row.real_name, //名字
  186. pwd: '',
  187. conf_pwd: '',
  188. phone: row.phone, //手机号
  189. roles: row.roles, //角色数组
  190. status: row.status === 1 ? true : false //是否启用
  191. }
  192. dialogVisible.value = true
  193. }
  194. const putUserStatus = (row: any) => {
  195. putUserRoleStatus({ id: row.id, status: row.status === 1 ? 0 : 1 }).then(() => {
  196. getList()
  197. })
  198. }
  199. const AddAction = () => {
  200. dialogTitle.value = t('exampleDemo.add')
  201. currentRow.value = undefined
  202. dialogVisible.value = true
  203. actionType.value = ''
  204. }
  205. const delAction = async (row: any) => {
  206. ElMessageBox.confirm('删除后无法恢复,是否删除?', {
  207. confirmButtonText: '删除',
  208. cancelButtonText: '取消',
  209. type: 'warning'
  210. })
  211. .then(async () => {
  212. await delUserRole({ id: row.id })
  213. await getList()
  214. ElMessage({
  215. showClose: true,
  216. message: '删除',
  217. type: 'success'
  218. })
  219. })
  220. .catch(() => {})
  221. }
  222. const save = async () => {
  223. const write = unref(writeRef)
  224. const formData = await write?.submit()
  225. if (formData) {
  226. saveLoading.value = true
  227. const data: AddAdmins = {
  228. id: formData.id || '',
  229. account: formData.account, //账号
  230. pwd: formData.pwd, //密码
  231. conf_pwd: formData.conf_pwd, //确认密码
  232. real_name: formData.real_name, //名字
  233. phone: formData.phone, //手机号
  234. roles: formData.roles, //角色数组
  235. status: formData.status ? 1 : 0 //是否启用
  236. }
  237. try {
  238. let res: any = {}
  239. if (actionType.value === 'edit') {
  240. res = await putUserRole(data)
  241. } else if (actionType.value === '') {
  242. res = await addUserRole(data)
  243. }
  244. if (res?.status == 200) {
  245. ElMessage({
  246. showClose: true,
  247. message: '保存成功',
  248. type: 'success'
  249. })
  250. getList()
  251. dialogVisible.value = false
  252. }
  253. } catch (error) {
  254. console.log(error)
  255. } finally {
  256. saveLoading.value = false
  257. }
  258. }
  259. }
  260. </script>
  261. <template>
  262. <ContentWrap>
  263. <Search :schema="searchSchema" @reset="setSearchParams" @search="setSearchParams" />
  264. <div class="mb-10px">
  265. <BaseButton type="primary" @click="AddAction">{{ t('exampleDemo.add') }}</BaseButton>
  266. </div>
  267. <Table
  268. v-model:current-page="currentPage"
  269. v-model:page-size="pageSize"
  270. :columns="tableColumns"
  271. default-expand-all
  272. node-key="id"
  273. stripe
  274. :data="dataList"
  275. :loading="loading"
  276. @register="tableRegister"
  277. :pagination="{
  278. total
  279. }"
  280. />
  281. </ContentWrap>
  282. <Dialog v-model="dialogVisible" :title="dialogTitle" width="60%">
  283. <Write v-if="actionType !== 'detail'" ref="writeRef" :current-row="currentRow" />
  284. <Detail v-if="actionType === 'detail'" :current-row="currentRow" />
  285. <template #footer>
  286. <BaseButton
  287. v-if="actionType !== 'detail'"
  288. type="primary"
  289. :loading="saveLoading"
  290. @click="save"
  291. >
  292. {{ t('exampleDemo.save') }}
  293. </BaseButton>
  294. <BaseButton @click="dialogVisible = false">{{ t('dialogDemo.close') }}</BaseButton>
  295. </template>
  296. </Dialog>
  297. </template>