Pre Merge pull request !204 from 云飞扬/N/A
This commit is contained in:
commit
97370cf034
|
|
@ -0,0 +1,127 @@
|
||||||
|
<template>
|
||||||
|
<div class="check-list" :key="pagek">
|
||||||
|
<div class="check-list__title">{{ title }}</div>
|
||||||
|
<div v-for="{ key, label } in options" :key="key">
|
||||||
|
<div class="check-list-item">
|
||||||
|
<span class="check-list-item__prefix">
|
||||||
|
<i
|
||||||
|
v-if="isEqual(key, 'success')"
|
||||||
|
class="iconfont el-icon-success"
|
||||||
|
></i>
|
||||||
|
<i
|
||||||
|
v-else-if="isEqual(key, 'error')"
|
||||||
|
class="iconfont el-icon-error"
|
||||||
|
></i>
|
||||||
|
<i
|
||||||
|
v-else-if="isEqual(key, 'warning')"
|
||||||
|
class="iconfont el-icon-warning"
|
||||||
|
></i>
|
||||||
|
<i v-else-if="isEqual(key, 'info')" class="el-icon-info"></i>
|
||||||
|
<i v-else class="iconfont el-icon-pending"></i>
|
||||||
|
</span>
|
||||||
|
<div class="check-list-label">{{ label }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'CheckList',
|
||||||
|
props: {
|
||||||
|
pagek: {
|
||||||
|
default: new Date().getTime()
|
||||||
|
},
|
||||||
|
values: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
},
|
||||||
|
data: ()=>{
|
||||||
|
return{
|
||||||
|
status : ["pending", "success", "error", "warning", "info"],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
defaultStatus() {
|
||||||
|
return this.options.reduce(
|
||||||
|
(res, {key}) => Object.assign(res, {[key]: this.status[0]}),
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
statusMap() {
|
||||||
|
return Object.assign({}, this.defaultStatus(), this.values);
|
||||||
|
},
|
||||||
|
isEqual(key, statusCode){
|
||||||
|
return this.statusMap()[key] == statusCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 胶囊状态颜色
|
||||||
|
.el-icon-success {
|
||||||
|
color: #40b828;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon-error {
|
||||||
|
color: #f0553a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon-warning {
|
||||||
|
color: #fc971c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon-info {
|
||||||
|
color: #878e99;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon-pending {
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
display: inline-flex;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border: 2px solid rgba(#000, 0.15);
|
||||||
|
border-radius: 50%;
|
||||||
|
// vertical-align: baseline;
|
||||||
|
// margin-bottom: -2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-list {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-list__title {
|
||||||
|
line-height: 20px;
|
||||||
|
color: #fc971c;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-list-item {
|
||||||
|
line-height: 20px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-list-item__prefix {
|
||||||
|
float: left;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.check-list-label {
|
||||||
|
margin-left: 16px + 12px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
import Password from "./index.vue";
|
||||||
|
import {usePassword} from "./utils";
|
||||||
|
|
||||||
|
export {usePassword};
|
||||||
|
|
||||||
|
export default Password;
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
<template>
|
||||||
|
<el-popover popper-class="gt-password-popper" v-bind="popoverOptions">
|
||||||
|
<template slot="reference">
|
||||||
|
<el-input
|
||||||
|
class="gt-password"
|
||||||
|
v-bind="$attrs"
|
||||||
|
v-on="$listeners"
|
||||||
|
type="password"
|
||||||
|
show-password
|
||||||
|
>
|
||||||
|
</el-input>
|
||||||
|
</template>
|
||||||
|
<CheckList
|
||||||
|
:pagek="pagek"
|
||||||
|
:values="checkValuesObj"
|
||||||
|
title="密码必须包括"
|
||||||
|
:options="checkList"
|
||||||
|
/>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import CheckList from "./CheckList.vue";
|
||||||
|
|
||||||
|
const popDefault = {
|
||||||
|
placement: "right-start",
|
||||||
|
width: 228,
|
||||||
|
trigger: "focus"
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Password',
|
||||||
|
components: {CheckList},
|
||||||
|
props: {
|
||||||
|
checkList: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
popover: {
|
||||||
|
type: Array,
|
||||||
|
required: false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data: () => {
|
||||||
|
return {
|
||||||
|
pagek: new Date().getTime(),
|
||||||
|
popoverOptions: {},
|
||||||
|
checkValuesObj: {},
|
||||||
|
passwordType: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.popoverOptions = {...this.popover, ...popDefault};
|
||||||
|
this.update(this.checkList);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
update(validList, clear = false) {
|
||||||
|
// 每次update 前先清空 checkValuesObj
|
||||||
|
Object.keys(this.checkValuesObj).forEach(v => {
|
||||||
|
this.checkValuesObj[v] = "";
|
||||||
|
});
|
||||||
|
|
||||||
|
let tempObj = {};
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.pagek = new Date().getTime();
|
||||||
|
tempObj =
|
||||||
|
validList.length > 0 &&
|
||||||
|
validList.reduce(
|
||||||
|
(res = {}, key = "1") => Object.assign(res, {[key]: "success"}),
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tempObj) {
|
||||||
|
Object.keys(tempObj).forEach(v => {
|
||||||
|
this.checkValuesObj[v] = tempObj[v];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (clear) {
|
||||||
|
Object.keys(this.checkValuesObj).forEach(v => {
|
||||||
|
this.checkValuesObj[v] = "";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
export const usePassword = (options) => {
|
||||||
|
const defaultRules = [
|
||||||
|
{
|
||||||
|
key: "length",
|
||||||
|
label: "长度在6到20个字符",
|
||||||
|
regExp: /^.{10,20}$/
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "lowercase",
|
||||||
|
label: "使用小写字母",
|
||||||
|
regExp: /[a-z]+/
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "capital",
|
||||||
|
label: "用大写字母",
|
||||||
|
regExp: /[A-Z]+/
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "number",
|
||||||
|
label: "使用数字",
|
||||||
|
regExp: /\d{1,}/
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const ruleItems = options
|
||||||
|
? options.reduce((res, item) => {
|
||||||
|
if (typeof item === "string") {
|
||||||
|
const rule = defaultRules.find(i => item === i.key);
|
||||||
|
if (rule) {
|
||||||
|
res.push(rule);
|
||||||
|
} else {
|
||||||
|
throw new Error("无效的规则");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.push(item);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}, [])
|
||||||
|
: [...defaultRules];
|
||||||
|
// 返回默认的匹配规则map 和 校验结果mapList
|
||||||
|
return {
|
||||||
|
checkList: ruleItems.map(({key, label}) => ({key, label})),
|
||||||
|
validate: (value) => {
|
||||||
|
// 过滤出符合正则的rule[], map返回key[]
|
||||||
|
const validList = ruleItems
|
||||||
|
.filter(({regExp, validator}) => {
|
||||||
|
if (validator) {
|
||||||
|
return validator(value);
|
||||||
|
} else if (regExp) {
|
||||||
|
return regExp.test(value);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.map(({key}) => {
|
||||||
|
return key;
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
validList,
|
||||||
|
valid: validList.length === ruleItems.length
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -238,7 +238,13 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item v-if="form.userId == undefined" label="用户密码" prop="password">
|
<el-form-item v-if="form.userId == undefined" label="用户密码" prop="password">
|
||||||
<el-input v-model="form.password" placeholder="请输入用户密码" type="password" maxlength="20" show-password/>
|
<Password
|
||||||
|
ref="passwordRef"
|
||||||
|
v-model="form.password"
|
||||||
|
:check-list="checkList"
|
||||||
|
placeholder="请输入用户密码"
|
||||||
|
>
|
||||||
|
</Password>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
@ -342,16 +348,18 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import Password,{ usePassword} from '@/components/Password'
|
||||||
import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus } from "@/api/system/user";
|
import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus } from "@/api/system/user";
|
||||||
import { getToken } from "@/utils/auth";
|
import { getToken } from "@/utils/auth";
|
||||||
import { treeselect } from "@/api/system/dept";
|
import { treeselect } from "@/api/system/dept";
|
||||||
import Treeselect from "@riophae/vue-treeselect";
|
import Treeselect from "@riophae/vue-treeselect";
|
||||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||||
|
let passwordE = null;// password 组件元素相关校验逻辑
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "User",
|
name: "User",
|
||||||
dicts: ['sys_normal_disable', 'sys_user_sex'],
|
dicts: ['sys_normal_disable', 'sys_user_sex'],
|
||||||
components: { Treeselect },
|
components: { Treeselect, Password },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// 遮罩层
|
// 遮罩层
|
||||||
|
|
@ -384,6 +392,7 @@ export default {
|
||||||
postOptions: [],
|
postOptions: [],
|
||||||
// 角色选项
|
// 角色选项
|
||||||
roleOptions: [],
|
roleOptions: [],
|
||||||
|
checkList: [],
|
||||||
// 表单参数
|
// 表单参数
|
||||||
form: {},
|
form: {},
|
||||||
defaultProps: {
|
defaultProps: {
|
||||||
|
|
@ -435,7 +444,17 @@ export default {
|
||||||
],
|
],
|
||||||
password: [
|
password: [
|
||||||
{ required: true, message: "用户密码不能为空", trigger: "blur" },
|
{ required: true, message: "用户密码不能为空", trigger: "blur" },
|
||||||
{ min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' }
|
{ type: String, validator: (rule, value, callback)=>{
|
||||||
|
let { validList = [], valid } = passwordE.validate(value)
|
||||||
|
this.$refs.passwordRef.update(validList)
|
||||||
|
// 几条规则是否都以校验完成,否则会有无效密码提示
|
||||||
|
if (!valid) {
|
||||||
|
callback(new Error("无效密码"));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}, trigger: ["change", "blur"]
|
||||||
|
}
|
||||||
],
|
],
|
||||||
email: [
|
email: [
|
||||||
{
|
{
|
||||||
|
|
@ -461,6 +480,8 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
passwordE = usePassword();
|
||||||
|
this.checkList = passwordE.checkList;
|
||||||
this.getList();
|
this.getList();
|
||||||
this.getTreeselect();
|
this.getTreeselect();
|
||||||
this.getConfigKey("sys.user.initPassword").then(response => {
|
this.getConfigKey("sys.user.initPassword").then(response => {
|
||||||
|
|
@ -588,17 +609,21 @@ export default {
|
||||||
},
|
},
|
||||||
/** 重置密码按钮操作 */
|
/** 重置密码按钮操作 */
|
||||||
handleResetPwd(row) {
|
handleResetPwd(row) {
|
||||||
|
let rulesMsg = passwordE.checkList.map(item=> item.label);
|
||||||
this.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
|
this.$prompt('请输入"' + row.userName + '"的新密码', "提示", {
|
||||||
confirmButtonText: "确定",
|
confirmButtonText: "确定",
|
||||||
cancelButtonText: "取消",
|
cancelButtonText: "取消",
|
||||||
closeOnClickModal: false,
|
closeOnClickModal: false,
|
||||||
inputPattern: /^.{5,20}$/,
|
inputValidator: (value) => {
|
||||||
inputErrorMessage: "用户密码长度必须介于 5 和 20 之间"
|
let { validList = [], valid } = passwordE.validate(value)
|
||||||
|
return valid;
|
||||||
|
},
|
||||||
|
inputErrorMessage: "用户密码" + rulesMsg
|
||||||
}).then(({ value }) => {
|
}).then(({ value }) => {
|
||||||
resetUserPwd(row.userId, value).then(response => {
|
resetUserPwd(row.userId, value).then(response => {
|
||||||
this.$modal.msgSuccess("修改成功,新密码是:" + value);
|
this.$modal.msgSuccess("修改成功,新密码是:" + value);
|
||||||
});
|
});
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
},
|
},
|
||||||
/** 分配角色操作 */
|
/** 分配角色操作 */
|
||||||
handleAuthRole: function(row) {
|
handleAuthRole: function(row) {
|
||||||
|
|
@ -669,4 +694,10 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
<style rel="stylesheet/scss" lang="scss">
|
||||||
|
/*禁止浏览器显示密码框选择*/
|
||||||
|
input[type="password" i] {
|
||||||
|
-webkit-text-security: disc !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,13 @@
|
||||||
<el-input v-model="user.oldPassword" placeholder="请输入旧密码" type="password" show-password/>
|
<el-input v-model="user.oldPassword" placeholder="请输入旧密码" type="password" show-password/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="新密码" prop="newPassword">
|
<el-form-item label="新密码" prop="newPassword">
|
||||||
<el-input v-model="user.newPassword" placeholder="请输入新密码" type="password" show-password/>
|
<Password
|
||||||
|
ref="passwordRef"
|
||||||
|
v-model="user.newPassword"
|
||||||
|
:check-list="checkList"
|
||||||
|
placeholder="请输入新密码"
|
||||||
|
>
|
||||||
|
</Password>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="确认密码" prop="confirmPassword">
|
<el-form-item label="确认密码" prop="confirmPassword">
|
||||||
<el-input v-model="user.confirmPassword" placeholder="请确认新密码" type="password" show-password/>
|
<el-input v-model="user.confirmPassword" placeholder="请确认新密码" type="password" show-password/>
|
||||||
|
|
@ -18,8 +24,14 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { updateUserPwd } from "@/api/system/user";
|
import { updateUserPwd } from "@/api/system/user";
|
||||||
|
import Password,{ usePassword} from '@/components/Password'
|
||||||
|
let passwordE = null;// password 组件元素相关校验逻辑
|
||||||
export default {
|
export default {
|
||||||
|
components: { Password },
|
||||||
|
created() {
|
||||||
|
passwordE = usePassword();
|
||||||
|
this.checkList = passwordE.checkList;
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
const equalToPassword = (rule, value, callback) => {
|
const equalToPassword = (rule, value, callback) => {
|
||||||
if (this.user.newPassword !== value) {
|
if (this.user.newPassword !== value) {
|
||||||
|
|
@ -29,6 +41,7 @@ export default {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
|
checkList: [],
|
||||||
user: {
|
user: {
|
||||||
oldPassword: undefined,
|
oldPassword: undefined,
|
||||||
newPassword: undefined,
|
newPassword: undefined,
|
||||||
|
|
@ -41,7 +54,17 @@ export default {
|
||||||
],
|
],
|
||||||
newPassword: [
|
newPassword: [
|
||||||
{ required: true, message: "新密码不能为空", trigger: "blur" },
|
{ required: true, message: "新密码不能为空", trigger: "blur" },
|
||||||
{ min: 6, max: 20, message: "长度在 6 到 20 个字符", trigger: "blur" }
|
{ type: String, validator: (rule, value, callback)=>{
|
||||||
|
let { validList = [], valid } = passwordE.validate(value)
|
||||||
|
this.$refs.passwordRef.update(validList)
|
||||||
|
// 几条规则是否都以校验完成,否则会有无效密码提示
|
||||||
|
if (!valid) {
|
||||||
|
callback(new Error("无效密码"));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}, trigger: ["change", "blur"]
|
||||||
|
}
|
||||||
],
|
],
|
||||||
confirmPassword: [
|
confirmPassword: [
|
||||||
{ required: true, message: "确认密码不能为空", trigger: "blur" },
|
{ required: true, message: "确认密码不能为空", trigger: "blur" },
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue