Browse Source

强制修改默认密码

xiaohaizhao 6 months ago
parent
commit
7055e73083
3 changed files with 249 additions and 53 deletions
  1. 220 50
      pages/index/changePassword.vue
  2. 15 0
      pages/login/login.vue
  3. 14 3
      pages/workOrder/changeMsg.vue

+ 220 - 50
pages/index/changePassword.vue

@@ -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>

+ 15 - 0
pages/login/login.vue

@@ -234,6 +234,21 @@ function accLogIn() {
     loading.value = true;
     $Http.login({ "accountno": accountno.value, "imagecaptcha": imagecaptcha.value, "password": hexMD5(password1.value), "systemclient": "wechatsaletool" }).then(res => {
         if (res.code == 1) {
+            if (res.remindchangepassword) return uni.showModal({
+                title: '提示',
+                content: '当前密码为系统初始化密码,请修改后重新登录',
+                showCancel: false,
+                confirmText: "前去修改",
+                complete: () => {
+                    uni.navigateTo({
+                        url: '/pages/index/changePassword?token=' + res.account_list[0].token
+                    })
+                    $Http.claerPassword = function () {
+                        phonenumber.value = '';
+                    }.bind(this);
+                    loading.value = false;
+                }
+            })
             if (res.account_list.length == 1) {
                 handleLogin1(res.account_list[0]);
             } else {

+ 14 - 3
pages/workOrder/changeMsg.vue

@@ -52,6 +52,14 @@
                 <up-input type="number" v-model="form.scenecontactphonenumber" placeholder="联系人电话" clearable />
             </up-form-item>
 
+            <up-form-item label="服务距离(单程)" prop="servicemileage">
+                <up-input v-model="form.servicemileage" placeholder="服务距离(单程)" clearable>
+                    <template #suffix>
+                        Km
+                    </template>
+                </up-input>
+            </up-form-item>
+
             <view class="title">
                 产品信息
             </view>
@@ -147,7 +155,8 @@ const form = reactive({
     'unitname': "", // 计量单位
     'spec': "", // 规格
     enterprisename: "", //  经销商
-    cardno: "" // 保修卡号
+    cardno: "",// 保修卡号
+    servicemileage: ""
 });
 const rules = reactive({
     class1: [{ required: true, message: '请选择产品品类', trigger: 'change' }],
@@ -205,7 +214,9 @@ function save() {
             let content = {
                 "sa_workorderid": sa_workorderid,
                 sa_serviceorderid: detail.sa_serviceorderid,
-                ...form
+                ...form,
+                servicemileage: form.servicemileage || 0,
+                phonenumber: form.customerphonenumber || '',
             };
             content.customerphonenumber = content.customerphonenumber || content.phonenumber;
             content.name = content.customername || '';
@@ -401,7 +412,7 @@ function toSelectProduct() {
 
     .picker {
         width: 100%;
-        // border-bottom: 1px solid #dadbde;
+        border: 1px solid #dadbde;
         font-size: 32rpx;
         color: #606266;
         padding: 9px;