|
|
@@ -5,17 +5,36 @@
|
|
|
修改密码
|
|
|
</view>
|
|
|
|
|
|
+ <!-- 原密码 -->
|
|
|
<up-form-item label="原密码" :required="rules.password[0].required" prop="password">
|
|
|
<up-input v-model="form.password" placeholder="请输入原密码" type="password" clearable />
|
|
|
</up-form-item>
|
|
|
|
|
|
+ <!-- 新密码 -->
|
|
|
<up-form-item label="新密码" :required="rules.newpassword[0].required" prop="newpassword">
|
|
|
- <up-input v-model="form.newpassword" placeholder="请输入新密码" type="password" clearable />
|
|
|
+ <up-input v-model="form.newpassword" placeholder="请输入新密码" type="password" clearable
|
|
|
+ @change="onNewPwdInput" />
|
|
|
</up-form-item>
|
|
|
|
|
|
+ <!-- 新增:动态密码规则 -->
|
|
|
+ <view v-if="form.newpassword" class="pwd-rules-box">
|
|
|
+ <view class="pwd-rule" v-for="item in rulesDisplay" :key="item.key">
|
|
|
+ <text :style="{ color: item.pass ? '#07c160' : '#fa5151' }">
|
|
|
+ {{ item.pass ? '✔' : '✖' }} {{ item.text }}
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <!-- 确认密码 -->
|
|
|
<up-form-item label="确认密码" :required="rules.confirmPassword[0].required" prop="confirmPassword">
|
|
|
- <up-input v-model="form.confirmPassword" placeholder="请确认新密码" type="password" clearable />
|
|
|
+ <up-input v-model="form.confirmPassword" placeholder="请确认新密码" type="password" clearable
|
|
|
+ @change="onConfirmInput" />
|
|
|
</up-form-item>
|
|
|
+
|
|
|
+ <!-- 新增:两次密码不一致提示 -->
|
|
|
+ <view v-if="confirmPassword === false" class="errmsg">
|
|
|
+ 两次密码不一致
|
|
|
+ </view>
|
|
|
</up-form>
|
|
|
|
|
|
<view style="padding-bottom: 50px;width: 350rpx;margin: 40rpx auto 0;" @click="save">
|
|
|
@@ -24,23 +43,127 @@
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
+
|
|
|
+
|
|
|
<script setup>
|
|
|
import { ref, reactive, getCurrentInstance } from 'vue';
|
|
|
-const { $Http } = getCurrentInstance().proxy;
|
|
|
import { onLoad } from '@dcloudio/uni-app';
|
|
|
+const { $Http } = getCurrentInstance().proxy;
|
|
|
|
|
|
+/* ---------------------- 表单结构 ---------------------- */
|
|
|
+const uFormRef = ref(null);
|
|
|
+const form = reactive({
|
|
|
+ password: '',
|
|
|
+ newpassword: '',
|
|
|
+ confirmPassword: ''
|
|
|
+});
|
|
|
|
|
|
+const confirmPassword = ref(""); // true、false、""
|
|
|
|
|
|
-const uFormRef = ref(null);
|
|
|
+/* ---------------------- 从缓存中读取 site 配置 ---------------------- */
|
|
|
+const site = uni.getStorageSync("siteP") || {};
|
|
|
+
|
|
|
+/* 获取密码规则 */
|
|
|
+function getPasswordRules() {
|
|
|
+ return {
|
|
|
+ minLength: site.password_length || 6,
|
|
|
+ needLowercase: site.password_needlowercase == 1,
|
|
|
+ needUppercase: site.password_needcapital == 1,
|
|
|
+ needNumber: site.password_neednum == 1,
|
|
|
+ needSpecial: site.password_needspecialchar == 1
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+/* ---------------------- 动态规则展示 ---------------------- */
|
|
|
+const rulesDisplay = ref([]);
|
|
|
+
|
|
|
+// 更新规则显示列表
|
|
|
+function updateRuleList(pwd) {
|
|
|
+ const rules = getPasswordRules();
|
|
|
+ const list = [];
|
|
|
+
|
|
|
+ list.push({
|
|
|
+ key: "min",
|
|
|
+ text: `长度至少 ${rules.minLength} 位`,
|
|
|
+ pass: pwd.length >= rules.minLength
|
|
|
+ });
|
|
|
+
|
|
|
+ if (rules.needLowercase)
|
|
|
+ list.push({ key: "lower", text: "包含小写字母 a-z", pass: /[a-z]/.test(pwd) });
|
|
|
+
|
|
|
+ if (rules.needUppercase)
|
|
|
+ list.push({ key: "upper", text: "包含大写字母 A-Z", pass: /[A-Z]/.test(pwd) });
|
|
|
+
|
|
|
+ if (rules.needNumber)
|
|
|
+ list.push({ key: "num", text: "包含数字 0-9", pass: /\d/.test(pwd) });
|
|
|
+
|
|
|
+ if (rules.needSpecial)
|
|
|
+ list.push({
|
|
|
+ key: "special",
|
|
|
+ text: "包含特殊符号(如 !@#$% 等)",
|
|
|
+ pass: /[^A-Za-z0-9]/.test(pwd)
|
|
|
+ });
|
|
|
+
|
|
|
+ rulesDisplay.value = list;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/* ---------------------- 输入事件 ---------------------- */
|
|
|
+function onNewPwdInput(value) {
|
|
|
+ form.newpassword = value; // 保证同步
|
|
|
+ updateRuleList(value);
|
|
|
+ checkConfirmPassword();
|
|
|
+}
|
|
|
+
|
|
|
+function onConfirmInput(value) {
|
|
|
+ form.confirmPassword = value; // 保证同步
|
|
|
+ checkConfirmPassword();
|
|
|
+}
|
|
|
+
|
|
|
+// 判断两次密码是否一致
|
|
|
+function checkConfirmPassword() {
|
|
|
+ if (!form.newpassword || !form.confirmPassword) {
|
|
|
+ confirmPassword.value = "";
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ confirmPassword.value = form.newpassword === form.confirmPassword;
|
|
|
+}
|
|
|
+
|
|
|
+/* ---------------------- 表单验证规则 ---------------------- */
|
|
|
const rules = reactive({
|
|
|
password: [{ required: true, message: '请输入原密码', trigger: 'blur' }],
|
|
|
- newpassword: [{ required: true, message: '请输入新密码', trigger: 'blur' }],
|
|
|
+ newpassword: [
|
|
|
+ { required: true, message: '请输入新密码', trigger: 'blur' },
|
|
|
+ {
|
|
|
+ validator: (rule, value) => {
|
|
|
+ const rules = getPasswordRules();
|
|
|
+
|
|
|
+ if (value.length < rules.minLength)
|
|
|
+ return new Error(`密码长度至少 ${rules.minLength} 位`);
|
|
|
+
|
|
|
+ if (rules.needLowercase && !/[a-z]/.test(value))
|
|
|
+ return new Error("需包含小写字母");
|
|
|
+
|
|
|
+ if (rules.needUppercase && !/[A-Z]/.test(value))
|
|
|
+ return new Error("需包含大写字母");
|
|
|
+
|
|
|
+ if (rules.needNumber && !/\d/.test(value))
|
|
|
+ return new Error("需包含数字");
|
|
|
+
|
|
|
+ if (rules.needSpecial && !/[^A-Za-z0-9]/.test(value))
|
|
|
+ return new Error("需包含特殊符号");
|
|
|
+
|
|
|
+ return true;
|
|
|
+ },
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ],
|
|
|
confirmPassword: [
|
|
|
{ required: true, message: '请确认新密码', trigger: 'input' },
|
|
|
{
|
|
|
validator: (rule, value) => {
|
|
|
if (value !== form.newpassword) {
|
|
|
- return new Error('两次输入的密码不一致');
|
|
|
+ return new Error("两次输入的密码不一致");
|
|
|
}
|
|
|
return true;
|
|
|
},
|
|
|
@@ -48,58 +171,88 @@ const rules = reactive({
|
|
|
}
|
|
|
]
|
|
|
});
|
|
|
+let token = null;
|
|
|
|
|
|
-(onLoad(() => {
|
|
|
- setTimeout(() => {
|
|
|
- uFormRef.value.setRules(rules);
|
|
|
- });
|
|
|
-}));
|
|
|
+onLoad(async (options) => {
|
|
|
+ // 定义一个函数用于初始化规则
|
|
|
+ const init = () => {
|
|
|
+ // 根据最新 site 初始化规则提示(如果 newpassword 有值会实时计算)
|
|
|
+ updateRuleList(form.newpassword);
|
|
|
|
|
|
-const form = reactive({
|
|
|
- password: '', // 原密码
|
|
|
- newpassword: '', // 新密码
|
|
|
- confirmPassword: '' // 确认密码
|
|
|
+ // 延迟是为了等待 uForm 渲染完成
|
|
|
+ setTimeout(() => {
|
|
|
+ uFormRef.value?.setRules(rules);
|
|
|
+ }, 50);
|
|
|
+ };
|
|
|
+
|
|
|
+ // ------------------ 情况 1:通过 token 异步获取 site ------------------
|
|
|
+ if (options.token) {
|
|
|
+ $Http.base({
|
|
|
+ "classname": "webmanage.site.site",
|
|
|
+ "method": "querySite_Parameter",
|
|
|
+ "content": {},
|
|
|
+ "accesstoken": options.token
|
|
|
+ }).then(res => {
|
|
|
+ if (res.msg === "成功") {
|
|
|
+ uni.setStorageSync("siteP", res.data);
|
|
|
+ // 更新本地 site
|
|
|
+ Object.assign(site, res.data);
|
|
|
+ } else {
|
|
|
+ uni.showToast({ title: res.msg, icon: "none" });
|
|
|
+ }
|
|
|
+ token = options.token;
|
|
|
+ init(); // 异步返回后初始化规则
|
|
|
+ }).catch(() => {
|
|
|
+ init(); // 保底执行
|
|
|
+ });
|
|
|
+
|
|
|
+ return; // 结束 onLoad,避免执行后面的本地初始化
|
|
|
+ }
|
|
|
+
|
|
|
+ // ------------------ 情况 2:直接读取本地缓存 site ------------------
|
|
|
+ const localSite = uni.getStorageSync("siteP");
|
|
|
+ if (localSite) Object.assign(site, localSite);
|
|
|
+
|
|
|
+ init(); // 本地立即初始化
|
|
|
});
|
|
|
|
|
|
+
|
|
|
+/* ---------------------- 保存 ---------------------- */
|
|
|
let loading = ref(false);
|
|
|
|
|
|
-function save() {
|
|
|
+async function save() {
|
|
|
if (loading.value) return;
|
|
|
+
|
|
|
+ // 先跑 uView 表单校验
|
|
|
uFormRef.value.validate().then(valid => {
|
|
|
- if (valid) {
|
|
|
- loading.value = true;
|
|
|
- $Http.basic({
|
|
|
- "classname": "common.usercenter.usercenter",
|
|
|
- "method": "changePassWord",
|
|
|
- "content": {
|
|
|
- "newpassword": hexMD5(form.newpassword),
|
|
|
- "password": hexMD5(form.password),
|
|
|
- }
|
|
|
- }).then(res => {
|
|
|
- console.log('修改密码结果', res);
|
|
|
- loading.value = false;
|
|
|
- if (res.code == 1) {
|
|
|
- uni.showToast({
|
|
|
- title: '密码修改成功,请重新登录',
|
|
|
- icon: 'none',
|
|
|
- mask: true
|
|
|
- });
|
|
|
- setTimeout(() => {
|
|
|
- uni.reLaunch({
|
|
|
- url: '/pages/login/login'
|
|
|
- });
|
|
|
- }, 500);
|
|
|
- } else {
|
|
|
- uni.showToast({
|
|
|
- title: res.msg || '密码修改失败',
|
|
|
- icon: 'none',
|
|
|
- duration: 2000
|
|
|
- });
|
|
|
- }
|
|
|
- })
|
|
|
+ if (!valid) return;
|
|
|
+
|
|
|
+ if (confirmPassword.value !== true) {
|
|
|
+ return uni.showToast({ title: "两次密码不一致", icon: "none" });
|
|
|
}
|
|
|
+
|
|
|
+ loading.value = true;
|
|
|
+ // 发起实际请求
|
|
|
+ $Http.base({
|
|
|
+ "classname": "common.usercenter.usercenter",
|
|
|
+ "method": "changePassWord",
|
|
|
+ "content": {
|
|
|
+ "newpassword": hexMD5(form.newpassword),
|
|
|
+ "password": hexMD5(form.password),
|
|
|
+ },
|
|
|
+ "accesstoken": token || uni.getStorageSync("userMsg").token
|
|
|
+ }).then(res => {
|
|
|
+ loading.value = false;
|
|
|
+ if (res.code == 1) {
|
|
|
+ uni.showToast({ title: '密码修改成功,请重新登录', icon: 'none', mask: true });
|
|
|
+ $Http.claerPassword && $Http.claerPassword(); // 清除密码缓存
|
|
|
+ setTimeout(() => uni.reLaunch({ url: '/pages/login/login' }), 500);
|
|
|
+ } else {
|
|
|
+ uni.showToast({ title: res.msg || '密码修改失败', icon: 'none' });
|
|
|
+ }
|
|
|
+ });
|
|
|
}).catch(err => {
|
|
|
- console.error('表单验证失败', err);
|
|
|
+ console.error("表单验证失败", err);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
@@ -244,9 +397,9 @@ function str2binl(str) {
|
|
|
.content {
|
|
|
width: 100vw;
|
|
|
padding: 20px;
|
|
|
- box-sizing: border-box;
|
|
|
min-height: 100vh;
|
|
|
background: #fff;
|
|
|
+ box-sizing: border-box;
|
|
|
|
|
|
.title {
|
|
|
font-size: 34rpx;
|
|
|
@@ -255,4 +408,21 @@ function str2binl(str) {
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
}
|
|
|
-</style>
|
|
|
+
|
|
|
+/* 新增:动态密码规则样式 */
|
|
|
+.pwd-rules-box {
|
|
|
+ margin: 10rpx 0 20rpx;
|
|
|
+ font-size: 26rpx;
|
|
|
+ line-height: 40rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+.pwd-rule {
|
|
|
+ margin: 6rpx 0;
|
|
|
+}
|
|
|
+
|
|
|
+.errmsg {
|
|
|
+ color: #fa5151;
|
|
|
+ margin: 10rpx 0 20rpx;
|
|
|
+}
|
|
|
+</style>
|