You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

888 lines
26 KiB

4 years ago
<template>
<div class="app-container">
<el-row :gutter="20">
<el-col :span="24">
<!--工具栏-->
<div class="head-container">
<div class="opts">
<el-button
class="filter-item addbutton"
size="mini"
icon="el-icon-plus"
@click="handleCreate"
v-permission="['AbpIdentity.Users.Create']"
>新增</el-button
>
<el-button
class="filter-item modifybutton"
size="mini"
icon="el-icon-edit"
v-permission="['AbpIdentity.Users.Update']"
@click="handleUpdate()"
>修改</el-button
>
<!-- 搜索 -->
<el-input
v-model="listQuery.Filter"
clearable
size="small"
placeholder="搜索..."
style="width: 200px;margin-left: 10px;margin-right: 5px;"
class="filter-item"
@keyup.enter.native="handleFilter"
/>
<el-button
class="filter-item searchbutton"
size="mini"
type="success"
icon="el-icon-search"
@click="handleFilter"
>搜索</el-button
>
</div>
</div>
<!--表单渲染-->
<el-dialog
:visible.sync="dialogFormVisible"
:close-on-click-modal="false"
:title="formTitle"
@close="cancel()"
width="600px"
>
<el-form
ref="form"
:inline="true"
:model="form"
:rules="rules"
size="small"
label-width="70px"
>
<el-form-item label="用户名" prop="userName">
<el-input
v-model="form.userName"
style="width: 184px"
maxlength="50"
/>
</el-form-item>
<el-form-item label="电话" prop="phoneNumber">
<el-input
v-model="form.phoneNumber"
style="width: 184px"
maxlength="20"
/>
</el-form-item>
<el-form-item label="姓名" prop="name">
<el-input
v-model="form.name"
style="width: 184px"
maxlength="60"
/>
</el-form-item>
<el-form-item label="邮箱" prop="email">
<el-input
v-model="form.email"
style="width: 184px"
maxlength="80"
/>
</el-form-item>
<el-form-item label="角色" prop="roles">
<el-select
v-model="checkedRole"
multiple
style="width: 188px"
placeholder="请选择"
>
<el-option
v-for="item in roleList"
:key="item.name"
:label="item.name"
:value="item.name"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="密码" prop="password" v-show="!isEdit">
<el-input
type="password"
v-model="form.password"
style="width: 184px"
maxlength="20"
/>
</el-form-item>
<!-- <el-form-item label="允许锁定">
<el-radio-group v-model="form.lockoutEnabled" style="width: 178px">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</el-form-item> -->
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="text" @click="cancel">取消</el-button>
<el-button v-loading="formLoading" type="primary" @click="save"
>确认</el-button
>
</div>
</el-dialog>
<!--表格渲染-->
<el-table
ref="multipleTable"
v-loading="listLoading"
:data="list"
size="small"
style="width: 100%"
@sort-change="sortChange"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
:height="tableHeight"
@current-change="handleSegalChange"
>
<el-table-column type="selection"></el-table-column>
<el-table-column
label="用户名"
prop="userName"
sortable="custom"
align="center"
>
<!-- <template slot-scope="{row}">
<span class="link-type" @click="handleUpdate(row)">{{row.userName}}</span>
</template> -->
</el-table-column>
<!-- <el-table-column label="所属机构" prop="orgIdToName" align="center">-->
<!-- <template slot-scope="scope">-->
<!-- <span>{{scope.row.orgIdToName}}</span>-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column
label="邮箱"
prop="email"
sortable="custom"
align="center"
>
<template slot-scope="scope">
<span>{{ scope.row.email }}</span>
</template>
</el-table-column>
<el-table-column
label="电话"
prop="phoneNumber"
sortable="custom"
align="center"
>
<template slot-scope="scope">
<span>{{ scope.row.phoneNumber }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="280">
<template slot-scope="{ row }">
<el-tooltip content="修改" placement="bottom" effect="light">
<el-button
type="primary"
size="mini"
@click="handleUpdate(row)"
v-permission="['AbpIdentity.Users.Update']"
icon="el-icon-edit"
/>
</el-tooltip>
<el-button
type="danger"
size="mini"
@click="handleDelete(row)"
:disabled="row.userName === 'admin'"
v-permission="['AbpIdentity.Users.Delete']"
icon="el-icon-delete"
/>
<!-- <el-tooltip placement="bottom" effect="light">
<div slot="content" >密码重置</div>
<el-button
type="warning"
size="mini"
@click="resetPassword(row)"
:disabled="row.userName === 'admin'"
icon="el-icon-eleme"
/>
</el-tooltip> -->
<el-tooltip
content="重置用户密码"
placement="bottom"
effect="light"
>
<el-button
type="warning"
size="mini"
@click="resetPassword(row)"
:disabled="row.userName === 'admin'"
icon="el-icon-eleme"
/>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination
v-show="totalCount > 0"
:total="totalCount"
:page.sync="page"
:limit.sync="listQuery.MaxResultCount"
@pagination="getList"
/>
</el-col>
<!-- <el-col :span="4">
<div class="head-container">
<el-input
v-model="orgName"
clearable
size="small"
placeholder="搜索组织..."
prefix-icon="el-icon-search"
class="filter-item "
@input="getOrgs"
/>
</div>
<div class="system-content">
<div class="system-view-nav"
:style="{ height: treeHeight + 'px'}"
style="background: #fff"
>
<el-tree
:data="orgData"
:load="getOrgs"
:props="defaultProps"
show-checkbox
default-expand-all
lazy
@node-click="handleNodeClick"
style="margin-top:15px"
ref="treeleft"
node-key="id"
/>
</div></div>
</el-col>
<el-col :span="6">
<div class="head-container">
<el-input
v-model="filterText"
clearable
size="small"
placeholder="搜索角色..."
prefix-icon="el-icon-search"
class="filter-item"
/>
</div>
<div class="system-content">
<div
class="system-view-nav"
:style="{ height: treeHeight + 'px' }"
style="background: #fff"
>
<el-tree
:data="roleList"
:filter-node-method="filterNode"
:props="defaultProps2"
style="margin-top: 15px"
show-checkbox
default-expand-all
node-key="id"
ref="treeright"
/>
</div>
</div>
</el-col> -->
</el-row>
</div>
</template>
<script>
import { isvalidPhone } from "@/utils/validate";
import Pagination from "@/components/Pagination";
import permission from "@/directive/permission/index.js";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import { LOAD_CHILDREN_OPTIONS } from "@riophae/vue-treeselect";
// function validCase(str) {
// var re =/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{6,}$/;
// return re.test(str);
// }
const defaultForm = {
id: undefined,
orgId: undefined,
userName: "",
phoneNumber: "",
name: "",
email: "",
password: "",
lockoutEnabled: false,
roleNames: [],
jobs: [],
orgIdToName: null,
};
export default {
name: "User",
components: { Pagination, Treeselect },
directives: { permission },
data() {
const validateNameInput = (rule, value, callback) => {
if (!value || value <= 0) {
return callback(new Error("此项必填!"));
}
// else if (!validCase(value)) {
// callback(new Error("密码至少包含一位非字母数字字符., 密码至少包含一位小写字母 ('a'-'z')., 密码至少包含一位大写字母 ('A'-'Z')."));
// }
else {
callback();
}
};
// 自定义验证
const validPhone = (rule, value, callback) => {
if (!value) {
callback(new Error("请输入电话号码"));
} else if (!isvalidPhone(value)) {
callback(new Error("请输入正确的11位手机号码"));
} else {
callback();
}
};
const validName = (rule, value, callback) => {
if (!value) {
callback(new Error("请输入登录名称"));
} else if (/[\u4E00-\u9FA5]/g.test(value)) {
callback(new Error("登录名不能输入汉字"));
} else {
callback();
}
};
return {
rules: {
userName: [
{ required: true, trigger: "blur", validator: validName },
{
min: 2,
max: 20,
message: "长度在 2 到 20 个字符",
trigger: "blur",
},
],
name: [
{ required: true, trigger: "blur", message: "请输入姓名" },
{
min: 2,
max: 20,
message: "长度在 2 到 20 个字符",
trigger: "blur",
},
],
email: [
{ required: true, message: "请输入邮箱地址", trigger: "blur" },
{ type: "email", message: "请输入正确的邮箱地址", trigger: "blur" },
],
phoneNumber: [
{ required: true, trigger: "blur", validator: validPhone },
],
// ,password:[
// {required:true,trigger: "blur",minlength:6,validator: validateNameInput}
// ]
},
defaultProps2: {
children: "children",
label: "name",
isLeaf: "leaf",
disabled: this.disabledFn,
},
defaultProps: {
children: "children",
label: "label",
disabled: this.disabledFn,
},
filterText: "",
form: Object.assign({}, defaultForm),
//form: {},
list: null,
orgName: "",
orgs: [],
roleName: "",
roles: [],
roleData: [],
jobData: [],
orgData: [],
roleList: [],
roleSearchList: [],
checkedRole: [],
totalCount: 0,
listLoading: true,
formLoading: false,
listQuery: {
OrgId: null,
Filter: "",
Sorting: "",
SkipCount: 0,
MaxResultCount: 10,
},
page: 1,
dialogFormVisible: false,
multipleSelection: [],
formTitle: "",
isEdit: false,
tableHeight: document.documentElement.clientHeight - 270, // 表的高度
treeHeight: document.documentElement.clientHeight - 150, // 表的3度
treeHeight2: document.documentElement.clientHeight - 150,
currentroleMessage: [],
currentroleMessageOrg: [],
};
},
created() {
// this.getList();
// this.getAllRoles()
var self = this;
/** 控制table的高度 */
window.onresize = function () {
self.tableHeight = document.documentElement.clientHeight - 270;
self.treeHeight = document.documentElement.clientHeight - 150;
self.treeHeight2 = document.documentElement.clientHeight - 150;
};
},
watch: {
filterText(val) {
this.$refs.treeright.filter(val);
},
},
mounted() {
this.getList();
this.getAllRoles();
},
methods: {
disabledFn() {
return true;
},
filterNode(value, data) {
if (!value) return true;
return data.name.indexOf(value) !== -1;
},
getOrgs(node, resolve) {
const params = {};
if (typeof node !== "object") {
if (node) {
params["filter"] = node;
}
} else if (node.level !== 0) {
params["id"] = node.data.id;
}
//TODO:仅获取启用机构
setTimeout(() => {
this.$axios.gets("/api/base/branch/all", params).then((response) => {
if (resolve) {
resolve(response.items);
} else {
this.orgData = response.items;
}
});
}, 100);
},
getOrgNodes() {
this.$axios.gets("/api/base/branch/children").then((response) => {
this.loadTree(response);
});
},
// getJobs(){
// this.$axios.gets('/api/base/job/jobs').then((response)=>{
// this.jobData=response.items
// })
// },
getList() {
this.listLoading = true;
this.listQuery.SkipCount = (this.page - 1) * 10;
this.$axios.gets("/api/base/user", this.listQuery).then((response) => {
this.list = response.items;
this.totalCount = response.totalCount;
this.listLoading = false;
});
},
fetchData(id) {
//this.getAllRoles();
//this.getOrgNodes();
//this.getJobs()
this.$axios.gets("/api/base/user/" + id).then((response) => {
this.form = response;
});
this.$axios.gets("/api/identity/users/" + id + "/roles").then((data) => {
data.items.forEach((item) => {
this.checkedRole.push(item.name);
});
});
},
loadOrgs({ action, parentNode, callback }) {
if (action === LOAD_CHILDREN_OPTIONS) {
this.$axios
//.gets("/api/base/orgs/loadOrgs", { id: parentNode.id })
.gets("/api/base/branch/all", { id: parentNode.id })
.then((response) => {
parentNode.children = response.items.map(function (obj) {
if (!obj.leaf) {
obj.children = null;
}
return obj;
});
setTimeout(() => {
callback();
}, 100);
});
}
},
// getAllRoles(node) {
// const params = {};
// if (typeof node !== "object") {
// if (node) {
// params["filter"] = node;
// }
// }
// this.$axios
// .gets("/api/identity/roles/all",params)
// .then((response) => {
// this.roleList = response.items;
// });
// },
getAllRoles(node, resolve) {
const params = {};
if (typeof node !== "object") {
if (node) {
params["filter"] = node;
}
} else if (node.level !== 0) {
params["id"] = node.data.id;
}
//TODO:仅获取启用机构
setTimeout(() => {
this.$axios.gets("/api/identity/roles/all", params).then((response) => {
if (resolve) {
resolve(response.items);
} else {
this.roleList = response.items;
}
});
}, 100);
},
handleFilter() {
this.page = 1;
this.getList();
},
handleNodeClick(data) {
// this.listQuery.OrgId = data.id;
// this.getList();
let userId = this.multipleSelection[0].id;
this.$axios
.gets("/api/base/userbranch/userRoles/" + userId + "/" + data.id)
.then((response) => {
this.currentroleMessage = response.map((item) => {
let JSonmessge = {
id: item.roleId,
label: item.roleId,
disabled: true,
};
return JSonmessge;
});
this.getRoleRulesInfotwo();
});
},
handleNodeClick2(data) {
this.listQuery.RolesId = data.id;
this.getList();
},
save() {
this.$refs.form.validate((valid) => {
if (valid) {
this.formLoading = true;
this.form.roleNames = this.checkedRole;
if (this.isEdit) {
this.$axios
.puts("/api/base/user/" + this.form.id, this.form)
.then((response) => {
this.formLoading = false;
this.$notify({
title: "成功",
message: "更新成功",
type: "success",
duration: 2000,
});
this.dialogFormVisible = false;
this.getList();
})
.catch(() => {
this.formLoading = false;
});
} else {
console.log(JSON.stringify(this.form))
this.$axios
.posts("/api/base/user", this.form)
.then((response) => {
this.formLoading = false;
this.$notify({
title: "成功",
message: "新增成功",
type: "success",
duration: 2000,
});
this.dialogFormVisible = false;
this.getList();
})
.catch(() => {
this.formLoading = false;
});
}
}
});
},
handleCreate() {
this.formTitle = "新增用户";
this.isEdit = false;
this.dialogFormVisible = true;
this.getAllRoles();
//this.getJobs()
//this.getOrgNodes();
},
handleDelete(row) {
if (row) {
this.$confirm("是否删除" + row.name + "?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
this.$axios
.deletes("/api/identity/users/" + row.id)
.then((response) => {
const index = this.list.indexOf(row);
this.list.splice(index, 1);
this.$notify({
title: "成功",
message: "删除成功",
type: "success",
duration: 2000,
});
});
})
.catch(() => {
this.$message({
type: "info",
message: "已取消删除",
});
});
} else {
this.$alert("暂时不支持用户批量删除", "提示", {
confirmButtonText: "确定",
callback: (action) => {
//
},
});
}
},
handleUpdate(row) {
this.formTitle = "修改用户";
this.isEdit = true;
if (row) {
this.fetchData(row.id);
this.dialogFormVisible = true;
} else {
if (this.multipleSelection.length != 1) {
this.$message({
message: "编辑必须选择单行",
type: "warning",
});
return;
} else {
this.fetchData(this.multipleSelection[0].id);
this.dialogFormVisible = true;
}
}
},
sortChange(data) {
const { prop, order } = data;
if (!prop || !order) {
this.handleFilter();
return;
}
this.listQuery.Sorting = prop + " " + order;
// alert(this.listQuery.Sorting)
this.handleFilter();
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
handleRowClick(row, column, event) {
this.$refs.multipleTable.clearSelection();
this.$refs.multipleTable.toggleRowSelection(row);
},
cancel() {
(this.form = Object.assign({}, defaultForm)), (this.checkedRole = []);
this.orgs = [];
this.jobData = [];
this.dialogFormVisible = false;
this.$refs.form.clearValidate();
},
//TODO:引用公共方法
loadTree(data) {
data.items.forEach((element) => {
if (!element.pid) {
element.hasChildren = element.leaf ? false : true;
if (!element.leaf) {
element.children = [];
}
this.orgs.push(element);
}
});
this.setChildren(this.orgs, data.items);
},
setChildren(roots, items) {
roots.forEach((element) => {
items.forEach((item) => {
if (item.pid == element.id) {
if (!element.children) element.children = [];
element.children.push(item);
}
});
if (element.children) {
this.setChildren(element.children, items);
}
});
},
handleSegalChange(val) {
this.currentroleMessage = [];
this.currentroleMessageOrg = [];
if (val.userName === "admin") {
if (val && val.id) {
this.fetchUserforAdminRole(val.id);
this.$refs.treeleft.setCheckedNodes([]);
}
} else {
if (val && val.id) {
//this.fetchData(val.id);
//this.fetchUserforRole(val.id);
//this.fetchUserforOrg(val.id);
//this.getRoleRulesInfo();
}
}
},
//admin-roles
fetchUserforAdminRole(id) {
this.$axios
.gets("/api/identity/users/" + id + "/roles")
.then((response) => {
this.currentroleMessage = response.items.map((item) => {
let JSonmessge = {
id: item.id,
label: item.name,
disabled: true,
};
return JSonmessge;
});
this.getRoleRulesInfotwo();
});
},
//用户-角色组
fetchUserforRole(id) {
//id为用户ID
this.$axios
.gets("/api/base/userbranch/" + id + "/userRoles")
.then((response) => {
this.currentroleMessage = response.map((item) => {
let JSonmessge = {
id: item.roleId,
label: item.roleId,
};
return JSonmessge;
});
this.getRoleRulesInfotwo();
});
},
fetchUserforOrg(id) {
this.$axios
.gets("/api/base/userbranch/" + id + "/branches")
.then((response) => {
console.log(JSON.stringify("fetchUserforOrg:" + response));
this.currentroleMessageOrg = response.map((item) => {
let JSonmessge = {
id: item.branchId,
label: item.branchName,
};
return JSonmessge;
});
this.getRoleRulesInfo();
});
},
/**
* 获取权限信息
*/
getRoleRulesInfo() {
this.$nextTick(() => {
console.log(JSON.stringify(this.currentroleMessageOrg));
// this.$refs.treeleft.setCheckedKeys([1]);
this.$refs.treeleft.setCheckedNodes(this.currentroleMessageOrg);
});
},
getRoleRulesInfotwo() {
this.$nextTick(() => {
console.log(JSON.stringify(this.currentroleMessage));
this.$refs.treeright.setCheckedNodes(this.currentroleMessage);
});
},
resetPassword(row) {
console.log(JSON.stringify(row));
this.$confirm("是否重置" + row.userName + "密码?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
this.$axios
.puts("/api/base/user/" + row.id + "/reset-password")
.then((response) => {
this.$notify({
title: "成功",
message: "重置成功,密码是:123456",
type: "success",
duration: 2000,
});
});
})
.catch(() => {
this.$message({
type: "info",
message: "已取消修改",
});
});
},
},
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.opts {
padding: 6px 0;
display: -webkit-flex;
display: flex;
align-items: center;
}
.leftTree {
height: calc(100vh - 100px);
box-sizing: border-box;
display: flex;
flex-direction: column;
.system-content {
position: relative;
height: 100%;
flex: 1;
display: flex;
overflow: hidden;
}
.system-view-nav {
width: 100%;
height: 100%;
overflow: auto;
background: #fff;
border: 1px solid #e6e6e6;
}
}
</style>