用户管理

This commit is contained in:
陈红丽 2024-07-09 18:34:42 +08:00
parent 31f3d32e77
commit a1bde6dca0
5 changed files with 183 additions and 289 deletions

View File

@ -116,6 +116,16 @@ export function userUpdate(data:any) {
data data
}); });
} }
/**
* @description:
*/
export function resetPwd(data:any) {
return http.request({
url: '/user/resetPwd',
method: 'PUT',
data
});
}
/** /**
* @description: * @description:
*/ */
@ -147,12 +157,9 @@ export function userExport() {
/** /**
* @description: * @description:
*/ */
export function getCityByList(params:any) { export function getCityByList(pid:any) {
return http.request({ return http.request({
url: '/city/list', url: '/city/getCityList/'+pid,
method: 'get', method: 'get',
params:{
...params
}
}); });
} }

View File

@ -36,7 +36,7 @@ const cascaderProps: CascaderProps = {
} }
const getCityList= (pid:any, level:any, resolve:any)=> { const getCityList= (pid:any, level:any, resolve:any)=> {
getCityByList({pid}).then(data => { getCityByList(pid).then(data => {
for (let i = 0; i < data.length; i++) { for (let i = 0; i < data.length; i++) {
data[i].areaCode = parseInt(data[i].areaCode) data[i].areaCode = parseInt(data[i].areaCode)
data[i].hasChild = level >= props.type-1 ? true : false data[i].hasChild = level >= props.type-1 ? true : false

View File

@ -176,7 +176,7 @@
// //
if (code === ResultEnum.SUCCESS) { if (code === ResultEnum.SUCCESS) {
fileList.value = getResponseImgUrls(resFileList); fileList.value = getResponseImgUrls(resFileList);
emit('uploadChange', fileList.value); emit('uploadChange', res.data);
} else { } else {
ElMessage({ ElMessage({
message: msg, message: msg,

View File

@ -1,237 +1,107 @@
<template> <template>
<el-dialog <el-dialog v-model="props.visible" :title="props.userId ? '编辑' : '新增'" width="700" :close-on-click-modal="false"
v-model="props.visible" :before-close="dialogClose">
:title="props.userId?'编辑':'新增'" <el-form ref="formRef" :model="formData" label-width="84px">
width="700"
:close-on-click-modal="false"
:before-close="dialogClose"
>
<el-form
ref="formRef"
:model="formData"
label-width="84px"
>
<div class="flex"> <div class="flex">
<el-form-item <el-form-item label="账号" prop="username" class="flex-1"
label="账号" :rules="{ required: true, message: '请输入账号', trigger: 'blur' }">
prop="username" <el-input :disabled="isRoot" v-model="formData.username" placeholder="请输入账号" clearable />
class="flex-1"
:rules="{ required: true, message: '请输入账号', trigger: 'blur' }"
>
<el-input
:disabled="isRoot"
v-model="formData.username"
placeholder="请输入账号"
clearable
/>
</el-form-item> </el-form-item>
<el-form-item <el-form-item label="密码" prop="password" class="flex-1"
label="名称" :rules="{ required: props.userId ? false : true, message: '请输入密码', trigger: 'blur' }">
prop="realname" <el-input v-model.trim="formData.password" show-password autocomplete="new-password" clearable
class="flex-1" placeholder="请输入密码" />
:rules="{ required: true, message: '请输入名称', trigger: 'blur' }"
>
<el-input
v-model="formData.realname"
placeholder="请输入名称"
clearable
/>
</el-form-item> </el-form-item>
</div> </div>
<div class="flex"> <div class="flex">
<el-form-item label="名称" prop="realname" class="flex-1"
:rules="{ required: true, message: '请输入名称', trigger: 'blur' }">
<el-input v-model="formData.realname" placeholder="请输入名称" clearable />
</el-form-item>
<el-form-item label="性别" prop="sex" class="flex-1"> <el-form-item label="性别" prop="sex" class="flex-1">
<el-radio-group v-model="formData.gender" name="gender"> <el-radio-group v-model="formData.gender" name="gender">
<el-space>
<el-radio :value="1"></el-radio> <el-radio :value="1"></el-radio>
<el-radio :value="2"></el-radio> <el-radio :value="2"></el-radio>
<el-radio :value="3">保密</el-radio> <el-radio :value="3">保密</el-radio>
</el-space>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item
label="角色" </div>
prop="roleIds" <div class="flex">
class="flex-1" <el-form-item label="角色" prop="roles" class="flex-1"
:rules="{ required: true, message: '请选择角色', trigger: 'change' }" :rules="{ required: true, message: '请选择角色', trigger: 'change' }">
> <el-select v-model="formData.roles" :disabled="isRoot" multiple class="flex-1" clearable placeholder="请选择角色">
<el-select
v-model="formData.roleIds"
:disabled="isRoot"
multiple
class="flex-1"
clearable
placeholder="请选择角色"
>
<el-option v-if="isRoot" label="系统管理员" value="0" /> <el-option v-if="isRoot" label="系统管理员" value="0" />
<el-option <el-option v-for="(item, index) in optionData.roleList" :key="index" :label="item.name" :value="item.id" />
v-for="(item, index) in optionData.roleList"
:key="index"
:label="item.name"
:value="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
</div> <el-form-item label="部门" prop="deptId" class="flex-1">
<div class="flex">
<el-form-item
label="手机号码"
prop="mobile"
class="flex-1"
:rules="{ required: true, message: '请输入手机号码', trigger: 'blur' }"
>
<el-input
v-model="formData.mobile"
placeholder="请输入手机号码"
clearable
/>
</el-form-item>
<el-form-item
label="邮箱地址"
prop="email"
class="flex-1"
:rules="{ required: true, message: '请输入邮箱地址', trigger: 'blur' }"
>
<el-input
v-model="formData.email"
placeholder="请输入邮箱地址"
clearable
/>
</el-form-item>
</div>
<div class="flex">
<el-form-item
label="部门"
prop="deptId"
class="flex-1"
>
<!-- <el-tree-select <!-- <el-tree-select
v-model="formData.deptId" v-model="formData.deptId"
:data="optionData.deptList" :data="optionData.deptList"
:render-after-expand="false" :render-after-expand="false"
/> --> /> -->
<el-select <el-select v-model="formData.deptId" class="flex-1" clearable placeholder="请选择部门">
v-model="formData.deptId" <el-option v-for="(item, index) in optionData.deptList" :key="index" :label="item.name" :value="item.id" />
multiple
class="flex-1"
clearable
placeholder="请选择角色"
>
<el-option
v-for="(item, index) in optionData.deptList"
:key="index"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item
label="职级"
prop="levelId"
class="flex-1"
>
<el-select
v-model="formData.levelId"
multiple
class="flex-1"
clearable
placeholder="请选择角色"
>
<el-option
v-for="(item, index) in optionData.levelList"
:key="index"
:label="item.name"
:value="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
</div> </div>
<div class="flex"> <div class="flex">
<el-form-item <el-form-item label="职级" prop="levelId" class="flex-1">
label="岗位" <el-select v-model="formData.levelId" class="flex-1" clearable placeholder="请选择职级">
prop="positionId" <el-option v-for="(item, index) in optionData.levelList" :key="index" :label="item.name" :value="item.id" />
class="flex-1" </el-select>
> </el-form-item>
<el-select <el-form-item label="岗位" prop="positionId" class="flex-1">
v-model="formData.positionId" <el-select v-model="formData.positionId" class="flex-1" clearable placeholder="请选择岗位">
multiple <el-option v-for="(item, index) in optionData.positionList" :key="index" :label="item.name" :value="item.id" />
class="flex-1"
clearable
placeholder="请选择角色"
>
<el-option
v-for="(item, index) in optionData.positionList"
:key="index"
:label="item.name"
:value="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
</div> </div>
<div class="flex">
<el-form-item label="手机号码" prop="mobile" class="flex-1"
:rules="{ required: true, message: '请输入手机号码', trigger: 'blur' }">
<el-input v-model="formData.mobile" placeholder="请输入手机号码" clearable />
</el-form-item>
<el-form-item label="邮箱地址" prop="email" class="flex-1"
:rules="{ type: 'email', message: '请输入正确邮箱地址', trigger: 'blur'}">
<el-input v-model="formData.email" placeholder="请输入邮箱地址" clearable />
</el-form-item>
</div>
<div class="flex"> <div class="flex">
<el-form-item label="所属区域" class="flex-1"> <el-form-item label="所属区域" class="flex-1">
<chinaArea style="width: 100%" :type="4" v-model="formData.city"></chinaArea>
<chinaArea style="width: 100%" :type="4" v-model="formData.cityCode"></chinaArea>
</el-form-item> </el-form-item>
<el-form-item label="详细地址" class="flex-1"> <el-form-item label="详细地址" class="flex-1">
<el-input <el-input v-model="formData.address" placeholder="请输入详细地址" clearable />
v-model="formData.address"
placeholder="请输入详细地址"
clearable
/>
</el-form-item> </el-form-item>
</div> </div>
<div class="flex"> <div class="flex">
<el-form-item <el-form-item label="用户状态" prop="status" class="flex-1">
label="密码" <el-radio-group v-model="formData.status" name="status">
prop="password" <el-radio :value="1">正常</el-radio>
class="flex-1" <el-radio :value="2">禁用</el-radio>
:rules="{ required: props.userId?false:true, message: '请输入密码', trigger: 'blur' }" </el-radio-group>
> </el-form-item>
<el-input <el-form-item label="排序" prop="sort" class="flex-1">
v-model.trim="formData.password" <el-input-number v-model="formData.sort" :max="9999" />
show-password </el-form-item>
autocomplete="new-password" </div>
clearable <div class="flex">
placeholder="请输入密码" <el-form-item label="简介" prop="intro" class="flex-1">
/> <el-input v-model="formData.intro" type="textarea" placeholder="请输入简介" clearable />
</el-form-item>
</div>
<div class="flex">
<el-form-item label="备注" prop="note" class="flex-1">
<el-input v-model="formData.note" type="textarea" placeholder="请输入备注" clearable />
</el-form-item> </el-form-item>
<el-form-item
label="确认密码"
prop="passwordConfirm"
class="flex-1"
:rules="[{ required: props.userId?false:true, message: '请输入密码', trigger: 'blur' },{validator: props.userId?void(0):passwordConfirmValidator,trigger: 'blur'}]"
>
<el-input
v-model.trim="formData.passwordConfirm"
autocomplete="new-password"
show-password
clearable
placeholder="请输入确认密码"
/>
</el-form-item>
</div> </div>
<div class="flex">
<el-form-item label="管理员状态" v-if="!isRoot">
<el-switch
v-model="formData.userStatus"
active-value="enable"
inactive-value="disable"
/>
</el-form-item>
</div>
<div class="flex"></div>
<el-form-item label="头像" prop="images"> <el-form-item label="头像" prop="images">
<BasicUpload <BasicUpload :action="`${uploadUrl}/api/upload/uploadFile`" :list="formData.avatar?[{name:'avatar',url:formData.avatar}]:[]" :headers="uploadHeaders"
:action="`${uploadUrl}/api/upload/uploadFile`" :data="{ name: 'avatar' }" :limit="1" @upload-change="uploadChange" />
v-model:list="fileList"
:headers="uploadHeaders"
:data="{ name: 'avatar' }"
:limit="1"
@upload-change="uploadChange"
/>
</el-form-item> </el-form-item>
</el-form> </el-form>
<template #footer> <template #footer>
@ -246,22 +116,22 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import {getUserDetail,userAdd,userUpdate} from '@/api/system/user'; import { getUserDetail, userAdd, userUpdate } from '@/api/system/user';
import { BasicUpload } from '@/components/Upload'; import { BasicUpload } from '@/components/Upload';
import chinaArea from '@/components/ChinaArea/index.vue'; import chinaArea from '@/components/ChinaArea/index.vue';
import {computed, onMounted, reactive, shallowRef,ref,unref} from "vue"; import { computed, onMounted, reactive, shallowRef, ref, unref } from "vue";
import { getRoleAllList } from '@/api/system/role'; import { getRoleAllList } from '@/api/system/role';
import { getDeptList } from '@/api/system/dept'; import { getDeptList } from '@/api/system/dept';
import { getLevelAllList } from '@/api/system/level'; import { getLevelAllList } from '@/api/system/level';
import { getPositionAllList } from '@/api/system/position'; import { getPositionAllList } from '@/api/system/position';
import {message} from "@/utils/auth"; import { message } from "@/utils/auth";
import {FormInstance} from "element-plus"; import { FormInstance } from "element-plus";
const formRef = shallowRef<FormInstance>(); const formRef = shallowRef<FormInstance>();
import {useLockFn} from "@/utils/useLockFn"; import { useLockFn } from "@/utils/useLockFn";
import { useGlobSetting } from '@/hooks/setting'; import { useGlobSetting } from '@/hooks/setting';
import { useUserStore } from '@/store/modules/user'; import { useUserStore } from '@/store/modules/user';
const globSetting = useGlobSetting(); const globSetting = useGlobSetting();
const { uploadUrl } = globSetting; const { uploadUrl } = globSetting;
const props = defineProps({ const props = defineProps({
visible: { visible: {
@ -278,21 +148,25 @@ const props = defineProps({
const emit = defineEmits(["success", "update:visible"]); const emit = defineEmits(["success", "update:visible"]);
const uploadHeaders = reactive({ const uploadHeaders = reactive({
authorization:useUserStore().getToken authorization: useUserStore().getToken
}); });
const formData = reactive({ const formData = reactive({
userId: 0, id: 0,
email:'', email: '',
username: "", username: "",
realname: "", realname: "",
mobile:'', mobile: '',
gender:1, gender: 1,
roleIds: [], roles: [],
deptId:'', deptId: '',
levelId:'', levelId: '',
positionId:'', positionId: '',
address:'', address: '',
cityCode:'', status: 1,
note: '',
intro: '',
sort: 0,
city: [],
avatar: "", avatar: "",
password: "", password: "",
passwordConfirm: "", passwordConfirm: "",
@ -323,9 +197,17 @@ const setFormData = async (row: any) => {
const data = await getUserDetail(row.userId); const data = await getUserDetail(row.userId);
for (const key in formData) { for (const key in formData) {
if (data[key] != null && data[key] != undefined) { if (data[key] != null && data[key] != undefined) {
if(key=='city'){
if(data.city.length>0){
formData[key] = [parseInt(data.city[0]),parseInt(data.city[1]),parseInt(data.city[2]),parseInt(data.city[3])];
}else{
formData[key] =''
}
}else{
formData[key] = data[key]; formData[key] = data[key];
} }
} }
}
}; };
const handleSubmit = async () => { const handleSubmit = async () => {
@ -335,19 +217,18 @@ const handleSubmit = async () => {
emit("success"); emit("success");
}; };
const { isLock:subLoading,lockFn: submit } = useLockFn(handleSubmit); const { isLock: subLoading, lockFn: submit } = useLockFn(handleSubmit);
const optionData = reactive({ const optionData = reactive({
roleList:[], roleList: [],
deptList:[], deptList: [],
levelList:[], levelList: [],
positionList:[] positionList: []
}); });
function uploadChange(list: string[]) { function uploadChange(data: string[]) {
console.log('🚀 ~ file: index.vue ~ line 118 ~ uploadChange ~ list', list); formData.avatar = data.fileUrl;
formData.avatar = unref(list); }
}
const getAllDict = async () => { const getAllDict = async () => {
let list = await getRoleAllList(); let list = await getRoleAllList();
@ -362,7 +243,7 @@ const getAllDict = async () => {
onMounted(() => { onMounted(() => {
getAllDict() getAllDict()
if (props.userId) { if (props.userId) {
setFormData({userId: props.userId}); setFormData({ userId: props.userId });
} }
}); });

View File

@ -87,12 +87,7 @@
import { columns } from './columns'; import { columns } from './columns';
import { schemas } from './querySchemas'; import { schemas } from './querySchemas';
import { useUserStore } from '@/store/modules/user'; import { useUserStore } from '@/store/modules/user';
import { import {downloadByData} from '@/utils/file/download';
downloadByUrl,
downloadByData,
downloadByBase64,
downloadByOnlineUrl,
} from '@/utils/file/download';
const userId = ref(0); const userId = ref(0);
const basicTableRef = ref(); const basicTableRef = ref();
const editVisible = ref(false) const editVisible = ref(false)
@ -120,7 +115,7 @@ const uploadHeaders = reactive({
}); });
const actionColumn = reactive({ const actionColumn = reactive({
width: 240, width: 250,
label: '操作', label: '操作',
prop: 'action', prop: 'action',
fixed: 'right', fixed: 'right',
@ -139,20 +134,25 @@ const uploadHeaders = reactive({
type: 'warning', type: 'warning',
onClick: handleEdit.bind(null, record), onClick: handleEdit.bind(null, record),
}, },
],
dropDownActions: [
{ {
label: '启用', label: '重置密码',
key: 'enabled', type: 'warning',
}, onClick: handleResetPassWord.bind(null, record),
{
label: '禁用',
key: 'disabled',
}, },
], ],
select: (key) => { // dropDownActions: [
ElMessage.info(`您点击了,${key} 按钮`); // {
}, // label: '',
// key: 'enabled',
// },
// {
// label: '',
// key: 'disabled',
// },
// ],
// select: (key) => {
// ElMessage.info(`${key} `);
// },
}); });
}, },
}); });
@ -172,6 +172,12 @@ const uploadHeaders = reactive({
await nextTick(); await nextTick();
editVisible.value=true editVisible.value=true
} }
async function handleResetPassWord(record: Recordable) {
userId.value=record.row.id
await nextTick();
editVisible.value=true
}
async function handleDelete(record: Recordable) { async function handleDelete(record: Recordable) {
await confirm('确定要删除?'); await confirm('确定要删除?');