|
@@ -0,0 +1,282 @@
|
|
|
+<template>
|
|
|
+ <div class="password-change-container">
|
|
|
+ <div class="password-change-card">
|
|
|
+ <!-- 左侧头像和姓名 -->
|
|
|
+ <div class="user-info">
|
|
|
+ <div class="avatar-container">
|
|
|
+ <img
|
|
|
+ v-if="form.avatar"
|
|
|
+ :src="baseUrl + form.avatar"
|
|
|
+ fit="cover"
|
|
|
+ style="width: 100%; height: 100%"
|
|
|
+ />
|
|
|
+ <svg-icon v-else fit="cover" style="width: 100%; height: 100%" />
|
|
|
+ </div>
|
|
|
+ <div class="user-name">{{ form.nickName }}</div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 右侧表单 -->
|
|
|
+ <div class="form-container">
|
|
|
+ <form @submit.prevent="handleSubmit" class="password-form">
|
|
|
+ <div class="form-group">
|
|
|
+ <label for="currentPassword">用户编号</label>
|
|
|
+ <input v-model="form.employeeCode" type="input" disabled="true" />
|
|
|
+ </div>
|
|
|
+ <div class="form-group">
|
|
|
+ <label for="newPassword">新密码</label>
|
|
|
+ <input
|
|
|
+ v-model="form.newPassword"
|
|
|
+ type="password"
|
|
|
+ id="newPassword"
|
|
|
+ required
|
|
|
+ placeholder="请输入新密码"
|
|
|
+ @input="validatePassword"
|
|
|
+ />
|
|
|
+ <div v-if="passwordError" class="error-message">
|
|
|
+ {{ passwordError }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="form-group">
|
|
|
+ <label for="password">确认新密码</label>
|
|
|
+ <input
|
|
|
+ v-model="form.password"
|
|
|
+ type="password"
|
|
|
+ id="password"
|
|
|
+ required
|
|
|
+ placeholder="请再次输入新密码"
|
|
|
+ @input="validatePassword"
|
|
|
+ />
|
|
|
+ <div v-if="confirmError" class="error-message">
|
|
|
+ {{ confirmError }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <button type="submit" class="submit-btn" :disabled="isSubmitting">
|
|
|
+ {{ isSubmitting ? "处理中..." : "提交" }}
|
|
|
+ </button>
|
|
|
+ </form>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+import { reactive, ref } from "vue";
|
|
|
+import { getUserDetail, updatePassword } from "@/api/user/index";
|
|
|
+
|
|
|
+const route = useRoute();
|
|
|
+const router = useRouter();
|
|
|
+
|
|
|
+const redirectPath = route.query.redirect;
|
|
|
+
|
|
|
+const baseUrl = import.meta.env.VITE_APP_UPLOAD_URL;
|
|
|
+
|
|
|
+const form = reactive({
|
|
|
+ id: Number(route.query.id),
|
|
|
+ avatar: "",
|
|
|
+ nickName: "",
|
|
|
+ employeeCode: "",
|
|
|
+ newPassword: "",
|
|
|
+ password: "",
|
|
|
+});
|
|
|
+
|
|
|
+const passwordError = ref<string>("");
|
|
|
+const confirmError = ref<string>("");
|
|
|
+const isSubmitting = ref<boolean>(false);
|
|
|
+
|
|
|
+const validatePassword = (): void => {
|
|
|
+ // 密码强度验证
|
|
|
+ // if (form.newPassword.length > 0 && form.newPassword.length < 8) {
|
|
|
+ // passwordError.value = "密码长度至少为8个字符";
|
|
|
+ // } else if (!/[A-Z]/.test(form.newPassword)) {
|
|
|
+ // passwordError.value = "密码必须包含至少一个大写字母";
|
|
|
+ // } else if (!/[a-z]/.test(form.newPassword)) {
|
|
|
+ // passwordError.value = "密码必须包含至少一个小写字母";
|
|
|
+ // } else if (!/[0-9]/.test(form.newPassword)) {
|
|
|
+ // passwordError.value = "密码必须包含至少一个数字";
|
|
|
+ // } else {
|
|
|
+ // passwordError.value = "";
|
|
|
+ // }
|
|
|
+
|
|
|
+ // 确认密码验证
|
|
|
+ if (form.password && form.newPassword !== form.password) {
|
|
|
+ confirmError.value = "两次输入的密码不一致";
|
|
|
+ } else {
|
|
|
+ confirmError.value = "";
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const handleSubmit = async (): Promise<void> => {
|
|
|
+ // 验证表单
|
|
|
+ validatePassword();
|
|
|
+ if (passwordError.value || confirmError.value) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ isSubmitting.value = true;
|
|
|
+
|
|
|
+ try {
|
|
|
+ updatePassword(form).then((res) => {
|
|
|
+ if (res.code !== 200) {
|
|
|
+ ElMessage.success("修改密码成功");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ // 重置表单
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error("修改密码失败");
|
|
|
+ } finally {
|
|
|
+ isSubmitting.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const getUserInfo = async () => {
|
|
|
+ try {
|
|
|
+ const res = await getUserDetail(form.id);
|
|
|
+ form.avatar = res.data.avatar;
|
|
|
+ form.nickName = res.data.nickName;
|
|
|
+ form.employeeCode = res.data.employeeCode;
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error("获取用户信息失败");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ getUserInfo();
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.password-change-container {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ min-height: 100%;
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ padding: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.password-change-card {
|
|
|
+ display: flex;
|
|
|
+ max-width: 800px;
|
|
|
+ width: 100%;
|
|
|
+ background-color: white;
|
|
|
+ border-radius: 10px;
|
|
|
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
|
+ overflow: hidden;
|
|
|
+ transform: translateY(-20%);
|
|
|
+}
|
|
|
+
|
|
|
+.user-info {
|
|
|
+ flex: 1;
|
|
|
+ padding: 40px 20px;
|
|
|
+ background-color: #f0f2f5;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+
|
|
|
+.avatar-container {
|
|
|
+ width: 150px;
|
|
|
+ height: 150px;
|
|
|
+ border-radius: 50%;
|
|
|
+ overflow: hidden;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ border: 3px solid #fff;
|
|
|
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
|
|
|
+}
|
|
|
+
|
|
|
+.avatar {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ object-fit: cover;
|
|
|
+}
|
|
|
+
|
|
|
+.user-name {
|
|
|
+ font-size: 20px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #333;
|
|
|
+}
|
|
|
+
|
|
|
+.form-container {
|
|
|
+ flex: 1;
|
|
|
+ padding: 40px;
|
|
|
+}
|
|
|
+
|
|
|
+.form-title {
|
|
|
+ margin-bottom: 30px;
|
|
|
+ color: #333;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+
|
|
|
+.password-form {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+}
|
|
|
+
|
|
|
+.form-group {
|
|
|
+ margin-bottom: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.form-group label {
|
|
|
+ display: block;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #555;
|
|
|
+}
|
|
|
+
|
|
|
+.form-group input {
|
|
|
+ width: 100%;
|
|
|
+ padding: 10px 15px;
|
|
|
+ border: 1px solid #ddd;
|
|
|
+ border-radius: 4px;
|
|
|
+ font-size: 16px;
|
|
|
+ transition: border-color 0.3s;
|
|
|
+}
|
|
|
+
|
|
|
+.form-group input:focus {
|
|
|
+ border-color: #409eff;
|
|
|
+ outline: none;
|
|
|
+}
|
|
|
+
|
|
|
+.error-message {
|
|
|
+ color: #f56c6c;
|
|
|
+ font-size: 12px;
|
|
|
+ margin-top: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.submit-btn {
|
|
|
+ padding: 12px;
|
|
|
+ background-color: #409eff;
|
|
|
+ color: white;
|
|
|
+ border: none;
|
|
|
+ border-radius: 4px;
|
|
|
+ font-size: 16px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: background-color 0.3s;
|
|
|
+ margin-top: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.submit-btn:hover {
|
|
|
+ background-color: #66b1ff;
|
|
|
+}
|
|
|
+
|
|
|
+.submit-btn:disabled {
|
|
|
+ background-color: #a0cfff;
|
|
|
+ cursor: not-allowed;
|
|
|
+}
|
|
|
+
|
|
|
+@media (max-width: 768px) {
|
|
|
+ .password-change-card {
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .user-info {
|
|
|
+ padding: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .avatar-container {
|
|
|
+ width: 100px;
|
|
|
+ height: 100px;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|