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'>>;
|
||||
|
||||
/** 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 */
|
||||
type UserInfo = {
|
||||
|
@ -2,6 +2,7 @@
|
||||
import { computed, ref } from 'vue';
|
||||
import { NButton, NDivider } from 'naive-ui';
|
||||
import { useBoolean, useLoading } from '@sa/hooks';
|
||||
import { jsonClone } from '@sa/utils';
|
||||
import { fetchBatchDeleteUser, fetchGetDeptTree, fetchGetUserList, fetchUpdateUserStatus } from '@/service/api/system';
|
||||
import { useAppStore } from '@/store/modules/app';
|
||||
import { useTable, useTableOperate } from '@/hooks/common/table';
|
||||
@ -13,6 +14,7 @@ import { $t } from '@/locales';
|
||||
import StatusSwitch from '@/components/custom/status-switch.vue';
|
||||
import UserOperateDrawer from './modules/user-operate-drawer.vue';
|
||||
import UserImportModal from './modules/user-import-modal.vue';
|
||||
import UserPasswordDrawer from './modules/user-password-drawer.vue';
|
||||
import UserSearch from './modules/user-search.vue';
|
||||
|
||||
defineOptions({
|
||||
@ -27,6 +29,7 @@ const appStore = useAppStore();
|
||||
const { download } = useDownload();
|
||||
|
||||
const { bool: importVisible, setTrue: openImportModal } = useBoolean();
|
||||
const { bool: passwordVisible, setTrue: openPasswordDrawer } = useBoolean();
|
||||
|
||||
const {
|
||||
columns,
|
||||
@ -118,19 +121,9 @@ const {
|
||||
key: 'operate',
|
||||
title: $t('common.operate'),
|
||||
align: 'center',
|
||||
width: 130,
|
||||
width: 150,
|
||||
render: row => {
|
||||
const divider = () => {
|
||||
if (!hasAuth('system:user:edit') || !hasAuth('system:user:remove')) {
|
||||
return null;
|
||||
}
|
||||
return <NDivider vertical />;
|
||||
};
|
||||
|
||||
const editBtn = () => {
|
||||
if (!hasAuth('system:user:edit')) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<ButtonIcon
|
||||
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 = () => {
|
||||
if (!hasAuth('system:user:remove')) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<ButtonIcon
|
||||
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 (
|
||||
<div class="flex-center gap-6px">
|
||||
{editBtn()}
|
||||
{divider()}
|
||||
{deleteBtn()}
|
||||
<div class="flex-center gap-8px">
|
||||
{buttons.map((btn, index) => (
|
||||
<>
|
||||
{index !== 0 && <NDivider vertical />}
|
||||
{btn}
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -191,6 +201,12 @@ async function edit(userId: CommonType.IdType) {
|
||||
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 deptPattern = ref<string>();
|
||||
const deptData = ref<Api.Common.CommonTreeRecord>([]);
|
||||
@ -332,6 +348,7 @@ const selectable = computed(() => {
|
||||
:dept-id="searchParams.deptId"
|
||||
@submitted="getDataByPage"
|
||||
/>
|
||||
<UserPasswordDrawer v-model:visible="passwordVisible" :row-data="editingData" />
|
||||
</NCard>
|
||||
</div>
|
||||
</TableSiderLayout>
|
||||
|
@ -115,11 +115,11 @@ async function handleSubmit() {
|
||||
const { error } = await fetchCreateUser({
|
||||
deptId,
|
||||
userName,
|
||||
password,
|
||||
nickName,
|
||||
email,
|
||||
phonenumber,
|
||||
sex,
|
||||
password,
|
||||
status,
|
||||
remark
|
||||
});
|
||||
@ -135,7 +135,6 @@ async function handleSubmit() {
|
||||
email,
|
||||
phonenumber,
|
||||
sex,
|
||||
password,
|
||||
status,
|
||||
remark
|
||||
});
|
||||
@ -156,7 +155,7 @@ watch(visible, () => {
|
||||
</script>
|
||||
|
||||
<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>
|
||||
<NSpin :show="loading">
|
||||
<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">
|
||||
<NInput v-model:value="model.userName" :placeholder="$t('page.system.user.form.userName.required')" />
|
||||
</NFormItem>
|
||||
<NFormItem :label="$t('page.system.user.password')" path="password">
|
||||
<NFormItem v-if="operateType === 'add'" :label="$t('page.system.user.password')" path="password">
|
||||
<NInput
|
||||
v-model:value="model.password"
|
||||
type="password"
|
||||
@ -216,7 +215,7 @@ watch(visible, () => {
|
||||
<template #footer>
|
||||
<NSpace :size="16">
|
||||
<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>
|
||||
</template>
|
||||
</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