feat: 新增重置密码弹窗
This commit is contained in:
parent
07a8d96f03
commit
84e8da75fc
4
src/typings/api/system.api.d.ts
vendored
4
src/typings/api/system.api.d.ts
vendored
@ -152,7 +152,9 @@ declare namespace Api {
|
|||||||
type UserProfileOperateParams = CommonType.RecordNullable<Pick<User, 'nickName' | 'email' | 'phonenumber' | 'sex'>>;
|
type UserProfileOperateParams = CommonType.RecordNullable<Pick<User, 'nickName' | 'email' | 'phonenumber' | 'sex'>>;
|
||||||
|
|
||||||
/** user password operate params */
|
/** user password operate params */
|
||||||
type UserPasswordOperateParams = CommonType.RecordNullable<Pick<User, 'password'> & { newPassword: string }>;
|
type UserPasswordOperateParams = CommonType.RecordNullable<
|
||||||
|
Pick<User, 'userId' | 'password'> & { newPassword: string }
|
||||||
|
>;
|
||||||
|
|
||||||
/** user info */
|
/** user info */
|
||||||
type UserInfo = {
|
type UserInfo = {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { NButton, NDivider } from 'naive-ui';
|
import { NButton, NDivider } from 'naive-ui';
|
||||||
import { useBoolean, useLoading } from '@sa/hooks';
|
import { useBoolean, useLoading } from '@sa/hooks';
|
||||||
|
import { jsonClone } from '@sa/utils';
|
||||||
import { fetchBatchDeleteUser, fetchGetDeptTree, fetchGetUserList, fetchUpdateUserStatus } from '@/service/api/system';
|
import { fetchBatchDeleteUser, fetchGetDeptTree, fetchGetUserList, fetchUpdateUserStatus } from '@/service/api/system';
|
||||||
import { useAppStore } from '@/store/modules/app';
|
import { useAppStore } from '@/store/modules/app';
|
||||||
import { useTable, useTableOperate } from '@/hooks/common/table';
|
import { useTable, useTableOperate } from '@/hooks/common/table';
|
||||||
@ -13,6 +14,7 @@ import { $t } from '@/locales';
|
|||||||
import StatusSwitch from '@/components/custom/status-switch.vue';
|
import StatusSwitch from '@/components/custom/status-switch.vue';
|
||||||
import UserOperateDrawer from './modules/user-operate-drawer.vue';
|
import UserOperateDrawer from './modules/user-operate-drawer.vue';
|
||||||
import UserImportModal from './modules/user-import-modal.vue';
|
import UserImportModal from './modules/user-import-modal.vue';
|
||||||
|
import UserPasswordDrawer from './modules/user-password-drawer.vue';
|
||||||
import UserSearch from './modules/user-search.vue';
|
import UserSearch from './modules/user-search.vue';
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
@ -27,6 +29,7 @@ const appStore = useAppStore();
|
|||||||
const { download } = useDownload();
|
const { download } = useDownload();
|
||||||
|
|
||||||
const { bool: importVisible, setTrue: openImportModal } = useBoolean();
|
const { bool: importVisible, setTrue: openImportModal } = useBoolean();
|
||||||
|
const { bool: passwordVisible, setTrue: openPasswordDrawer } = useBoolean();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
columns,
|
columns,
|
||||||
@ -118,19 +121,9 @@ const {
|
|||||||
key: 'operate',
|
key: 'operate',
|
||||||
title: $t('common.operate'),
|
title: $t('common.operate'),
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 130,
|
width: 150,
|
||||||
render: row => {
|
render: row => {
|
||||||
const divider = () => {
|
|
||||||
if (!hasAuth('system:user:edit') || !hasAuth('system:user:remove')) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return <NDivider vertical />;
|
|
||||||
};
|
|
||||||
|
|
||||||
const editBtn = () => {
|
const editBtn = () => {
|
||||||
if (!hasAuth('system:user:edit')) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<ButtonIcon
|
<ButtonIcon
|
||||||
text
|
text
|
||||||
@ -142,10 +135,19 @@ const {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const passwordBtn = () => {
|
||||||
|
return (
|
||||||
|
<ButtonIcon
|
||||||
|
text
|
||||||
|
type="primary"
|
||||||
|
icon="material-symbols:key-vertical-outline"
|
||||||
|
tooltipContent="重置密码"
|
||||||
|
onClick={() => handleResetPwd(row.userId!)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const deleteBtn = () => {
|
const deleteBtn = () => {
|
||||||
if (!hasAuth('system:user:remove')) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<ButtonIcon
|
<ButtonIcon
|
||||||
text
|
text
|
||||||
@ -158,11 +160,19 @@ const {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const buttons = [];
|
||||||
|
if (hasAuth('system:user:edit')) buttons.push(editBtn());
|
||||||
|
if (hasAuth('system:user:resetPwd')) buttons.push(passwordBtn());
|
||||||
|
if (hasAuth('system:user:remove')) buttons.push(deleteBtn());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="flex-center gap-6px">
|
<div class="flex-center gap-8px">
|
||||||
{editBtn()}
|
{buttons.map((btn, index) => (
|
||||||
{divider()}
|
<>
|
||||||
{deleteBtn()}
|
{index !== 0 && <NDivider vertical />}
|
||||||
|
{btn}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -191,6 +201,12 @@ async function edit(userId: CommonType.IdType) {
|
|||||||
handleEdit('userId', userId);
|
handleEdit('userId', userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleResetPwd(userId: CommonType.IdType) {
|
||||||
|
const findItem = data.value.find(item => item.userId === userId) || null;
|
||||||
|
editingData.value = jsonClone(findItem);
|
||||||
|
openPasswordDrawer();
|
||||||
|
}
|
||||||
|
|
||||||
const { loading: treeLoading, startLoading: startTreeLoading, endLoading: endTreeLoading } = useLoading();
|
const { loading: treeLoading, startLoading: startTreeLoading, endLoading: endTreeLoading } = useLoading();
|
||||||
const deptPattern = ref<string>();
|
const deptPattern = ref<string>();
|
||||||
const deptData = ref<Api.Common.CommonTreeRecord>([]);
|
const deptData = ref<Api.Common.CommonTreeRecord>([]);
|
||||||
@ -332,6 +348,7 @@ const selectable = computed(() => {
|
|||||||
:dept-id="searchParams.deptId"
|
:dept-id="searchParams.deptId"
|
||||||
@submitted="getDataByPage"
|
@submitted="getDataByPage"
|
||||||
/>
|
/>
|
||||||
|
<UserPasswordDrawer v-model:visible="passwordVisible" :row-data="editingData" />
|
||||||
</NCard>
|
</NCard>
|
||||||
</div>
|
</div>
|
||||||
</TableSiderLayout>
|
</TableSiderLayout>
|
||||||
|
@ -115,11 +115,11 @@ async function handleSubmit() {
|
|||||||
const { error } = await fetchCreateUser({
|
const { error } = await fetchCreateUser({
|
||||||
deptId,
|
deptId,
|
||||||
userName,
|
userName,
|
||||||
|
password,
|
||||||
nickName,
|
nickName,
|
||||||
email,
|
email,
|
||||||
phonenumber,
|
phonenumber,
|
||||||
sex,
|
sex,
|
||||||
password,
|
|
||||||
status,
|
status,
|
||||||
remark
|
remark
|
||||||
});
|
});
|
||||||
@ -135,7 +135,6 @@ async function handleSubmit() {
|
|||||||
email,
|
email,
|
||||||
phonenumber,
|
phonenumber,
|
||||||
sex,
|
sex,
|
||||||
password,
|
|
||||||
status,
|
status,
|
||||||
remark
|
remark
|
||||||
});
|
});
|
||||||
@ -156,7 +155,7 @@ watch(visible, () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<NDrawer v-model:show="visible" :title="title" display-directive="show" :width="800" class="max-w-90%">
|
<NDrawer v-model:show="visible" display-directive="show" :width="800" class="max-w-90%">
|
||||||
<NDrawerContent :title="title" :native-scrollbar="false" closable>
|
<NDrawerContent :title="title" :native-scrollbar="false" closable>
|
||||||
<NSpin :show="loading">
|
<NSpin :show="loading">
|
||||||
<NForm ref="formRef" :model="model" :rules="rules">
|
<NForm ref="formRef" :model="model" :rules="rules">
|
||||||
@ -184,7 +183,7 @@ watch(visible, () => {
|
|||||||
<NFormItem v-if="operateType === 'add'" :label="$t('page.system.user.userName')" path="userName">
|
<NFormItem v-if="operateType === 'add'" :label="$t('page.system.user.userName')" path="userName">
|
||||||
<NInput v-model:value="model.userName" :placeholder="$t('page.system.user.form.userName.required')" />
|
<NInput v-model:value="model.userName" :placeholder="$t('page.system.user.form.userName.required')" />
|
||||||
</NFormItem>
|
</NFormItem>
|
||||||
<NFormItem :label="$t('page.system.user.password')" path="password">
|
<NFormItem v-if="operateType === 'add'" :label="$t('page.system.user.password')" path="password">
|
||||||
<NInput
|
<NInput
|
||||||
v-model:value="model.password"
|
v-model:value="model.password"
|
||||||
type="password"
|
type="password"
|
||||||
@ -216,7 +215,7 @@ watch(visible, () => {
|
|||||||
<template #footer>
|
<template #footer>
|
||||||
<NSpace :size="16">
|
<NSpace :size="16">
|
||||||
<NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
|
<NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
|
||||||
<NButton type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</NButton>
|
<NButton type="primary" @click="handleSubmit">{{ $t('common.save') }}</NButton>
|
||||||
</NSpace>
|
</NSpace>
|
||||||
</template>
|
</template>
|
||||||
</NDrawerContent>
|
</NDrawerContent>
|
||||||
|
114
src/views/system/user/modules/user-password-drawer.vue
Normal file
114
src/views/system/user/modules/user-password-drawer.vue
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, watch } from 'vue';
|
||||||
|
import { fetchResetUserPassword } from '@/service/api/system';
|
||||||
|
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
|
||||||
|
import { $t } from '@/locales';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'UserPasswordDrawer'
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
/** the edit row data */
|
||||||
|
rowData?: Api.System.User | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: 'submitted'): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<Emits>();
|
||||||
|
|
||||||
|
const visible = defineModel<boolean>('visible', {
|
||||||
|
default: false
|
||||||
|
});
|
||||||
|
|
||||||
|
const { formRef, validate, restoreValidation } = useNaiveForm();
|
||||||
|
const { patternRules } = useFormRules();
|
||||||
|
|
||||||
|
type Model = Api.System.UserOperateParams & { deptName: string };
|
||||||
|
|
||||||
|
const model: Model = reactive(createDefaultModel());
|
||||||
|
|
||||||
|
function createDefaultModel(): Model {
|
||||||
|
return {
|
||||||
|
deptId: null,
|
||||||
|
userName: '',
|
||||||
|
nickName: '',
|
||||||
|
deptName: '',
|
||||||
|
password: ''
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
type RuleKey = Extract<keyof Model, 'password'>;
|
||||||
|
|
||||||
|
const rules: Record<RuleKey, App.Global.FormRule[]> = {
|
||||||
|
password: [{ ...patternRules.pwd }]
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleUpdateModelWhenEdit() {
|
||||||
|
Object.assign(model, props.rowData);
|
||||||
|
model.password = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeDrawer() {
|
||||||
|
visible.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleSubmit() {
|
||||||
|
await validate();
|
||||||
|
|
||||||
|
const { userId, password } = model;
|
||||||
|
|
||||||
|
// request
|
||||||
|
const { error } = await fetchResetUserPassword(userId!, password!);
|
||||||
|
if (error) return;
|
||||||
|
|
||||||
|
window.$message?.success($t('common.updateSuccess'));
|
||||||
|
closeDrawer();
|
||||||
|
emit('submitted');
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(visible, () => {
|
||||||
|
if (visible.value) {
|
||||||
|
handleUpdateModelWhenEdit();
|
||||||
|
restoreValidation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<NDrawer v-model:show="visible" display-directive="show" :width="800" class="max-w-90%">
|
||||||
|
<NDrawerContent title="重置密码" :native-scrollbar="false" closable>
|
||||||
|
<NForm ref="formRef" :model="model" :rules="rules">
|
||||||
|
<NFormItem :label="$t('page.system.user.nickName')" path="nickName">
|
||||||
|
<NInput v-model:value="model.nickName" disabled />
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem :label="$t('page.system.user.deptName')" path="deptName">
|
||||||
|
<NInput v-model:value="model.deptName" disabled />
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem :label="$t('page.system.user.userName')" path="userName">
|
||||||
|
<NInput v-model:value="model.userName" disabled />
|
||||||
|
</NFormItem>
|
||||||
|
<NFormItem :label="$t('page.system.user.password')" path="password">
|
||||||
|
<NInput
|
||||||
|
v-model:value="model.password"
|
||||||
|
type="password"
|
||||||
|
show-password-on="click"
|
||||||
|
:placeholder="$t('page.system.user.form.password.required')"
|
||||||
|
/>
|
||||||
|
</NFormItem>
|
||||||
|
</NForm>
|
||||||
|
<template #footer>
|
||||||
|
<NSpace :size="16">
|
||||||
|
<NButton @click="closeDrawer">{{ $t('common.cancel') }}</NButton>
|
||||||
|
<NButton type="primary" @click="handleSubmit">{{ $t('common.save') }}</NButton>
|
||||||
|
</NSpace>
|
||||||
|
</template>
|
||||||
|
</NDrawerContent>
|
||||||
|
</NDrawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
Loading…
Reference in New Issue
Block a user