From 01d423865ae5eddf91f35c8526f5683c3b430870 Mon Sep 17 00:00:00 2001
From: Crunchy <3114200645@qq.com>
Date: 星期一, 13 一月 2025 09:30:06 +0800
Subject: [PATCH] 密码强校验添加

---
 src/views/admin/user/info.vue |  503 ++++++++++++++++++++++++++++++-------------------------
 1 files changed, 274 insertions(+), 229 deletions(-)

diff --git a/src/views/admin/user/info.vue b/src/views/admin/user/info.vue
index b7fb0b1..f220390 100644
--- a/src/views/admin/user/info.vue
+++ b/src/views/admin/user/info.vue
@@ -16,269 +16,314 @@
   -->
 
 <template>
-  <div class="app-container calendar-list-container">
-    <basic-container>
-      <template>
-        <el-tabs v-model="switchStatus" @tab-click="switchTab" style="padding-left:20px">
-          <el-tab-pane label="淇℃伅绠$悊" name="userManager"/>
-          <el-tab-pane label="瀵嗙爜绠$悊" name="passwordManager"/>
-        </el-tabs>
-      </template>
-      <el-row>
-        <el-col :span="12">
-          <div class="grid-content bg-purple">
-            <el-form
-              v-if="switchStatus==='userManager'"
-              ref="ruleForm2"
-              :model="ruleForm2"
-              :rules="rules2"
-              label-width="100px"
-              class="demo-ruleForm">
-              <el-form-item
-                label="鐢ㄦ埛鍚�"
-                prop="username">
-                <el-input
-                  v-model="ruleForm2.username"
-                  type="text"
-                  disabled/>
-              </el-form-item>
-              <el-form-item label="鎵嬫満鍙�" prop="phone">
-                <el-input v-model="ruleForm2.phone" placeholder="楠岃瘉鐮佺櫥褰曚娇鐢�"/>
-              </el-form-item>
-              <el-form-item label="澶村儚">
-                <el-upload
-                  :headers="headers"
-                  :show-file-list="false"
-                  :on-success="handleAvatarSuccess"
-                  class="avatar-uploader"
-                  action="/admin/sys-file/upload">
-                  <img v-if="ruleForm2.avatar" id="avatar" :src="avatarUrl" class="avatar">
-                  <i v-else class="el-icon-plus avatar-uploader-icon"/>
-                </el-upload>
-              </el-form-item>
-              <!-- <el-form-item
-                label="绀句氦鐧诲綍"
-                prop="social">
-                <a
-                  href="#"
-                  style="color: blue"
-                  @click="handleClick('wechat')">缁戝畾寰俊</a>锝�
-                <a
-                  href="#"
-                  style="color: blue"
-                  @click="handleClick('gitee')">缁戝畾鐮佷簯</a> |
-                <a
-                  href="#"
-                  style="color: blue"
-                  @click="handleClick('osc')">寮�婧愪腑鍥�</a>
-              </el-form-item> -->
-              <el-form-item>
-                <el-button
-                  type="primary"
-                  @click="submitForm('ruleForm2')">鎻愪氦
-                </el-button>
-                <el-button @click="resetForm('ruleForm2')">閲嶇疆</el-button>
-              </el-form-item>
-            </el-form>
-            <el-form
-              v-if="switchStatus==='passwordManager'"
-              ref="ruleForm2"
-              :model="ruleForm2"
-              :rules="rules2"
-              label-width="100px"
-              class="demo-ruleForm">
-              <el-form-item
-                label="鍘熷瘑鐮�"
-                prop="password">
-                <el-input
-                  v-model="ruleForm2.password"
-                  type="password"
-                  auto-complete="off"/>
-              </el-form-item>
-              <el-form-item
-                label="瀵嗙爜"
-                prop="newpassword1">
-                <el-input
-                  v-model="ruleForm2.newpassword1"
-                  type="password"
-                  auto-complete="off"/>
-              </el-form-item>
-              <el-form-item
-                label="纭瀵嗙爜"
-                prop="newpassword2">
-                <el-input
-                  v-model="ruleForm2.newpassword2"
-                  type="password"
-                  auto-complete="off"/>
-              </el-form-item>
-              <el-form-item>
-                <el-button
-                  type="primary"
-                  @click="submitForm('ruleForm2')">鎻愪氦
-                </el-button>
-                <el-button @click="resetForm('ruleForm2')">閲嶇疆</el-button>
-              </el-form-item>
-            </el-form>
-          </div>
-        </el-col>
-      </el-row>
-    </basic-container>
-  </div>
+    <div class="app-container calendar-list-container">
+        <basic-container>
+            <template>
+                <el-tabs @tab-click="switchTab">
+                    <el-tab-pane label="淇℃伅绠$悊" name="userManager" />
+                    <el-tab-pane label="瀵嗙爜绠$悊" name="passwordManager" />
+                </el-tabs>
+            </template>
+            <el-row>
+                <el-col :span="12">
+                    <div class="grid-content bg-purple">
+                        <el-form v-if="switchStatus === 'userManager'" ref="ruleForm2" :model="ruleForm2" :rules="rules2" label-width="100px" class="demo-ruleForm">
+                            <el-form-item label="鐢ㄦ埛鍚�" prop="username">
+                                <el-input v-model="ruleForm2.username" type="text" disabled />
+                            </el-form-item>
+                            <el-form-item label="鎵嬫満鍙�" prop="phone">
+                                <el-input v-model="ruleForm2.phone" placeholder="楠岃瘉鐮佺櫥褰曚娇鐢�" />
+                            </el-form-item>
+                            <el-form-item label="澶村儚">
+                                <el-upload :headers="headers" :show-file-list="false" :on-success="handleAvatarSuccess" class="avatar-uploader" action="/admin/sys-file/upload">
+                                    <img v-if="ruleForm2.avatar" id="avatar" :src="avatarUrl" class="avatar" />
+                                    <i v-else class="el-icon-plus avatar-uploader-icon" />
+                                </el-upload>
+                            </el-form-item>
+                            <el-form-item label="绀句氦鐧诲綍" prop="social">
+                                <a href="#" style="color: blue" @click="handleClick('wechat')">缁戝畾寰俊</a>锝� <a href="#" style="color: blue" @click="handleClick('gitee')">缁戝畾鐮佷簯</a> |
+                                <a href="#" style="color: blue" @click="handleClick('osc')">寮�婧愪腑鍥�</a>
+                            </el-form-item>
+                            <el-form-item>
+                                <el-button type="primary" @click="submitForm('ruleForm2')">鎻愪氦 </el-button>
+                                <el-button @click="resetForm('ruleForm2')">閲嶇疆</el-button>
+                            </el-form-item>
+                        </el-form>
+                        <el-form v-if="switchStatus === 'passwordManager'" ref="ruleForm2" :model="ruleForm2" :rules="rules2" label-width="100px" class="demo-ruleForm">
+                            <el-form-item label="鍘熷瘑鐮�" prop="password">
+                                <el-input v-model="ruleForm2.password" type="password" auto-complete="off" />
+                            </el-form-item>
+                            <el-form-item label="瀵嗙爜" prop="newpassword1">
+                                <div class="password-input-container">
+                                    <el-input v-model="ruleForm2.newpassword1" type="password" @input="checkPasswordStrength" show-password auto-complete="off" />
+                                    <div v-if="ruleForm2.newpassword1" class="password-strength-indicator">
+                                        瀵嗙爜寮哄害: <span :class="passwordLevelClass">{{ passwordLevel }}</span>
+                                    </div>
+                                </div>
+                            </el-form-item>
+                            <el-form-item label="纭瀵嗙爜" prop="newpassword2">
+                                <el-input v-model="ruleForm2.newpassword2" type="password" auto-complete="off" />
+                            </el-form-item>
+                            <el-form-item>
+                                <el-button type="primary" @click="submitForm('ruleForm2')">鎻愪氦 </el-button>
+                                <el-button @click="resetForm('ruleForm2')">閲嶇疆</el-button>
+                            </el-form-item>
+                        </el-form>
+                    </div>
+                </el-col>
+            </el-row>
+        </basic-container>
+    </div>
 </template>
 
 <script>
-  import {handleImg, openWindow} from '@/util/util'
-  import {mapState} from 'vuex'
-  import store from '@/store'
-  import {getStore, setStore} from '@/util/store'
-  import {editInfo} from '@/api/admin/user'
+import { handleImg, openWindow } from '@/util/util'
+import { mapState } from 'vuex'
+import store from '@/store'
+import { getStore, setStore } from '@/util/store'
+import { editInfo } from '@/api/admin/user'
 
-
-  export default {
+export default {
     data() {
-      var validatePass = (rule, value, callback) => {
-        if (this.ruleForm2.password !== '') {
-          if (value !== this.ruleForm2.newpassword1) {
-            callback(new Error('涓ゆ杈撳叆瀵嗙爜涓嶄竴鑷�!'))
-          } else {
-            callback()
-          }
-        } else {
-          callback()
+        // 瀵嗙爜寮哄害鏍¢獙
+        const validatePasswordStrength = (rule, value, callback) => {
+            let strength = 0
+
+            if (value.length >= 8) strength++
+            if (/\d/.test(value)) strength++
+            if (/[a-z]/.test(value)) strength++
+            if (/[A-Z]/.test(value)) strength++
+            if (/[!@#$%^&*]/.test(value)) strength++
+
+            if (strength < 4) {
+                callback(new Error('瀵嗙爜寮哄害涓嶅锛岃纭繚瀵嗙爜鍖呭惈锛氬ぇ灏忓啓瀛楁瘝銆佹暟瀛楀拰鐗规畩瀛楃锛屼笖闀垮害涓嶅皯浜�8浣�'))
+            } else {
+                callback()
+            }
         }
-      }
-      return {
-        switchStatus: 'userManager',
-        avatarUrl: '',
-        show: false,
-        headers: {
-          'Authorization': 'Bearer ' + store.getters.access_token,
-        },
-        ruleForm2: {
-          username: '',
-          password: '',
-          newpassword1: '',
-          newpassword2: '',
-          avatar: '',
-          phone: ''
-        },
-        rules2: {
-          password: [{required: true, min: 6, message: '鍘熷瘑鐮佷笉鑳戒负绌轰笖涓嶅皯浜�6浣�', trigger: 'change'}],
-          newpassword1: [{required: false, min: 6, message: '涓嶅皯浜�6浣�', trigger: 'change'}],
-          newpassword2: [{required: false, validator: validatePass, trigger: 'blur'}]
+
+        // 纭瀵嗙爜鏍¢獙
+        var validatePass = (rule, value, callback) => {
+            if (this.ruleForm2.password !== '') {
+                if (value !== this.ruleForm2.newpassword1) {
+                    callback(new Error('涓ゆ杈撳叆瀵嗙爜涓嶄竴鑷�!'))
+                } else {
+                    callback()
+                }
+            } else {
+                callback()
+            }
         }
-      }
+
+        return {
+            switchStatus: 'userManager',
+            avatarUrl: '',
+            show: false,
+            headers: {
+                Authorization: 'Bearer ' + store.getters.access_token
+            },
+            ruleForm2: {
+                username: '',
+                password: '',
+                newpassword1: '',
+                newpassword2: '',
+                avatar: '',
+                phone: ''
+            },
+            passwordLevel: '', // 瀵嗙爜寮哄害绾у埆
+            passwordLevelClass: '', // 瀵嗙爜寮哄害鏍峰紡绫�
+            rules2: {
+                password: [
+                    {
+                        required: true,
+                        min: 8,
+                        message: '鍘熷瘑鐮佷笉鑳戒负绌轰笖涓嶅皯浜�8浣�',
+                        trigger: 'change'
+                    }
+                ],
+                newpassword1: [{ required: true, message: '璇疯緭鍏ユ柊瀵嗙爜', trigger: 'blur' }, { validator: validatePasswordStrength, trigger: 'blur' }],
+                newpassword2: [
+                    {
+                        required: true,
+                        validator: validatePass,
+                        trigger: 'blur'
+                    }
+                ]
+            }
+        }
     },
     created() {
-      this.resetForm()
+        this.resetForm()
     },
     computed: {
-      ...mapState({
-        userInfo: state => state.user.userInfo
-      })
+        ...mapState({
+            userInfo: (state) => state.user.userInfo
+        })
     },
     methods: {
-      switchTab(tab) {
-        if (tab.name === 'userManager') {
-          handleImg(this.ruleForm2.avatar, 'avatar')
-        }
-        this.switchStatus = tab.name
-      },
-      submitForm(formName) {
-        this.$refs[formName].validate(valid => {
-          if (!valid) {
-            return false
-          }
-          editInfo(this.ruleForm2).then(response => {
-            this.handleLocalData(this.ruleForm2)
-            this.$notify.success('淇敼鎴愬姛')
-            // 淇敼瀵嗙爜涔嬪悗寮哄埗閲嶆柊鐧诲綍
-            if (this.switchStatus === 'passwordManager') {
-              this.$store.dispatch('LogOut').then(() => {
-                location.reload() // 涓轰簡閲嶆柊瀹炰緥鍖杤ue-router瀵硅薄 閬垮厤bug
-              })
+        switchTab(tab) {
+            if (tab.name === 'userManager') {
+                handleImg(this.ruleForm2.avatar, 'avatar')
             }
-          })
-        })
-      },
-      resetForm() {
-        this.ruleForm2.password = undefined
-        this.ruleForm2.newpassword1 = undefined
-        this.ruleForm2.newpassword2 = undefined
-        this.ruleForm2.username = this.userInfo.username
-        this.ruleForm2.phone = this.userInfo.phone
-        this.ruleForm2.avatar = this.userInfo.avatar
-        handleImg(this.userInfo.avatar, 'avatar')
-        //鍒ゆ柇鏄惁閫夋嫨浜嗙鎴稩D
-        const TENANT_ID = getStore({name: 'tenantId'})
-        if (TENANT_ID) {
-          this.headers['TENANT-ID'] = TENANT_ID // 绉熸埛ID
-        }
-      },
-      handleClick(thirdpart) {
-        let appid, client_id, redirect_uri, url
-        redirect_uri = encodeURIComponent(window.location.origin + '/#/authredirect')
-        if (thirdpart === 'wechat') {
-          appid = 'wxd1678d3f83b1d83a'
-          url = 'https://open.weixin.qq.com/connect/qrconnect?appid=' + appid + '&redirect_uri=' + redirect_uri + '&state=WX-BIND&response_type=code&scope=snsapi_login#wechat_redirect'
-        } else if (thirdpart === 'tencent') {
-          client_id = '101322838'
-          url = 'https://graph.qq.com/oauth2.0/authorize?response_type=code&state=QQ-BIND&client_id=' + client_id + '&redirect_uri=' + redirect_uri
-        } else if (thirdpart === 'gitee') {
-          client_id = '235ce26bbc59565b82c989aa3a407ce844cf59a7c5e0f9caa9bb3bf32cee5952'
-          url = 'https://gitee.com/oauth/authorize?response_type=code&state=GITEE-BIND&client_id=' + client_id + '&redirect_uri=' + redirect_uri
-        } else if (thirdpart === 'osc') {
-          client_id = 'neIIqlwGsjsfsA6uxNqD'
-          url = 'https://www.oschina.net/action/oauth2/authorize?response_type=code&client_id=' + client_id + '&state=OSC-BIND&redirect_uri=' + redirect_uri
-        }
-        openWindow(url, thirdpart, 540, 540)
-      },
-      handleAvatarSuccess(res, file) {
-        this.avatarUrl = URL.createObjectURL(file.raw)
-        this.ruleForm2.avatar = res.data.url
-      },
-      // 澶勭悊鏈湴鏁版嵁锛岄伩鍏嶅埛鏂颁笉鍚屾
-      handleLocalData(form) {
-        let userInfo = getStore({name: 'userInfo'})
+            this.switchStatus = tab.name
+        },
+        submitForm(formName) {
+            this.$refs[formName].validate((valid) => {
+                if (!valid) {
+                    return false
+                }
+                editInfo(this.ruleForm2).then((response) => {
+                    this.handleLocalData(this.ruleForm2)
+                    this.$notify.success('淇敼鎴愬姛')
+                    // 淇敼瀵嗙爜涔嬪悗寮哄埗閲嶆柊鐧诲綍
+                    if (this.switchStatus === 'passwordManager') {
+                        this.$store.dispatch('LogOut').then(() => {
+                            location.reload() // 涓轰簡閲嶆柊瀹炰緥鍖杤ue-router瀵硅薄 閬垮厤bug
+                        })
+                    }
+                })
+            })
+        },
+        resetForm() {
+            this.ruleForm2.password = undefined
+            this.ruleForm2.newpassword1 = undefined
+            this.ruleForm2.newpassword2 = undefined
+            this.ruleForm2.username = this.userInfo.username
+            this.ruleForm2.phone = this.userInfo.phone
+            this.ruleForm2.avatar = this.userInfo.avatar
+            handleImg(this.userInfo.avatar, 'avatar')
+            //鍒ゆ柇鏄惁閫夋嫨浜嗙鎴稩D
+            const TENANT_ID = getStore({ name: 'tenantId' })
+            if (TENANT_ID) {
+                this.headers['TENANT-ID'] = TENANT_ID // 绉熸埛ID
+            }
+        },
+        handleClick(thirdpart) {
+            let appid, client_id, redirect_uri, url
+            redirect_uri = encodeURIComponent(window.location.origin + '/#/authredirect')
+            if (thirdpart === 'wechat') {
+                appid = 'wxd1678d3f83b1d83a'
+                url = 'https://open.weixin.qq.com/connect/qrconnect?appid=' + appid + '&redirect_uri=' + redirect_uri + '&state=WX-BIND&response_type=code&scope=snsapi_login#wechat_redirect'
+            } else if (thirdpart === 'tencent') {
+                client_id = '101322838'
+                url = 'https://graph.qq.com/oauth2.0/authorize?response_type=code&state=QQ-BIND&client_id=' + client_id + '&redirect_uri=' + redirect_uri
+            } else if (thirdpart === 'gitee') {
+                client_id = '235ce26bbc59565b82c989aa3a407ce844cf59a7c5e0f9caa9bb3bf32cee5952'
+                url = 'https://gitee.com/oauth/authorize?response_type=code&state=GITEE-BIND&client_id=' + client_id + '&redirect_uri=' + redirect_uri
+            } else if (thirdpart === 'osc') {
+                client_id = 'neIIqlwGsjsfsA6uxNqD'
+                url = 'https://www.oschina.net/action/oauth2/authorize?response_type=code&client_id=' + client_id + '&state=OSC-BIND&redirect_uri=' + redirect_uri
+            }
+            openWindow(url, thirdpart, 540, 540)
+        },
+        handleAvatarSuccess(res, file) {
+            this.avatarUrl = URL.createObjectURL(file.raw)
+            this.ruleForm2.avatar = res.data.url
+        },
+        // 澶勭悊鏈湴鏁版嵁锛岄伩鍏嶅埛鏂颁笉鍚屾
+        handleLocalData(form) {
+            let userInfo = getStore({ name: 'userInfo' })
 
-        if (userInfo) {
-          userInfo.avatar = form.avatar
-          userInfo.phone = form.phone
-          setStore({
-            name: 'userInfo',
-            content: userInfo,
-            type: 'session'
-          })
+            if (userInfo) {
+                userInfo.avatar = form.avatar
+                userInfo.phone = form.phone
+                setStore({
+                    name: 'userInfo',
+                    content: userInfo,
+                    type: 'session'
+                })
+            }
+        },
+        // 妫�鏌ュ瘑鐮佸己搴�
+        checkPasswordStrength(password) {
+            let strength = 0
+
+            // 妫�鏌ラ暱搴�
+            if (password.length >= 8) strength++
+
+            // 妫�鏌ユ槸鍚﹀寘鍚暟瀛�
+            if (/\d/.test(password)) strength++
+
+            // 妫�鏌ユ槸鍚﹀寘鍚皬鍐欏瓧姣�
+            if (/[a-z]/.test(password)) strength++
+
+            // 妫�鏌ユ槸鍚﹀寘鍚ぇ鍐欏瓧姣�
+            if (/[A-Z]/.test(password)) strength++
+
+            // 妫�鏌ユ槸鍚﹀寘鍚壒娈婂瓧绗�
+            if (/[!@#$%^&*]/.test(password)) strength++
+
+            switch (strength) {
+                case 0:
+                case 1:
+                    this.passwordLevel = '寮�'
+                    this.passwordLevelClass = 'password-weak'
+                    break
+                case 2:
+                case 3:
+                    this.passwordLevel = '涓�'
+                    this.passwordLevelClass = 'password-medium'
+                    break
+                case 4:
+                case 5:
+                    this.passwordLevel = '寮�'
+                    this.passwordLevelClass = 'password-strong'
+                    break
+            }
         }
-      }
     }
-  }
+}
 </script>
 <style>
-  .avatar-uploader .el-upload {
+.avatar-uploader .el-upload {
     border: 1px dashed #d9d9d9;
     border-radius: 6px;
     cursor: pointer;
     position: relative;
     overflow: hidden;
-  }
+}
 
-  .avatar-uploader .el-upload:hover {
-    border-color: #409EFF;
-  }
+.avatar-uploader .el-upload:hover {
+    border-color: #409eff;
+}
 
-  .avatar-uploader-icon {
+.avatar-uploader-icon {
     font-size: 28px !important;
     color: #8c939d !important;
     width: 178px !important;
     height: 178px !important;
     line-height: 178px !important;
     text-align: center !important;
-  }
+}
 
-  .avatar {
+.avatar {
     width: 178px;
     height: 178px;
     display: block;
-  }
+}
+
+.password-input-container {
+    width: 100%;
+    .el-input {
+        width: 100%;
+    }
+}
+
+.password-strength-indicator {
+    margin-top: 5px;
+    font-size: 12px;
+    color: #606266;
+}
+
+.password-weak {
+    color: #f56c6c;
+}
+
+.password-medium {
+    color: #e6a23c;
+}
+
+.password-strong {
+    color: #67c23a;
+}
 </style>

--
Gitblit v1.9.3