<!--
|
- Copyright (c) 2018-2025, ztt All rights reserved.
|
-
|
- Redistribution and use in source and binary forms, with or without
|
- modification, are permitted provided that the following conditions are met:
|
-
|
- Redistributions of source code must retain the above copyright notice,
|
- this list of conditions and the following disclaimer.
|
- Redistributions in binary form must reproduce the above copyright
|
- notice, this list of conditions and the following disclaimer in the
|
- documentation and/or other materials provided with the distribution.
|
- Neither the name of the pig4cloud.com developer nor the names of its
|
- contributors may be used to endorse or promote products derived from
|
- this software without specific prior written permission.
|
- Author: ztt
|
-->
|
|
<template>
|
<div class="user">
|
<basic-container>
|
<el-row :span="24">
|
<el-col :xs="24" :sm="24" :md="5" class="user__tree">
|
<avue-tree
|
:option="treeOption"
|
:data="treeData"
|
@node-click="nodeClick"
|
>
|
<span class="el-tree-node__label" slot-scope="{ node, data }">
|
<el-tooltip
|
class="item"
|
effect="dark"
|
content="无数据权限"
|
placement="right-start"
|
v-if="data.isLock"
|
>
|
<span>{{ node.label }} <i class="el-icon-lock"></i></span>
|
</el-tooltip>
|
<span v-if="!data.isLock">{{ node.label }}</span>
|
</span>
|
</avue-tree>
|
</el-col>
|
<el-col :xs="24" :sm="24" :md="19" class="user__main">
|
<avue-crud
|
ref="crud"
|
:option="option"
|
v-model="form"
|
:page="page"
|
:table-loading="listLoading"
|
:before-open="handleOpenBefore"
|
:data="list"
|
@on-load="getList"
|
@search-change="searchChange"
|
@refresh-change="refreshChange"
|
@size-change="sizeChange"
|
@current-change="currentChange"
|
@row-update="update"
|
@row-save="create"
|
>
|
<template slot="menuLeft">
|
<el-button
|
v-if="sys_user_add"
|
class="filter-item"
|
type="primary"
|
size="small"
|
icon="el-icon-edit"
|
@click="$refs.crud.rowAdd()"
|
>添加
|
</el-button>
|
<!-- <el-button
|
v-if="sys_user_add"
|
class="filter-item"
|
type="primary"
|
size="small"
|
icon="el-icon-upload"
|
@click="importDialogVisible=true"
|
>导入
|
</el-button> -->
|
</template>
|
<template slot="username" slot-scope="scope">
|
<span>{{ scope.row.username }}</span>
|
</template>
|
<template slot="role" slot-scope="scope">
|
<span v-for="(role, index) in scope.row.roleList" :key="index">
|
<el-tag>{{ role.roleName }} </el-tag>
|
</span>
|
</template>
|
<template slot="deptId" slot-scope="scope">
|
{{ scope.row.deptName }}
|
</template>
|
<template slot="lockFlag" slot-scope="scope">
|
<el-tag>{{ scope.label }}</el-tag>
|
</template>
|
<template slot="menu" slot-scope="scope">
|
<el-button
|
v-if="sys_user_edit"
|
type="text"
|
size="small"
|
icon="el-icon-edit"
|
@click="handleUpdate(scope.row, scope.index)"
|
>编辑
|
</el-button>
|
<el-button
|
v-if="sys_user_del"
|
type="text"
|
size="small"
|
icon="el-icon-delete"
|
@click="deletes(scope.row, scope.index)"
|
>删除
|
</el-button>
|
<el-button
|
v-if="sys_user_lock"
|
type="text"
|
size="small"
|
icon="el-icon-unlock"
|
@click="unlock(scope.row, scope.index)"
|
>解锁
|
</el-button>
|
</template>
|
<template slot="deptIdForm" slot-scope="scope">
|
<avue-input-tree
|
v-model="form.deptId"
|
:node-click="getNodeData"
|
:dic="treeDeptData"
|
:props="defaultProps"
|
placeholder="请选择所属分组"
|
/>
|
</template>
|
<template slot="staffInfoForm" slot-scope="scope">
|
<el-input
|
@focus="showStaff = true"
|
v-model="form.staffInfo"
|
readonly
|
>
|
<i
|
class="el-icon-arrow-down el-input__icon"
|
slot="suffix"
|
@click="showStaff = true"
|
></i>
|
</el-input>
|
</template>
|
<template slot="roleForm" slot-scope="scope">
|
<avue-select
|
v-model="role"
|
:dic="rolesOptions"
|
:props="roleProps"
|
multiple
|
placeholder="请选择角色"
|
/>
|
</template>
|
</avue-crud>
|
</el-col>
|
</el-row>
|
</basic-container>
|
|
<staffDialog
|
:currshowlist.sync="showStaff"
|
@listenToStaffEvent="selectStaff"
|
/>
|
<el-dialog title="导入" :visible.sync="importDialogVisible" width="30%">
|
<span>
|
<div>
|
<div>
|
<el-upload
|
style="margin-left:8px;display: inline;"
|
class="upload-demo"
|
drag
|
:headers="headers"
|
:action="uploadInfo.url"
|
:beforeUpload="beforeAvatarUpload"
|
:limit="1"
|
:show-file-list="false"
|
:file-list="fileList"
|
:on-success="fileSuccessUploadScan"
|
:on-error="handleError"
|
accept=".xlsx,.xls,.csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel"
|
:auto-upload="true"
|
ref="uploadScan"
|
multiple
|
>
|
<i class="el-icon-upload"></i>
|
<div class="el-upload__text"><em>点击导入数据</em></div>
|
<div class="el-upload__tip" slot="tip" >
|
只能上传xlsx/xls文件,且不超过10M<el-button
|
type="text"
|
style="font-size:12px;"
|
@click="downDataTemplate(uploadInfo.fileName)"
|
v-if="uploadInfo.Download"
|
>下载模板</el-button
|
>
|
</div>
|
</el-upload>
|
</div>
|
<div></div>
|
</div>
|
</span>
|
<span slot="footer" class="dialog-footer"> </span>
|
</el-dialog>
|
</div>
|
</template>
|
<script>
|
import staffDialog from '@/views/common/staff.vue'
|
import { addObj, delObj, fetchList, putObj, unlock } from '@/api/admin/user'
|
import { deptRoleList } from '@/api/admin/role'
|
import { fetchTree } from '@/api/admin/dept'
|
import { tableOption } from '@/const/crud/admin/user'
|
import { mapGetters } from 'vuex'
|
import Template from '../../quality/parts/template'
|
import { getObj } from '@/api/basic/staff'
|
import { getStore } from '@/util/store.js'
|
import { uploadTemplate } from '@/api/basic/template'
|
export default {
|
name: 'SysUser',
|
components: { Template, staffDialog },
|
data() {
|
return {
|
fileList: [], // 上传文件列表
|
// 上传头信息
|
headers: {
|
Authorization: 'Bearer ' + getStore({ name: 'access_token' })
|
},
|
uploadInfo: {
|
// 是否展示上传EXCEL以及对应的url
|
isShow: true,
|
url: '/mes/user/upload',
|
download: true,
|
fileName: '用户模板'
|
},
|
importDialogVisible: false,
|
showStaff: false,
|
searchForm: {},
|
treeOption: {
|
nodeKey: 'id',
|
addBtn: false,
|
menu: false,
|
props: {
|
label: 'name',
|
value: 'id'
|
}
|
},
|
treeData: [],
|
option: tableOption,
|
treeDeptData: [],
|
checkedKeys: [],
|
roleProps: {
|
label: 'roleName',
|
value: 'roleId'
|
},
|
defaultProps: {
|
label: 'name',
|
value: 'id'
|
},
|
page: {
|
total: 0, // 总页数
|
currentPage: 1, // 当前页数
|
pageSize: 20, // 每页显示多少条,
|
isAsc: false // 是否倒序
|
},
|
list: [],
|
listLoading: true,
|
role: [],
|
form: {},
|
rolesOptions: []
|
}
|
},
|
computed: {
|
...mapGetters(['permissions'])
|
},
|
watch: {
|
role() {
|
this.form.role = this.role
|
}
|
},
|
created() {
|
this.sys_user_add = this.permissions.sys_user_add
|
this.sys_user_edit = this.permissions.sys_user_edit
|
this.sys_user_del = this.permissions.sys_user_del
|
this.sys_user_lock = this.permissions.sys_user_lock
|
this.init()
|
},
|
methods: {
|
// 限制文件上传大小,目前限制为10M(另可以加类型限制)
|
beforeAvatarUpload(file) {
|
const fileName = file.name
|
const fileType = fileName.substring(fileName.lastIndexOf('.') + 1)
|
const isLt10M = file.size / 1024 / 1024 < 10
|
if (fileType !== 'xlsx' && fileType !== 'xls') {
|
this.$message.error('文件格式只能为xlsx或xls,请删除后重新上传')
|
}
|
if (!isLt10M) {
|
this.$message({
|
message: '文件大小',
|
type: 'warning'
|
})
|
}
|
return isLt10M
|
},
|
// 文件上传成功回调事件
|
fileSuccessUploadScan(response, file, fileList) {
|
if (response.code != '0') {
|
this.$message.warning(response.msg)
|
} else {
|
if(response.data!=""&&response.data!=[]&&response.data!=null){
|
this.$message({
|
message: response.data,
|
type: 'success',
|
dangerouslyUseHTMLString: true,
|
})
|
}else{
|
this.$message({
|
message: '上传成功',
|
type: 'success'
|
})
|
}
|
this.importDialogVisible=false
|
this.fileList=[]
|
this.init()
|
// this.getDataList()
|
}
|
this.$refs.uploadScan.clearFiles()
|
},
|
// 上传失败
|
handleError(err, file, fileList) {
|
const error = JSON.parse(err.message)
|
if (error.msg) {
|
this.$message.error(error.msg)
|
} else {
|
this.$message.error('上传失败')
|
}
|
},
|
// 下载数据模板
|
downDataTemplate() {
|
uploadTemplate("user").then((response) => {
|
const blob = new Blob([response.data], {
|
type: 'application/force-download'
|
})
|
let fileName="模板文件";
|
if(this.uploadInfo.fileName!=undefined&&this.uploadInfo.fileName!=''&&this.uploadInfo.fileName!=null){
|
fileName=this.uploadInfo.fileName
|
}
|
const filename = decodeURI(fileName+'.xlsx')
|
// 创建一个超链接,将文件流赋进去,然后实现这个超链接的单击事件
|
const elink = document.createElement('a')
|
elink.download = filename
|
elink.style.display = 'none'
|
elink.href = URL.createObjectURL(blob)
|
document.body.appendChild(elink)
|
elink.click()
|
URL.revokeObjectURL(elink.href) // 释放URL 对象
|
document.body.removeChild(elink)
|
})
|
},
|
selectStaff(staff) {
|
this.form.staffInfo = staff.staffName + '-' + staff.staffNo
|
this.form.phone = staff.phone
|
this.form.staffId = staff.id
|
},
|
init() {
|
fetchTree().then((response) => {
|
this.treeData = response.data.data
|
})
|
},
|
nodeClick(data) {
|
this.page.page = 1
|
this.getList(this.page, { deptId: data.id })
|
},
|
getList(page, params) {
|
this.listLoading = true
|
fetchList(
|
Object.assign(
|
{
|
current: page.currentPage,
|
size: page.pageSize
|
},
|
params,
|
this.searchForm
|
)
|
).then((response) => {
|
this.list = response.data.data.records
|
this.page.total = response.data.data.total
|
this.listLoading = false
|
})
|
},
|
getNodeData() {
|
deptRoleList().then((response) => {
|
this.rolesOptions = response.data.data
|
})
|
},
|
searchChange(param, done) {
|
this.searchForm = param
|
this.page.currentPage = 1
|
this.getList(this.page, param)
|
done()
|
},
|
sizeChange(pageSize) {
|
this.page.pageSize = pageSize
|
},
|
currentChange(current) {
|
this.page.currentPage = current
|
},
|
refreshChange() {
|
this.getList(this.page)
|
},
|
handleOpenBefore(show, type) {
|
window.boxType = type
|
// 查询部门树
|
fetchTree().then((response) => {
|
this.treeDeptData = response.data.data
|
})
|
// 查询角色列表
|
deptRoleList().then((response) => {
|
this.rolesOptions = response.data.data
|
})
|
|
if (['edit', 'views'].includes(type)) {
|
this.role = []
|
for (let i = 0; i < this.form.roleList.length; i++) {
|
this.role[i] = this.form.roleList[i].roleId
|
}
|
} else if (type === 'add') {
|
this.role = []
|
}
|
show()
|
},
|
handleUpdate(row, index) {
|
this.$refs.crud.rowEdit(row, index)
|
this.form.password = undefined
|
},
|
|
create(row, done, loading) {
|
if (this.form.phone.indexOf('*') > 0) {
|
this.form.phone = undefined
|
}
|
addObj(this.form)
|
.then(() => {
|
this.getList(this.page)
|
done()
|
this.$notify.success('创建成功')
|
})
|
.catch(() => {
|
loading()
|
})
|
},
|
update(row, index, done, loading) {
|
if (this.form.phone && this.form.phone.indexOf('*') > 0) {
|
this.form.phone = undefined
|
}
|
putObj(this.form)
|
.then(() => {
|
this.getList(this.page)
|
done()
|
this.$notify.success('修改成功')
|
})
|
.catch(() => {
|
loading()
|
})
|
},
|
deletes(row, index) {
|
this.$confirm(
|
'此操作将永久删除该用户(用户名:' + row.username + '), 是否继续?',
|
'提示',
|
{
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
closeOnClickModal: false,
|
type: 'warning'
|
}
|
).then(() => {
|
delObj(row.userId)
|
.then(() => {
|
this.list.splice(index, 1)
|
this.$notify.success('删除成功')
|
})
|
.catch(() => {
|
this.$notify.error('删除失败')
|
})
|
})
|
},
|
unlock(row, index) {
|
unlock({ id: row.userId }).then((repsonse) => {
|
if(repsonse.data.data){
|
this.$message.success("该用户已解锁")
|
}
|
})
|
}
|
}
|
}
|
</script>
|
<style lang="scss">
|
.user {
|
height: 100%;
|
|
&__tree {
|
padding-top: 3px;
|
padding-right: 20px;
|
}
|
|
&__main {
|
.el-card__body {
|
padding-top: 0;
|
}
|
}
|
}
|
</style>
|