2023-11-21 11:26:54 +08:00

723 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<!-- Query -->
<a-form ref="queryFormRef" :model="queryForm" layout="inline">
<a-form-item field="dept_name" label="部门名称">
<a-input v-model="queryForm.dept_name" placeholder="请输入部门名称" @press-enter="handleQuery" />
</a-form-item>
<a-form-item field="access" label="用户昵称">
<a-input v-model="queryForm.nick_name" placeholder="请输入昵称" @press-enter="handleQuery" />
</a-form-item>
<a-form-item field="phone" label="手机号码">
<a-input v-model="queryForm.phone" placeholder="请输入用户手机号" @press-enter="handleQuery" />
</a-form-item>
<a-form-item field="role_status" label="用户状态">
<a-select
v-model="queryForm.role_status"
placeholder="请选择用户状态"
:style="{ width: '205px' }"
>
<!-- 1:正常 2:审核中 3:审核失败) -->
<a-option :value="1">正常</a-option>
<a-option :value="2">审核中</a-option>
<a-option :value="3">审核失败</a-option>
</a-select>
</a-form-item>
<!-- <a-divider direction="vertical" :style="{ height: '30px' }" /> -->
<a-form-item field="is_deleted" label="删除状态">
<a-select
v-model="queryForm.is_deleted"
placeholder="请选择删除状态"
:style="{ width: '182px' }"
>
<!-- 1:正常 2:审核中 3:审核失败) -->
<a-option :value="1">是</a-option>
<a-option :value="0">否</a-option>
</a-select>
</a-form-item>
<a-form-item field="is_disabled" label="禁用状态">
<a-select
v-model="queryForm.is_disabled"
placeholder="请选择禁用状态"
:style="{ width: '182px' }"
>
<!-- 1:正常 2:审核中 3:审核失败) -->
<a-option :value="1">是</a-option>
<a-option :value="0">否</a-option>
</a-select>
</a-form-item>
<a-form-item class="form-action">
<a-space size="medium">
<a-button type="primary" @click="handleQuery"><icon-search /> 搜索</a-button>
<a-button @click="handleResetQuery"><icon-loop /> 重置</a-button>
</a-space>
</a-form-item>
</a-form>
<!-- divider -->
<a-divider />
<!-- Table -->
<a-row>
<a-col :span="4">
<!-- tree组件只在组件第一次渲染时展开此处等待数据加载完成再渲染组件 -->
<tree-dept v-if="treeDeptData" ref="treeRef_parent" :data="treeDeptData" @nodeClick="getSysUserInfo" :selectedKeys="queryForm.dept_id" />
</a-col>
<a-col :span="20">
<!-- Action -->
<a-space class="action">
<a-button v-has="'admin:sysUser:add'" type="primary" @click="handleAdd" data-test="newUser"><icon-plus /> 新增</a-button>
<a-button v-has="'admin:sysUser:remove'" type="primary" status="danger" @click="() => { deleteVisible = true; }"><icon-delete /> 批量删除</a-button>
</a-space>
<!-- Table -->
<a-table
:columns="columns"
:data="tableData"
:bordered="false"
:row-selection="{ type: 'checkbox', showCheckedAll: true }"
:pagination="{ 'show-total': true, 'show-jumper': true, 'show-page-size': true, total: pager.total, current: currentPage }"
row-key="user_id"
@selection-change="(selection) => {deleteData = selection;}"
@page-change="handlePageChange"
@page-size-change="handlePageSizeChange"
>
<template #user_id="{record,rowIndex}">
<div>{{(rowIndex+1)+(pager.page-1)*pager.page_size}}</div>
</template>
<template #role_name="{ record }">
{{ record.role_name?.role_name}}
</template>
<template #dept_name="{ record }">
{{ record.dept?.dept_name }}
</template>
<!-- 1:正常 2:审核中 3:审核失败) -->
<template #status="{ record }">
<a-tag v-if="record.status ==1" color="green">正常</a-tag>
<a-tag v-else-if="record.status == 2" color="yellow">审核中</a-tag>
<a-tag v-else-if="record.status == 3" color="red">审核失败</a-tag>
</template>
<template #created_at="{ record }">
{{ parseTime(record.created_at) }}
</template>
<template #action="{ record }">
<a-button v-has="'admin:sysUser:edit'" type="text" @click="handleUpdate(record)"><icon-edit /> 修改</a-button>
<a-button v-has="'admin:sysUser:remove'" type="text" @click="() => { deleteVisible = true; deleteData = [record.user_id]; }"><icon-delete /> 删除</a-button>
<a-button v-has="'admin:sysUser:reset'" type="text" @click="handleReset(record.user_id)"><icon-refresh /> 重置</a-button>
</template>
</a-table>
</a-col>
</a-row>
<!-- Modal -->
<a-modal
v-model:visible="modalVisible"
title-align="start"
:width="600"
@cancel="handleModalCancel('modalFormRef')"
@before-ok="handleBeforeOk"
>
<template #title>
{{ modalTitle }}
</template>
<a-form
ref="modalFormRef"
:model="modalForm"
:rules="rules"
auto-label-width
>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item field="access" label="账号名称">
<a-input
v-model="modalForm.access"
placeholder="请输入账号名称"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item field="nick_name" label="用户昵称">
<a-input
v-model="modalForm.nick_name"
placeholder="请输入用户昵称"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item field="dept_id" label="所属部门">
<a-tree-select
v-model="modalForm.dept_id"
:data="treeDeptData"
:field-names="{ key: 'dept_id', title: 'dept_name' }"
placeholder="请选择所属部门"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item field="phone" label="手机号码">
<a-input v-model="modalForm.phone" placeholder="请输入手机号码" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item field="email" label="邮箱">
<a-input v-model="modalForm.email" placeholder="请输入邮箱" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item field="is_deleted" label="是否删除">
<!-- 1:正常 2:审核中 3:审核失败) -->
<a-radio-group v-model="modalForm.is_deleted">
<a-radio :value="1"> 是 </a-radio>
<a-radio :value="0">否 </a-radio>
</a-radio-group>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item field="is_deleted" label="是否禁用">
<!-- 1:正常 2:审核中 3:审核失败) -->
<a-radio-group v-model="modalForm.is_disabled">
<a-radio :value="1"> 是 </a-radio>
<a-radio :value="0">否 </a-radio>
</a-radio-group>
</a-form-item>
</a-col>
<a-col v-if="!modalForm.user_id" :span="12">
<a-form-item field="password" label="用户密码">
<a-input-password
v-model="modalForm.password"
placeholder="请输入用户密码"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item field="sex" label="用户性别">
<a-select v-model="modalForm.sex" placeholder="请选择用户性别">
<a-option :value="1"> 男 </a-option>
<a-option :value="2"> 女 </a-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item field="status" label="状态">
<!-- 1:正常 2:审核中 3:审核失败) -->
<a-radio-group v-model="modalForm.status">
<a-radio :value="1"> 正常 </a-radio>
<a-radio :value="2"> 审核中 </a-radio>
<a-radio :value="3"> 审核失败 </a-radio>
</a-radio-group>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item field="post_id" label="岗位">
<a-select v-model="modalForm.post_id" placeholder="请选择岗位">
<a-option
v-for="item in postList"
:key="item.post_id"
:value="item.post_id"
:label="item.post_name"
/>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item field="role_id" label="角色">
<a-select v-model="modalForm.role_id" placeholder="请选择角色">
<a-option
:key="item.role_id"
v-for="item in roleList"
:value="item.role_id"
:label="item.role_name"
/>
</a-select>
</a-form-item>
</a-col>
</a-row>
</a-form>
</a-modal>
<a-modal
v-model:visible="resetPwdVisible"
title="重置密码"
@before-ok="handleResetPwd"
@cancel="$refs.resetPwdFormRef.resetFields()"
>
<a-form
ref="resetPwdFormRef"
:model="resetPwdForm"
:rules="resetPwdRules"
auto-label-width
>
<a-form-item field="password" label="原密码">
<a-input-password
v-model="resetPwdForm.password"
placeholder="请输入原密码"
/>
</a-form-item>
<a-form-item field="new_password" label="新密码">
<a-input-password
v-model="resetPwdForm.new_password"
placeholder="请输入新密码"
/>
</a-form-item>
</a-form>
</a-modal>
<!-- Akiraka 20230223 删除与批量删除 开始 -->
<DeleteModal
:data="deleteData"
:visible="deleteVisible"
:delType="'user_ids'"
:apiDelete="removeUser"
@deleteVisibleChange="() => deleteVisible = false"
/>
<!-- Akiraka 20230223 删除与批量删除 结束 -->
</div>
</template>
<script setup>
import { reactive, ref, getCurrentInstance, onMounted, watch,nextTick} from 'vue';
import { IconSearch, IconLoop } from '@arco-design/web-vue/es/icon';
import TreeDept from './components/TreeDept.vue';
import { getUser, addUser, updateUser, removeUser, updateUserStatus, resetUserPwd } from '@/api/admin/sys-user';
import { getRoleList } from '@/api/admin/role';
import { getPostList } from '@/api/admin/post';
import { getDept } from '@/api/admin/sys-dept';
const treeRef_parent = ref(null);
// Akiraka 20230210 删除数据
const deleteData = ref([])
// Akiraka 20230210 删除对话框
const deleteVisible = ref(false)
// Akiraka 20230210 监听删除事件
watch(() => deleteVisible.value ,(value) => {
if ( value == false ) {
getSysUserInfo({ ...pager, ...queryForm });
}
})
const { proxy } = getCurrentInstance();
// Query
const { queryForm, handleQuery, handleResetQuery } = useQueryData();
// ApiInfo
const { currentPage, getSysPostInfo, getSysRoleInfo, getSysDeptTreeInfo, getSysUserInfo } =
useApiInfo();
// Pager
const pager = reactive({
total: 1,
page: 1,
page_size: 10
});
// Reset Pwd
const {
resetPwdForm,
resetPwdVisible,
resetPwdRules,
handleReset,
handleResetPwd,
} = useResetPwd();
// Table Operate
const {
columns,
tableData,
treeDeptData,
roleList,
postList,
handlePageChange,
handlePageSizeChange,
handleSwitchChange,
} = useTableList();
// ModalForm Operate
const {
rules,
modalForm,
modalVisible,
modalTitle,
handleAdd,
handleUpdate,
handleBeforeOk,
handleModalCancel,
} = useModalOperate();
function useQueryData() {
const queryForm = reactive({});
// 查询
const handleQuery = () => {
pager.page=1;
getSysUserInfo({ ...pager, ...queryForm });
};
// 重置查询
const handleResetQuery = () => {
pager.page=1;
proxy.$refs.queryFormRef.resetFields();
treeRef_parent.value.resetTree();
queryForm.dept_id='';
queryForm.nick_name='';
getSysUserInfo({ ...pager, ...queryForm });
};
return { queryForm, handleQuery, handleResetQuery };
}
// const changeSelect=(value,type)=>{
// console.log(value)
// if(type=='role'){
// console.log(value.role_name)
// role_name.value=value.role_name;
// modalForm.role={
// role_name:value.role_name,
// role_id:value.role_id
// }
// }else if(type=='post'){
// post_name.value=value.post_name;
// modalForm.post={
// post_name:value.post_name,
// post_id:value.post_id
// }
// }
// };
function useResetPwd() {
const resetPwdVisible = ref(false);
const resetPwdForm = reactive({});
// Rules
const resetPwdRules = {
password: [{ required: true, message: '请输入密码' }],
new_password: [
{
required: true,
message: '请输入新密码',
},
{
validator: (value, cb) => {
let reg=/^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,}$/;
if (!reg.test(value)) {
cb('密码必须为字母、数字、符号(例如$@$!%*#?&)组合且不小于8位数');
}
},
},
],
};
// 用户重置密码API参数
const resetParams = {};
// 重置
const handleReset = (user_id) => {
resetPwdVisible.value = true;
resetParams.user_id = user_id;
};
// 重置用户密码
const handleResetPwd = (done) => {
proxy.$refs.resetPwdFormRef.validate(async (err) => {
if (!err) {
resetParams.password = resetPwdForm.password;
resetParams.new_password=resetPwdForm.new_password;
const { message,code } = await resetUserPwd(resetParams);
if(code==200){
proxy.$message.success('密码设置成功');
}else{
proxy.$message.error(message);
}
done();
getSysUserInfo();
} else {
done(false);
}
});
};
return {
resetPwdForm,
resetPwdVisible,
resetPwdRules,
handleReset,
handleResetPwd,
};
}
function useApiInfo() {
const currentPage = ref(1);
/**
* 获取用户信息
* @param {*} [params]
*/
const getSysUserInfo = async (params = {}) => {
queryForm.dept_id=params.dept_id;
const { data, code, message } = await getUser({...params,...pager});
if ( code == 200 ) {
tableData.value = data.data;
Object.assign(pager, { total: data.total, page: data.page, page_size: data.page_size });
} else {
proxy.$notification.error(message);
}
};
// 获取角色信息
const getSysRoleInfo = async () => {
const {data,code,message} = await getRoleList({
role_name:''
});
if (code == 200 ) {
roleList.value = data;
} else {
proxy.$notification.error(message);
}
};
// 获取岗位信息
const getSysPostInfo = async () => {
const {data,code,message} = await getPostList({
post_name:''
});
if (code == 200 ) {
postList.value = data;
} else {
proxy.$notification.error(message);
}
};
// 获取部门树信息
const getSysDeptTreeInfo = async () => {
const res = await getDept();
treeDeptData.value = res.data;
};
return {
currentPage,
getSysPostInfo,
getSysRoleInfo,
getSysDeptTreeInfo,
getSysUserInfo,
};
}
function useTableList() {
// 部门数据
const treeDeptData = ref();
const roleList = ref([]);
const postList = ref([]);
// Table columns
const columns = [
{
title: '编号',
dataIndex: 'user_id',
slotName: 'user_id',
},
{
title: '角色',
dataIndex: 'role_name',
slotName: 'role_name',
},
{
title: '用户昵称',
dataIndex: 'nick_name',
},
{
title: '部门',
dataIndex: 'dept_name',
slotName: 'dept_name',
},
{
title: '手机号',
dataIndex: 'phone',
},
{
title: '状态',
dataIndex:'status',
slotName:'status',
},
{
title: '创建时间',
dataIndex: 'created_at',
slotName: 'created_at',
},
{
title: '操作',
slotName: 'action',
},
];
// Table Data
const tableData = ref([]);
/**
* 分页改变
* @param {Number} [page]
*/
const handlePageChange = (page) => {
pager.page = page;
// 修改当前页码
currentPage.value = page;
getSysUserInfo({ ...pager, ...queryForm });
};
// 每页数据量
const handlePageSizeChange = (page_size) => {
console.log(queryForm);
pager.page_size = page_size;
getSysUserInfo({ ...pager, ...queryForm });
};
// 用户状态快速切换
const handleSwitchChange = (record) => {
proxy.$modal.warning({
title: '注意',
content: `是否${record.status == 1 ? '停用' : '启用'} ${
record.username
} 用户?`,
hideCancel: false,
onOk: async () => {
const params = { user_id: record.user_id, status: record.status };
const res = await updateUserStatus(params);
proxy.$message.success(res.msg);
},
onCancel: () => {
record.status = record.status == '2' ? '1' : '2';
},
});
};
return {
treeDeptData,
roleList,
postList,
columns,
tableData,
handlePageChange,
handlePageSizeChange,
handleSwitchChange,
};
}
function useModalOperate() {
const modalVisible = ref(false);
const modalTitle = ref('默认标题');
// Form
const modalForm = reactive({ status: null,role:{},post:{},dept:{}
});
// AddRules
const rules = {
nick_name: [{ required: true, message: '请输入用户昵称' }],
dept_id: [{ required: true, message: '请选择所属部门' }],
phone: [{ required: true, message: '请输入手机号' }],
sex: [{ required: true, message: '请选择性别' }],
role_id: [{ required: true, message: '请选择角色' }],
status:[{ required: true, message: '请选择状态' }],
post_id:[{ required: true, message: '请选择岗位' }],
email: [
{ required: false, message: '请输入邮箱' },
{ type: 'email', message: '请输入正确的邮箱格式' },
],
access: [{ required: true, message: '请输入用户名称' }],
password: [{ required: true, message: '请输入用户密码' }],
};
// Modal 取消后重置表单
const handleModalCancel = (formEl) => {
modalVisible.value = false;
resetForm(formEl);
modalForm.user_id = null;
};
// 新增用户
const handleAdd = () => {
modalVisible.value = true;
modalTitle.value = '新增用户';
};
/**
* 修改用户
* @param {Object} val
*/
const handleUpdate = (val) => {
modalVisible.value = true;
modalTitle.value = '修改用户';
// role_name.value= val.role.role_name;
// post_name.value= val.post.post_name;
Object.assign(modalForm, val);
};
// 重置Form
const resetForm = (formEl) => {
if (!formEl) return;
proxy.$refs[formEl].resetFields();
};
// 表单提交
const handleBeforeOk = (done) => {
proxy.$refs.modalFormRef.validate(async (valid) => {
if (!valid) {
if (!modalForm.user_id) {
const { code, msg } = await addUser(modalForm);
if (code == 200 ) {
proxy.$notification.success('新增成功');
} else {
proxy.$notification.error(msg);
}
} else {
const { code, msg } = await updateUser(modalForm, modalForm.user_id);
if (code == 200 ) {
proxy.$notification.success('更新成功');
} else {
proxy.$notification.error(msg);
}
}
done();
proxy.$refs.modalFormRef.resetFields();
getSysUserInfo();
} else {
proxy.$message.error('表单校验失败');
done(false);
}
});
};
return {
rules,
modalForm,
modalVisible,
modalTitle,
handleAdd,
handleUpdate,
handleBeforeOk,
handleModalCancel,
};
}
onMounted(() => {
getSysUserInfo();
getSysDeptTreeInfo();
getSysRoleInfo();
getSysPostInfo();
});
</script>
<style lang="scss">
@media screen and (max-width: 1720px) {
.form-action {
margin-top: 0px;
}
}
.action {
margin-bottom: 8px;
}
</style>