From 8521290ee4a337a2093032859b512fb90fa807cb Mon Sep 17 00:00:00 2001 From: BianLzhaoMin <11485688+bianliangzhaomin123@user.noreply.gitee.com> Date: Sun, 4 Jan 2026 10:21:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AF=86=E7=A0=81=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/validate.js | 113 ++++++++++++++++----- src/views/system/user/index.vue | 9 +- src/views/system/user/profile/resetPwd.vue | 92 ++++++++++------- 3 files changed, 144 insertions(+), 70 deletions(-) diff --git a/src/utils/validate.js b/src/utils/validate.js index 6a4c0c5..de0b290 100644 --- a/src/utils/validate.js +++ b/src/utils/validate.js @@ -5,30 +5,33 @@ * @returns {Boolean} */ export function isPathMatch(pattern, path) { - const regexPattern = pattern.replace(/\//g, '\\/').replace(/\*\*/g, '.*').replace(/\*/g, '[^\\/]*') - const regex = new RegExp(`^${regexPattern}$`) - return regex.test(path) + const regexPattern = pattern + .replace(/\//g, '\\/') + .replace(/\*\*/g, '.*') + .replace(/\*/g, '[^\\/]*') + const regex = new RegExp(`^${regexPattern}$`) + return regex.test(path) } /** - * 判断value字符串是否为空 + * 判断value字符串是否为空 * @param {string} value * @returns {Boolean} */ export function isEmpty(value) { - if (value == null || value == "" || value == undefined || value == "undefined") { - return true - } - return false + if (value == null || value == '' || value == undefined || value == 'undefined') { + return true + } + return false } /** - * 判断url是否是http或https + * 判断url是否是http或https * @param {string} url * @returns {Boolean} */ export function isHttp(url) { - return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1 + return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1 } /** @@ -37,7 +40,7 @@ export function isHttp(url) { * @returns {Boolean} */ export function isExternal(path) { - return /^(https?:|mailto:|tel:)/.test(path) + return /^(https?:|mailto:|tel:)/.test(path) } /** @@ -45,8 +48,8 @@ export function isExternal(path) { * @returns {Boolean} */ export function validUsername(str) { - const valid_map = ['admin', 'editor'] - return valid_map.indexOf(str.trim()) >= 0 + const valid_map = ['admin', 'editor'] + return valid_map.indexOf(str.trim()) >= 0 } /** @@ -54,8 +57,9 @@ export function validUsername(str) { * @returns {Boolean} */ export function validURL(url) { - const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/ - return reg.test(url) + const reg = + /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/ + return reg.test(url) } /** @@ -63,8 +67,8 @@ export function validURL(url) { * @returns {Boolean} */ export function validLowerCase(str) { - const reg = /^[a-z]+$/ - return reg.test(str) + const reg = /^[a-z]+$/ + return reg.test(str) } /** @@ -72,8 +76,8 @@ export function validLowerCase(str) { * @returns {Boolean} */ export function validUpperCase(str) { - const reg = /^[A-Z]+$/ - return reg.test(str) + const reg = /^[A-Z]+$/ + return reg.test(str) } /** @@ -81,8 +85,8 @@ export function validUpperCase(str) { * @returns {Boolean} */ export function validAlphabets(str) { - const reg = /^[A-Za-z]+$/ - return reg.test(str) + const reg = /^[A-Za-z]+$/ + return reg.test(str) } /** @@ -90,8 +94,9 @@ export function validAlphabets(str) { * @returns {Boolean} */ export function validEmail(email) { - const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ - return reg.test(email) + const reg = + /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + return reg.test(email) } /** @@ -99,7 +104,7 @@ export function validEmail(email) { * @returns {Boolean} */ export function isString(str) { - return typeof str === 'string' || str instanceof String + return typeof str === 'string' || str instanceof String } /** @@ -107,8 +112,60 @@ export function isString(str) { * @returns {Boolean} */ export function isArray(arg) { - if (typeof Array.isArray === 'undefined') { - return Object.prototype.toString.call(arg) === '[object Array]' - } - return Array.isArray(arg) + if (typeof Array.isArray === 'undefined') { + return Object.prototype.toString.call(arg) === '[object Array]' + } + return Array.isArray(arg) +} + +/** + * 验证新密码(用于 Element UI 表单验证规则) + * @param {Object} rule 验证规则对象 + * @param {string} value 密码值 + * @param {Function} callback 回调函数 + */ +export function validateNewPassword(rule, value, callback) { + if (!value) { + callback(new Error('密码不能为空')) + return + } + // 1. 检查密码长度 + if (value.length < 8 || value.length > 16) { + callback(new Error('密码长度应为8至16位,且必须包含大小写字母及数字及特殊字符!')) + return + } + // 2. 检查密码复杂度 + const hasUpperCase = /[A-Z]/.test(value) + const hasLowerCase = /[a-z]/.test(value) + const hasDigit = /\d/.test(value) + const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(value) + if (!hasUpperCase || !hasLowerCase || !hasDigit || !hasSpecialChar) { + callback(new Error('密码长度应为8至16位,且必须包含大小写字母及数字及特殊字符!')) + return + } + callback() // 验证成功 +} + +/** + * 同步验证新密码(用于 $prompt 的 inputValidator 等场景) + * @param {string} value 密码值 + * @returns {string|boolean} 返回错误信息字符串或 true(验证通过) + */ +export function validateNewPasswordSync(value) { + if (!value) { + return '密码不能为空' + } + // 1. 检查密码长度 + if (value.length < 8 || value.length > 16) { + return '密码长度应为8至16位,且必须包含大小写字母及数字及特殊字符!' + } + // 2. 检查密码复杂度 + const hasUpperCase = /[A-Z]/.test(value) + const hasLowerCase = /[a-z]/.test(value) + const hasDigit = /\d/.test(value) + const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(value) + if (!hasUpperCase || !hasLowerCase || !hasDigit || !hasSpecialChar) { + return '密码长度应为8至16位,且必须包含大小写字母及数字及特殊字符!' + } + return true } diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue index cc2afbe..08162ae 100644 --- a/src/views/system/user/index.vue +++ b/src/views/system/user/index.vue @@ -531,6 +531,7 @@ import 'splitpanes/dist/splitpanes.css' import CryptoUtil from '../../../api/crypto.js' import ComDialog from '@/components/ComDialog/index.vue' import ComButton from '@/components/ComButton/index.vue' +import { validateNewPasswordSync } from '@/utils/validate' const router = useRouter() const appStore = useAppStore() @@ -769,13 +770,7 @@ function handleResetPwd(row) { confirmButtonText: '确定', cancelButtonText: '取消', closeOnClickModal: false, - inputPattern: /^.{5,20}$/, - inputErrorMessage: '用户密码长度必须介于 5 和 20 之间', - inputValidator: (value) => { - if (/<|>|"|'|\||\\/.test(value)) { - return '不能包含非法字符:< > " \' \\\ |' - } - }, + inputValidator: validateNewPasswordSync, }) .then(({ value }) => { resetUserPwd(row.userId, value).then((response) => { diff --git a/src/views/system/user/profile/resetPwd.vue b/src/views/system/user/profile/resetPwd.vue index 73c6b18..e26db71 100644 --- a/src/views/system/user/profile/resetPwd.vue +++ b/src/views/system/user/profile/resetPwd.vue @@ -1,59 +1,81 @@