提交 223ea709 authored 作者: 龙菲's avatar 龙菲

增加用户管理

上级 f8f14d88
......@@ -49,3 +49,21 @@ export function getRoleList() {
}
// 获取用户组织树
export function getDeptTree(params) {
return request({
url: 'sys/dept/tree',
method: 'get',
params
})
}
// 获取用户列表
export function getUserList(data) {
return request({
url: 'sys/users',
method: 'post',
data
})
}
<template>
<div class="app-container">
<div class="top-bar">
<SearchBar :config="searchConfig" @search="search" @reset="reset" />
<el-button
type="primary"
@click.native="handleOperation({ type: 'add' })"
icon="el-icon-s-promotion"
>
发布</el-button
>
</div>
<el-row :gutter="32">
<el-col :span="4" v-for="(item, index) in list.records" :key="index">
<el-card
shadow="hover"
:body-style="{ padding: '0px' }"
style="margin-bottom: 10px"
>
<div slot="header" class="clearfix">
<span>{{ item.name }}</span>
</div>
<!-- <div class="deptName">贵州省博物馆</div> -->
<div class="faceImage">
<div class="img">
<el-image :src="item.faceImage" style="width:100%;height: 100%;" fit="cover">
<div slot="error" class="image-slot">
<img src="@/assets/404_images/no-pic1.png" alt="">
</div>
</el-image>
<div class="modal">
<i class="el-icon-view"></i>
<div class="view-text">查看</div>
</div>
</div>
</div>
<div class="theme">{{ item.intro }}</div>
<div class="buttons">
<el-row>
<el-col :span="12">
<el-button icon="el-icon-edit" style="width: 100%"> </el-button>
</el-col>
<el-col :span="12">
<el-button icon="el-icon-delete" style="width: 100%">
</el-button>
</el-col>
</el-row>
</div>
</el-card>
</el-col>
</el-row>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="Number(list.current)"
:page-sizes="[10, 20, 40, 50]"
:page-size="Number(list.size)"
layout="total, sizes, prev, pager, next, jumper"
:total="Number(list.total)"
class="pagination"
>
</el-pagination>
<InfoEditDialog
:visible="drawerVisible"
:form="form"
@handleClose="handleClose"
@refresh="loadData"
/>
</div>
</template>
<script>
import TablePage from "@/components/Table/TablePage.vue";
import TableOperation from "@/components/Table/TableOperation.vue";
import { title, operates, operations } from "./config";
import {
getMuseumList,
// getRCDetailById,
// deleteCultralRelic,
// editCulturalRelic,
} from "@/api/org";
import InfoEditDialog from "./components/InfoEditDialog";
import SearchBar from "@/components/SearchBar";
export default {
components: {
TablePage,
TableOperation,
InfoEditDialog,
SearchBar,
},
data() {
return {
list: {
records: [],
size: 10,
current: 1,
total: 0,
},
searchForm: {
name: "",
status: "",
},
searchConfig: [
{
prop: "name",
type: "input",
label: "博物馆名称",
},
{
prop: "status",
type: "select",
label: "状态",
selectOptions: [
{
label: "已上架",
value: "1",
},
{
label: "已下架",
value: "0",
},
],
},
],
drawerVisible: false,
isAdd: true,
form: {
name: "", //名称
intro: "",
latitude: "",//纬度
longitude: "",//经度
faceImage: "",
pid:'',//所属部门id
regionCode:'',//所属地code
},
loading: false,
};
},
computed: {
tableTitle() {
return title;
},
tableOperates() {
return operates;
},
tableOperations() {
return operations;
},
getStatusTitle(status) {
return (status) => {
if (Number(status)) {
return "是否确定要下架?";
} else {
return "是否确定要上架?";
}
};
},
},
mounted() {
this.loadData();
},
methods: {
async search(form) {
var params = {
page: this.list.current,
limit: this.list.size,
...form,
};
if (params.status == "") {
delete params.status;
}
console.log("params", params);
let res = await getMuseumList(params);
if (res.code == 0) {
this.list = res.data;
}
},
reset() {
this.loadData();
},
// 加载表格数据
async loadData() {
var params = {
page: this.list.current,
limit: this.list.size,
};
let res = await getMuseumList(params);
if (res.code == 0) {
this.list.records = res.data; //TODO:待后端增加分页
}
},
async handleOperation(value, row) {
console.log("handleOperation", value, row);
switch (value.type) {
case "add":
this.drawerVisible = true;
break;
case "view":
break;
case "edit":
let detailRes = await getRCDetailById({ crId: row.crId });
if (detailRes.code == 0) {
this.form = detailRes.data;
this.drawerVisible = true;
}
break;
case "delete":
let deleteRes = await deleteCultralRelic([row.crId]);
if (deleteRes.code == 0) {
this.$message.success("删除成功!");
this.loadData();
}
break;
}
},
async handleChangeStatus(row) {
console.log("status", row);
const { status } = row;
let newStatus = status === "0" ? "1" : "0";
const params = {
...row,
status: newStatus,
};
let res = await editCulturalRelic(params);
if (res.code == 0) {
this.loadData();
this.$message.success("修改成功!");
}
},
// 多选
handleSelectionChange(val) {
this.multipleSelection = val;
},
// 改变页容量
handleSizeChange(value) {
this.list.size = value;
this.loadData();
},
// 改变当前显示页
handleCurrentChange(value) {
this.list.current = value;
this.loadData();
},
// 搜索
onSubmitSearch() {
console.log("submit!");
},
// 打开drawer
handleOpenDialog(type, value) {
this.drawerVisible = true;
switch (type) {
case "add":
console.log("新增");
break;
case "edit":
console.log("编辑", value);
break;
}
},
// 关闭Dialog
handleClose() {
this.drawerVisible = false;
},
},
};
</script>
<style lang="scss" scoped>
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.pagination {
margin: 16px;
}
::v-deep .el-card__header {
padding: 10px 20px;
font-weight: bold;
}
.deptName {
padding: 12px 16px;
font-size: 13px;
}
.theme {
padding: 4px 16px;
font-size: 13px;
}
.faceImage {
padding: 16px;
.img {
position: relative;
// width: 100%;
width: 100%;
height: 160px;
&:hover {
.modal {
background-color: rgba(0, 0, 0, 0.3);
i {
display: inline;
}
.view-text {
display: block;
}
}
}
img {
width: 100%;
height: 100%;
}
.modal {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
transition: all ease 0.3s;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
i {
font-size: 28px;
color: #fff;
display: none;
transition: all ease 0.3s;
}
.view-text {
color: #fff;
font-size: 12px;
display: none;
transition: all ease 0.3s;
}
// display: none;
}
}
}
::v-deep .el-image{
.image-slot{
width: 100%;
height: 100%;
}
}
.buttons {
.el-button {
border-radius: 0;
}
}
</style>
\ No newline at end of file
<template>
<el-dialog
:visible.sync="dialogVisible"
width="40%"
style="height: 98%"
:before-close="handleClose"
top="5vh"
lock-scroll
>
<div class="title" slot="title">
<div class="divider"></div>
<div class="label">{{ title }}</div>
</div>
<div class="dialog-content">
<el-form :model="dialogForm" class="basic-info">
<el-form-item label="博物馆名称" :label-width="formLabelWidth">
<el-input
v-model="dialogForm.name"
autocomplete="off"
placeholder="请输入博物馆名称"
></el-input>
</el-form-item>
<!-- <el-form-item label="所属部门" :label-width="formLabelWidth">
<el-cascader
style="width: 100%"
v-model="dialogForm.pid"
:options="orgTreeData"
:props="optionProps"
placeholder="请选择所属部门"
:key="pidModalKey"
disabled
>
</el-cascader>
</el-form-item> -->
<el-form-item label="所属地" :label-width="formLabelWidth">
<el-cascader
style="width: 100%"
v-model="dialogForm.regionCode"
:options="regionTree"
:props="regionOptionProps"
placeholder="请选择所属地"
:key="regionCodeModalKey"
>
</el-cascader>
</el-form-item>
<el-row :gutter="5">
<el-col :span="12">
<el-form-item label="经度" :label-width="formLabelWidth">
<el-input
style="width: 100%"
v-model="dialogForm.longitude"
autocomplete="off"
placeholder="请输入经度"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12"
><el-form-item label="纬度" :label-width="formLabelWidth">
<el-input
v-model="dialogForm.latitude"
autocomplete="off"
placeholder="请输入纬度"
></el-input> </el-form-item
></el-col>
</el-row>
<el-form-item label="状态" :label-width="formLabelWidth">
<el-switch v-model="status"> </el-switch>
</el-form-item>
<el-form-item label="博物馆封面" :label-width="formLabelWidth">
<ManualUploader
:files="faceImage"
:fileLimit="1"
:fileSize="50"
listType="picture-card"
:fileType="['png', 'jpeg', 'jpg']"
ref="museumFaceImage"
/>
</el-form-item>
<el-form-item label="简介" :label-width="formLabelWidth">
<el-input
type="textarea"
placeholder="请输入博物馆简介"
v-model="dialogForm.intro"
maxlength="600"
show-word-limit
>
</el-input>
</el-form-item>
</el-form>
</div>
<div class="dialog-footer">
<el-button @click="cancelForm">取 消</el-button>
<el-button type="primary" @click="handleSubmit"
>确定<i class="el-icon-right" style="margin-left: 5px"></i
></el-button>
</div>
</el-dialog>
</template>
<script>
import { addMuseum, editMuseum } from "@/api/org";
import ManualUploader from "@/components/Uploader/ManualUploader.vue";
import { mapGetters } from "vuex";
import { uploadV1 } from "@/utils/file";
import { deleteFiles } from "@/api/file";
export default {
name: "InfoEditDialog",
components: {
ManualUploader,
},
props: {
visible: {
type: Boolean,
default: false,
},
form: {
type: Object,
default: () => ({}),
},
orgTreeData: {
type: Array,
default: () => [],
},
},
computed: {
...mapGetters(["userInfo"]),
dialogVisible: {
get: function () {
return this.visible;
},
set: function () {},
},
title() {
if (this.dialogForm.id) {
return "修改博物馆信息";
} else {
return "添加博物馆";
}
},
},
watch: {
dialogVisible(value) {
if (value) {
// 判断是否本地
this.loadRegionTree();
}
},
form: {
handler: function (value) {
let that = this;
that.dialogForm = JSON.parse(JSON.stringify(value));
// 编辑状态
if (that.dialogForm.id) {
that.status = Boolean(Number(that.dialogForm.status));
// 回填封面
if (this.dialogForm.faceImage) {
that.faceImage = [
{
name: this.dialogForm.name + "封面.png",
url:
this.dialogForm.faceImagePressUrl ||
this.dialogForm.faceImageUrl,
fileId: this.dialogForm.faceImage,
},
];
}
// 编辑状态下禁用当前所属地之下的节点
}
},
immediate: true,
deep: true,
},
orgTreeData: {
handler: function (value) {
if (value && value.length > 0) {
if (value.length > 0 && !this.dialogForm.id) {
this.dialogForm.pid = value[0].id; //新增状态下,将所属部门默认填写为树结构根节点
}
}
},
immediate: true,
deep: true,
},
status(value) {
console.log(value);
},
},
data() {
return {
dialogForm: {},
formLabelWidth: "100px",
optionProps: {
value: "id",
label: "name",
children: "children",
checkStrictly: true, //单选选择任意一级选项
},
regionOptionProps: {
value: "code",
label: "name",
children: "children",
checkStrictly: true, //单选选择任意一级选项
},
regionTree: [],
status: false,
pidModalKey: 0,
regionCodeModalKey: 0,
faceImage: [],
parentPid: null, //博物馆根节点id
};
},
methods: {
handlePreview({ type, file }) {
console.log(type, file);
},
handleRemove(file, fileList) {
console.log(file, fileList);
},
// 取消编辑
cancelForm() {
this.$emit("handleClose");
this.faceImage = [];
},
loadRegionTree() {
let parentId = "";
this.$store.dispatch("org/getSysRegionTreeData", parentId).then((res) => {
this.regionTree = res;
loopTree(this.regionTree);
function loopTree(arr) {
if (arr && arr.length > 0) {
arr.forEach((item) => {
if (item.children && item.children.length == 0) {
delete item.children;
} else {
loopTree(item.children);
}
});
}
}
});
},
async handleSubmit() {
let params = { ...this.dialogForm };
let deleteFileArr = [];
// 回填图片
let file = this.$refs.museumFaceImage.getFiles();
if (file.length > 0) {
let formData = new FormData();
switch (file[0].status) {
case "ready":
formData.append("faceImage", file[0].raw);
let upLoadRes = await uploadV1(formData);
if (upLoadRes.code == 0) {
params.faceImage = upLoadRes.data[0].fileId;
} else {
this.$message.error("上传失败!:" + upLoadRes.data.msg);
}
deleteFileArr.push(this.dialogForm.faceImage);
break;
case "success":
params.faceImage = file[0].fileId;
break;
}
} else {
params.faceImage = "";
}
// 处理行政区划
if (params.regionCode instanceof Array) {
params.regionCode = params.regionCode[params.regionCode.length - 1];
}
// 处理所属部门
params.pid = this.regionTree[0].regionId;
// 处理状态
params.status = this.status ? 1 : 0;
if (this.dialogForm.id) {
let res = await editMuseum(params);
deleteFiles(deleteFileArr);
if (res.code == 0) {
this.$message.success("修改成功!");
this.reload();
}
} else {
let res = await addMuseum(params);
if (res.code == 0) {
this.$message.success("添加成功!");
this.reload();
}
}
},
reload() {
this.$emit("refresh", true); //需要重新获取orgTree
this.$emit("handleClose");
this.faceImage = [];
},
handleClose(done) {
this.$confirm("确认关闭?")
.then((_) => {
done();
this.$emit("handleClose");
this.faceImage = [];
})
.catch((_) => {});
},
},
};
</script>
<style lang='scss' scoped>
.title {
display: flex;
margin-bottom: 16px;
.divider {
width: 8px;
border-left: 4px solid #409eff;
margin-right: 8px;
}
.label {
font-weight: bold;
}
}
.dialog-content {
padding: 0 32px;
display: flex;
.basic-info {
flex: 1;
margin-right: 48px;
}
.relate {
flex: 1;
}
}
.dialog-footer {
display: flex;
justify-content: flex-end;
}
.upload-box {
background-color: #fbfdff;
border: 1px dashed #c0ccda;
border-radius: 6px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 148px;
height: 148px;
line-height: 146px;
vertical-align: top;
text-align: center;
margin: 0 8px 8px 0;
i {
font-size: 28px;
color: #8c939d;
}
}
.video-lists {
display: flex;
}
</style>
\ No newline at end of file
export const title = [{
prop: "username",
label: "账号",
columnAlign: 'center',
},
{
prop: "nickName",
label: "昵称",
columnAlign: 'center',
},
{
prop: "deptName",
label: "所属部门",
columnAlign: 'center',
},
{
prop: "phone",
label: "手机号",
columnAlign: 'center',
},
]
export const operates = {
operate: true,
label: "操作",
width: "260px",
minwidth: "220px",
titleAlign: "center",
columnAlign: "center",
}
export const operations = [
{
type: 'edit',
title: '编辑'
},
{
type: 'delete',
title: '删除'
},
]
<!-- -->
<template>
<div class=''>
用户管理
</div>
<div class='users app-container'>
<el-row :gutter="16">
<el-col :span="4">
<el-tree :data="treeData" :props="defaultProps" @node-click="handleNodeClick" default-expand-all></el-tree>
</el-col>
<el-col :span="20">
<div class="top-bar">
<SearchBar :config="searchConfig" @search="search" @reset="reset" />
<el-button type="primary" @click.native="handleOperation({ type: 'add' })" icon="el-icon-s-promotion">
发布</el-button>
</div>
<TablePage :data="list.records" :tableTitle="tableTitle" :operates="tableOperates">
<template v-slot:status="data">
<el-popconfirm :title="getStatusTitle(data.scope.status)" @onConfirm="handleChangeStatus(data.scope)">
<el-switch slot="reference" :value="Boolean(Number(data.scope.status))"></el-switch>
</el-popconfirm>
</template>
<template v-slot:operates="scope">
<TableOperation :operations="tableOperations" :rawData="scope.scope.row" @handleOperation="handleOperation">
</TableOperation>
</template>
</TablePage>
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
:current-page="Number(list.current)" :page-sizes="[10, 20, 40, 50]" :page-size="Number(list.size)"
layout="total, sizes, prev, pager, next, jumper" :total="Number(list.total)" class="pagination">
</el-pagination>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
import TablePage from "@/components/Table/TablePage.vue";
import TableOperation from "@/components/Table/TableOperation.vue";
import SearchBar from "@/components/SearchBar";
import { title, operates, operations } from "./config";
import { getDeptTree, getUserList } from '@/api/user'
export default {
components: {
TablePage,
TableOperation,
SearchBar
// InfoEditDialog,
},
computed: {
tableTitle() {
return title;
},
tableOperates() {
return operates;
},
tableOperations() {
return operations;
},
},
data() {
return {
return {
treeData: [
],
defaultProps: {
children: 'children',
label: 'label'
},
list: {
records: [],
size: 10,
current: 1,
total: 0,
},
searchConfig: [
{
prop: "username",
type: "input",
label: "用户名",
},
{
prop: "nickName",
type: "input",
label: "昵称",
},
],
};
};
},
mounted() {
this.loadTreeData()
this.loadListData()
},
methods: {
// 加载树结构数据
async loadTreeData() {
const res = await getDeptTree()
console.log(111, res);
if (res.code == 0) {
this.treeData = res.data
}
},
// 加载表格数据
async loadListData() {
var params = {
page: this.list.current,
limit: this.list.size,
};
const res = await getUserList(params)
if (res.code == 0) {
this.list = res.data;
}
},
async search(form) {
var params = {
page: this.list.current,
limit: this.list.size,
...form,
};
const res = await getUserList(params)
if (res.code == 0) {
this.list = res.data;
}
},
reset() {
this.loadListData();
},
handleNodeClick(e) {
console.log(e);
},
// 改变页容量
handleSizeChange(value) {
this.list.size = value;
this.loadListData();
},
// 改变当前显示页
handleCurrentChange(value) {
this.list.current = value;
this.loadListData();
},
async handleOperation(value, row) {
console.log("handleOperation", value, row);
switch (value.type) {
case "add":
// this.drawerVisible = true;
break;
case "edit":
// this.form = row;
// this.drawerVisible = true;
break;
case "delete":
// let deleteRes = await deleteLt([row.literatureId]);
// if (deleteRes.code == 0) {
// this.$message.success("删除成功!");
// this.loadData();
// }
break;
}
},
},
};
};
</script>
<style lang="scss" scoped>
.top-bar {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.pagination {
margin: 16px;
}
</style>
.el-button {
margin-bottom: 22px;
}
</style>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论