<template>
|
<div class="user-management-drawer">
|
<div class="toolbar">
|
<el-input
|
style="width: 300px"
|
size="small"
|
placeholder="请输入用户名或姓名"
|
v-model="search"
|
clearable
|
>
|
</el-input>
|
|
<el-button
|
plain
|
size="small"
|
icon="el-icon-refresh"
|
@click="resetSearch"
|
>重置</el-button
|
>
|
|
<el-button
|
v-if="isSuperuser"
|
type="primary"
|
size="small"
|
icon="el-icon-plus"
|
@click="handleAdd"
|
>新增用户</el-button
|
>
|
</div>
|
|
<el-dialog
|
:title="dialogTitle"
|
width="50%"
|
:close-on-click-modal="false"
|
:modal="false"
|
:visible.sync="dialogVisible"
|
@close="handleDialogClose"
|
append-to-body
|
>
|
<el-form
|
:inline="true"
|
label-position="right"
|
:model="userForm"
|
:rules="rules"
|
ref="userForm"
|
label-width="100px"
|
>
|
<el-form-item label="用户名" prop="username" v-if="isCreate">
|
<el-input v-model="userForm.username" placeholder="请输入用户名"></el-input>
|
</el-form-item>
|
|
<el-form-item label="用户名" prop="username" v-if="!isCreate">
|
<el-input v-model="userForm.username" disabled></el-input>
|
</el-form-item>
|
|
<el-form-item label="姓名" prop="name">
|
<el-input v-model="userForm.name" placeholder="请输入姓名"></el-input>
|
</el-form-item>
|
|
<el-form-item label="手机号" prop="phone">
|
<el-input v-model="userForm.phone" placeholder="请输入手机号"></el-input>
|
</el-form-item>
|
|
<el-form-item label="密码" prop="password" v-if="isCreate">
|
<el-input
|
type="password"
|
v-model="userForm.password"
|
placeholder="请输入密码"
|
></el-input>
|
</el-form-item>
|
|
<el-form-item label="确认密码" prop="confirm_password" v-if="isCreate">
|
<el-input
|
type="password"
|
v-model="userForm.confirm_password"
|
placeholder="请再次输入密码"
|
></el-input>
|
</el-form-item>
|
|
<el-form-item label="是否激活" prop="is_active">
|
<el-switch v-model="userForm.is_active" :disabled="!isSuperuser"></el-switch>
|
</el-form-item>
|
|
<el-form-item label="是否管理员" prop="is_staff">
|
<el-switch v-model="userForm.is_staff" :disabled="!isSuperuser"></el-switch>
|
</el-form-item>
|
|
<el-form-item label="超级用户" prop="is_superuser">
|
<el-switch v-model="userForm.is_superuser" :disabled="!isSuperuser"></el-switch>
|
</el-form-item>
|
|
<el-form-item label="显示Hosts" prop="show_hosts">
|
<el-switch v-model="userForm.show_hosts" :disabled="!isSuperuser"></el-switch>
|
</el-form-item>
|
|
<el-form-item label="所属分组" prop="groups">
|
<el-select
|
v-model="userForm.groups"
|
multiple
|
placeholder="请选择分组"
|
style="width: 100%"
|
:disabled="!isSuperuser"
|
>
|
<el-option
|
v-for="group in groupList"
|
:key="group.id"
|
:label="group.name"
|
:value="group.id"
|
></el-option>
|
</el-select>
|
</el-form-item>
|
</el-form>
|
|
<span slot="footer" class="dialog-footer">
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
<el-button type="primary" @click="handleSubmit">确 定</el-button>
|
</span>
|
</el-dialog>
|
|
<el-dialog
|
title="用户详情"
|
width="50%"
|
:close-on-click-modal="false"
|
:modal="false"
|
:visible.sync="detailDialogVisible"
|
append-to-body
|
>
|
<el-form
|
:inline="true"
|
label-position="right"
|
:model="userDetail"
|
label-width="100px"
|
>
|
<el-form-item label="用户名">
|
<el-input v-model="userDetail.username" readonly></el-input>
|
</el-form-item>
|
|
<el-form-item label="姓名">
|
<el-input v-model="userDetail.name" readonly></el-input>
|
</el-form-item>
|
|
<el-form-item label="手机号">
|
<el-input v-model="userDetail.phone" readonly></el-input>
|
</el-form-item>
|
|
<el-form-item label="是否激活">
|
<el-tag :type="userDetail.is_active ? 'success' : 'danger'">
|
{{ userDetail.is_active ? '是' : '否' }}
|
</el-tag>
|
</el-form-item>
|
|
<el-form-item label="是否管理员">
|
<el-tag :type="userDetail.is_staff ? 'success' : 'info'">
|
{{ userDetail.is_staff ? '是' : '否' }}
|
</el-tag>
|
</el-form-item>
|
|
<el-form-item label="超级用户">
|
<el-tag :type="userDetail.is_superuser ? 'success' : 'info'">
|
{{ userDetail.is_superuser ? '是' : '否' }}
|
</el-tag>
|
</el-form-item>
|
|
<el-form-item label="显示Hosts">
|
<el-tag :type="userDetail.show_hosts ? 'success' : 'info'">
|
{{ userDetail.show_hosts ? '是' : '否' }}
|
</el-tag>
|
</el-form-item>
|
|
<el-form-item label="所属分组">
|
<el-tag
|
v-for="group in userDetail.groups"
|
:key="group"
|
style="margin-right: 5px"
|
>
|
{{ group }}
|
</el-tag>
|
</el-form-item>
|
|
<el-form-item label="可访问项目">
|
<el-tag
|
v-for="project in userDetail.accessible_projects"
|
:key="project"
|
style="margin-right: 5px"
|
>
|
{{ project }}
|
</el-tag>
|
</el-form-item>
|
|
<el-form-item label="注册时间">
|
<el-input
|
:value="userDetail.date_joined | datetimeFormat"
|
readonly
|
></el-input>
|
</el-form-item>
|
|
<el-form-item label="最后登录">
|
<el-input
|
:value="formatLastLogin(userDetail.last_login)"
|
readonly
|
></el-input>
|
</el-form-item>
|
</el-form>
|
|
<span slot="footer" class="dialog-footer">
|
<el-button @click="detailDialogVisible = false">关 闭</el-button>
|
</span>
|
</el-dialog>
|
|
<div class="table-container">
|
<el-table
|
highlight-current-row
|
stripe
|
:data="userData"
|
v-loading="isLoading"
|
height="calc(100vh - 150px)"
|
@cell-mouse-enter="cellMouseEnter"
|
@cell-mouse-leave="cellMouseLeave"
|
>
|
<el-table-column label="用户名" width="120">
|
<template slot-scope="scope">
|
<div
|
:title="scope.row.username"
|
class="table-column"
|
>
|
{{ scope.row.username }}
|
</div>
|
</template>
|
</el-table-column>
|
|
<el-table-column label="姓名" width="120">
|
<template slot-scope="scope">
|
<div
|
:title="scope.row.name"
|
class="table-column"
|
>
|
{{ scope.row.name }}
|
</div>
|
</template>
|
</el-table-column>
|
|
<el-table-column label="手机号" width="120">
|
<template slot-scope="scope">
|
<div
|
:title="scope.row.phone"
|
class="table-column"
|
>
|
{{ scope.row.phone }}
|
</div>
|
</template>
|
</el-table-column>
|
|
<el-table-column label="是否激活" width="100">
|
<template slot-scope="scope">
|
<el-tag :type="scope.row.is_active ? 'success' : 'danger'">
|
{{ scope.row.is_active ? '是' : '否' }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
|
<el-table-column label="是否管理员" width="100">
|
<template slot-scope="scope">
|
<el-tag :type="scope.row.is_staff ? 'success' : 'info'">
|
{{ scope.row.is_staff ? '是' : '否' }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
|
<el-table-column label="超级用户" width="100">
|
<template slot-scope="scope">
|
<el-tag :type="scope.row.is_superuser ? 'success' : 'info'">
|
{{ scope.row.is_superuser ? '是' : '否' }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
|
<el-table-column label="所属分组" width="200">
|
<template slot-scope="scope">
|
<div class="table-column">
|
<el-tag
|
v-for="group in scope.row.groups"
|
:key="group"
|
size="mini"
|
style="margin-right: 3px"
|
>
|
{{ group }}
|
</el-tag>
|
</div>
|
</template>
|
</el-table-column>
|
|
<el-table-column label="注册时间" width="180">
|
<template slot-scope="scope">
|
<div>
|
{{ scope.row.date_joined | datetimeFormat }}
|
</div>
|
</template>
|
</el-table-column>
|
|
<el-table-column label="操作" width="200" fixed="right">
|
<template slot-scope="scope">
|
<el-row v-show="currentRow === scope.row">
|
<el-button
|
type="success"
|
icon="el-icon-view"
|
title="查看"
|
circle
|
size="mini"
|
@click="handleView(scope.row)"
|
></el-button>
|
<el-button
|
type="primary"
|
icon="el-icon-edit"
|
title="编辑"
|
circle
|
size="mini"
|
v-if="isSuperuser"
|
@click="handleEdit(scope.row)"
|
></el-button>
|
<el-button
|
type="danger"
|
icon="el-icon-delete"
|
title="删除"
|
circle
|
size="mini"
|
v-if="isSuperuser && scope.row.id !== currentUserId"
|
@click="handleDelete(scope.row)"
|
></el-button>
|
</el-row>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
export default {
|
name: "UserManagementDrawer",
|
data() {
|
var validateConfirmPassword = (rule, value, callback) => {
|
if (value !== this.userForm.password) {
|
callback(new Error("两次输入的密码不一致"));
|
} else {
|
callback();
|
}
|
};
|
|
return {
|
search: "",
|
currentRow: "",
|
isLoading: true,
|
userData: [],
|
groupList: [],
|
dialogVisible: false,
|
detailDialogVisible: false,
|
isCreate: false,
|
isSuperuser: false,
|
currentUserId: null,
|
userForm: {
|
id: null,
|
username: "",
|
name: "",
|
phone: "",
|
password: "",
|
confirm_password: "",
|
is_active: true,
|
is_staff: false,
|
is_superuser: false,
|
show_hosts: false,
|
groups: []
|
},
|
userDetail: {
|
username: "",
|
name: "",
|
phone: "",
|
is_active: false,
|
is_staff: false,
|
is_superuser: false,
|
show_hosts: false,
|
groups: [],
|
accessible_projects: [],
|
date_joined: "",
|
last_login: ""
|
},
|
rules: {
|
username: [
|
{ required: true, message: "请输入用户名", trigger: "blur" }
|
],
|
name: [
|
{ required: true, message: "请输入姓名", trigger: "blur" }
|
],
|
password: [
|
{ required: true, message: "请输入密码", trigger: "blur" },
|
{ min: 6, message: "密码长度不能少于6位", trigger: "blur" }
|
],
|
confirm_password: [
|
{ required: true, message: "请再次输入密码", trigger: "blur" },
|
{ validator: validateConfirmPassword, trigger: "blur" }
|
]
|
}
|
};
|
},
|
computed: {
|
dialogTitle() {
|
return this.isCreate ? "新增用户" : "编辑用户";
|
}
|
},
|
methods: {
|
cellMouseEnter(row) {
|
this.currentRow = row;
|
},
|
cellMouseLeave() {
|
this.currentRow = "";
|
},
|
handleAdd() {
|
this.isCreate = true;
|
this.dialogVisible = true;
|
this.resetForm();
|
},
|
handleEdit(row) {
|
this.isCreate = false;
|
this.dialogVisible = true;
|
const groupIds = this.getGroupIdsByName(row.groups || []);
|
this.userForm = {
|
id: row.id,
|
username: row.username,
|
name: row.name,
|
phone: row.phone,
|
is_active: row.is_active,
|
is_staff: row.is_staff,
|
is_superuser: row.is_superuser,
|
show_hosts: row.show_hosts,
|
groups: groupIds
|
};
|
},
|
handleView(row) {
|
this.getUserDetail(row.id);
|
},
|
handleDelete(row) {
|
this.$confirm("确定要删除该用户吗?", "提示", {
|
confirmButtonText: "确定",
|
cancelButtonText: "取消",
|
type: "warning"
|
}).then(() => {
|
this.$api.deleteUser(row.id).then(() => {
|
this.$message.success("删除成功");
|
this.getUserList();
|
});
|
}).catch(() => {});
|
},
|
handleSubmit() {
|
this.$refs.userForm.validate(valid => {
|
if (valid) {
|
console.log("提交表单数据:", this.userForm);
|
if (this.isCreate) {
|
this.$api.createUser(this.userForm).then(() => {
|
this.$message.success("创建成功");
|
this.dialogVisible = false;
|
this.getUserList();
|
}).catch(err => {
|
console.error("创建用户失败:", err);
|
console.error("错误详情:", err.response ? err.response.data : err.message);
|
this.$message.error("创建用户失败,请检查输入信息");
|
});
|
} else {
|
this.$api.updateUser(this.userForm.id, this.userForm).then(() => {
|
this.$message.success("更新成功");
|
this.dialogVisible = false;
|
this.getUserList();
|
}).catch(err => {
|
console.error("更新用户失败:", err);
|
console.error("错误详情:", err.response ? err.response.data : err.message);
|
this.$message.error("更新用户失败,请检查输入信息");
|
});
|
}
|
} else {
|
this.$message.warning("请检查表单输入");
|
}
|
});
|
},
|
handleDialogClose() {
|
this.$refs.userForm.resetFields();
|
},
|
resetForm() {
|
this.userForm = {
|
id: null,
|
username: "",
|
name: "",
|
phone: "",
|
password: "",
|
confirm_password: "",
|
is_active: true,
|
is_staff: false,
|
is_superuser: false,
|
show_hosts: false,
|
groups: []
|
};
|
},
|
getUserList() {
|
this.isLoading = true;
|
console.log("搜索关键词:", this.search);
|
this.$api.getUserManagementList({ search: this.search }).then(resp => {
|
console.log("搜索结果:", resp);
|
this.userData = resp.results || resp;
|
this.isLoading = false;
|
}).catch(err => {
|
console.error("获取用户列表失败:", err);
|
this.isLoading = false;
|
});
|
},
|
getUserDetail(userId) {
|
this.$api.getUserDetail(userId).then(resp => {
|
this.userDetail = resp;
|
this.detailDialogVisible = true;
|
});
|
},
|
getGroupList() {
|
this.$api.getGroupList().then(resp => {
|
this.groupList = resp;
|
});
|
},
|
resetSearch() {
|
this.search = "";
|
this.getUserList();
|
},
|
formatLastLogin(lastLogin) {
|
if (!lastLogin) {
|
return "从未登录";
|
}
|
return lastLogin;
|
},
|
getGroupIdsByName(groupNames) {
|
if (!groupNames || groupNames.length === 0) {
|
return [];
|
}
|
const groupMap = {};
|
this.groupList.forEach(group => {
|
groupMap[group.name] = group.id;
|
});
|
return groupNames.map(name => groupMap[name]).filter(id => id !== undefined);
|
}
|
},
|
watch: {
|
search() {
|
this.getUserList();
|
}
|
},
|
mounted() {
|
this.isSuperuser = this.$store.state.is_superuser;
|
this.currentUserId = this.$store.state.id;
|
this.getUserList();
|
if (this.isSuperuser) {
|
this.getGroupList();
|
}
|
}
|
};
|
</script>
|
|
<style scoped>
|
.user-management-drawer {
|
width: 100%;
|
height: 100%;
|
padding: 0;
|
}
|
|
.toolbar {
|
display: flex;
|
align-items: center;
|
padding: 10px 20px;
|
gap: 10px;
|
background: #f5f5f5;
|
border-bottom: 1px solid #e0e0e0;
|
}
|
|
.toolbar .el-input {
|
margin-right: 10px;
|
}
|
|
.table-container {
|
padding: 20px;
|
height: calc(100vh - 150px);
|
overflow: auto;
|
}
|
|
.table-column {
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
</style>
|