| | |
| | | --> |
| | | |
| | | <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() // 为了重新实例化vue-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') |
| | | //判断是否选择了租户ID |
| | | 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() // 为了重新实例化vue-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') |
| | | //判断是否选择了租户ID |
| | | 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> |