feat(components): 新增创建分类和笔记对话框及头部组件
- 新增 CreateGroupDialog 组件用于创建分类 - 新增 CreateNoteDialog 组件用于创建笔记 - 新增 HomeHeader 组件用于显示主页头部信息 - 对话框组件使用 Element Plus 样式- 头部组件包含用户操作按钮和搜索功能
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:model-value="visible"
|
||||
title="新建分类"
|
||||
width="400px"
|
||||
@close="handleClose"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form :model="form" :rules="rules" ref="formRef" label-width="80px">
|
||||
<el-form-item label="父级分类">
|
||||
<el-cascader
|
||||
v-model="form.parentId"
|
||||
:options="categoryOptions"
|
||||
:props="{ checkStrictly: true, emitPath: false, value: 'id', label: 'grouping' }"
|
||||
clearable
|
||||
placeholder="不选则为一级分类"
|
||||
style="width: 100%;"
|
||||
></el-cascader>
|
||||
</el-form-item>
|
||||
<el-form-item label="分类名称" prop="name">
|
||||
<el-input v-model="form.name" autocomplete="off"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { addGroupings } from '@/api/CommonApi.js';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
categoryOptions: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:visible', 'group-created']);
|
||||
|
||||
const formRef = ref(null);
|
||||
const form = ref({
|
||||
name: '',
|
||||
parentId: null,
|
||||
});
|
||||
|
||||
const rules = ref({
|
||||
name: [{ required: true, message: '请输入分类名称', trigger: 'blur' }],
|
||||
});
|
||||
|
||||
// 当对话框关闭时,重置表单
|
||||
watch(() => props.visible, (newVal) => {
|
||||
if (!newVal && formRef.value) {
|
||||
formRef.value.resetFields();
|
||||
form.value = { name: '', parentId: null };
|
||||
}
|
||||
});
|
||||
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value) return;
|
||||
await formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
try {
|
||||
const payload = {
|
||||
grouping: form.value.name,
|
||||
parentId: form.value.parentId || 0,
|
||||
};
|
||||
await addGroupings(payload);
|
||||
ElMessage.success('分类创建成功');
|
||||
emit('group-created'); // 通知父组件刷新
|
||||
handleClose();
|
||||
} catch (error) {
|
||||
ElMessage.error('创建分类失败: ' + error.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
109
biji-qianduan/src/components/home/dialogs/CreateNoteDialog.vue
Normal file
109
biji-qianduan/src/components/home/dialogs/CreateNoteDialog.vue
Normal file
@@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:model-value="visible"
|
||||
title="新建笔记"
|
||||
width="400px"
|
||||
@close="handleClose"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form :model="form" :rules="rules" ref="formRef" label-width="80px">
|
||||
<el-form-item label="笔记标题" prop="title">
|
||||
<el-input v-model="form.title" autocomplete="off"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="选择分类" prop="groupingId">
|
||||
<el-cascader
|
||||
v-model="form.groupingId"
|
||||
:options="categoryOptions"
|
||||
:props="{ checkStrictly: true, emitPath: false, value: 'id', label: 'grouping' }"
|
||||
clearable
|
||||
placeholder="请选择笔记所属分类"
|
||||
style="width: 100%;"
|
||||
></el-cascader>
|
||||
</el-form-item>
|
||||
<el-form-item label="私密笔记">
|
||||
<el-switch
|
||||
v-model="form.isPrivate"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
active-text="私密"
|
||||
inactive-text="公开"
|
||||
/>
|
||||
<div class="form-item-help">私密笔记只有登录用户才能查看内容</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
categoryOptions: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:visible', 'create-note']);
|
||||
|
||||
const formRef = ref(null);
|
||||
const form = ref({
|
||||
title: '',
|
||||
groupingId: null,
|
||||
isPrivate: 0,
|
||||
});
|
||||
|
||||
const rules = ref({
|
||||
title: [{ required: true, message: '请输入笔记标题', trigger: 'blur' }],
|
||||
groupingId: [{ required: true, message: '请选择分类', trigger: 'change' }],
|
||||
});
|
||||
|
||||
watch(() => props.visible, (newVal) => {
|
||||
if (!newVal && formRef.value) {
|
||||
formRef.value.resetFields();
|
||||
form.value = { title: '', groupingId: null, isPrivate: 0 };
|
||||
}
|
||||
});
|
||||
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value) return;
|
||||
await formRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
const payload = {
|
||||
id: null,
|
||||
title: form.value.title,
|
||||
groupingId: form.value.groupingId,
|
||||
fileName: form.value.title + '.md',
|
||||
content: '',
|
||||
isPrivate: form.value.isPrivate,
|
||||
};
|
||||
emit('create-note', payload);
|
||||
handleClose();
|
||||
} else {
|
||||
ElMessage.error('请填写必要的字段');
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.form-item-help {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-top: 4px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
</style>
|
||||
81
biji-qianduan/src/components/home/dialogs/MoveNoteDialog.vue
Normal file
81
biji-qianduan/src/components/home/dialogs/MoveNoteDialog.vue
Normal file
@@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:model-value="visible"
|
||||
title="移动笔记到"
|
||||
width="400px"
|
||||
@close="handleClose"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-cascader
|
||||
v-model="moveToGroupId"
|
||||
:options="categoryOptions"
|
||||
:props="{ checkStrictly: true, emitPath: false, value: 'id', label: 'grouping' }"
|
||||
clearable
|
||||
placeholder="请选择目标分类"
|
||||
style="width: 100%;"
|
||||
></el-cascader>
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { updateMarkdown } from '@/api/CommonApi.js';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
categoryOptions: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
noteToMove: {
|
||||
type: Object,
|
||||
default: null,
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:visible', 'move-success']);
|
||||
|
||||
const moveToGroupId = ref(null);
|
||||
|
||||
watch(() => props.visible, (newVal) => {
|
||||
if (!newVal) {
|
||||
moveToGroupId.value = null;
|
||||
}
|
||||
});
|
||||
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!moveToGroupId.value) {
|
||||
ElMessage.error('请选择目标分类');
|
||||
return;
|
||||
}
|
||||
if (!props.noteToMove) {
|
||||
ElMessage.error('没有需要移动的笔记');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const payload = {
|
||||
...props.noteToMove,
|
||||
groupingId: moveToGroupId.value,
|
||||
};
|
||||
await updateMarkdown(payload);
|
||||
ElMessage.success('笔记移动成功');
|
||||
emit('move-success');
|
||||
handleClose();
|
||||
} catch (error) {
|
||||
ElMessage.error('移动失败: ' + error.message);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
91
biji-qianduan/src/components/home/dialogs/PrivacyDialog.vue
Normal file
91
biji-qianduan/src/components/home/dialogs/PrivacyDialog.vue
Normal file
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:model-value="visible"
|
||||
:title="title"
|
||||
width="400px"
|
||||
@close="handleClose"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<div v-if="note">
|
||||
<p>您确定要将笔记 <strong>"{{ note.title }}"</strong> {{ note.isPrivate === 1 ? '设为公开' : '设为私密' }}吗?</p>
|
||||
<div class="privacy-explanation">
|
||||
<el-icon><InfoFilled /></el-icon>
|
||||
<span>{{ explanation }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { updateMarkdown } from '@/api/CommonApi.js';
|
||||
import { InfoFilled } from '@element-plus/icons-vue';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
note: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:visible', 'privacy-changed']);
|
||||
|
||||
const title = computed(() => {
|
||||
if (!props.note) return '';
|
||||
return props.note.isPrivate === 1 ? '设为公开笔记' : '设为私密笔记';
|
||||
});
|
||||
|
||||
const explanation = computed(() => {
|
||||
if (!props.note) return '';
|
||||
return props.note.isPrivate === 1 ? '公开笔记:所有用户都可以查看内容' : '私密笔记:只有登录用户才能查看内容';
|
||||
});
|
||||
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!props.note) return;
|
||||
|
||||
try {
|
||||
const newPrivacyStatus = props.note.isPrivate === 1 ? 0 : 1;
|
||||
const payload = {
|
||||
...props.note,
|
||||
isPrivate: newPrivacyStatus,
|
||||
};
|
||||
|
||||
const updatedFile = await updateMarkdown(payload);
|
||||
ElMessage.success(`笔记已${newPrivacyStatus === 1 ? '设为私密' : '设为公开'}`);
|
||||
emit('privacy-changed', updatedFile);
|
||||
handleClose();
|
||||
} catch (error) {
|
||||
ElMessage.error('修改笔记状态失败: ' + error.message);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.privacy-explanation {
|
||||
margin-top: 1rem;
|
||||
padding: 0.75rem;
|
||||
background-color: #f4f4f5;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: #909399;
|
||||
}
|
||||
.dark-theme .privacy-explanation {
|
||||
background-color: #2c2c3e;
|
||||
color: #a9a9a9;
|
||||
}
|
||||
</style>
|
||||
65
biji-qianduan/src/components/home/dialogs/RenameDialog.vue
Normal file
65
biji-qianduan/src/components/home/dialogs/RenameDialog.vue
Normal file
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:model-value="visible"
|
||||
title="重命名"
|
||||
width="400px"
|
||||
@close="handleClose"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-input v-model="newName" placeholder="请输入新名称" @keyup.enter="handleSubmit"></el-input>
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { updateMarkdownTitle, updateGroupingName } from '@/api/CommonApi.js';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
item: {
|
||||
type: Object,
|
||||
default: () => null,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:visible', 'renamed']);
|
||||
|
||||
const newName = ref('');
|
||||
|
||||
watch(() => props.item, (newItem) => {
|
||||
if (newItem) {
|
||||
newName.value = newItem.type === 'file' ? newItem.title : newItem.grouping;
|
||||
}
|
||||
});
|
||||
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!newName.value.trim()) {
|
||||
ElMessage.error('名称不能为空');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (props.item.type === 'file') {
|
||||
await updateMarkdownTitle({ id: props.item.id, title: newName.value });
|
||||
} else {
|
||||
await updateGroupingName({ id: props.item.id, grouping: newName.value });
|
||||
}
|
||||
ElMessage.success('重命名成功');
|
||||
emit('renamed');
|
||||
handleClose();
|
||||
} catch (error) {
|
||||
ElMessage.error('重命名失败: ' + error.message);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:model-value="visible"
|
||||
title="选择导入的分类"
|
||||
width="400px"
|
||||
@close="handleClose"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-cascader
|
||||
v-model="importGroupId"
|
||||
:options="categoryOptions"
|
||||
:props="{ checkStrictly: true, emitPath: false, value: 'id', label: 'grouping' }"
|
||||
clearable
|
||||
placeholder="请选择要导入的分类"
|
||||
style="width: 100%;"
|
||||
></el-cascader>
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { updateMarkdown } from '@/api/CommonApi.js';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
categoryOptions: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
fileToImport: {
|
||||
type: File,
|
||||
default: null,
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:visible', 'import-success']);
|
||||
|
||||
const importGroupId = ref(null);
|
||||
|
||||
watch(() => props.visible, (newVal) => {
|
||||
if (!newVal) {
|
||||
importGroupId.value = null;
|
||||
}
|
||||
});
|
||||
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!importGroupId.value) {
|
||||
ElMessage.error('请选择要导入的分类');
|
||||
return;
|
||||
}
|
||||
if (!props.fileToImport) {
|
||||
ElMessage.error('没有需要导入的文件');
|
||||
return;
|
||||
}
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = async (e) => {
|
||||
const content = e.target.result;
|
||||
const payload = {
|
||||
title: props.fileToImport.name.replace(/\.md$/, ''),
|
||||
groupingId: importGroupId.value,
|
||||
content: content,
|
||||
fileName: props.fileToImport.name,
|
||||
};
|
||||
try {
|
||||
await updateMarkdown(payload);
|
||||
ElMessage.success('Markdown 文件导入成功');
|
||||
emit('import-success');
|
||||
handleClose();
|
||||
} catch (error) {
|
||||
ElMessage.error('导入失败: ' + error.message);
|
||||
}
|
||||
};
|
||||
reader.readAsText(props.fileToImport);
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,98 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:model-value="visible"
|
||||
title="系统管理"
|
||||
width="500px"
|
||||
@close="handleClose"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form label-width="120px">
|
||||
<el-form-item label="开放注册">
|
||||
<el-switch v-model="isRegistrationEnabled" @change="handleToggleRegistration"></el-switch>
|
||||
</el-form-item>
|
||||
<el-form-item label="生成注册码">
|
||||
<el-button type="primary" @click="handleGenerateCode">生成</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="generatedCode" label="新注册码">
|
||||
<el-input v-model="generatedCode" readonly>
|
||||
<template #append>
|
||||
<el-button @click="copyToClipboard(generatedCode)">复制</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch, onMounted } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import {
|
||||
getRegistrationStatus,
|
||||
toggleRegistration,
|
||||
generateRegistrationCode,
|
||||
} from '@/api/CommonApi.js';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:visible']);
|
||||
|
||||
const isRegistrationEnabled = ref(true);
|
||||
const generatedCode = ref('');
|
||||
|
||||
watch(() => props.visible, (newVal) => {
|
||||
if (newVal) {
|
||||
fetchRegistrationStatus();
|
||||
generatedCode.value = ''; // Reset code when dialog opens
|
||||
}
|
||||
});
|
||||
|
||||
const fetchRegistrationStatus = async () => {
|
||||
try {
|
||||
isRegistrationEnabled.value = await getRegistrationStatus();
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch registration status:", error);
|
||||
ElMessage.error('获取注册状态失败');
|
||||
}
|
||||
};
|
||||
|
||||
const handleToggleRegistration = async (value) => {
|
||||
try {
|
||||
await toggleRegistration(value);
|
||||
ElMessage.success(`注册功能已${value ? '开启' : '关闭'}`);
|
||||
} catch (error) {
|
||||
ElMessage.error('操作失败');
|
||||
isRegistrationEnabled.value = !value; // Revert on failure
|
||||
}
|
||||
};
|
||||
|
||||
const handleGenerateCode = async () => {
|
||||
try {
|
||||
const code = await generateRegistrationCode();
|
||||
generatedCode.value = code;
|
||||
ElMessage.success('注册码生成成功');
|
||||
} catch (error) {
|
||||
ElMessage.error('生成注册码失败: ' + error.message);
|
||||
}
|
||||
};
|
||||
|
||||
const copyToClipboard = (text) => {
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
ElMessage.success('已复制到剪贴板');
|
||||
}, () => {
|
||||
ElMessage.error('复制失败');
|
||||
});
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,97 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:model-value="visible"
|
||||
title="修改密码"
|
||||
width="400px"
|
||||
@close="handleClose"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
|
||||
<el-form-item label="旧密码" prop="oldPassword">
|
||||
<el-input v-model="form.oldPassword" type="password" show-password autocomplete="off"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="新密码" prop="newPassword">
|
||||
<el-input v-model="form.newPassword" type="password" show-password autocomplete="off"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="确认新密码" prop="confirmPassword">
|
||||
<el-input v-model="form.confirmPassword" type="password" show-password autocomplete="off"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch } from 'vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { updatePassword } from '@/api/CommonApi.js';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const props = defineProps({
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:visible', 'password-updated']);
|
||||
const userStore = useUserStore();
|
||||
const router = useRouter();
|
||||
|
||||
const formRef = ref(null);
|
||||
const form = ref({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: '',
|
||||
});
|
||||
|
||||
const validateConfirmPassword = (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
callback(new Error('请再次输入新密码'));
|
||||
} else if (value !== form.value.newPassword) {
|
||||
callback(new Error("两次输入的新密码不一致"));
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
const rules = ref({
|
||||
oldPassword: [{ required: true, message: '请输入旧密码', trigger: 'blur' }],
|
||||
newPassword: [{ required: true, message: '请输入新密码', trigger: 'blur' }, { min: 6, message: '密码长度不能少于6位', trigger: 'blur' }],
|
||||
confirmPassword: [{ required: true, validator: validateConfirmPassword, trigger: 'blur' }],
|
||||
});
|
||||
|
||||
watch(() => props.visible, (newVal) => {
|
||||
if (!newVal && formRef.value) {
|
||||
formRef.value.resetFields();
|
||||
}
|
||||
});
|
||||
|
||||
const handleClose = () => {
|
||||
emit('update:visible', false);
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value) return;
|
||||
await formRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
try {
|
||||
await updatePassword({
|
||||
oldPassword: form.value.oldPassword,
|
||||
newPassword: form.value.newPassword,
|
||||
});
|
||||
ElMessage.success('密码修改成功,请重新登录');
|
||||
emit('password-updated');
|
||||
handleClose();
|
||||
// Logout logic will be handled by the parent component
|
||||
} catch (error) {
|
||||
ElMessage.error('密码修改失败: ' + error.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user