| <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)  | 
|   | 
| const state = reactive({  | 
|   selectedRowKeys: [],  | 
|   loading: false,  | 
| });  | 
|   | 
| 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 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() {  | 
|   state.loading = true;  | 
|   | 
|   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;  | 
|   | 
|       state.loading = false;  | 
|     } 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');  | 
|   currentPage = 1;  | 
|   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" :loading="state.loading">  | 
|         <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>  |