| <script setup> | 
| import { getCurrentInstance, ref, computed, reactive } from 'vue'; | 
| import { useRouter } from "vue-router"; | 
| import { get, post, postBlob } from '@/utils/request.js' | 
| import { message, Modal } from 'ant-design-vue'; | 
| import { logout } from '@/config.js'; | 
| import EditView from './edit.vue' | 
| import { formatMessage } from '@/utils/localeUtils.js'; | 
| import { | 
|   DownOutlined, | 
| } from "@ant-design/icons-vue"; | 
| const context = getCurrentInstance()?.appContext.config.globalProperties; | 
|   | 
| const router = useRouter(); | 
|   | 
| const TABLE_KEY = 'table-user'; | 
| let currentPage = 1; | 
| let pageSize = 10; | 
| const searchInput = ref("") | 
| const editChild = ref(null) | 
|   | 
| let currentDept = ref(null); | 
| let tableData = ref([]); | 
| getPage(); | 
|   | 
| const columns = [ | 
|   { | 
|     title: formatMessage('db.sys_user.username', '账号'), | 
|     dataIndex: 'username', | 
|     width: 140, | 
|     ellipsis: true, | 
|   }, | 
|   { | 
|     title: formatMessage('db.sys_user.nickname', '昵称'), | 
|     dataIndex: 'nickname', | 
|     width: 140, | 
|     ellipsis: true, | 
|   }, | 
|   // { | 
|   //   title: formatMessage('db.sys_user.avatar', '头像'), | 
|   //   dataIndex: 'avatar', | 
|   //   width: 140, | 
|   //   ellipsis: true, | 
|   // }, | 
|   // { | 
|   //   title: formatMessage('db.sys_user.code', '工号'), | 
|   //   dataIndex: 'code', | 
|   //   width: 140, | 
|   //   ellipsis: true, | 
|   // }, | 
|   { | 
|     title: formatMessage('db.sys_user.sex', '性别'), | 
|     dataIndex: 'sex$', | 
|     width: 140, | 
|     ellipsis: true, | 
|   }, | 
|   { | 
|     title: formatMessage('db.sys_user.phone', '手机号'), | 
|     dataIndex: 'phone', | 
|     width: 140, | 
|     ellipsis: true, | 
|   }, | 
|   // { | 
|   //   title: formatMessage('db.sys_user.email', '邮箱'), | 
|   //   dataIndex: 'email', | 
|   //   width: 140, | 
|   //   ellipsis: true, | 
|   // }, | 
|   // { | 
|   //   title: formatMessage('db.sys_user.email_verified', '邮箱验证'), | 
|   //   dataIndex: 'emailVerified$', | 
|   //   width: 140, | 
|   //   ellipsis: true, | 
|   // }, | 
|   { | 
|     title: formatMessage('db.sys_user.dept_id', '部门'), | 
|     dataIndex: 'deptId$', | 
|     width: 140, | 
|     ellipsis: true, | 
|   }, | 
|   // { | 
|   //   title: formatMessage('db.sys_user.real_name', '真实姓名'), | 
|   //   dataIndex: 'realName', | 
|   //   width: 140, | 
|   //   ellipsis: true, | 
|   // }, | 
|   // { | 
|   //   title: formatMessage('db.sys_user.id_card', '身份证号'), | 
|   //   dataIndex: 'idCard', | 
|   //   width: 140, | 
|   //   ellipsis: true, | 
|   // }, | 
|   // { | 
|   //   title: formatMessage('db.sys_user.birthday', '出生日期'), | 
|   //   dataIndex: 'birthday', | 
|   //   width: 140, | 
|   //   ellipsis: true, | 
|   // }, | 
|   // { | 
|   //   title: formatMessage('db.sys_user.introduction', '个人简介'), | 
|   //   dataIndex: 'introduction', | 
|   //   width: 140, | 
|   //   ellipsis: true, | 
|   // }, | 
|   { | 
|     title: formatMessage('db.sys_user.status', '状态'), | 
|     dataIndex: 'status$', | 
|     width: 140, | 
|     ellipsis: true, | 
|   }, | 
|   // { | 
|   //   title: formatMessage('db.sys_user.create_time', '添加时间'), | 
|   //   dataIndex: 'createTime$', | 
|   //   width: 140, | 
|   //   ellipsis: true, | 
|   // }, | 
|   // { | 
|   //   title: formatMessage('db.sys_user.create_by', '添加人员'), | 
|   //   dataIndex: 'createBy$', | 
|   //   width: 140, | 
|   //   ellipsis: true, | 
|   // }, | 
|   // { | 
|   //   title: formatMessage('db.sys_user.update_time', '修改时间'), | 
|   //   dataIndex: 'updateTime$', | 
|   //   width: 140, | 
|   //   ellipsis: true, | 
|   // }, | 
|   // { | 
|   //   title: formatMessage('db.sys_user.update_by', '修改人员'), | 
|   //   dataIndex: 'updateBy$', | 
|   //   width: 140, | 
|   //   ellipsis: true, | 
|   // }, | 
|   // { | 
|   //   title: formatMessage('db.sys_user.memo', '备注'), | 
|   //   dataIndex: 'memo', | 
|   //   width: 140, | 
|   //   ellipsis: true, | 
|   // }, | 
|   | 
|   { | 
|     title: formatMessage('common.operation', '操作'), | 
|     name: 'oper', | 
|     dataIndex: 'oper', | 
|     key: 'oper', | 
|     width: 240, | 
|   }, | 
| ]; | 
|   | 
| const state = reactive({ | 
|   selectedRowKeys: [], | 
|   loading: false, | 
| }); | 
| const hasSelected = computed(() => state.selectedRowKeys.length > 0); | 
| const start = () => { | 
|   state.loading = true; | 
|   // ajax request after empty completing | 
|   setTimeout(() => { | 
|     state.loading = false; | 
|     state.selectedRowKeys = []; | 
|   }, 1000); | 
| }; | 
| const onSelectChange = selectedRowKeys => { | 
|   // console.log('selectedRowKeys changed: ', selectedRowKeys); | 
|   state.selectedRowKeys = selectedRowKeys; | 
| }; | 
|   | 
| function getPage() { | 
|   post('/api/user/page1', { | 
|     current: currentPage, | 
|     pageSize: pageSize, | 
|     condition: searchInput.value, | 
|     deptId: currentDept?.value?.id, | 
|   }).then((resp) => { | 
|     let result = resp.data; | 
|     if (result.code == 200) { | 
|       let data = result.data; | 
|       tableData.value = data; | 
|     } else if (result.code === 401) { | 
|       message.error(result.msg); | 
|       logout() | 
|     } else { | 
|       message.error(result.msg); | 
|     } | 
|   }) | 
| } | 
|   | 
| const handleEdit = (item) => { | 
|   editChild.value.open = true; | 
|   editChild.value.formData = item == null ? editChild.value.initFormData : JSON.parse(JSON.stringify(item)); | 
|   editChild.value.isSave = item == null; | 
| } | 
|   | 
| const handleDel = (rows) => { | 
|   Modal.confirm({ | 
|     title: formatMessage('page.delete', '删除'), | 
|     content: formatMessage('page.delete.confirm', '确定删除该项吗?'), | 
|     maskClosable: true, | 
|     onOk: async () => { | 
|       const hide = message.loading(formatMessage('common.loading', '请求中')); | 
|       try { | 
|         post('/api/user/remove/' + rows.map((row) => row.id).join(','), {}).then(resp => { | 
|           let result = resp.data; | 
|           if (result.code === 200) { | 
|             message.success(result.msg); | 
|           } else { | 
|             message.error(result.msg); | 
|           } | 
|           getPage() | 
|           hide() | 
|         }) | 
|       } catch (error) { | 
|         message.error(formatMessage('common.fail', '请求失败')); | 
|       } | 
|     }, | 
|   }); | 
| } | 
|   | 
| const handleExport = async (intl) => { | 
|   postBlob('/api/user/export', {}).then(result => { | 
|     const blob = new Blob([result.data], { type: 'application/vnd.ms-excel' }); | 
|     window.location.href = window.URL.createObjectURL(blob); | 
|     return true; | 
|   }) | 
| }; | 
|   | 
| let openResetPass = ref(false); | 
| let currentResetPass = ref(null); | 
| let newPassword = ref(""); | 
| const handleResetPass = (item) => { | 
|   openResetPass.value = true; | 
|   currentResetPass.value = item; | 
| } | 
|   | 
| const handleResetPassSubmit = (e) => { | 
|   if (newPassword.value == '') { | 
|     message.warning(formatMessage('login.rule.password', '请输入密码')) | 
|     return; | 
|   } | 
|   | 
|   post('/api/user/reset/pwd', { | 
|     id: currentResetPass.value.id, | 
|     password: newPassword.value | 
|   }).then((resp) => { | 
|     let result = resp.data; | 
|     if (result.code == 200) { | 
|       message.success(result.msg); | 
|       openResetPass.value = false; | 
|       currentResetPass.value = null; | 
|       newPassword.value = ""; | 
|     } else if (result.code === 401) { | 
|       message.error(result.msg); | 
|       logout() | 
|     } else { | 
|       message.error(result.msg); | 
|     } | 
|   }) | 
| } | 
|   | 
| let openAssignRole = ref(false); | 
| let currentAssignRole = ref(null); | 
| let assignRoleData = ref([]); | 
| let currentCheckRole = ref([]); | 
| const handleAssignRole = (item) => { | 
|   openAssignRole.value = true; | 
|   currentAssignRole.value = item; | 
|   currentCheckRole.value = item.userRoleIds; | 
| } | 
|   | 
| const handleAssignRoleSubmit = (e) => { | 
|   post('/api/user/update', { | 
|     id: currentAssignRole.value.id, | 
|     roleIds: currentCheckRole.value, | 
|   }).then((resp) => { | 
|     let result = resp.data; | 
|     if (result.code == 200) { | 
|       message.success(result.msg); | 
|       openAssignRole.value = false; | 
|       currentAssignRole.value = null; | 
|       currentCheckRole.value = []; | 
|       getPage() | 
|     } else if (result.code === 401) { | 
|       message.error(result.msg); | 
|       logout() | 
|     } else { | 
|       message.error(result.msg); | 
|     } | 
|   }) | 
| } | 
|   | 
| getAssignRoleData(); | 
| function getAssignRoleData() { | 
|   post('/api/role/query', {}).then((resp) => { | 
|     let result = resp.data; | 
|     if (result.code == 200) { | 
|       let data = result.data; | 
|       assignRoleData.value = data; | 
|     } else if (result.code === 401) { | 
|       message.error(result.msg); | 
|       logout() | 
|     } else { | 
|       message.error(result.msg); | 
|     } | 
|   }) | 
| } | 
|   | 
| const onSearch = () => { | 
|   // console.log('search'); | 
|   getPage() | 
| } | 
|   | 
| const onPageChange = (page, size) => { | 
|   currentPage = page; | 
|   pageSize = size; | 
|   getPage(); | 
| } | 
|   | 
| function handleTableReload(value) { | 
|   getPage() | 
| } | 
|   | 
| let deptExpandedKeys = ref([]); | 
| let deptData = ref([]); | 
| let searchDept = ref(""); | 
| getDeptData() | 
| function getDeptData() { | 
|   post('/api/dept/tree', { | 
|     current: currentPage, | 
|     pageSize: pageSize, | 
|     condition: searchDept.value | 
|   }).then((resp) => { | 
|     let result = resp.data; | 
|     if (result.code == 200) { | 
|       let data = result.data; | 
|       deptData.value = [{ | 
|         id: null, | 
|         name: '全部', | 
|         children: data | 
|       }] | 
|     } else if (result.code === 401) { | 
|       message.error(result.msg); | 
|       logout() | 
|     } else { | 
|       message.error(result.msg); | 
|     } | 
|   | 
|     deptExpandedKeys.value = ['0-0'] | 
|   }) | 
| } | 
|   | 
| const handleDeptSelected = (selectedKeys, e) => { | 
|   currentDept.value = { | 
|     id: e.node.id, | 
|     name: e.node.name, | 
|   }; | 
|   getPage() | 
| } | 
|   | 
| const handleSearchDept = (e) => { | 
|   getDeptData() | 
| } | 
|   | 
| </script> | 
|   | 
| <script> | 
| export default { | 
|   name: '用户管理' | 
| } | 
| </script> | 
|   | 
| <template> | 
|   <div style="display: flex;"> | 
|     <a-card :title="formatMessage('common.dept', '部门')" style="flex: 3;margin-right: 30px;"> | 
|       <a-input v-model:value="searchDept" @change="handleSearchDept" :placeholder="formatMessage('page.input', '请输入')" | 
|         style="margin-bottom: 8px" /> | 
|       <a-tree v-model:expandedKeys="deptExpandedKeys" @select="handleDeptSelected" :tree-data="deptData" blockNode> | 
|         <template #title="{ name }"> | 
|           <span>{{ name }}</span> | 
|         </template> | 
|       </a-tree> | 
|     </a-card> | 
|   | 
|     <a-card style="flex: 10;"> | 
|       <EditView ref="editChild" @tableReload="handleTableReload" /> | 
|       <div class="table-header"> | 
|         <a-input-search v-model:value="searchInput" :placeholder="formatMessage('page.input', '请输入')" | 
|           style="width: 200px;" @search="onSearch" /> | 
|         <div class="table-header-right"> | 
|           <a-button @click="handleEdit(null)" type="primary">{{ formatMessage('page.add', '添加') }}</a-button> | 
|           <a-button @click="handleExport">{{ formatMessage('page.export', '导出') }}</a-button> | 
|         </div> | 
|       </div> | 
|       <a-table :row-selection="{ selectedRowKeys: state.selectedRowKeys, onChange: onSelectChange }" | 
|         :data-source="tableData.records" :defaultExpandAllRows="false" :key="TABLE_KEY" rowKey="id" | 
|         :pagination="{ total: tableData.total, onChange: onPageChange }" | 
|         :scroll="{ y: 768, scrollToFirstRowOnChange: true }" :columns="columns"> | 
|         <template #bodyCell="{ column, text, record }"> | 
|           <template v-if="column.dataIndex === 'oper'"> | 
|             <div style="display: flex;justify-content: space-evenly;"> | 
|               <a-button type="link" primary> <a-dropdown> | 
|                   <a class="ant-dropdown-link" @click.prevent> | 
|                     {{ formatMessage('common.operation', '操作') }} | 
|                     <DownOutlined /> | 
|                   </a> | 
|                   <template #overlay> | 
|                     <a-menu> | 
|                       <a-menu-item> | 
|                         <a-button type="link" primary @click="handleResetPass(record)"> | 
|                           {{ formatMessage('page.reset.pwd', '重置密码') }} | 
|                         </a-button> | 
|                       </a-menu-item> | 
|                       <a-menu-item> | 
|                         <a-button type="link" primary @click="handleAssignRole(record)"> | 
|                           {{ formatMessage('page.assign.role', '分配角色') }} | 
|                         </a-button> | 
|                       </a-menu-item> | 
|                     </a-menu> | 
|                   </template> | 
|                 </a-dropdown> | 
|               </a-button> | 
|               <a-button type="link" primary @click="handleEdit(record)"> | 
|                 {{ formatMessage('page.edit', '编辑') }} | 
|               </a-button> | 
|               <a-button type="link" danger @click="handleDel([record])"> | 
|                 {{ formatMessage('page.delete', '删除') }} | 
|               </a-button> | 
|             </div> | 
|           </template> | 
|         </template> | 
|       </a-table> | 
|     </a-card> | 
|   | 
|     <a-modal v-model:open="openResetPass" :title="formatMessage('page.reset.pwd', '重置密码')" @ok="handleResetPassSubmit"> | 
|       <a-form style="display: flex;justify-content: center;flex-wrap: wrap;" autocomplete="off"> | 
|         <a-form-item :label="formatMessage('personal.security.new.pwd', '新密码')"> | 
|           <a-input v-model:value="newPassword" /> | 
|         </a-form-item> | 
|       </a-form> | 
|     </a-modal> | 
|   | 
|     <a-modal v-model:open="openAssignRole" :title="formatMessage('page.assign.role', '分配角色')" | 
|       @ok="handleAssignRoleSubmit"> | 
|       <a-form style="display: flex;justify-content: center;flex-wrap: wrap;" autocomplete="off"> | 
|         <a-form-item :label="formatMessage('page.assign.role', '角色')"> | 
|           <a-select v-model:value="currentCheckRole" :options="assignRoleData" mode="multiple" style="width: 380px;"> | 
|           </a-select> | 
|         </a-form-item> | 
|       </a-form> | 
|     </a-modal> | 
|   </div> | 
| </template> | 
|   | 
| <style></style> |