'保安项目提交'

This commit is contained in:
esacpe
2025-09-22 09:01:41 +08:00
commit 21e2a12e3c
1439 changed files with 336271 additions and 0 deletions

View File

@ -0,0 +1,34 @@
<template>
<el-dialog title="角色选择" :model-value="modelValue" @close="closed">
内容
<template #footer>
<div class="dialog-footer">
<el-button @click="closed">关闭</el-button>
<el-button type="primary" @click="onConfirm">保存</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { defineProps } from 'vue';
defineProps({
modelValue: {
type: Boolean,
required: true
}
})
const emits = defineEmits(['update:modelValue'])
const closed = () => {
emits('update:moselValus',false)
}
/**
确定按钮点击事件
*/
const onConfirm = async () => {
closed()
}
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,124 @@
<template>
<el-dialog title="配置角色" :model-value="modelValue" @close="closed">
<!-- <el-checkbox-group v-model="userRoleTitleList">
<el-checkbox v-for="item in allRoleList" :key="item.id" :label="item.roleName" />
</el-checkbox-group>-->
<el-table max-height="380px" ref="multipleTableRef" :data="allRoleList" style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column property="orderNo" label="角色编号" />
<el-table-column property="roleName" label="角色名称" />
<el-table-column prop="xtZhxgsj" label="更新时间">
<template #default="{ row }">{{ $filters.dateFilter(row.xtZhxgsj) }}</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer">
<el-button @click="closed">取消</el-button>
<el-button type="primary" :loading="buttonLoading" @click="onComfirm">保存</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ElMessage } from "element-plus";
import { defineProps, watch, ref, onMounted, nextTick } from "vue";
import {
getRoleList,
saveRoleDeptInfo,
selectRolePageByDept,
getUserRoleList,
grantRoleToUser
} from "@/api/user-manage";
const props = defineProps({
modelValue: {
type: Boolean,
required: true
},
deptId: {
type: String,
required: true
}
});
const buttonLoading = ref(false)
const emits = defineEmits(["update:modelValue", "updateRole"]);
const closed = () => {
emits("update:modelValue", false);
};
const multipleTableRef = ref(null)
const multipleSelection = ref([]);
const handleSelectionChange = (val) => {
multipleSelection.value = val;
};
// 为用户分配角色
const onComfirm = () => {
const ids = multipleSelection.value.map((item) => {
return item.id;
});
let params = {
deptId: props.deptId,
roleIds: ids
};
buttonLoading.value = true;
saveRoleDeptInfo(params).then((res) => {
ElMessage.success("操作成功");
//通知
emits("updateRole");
}).finally(() => {
buttonLoading.value = false;
}); ;
closed();
};
//当前用户角色
const userRoleTitleList = ref([]);
const getUserRoles = async () => {
const res = await selectRolePageByDept({ current: 1, size: 9999, deptId: props.deptId });
userRoleTitleList.value = res.records.map((item) => item.roleId);
const hx = [];
allRoleList.value.forEach(item => {
if (userRoleTitleList.value.indexOf(item.id)!=-1) {
hx.push(item)
}
})
toggleSelection(hx)
};
const toggleSelection = (rows) => {
if (rows) {
rows.forEach((row) => {
multipleTableRef.value.toggleRowSelection(row, true)
})
} else {
multipleTableRef.value.clearSelection()
}
}
//所有角色
const allRoleList = ref([]);
const getAllRoleList = async () => {
const params = {
page: 1,
size: 999
};
const res = await getRoleList(params);
allRoleList.value = res?.records;
getUserRoles();
};
watch(
() => props.deptId,
(val) => {
if (val) {
getAllRoleList();
}
}
);
</script>
<style>
</style>

View File

@ -0,0 +1,480 @@
<template>
<div class="user-list-page">
<el-card class="table-header-wrap">
<el-form :model="listQuery" class="mosty-from-wrap" :inline="true">
<el-form-item label="用户ID">
<el-input
placeholder="请输入用户ID"
v-model="listQuery.userId"
clearable
></el-input>
</el-form-item>
<el-form-item>
<el-button type="success" @click="handleFilter">查询</el-button>
</el-form-item>
<el-form-item>
<el-button type="danger" @click="unbundleRole()"
>批量取消授权</el-button
>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="addUser()">添加用户</el-button>
</el-form-item>
</el-form>
</el-card>
<div class="main-box">
<el-card class="user-main-wrap">
<el-table
ref="multipleTableRef"
@selection-change="handleSelectionChange"
:data="tableData"
border
style="width: 100%"
>
<el-table-column type="selection" width="55" />
<el-table-column
prop="loginName"
align="center"
label="用户名"
></el-table-column>
<el-table-column
prop="userName"
align="center"
label="用户昵称"
></el-table-column>
<el-table-column
prop="mobile"
width="120px"
label="移动电话"
></el-table-column>
<el-table-column prop="xtZhxgsj" align="center" label="录入时间">
<template #default="{ row }">{{
$filters.dateFilter(row.xtLrsj)
}}</template>
</el-table-column>
<el-table-column label="操作" width="120">
<template #default="{ row }">
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要删除?"
@confirm="unbundleRole(row)"
>
<template #reference>
<el-button type="danger" size="small">取消授权</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.current"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</el-card>
</div>
<el-dialog
width="900px"
custom-class="way"
v-model="dialogFormVisible"
@closed="closeDialog"
:title="isEdit ? '修改' : '新增'"
>
<p>{{ dialogForm }}</p>
<el-form
ref="formRef"
:model="dialogForm"
label-width="120px"
class="mosty-from-wrap twoLine"
:rules="rules"
>
<el-form-item label="用户昵称:" prop="">
<MOSTY.Other
width="280px"
placeholder="用户昵称"
clearable
v-model="dialogForm.userName"
/>
</el-form-item>
<el-form-item label="登录账号:" prop="">
<MOSTY.Other
width="280px"
placeholder="登录账号"
clearable
v-model="dialogForm.loginName"
/>
</el-form-item>
<el-form-item label="密码:" prop="">
<MOSTY.Other
width="280px"
placeholder="密码"
show-password
v-model="dialogForm.password"
/>
</el-form-item>
<el-form-item label="身份证号" prop="idEntityCard">
<MOSTY.IdentityCard
width="280px"
v-model="dialogForm.idEntityCard"
clearable
></MOSTY.IdentityCard>
</el-form-item>
<el-form-item label="电话号码:" prop="telePhone">
<MOSTY.Phone
width="280px"
v-model="dialogForm.telePhone"
maxlength="11"
clearable
></MOSTY.Phone>
</el-form-item>
<el-form-item label="移动电话:" prop="mobile">
<MOSTY.Phone
width="280px"
v-model="dialogForm.mobile"
maxlength="11"
clearable
></MOSTY.Phone>
</el-form-item>
<el-form-item label="封装民族:" prop="nation">
<MOSTY.PackageSelect
width="280px"
v-model="dialogForm.nation"
dictEnum="NATION"
clearable
filterable
/>
</el-form-item>
<el-form-item label="性别:" prop="">
<MOSTY.Sex width="220px" v-model:sex="dialogForm.sex" />
</el-form-item>
<el-form-item label="文化程度:" prop="">
<MOSTY.PackageSelect
dictEnum="EDUCATION"
width="280px"
v-model="dialogForm.whcd"
clearable
filterable
/>
</el-form-item>
<el-form-item label="E-mail" prop="email">
<MOSTY.Email
v-model="dialogForm.email"
width="280px"
clearable
></MOSTY.Email>
</el-form-item>
<el-form-item label="出生日期" prop="email">
<el-date-picker
v-model="dialogForm.birthday"
type="date"
placeholder="出生日期"
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="有效期:" prop="">
<el-date-picker
v-model="dialogForm.endTime"
type="datetime"
placeholder="Select date and time"
format="YYYY/MM/DD hh:mm:ss"
value-format="x"
/>
</el-form-item>
<el-form-item label="行业号码:" prop="">
<MOSTY.Other
width="280px"
placeholder="行业号码"
v-model="dialogForm.inDustRialId"
/>
</el-form-item>
<el-form-item label="管理部门名称:" prop="">
<MOSTY.Other
width="280px"
placeholder="管理部门名称"
v-model="dialogForm.managerOrgName"
/>
</el-form-item>
<el-form-item label="管理部门ID:" prop="">
<MOSTY.Department
placeholder="管理部门ID"
width="280px"
clearable
filterable
multiple
v-model="dialogForm.managerOrgId"
/>
</el-form-item>
<el-form-item label="岗位名称:" prop="">
<MOSTY.Other
width="280px"
placeholder="岗位名称"
v-model="dialogForm.positionName"
/>
</el-form-item>
<el-form-item label="岗位ID:" prop="">
<MOSTY.Other
width="280px"
placeholder="岗位ID"
v-model="dialogForm.positionId"
/>
</el-form-item>
<el-form-item label="用户类型:" prop="">
<el-select v-model="dialogForm.userType" placeholder="请选择">
<el-option label="系统用户默认" value="00" />
<el-option label="注册用户" value="01" />
</el-select>
</el-form-item>
<el-form-item label="虚拟用户:" prop="">
<el-select v-model="dialogForm.isVirtualUser" placeholder="请选择">
<el-option label="是" value="1" />
<el-option label="不是" value="2" />
</el-select>
</el-form-item>
<el-form-item label="备注">
<el-input
v-model="dialogForm.bz"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" v-if="isEdit" @click="onSave"
>保存</el-button
>
<el-button type="primary" v-else @click="onAdd">新增</el-button>
</span>
</template>
</el-dialog>
<ChooseUser
v-model="chooseUserVisible"
:roleId="route.params.id"
@choosedUsers="saveUsers"
></ChooseUser>
</div>
</template>
<script setup>
import ChooseUser from "@/components/MyComponents/ChooseUser";
import { useRoute } from "vue-router";
import * as rule from "@/utils/rules.js";
import * as MOSTY from "@/components/MyComponents/index";
import { ElMessage } from "element-plus";
import { ref, reactive, computed, watch } from "vue";
import {
selectUnAccreditPage,
batchUnboundUserRole,
selectUserPageByDept,
grantUserToRole
} from "@/api/user-manage";
const route = useRoute();
const rules = ref({
...rule.phoneRule({ validator: true }, "mobile"), // 是否必填 是否进行校验
...rule.phoneRule({ validator: true }, "telePhone"), // 是否必填 是否进行校验 如果props与from里面数据不一致可以传第二个参数
...rule.identityCardRule({ validator: true }), //身份证校验
...rule.addressSelectRule({ require: true }), //地址
...rule.emailRule({ validator: true }), //邮箱
packageSelect: [
{
required: true,
message: "请选择",
trigger: "change"
}
],
other: [
{
required: true,
message: "自由发挥哦",
trigger: "blur"
}
]
});
//查询参数
const total = ref(0);
const currentRow = ref({});
const listQuery = ref({
current: 1,
size: 20
});
const isEdit = ref(true);
const dialogForm = ref({
userName: ""
});
// 数据相关
const tableData = ref([]);
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
// 获取数据的方法
const getListData = async () => {
const params = listQuery.value;
params.current = params.page;
params.deptId = route.params.id;
const res = await selectUserPageByDept(params);
tableData.value = res?.records;
total.value = Number(res.total);
};
const handleFilter = () => {
listQuery.value.current = 1;
getListData();
};
// 分页相关
/**
* size 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.size = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.current = currentPage;
getListData();
};
const unbundleRole = (row) => {
let params = {
roleId: route.params.id,
userIdList: []
};
if (row) {
params.userIdList.push(row.id);
} else {
if (multipleSelection.value.length <= 0) return false;
multipleSelection.value.forEach((item) => {
params.userIdList.push(item.id);
});
}
batchUnboundUserRole(params).then((res) => {
ElMessage.success("操作成功");
handleFilter();
});
};
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
};
//分配角色
const currentUserId = ref("");
const roleDialogVisible = ref(false);
const assignRoles = (row) => {
roleDialogVisible.value = true;
currentUserId.value = row.id;
};
const multipleTableRef = ref(null);
const multipleSelection = ref([]);
const handleSelectionChange = (val) => {
multipleSelection.value = val;
};
const chooseUserVisible = ref(false);
const addUser = () => {
chooseUserVisible.value = true;
};
//批量添加用户
const saveUsers = (users) => {
if (users.length > 0) {
let userIds = users.map((item) => item.id);
let params = {
roleId: route.params.id,
userIds: userIds
};
grantUserToRole(params).then((res) => {
ElMessage.success("修改成功");
handleFilter();
});
}
};
//watch监听路由变化
watch(roleDialogVisible, (val) => {
if (!val) currentUserId.value = "";
});
watch(
listQuery.value,
() => {
handleFilter();
},
{
immediate: true
}
);
</script>
<style lang="scss" scoped>
.user-list-page {
.table-header-wrap {
margin-bottom: 22px;
}
::v-deep .avatar {
width: 60px;
height: 60px;
border-radius: 50%;
}
::v-deep .el-tag {
margin-right: 6px;
}
.pagination {
margin-top: 20px;
}
.twoLine {
display: flex;
align-items: flex-start;
flex-flow: wrap;
.el-form-item {
width: 380px;
}
}
.main-box {
padding-top: 20px;
display: flex;
justify-content: space-between;
.departmentTree-box {
overflow: auto;
}
.user-main-wrap {
overflow: hidden;
// width: calc(100% - 260px);
width: 100%;
.el-table--fit {
float: right;
width: 800px;
}
}
}
}
</style>

View File

@ -0,0 +1,617 @@
<template>
<div>
<div class="titleBox">
<div class="title">部门管理</div>
<div class="btnBox">
<el-button type="primary" @click="addItemMenu">
<el-icon><CirclePlus /></el-icon>
<span>新增</span>
</el-button>
</div>
</div>
<div class="searchBox" ref="searchBox">
<el-form :model="listQuery" :inline="true">
<el-form-item label="部门名称">
<el-input
placeholder="请输入部门名称"
v-model="listQuery.deptname"
clearable
></el-input>
</el-form-item>
<el-form-item>
<el-button @click="handleFilter">查询</el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="tabBox">
<el-table
:data="tableData"
v-loading="loading"
border
row-key="orgCode"
:tree-props="{ children: 'childDeptList', hasChildren: 'hasChildren' }"
style="width: 100%"
:height="tableHeight"
:key="keyCount"
lazy
:load="depLoad"
>
<el-table-column
sortable
prop="orgName"
label="部门名称"
show-overflow-tooltip
width="320"
>
<template #default="{ row }">
{{ row.orgName ? row.orgName : row.orgJc }}
</template>
</el-table-column>
<el-table-column
sortable
prop="orgType"
label="部门类型"
show-overflow-tooltip
align="center"
>
<template #default="{ row }">
<dict-tag :options="D_BZ_BMLX" :value="row.orgType" :tag="false" />
</template>
</el-table-column>
<el-table-column
sortable
prop="orgLevel"
label="部门等级"
show-overflow-tooltip
align="center"
>
<template #default="{ row }">
<dict-tag :options="D_BZ_BMDJ" :value="row.orgLevel" :tag="false" />
</template>
</el-table-column>
<el-table-column
sortable
prop="linkTel"
label="部门电话"
show-overflow-tooltip
align="center"
>
</el-table-column>
<el-table-column
sortable
prop="linkManTel"
label="部门联系人电话"
show-overflow-tooltip
align="center"
>
</el-table-column>
<el-table-column
sortable
prop="linkMan"
label="部门联系人"
show-overflow-tooltip
align="center"
>
</el-table-column>
<!-- <el-table-column prop="qxbs" label="权限标识" align="center" width="140px"></el-table-column> -->
<el-table-column label="操作" align="center" fixed="right" width="320">
<template #default="{ row }">
<el-button @click="update(row)" size="small">编辑</el-button>
<el-button @click="addItemMenu(row)" size="small"
>添加下级</el-button
>
<el-button @click="assignRoles(row)" size="small"
>绑定角色</el-button
>
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要删除?"
@confirm="delDictItem(row)"
>
<template #reference>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</div>
<RolesDialog
v-model="roleDialogVisible"
:deptId="currentDeptId"
@updateRole="handleFilter"
></RolesDialog>
<div v-if="dialogFormVisible" class="dialog">
<div class="head_box">
<span class="title">{{ isEdit ? "修改" : "新增" }}</span>
<div>
<!-- 修改 -->
<el-button
v-if="isEdit"
type="primary"
size="small"
@click="onSave"
:loading="buttonLoading"
>保存</el-button
>
<!-- 新增 -->
<el-button
v-else
type="primary"
size="small"
@click="onAdd"
:loading="buttonLoading"
>保存</el-button
>
<el-button size="small" @click="closeDialog">关闭</el-button>
</div>
</div>
<el-form
class="mosty-from-wrap"
ref="editRef"
:inline="true"
label-position="top"
:model="dialogForm"
>
<el-form-item
label="部门名称"
:rules="[{ required: true, message: '请填写部门名称' }]"
prop="orgName"
label-width="140px"
>
<el-input
placeholder="请填写部门名称"
v-model="dialogForm.orgName"
show-word-limit
maxlength="30"
></el-input>
</el-form-item>
<el-form-item
label="部门全称"
show-word-limit
maxlength="30"
prop="orgQc"
required
label-width="140px"
>
<el-input
placeholder="请填写部门全称"
v-model="dialogForm.orgQc"
show-word-limit
maxlength="30"
></el-input>
</el-form-item>
<el-form-item
label="部门简称"
:rules="[{ required: true, message: '请填写部门简称' }]"
prop="orgJc"
required
label-width="140px"
>
<el-input
placeholder="请填写部门简称"
v-model="dialogForm.orgJc"
show-word-limit
maxlength="30"
></el-input>
</el-form-item>
<el-form-item
label="部门类型"
:rules="[{ required: true, message: '请选择部门类型' }]"
prop="orgType"
required
label-width="140px"
>
<!-- <el-input
show-word-limit
maxlength="30"
v-model="dialogForm.orgType"
></el-input> -->
<el-select
style="width: 100%"
v-model="dialogForm.orgType"
class="m-4"
placeholder="请选择部门类型"
>
<el-option
v-for="item in D_BZ_BMLX"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item
label="部门代码"
:rules="[{ required: true, message: '请填写部门代码' }]"
prop="orgCode"
required
label-width="140px"
>
<el-input
placeholder="请填写部门代码"
show-word-limit
maxlength="30"
v-model="dialogForm.orgCode"
></el-input>
</el-form-item>
<el-form-item
label="部门等级"
:rules="[{ required: true, message: '请选择部门等级' }]"
prop="orgLevel"
required
label-width="140px"
>
<el-select
style="width: 100%"
v-model="dialogForm.orgLevel"
class="m-4"
placeholder="请选择部门等级"
>
<el-option
v-for="dict in D_BZ_BMDJ"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="部门顺序号" label-width="140px">
<el-input-number
style="width: 100%"
v-model="dialogForm.orgNo"
class="mx-4"
placeholder="请填写部门顺序号"
:min="1"
:max="100"
controls-position="right"
/>
</el-form-item>
<el-form-item label="部门电话" prop="linkTel" label-width="140px">
<el-input
v-model="dialogForm.linkTel"
placeholder="请填写部门电话"
></el-input>
</el-form-item>
<el-form-item
label="部门业务类型"
:rules="[{ required: true, message: '请选择部门业务类型' }]"
prop="orgBizType"
required
label-width="140px"
>
<!-- <el-input
show-word-limit
maxlength="30"
v-model="dialogForm.orgBizType"
></el-input> -->
<el-select
style="width: 100%"
v-model="dialogForm.orgBizType"
class="m-4"
placeholder="请选择部门业务类型"
>
<el-option
v-for="item in D_BZ_BMYWLX"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="部门联系人电话" label-width="140px">
<el-input
placeholder="请填写部门联系人电话"
v-model="dialogForm.linkManTel"
></el-input>
</el-form-item>
<el-form-item label="部门联系人" label-width="140px">
<el-input
show-word-limit
placeholder="请填写部门联系人"
maxlength="30"
v-model="dialogForm.linkMan"
></el-input>
</el-form-item>
<el-form-item label="部门邮箱" label-width="140px">
<el-input
v-model="dialogForm.email"
placeholder="请填写部门邮箱"
></el-input>
</el-form-item>
<el-form-item label="部门名称拼音" label-width="140px">
<el-input
show-word-limit
maxlength="30"
placeholder="请填写部门名称拼音"
v-model="dialogForm.bmpyszm"
></el-input>
</el-form-item>
<el-form-item label="部门主页" label-width="140px">
<el-input
show-word-limit
placeholder="请填写部门主页"
maxlength="50"
v-model="dialogForm.webUrl"
></el-input>
</el-form-item>
<el-form-item label="部门所属行政区划" label-width="140px">
<el-input
show-word-limit
placeholder="请填写部门所属行政区划"
maxlength="50"
v-model="dialogForm.xzqh"
></el-input>
</el-form-item>
<!-- <el-form-item label="状态" label-width="140px">
<el-select v-model="dialogForm.zdywlb" placeholder="请选择业务类别">
<el-option label="正常" value="0"></el-option>
<el-option label="注销" value="1"></el-option>
</el-select>
</el-form-item>-->
<el-form-item style="width: 100%" label="部门地址" label-width="140px">
<el-input
show-word-limit
placeholder="请填写部门地址"
maxlength="200"
v-model="dialogForm.address"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
></el-input>
</el-form-item>
<el-form-item style="width: 100%" label="备注" label-width="140px">
<el-input
v-model="dialogForm.bz"
show-word-limit
maxlength="200"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
></el-input>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script setup>
import RolesDialog from "./components/roles.vue";
import { ElMessage } from "element-plus";
import { ref, reactive, onMounted, getCurrentInstance, onUnmounted } from "vue";
import {
addSysDept,
deleteSysDept,
updateSysDept,
selectDeptPage
} from "@/api/user-manage";
import { useRouter, useRoute } from "vue-router";
const { proxy } = getCurrentInstance();
const { D_BZ_BMYWLX, D_BZ_BMDJ, D_BZ_BMLX } = proxy.$dict(
"D_BZ_BMYWLX",
"D_BZ_BMDJ",
"D_BZ_BMLX"
);
const keyCount = ref(0); //tabel组件刷新值
const searchBox = ref(null); // 搜索盒子
const tableHeight = ref(); // 表格高度
const route = useRoute();
//查询参数
const total = ref(0);
const currentRow = ref({});
const listQuery = ref({
deptname: "",
deptcode: ""
});
const topParentId = ref("");
const id = ref("");
const zdlx = ref();
const buttonLoading = ref(false);
const isEdit = ref(true);
const dialogForm = ref({
orgNo: 1
});
// 数据相关
const tableData = ref([]);
const loading = ref(false);
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
//动态加载部门数据
function depLoad(row, treeNode, resolve) {
listQuery.value.parentid = row.id;
selectDeptPage(listQuery.value).then((res) => {
resolve(res);
});
}
// 获取数据的方法
const getListData = async () => {
const params = listQuery.value;
loading.value = true
const res = await selectDeptPage(params);
tableData.value = res;
loading.value = false
total.value = Number(res.total);
};
const reset = () => {
tableData.value = [];
listQuery.value = {
deptname: "",
deptcode: ""
};
getListData();
};
const handleFilter = () => {
getListData();
};
getListData();
// 分页相关
/**
* size 改变触发
*/
const handleSizeChange = (currentSize) => {
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
getListData();
};
/**修改字典 */
const update = (row) => {
isEdit.value = true;
dialogForm.value = { ...row };
// dialogForm.value.linkManTel = parseInt(dialogForm.value.linkManTel);
// dialogForm.value.linkTel = parseInt(dialogForm.value.linkTel);
dialogFormVisible.value = true;
};
function isNull(data) {
if (!data) return true;
if (JSON.stringify(data) === "{}") return true;
if (JSON.stringify(data) === "[]") return true;
return false;
}
const addItemMenu = (row) => {
id.value = isNull(row) ? topParentId.value : row.id;
isEdit.value = false;
dialogForm.value = {
orgNo: 1
};
dialogFormVisible.value = true;
};
const onSave = () => {
editRef.value.validate((valid) => {
if (valid) {
buttonLoading.value = true;
updateSysDept({
...dialogForm.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("修改成功");
reset();
})
.finally(() => {
buttonLoading.value = false;
});
} else {
ElMessage.error("请填写完必填项!");
return false;
}
});
};
const editRef = ref(null);
const onAdd = () => {
editRef.value.validate((valid) => {
if (valid) {
buttonLoading.value = true;
addSysDept({
...dialogForm.value,
parentId: id.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("新增成功");
reset();
})
.finally(() => {
buttonLoading.value = false;
});
} else {
ElMessage.error("请填写完必填项!");
return false;
}
});
};
const delDictItem = (row) => {
deleteSysDept({
id: Number(row.id)
}).then((res) => {
ElMessage.success("删除成功");
reset();
});
};
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
};
const toGoPage = (row) => {
router.push("/user/role?zdbh=" + row.zdbh);
};
//分配角色
const currentDeptId = ref("");
const roleDialogVisible = ref(false);
const assignRoles = (row) => {
roleDialogVisible.value = true;
currentDeptId.value = row.id;
};
//分配用户
const router = useRouter();
const allocationUser = (row) => {
router.push(`/user/deptAllocationUser/${row.id}`);
};
// 表格高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 210;
};
onMounted(() => {
tabHeightFn();
window.onresize = function () {
tabHeightFn();
};
proxy.mittBus.on("mittFn", (data) => {
keyCount.value = data;
});
});
onUnmounted(() => {
proxy.mittBus.off("mittFn");
});
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
.user-manage-container {
.table-header-wrap {
margin-bottom: 22px;
}
::v-deep .avatar {
width: 60px;
height: 60px;
border-radius: 50%;
}
::v-deep .el-tag {
margin-right: 6px;
}
.pagination {
margin-top: 20px;
}
.twoLine {
display: flex;
align-items: flex-start;
flex-flow: wrap;
.el-form-item {
width: 380px;
}
}
}
</style>

View File

@ -0,0 +1,403 @@
<template>
<div class="user-manage-container">
<div class="titleBox">
<div class="title">字典数据</div>
<div class="btnBox">
<el-button type="primary" @click="addItemDict()">
<el-icon><CirclePlus /></el-icon>
<span>新增</span>
</el-button>
<el-button @click="batchDelete" :disabled="ids.length == 0" typeof="danger">
<el-icon style="vertical-align: middle">
<Delete />
</el-icon>
<span style="vertical-align: middle">批量删除</span>
</el-button>
<el-button type="primary" @click="closeItemDict()"> 关闭</el-button>
</div>
</div>
<div ref="searchBox">
<el-card class="table-header-wrap">
<el-form :model="listQuery" :inline="true">
<el-form-item label="字典名称">
<el-input
placeholder="请输入字典名称"
v-model="listQuery.dictName"
clearable
></el-input>
</el-form-item>
<el-form-item>
<el-button type="success" @click="handleFilter"> 查询 </el-button>
</el-form-item>
<el-form-item>
<el-button type="success" @click="resetHandleFilter">
重置
</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
<el-card :style="{ height: tableHeight + 'px' }">
<el-table
:data="tableData"
border
row-key="id"
@selection-change="handleSelectionChange"
:tree-props="{ children: 'itemList', hasChildren: true }"
:height="h"
>
<el-table-column type="selection" width="40" align="center" />
<el-table-column prop="dm" align="center" label="字典代码">
</el-table-column>
<el-table-column prop="zdmc" label="字典名称"> </el-table-column>
<el-table-column prop="py" label="字典拼音" align="center">
</el-table-column>
<el-table-column prop="px" label="字典排序" align="center" sortable>
</el-table-column>
<el-table-column prop="bz" label="备注"> </el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="220">
<template #default="{ row }">
<el-button type="primary" @click="update(row)" size="small"
>编辑</el-button
>
<el-button
type="primary"
v-if="zdlx === 2"
@click="addItemDict(row)"
size="small"
>添加下级</el-button
>
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要删除?"
@confirm="delDictItem(row)"
>
<template #reference>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</el-card>
<div class="fenye" :style="{ top: tableHeight + 'px' }" v-if="type == 1">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageCurrent"
:page-sizes="[10, 20, 50, 100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</div>
<el-dialog
custom-class="way"
v-model="dialogFormVisible"
@closed="closeDialog"
:title="isEdit ? '修改' : '新增'"
>
<el-form
v-if="dialogFormVisible"
ref="formDom"
:rules="rules"
:model="dialogForm"
>
<el-form-item label="字典名称" prop="zdmc" label-width="140px">
<el-input
v-model="dialogForm.zdmc"
show-word-limit
maxlength="50"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="字典拼音" label-width="140px">
<el-input
v-model="dialogForm.py"
show-word-limit
maxlength="50"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="字典代码" prop="dm" label-width="140px">
<el-input
v-model="dialogForm.dm"
show-word-limit
maxlength="50"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item label="排序" prop="px" label-width="140px">
<el-input-number
v-model="dialogForm.px"
class="mx-4"
:min="1"
:max="100"
controls-position="right"
/>
</el-form-item>
<el-form-item label="备注" label-width="140px">
<el-input
v-model="dialogForm.bz"
:autosize="{ minRows: 2, maxRows: 4 }"
show-word-limit
maxlength="200"
type="textarea"
></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" v-if="isEdit" @click="onSave"
>保存</el-button
>
<el-button type="primary" v-else @click="onAdd">新增</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ElMessage } from "element-plus";
import { qcckPost, qcckGet,qcckPut,qcckDelete } from "@/api/qcckApi.js";
import { ref, reactive, onMounted, getCurrentInstance } from "vue";
import { updateSysDictItem, getSysDictByCode, getSysDictByCodeList, deleteSysDictItem, addSysDictItem} from "@/api/sysDict";
import { useRouter, useRoute } from "vue-router";
const formDom = ref(null);
const rules = ref({
zdmc: [{ required: true, message: "请输入字典名称" }],
py: [{ required: true, pattern: /^[a-zA-Z]+$/, message: "请输入字典拼音" }],
dm: [{ required: true, message: "请输入字典代码" }],
px: [{ required: true, message: "请输入字典排序" }]
});
const { proxy } = getCurrentInstance();
const type = ref("1");
const router = useRouter();
const route = useRoute();
//查询参数
const currentRow = ref({});
const listQuery = ref({
dictName: "",
dictCode: "",
xtZxbz: ""
});
const total = ref(0);
const pageSize = ref(20);
const pageCurrent = ref(1);
const ids = ref([]);
const topParentId = ref("");
const id = ref("");
const zdlx = ref();
const isEdit = ref(true);
const dialogForm = ref({});
// 数据相关
const tableData = ref([]);
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
const tableHeight = ref();
const searchBox = ref(null);
const h = ref();
// 表格高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 280;
h.value = window.innerHeight - searchBox.value.offsetHeight - 300;
window.onresize = function () { tabHeightFn(); };
};
onMounted(() => {
type.value = route.query.zdlx;
tabHeightFn();
getListData();
});
//批量数据
const handleSelectionChange = (val) => {
ids.value = val.map((v) => { return v.id; });
};
//批量删除数据
const batchDelete = () => {
proxy.$confirm("确定要删除", "警告", { type: "warning" }).then(() => {
qcckPost(ids.value,'/mosty-base/sys-dict-item/deleteSysDictItemBatch').then(res=>{
proxy.$message({ message: "删除成功",type: "success"});
getListData();
})
}).catch(() => {
proxy.$message.info("已取消");
});
};
// size 改变触发
const handleSizeChange = (currentSize) => {
pageSize.value = currentSize;
getListData();
};
// 页码改变触发
const handleCurrentChange = (currentPage) => {
pageCurrent.value = currentPage;
getListData();
};
// 获取数据的方法
const getListData = async () => {
const params = { dictCode: route.query.zdbh, zdmc: listQuery.value.dictName };
if (route.query.zdlx == 1) {
//列表
params.size = pageSize.value;
params.current = pageCurrent.value;
getlist(params);
} else {
getree(params);
}
};
const getlist = async (params) => {
let res = await getSysDictByCodeList(params);
topParentId.value = route.query.Pid;
tableData.value = res ? res.records : [];
total.value = Number(res.total);
};
const getree = async (params) => {
let res = await getSysDictByCode(params);
topParentId.value = res.id;
zdlx.value = res.zdlx;
tableData.value = res?.itemList;
};
const handleFilter = () => {
listQuery.value.current = 1;
getListData();
};
const resetHandleFilter = () => {
listQuery.value.dictName = "";
listQuery.value.current = 1;
getListData();
};
/**修改字典 */
const update = (row) => {
isEdit.value = true;
dialogForm.value = { ...row };
dialogFormVisible.value = true;
};
function isNull(data) {
if (!data) return true;
if (JSON.stringify(data) === "{}") return true;
if (JSON.stringify(data) === "[]") return true;
return false;
}
const addItemDict = (row) => {
id.value = isNull(row) ? topParentId.value : row.id;
isEdit.value = false;
dialogForm.value = {};
dialogFormVisible.value = true;
};
// 返回字典列表页面
const closeItemDict = () => {
router.push("/dict/index");
};
const onSave = () => {
formDom.value.validate((valid) => {
if (!valid) {
return false;
}
updateSysDictItem({
bz: dialogForm.value.bz,
id: dialogForm.value.id,
dm: dialogForm.value.dm,
px: dialogForm.value.px,
py: dialogForm.value.py,
zdbh: dialogForm.value.zdbh,
zdmc: dialogForm.value.zdmc
}).then((res) => {
dialogFormVisible.value = false;
ElMessage.success("修改成功");
handleFilter();
});
});
};
const onAdd = () => {
formDom.value.validate((valid) => {
if (!valid) {
return false;
}
addSysDictItem({
parentId: id.value,
bz: dialogForm.value.bz,
dm: dialogForm.value.dm,
px: dialogForm.value.px,
py: dialogForm.value.py,
zdbh: dialogForm.value.zdbh,
zdmc: dialogForm.value.zdmc
}).then((res) => {
dialogFormVisible.value = false;
ElMessage.success("新增成功");
handleFilter();
});
});
};
const delDictItem = (row) => {
deleteSysDictItem({ id: Number(row.id) }).then((res) => {
ElMessage.success("删除成功");
handleFilter();
});
};
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
};
const toGoPage = (row) => {
router.push("/user/role?zdbh=" + row.zdbh);
};
</script>
<style lang="scss" scoped>
.user-manage-container {
.table-header-wrap {
margin-bottom: 22px;
}
::v-deep .avatar {
width: 60px;
height: 60px;
border-radius: 50%;
}
::v-deep .el-tag {
margin-right: 6px;
}
.pagination {
margin-top: 20px;
}
}
::v-deep .el-card__body {
background-color: rgba(0, 0, 0, 0);
}
::v-deep .el-card {
--el-card-border-color: #143578;
--el-card-border-radius: 4px;
--el-card-padding: 20px;
--el-card-bg-color: #17096130;
position: relative;
}
::v-deep .el-table--fit {
position: absolute;
top: 14px;
right: 14px;
left: 14px;
// overflow-y: scroll;
width: calc(100% - 28px);
}
</style>

View File

@ -0,0 +1,452 @@
<template>
<div>
<div class="titleBox">
<div class="title">字典列表</div>
<div class="btnBox">
<el-button type="primary" @click="addDict">
<el-icon><CirclePlus /></el-icon>
<span>新增</span>
</el-button>
</div>
</div>
<div class="searchBox" ref="searchBox">
<el-form :model="listQuery" :inline="true">
<el-form-item label="字典名称">
<el-input
placeholder="请输入字典名称"
v-model="listQuery.dictName"
clearable
></el-input>
</el-form-item>
<el-form-item label="字典编码">
<el-input
placeholder="请输入字典编码"
v-model="listQuery.dictCode"
clearable
></el-input>
</el-form-item>
<el-form-item label="字典状态">
<el-select
clearable
v-model="listQuery.xtZxbz"
placeholder="请选择状态"
>
<el-option label="正常" value="0"></el-option>
<el-option label="注销" value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleFilter"> 查询 </el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="tabBox">
<el-table
:data="tableData"
border
row-key="id"
:tree-props="{ children: 'itemList', hasChildren: true }"
style="width: 100%"
:height="tableHeight"
:key="keyCount"
>
<el-table-column
sortable
prop="zdbh"
label="字典编号"
show-overflow-tooltip
>
</el-table-column>
<el-table-column
sortable
prop="zdmc"
label="字典名称"
show-overflow-tooltip
>
</el-table-column>
<el-table-column sortable label="状态" width="80px">
<template #default="{ row }">
<div>
<el-tag size="small" type="success" v-if="row.xtZxbz == 0"
>正常</el-tag
>
<el-tag size="small" type="danger" v-else-if="row.xtZxbz == 1"
>注销</el-tag
>
<el-tag size="small" type="info" v-else>未知</el-tag>
</div>
</template>
</el-table-column>
<el-table-column sortable prop="bz" label="备注" show-overflow-tooltip>
</el-table-column>
<el-table-column sortable prop="xtZhxgsj" label="更新时间">
<template #default="{ row }">
{{ $filters.dateFilter(row.xtZhxgsj) }}
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="260">
<template #default="{ row }">
<el-button @click="updateDict(row)" size="small"> 修改</el-button>
<el-button @click="toGoPage(row)" size="small">
{{ row.zdlx === 1 ? "列表" : "树形" }}</el-button
>
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要注销?"
@confirm="delDict(row)"
@cancel="cancelEvent">
<template #reference>
<el-button type="danger" size="small">注销</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
size
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.current"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</div>
</div>
<div v-if="dialogFormVisible" class="dialog">
<div class="head_box">
<span class="title">{{ isEdit ? "修改" : "新增" }}</span>
<div>
<!-- 修改 -->
<el-button
v-if="isEdit"
type="primary"
size="small"
@click="onSave"
:loading="buttonLoading"
>保存</el-button
>
<!-- 新增 -->
<el-button
v-else
type="primary"
size="small"
@click="onAdd"
:loading="buttonLoading"
>保存</el-button
>
<el-button size="small" @click="closeDialog">关闭</el-button>
</div>
</div>
<el-form
class="mosty-from-wrap"
:inline="true"
label-position="top"
:model="dialogForm"
:rules="rules"
ref="elform"
>
<el-form-item prop="zdmc" class="one" label="字典名称">
<el-input
style="width: 100%"
v-model="dialogForm.zdmc"
show-word-limit
maxlength="50"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item class="one" prop="zdbh" label="字典编码">
<el-input
style="width: 100%"
v-model="dialogForm.zdbh"
show-word-limit
maxlength="30"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item prop="yybz" class="one" label="引用标准">
<el-input
style="width: 100%"
v-model="dialogForm.yybz"
show-word-limit
maxlength="50"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item class="one" prop="xtZxbz" label="状态">
<el-select
style="width: 100%"
v-model="dialogForm.xtZxbz"
placeholder="请选择业务类别"
>
<el-option label="正常" :value="0"></el-option>
<el-option label="注销" :value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item class="one" label="是否是树形结构" prop="zdlx">
<el-select
style="width: 100%"
v-model="dialogForm.zdlx"
placeholder="请选择"
>
<el-option label="列表" :value="1"></el-option>
<el-option label="树形" :value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item class="one" label="备注">
<el-input
style="width: 100%"
v-model="dialogForm.bz"
:autosize="{ minRows: 2, maxRows: 4 }"
show-word-limit
maxlength="200"
type="textarea"
></el-input>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script setup>
import { ElMessage } from "element-plus";
import { ref, reactive, onMounted, getCurrentInstance, onUnmounted } from "vue";
import {
getAllSysDict,
updateSysDict,
addSysDict,
deleteSysDict
} from "@/api/sysDict";
import { useRouter } from "vue-router";
const { proxy } = getCurrentInstance();
const searchBox = ref(null); // 搜索盒子
const tableHeight = ref(); // 表格高度
const keyCount = ref(0); //tabel组件刷新值
const elform = ref(null);
const router = useRouter();
//查询参数
const total = ref(0);
const size = ref(20);
const currentRow = ref({});
const buttonLoading = ref(false);
const listQuery = ref({
current: 1,
size: 20,
dictName: "",
dictCode: "",
xtZxbz: ""
});
const reset = () => {
listQuery.value = {
current: 1,
size: 20,
dictName: "",
dictCode: "",
xtZxbz: ""
};
getListData();
};
const isEdit = ref(true);
const dialogForm = ref({});
// 数据相关
const tableData = ref([]);
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
// 获取数据的方法
const getListData = async () => {
// listQuery.value.pageIndex = pageIndex.value;
// this.listQuery.pageSize = this.pageSize;
// for (let key in this.listQuery) {
// if (this.listQuery[key] === "") {
// delete this.listQuery[key];
// }
// }
const params = listQuery.value;
const res = await getAllSysDict(params);
tableData.value = res?.records;
total.value = Number(res.total);
};
//验证
const rules = ref({
zdmc: [{ required: true, message: "请输入字典名称", trigger: "change" }],
zdbh: [{ required: true, message: "请输入字典编码", trigger: "change" }],
xtZxbz: [{ required: true, message: "请选择业务类别", trigger: "change" }],
zdlx: [{ required: true, message: "请选择字典类型", trigger: "change" }],
yybz: [{ required: true, message: "请填写引用标准", trigger: "change" }]
});
const handleFilter = () => {
listQuery.value.current = 1;
getListData();
};
getListData();
// 分页相关
/**
* size 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.size = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.current = currentPage;
getListData();
};
const cancelEvent = () => {};
/**修改字典 */
const updateDict = (row) => {
isEdit.value = true;
dialogForm.value = { ...row };
dialogForm.value.zdywlb = Number(dialogForm.value.zdywlb);
dialogFormVisible.value = true;
};
const delDict = (row) => {
deleteSysDict({
id: Number(row.id)
}).then((res) => {
ElMessage.success("注销成功");
handleFilter();
});
};
const addDict = (row) => {
isEdit.value = false;
dialogForm.value = {};
dialogFormVisible.value = true;
};
const isAvailable = (val) => {
if (val === 0) return true;
if (
val == null ||
val == undefined ||
val == "" ||
val == "undefined" ||
val == "null"
) {
return false;
} else {
return true;
}
};
const onSave = () => {
elform.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
buttonLoading.value = true;
updateSysDict({
bz: dialogForm.value.bz,
id: dialogForm.value.id,
yybz: dialogForm.value.yybz,
zdbh: dialogForm.value.zdbh,
zdlx: dialogForm.value.zdlx,
zdmc: dialogForm.value.zdmc,
zdywlb: dialogForm.value.zdywlb,
xtZxbz: dialogForm.value.xtZxbz
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("修改成功");
buttonLoading.value = false;
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
});
};
const onAdd = () => {
elform.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
buttonLoading.value = true;
addSysDict({
bz: dialogForm.value.bz,
// id: dialogForm.value.id,
yybz: dialogForm.value.yybz,
zdbh: dialogForm.value.zdbh,
zdlx: dialogForm.value.zdlx,
zdmc: dialogForm.value.zdmc,
zdywlb: dialogForm.value.zdywlb
})
.then((res) => {
ElMessage.success("添加成功");
dialogFormVisible.value = false;
buttonLoading.value = false;
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
});
};
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
};
const toGoPage = (row) => {
router.push("/dict/detail?zdbh=" + row.zdbh + '&zdlx='+row.zdlx + '&Pid='+ row.id);
};
// 表格高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 240;
};
onMounted(() => {
tabHeightFn();
window.onresize = function () {
tabHeightFn();
};
proxy.mittBus.on("mittFn", (data) => {
keyCount.value = data;
});
});
onUnmounted(() => {
proxy.mittBus.off("mittFn");
});
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
// .user-manage-container {
// .table-header-wrap {
// margin-bottom: 22px;
// }
// ::v-deep .avatar {
// width: 60px;
// height: 60px;
// border-radius: 50%;
// }
// ::v-deep .el-tag {
// margin-right: 6px;
// }
// .pagination {
// margin-top: 20px;
// }
// }
</style>

View File

@ -0,0 +1,49 @@
<template>
<el-form ref="basicInfoForm" :model="info" :rules="rules" label-width="150px">
<el-row>
<el-col :span="12">
<el-form-item label="表名称" prop="tableName">
<el-input placeholder="请输入仓库名称" v-model="info.tableName" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="表描述" prop="tableComment">
<el-input placeholder="请输入" v-model="info.tableComment" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="实体类名称" prop="className">
<el-input placeholder="请输入" v-model="info.className" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="作者" prop="functionAuthor">
<el-input placeholder="请输入" v-model="info.functionAuthor" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input type="textarea" :rows="3" v-model="info.remark"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script setup>
import { ref,defineProps, toRefs,reactive,onActivated, watch, nextTick,getCurrentInstance } from "vue";
defineProps({
info: {
type: Object,
default: null
}
});
// 表单校验
const rules = ref({
tableName: [{ required: true, message: "请输入表名称", trigger: "blur" }],
tableComment: [{ required: true, message: "请输入表描述", trigger: "blur" }],
className: [{ required: true, message: "请输入实体类名称", trigger: "blur" }],
functionAuthor: [{ required: true, message: "请输入作者", trigger: "blur" }]
});
</script>

View File

@ -0,0 +1,195 @@
<template>
<el-card>
<el-tabs v-model="activeName">
<el-tab-pane label="基本信息" name="basic">
<basic-info-form ref="basicInfo" :info="info" />
</el-tab-pane>
<el-tab-pane label="字段信息" name="columnInfo">
<el-table ref="dragTable" :data="columns" row-key="columnId" :max-height="tableHeight">
<el-table-column label="序号" type="index" min-width="5%" />
<el-table-column label="字段列名" prop="columnName" min-width="10%" :show-overflow-tooltip="true" />
<el-table-column label="字段描述" min-width="10%">
<template #default="scope">
<el-input v-model="scope.row.columnComment"></el-input>
</template>
</el-table-column>
<el-table-column label="物理类型" prop="columnType" min-width="10%" :show-overflow-tooltip="true" />
<el-table-column label="Java类型" min-width="11%">
<template #default="scope">
<el-select v-model="scope.row.javaType">
<el-option label="Long" value="Long" />
<el-option label="String" value="String" />
<el-option label="Integer" value="Integer" />
<el-option label="Double" value="Double" />
<el-option label="BigDecimal" value="BigDecimal" />
<el-option label="Date" value="Date" />
<el-option label="Boolean" value="Boolean" />
</el-select>
</template>
</el-table-column>
<el-table-column label="java属性" min-width="10%">
<template #default="scope">
<el-input v-model="scope.row.javaField"></el-input>
</template>
</el-table-column>
<el-table-column label="插入" min-width="5%">
<template #default="scope">
<el-checkbox true-label="1" v-model="scope.row.isInsert"></el-checkbox>
</template>
</el-table-column>
<el-table-column label="编辑" min-width="5%">
<template #default="scope">
<el-checkbox true-label="1" v-model="scope.row.isEdit"></el-checkbox>
</template>
</el-table-column>
<el-table-column label="列表" min-width="5%">
<template #default="scope">
<el-checkbox true-label="1" v-model="scope.row.isList"></el-checkbox>
</template>
</el-table-column>
<el-table-column label="查询" min-width="5%">
<template #default="scope">
<el-checkbox true-label="1" v-model="scope.row.isQuery"></el-checkbox>
</template>
</el-table-column>
<el-table-column label="查询方式" min-width="10%">
<template #default="scope">
<el-select v-model="scope.row.queryType">
<el-option label="=" value="EQ" />
<el-option label="!=" value="NE" />
<el-option label=">" value="GT" />
<el-option label=">=" value="GTE" />
<el-option label="<" value="LT" />
<el-option label="<=" value="LTE" />
<el-option label="LIKE" value="LIKE" />
<el-option label="BETWEEN" value="BETWEEN" />
</el-select>
</template>
</el-table-column>
<el-table-column label="必填" min-width="5%">
<template #default="scope">
<el-checkbox true-label="1" v-model="scope.row.isRequired"></el-checkbox>
</template>
</el-table-column>
<el-table-column label="显示类型" min-width="12%">
<template #default="scope">
<el-select v-model="scope.row.htmlType">
<el-option label="文本框" value="input" />
<el-option label="文本域" value="textarea" />
<el-option label="下拉框" value="select" />
<el-option label="单选框" value="radio" />
<el-option label="复选框" value="checkbox" />
<el-option label="日期控件" value="datetime" />
<el-option label="图片上传" value="imageUpload" />
<el-option label="文件上传" value="fileUpload" />
<el-option label="富文本控件" value="editor" />
</el-select>
</template>
</el-table-column>
<el-table-column label="字典类型" min-width="12%">
<template #default="scope">
<el-select v-model="scope.row.dictType" clearable filterable placeholder="请选择">
<el-option v-for="dict in dictOptions" :key="dict.dictType" :label="dict.dictName"
:value="dict.dictType">
<span style="float: left">{{ dict.dictName }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ dict.dictType }}</span>
</el-option>
</el-select>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="生成信息" name="genInfo">
<gen-info-form ref="genInfo" :info="info" :tables="tables" />
</el-tab-pane>
</el-tabs>
<el-form label-width="100px">
<div style="text-align: center;margin-left:-100px;margin-top:10px;">
<el-button type="primary" @click="submitForm()">提交</el-button>
<el-button @click="close()">返回</el-button>
</div>
</el-form>
</el-card>
</template>
<script setup name="GenEdit">
import { ref, toRefs, reactive, onActivated, watch, nextTick, defineProps, getCurrentInstance } from "vue";
import { getGenTable11, updateGenTable, getDictOptionselect } from "@/api/tool/gen";
// import { optionselect as getDictOptionselect } from "@/api/tool/gen";
import basicInfoForm from "./basicInfoForm";
import genInfoForm from "./genInfoForm";
import { useRoute, useRouter } from 'vue-router';
const router = useRouter();
const route = useRoute();
const { proxy } = getCurrentInstance();
const props = defineProps({
modelValue: {
type: Boolean,
required: true
}
})
const activeName = ref("columnInfo");
const tableHeight = ref(document.documentElement.scrollHeight - 245 + "px");
const tables = ref([]);
const columns = ref([]);
const dictOptions = ref([]);
const info = ref({});
/** 提交按钮 */
function submitForm() {
const basicForm = proxy.$refs.basicInfo.$refs.basicInfoForm;
const genForm = proxy.$refs.genInfo.$refs.genInfoForm;
Promise.all([basicForm, genForm].map(getFormPromise)).then(res => {
const validateResult = res.every(item => !!item);
if (validateResult) {
const genTable = Object.assign({}, basicForm.model, genForm.model);
genTable.columns = columns.value;
genTable.params = {
treeCode: genTable.treeCode,
treeName: genTable.treeName,
treeParentCode: genTable.treeParentCode,
parentMenuId: genTable.parentMenuId
};
updateGenTable(genTable).then(res => {
proxy.$modal.msgSuccess(res.msg);
if (res.code === 200) {
close();
}
});
} else {
proxy.$modal.msgError("表单校验未通过,请重新检查提交内容");
}
});
}
function getFormPromise(form) {
return new Promise(resolve => {
form.validate(res => {
resolve(res);
});
});
}
function close() {
router.push('/gen/index')
}
(() => {
const tableId = route.params && route.params.tableId;
if (tableId) {
// 获取表详细信息
getGenTable11(tableId)
.then(res => {
columns.value = res.data.rows;
info.value = res.data.info;
tables.value = res.data.tables;
});
/** 查询字典下拉列表 */
getDictOptionselect().then(response => {
dictOptions.value = response.data;
});
}
})();
</script>

View File

@ -0,0 +1,359 @@
<template>
<el-form ref="genInfoForm" :model="info" :rules="rules" label-width="150px">
<el-row>
<el-col :span="12">
<el-form-item prop="tplCategory">
<template #label>生成模板</template>
<el-select v-model="info.tplCategory" @change="tplSelectChange">
<el-option label="单表(增删改查)" value="crud" />
<el-option label="树表(增删改查)" value="tree" />
<el-option label="主子表(增删改查)" value="sub" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="packageName">
<template #label>
生成包路径
<el-tooltip content="生成在哪个java包下例如 com.ruoyi.system" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
</template>
<el-input v-model="info.packageName" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="moduleName">
<template #label>
生成模块名
<el-tooltip content="可理解为子系统名,例如 system" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
</template>
<el-input v-model="info.moduleName" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="businessName">
<template #label>
生成业务名
<el-tooltip content="可理解为功能英文名,例如 user" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
</template>
<el-input v-model="info.businessName" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="functionName">
<template #label>
生成功能名
<el-tooltip content="用作类描述,例如 用户" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
</template>
<el-input v-model="info.functionName" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<template #label>
上级菜单
<el-tooltip content="分配到指定菜单下,例如 系统管理" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
</template>
<tree-select v-model:value="info.parentMenuId" :options="menuOptions"
:objMap="{ value: 'id', label: 'menuName', children: 'sysMenuList' }" placeholder="请选择系统菜单" />
<!-- <el-tree
ref="treeRef"
:data="menuOptions"
:props="defaultProps"
node-key="id"
show-checkbox
default-expand-all
:check-strictly="true"
@check="checkeTree"
>
</el-tree> -->
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item prop="genType">
<template #label>
生成代码方式
<el-tooltip content="默认为zip压缩包下载也可以自定义生成路径" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
</template>
<el-radio v-model="info.genType" label="0">zip压缩包</el-radio>
<el-radio v-model="info.genType" label="1">自定义路径</el-radio>
</el-form-item>
</el-col>
<el-col :span="24" v-if="info.genType == '1'">
<el-form-item prop="genPath">
<template #label>
自定义路径
<el-tooltip content="填写磁盘绝对路径若不填写则生成到当前Web项目下" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
</template>
<el-input v-model="info.genPath">
<template #append>
<el-dropdown>
<el-button type="primary">
最近路径快速选择
<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="info.genPath = '/'">恢复默认的生成基础路径</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<template v-if="info.tplCategory == 'tree'">
<h4 class="form-header">其他信息</h4>
<el-row v-show="info.tplCategory == 'tree'">
<el-col :span="12">
<el-form-item>
<template #label>
树编码字段
<el-tooltip content="树显示的编码字段名, 如dept_id" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
</template>
<el-select v-model="info.treeCode" placeholder="请选择">
<el-option v-for="(column, index) in info.columns" :key="index"
:label="column.columnName + '' + column.columnComment" :value="column.columnName"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<template #label>
树父编码字段
<el-tooltip content="树显示的父编码字段名, 如parent_Id" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
</template>
<el-select v-model="info.treeParentCode" placeholder="请选择">
<el-option v-for="(column, index) in info.columns" :key="index"
:label="column.columnName + '' + column.columnComment" :value="column.columnName"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<template #label>
树名称字段
<el-tooltip content="树节点的显示名称字段名, 如dept_name" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
</template>
<el-select v-model="info.treeName" placeholder="请选择">
<el-option v-for="(column, index) in info.columns" :key="index"
:label="column.columnName + '' + column.columnComment" :value="column.columnName"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</template>
<template v-if="info.tplCategory == 'sub'">
<h4 class="form-header">关联信息</h4>
<el-row>
<el-col :span="12">
<el-form-item>
<template #label>
关联子表的表名
<el-tooltip content="关联子表的表名, 如sys_user" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
</template>
<el-select v-model="info.subTableName" placeholder="请选择" @change="subSelectChange">
<el-option v-for="(table, index) in tables" :key="index"
:label="table.tableName + '' + table.tableComment" :value="table.tableName"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item>
<template #label>
子表关联的外键名
<el-tooltip content="子表关联的外键名, 如user_id" placement="top">
<i class="el-icon-question"></i>
</el-tooltip>
</template>
<el-select v-model="info.subTableFkName" placeholder="请选择">
<el-option v-for="(column, index) in subColumns" :key="index"
:label="column.columnName + '' + column.columnComment" :value="column.columnName"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</template>
</el-form>
</template>
<script setup>
import { getMenuTree as listMenu } from "@/api/user-manage";
import {
ref,
toRefs,
reactive,
onActivated,
watch,
nextTick,
getCurrentInstance
} from "vue";
const subColumns = ref([]);
const menuOptions = ref({});
const { proxy } = getCurrentInstance();
const props = defineProps({
info: {
type: Object,
default: null
},
tables: {
type: Array,
default: null
}
});
// 表单校验
const rules = ref({
tplCategory: [{ required: true, message: "请选择生成模板", trigger: "blur" }],
packageName: [
{ required: true, message: "请输入生成包路径", trigger: "blur" }
],
moduleName: [
{ required: true, message: "请输入生成模块名", trigger: "blur" }
],
businessName: [
{ required: true, message: "请输入生成业务名", trigger: "blur" }
],
functionName: [
{ required: true, message: "请输入生成功能名", trigger: "blur" }
]
});
function subSelectChange(value) {
props.info.subTableFkName = "";
}
function tplSelectChange(value) {
if (value !== "sub") {
props.info.subTableName = "";
props.info.subTableFkName = "";
}
}
function setSubTableColumns(value) {
for (var item in props.tables) {
const name = props.tables[item].tableName;
if (value === name) {
subColumns.value = props.tables[item].columns;
break;
}
}
}
/**
* 构造树型结构数据
* @param {*} data 数据源
* @param {*} id id字段 默认 'id'
* @param {*} parentId 父节点字段 默认 'parentId'
* @param {*} children 孩子节点字段 默认 'children'
*/
const handleTree = (data, id, parentId, children) => {
let config = {
id: id || "id",
parentId: parentId || "parentId",
childrenList: children || "children"
};
var childrenListMap = {};
var nodeIds = {};
var tree = [];
for (let d of data) {
let parentId = d[config.parentId];
if (childrenListMap[parentId] == null) {
childrenListMap[parentId] = [];
}
nodeIds[d[config.id]] = d;
childrenListMap[parentId].push(d);
}
for (let d of data) {
let parentId = d[config.parentId];
if (nodeIds[parentId] == null) {
tree.push(d);
}
}
for (let t of tree) {
adaptToChildrenList(t);
}
function adaptToChildrenList(o) {
if (childrenListMap[o[config.id]] !== null) {
o[config.childrenList] = childrenListMap[o[config.id]];
}
if (o[config.childrenList]) {
for (let c of o[config.childrenList]) {
adaptToChildrenList(c);
}
}
}
return tree;
};
/** 查询菜单下拉树结构 */
function getMenuTreeselect() {
listMenu().then((response) => {
menuOptions.value = handleTree(response, "id");
});
}
// 选中子节点,默认选中父节点
const checkeTree = (data) => {
let thisNode = treeRef.value.getNode(data.id); // 获取当前节点
const keys = treeRef.value.getCheckedKeys(); // 获取已勾选节点的key值
if (thisNode.checked) {
// 当前节点若被选中
for (let i = thisNode.level; i > 1; i--) {
// 判断是否有父级节点
if (!thisNode.parent.checked) {
// 父级节点未被选中则将父节点替换成当前节点往上继续查询并将此节点key存入keys数组
thisNode = thisNode.parent;
keys.push(thisNode.data.id);
}
}
}
treeRef.value.setCheckedKeys(keys); // 将所有keys数组的节点全选中
};
const treeRef = ref(null);
//属性结构配置
const defaultProps = {
children: "sysMenuList",
label: "menuName"
};
watch(
() => props.info.subTableName,
(val) => {
setSubTableColumns(val);
}
);
getMenuTreeselect();
</script>

View File

@ -0,0 +1,118 @@
<template>
<!-- 导入表 -->
<el-dialog title="导入表" v-model="visible" width="800px" top="5vh" append-to-body>
<el-form :model="queryParams" ref="queryRef" :inline="true">
<el-form-item label="表名称" prop="tableName">
<el-input
v-model="queryParams.tableName"
placeholder="请输入表名称"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="表描述" prop="tableComment">
<el-input
v-model="queryParams.tableComment"
placeholder="请输入表描述"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row>
<el-table @row-click="clickRow" ref="table" :data="dbTableList" @selection-change="handleSelectionChange" height="260px">
<el-table-column type="selection" width="55"></el-table-column>
<el-table-column prop="tableName" label="表名称" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="tableComment" label="表描述" :show-overflow-tooltip="true"></el-table-column>
<el-table-column prop="createTime" label="创建时间"></el-table-column>
<el-table-column prop="updateTime" label="更新时间"></el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</el-row>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="handleImportTable"> </el-button>
<el-button @click="visible = false"> </el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { listDbTable, importTable } from "@/api/tool/gen";
const total = ref(0);
const visible = ref(false);
const tables = ref([]);
const dbTableList = ref([]);
const { proxy } = getCurrentInstance();
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
tableName: undefined,
tableComment: undefined
});
const emit = defineEmits(["ok"]);
/** 查询参数列表 */
function show() {
getList();
visible.value = true;
}
/** 单击选择行 */
function clickRow(row) {
proxy.$refs.table.toggleRowSelection(row);
}
/** 多选框选中数据 */
function handleSelectionChange(selection) {
tables.value = selection.map(item => item.tableName);
}
/** 查询表数据 */
function getList() {
listDbTable(queryParams).then(res => {
dbTableList.value = res.rows;
total.value = res.total;
});
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.pageNum = 1;
getList();
}
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef");
handleQuery();
}
/** 导入按钮操作 */
function handleImportTable() {
const tableNames = tables.value.join(",");
if (tableNames == "") {
proxy.$modal.msgError("请选择要导入的表");
return;
}
importTable({ tables: tableNames }).then(res => {
proxy.$modal.msgSuccess(res.msg);
if (res.code === 200) {
visible.value = false;
emit("ok");
}
});
}
defineExpose({
show
});
</script>

View File

@ -0,0 +1,426 @@
<template>
<div>
<div class="titleBox">
<div class="title">代码生成</div>
<div class="btnBox">
<el-button icon="Download" @click="handleGenTable">生成</el-button>
<el-button icon="Upload" @click="openImportTable">导入</el-button>
<el-button icon="Edit" :disabled="single" @click="handleEditTable"
>修改</el-button
>
<el-button
type="danger"
icon="Delete"
:disabled="multiple"
@click="handleDelete"
>删除</el-button
>
</div>
</div>
<div class="searchBox" ref="searchBox">
<el-form
:model="queryParams"
ref="queryRef"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="表名称" prop="tableName">
<el-input
v-model="queryParams.tableName"
placeholder="请输入表名称"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="表描述" prop="tableComment">
<el-input
v-model="queryParams.tableComment"
placeholder="请输入表描述"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker
v-model="dateRange"
value-format="YYYY-MM-DD"
type="daterange"
unlink-panels
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery">查询</el-button>
<el-button @click="resetQuery()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<!-- <el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Download" @click="handleGenTable"
>生成</el-button
>
</el-col>
<el-col :span="1.5">
<el-button type="info" plain icon="Upload" @click="openImportTable"
>导入</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleEditTable"
>修改</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
>删除</el-button
>
</el-col>
<right-toolbar
v-model:showSearch="showSearch"
@queryTable="getList"
></right-toolbar>
</el-row> -->
<div class="tabBox">
<el-table
border
:data="tableList"
@selection-change="handleSelectionChange"
:height="tableHeight"
>
<el-table-column
type="selection"
align="center"
width="55"
></el-table-column>
<el-table-column label="序号" type="index" width="60" align="center">
<template #default="scope">
<span>{{
(queryParams.pageNum - 1) * queryParams.pageSize +
scope.$index +
1
}}</span>
</template>
</el-table-column>
<el-table-column
sortable
label="表名称"
align="center"
prop="tableName"
:show-overflow-tooltip="true"
/>
<el-table-column
sortable
label="表描述"
align="center"
prop="tableComment"
:show-overflow-tooltip="true"
/>
<el-table-column
sortable
label="实体"
align="center"
prop="className"
:show-overflow-tooltip="true"
/>
<el-table-column
sortable
label="创建时间"
align="center"
prop="createTime"
width="160"
/>
<el-table-column
sortable
label="更新时间"
align="center"
prop="updateTime"
width="160"
/>
<el-table-column
label="操作"
align="center"
width="330"
class-name="small-padding fixed-width"
>
<template #default="scope">
<el-tooltip content="预览" placement="top">
<el-button
type="text"
icon="View"
@click="handlePreview(scope.row)"
></el-button>
</el-tooltip>
<el-tooltip content="编辑" placement="top">
<el-button
type="text"
icon="Edit"
@click="handleEditTable(scope.row)"
></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button
type="text"
icon="Delete"
@click="handleDelete(scope.row)"
></el-button>
</el-tooltip>
<el-tooltip content="同步" placement="top">
<el-button
type="text"
icon="Refresh"
@click="handleSynchDb(scope.row)"
></el-button>
</el-tooltip>
<el-tooltip content="生成代码" placement="top">
<el-button
type="text"
icon="Download"
@click="handleGenTable(scope.row)"
></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</div>
</div>
<!-- 预览界面 -->
<el-dialog
:title="preview.title"
v-model="preview.open"
width="80%"
top="5vh"
append-to-body
custom-class="scrollbar"
>
<el-tabs v-model="preview.activeName">
<el-tab-pane
v-for="(value, key) in preview.data"
:label="key.substring(key.lastIndexOf('/') + 1, key.indexOf('.vm'))"
:name="key.substring(key.lastIndexOf('/') + 1, key.indexOf('.vm'))"
:key="key"
>
<pre>{{ value }}</pre>
</el-tab-pane>
</el-tabs>
</el-dialog>
<!-- <import-table ref="importRef" @ok="handleQuery" /> -->
</div>
</template>
<script setup name="Gen">
import {
ref,
toRefs,
reactive,
onActivated,
watch,
nextTick,
getCurrentInstance,
onMounted
} from "vue";
import {
listTable,
previewTable,
delTable,
genCode,
synchDb
} from "@/api/tool/gen";
// import importTable from "./importTable";
import { useRoute, useRouter } from "vue-router";
const searchBox = ref(null); // 搜索盒子
const tableHeight = ref(); // 表格高度
const router = useRouter();
const route = useRoute();
const { proxy } = getCurrentInstance();
const editTableDialogVisible = ref(false);
const tableList = ref([]);
const loading = ref(false);
const showSearch = ref(true);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const tableNames = ref([]);
const dateRange = ref([]);
const uniqueId = ref("");
const data = reactive({
queryParams: {
pageNum: 1,
pageSize: 10,
tableName: undefined,
tableComment: undefined
},
preview: {
open: false,
title: "代码预览",
data: {},
activeName: "domain.java"
}
});
const { queryParams, preview } = toRefs(data);
onActivated(() => {
const time = route.query.t;
if (time != null && time != uniqueId.value) {
uniqueId.value = time;
queryParams.value.pageNum = Number(route.query.pageNum);
dateRange.value = [];
proxy.resetForm("queryForm");
getList();
}
});
const addDateRange = (params, dateRange, propName) => {
let search = params;
search.params =
typeof search.params === "object" &&
search.params !== null &&
!Array.isArray(search.params)
? search.params
: {};
dateRange = Array.isArray(dateRange) ? dateRange : [];
if (typeof propName === "undefined") {
search.params.beginTime = dateRange[0];
search.params.endTime = dateRange[1];
} else {
search.params["begin" + propName] = dateRange[0];
search.params["end" + propName] = dateRange[1];
}
return search;
};
/** 查询表集合 */
function getList() {
let params = addDateRange(queryParams.value, dateRange.value);
loading.value = true;
listTable(params).then((response) => {
tableList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
/** 生成代码操作 */
function handleGenTable(row) {
const tbNames = row.tableName || tableNames.value;
if (tbNames == "") {
proxy.$modal.msgError("请选择要生成的数据");
return;
}
if (row.genType === "1") {
genCode(row.tableName).then((response) => {
proxy.$modal.msgSuccess("成功生成到自定义路径:" + row.genPath);
});
} else {
proxy.$modal.msgError(
"下载功能 需要沟通一下,后端直接生成 给一个下载地址?"
);
// proxy.$download.zip("/tool/gen/batchGenCode?tables=" + tbNames, "zhiyu");
}
}
/** 同步数据库操作 */
function handleSynchDb(row) {
const tableName = row.tableName;
proxy.$modal
.confirm('确认要强制同步"' + tableName + '"表结构吗?')
.then(function () {
return synchDb(tableName);
})
.then(() => {
proxy.$modal.msgSuccess("同步成功");
})
.catch(() => {});
}
/** 打开导入表弹窗 */
function openImportTable() {
proxy.$refs.importRef.show();
}
/** 重置按钮操作 */
function resetQuery() {
dateRange.value = [];
proxy.resetForm("queryRef");
handleQuery();
}
/** 预览按钮 */
function handlePreview(row) {
previewTable(row.tableId).then((response) => {
preview.value.data = response;
preview.value.open = true;
preview.value.activeName = "domain.java";
});
}
// 多选框选中数据
function handleSelectionChange(selection) {
ids.value = selection.map((item) => item.tableId);
tableNames.value = selection.map((item) => item.tableName);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
/** 修改按钮操作 */
function handleEditTable(row) {
const tableId = row.tableId || ids.value[0];
router.push({
path: "/tool/gen-edit/index/" + tableId,
query: { pageNum: queryParams.value.pageNum }
});
}
/** 删除按钮操作 */
function handleDelete(row) {
const tableIds = row.tableId || ids.value;
proxy.$modal
.confirm('是否确认删除表编号为"' + tableIds + '"的数据项?')
.then(function () {
return delTable(tableIds);
})
.then(() => {
getList();
proxy.$modal.msgSuccess("删除成功");
})
.catch(() => {});
}
getList();
// 表格高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 240;
};
onMounted(() => {
tabHeightFn();
window.onresize = function () {
tabHeightFn();
};
});
</script>
<style lang="scss" scoped>
@import "@/assets/css/element-plus.scss";
@import "@/assets/css/layout.scss";
</style>

View File

@ -0,0 +1,421 @@
<template>
<div>
<div class="titleBox">
<div class="title">岗位列表</div>
<div class="btnBox">
<el-button type="primary" @click="addJob()">
<el-icon><CirclePlus /></el-icon>
<span>新增</span>
</el-button>
</div>
</div>
<div class="searchBox" ref="searchBox">
<el-form :model="listQuery" :inline="true">
<el-form-item label="岗位名称">
<el-input
placeholder="请输入岗位名称"
v-model="listQuery.positionName"
clearable
></el-input>
</el-form-item>
<el-form-item label="岗位编码">
<el-input
placeholder="请输入岗位编码"
v-model="listQuery.positionCode"
clearable
></el-input>
</el-form-item>
<el-form-item>
<el-button @click="handleFilter"> 查询 </el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="tabBox">
<el-table
:data="tableData"
border
:height="tableHeight"
style="width: 100%"
:key="keyCount"
>
<el-table-column
sortable
prop="postCode"
show-overflow-tooltip
label="岗位编码"
>
</el-table-column>
<el-table-column
sortable
prop="postName"
show-overflow-tooltip
label="岗位名称"
>
</el-table-column>
<el-table-column sortable label="状态" width="80px">
<template #default="{ row }">
<div>
<el-tag size="small" type="success" v-if="row.xtZxbz === 0"
>正常</el-tag
>
<el-tag size="small" type="danger" v-else-if="row.xtZxbz === 1"
>注销</el-tag
>
<el-tag size="small" type="info" v-else>未知</el-tag>
</div>
</template>
</el-table-column>
<el-table-column
sortable
prop="postDesc"
label="岗位描述"
show-overflow-tooltip
>
</el-table-column>
<el-table-column sortable prop="bz" label="备注" show-overflow-tooltip>
</el-table-column>
<el-table-column sortable prop="xtZhxgsj" label="修改时间" width="180">
<template #default="{ row }">
{{ $filters.dateFilter(row.xtZhxgsj) }}
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="160">
<template #default="{ row }">
<el-button @click="updateJob(row)" size="small">修改</el-button>
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要删除?"
@confirm="delRole(row)"
>
<template #reference>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.page"
:page-sizes="[ 10, 20 , 30 , 50]"
:page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</div>
</div>
<div v-if="dialogFormVisible" class="dialog">
<div class="head_box">
<span class="title">{{ isEdit ? "修改" : "新增" }}</span>
<div>
<!-- 修改 -->
<el-button
v-if="isEdit"
type="primary"
size="small"
@click="onSave"
:loading="buttonLoading"
>保存</el-button
>
<!-- 新增 -->
<el-button
v-else
type="primary"
size="small"
@click="onAdd"
:loading="buttonLoading"
>保存</el-button
>
<el-button size="small" @click="closeDialog">关闭</el-button>
</div>
</div>
<el-form
ref="elform"
class="mosty-from-wrap"
:rules="rules"
:inline="true"
label-position="top"
:model="dialogForm"
>
<el-form-item
class="one"
prop="postName"
label="岗位名称"
label-width="140px"
>
<el-input
v-model="dialogForm.postName"
autocomplete="off"
show-word-limit
maxlength="30"
></el-input>
</el-form-item>
<el-form-item
class="one"
prop="postCode"
label="岗位编码"
label-width="140px"
>
<el-input
v-model="dialogForm.postCode"
autocomplete="off"
show-word-limit
maxlength="30"
></el-input>
</el-form-item>
<el-form-item class="one" prop="xtZxbz" label="状态">
<el-select
style="width: 100%"
v-model="dialogForm.xtZxbz"
placeholder="请选择业务类别"
>
<el-option label="正常" :value="0"></el-option>
<el-option label="注销" :value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item class="one" label="岗位描述" label-width="140px">
<el-input
v-model="dialogForm.postDesc"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
show-word-limit
maxlength="200"
></el-input>
</el-form-item>
<el-form-item class="one" label="备注" label-width="140px">
<el-input
v-model="dialogForm.bz"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
show-word-limit
maxlength="200"
></el-input>
</el-form-item>
</el-form>
</div>
<!-- <el-dialog
draggable
custom-class="way"
v-model="dialogFormVisible"
@closed="closeDialog"
:title="isEdit ? '修改' : '新增'"
>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button
type="primary"
v-if="isEdit"
:loading="buttonLoading"
@click="onSave"
>保存</el-button
>
<el-button
type="primary"
v-else
:loading="buttonLoading"
@click="onAdd"
>新增</el-button
>
</span>
</template>
</el-dialog> -->
</div>
</template>
<script setup>
import { ElMessage } from "element-plus";
import { ref, reactive, onMounted,onUnmounted,getCurrentInstance } from "vue";
import {
selectJobPage,
updateSysPosition,
deleteSysPosition,
addSysPosition
} from "@/api/user-manage";
const { proxy } = getCurrentInstance();
const searchBox = ref(null); // 搜索盒子
const keyCount = ref(0); //tabel组件刷新值
const tableHeight = ref(); // 表格高度
//查询参数
const total = ref(0);
const page = ref(1);
const size = ref(20);
const buttonLoading = ref(false);
const currentRow = ref({});
const listQuery = ref({
page: 1,
size: 10,
positionName: "",
positionCode: ""
});
const elform = ref(null);
//验证
const rules = ref({
postName: [{ required: true, message: "请输入岗位名称", trigger: "change" }],
postCode: [{ required: true, message: "请输入岗位编码", trigger: "change" }]
});
const isEdit = ref(true);
const dialogForm = ref({});
const reset = () => {
listQuery.value = {
page: 1,
size: 10,
positionName: "",
positionCode: ""
};
getListData();
};
// 数据相关
const tableData = ref([]);
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
// 获取数据的方法
const getListData = async () => {
const params = listQuery.value;
params.current = params.page;
params.current = params.page;
const res = await selectJobPage(params);
tableData.value = res?.records;
total.value = Number(res.total);
};
const handleFilter = () => {
listQuery.value.page = 1;
getListData();
};
getListData();
// 分页相关
/**
* size 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.size = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.page = currentPage;
getListData();
};
/**修改字典 */
const updateJob = (row) => {
isEdit.value = true;
dialogForm.value = { ...row };
dialogFormVisible.value = true;
};
const addJob = (row) => {
isEdit.value = false;
dialogForm.value = {};
dialogFormVisible.value = true;
};
const onSave = () => {
elform.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
buttonLoading.value = true;
updateSysPosition({
...dialogForm.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("修改成功");
buttonLoading.value = false;
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
});
};
const onAdd = () => {
elform.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
buttonLoading.value = true;
addSysPosition({
...dialogForm.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("新增成功");
buttonLoading.value = false;
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
});
};
const delRole = (row) => {
deleteSysPosition({
id: Number(row.id)
}).then((res) => {
ElMessage.success("删除成功");
handleFilter();
});
};
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
};
// 高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 240;
};
onMounted(() => {
tabHeightFn();
window.onresize = function () {
tabHeightFn();
};
proxy.mittBus.on("mittFn", (data) => {
keyCount.value = data;
});
});
onUnmounted(() => {
proxy.mittBus.off("mittFn");
});
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
.user-manage-container {
.table-header-wrap {
margin-bottom: 22px;
}
::v-deep .avatar {
width: 60px;
height: 60px;
border-radius: 50%;
}
::v-deep .el-tag {
margin-right: 6px;
}
.pagination {
margin-top: 20px;
}
}
</style>

View File

@ -0,0 +1,14 @@
<template>
1111
<router-view></router-view>
</template>
<script>
export default {
}
</script>
<style>
</style>

View File

@ -0,0 +1,387 @@
<template>
<div>
<div class="titleBox">
<div class="title">登录日志</div>
<div class="btnBox">
<el-button style="margin-left: 10px" type="info" @click="exportExcel">
导出
</el-button>
</div>
</div>
<div class="searchBox" ref="searchBox">
<el-form :model="listQuery" :inline="true">
<el-form-item label="登录账号">
<el-input
placeholder="请输入登录账号"
v-model="listQuery.userName"
clearable
></el-input>
</el-form-item>
<!-- <el-form-item label="操作人员">
<el-input placeholder="请输入操作人员" v-model="listQuery.userName" clearable></el-input>
</el-form-item> -->
<el-form-item label="状态">
<el-select
clearable
v-model="listQuery.status"
placeholder="请选择状态"
>
<el-option label="正常" value="0"></el-option>
<el-option label="异常" value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="success" @click="handleFilter">查询</el-button>
<el-button type="success" @click="reset">重置</el-button>
</el-form-item>
</el-form>
</div>
<div class="tabBox">
<el-table
:data="tableData"
border
style="width: 100%"
:height="tableHeight"
:key="keyCount"
>
<el-table-column
sortable
prop="infoId"
label="访问编号"
></el-table-column>
<el-table-column
sortable
prop="browser"
label="浏览器"
></el-table-column>
<el-table-column
sortable
prop="ipaddr"
label="访问地址"
></el-table-column>
<el-table-column sortable prop="msg" label="操作信息"></el-table-column>
<el-table-column sortable prop="os" label="操作系统"></el-table-column>
<el-table-column
sortable
prop="userName"
label="登录账号"
></el-table-column>
<!-- <el-table-column prop="msg" label="操作信息"></el-table-column> -->
<el-table-column sortable prop="accessTime" label="操作时间">
<template #default="{ row }">
{{ $filters.dateFilter(row.accessTime) }}
</template>
</el-table-column>
<el-table-column sortable label="登录状态" width="110px">
<template #default="{ row }">
<div>
<el-tag size="small" type="success" v-if="row.status == 0"
>正常</el-tag
>
<el-tag size="small" type="danger" v-else-if="row.status == 1"
>异常</el-tag
>
<el-tag size="small" type="info" v-else>未知</el-tag>
</div>
</template>
</el-table-column>
<!-- <el-table-column label="操作" fixed="right" width="120">
<template #default="{ row }">
<el-button type="success" size="small" @click="handleDetail(row)">详情</el-button>
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要删除?"
@confirm="delRow(row)"
>
<template #reference>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column> -->
</el-table>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
</div>
<el-dialog
custom-class="way"
v-model="dialogFormVisible"
@closed="closeDialog"
:title="isEdit ? '修改' : '新增'"
>
<el-form :model="dialogForm">
<el-form-item label="部门名称" label-width="140px">
<el-input v-model="dialogForm.orgName"></el-input>
</el-form-item>
<el-form-item label="部门全称" label-width="140px">
<el-input v-model="dialogForm.orgQc"></el-input>
</el-form-item>
<el-form-item label="部门简称" label-width="140px">
<el-input v-model="dialogForm.orgJc"></el-input>
</el-form-item>
<el-form-item label="部门类型" label-width="140px">
<el-input v-model="dialogForm.orgType"></el-input>
</el-form-item>
<el-form-item label="部门代码" label-width="140px">
<el-input v-model="dialogForm.orgCode"></el-input>
</el-form-item>
<el-form-item label="部门等级" label-width="140px">
<el-input-number
v-model="dialogForm.orgLevel"
class="mx-4"
:min="1"
:max="100"
controls-position="right"
/>
</el-form-item>
<el-form-item label="部门顺序号" label-width="140px">
<el-input-number
v-model="dialogForm.orgNo"
class="mx-4"
:min="1"
:max="100"
controls-position="right"
/>
</el-form-item>
<el-form-item label="部门电话" label-width="140px">
<el-input v-model="dialogForm.linkTel"></el-input>
</el-form-item>
<el-form-item label="部门业务类型" label-width="140px">
<el-input v-model="dialogForm.orgBizType"></el-input>
</el-form-item>
<el-form-item label="部门联系人电话" label-width="140px">
<el-input v-model="dialogForm.linkManTel"></el-input>
</el-form-item>
<el-form-item label="部门联系人" label-width="140px">
<el-input v-model="dialogForm.linkMan"></el-input>
</el-form-item>
<el-form-item label="部门邮箱" label-width="140px">
<el-input v-model="dialogForm.email"></el-input>
</el-form-item>
<el-form-item label="部门名称拼音" label-width="140px">
<el-input v-model="dialogForm.bmpyszm"></el-input>
</el-form-item>
<el-form-item label="部门地址" label-width="140px">
<el-input v-model="dialogForm.address"></el-input>
</el-form-item>
<el-form-item label="部门主页" label-width="140px">
<el-input v-model="dialogForm.webUrl"></el-input>
</el-form-item>
<el-form-item label="部门所属行政区划" label-width="140px">
<el-input v-model="dialogForm.xzqh"></el-input>
</el-form-item>
<!-- <el-form-item label="状态" label-width="140px">
<el-select v-model="dialogForm.zdywlb" placeholder="请选择业务类别">
<el-option label="正常" value="0"></el-option>
<el-option label="注销" value="1"></el-option>
</el-select>
</el-form-item>-->
<el-form-item label="备注" label-width="140px">
<el-input
readonly
v-model="dialogForm.bz"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" v-if="isEdit" @click="onSave"
>保存</el-button
>
<el-button type="primary" v-else @click="onAdd">新增</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { download } from "@/utils/request";
import { ElMessage } from "element-plus";
import { ref, reactive, onMounted,onUnmounted,getCurrentInstance } from "vue";
import {
getSysLoginLogList,
sysLogRemove,
LoginlogClean,
sysLoginogDetail
} from "@/api/user-manage";
const { proxy } = getCurrentInstance();
const searchBox = ref(null); // 搜索盒子
const tableHeight = ref(); // 表格高度
const keyCount = ref(0); //tabel组件刷新值
//查询参数
const total = ref(0);
const page = ref(1);
const size = ref(20);
const currentRow = ref({});
const listQuery = ref({
page: 1,
size: 20
});
const isEdit = ref(true);
const dialogForm = ref({});
// 数据相关
const tableData = ref([]);
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
// 获取数据的方法
const getListData = async () => {
const params = listQuery.value;
params.current = params.page;
const res = await getSysLoginLogList(params);
tableData.value = res?.records;
total.value = Number(res.total);
};
const handleFilter = () => {
listQuery.value.page = 1;
getListData();
};
getListData();
// 分页相关
/**
* size 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.size = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.page = currentPage;
getListData();
};
/**修改字典 */
const updateDict = (row) => {
isEdit.value = true;
dialogForm.value = { ...row };
dialogFormVisible.value = true;
};
const handleDetail = (row) => {
dialogForm.value = { ...row };
dialogFormVisible.value = true;
};
const addRole = (row) => {
isEdit.value = false;
dialogForm.value = {};
dialogFormVisible.value = true;
};
const onSave = () => {
updateSysRole({
...dialogForm.value
}).then((res) => {
dialogFormVisible.value = false;
ElMessage.success("修改成功");
handleFilter();
});
};
// 导出
function exportExcel() {
proxy.$confirm(`当前数据${total.value}条,确定是否导出全部数据?`, "警告", {type: "warning"}).then(() => {
download('/mosty-base/other/exportLoginLog',listQuery.value , `人员核查日志_${new Date().getTime()}.xlsx`)
}).catch(() => {
proxy.$message.info("已取消");
});
}
const onAdd = () => {
addSysRole({
...dialogForm.value
}).then((res) => {
dialogFormVisible.value = false;
ElMessage.success("新增成功");
handleFilter();
});
};
const clearAll = async () => {
const res = await LoginlogClean();
ElMessage.success("删除成功");
handleFilter();
};
const delRow = (row) => {
sysLogRemove({
ids: [row.infoId]
}).then((res) => {
ElMessage.success("删除成功");
handleFilter();
});
};
function reset() {
listQuery.value = {};
listQuery.value.page = 1;
listQuery.value.size = 20;
getListData();
}
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
};
// 表格高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 240;
};
onMounted(() => {
tabHeightFn();
window.onresize = function () {
tabHeightFn();
};
proxy.mittBus.on("mittFn", (data) => {
keyCount.value = data;
});
});
onUnmounted(() => {
proxy.mittBus.off("mittFn");
});
</script>
<style lang="scss" scoped>
@import "@/assets/css/element-plus.scss";
.user-manage-container {
.table-header-wrap {
margin-bottom: 22px;
}
::v-deep .avatar {
width: 60px;
height: 60px;
border-radius: 50%;
}
::v-deep .el-tag {
margin-right: 6px;
}
.pagination {
margin-top: 20px;
}
}
</style>

View File

@ -0,0 +1,451 @@
<template>
<div>
<div class="titleBox">
<div class="title">操作日志</div>
<div class="btnBox">
<el-button style="margin-left: 10px" type="info" @click="exportExcel">
导出
</el-button>
</div>
</div>
<div class="searchBox" ref="searchBox">
<el-form :model="listQuery" :inline="true">
<el-form-item label="系统模块">
<el-input
placeholder="请输入系统模块"
v-model="listQuery.title"
clearable
></el-input>
</el-form-item>
<el-form-item label="操作人员">
<el-input
placeholder="请输入操作人员"
v-model="listQuery.operName"
clearable
></el-input>
</el-form-item>
<el-form-item label="类型">
<el-select
clearable
v-model="listQuery.businessType"
placeholder="请选择类型"
>
<el-option
v-for="item in businessTypeArr"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="状态">
<el-select
clearable
v-model="listQuery.status"
placeholder="请选择状态"
>
<el-option label="正常" value="0"></el-option>
<el-option label="异常" value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="success" @click="handleFilter">查询</el-button>
<el-button type="success" @click="reset">重置</el-button>
</el-form-item>
</el-form>
</div>
<div class="tabBox">
<el-table
:data="tableData"
border
style="width: 100%"
:height="tableHeight"
:key="keyCount"
>
<el-table-column
sortable
prop="operId"
label="日志编号"
></el-table-column>
<el-table-column
sortable
prop="title"
label="系统模块"
></el-table-column>
<el-table-column sortable label="操作类型" width="120px">
<template #default="{ row }">
<div>
{{
businessTypeArr.find((item) => item.value == row.businessType)
.label || "未知"
}}
</div>
</template>
</el-table-column>
<el-table-column
sortable
prop="requestMethod"
label="请求方式"
></el-table-column>
<el-table-column
sortable
prop="operName"
label="操作人员"
></el-table-column>
<el-table-column
sortable
prop="operIp"
label="操作地址"
></el-table-column>
<el-table-column sortable label="操作状态" width="120px">
<template #default="{ row }">
<div>
<el-tag size="small" type="success" v-if="row.status == 0"
>正常</el-tag
>
<el-tag size="small" type="danger" v-else-if="row.status == 1"
>异常</el-tag
>
<el-tag size="small" type="info" v-else>未知</el-tag>
</div>
</template>
</el-table-column>
<el-table-column
sortable
prop="operTime"
label="操作时间"
width="200px"
></el-table-column>
<!-- <template #default="{ row }">{{ $filters.dateFilter(row.createTime) }}</template> -->
<el-table-column label="操作" fixed="right" width="100px">
<template #default="{ row }">
<el-button size="small" @click="handleDetail(row)">详情</el-button>
<!-- <el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要删除?"
@confirm="delHandler(row)"
>
<template #reference>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm> -->
</template>
</el-table-column>
</el-table>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
</div>
<div v-if="dialogFormVisible" class="dialog">
<div class="head_box">
<span class="title">{{ isEdit ? "修改" : "新增" }}</span>
<div>
<el-button size="small" @click="closeDialog">关闭</el-button>
</div>
</div>
<el-form :model="dialogForm" class="mosty-from-wrap" :inline="true">
<el-form-item class="one" label="系统模块" label-width="140px">{{
dialogForm.title
}}</el-form-item>
<el-form-item class="one" label="请求方式" label-width="140px">{{
dialogForm.requestMethod
}}</el-form-item>
<el-form-item class="one" label="操作人员" label-width="140px">{{
dialogForm.operName
}}</el-form-item>
<el-form-item class="one" label="使用方法" label-width="140px">{{
dialogForm.method
}}</el-form-item>
<el-form-item class="one" label="jsonResult" label-width="140px">
{{ dialogForm.jsonResult }}
</el-form-item>
<el-form-item label="操作地址" label-width="140px">
{{ dialogForm.operIp }}
</el-form-item>
<el-form-item class="one" label="操作状态" label-width="140px">
{{ dialogForm.statu == 0 ? "正常" : "注销" }}
</el-form-item>
<el-form-item class="one" label="操作时间" label-width="140px">{{
$filters.dateFilter(dialogForm.createTime)
}}</el-form-item>
</el-form>
</div>
<!-- <el-dialog
draggable
custom-class="way"
v-model="dialogFormVisible"
@closed="closeDialog"
title="详情"
>
<el-form :model="dialogForm">
<el-form-item label="系统模块" label-width="140px">{{
dialogForm.title
}}</el-form-item>
<el-form-item label="请求方式" label-width="140px">{{
dialogForm.requestMethod
}}</el-form-item>
<el-form-item label="操作人员" label-width="140px">{{
dialogForm.operName
}}</el-form-item>
<el-form-item label="使用方法" label-width="140px">{{
dialogForm.method
}}</el-form-item>
<el-form-item label="jsonResult" label-width="140px">
<el-input
readonly
v-model="dialogForm.jsonResult"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
></el-input>
</el-form-item>
<el-form-item label="操作地址" label-width="140px">
{{ dialogForm.operIp }}
</el-form-item>
<el-form-item label="操作状态" label-width="140px">
<el-select
readonly
v-model="dialogForm.status"
placeholder="请选择状态"
>
<el-option label="正常" :value="0"></el-option>
<el-option label="注销" :value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item label="操作时间" label-width="140px">{{
$filters.dateFilter(dialogForm.createTime)
}}</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogFormVisible = false">关闭</el-button>
</span>
</template>
</el-dialog> -->
</div>
</template>
<script setup>
import { download } from "@/utils/request";
import { ElMessage } from "element-plus";
import { ref, reactive, onMounted,onUnmounted,getCurrentInstance } from "vue";
import {
getOperlogList,
operlogRemove,
operlogClean,
operlogDetail
} from "@/api/user-manage";
const { proxy } = getCurrentInstance();
const searchBox = ref(null); // 搜索盒子
const tableHeight = ref(); // 表格高度
const keyCount = ref(0); //tabel组件刷新值
//查询参数
const total = ref(0);
const page = ref(1);
const size = ref(20);
const currentRow = ref({});
const listQuery = ref({
page: 1,
size: 20
});
const isEdit = ref(true);
const dialogForm = ref({});
const businessTypeArr = ref([
{
value: "0",
label: "其他"
},
{
value: "1",
label: "新增"
},
{
value: "2",
label: "修改"
},
{
value: "3",
label: "删除"
},
{
value: "4",
label: "授权"
},
{
value: "5",
label: "导出"
},
{
value: "6",
label: "导入"
},
{
value: "7",
label: "强退"
},
{
value: "8",
label: "生成代码"
},
{
value: "9",
label: "清空数据"
}
]);
// 数据相关
const tableData = ref([]);
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
// 获取数据的方法
const getListData = async () => {
const params = listQuery.value;
params.current = params.page;
const res = await getOperlogList(params);
tableData.value = res?.records;
total.value = Number(res.total);
// tableData.value = result.list
// total.value = result.total
};
const handleFilter = () => {
listQuery.value.page = 1;
getListData();
};
getListData();
// 分页相关
/**
* size 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.size = currentSize;
getListData();
};
function reset() {
listQuery.value = {};
listQuery.value.page = 1;
listQuery.value.size = 20;
getListData();
}
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.page = currentPage;
getListData();
};
const clearAll = async () => {
const res = await operlogClean();
ElMessage.success("删除成功");
handleFilter();
};
/**修改字典 */
const updateDict = (row) => {
isEdit.value = true;
dialogForm.value = { ...row };
dialogFormVisible.value = true;
};
const handleDetail = (row) => {
dialogForm.value = { ...row };
dialogFormVisible.value = true;
};
const onSave = () => {
updateSysRole({
...dialogForm.value
}).then((res) => {
dialogFormVisible.value = false;
ElMessage.success("修改成功");
handleFilter();
});
};
const onAdd = () => {
addSysRole({
...dialogForm.value
}).then((res) => {
dialogFormVisible.value = false;
ElMessage.success("新增成功");
handleFilter();
});
};
const delHandler = (row) => {
operlogRemove({
ids: [row.operId]
}).then((res) => {
ElMessage.success("删除成功");
handleFilter();
});
};
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
};
// 表格高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 240;
};
// 导出
function exportExcel() {
proxy.$confirm(`当前数据${total.value}条,确定是否导出全部数据?`, "警告", {type: "warning"}).then(() => {
download('/mosty-base/other/exportOperlog',listQuery.value , `人员核查日志_${new Date().getTime()}.xlsx`)
}).catch(() => {
proxy.$message.info("已取消");
});
}
onMounted(() => {
tabHeightFn();
window.onresize = function () {
tabHeightFn();
};
proxy.mittBus.on("mittFn", (data) => {
keyCount.value = data;
});
});
onUnmounted(() => {
proxy.mittBus.off("mittFn");
});
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
.user-manage-container {
.table-header-wrap {
margin-bottom: 22px;
}
::v-deep .avatar {
width: 60px;
height: 60px;
border-radius: 50%;
}
::v-deep .el-tag {
margin-right: 6px;
}
.pagination {
margin-top: 20px;
}
}
</style>

View File

@ -0,0 +1,547 @@
<template>
<div>
<div class="titleBox">
<div class="title">菜单管理</div>
<div class="btnBox">
<el-button type="primary" @click="addItemMenu">
<el-icon><CirclePlus /></el-icon>
<span>新增</span>
</el-button>
</div>
</div>
<div class="searchBox" ref="searchBox">
<el-form :model="listQuery" :inline="true">
<el-form-item label="菜单名称">
<el-input
placeholder="请输入菜单名称"
v-model="listQuery.menuName"
clearable
></el-input>
</el-form-item>
<el-form-item>
<el-button @click="handleFilter"> 查询 </el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="tabBox">
<el-table
v-if="refreshTable"
:data="tableData"
border
v-loading="loading"
ref="dataTreeList"
row-key="id"
:tree-props="{ children: 'sysMenuList', hasChildren: true }"
style="width: 100%"
:height="tableHeight"
:key="keyCount"
>
<el-table-column
sortable
prop="menuName"
show-overflow-tooltip
width="200px"
label="菜单名称"
>
</el-table-column>
<el-table-column
sortable
prop="menuCode"
show-overflow-tooltip
align="center"
width="150px"
label="菜单编码"
>
</el-table-column>
<el-table-column
sortable
prop="orderNo"
label="排序"
width="140px"
></el-table-column>
<el-table-column
sortable
prop="menuUrl"
show-overflow-tooltip
label="菜单地址"
align="center"
width="140px"
>
</el-table-column>
<el-table-column
sortable
prop="menuType"
label="类型"
align="center"
width="140px"
>
<template #default="{ row }">
<el-tag v-if="row.menuType === 1" size="small">菜单组</el-tag>
<el-tag v-else-if="row.menuType === 2" type="success" size="small"
>菜单</el-tag
>
<el-tag v-else-if="row.menuType === 3" type="success" size="small"
>页面</el-tag
>
<el-tag v-else-if="row.menuType === 4" type="success" size="small"
>资源</el-tag
>
<el-tag v-else type="info" size="small">未知</el-tag>
</template>
</el-table-column>
<el-table-column
sortable
prop="showMode"
label="可见"
align="center"
width="140px"
>
<template #default="{ row }">
<el-tag v-if="row.showMode === 1" type="success" size="small"
>展示</el-tag
>
<el-tag v-else-if="row.showMode === 2" type="info" size="small"
>不展示</el-tag
>
<el-tag v-else type="warning">未知</el-tag>
</template>
</el-table-column>
<el-table-column
sortable
prop="bz"
show-overflow-tooltip
label="备注"
></el-table-column>
<el-table-column
sortable
prop="qxbs"
label="权限标识"
show-overflow-tooltip
align="center"
width="140px"
></el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="220">
<template #default="{ row }">
<el-button @click="update(row)" size="small">编辑</el-button>
<el-button @click="addItemMenu(row)" size="small"
>添加下级</el-button
>
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要删除?"
@confirm="delDictItem(row)"
>
<template #reference>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
</div>
<div v-if="dialogFormVisible" class="dialog">
<div class="head_box">
<span class="title">{{ isEdit ? "修改" : "新增" }}</span>
<div>
<!-- 修改 -->
<el-button
v-if="isEdit"
type="primary"
size="small"
@click="onSave"
:loading="buttonLoading"
>保存</el-button
>
<!-- 新增 -->
<el-button
v-else
type="primary"
size="small"
@click="onAdd"
:loading="buttonLoading"
>保存</el-button
>
<el-button size="small" @click="closeDialog">关闭</el-button>
</div>
</div>
<el-form
class="mosty-from-wrap"
:inline="true"
label-position="top"
ref="editRef"
:rules="rules"
:model="dialogForm"
>
<el-form-item
class="one"
label="菜单名称"
prop="menuName"
label-width="140px"
>
<el-input
v-model="dialogForm.menuName"
show-word-limit
maxlength="30"
autocomplete="off"
></el-input>
</el-form-item>
<!-- <el-form-item label="菜单编码" label-width="140px">
<el-input v-model="dialogForm.menuCode" show-word-limit maxlength="50" autocomplete="off"></el-input>
</el-form-item> -->
<el-form-item
class="one"
label="菜单地址"
prop="menuUrl"
label-width="140px"
>
<el-input
v-model="dialogForm.menuUrl"
show-word-limit
maxlength="50"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
class="one"
label="是否展示"
prop="showMode"
label-width="140px"
>
<el-radio-group v-model="dialogForm.showMode">
<el-radio :label="1">展示</el-radio>
<el-radio :label="2">不展示</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
class="one"
label="菜单类型"
prop="menuType"
label-width="140px"
>
<el-radio-group :disabled="isEdit" v-model="dialogForm.menuType">
<el-radio :label="1">菜单组</el-radio>
<el-radio :label="2">菜单</el-radio>
<el-radio :label="3">页面</el-radio>
<el-radio :label="4">资源</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
class="one"
v-if="dialogForm.menuType == 4"
prop="buttonResource"
label="按钮标识"
label-width="140px"
>
<el-input
v-model="dialogForm.buttonResource"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
class="one"
label="菜单编码"
prop="menuCode"
label-width="140px"
>
<el-input
v-model="dialogForm.menuCode"
show-word-limit
maxlength="50"
placeholder="权限标识对应路由name"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
class="one"
label="选择图标"
prop="iconName"
label-width="140px"
>
<ChooseIcon
width="400"
:limit="13"
:isImg="false"
clearable=""
v-model="dialogForm.iconName"
></ChooseIcon>
</el-form-item>
<el-form-item
class="one"
label="排序"
prop="orderNo"
label-width="140px"
>
<el-input-number
v-model="dialogForm.orderNo"
class="mx-4"
:min="1"
:max="100"
controls-position="right"
/>
</el-form-item>
<!-- <el-form-item label="状态" label-width="140px">
<el-select v-model="dialogForm.zdywlb" placeholder="请选择业务类别">
<el-option label="正常" value="0"></el-option>
<el-option label="注销" value="1"></el-option>
</el-select>
</el-form-item>-->
<el-form-item class="one" label="备注" label-width="140px">
<el-input
v-model="dialogForm.bz"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
show-word-limit
maxlength="200"
></el-input>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script setup>
import ChooseIcon from "@/components/MyComponents/ChooseIcon";
import { ElMessage } from "element-plus";
import {
ref,
reactive,
watch,
nextTick,
onMounted,
getCurrentInstance,
onUnmounted
} from "vue";
import {
getSystemMeny,
addSysMenu,
updateSysMenu,
deleteSysMenu
} from "@/api/user-manage";
import { useRouter, useRoute } from "vue-router";
const { proxy } = getCurrentInstance();
const keyCount = ref(0); //tabel组件刷新值
const searchBox = ref(null); // 搜索盒子
const tableHeight = ref(); // 表格高度
const rules = ref({
menuName: [{ required: true, message: "请输入菜单名称 " }],
menuUrl: [{ required: true, message: "请输入菜单地址 " }],
showMode: [{ required: true, message: " 请选择是否展示" }],
menuType: [{ required: true, message: "请选择菜单类型 " }],
buttonResource: [{ required: true, message: "请填写菜单编码" }],
menuCode: [{ required: true, message: "请填写菜单编码 " }],
iconName: [{ required: true, message: " 请选择图标" }],
orderNo: [{ required: true, message: "请填写排序号 " }]
});
const router = useRouter();
const route = useRoute();
//查询参数
const total = ref(0);
const currentRow = ref({});
const listQuery = ref({
dictName: "",
dictCode: "",
xtZxbz: "",
current: 1,
size:20
});
const buttonLoading = ref(false);
const topParentId = ref("");
const id = ref("");
const zdlx = ref();
const refreshTable = ref(true);
const isExpand = ref(false); //展开折叠
const isEdit = ref(true);
const dialogForm = ref({});
// 数据相关
const tableData = ref([]);
const loading = ref(false);
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
// 获取数据的方法
const getListData = async () => {
const params = listQuery.value;
loading.value = true
const res = await getSystemMeny(params);
tableData.value = res?.records;
total.value = Number(res.total);
loading.value = false
};
const editRef = ref(null);
const handleFilter = () => {
listQuery.value.current = 1;
getListData();
};
getListData();
//isExpand 监听 时候展开table
watch(isExpand, (val) => {
refreshTable.value = false;
nextTick(() => {
refreshTable.value = true;
});
});
const reset = () => {
listQuery.value = {
current: 1,
size: 20,
menuName: ""
};
getListData();
};
// 分页相关
/**
* size 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.size = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.current = currentPage;
getListData();
};
/**修改字典 */
const update = (row) => {
isEdit.value = true;
dialogForm.value = { ...row };
dialogFormVisible.value = true;
};
function isNull(data) {
if (!data) return true;
if (JSON.stringify(data) === "{}") return true;
if (JSON.stringify(data) === "[]") return true;
return false;
}
const addItemMenu = (row) => {
id.value = isNull(row) ? topParentId.value : row.id;
isEdit.value = false;
dialogForm.value = {};
dialogFormVisible.value = true;
};
const onSave = () => {
editRef.value.validate((valid) => {
if (valid) {
buttonLoading.value = true;
updateSysMenu({
...dialogForm.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("修改成功");
buttonLoading.value = false;
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
} else {
ElMessage.error("请填写完必填项!");
return false;
}
});
};
const onAdd = () => {
editRef.value.validate((valid) => {
if (valid) {
buttonLoading.value = true;
addSysMenu({
...dialogForm.value,
parentId: id.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("新增成功");
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
} else {
ElMessage.error("请填写完必填项!");
return false;
}
});
};
const delDictItem = (row) => {
deleteSysMenu({
id: Number(row.id)
}).then((res) => {
ElMessage.success("删除成功");
handleFilter();
});
};
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
};
const toGoPage = (row) => {
router.push("/user/role?zdbh=" + row.zdbh);
};
// 表格高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 240;
};
onMounted(() => {
tabHeightFn();
window.onresize = function () {
tabHeightFn();
};
proxy.mittBus.on("mittFn", (data) => {
keyCount.value = data;
});
});
onUnmounted(() => {
proxy.mittBus.off("mittFn");
});
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
.user-manage-container {
.table-header-wrap {
margin-bottom: 22px;
}
::v-deep .avatar {
width: 60px;
height: 60px;
border-radius: 50%;
}
::v-deep .el-tag {
margin-right: 6px;
}
.pagination {
margin-top: 20px;
}
}
::v-deep .el-loading-mask{
background:rgba(0,0,0,.5)
}
</style>

View File

@ -0,0 +1,9 @@
<template>
<div class="">权限列表</div>
</template>
<script setup>
import {} from 'vue'
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,511 @@
<template>
<div>
<div class="titleBox">
<div class="title">公安机关要素</div>
<div class="btnBox">
<el-button type="primary" @click="addItemMenu">
<el-icon><CirclePlus /></el-icon>
<span>新增</span>
</el-button>
</div>
</div>
<div class="searchBox" ref="searchBox">
<el-form :model="listQuery" :inline="true">
<el-form-item label="要素名称">
<el-input
placeholder="请输入要素名称"
v-model="listQuery.gajgmc"
clearable
></el-input>
</el-form-item>
<el-form-item>
<el-button @click="handleFilter"> 查询 </el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="tabBox">
<el-table
v-if="refreshTable"
:data="tableData"
border
row-key="id"
style="width: 100%"
:height="tableHeight"
:key="keyCount"
>
<el-table-column
prop="gajgmc"
show-overflow-tooltip
align="center"
width="200px"
label="要素名称"
>
</el-table-column>
<el-table-column
prop="gajgjc"
align="center"
show-overflow-tooltip
width="200px"
label="要素简称"
/>
<el-table-column
prop="wzBc"
label="位置别称"
align="center"
></el-table-column>
<el-table-column
prop="wzXz"
show-overflow-tooltip
label="位置"
align="center"
>
</el-table-column>
<el-table-column
prop="ysdl"
label="要素大类"
align="center"
width="140px"
>
<template #default="{ row }">
<dict-tag
:options="D_ZDY_YSDL"
:value="row.ysdl"
:tag="false"
></dict-tag>
</template>
</el-table-column>
<el-table-column
prop="yszl"
label="要素中类"
align="center"
width="140px"
>
<template #default="{ row }">
<dict-tag
:options="D_ZDY_YSZL"
:value="row.yszl"
:tag="false"
></dict-tag>
</template>
</el-table-column>
<el-table-column
prop="ysxl"
label="要素小类"
align="center"
width="140px"
>
<template #default="{ row }">
<dict-tag
:options="D_ZDY_YSXL"
:value="row.ysxl"
:tag="false"
></dict-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="220">
<template #default="{ row }">
<el-button @click="update(row)" size="small">编辑</el-button>
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要删除?"
@confirm="delDictItem(row)"
>
<template #reference>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
</div>
<div v-if="dialogFormVisible" class="dialog">
<div class="head_box">
<span class="title">{{ isEdit ? "修改" : "新增" }}</span>
<div>
<!-- 修改 -->
<el-button
v-if="isEdit"
type="primary"
size="small"
@click="onSave"
:loading="buttonLoading"
>保存</el-button
>
<!-- 新增 -->
<el-button
v-else
type="primary"
size="small"
@click="onAdd"
:loading="buttonLoading"
>保存</el-button
>
<el-button size="small" @click="closeDialog">关闭</el-button>
</div>
</div>
<el-form
class="mosty-from-wrap"
:inline="true"
label-position="top"
ref="editRef"
:rules="rules"
:model="dialogForm"
>
<el-form-item label="要素名称" prop="gajgmc" label-width="140px">
<el-input
v-model="dialogForm.gajgmc"
placeholder="请输入要素名称"
></el-input>
</el-form-item>
<el-form-item label="要素简称" prop="gajgjc" label-width="140px">
<el-input
v-model="dialogForm.gajgjc"
placeholder="请输入要素简称"
></el-input>
</el-form-item>
<el-form-item label="关联部门" label-width="140px">
<MOSTY.Department
placeholder="部门"
width="280px"
clearable
multiple
filterable
v-model="dialogForm.glbmDtoList"
/>
</el-form-item>
<el-form-item label="要素小类" prop="ysxl" label-width="140px">
<el-select v-model="dialogForm.ysxl" placeholder="请选择要素小类">
<el-option
v-for="dict in D_ZDY_YSXL"
:key="dict.value + 'ysxl'"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="位置别称" prop="wzBc" label-width="140px">
<el-input
v-model="dialogForm.wzBc"
placeholder="请输入位置别称"
></el-input>
</el-form-item>
<el-form-item label="位置" prop="wzXz" label-width="140px">
<el-input
v-model="dialogForm.wzXz"
placeholder="请输入地址详址"
></el-input>
</el-form-item>
<el-form-item style="width: 48%" prop="jd" label="坐标位置">
<div class="latlng">
<el-input v-model="dialogForm.jd" clearable style="width: 45%" />
<el-input v-model="dialogForm.wd" clearable style="width: 45%" />
<el-button @click="chackLat">选取坐标</el-button>
</div>
</el-form-item>
<el-form-item style="width: 100%">
<div class="map">
<GdMap v-if="dialogFormVisible" />
</div>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script setup>
import GdMap from "@/components/GdMap/index.vue";
import * as rule from "@/utils/rules.js";
import * as MOSTY from "@/components/MyComponents/index";
import ChooseIcon from "@/components/MyComponents/ChooseIcon";
import emitter from "@/utils/eventBus.js";
import { ElMessage } from "element-plus";
import { getAddressApi } from "@/utils/tools.js";
import {
ref,
reactive,
watch,
nextTick,
onMounted,
getCurrentInstance,
onUnmounted
} from "vue";
import {
getPageList,
getYsAdd,
getYsUpdate,
getYsDelete,
getYsInfo
} from "@/api/ysCenter";
import { useRouter, useRoute } from "vue-router";
const { proxy } = getCurrentInstance();
const { D_ZDY_YSDL, D_ZDY_YSZL, D_ZDY_YSXL } = proxy.$dict(
"D_ZDY_YSDL",
"D_ZDY_YSZL",
"D_ZDY_YSXL"
);
const keyCount = ref(0); //tabel组件刷新值
const searchBox = ref(null); // 搜索盒子
const tableHeight = ref(); // 表格高度
const rules = ref({
gajgmc: [{ required: true, message: "请输入要素名称 " }],
gajgjc: [{ required: true, message: "请输入要素简称 " }],
glbmDtoList: [{ required: true, message: " 请选择关联部门" }],
ysxl: [{ required: true, message: "请填写要素小类 " }],
jd: [{ required: true, message: "请选择位置 " }]
});
const router = useRouter();
const route = useRoute();
//查询参数
const total = ref(0);
const currentRow = ref({});
const listQuery = ref({
gajgmc: "",
yszl: "",
jsnr: "",
ysxl:'',
pageNum: 1,
pageSize: 10
});
const buttonLoading = ref(false);
const topParentId = ref("");
const id = ref("");
const zdlx = ref();
const refreshTable = ref(true);
const isEdit = ref(true);
const dialogForm = ref({
ysdl: "001",
yszl: "001001"
});
// 数据相关
const tableData = ref([]);
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
// 获取数据的方法
const getListData = async () => {
const params = listQuery.value;
const res = await getPageList(params);
tableData.value = res?.records;
total.value = Number(res.total);
};
const editRef = ref(null);
const handleFilter = () => {
listQuery.value.pageNum = 1;
getListData();
};
getListData();
//获取经纬度
function chackLat(type) {
emitter.emit("drawShape", {
type: "drawPoint",
flag: "point"
});
dialogForm.value.jd = "";
dialogForm.value.wd = "";
}
const reset = () => {
listQuery.value = {
gajgmc: "",
yszl: "",
jsnr: "",
pageNum: 1,
pageSize: 10
};
getListData();
};
// 分页相关
/**
* size 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.size = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.current = currentPage;
getListData();
};
/**修改字典 */
const update = (row) => {
getYsInfo(row.id).then((res) => {
isEdit.value = true;
dialogForm.value = { ...res };
dialogForm.value.glbmDtoList = res.glbmDtoList.map(
(item) => item.ssbmid * 1
);
dialogFormVisible.value = true;
setTimeout(() => {
emitter.emit("addPointArea", {
coords: [res],
icon: require("@/assets/point/kfd.png"),
flag: "kfd"
});
}, 1000);
});
};
function isNull(data) {
if (!data) return true;
if (JSON.stringify(data) === "{}") return true;
if (JSON.stringify(data) === "[]") return true;
return false;
}
const addItemMenu = (row) => {
id.value = isNull(row) ? topParentId.value : row.id;
isEdit.value = false;
dialogForm.value = {
ysdl: "001",
yszl: "001001"
};
dialogFormVisible.value = true;
};
const onSave = () => {
editRef.value.validate((valid) => {
if (valid) {
buttonLoading.value = true;
const data = { ...dialogForm.value };
data.glbmDtoList = data.glbmDtoList.map((item) => {
return { ssbmid: item };
});
getYsUpdate({
...data
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("修改成功");
buttonLoading.value = false;
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
} else {
ElMessage.error("请填写完必填项!");
return false;
}
});
};
const onAdd = () => {
editRef.value.validate((valid) => {
if (valid) {
buttonLoading.value = true;
const data = { ...dialogForm.value };
data.glbmDtoList = data.glbmDtoList.map((item) => {
return {
ssbmid: item
};
});
getYsAdd({
...data
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("新增成功");
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
} else {
ElMessage.error("请填写完必填项!");
return false;
}
});
};
const delDictItem = (row) => {
getYsDelete(row.id).then((res) => {
ElMessage.success("删除成功");
handleFilter();
});
};
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
};
const toGoPage = (row) => {
router.push("/user/role?zdbh=" + row.zdbh);
};
// 表格高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 240;
};
onMounted(() => {
tabHeightFn();
window.onresize = function () {
tabHeightFn();
};
proxy.mittBus.on("mittFn", (data) => {
keyCount.value = data;
});
emitter.on("coordString", (res) => {
if (res.type === "drawPoint") {
let arr = res.coord.split(",");
dialogForm.value.jd = arr[0];
dialogForm.value.wd = arr[1];
// getAddressApi({ jd: arr[0], wd: arr[1] }, (res) => {
// dialogForm.value.wzXz = res.address;
// });
}
});
});
onUnmounted(() => {
proxy.mittBus.off("mittFn");
emitter.off("coordString");
});
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
.user-manage-container {
.table-header-wrap {
margin-bottom: 22px;
}
::v-deep .avatar {
width: 60px;
height: 60px;
border-radius: 50%;
}
::v-deep .el-tag {
margin-right: 6px;
}
.pagination {
margin-top: 20px;
}
}
.map {
width: 100%;
height: 400px;
position: relative;
}
.latlng {
width: 100%;
display: flex;
justify-content: space-between;
}
</style>

View File

@ -0,0 +1,469 @@
<template>
<div class="user-list-page">
<div class="searchBox" ref="searchBox">
<el-form :model="listQuery" class="mosty-from-wrap" :inline="true">
<el-form-item label="用户名">
<el-input
placeholder="请输入用户名"
v-model="listQuery.userName"
clearable
></el-input>
</el-form-item>
<el-form-item label="电话号码">
<el-input
placeholder="请输入电话号码"
v-model="listQuery.phone"
clearable
></el-input>
</el-form-item>
<el-form-item>
<el-button type="success" @click="handleFilter">查询</el-button>
</el-form-item>
<el-form-item>
<el-button type="info" @click="reset()"> 重置 </el-button>
</el-form-item>
<el-form-item>
<el-button type="danger" @click="unbundleRole()"
>批量取消授权</el-button
>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="addUser()">添加用户</el-button>
</el-form-item>
</el-form>
</div>
<div class="tabBox">
<el-table
ref="multipleTableRef"
@selection-change="handleSelectionChange"
:data="tableData"
border
:height="tableHeight"
:key="keyCount"
style="width: 100%"
>
<el-table-column type="selection" width="55" />
<el-table-column
prop="loginName"
align="center"
label="用户名"
></el-table-column>
<el-table-column
prop="userName"
align="center"
label="用户昵称"
></el-table-column>
<el-table-column
prop="mobile"
width="120px"
label="移动电话"
></el-table-column>
<el-table-column prop="xtZhxgsj" align="center" label="录入时间">
<template #default="{ row }">{{
$filters.dateFilter(row.xtLrsj)
}}</template>
</el-table-column>
<el-table-column label="操作" width="120">
<template #default="{ row }">
<el-popconfirm
confirm-button-text="Yes"
cancel-button-text="No"
icon-color="red"
title="确定要删除?"
@confirm="unbundleRole(row)"
>
<template #reference>
<el-button type="danger" size="small">取消授权</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
</div>
<el-dialog
width="900px"
custom-class="way"
v-model="dialogFormVisible"
@closed="closeDialog"
:title="isEdit ? '修改' : '新增'"
>
<!-- <p>{{ dialogForm }}</p> -->
<el-form
ref="formRef"
:model="dialogForm"
label-width="120px"
class="mosty-from-wrap twoLine"
:rules="rules"
>
<el-form-item label="用户昵称:" prop="">
<MOSTY.Other
width="280px"
placeholder="用户昵称"
clearable
v-model="dialogForm.userName"
/>
</el-form-item>
<el-form-item label="登录账号:" prop="">
<MOSTY.Other
width="280px"
placeholder="登录账号"
clearable
v-model="dialogForm.loginName"
/>
</el-form-item>
<el-form-item label="密码:" prop="">
<MOSTY.Other
width="280px"
placeholder="密码"
show-password
v-model="dialogForm.password"
/>
</el-form-item>
<el-form-item label="身份证号" prop="idEntityCard">
<MOSTY.IdentityCard
width="280px"
v-model="dialogForm.idEntityCard"
clearable
></MOSTY.IdentityCard>
</el-form-item>
<el-form-item label="电话号码:" prop="telePhone">
<MOSTY.Phone
width="280px"
v-model="dialogForm.telePhone"
maxlength="11"
clearable
></MOSTY.Phone>
</el-form-item>
<el-form-item label="移动电话:" prop="mobile">
<MOSTY.Phone
width="280px"
v-model="dialogForm.mobile"
maxlength="11"
clearable
></MOSTY.Phone>
</el-form-item>
<el-form-item label="封装民族:" prop="nation">
<MOSTY.PackageSelect
width="280px"
v-model="dialogForm.nation"
dictEnum="NATION"
clearable
filterable
/>
</el-form-item>
<el-form-item label="性别:" prop="">
<MOSTY.Sex width="220px" v-model:sex="dialogForm.sex" />
</el-form-item>
<el-form-item label="文化程度:" prop="">
<MOSTY.PackageSelect
dictEnum="EDUCATION"
width="280px"
v-model="dialogForm.whcd"
clearable
filterable
/>
</el-form-item>
<el-form-item label="E-mail" prop="email">
<MOSTY.Email
v-model="dialogForm.email"
width="280px"
clearable
></MOSTY.Email>
</el-form-item>
<el-form-item label="出生日期" prop="email">
<el-date-picker
v-model="dialogForm.birthday"
type="date"
placeholder="出生日期"
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="有效期:" prop="">
<el-date-picker
v-model="dialogForm.endTime"
type="datetime"
placeholder="Select date and time"
format="YYYY/MM/DD hh:mm:ss"
value-format="x"
/>
</el-form-item>
<el-form-item label="行业号码:" prop="">
<MOSTY.Other
width="280px"
placeholder="行业号码"
v-model="dialogForm.inDustRialId"
/>
</el-form-item>
<el-form-item label="管理部门名称:" prop="">
<MOSTY.Other
width="280px"
placeholder="管理部门名称"
v-model="dialogForm.managerOrgName"
/>
</el-form-item>
<el-form-item label="管理部门ID:" prop="">
<MOSTY.Department
placeholder="管理部门ID"
width="280px"
clearable
filterable
multiple
v-model="dialogForm.managerOrgId"
/>
</el-form-item>
<el-form-item label="岗位名称:" prop="">
<MOSTY.Other
width="280px"
placeholder="岗位名称"
v-model="dialogForm.positionName"
/>
</el-form-item>
<el-form-item label="岗位ID:" prop="">
<MOSTY.Other
width="280px"
placeholder="岗位ID"
v-model="dialogForm.positionId"
/>
</el-form-item>
<el-form-item label="用户类型:" prop="">
<el-select v-model="dialogForm.userType" placeholder="请选择">
<el-option label="系统用户默认" value="00" />
<el-option label="注册用户" value="01" />
</el-select>
</el-form-item>
<el-form-item label="虚拟用户:" prop="">
<el-select v-model="dialogForm.isVirtualUser" placeholder="请选择">
<el-option label="是" value="1" />
<el-option label="不是" value="2" />
</el-select>
</el-form-item>
<el-form-item label="备注">
<el-input
v-model="dialogForm.bz"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
></el-input>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogFormVisible = false">取消</el-button>
<el-button type="primary" v-if="isEdit" @click="onSave"
>保存</el-button
>
<el-button type="primary" v-else @click="onAdd">新增</el-button>
</span>
</template>
</el-dialog>
<ChooseUser
v-model="chooseUserVisible"
:roleId="route.params.id"
@choosedUsers="saveUsers"
></ChooseUser>
</div>
</template>
<script setup>
import ChooseUser from "@/components/MyComponents/ChooseUser";
import { useRoute } from "vue-router";
import * as rule from "@/utils/rules.js";
import * as MOSTY from "@/components/MyComponents/index";
import { ElMessage } from "element-plus";
import { ref, reactive, computed, watch,onMounted,onUnmounted,getCurrentInstance } from "vue";
import {
selectUnAccreditPage,
batchUnboundUserRole,
getRoleUserList,
grantUserToRole
} from "@/api/user-manage";
const { proxy } = getCurrentInstance();
const route = useRoute();
const searchBox = ref()
const keyCount = ref(0); //tabel组件刷新值
const tableHeight = ref(); // 表格高度
const rules = ref({
...rule.phoneRule({ validator: true }, "mobile"), // 是否必填 是否进行校验
...rule.phoneRule({ validator: true }, "telePhone"), // 是否必填 是否进行校验 如果props与from里面数据不一致可以传第二个参数
...rule.identityCardRule({ validator: true }), //身份证校验
...rule.addressSelectRule({ require: true }), //地址
...rule.emailRule({ validator: true }), //邮箱
packageSelect: [
{
required: true,
message: "请选择",
trigger: "change"
}
],
other: [
{
required: true,
message: "自由发挥哦",
trigger: "blur"
}
]
});
//查询参数
const total = ref(0);
const page = ref(1);
const size = ref(20);
const currentRow = ref({});
const listQuery = ref({
page: 1,
size: 20,
userName: '',
phone: ''
});
const isEdit = ref(true);
const dialogForm = ref({
userName: ""
});
//分配角色
const currentUserId = ref("");
const roleDialogVisible = ref(false);
const multipleTableRef = ref(null);
const multipleSelection = ref([]);
const chooseUserVisible = ref(false);
// 数据相关
const tableData = ref([]);
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
onMounted(() => {
getListData();
tabHeightFn();
proxy.mittBus.on("mittFn", (data) => {
keyCount.value = data;
});
});
onUnmounted(() => {
proxy.mittBus.off("mittFn");
});
// 获取数据的方法
const getListData = async () => {
const params = listQuery.value;
params.current = params.page;
params.roleId = route.params.id;
const res = await getRoleUserList(params);
tableData.value = res?.records;
total.value = Number(res.total);
};
const reset = () => {
listQuery.value = {
page: 1,
size: 5,
userName: "",
phone: ""
};
getListData();
};
const handleFilter = () => {
listQuery.value.page = 1;
getListData();
};
// 分页相关 size 改变触发
const handleSizeChange = (currentSize) => {
listQuery.value.size = currentSize;
getListData();
};
// 页码改变触发
const handleCurrentChange = (currentPage) => {
listQuery.value.page = currentPage;
getListData();
};
const unbundleRole = (row) => {
let params = {
roleId: route.params.id,
ids: []
};
if (row) {
params.ids.push(row.id);
} else {
if (multipleSelection.value.length <= 0) return false;
multipleSelection.value.forEach((item) => {
params.ids.push(item.id);
});
}
batchUnboundUserRole(params).then((res) => {
ElMessage.success("操作成功");
handleFilter();
});
};
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
};
const assignRoles = (row) => {
roleDialogVisible.value = true;
currentUserId.value = row.id;
};
const handleSelectionChange = (val) => {
multipleSelection.value = val;
};
const addUser = () => {
chooseUserVisible.value = true;
};
//批量添加用户
const saveUsers = (users) => {
if (users.length > 0) {
let userIds = users.map((item) => item.id);
let params = {
roleId: route.params.id,
userIds: userIds
};
grantUserToRole(params).then((res) => {
ElMessage.success("修改成功");
handleFilter();
});
}
};
// 高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 200;
window.onresize = function () {
tabHeightFn();
};
};
//watch监听路由变化
watch(roleDialogVisible, (val) => {
if (!val) currentUserId.value = "";
});
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
</style>

View File

@ -0,0 +1,130 @@
<template>
<div>
<el-dialog
title="分配权限"
width="500px"
:model-value="modelValue"
:destroy-on-close="true"
@close="closed"
>
<div class="treeCnt">
<el-tree
ref="treeRef"
:data="allPermission"
:props="defaultProps"
node-key="id"
show-checkbox
default-expand-all
:check-strictly="true"
@check="checkeTree"
>
</el-tree>
</div>
<template #footer>
<div class="dialog-footer">
<el-button @click="closed">取消</el-button>
<el-button type="primary" @click="onComfirm">保存</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ElMessage } from "element-plus";
import { defineProps, watch, ref, onMounted, nextTick } from "vue";
import {
saveRoleMenuInfo,
getRoleMenuIds,
getMenuTree
} from "@/api/user-manage";
const props = defineProps({
modelValue: {
type: Boolean,
required: true
},
roleId: {
type: String,
required: true
}
});
const form = ref({});
const emits = defineEmits(["update:modelValue", "updateRole"]);
const closed = () => {
emits("update:modelValue", false);
};
const onComfirm = () => {
let params = {
roleId: Number(props.roleId),
menuIds: treeRef.value.getCheckedKeys().map((item) => Number(item))
};
saveRoleMenuInfo(params).then((res) => {
ElMessage.success("操作成功");
});
closed();
};
//所有权限
const allPermission = ref([]);
const getPermissionList = async () => {
const res = await getMenuTree();
allPermission.value = res;
};
getPermissionList();
const treeRef = ref(null);
//属性结构配置
const defaultProps = {
children: "sysMenuList",
label: "menuName"
};
//当前角色权限
const getRolePermission = async () => {
const checkedKeys = await getRoleMenuIds(props.roleId);
treeRef.value.setCheckedKeys(checkedKeys);
};
// 选中子节点,默认选中父节点
const checkeTree = (data) => {
let thisNode = treeRef.value.getNode(data.id); // 获取当前节点
const keys = treeRef.value.getCheckedKeys(); // 获取已勾选节点的key值
if (thisNode.checked) {
// 当前节点若被选中
for (let i = thisNode.level; i > 1; i--) {
// 判断是否有父级节点
if (!thisNode.parent.checked) {
// 父级节点未被选中则将父节点替换成当前节点往上继续查询并将此节点key存入keys数组
thisNode = thisNode.parent;
// keys.push(thisNode.data.id);
}
}
}
treeRef.value.setCheckedKeys(keys); // 将所有keys数组的节点全选中
};
watch(
() => props.roleId,
(val) => {
if (val) {
getRolePermission();
}
},
{
immediate: true,
deep: true
}
);
</script>
<style lang="scss" scoped>
::v-deep .el-dialog {
max-height: 80vh;
.treeCnt {
height: 65vh;
overflow: hidden;
overflow-y: auto;
}
}
</style>

View File

@ -0,0 +1,465 @@
<template>
<div>
<div class="titleBox">
<div class="title">角色列表</div>
<div class="btnBox">
<el-button type="primary" @click="addRole()">
<el-icon><CirclePlus /></el-icon>
<span>新增</span>
</el-button>
</div>
</div>
<div class="searchBox" ref="searchBox">
<el-form :model="listQuery" :inline="true">
<el-form-item label="角色名称">
<el-input
placeholder="请输入角色名称"
v-model="listQuery.roleName"
clearable
></el-input>
</el-form-item>
<el-form-item>
<el-button @click="handleFilter"> 查询 </el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="tabBox">
<el-table
:data="tableData"
border
:height="tableHeight"
style="width: 100%"
:key="keyCount"
>
<el-table-column
sortable
prop="orderNo"
label="角色编号"
show-overflow-tooltip
width="120px"
>
</el-table-column>
<el-table-column
sortable
prop="roleName"
label="角色名称"
show-overflow-tooltip
>
</el-table-column>
<el-table-column
sortable
prop="roleCode"
label="角色编码"
show-overflow-tooltip
>
</el-table-column>
<el-table-column sortable label="状态" width="80px">
<template #default="{ row }">
<div>
<el-tag size="small" type="success" v-if="row.xtZxbz === 0"
>正常</el-tag
>
<el-tag size="small" type="danger" v-else-if="row.xtZxbz === 1"
>注销</el-tag
>
<el-tag size="small" type="info" v-else>未知</el-tag>
</div>
</template>
</el-table-column>
<el-table-column
sortable
prop="roleDesc"
label="角色描述"
show-overflow-tooltip
>
</el-table-column>
<el-table-column sortable prop="bz" label="备注" show-overflow-tooltip>
</el-table-column>
<el-table-column sortable prop="xtZhxgsj" label="更新时间">
<template #default="{ row }">
{{ $filters.dateFilter(row.xtZhxgsj) }}
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="320">
<template #default="{ row }">
<el-button @click="updateDict(row)" size="small">修改</el-button>
<el-button @click="allocationUser(row)" size="small"
>管理用户</el-button
>
<el-button @click="privilegesHanlder(row)" size="small"
>菜单权限</el-button
>
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要删除?"
@confirm="delRole(row)"
>
<template #reference>
<!-- v-permission="['removeTest','removeTest2']" -->
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</div>
</div>
<div v-if="dialogFormVisible" class="dialog">
<div class="head_box">
<span class="title">{{ isEdit ? "修改" : "新增" }}</span>
<div>
<!-- 修改 -->
<el-button
v-if="isEdit"
type="primary"
size="small"
@click="onSave"
:loading="buttonLoading"
>保存</el-button
>
<!-- 新增 -->
<el-button
v-else
type="primary"
size="small"
@click="onAdd"
:loading="buttonLoading"
>保存</el-button
>
<el-button size="small" @click="closeDialog">关闭</el-button>
</div>
</div>
<el-form
:rules="rules"
ref="elform"
inline="true"
label-position="top"
:model="dialogForm"
class="mosty-from-wrap"
>
<el-form-item prop="roleName" class="one" label="角色名称">
<el-input
v-model="dialogForm.roleName"
show-word-limit
maxlength="20"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
class="one"
prop="roleCode"
label="角色编码"
label-width="140px"
>
<el-input
v-model="dialogForm.roleCode"
show-word-limit
maxlength="50"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
class="one"
label="角色描述"
prop="roleDesc"
label-width="140px"
>
<el-input
v-model="dialogForm.roleDesc"
show-word-limit
maxlength="50"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
class="one"
label="排序号"
prop="orderNo"
label-width="140px"
>
<el-input-number
v-model="dialogForm.orderNo"
class="mx-4"
:min="1"
:max="100"
controls-position="right"
/>
</el-form-item>
<el-form-item
class="one"
label="权限范围"
prop="dataPermissionLevel"
label-width="140px"
>
<!-- <MOSTY.PackageSelect
width="280px"
v-model="dialogForm.dataPermissionLevel"
dictEnum="D_ZDY_SJQX"
clearable
filterable
/> -->
<el-select
clearable
v-model="dialogForm.dataPermissionLevel"
placeholder="请选择"
>
<el-option
v-for="(dict, index) in D_ZDY_SJQX"
:key="index"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item class="one" label="备注" label-width="140px">
<el-input
v-model="dialogForm.bz"
show-word-limit
maxlength="200"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
></el-input>
</el-form-item>
</el-form>
</div>
<PrivilegesDialog
v-model="privilegesDialogVisible"
:roleId="currentRow.id"
></PrivilegesDialog>
</div>
</template>
<script setup>
import * as rule from "@/utils/rules.js";
import * as MOSTY from "@/components/MyComponents/index";
import PrivilegesDialog from "./conponents/PrivilegesDialog.vue";
import { ElMessage } from "element-plus";
import { ref, onMounted, getCurrentInstance, onUnmounted } from "vue";
const { proxy } = getCurrentInstance();
const { D_ZDY_SJQX } = proxy.$dict("D_ZDY_SJQX");
import {
getRoleList,
addSysRole,
updateSysRole,
deleteSysRole
} from "@/api/user-manage";
import { useRouter } from "vue-router";
const searchBox = ref(null); // 搜索盒子
const keyCount = ref(0); //tabel组件刷新值
const tableHeight = ref(); // 表格高度
//查询参数
const total = ref(0);
const page = ref(1);
const size = ref(20);
const currentRow = ref({});
const listQuery = ref({
page: 1,
size: 20,
dictName: "",
dictCode: "",
xtZxbz: ""
});
const elform = ref(null);
//验证
const rules = ref({
roleName: [{ required: true, message: "请输入角色名称", trigger: "change" }],
roleCode: [{ required: true, message: "请输入角色编码", trigger: "change" }],
roleDesc: [{ required: true, message: "请输入角色描述", trigger: "change" }],
orderNo: [{ required: true, message: "请输入排序号", trigger: "change" }],
dataPermissionLevel: [
{ required: true, message: "请选择权限范围", trigger: "change" }
]
});
const isEdit = ref(true);
const dialogForm = ref({});
const buttonLoading = ref(false);
// 数据相关
const tableData = ref([]);
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
// 获取数据的方法
const getListData = async () => {
const params = listQuery.value;
params.current = params.page;
const res = await getRoleList(params);
tableData.value = res?.records;
total.value = Number(res.total);
};
const handleFilter = () => {
listQuery.value.page = 1;
getListData();
};
getListData();
const reset = () => {
listQuery.value = {
page: 1,
size: 5,
roleName: ""
};
getListData();
};
// 分页相关
/**
* size 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.size = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.page = currentPage;
getListData();
};
/**修改字典 */
const updateDict = (row) => {
isEdit.value = true;
row.dataPermissionLevel = "" + row.dataPermissionLevel;
dialogForm.value = { ...row };
dialogFormVisible.value = true;
};
/**privileges 分配权限 */
const privilegesDialogVisible = ref(false);
const privilegesHanlder = (row) => {
privilegesDialogVisible.value = true;
currentRow.value = { ...row };
};
const addRole = (row) => {
isEdit.value = false;
dialogForm.value = {};
dialogFormVisible.value = true;
};
const onSave = () => {
elform.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
buttonLoading.value = true;
updateSysRole({
...dialogForm.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("修改成功");
buttonLoading.value = false;
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
});
};
const onAdd = () => {
elform.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
buttonLoading.value = true;
addSysRole({
...dialogForm.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("操作成功");
buttonLoading.value = false;
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
});
};
const delRole = (row) => {
buttonLoading.value = true;
deleteSysRole({
id: Number(row.id)
})
.then((res) => {
ElMessage.success("删除成功");
buttonLoading.value = false;
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
};
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
};
//分配用户
const router = useRouter();
const allocationUser = (row) => {
//
router.push(`/user/allocationUser/${row.id}`);
};
// 高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 240;
};
onMounted(() => {
tabHeightFn();
window.onresize = function () {
tabHeightFn();
};
proxy.mittBus.on("mittFn", (data) => {
keyCount.value = data;
});
});
onUnmounted(() => {
proxy.mittBus.off("mittFn");
});
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
.user-manage-container {
.table-header-wrap {
margin-bottom: 22px;
}
::v-deep .avatar {
width: 60px;
height: 60px;
border-radius: 50%;
}
::v-deep .el-tag {
margin-right: 6px;
}
.pagination {
margin-top: 20px;
}
}
</style>

View File

@ -0,0 +1,387 @@
<template>
<div>
<div class="titleBox">
<div class="title">系统配置</div>
<div class="btnBox">
<el-button type="primary" @click="addConfig">
<el-icon><CirclePlus /></el-icon>
<span>新增</span>
</el-button>
</div>
</div>
<div class="searchBox" ref="searchBox">
<el-form :model="listQuery" :inline="true">
<el-form-item label="配置名称">
<el-input
placeholder="请输入配置名称"
v-model="listQuery.configName"
clearable
></el-input>
</el-form-item>
<el-form-item label="配置键">
<el-input
placeholder="请输入配置键"
v-model="listQuery.configKey"
clearable
></el-input>
</el-form-item>
<el-form-item>
<el-button @click="handleFilter"> 查询 </el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="tabBox">
<el-table
:data="tableData"
border
style="width: 100%"
:height="tableHeight"
:key="keyCount"
>
<el-table-column
sortable
prop="pzmc"
show-overflow-tooltip
label="配置名称"
>
</el-table-column>
<el-table-column
sortable
prop="pzj"
show-overflow-tooltip
label="配置键"
>
</el-table-column>
<el-table-column
sortable
prop="pzz"
show-overflow-tooltip
label="配置值"
>
</el-table-column>
<el-table-column
sortable
prop="xtZhxgrxm"
show-overflow-tooltip
label="修改人姓名"
>
</el-table-column>
<el-table-column sortable prop="bz" show-overflow-tooltip label="备注">
</el-table-column>
<el-table-column sortable prop="xtCjsj" label="采集时间">
<template #default="{ row }">
{{ $filters.dateFilter(row.xtCjsj) }}
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="160">
<template #default="{ row }">
<el-button @click="updateDict(row)" size="small">修改</el-button>
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要删除?"
@confirm="delConfig(row)"
>
<template #reference>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</div>
</div>
<div v-if="dialogFormVisible" class="dialog">
<div class="head_box">
<span class="title">{{ isEdit ? "修改" : "新增" }}</span>
<div>
<!-- 修改 -->
<el-button
v-if="isEdit"
type="primary"
size="small"
@click="onSave"
:loading="buttonLoading"
>保存</el-button
>
<!-- 新增 -->
<el-button
v-else
type="primary"
size="small"
@click="onAdd"
:loading="buttonLoading"
>保存</el-button
>
<el-button size="small" @click="closeDialog">关闭</el-button>
</div>
</div>
<el-form
ref="formRef"
class="mosty-from-wrap"
:inline="true"
label-position="top"
:model="dialogForm"
:rules="rules"
>
<el-form-item
class="one"
label="配置名称"
prop="pzmc"
label-width="140px"
>
<el-input
v-model="dialogForm.pzmc"
show-word-limit
maxlength="50"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item class="one" label="配置键" prop="pzj" label-width="140px">
<el-input
v-model="dialogForm.pzj"
show-word-limit
maxlength="50"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
class="one"
label="配置值"
prop="pzz"
required
label-width="140px"
>
<el-input
v-model="dialogForm.pzz"
show-word-limit
maxlength="50"
autocomplete="off"
></el-input>
</el-form-item>
<!-- <el-form-item class="one" prop="xtZxbz" label="状态">
<el-select
style="width: 100%"
v-model="dialogForm.xtZxbz"
placeholder="请选择配置状态"
>
<el-option label="正常" :value="0"></el-option>
<el-option label="注销" :value="1"></el-option>
</el-select>
</el-form-item> -->
<el-form-item class="one" label="备注" label-width="140px">
<el-input
v-model="dialogForm.bz"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
show-word-limit
maxlength="200"
></el-input>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script setup>
import { ElMessage } from "element-plus";
import { ref, reactive, onMounted, onUnmounted, getCurrentInstance } from "vue";
import {
getSysConfigList,
addSysConfig,
updateSysConfig,
deleteSysConfig
} from "@/api/user-manage";
const { proxy } = getCurrentInstance();
const keyCount = ref(0); //tabel组件刷新值
const searchBox = ref(null); // 搜索盒子
const tableHeight = ref(); // 表格高度
const formRef = ref(null);
const rules = ref({
pzmc: [{ required: true, message: "请填写配置名称", trigger: "blur" }],
pzj: [{ required: true, message: "请填写配置键", trigger: "blur" }],
pzz: [{ required: true, message: "请填写配置值", trigger: "blur" }],
xtZxbz: [{ required: true, message: "请选择配置状态", trigger: "blur" }],
});
//查询参数
const total = ref(0);
const page = ref(1);
const size = ref(20);
const currentRow = ref({});
const listQuery = ref({
page: 1,
size: 20,
dictName: "",
dictCode: "",
xtZxbz: ""
});
const isEdit = ref(true);
const dialogForm = ref({});
const buttonLoading = ref(false);
// 数据相关
const tableData = ref([]);
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
// 获取数据的方法
const getListData = async () => {
const params = listQuery.value;
params.current = params.page;
const res = await getSysConfigList(params);
tableData.value = res?.records;
total.value = Number(res.total);
};
const reset = () => {
listQuery.value = {
page: 1,
size: 20,
configName: "",
configKey: ""
};
getListData();
};
const handleFilter = () => {
listQuery.value.page = 1;
getListData();
};
getListData();
// 分页相关
/**
* size 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.size = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.page = currentPage;
getListData();
};
/**修改字典 */
const updateDict = (row) => {
isEdit.value = true;
dialogForm.value = { ...row };
dialogFormVisible.value = true;
};
const addConfig = (row) => {
isEdit.value = false;
dialogForm.value = {};
dialogFormVisible.value = true;
};
const onSave = () => {
formRef.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
buttonLoading.value = true;
updateSysConfig({
...dialogForm.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("修改成功");
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
});
};
const onAdd = () => {
formRef.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
buttonLoading.value = true;
addSysConfig({
...dialogForm.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("新增成功");
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
});
};
const delConfig = (row) => {
deleteSysConfig({
id: Number(row.id)
}).then((res) => {
ElMessage.success("删除成功");
handleFilter();
});
};
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
};
// 表格高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 240;
};
onMounted(() => {
tabHeightFn();
window.onresize = function () {
tabHeightFn();
};
proxy.mittBus.on("mittFn", (data) => {
keyCount.value = data;
});
});
onUnmounted(() => {
proxy.mittBus.off("mittFn");
});
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
.user-manage-container {
.table-header-wrap {
margin-bottom: 22px;
}
::v-deep .avatar {
width: 60px;
height: 60px;
border-radius: 50%;
}
::v-deep .el-tag {
margin-right: 6px;
}
.pagination {
margin-top: 20px;
}
}
</style>

View File

@ -0,0 +1,399 @@
<template>
<div>
<div class="titleBox">
<div class="title">系统版本管理</div>
<div class="btnBox">
<el-button type="primary" @click="addVersion">
<el-icon><CirclePlus /></el-icon>
<span>新增</span>
</el-button>
</div>
</div>
<div class="searchBox" ref="searchBox">
<el-form :model="listQuery" :inline="true">
<el-form-item label="版本号">
<el-input
placeholder="请输入版本"
v-model="listQuery.sysVersion"
clearable
></el-input>
</el-form-item>
<el-form-item label="发布时间">
<el-date-picker
v-model="listQuery.startPublishTime"
type="datetime"
placeholder="选择发布时间"
format="YYYY/MM/DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
<el-form-item label>
<el-date-picker
v-model="listQuery.endPublishTime"
type="datetime"
placeholder="结束时间"
format="YYYY/MM/DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleFilter">查询</el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="tabBox">
<el-table
:data="tableData"
border
style="width: 100%"
:height="tableHeight"
:key="keyCount"
>
<el-table-column
sortable
prop="sysVersion"
label="版本"
show-overflow-tooltip
></el-table-column>
<el-table-column
sortable
prop="addFunction"
label="新增功能"
show-overflow-tooltip
></el-table-column>
<el-table-column
sortable
prop="fixBug"
label="修复bug"
show-overflow-tooltip
></el-table-column>
<el-table-column sortable prop="xtCjsj" label="发布时间" width="160">
<template #default="{ row }">{{
$filters.dateFilter(row.xtCjsj)
}}</template>
</el-table-column>
<el-table-column
sortable
prop="bz"
label="备注"
show-overflow-tooltip
></el-table-column>
<el-table-column label="操作" fixed="right" width="260">
<template #default="{ row }">
<el-button @click="updateVersion(row)" size="small">修改</el-button>
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要删除?"
@confirm="delVersion(row)"
>
<template #reference>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
</div>
<div v-if="dialogFormVisible" class="dialog">
<div class="head_box">
<span class="title">{{ isEdit ? "修改" : "新增" }}</span>
<div>
<!-- 修改 -->
<el-button
v-if="isEdit"
type="primary"
size="small"
@click="onSave"
:loading="buttonLoading"
>保存</el-button
>
<!-- 新增 -->
<el-button
v-else
type="primary"
size="small"
@click="onAdd"
:loading="buttonLoading"
>保存</el-button
>
<el-button size="small" @click="closeDialog">关闭</el-button>
</div>
</div>
<el-form
class="mosty-from-wrap"
:inline="true"
label-position="top"
:model="dialogForm"
ref="elform"
>
<el-form-item
prop="sysVersion"
class="one"
label="版本"
:rules="[{ required: true, message: '请填写版本号' }]"
label-width="140px"
>
<el-input
v-model="dialogForm.sysVersion"
show-word-limit
maxlength="50"
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
class="one"
prop="addFunction"
label="新增功能"
:rules="[{ required: true, message: '请填写新增功能描述' }]"
label-width="140px"
>
<el-input
v-model="dialogForm.addFunction"
show-word-limit
maxlength="200"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
></el-input>
</el-form-item>
<el-form-item
class="one"
prop="fixBug"
label="修复bug"
:rules="[{ required: true, message: '请填写修复bug' }]"
label-width="140px"
>
<el-input
v-model="dialogForm.fixBug"
show-word-limit
maxlength="200"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
></el-input>
</el-form-item>
<el-form-item
class="one"
prop="publishTime"
label="发布时间"
:rules="[{ required: true, message: '请选择发布时间' }]"
label-width="140px"
>
<el-date-picker
v-model="dialogForm.publishTime"
type="datetime"
placeholder="选择时间"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
/>
</el-form-item>
<el-form-item class="one" label="备注" label-width="140px">
<el-input
v-model="dialogForm.bz"
:autosize="{ minRows: 2, maxRows: 4 }"
show-word-limit
maxlength="200"
type="textarea"
></el-input>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script setup>
import { ElMessage } from "element-plus";
import { ref, reactive, onMounted,onUnmounted,getCurrentInstance } from "vue";
import {
getSysVersionList,
updateVersionManage,
deleteVersionManage,
addVersionManage
} from "@/api/user-manage";
const { proxy } = getCurrentInstance();
const keyCount = ref(0); //tabel组件刷新值
const searchBox = ref(null); // 搜索盒子
const tableHeight = ref(); // 表格高度
//查询参数
const total = ref(0);
const elform = ref(null);
const page = ref(1);
const size = ref(20);
const currentRow = ref({});
const listQuery = ref({
page: 1,
size: 20,
dictName: "",
dictCode: "",
xtZxbz: ""
});
const isEdit = ref(true);
const dialogForm = ref({});
const buttonLoading = ref(false);
// 数据相关
const tableData = ref([]);
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
// 获取数据的方法
const getListData = async () => {
const params = listQuery.value;
params.current = params.page;
const res = await getSysVersionList(params);
tableData.value = res?.records;
total.value = Number(res.total);
};
const handleFilter = () => {
listQuery.value.page = 1;
getListData();
};
getListData();
// 分页相关
/**
* size 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.size = currentSize;
getListData();
};
const reset = () => {
listQuery.value = {
page: 1,
size: 20,
sysVersion: "",
startPublishTime: "",
endPublishTime: ""
};
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.page = currentPage;
getListData();
};
const updateVersion = (row) => {
isEdit.value = true;
dialogForm.value = { ...row };
dialogFormVisible.value = true;
};
const addVersion = (row) => {
isEdit.value = false;
dialogForm.value = {};
dialogFormVisible.value = true;
};
const onSave = () => {
elform.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
buttonLoading.value = true;
updateVersionManage({
...dialogForm.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("修改成功");
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
});
};
const onAdd = () => {
elform.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
buttonLoading.value = true;
addVersionManage({
...dialogForm.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("新增成功");
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
});
};
const delVersion = (row) => {
deleteVersionManage({
id: Number(row.id)
}).then((res) => {
ElMessage.success("删除成功");
handleFilter();
});
};
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
};
// 表格高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 240;
};
onMounted(() => {
tabHeightFn();
window.onresize = function () {
tabHeightFn();
};
proxy.mittBus.on("mittFn", (data) => {
keyCount.value = data;
});
});
onUnmounted(() => {
proxy.mittBus.off("mittFn");
});
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
.user-manage-container {
.table-header-wrap {
margin-bottom: 22px;
}
::v-deep .avatar {
width: 60px;
height: 60px;
border-radius: 50%;
}
::v-deep .el-tag {
margin-right: 6px;
}
.pagination {
margin-top: 20px;
}
}
</style>

View File

@ -0,0 +1,740 @@
<template>
<div>
<div class="titleBox">
<div class="title">系统分析模型</div>
<div class="btnBox">
<el-button type="primary" @click="addJob()">
<el-icon><CirclePlus /></el-icon>
<span>新增</span>
</el-button>
</div>
</div>
<div class="searchBox" ref="searchBox">
<el-form :model="listQuery" :inline="true">
<el-form-item label="模型名称">
<el-input
placeholder="请输入模型名称"
v-model="listQuery.mxmc"
clearable
></el-input>
</el-form-item>
<el-form-item>
<el-button @click="handleFilter"> 查询 </el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="tabBox">
<el-table
:data="tableData"
border
:height="tableHeight"
style="width: 100%"
:key="keyCount"
>
<el-table-column
sortable
prop="id"
show-overflow-tooltip
label="模型编号"
>
</el-table-column>
<el-table-column
sortable
prop="mxmc"
show-overflow-tooltip
label="模型名称"
>
</el-table-column>
<el-table-column
sortable
prop="mxsm"
show-overflow-tooltip
label="模型说明"
>
</el-table-column>
<el-table-column
sortable
prop="yxcs"
show-overflow-tooltip
label="运行次数"
>
</el-table-column>
<el-table-column
sortable
prop="yjCs"
show-overflow-tooltip
label="预警次数"
>
</el-table-column>
<el-table-column sortable label="模型状态" width="100px">
<template #default="{ row }">
<div>
<el-tag size="small" type="success" v-if="row.mxzt == '01'"
>运行中</el-tag
>
<el-tag size="small" type="danger" v-else-if="row.mxzt == '02'"
>已停止</el-tag
>
</div>
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="280">
<template #default="{ row }">
<template v-if="row.mxzt == '01'">
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要停止?"
@confirm="startModel(row)"
>
<template #reference>
<el-button size="small">停止</el-button>
</template>
</el-popconfirm>
</template>
<template v-else>
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要启动?"
@confirm="stopModel(row)"
>
<template #reference>
<el-button size="small">启动</el-button>
</template>
</el-popconfirm>
</template>
<el-button @click="csSet(row)" size="small">参数设置</el-button>
<el-button @click="updateJob(row)" size="small">修改</el-button>
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要删除?"
@confirm="delRole(row)"
>
<template #reference>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.page"
:page-sizes="[10, 20, 30, 50]"
:page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</div>
</div>
<div v-if="dialogFormVisible" class="dialog">
<div class="head_box">
<span class="title">{{ isEdit ? "修改" : "新增" }}</span>
<div>
<!-- 修改 -->
<el-button
v-if="isEdit"
type="primary"
size="small"
@click="onSave"
:loading="buttonLoading"
>保存</el-button
>
<!-- 新增 -->
<el-button
v-else
type="primary"
size="small"
@click="onAdd"
:loading="buttonLoading"
>保存</el-button
>
<el-button size="small" @click="closeDialog">关闭</el-button>
</div>
</div>
<el-form
ref="elform"
class="mosty-from-wrap"
:rules="rules"
:inline="true"
label-position="top"
:model="dialogForm"
>
<el-form-item
class="one"
prop="id"
label="模型编号"
label-width="140px"
>
<el-input
v-model="dialogForm.id"
placeholder="请输入模型编号"
></el-input>
</el-form-item>
<el-form-item
class="one"
prop="ssbmid"
label="所属辖区"
label-width="140px"
>
<MOSTY.Department
placeholder="请选择所属辖区"
width="100%"
clearable
filterable
v-model="dialogForm.ssbmid"
/>
</el-form-item>
<el-form-item
class="one"
prop="mxmc"
label="模型名称"
label-width="140px"
>
<el-input
v-model="dialogForm.mxmc"
placeholder="请输入模型名称"
></el-input>
</el-form-item>
<el-form-item class="one" prop="mxlx" label="模型类型">
<el-select
style="width: 100%"
v-model="dialogForm.mxlx"
placeholder="请选择模型类型"
>
<el-option label="街面违法犯罪预警" :value="'01'"></el-option>
<el-option label="重点巡防区域预警" :value="'02'"></el-option>
</el-select>
</el-form-item>
<el-form-item
class="one"
prop="mxsm"
label="模型说明"
label-width="140px"
>
<el-input
v-model="dialogForm.mxsm"
autocomplete="off"
show-word-limit
maxlength="3000"
></el-input>
</el-form-item>
</el-form>
</div>
<!-- 模型参数 -->
<div v-if="dialogCSSZTableVisible" class="dialog">
<div class="head_box">
<span class="title">参数设置</span>
<div>
<el-button size="small" @click="dialogCSSZTableVisible = false"
>关闭</el-button
>
</div>
</div>
<div class="mxcs_table">
<div class="csmxadd">
<el-button type="primary" @click="addCsModel()">
<el-icon><CirclePlus /></el-icon>
<span>新增</span>
</el-button>
</div>
<el-table
:data="tableCSData"
border
:height="tableHeight"
style="width: 100%"
:key="keyCount"
>
<el-table-column
sortable
prop="cslx"
show-overflow-toolt
label="参数类型"
>
<template #default="{ row }">
<span>{{row.cslx == '01' ? '时间(分)':row.cslx == '02' ? '次数':row.cslx == '03' ? '人数':'距离(米)'}}</span>
</template>
</el-table-column>
<el-table-column
sortable
prop="csmc"
show-overflow-tooltip
label="参数名"
>
</el-table-column>
<el-table-column
sortable
prop="csz"
show-overflow-tooltip
label="参数值"
>
</el-table-column>
<el-table-column
sortable
prop="csdm"
show-overflow-tooltip
label="参数代码"
>
</el-table-column>
<el-table-column label="操作" fixed="right" width="140">
<template #default="{ row }">
<el-button @click="updateCs(row)" size="small">修改</el-button>
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要删除?"
@confirm="deleteCs(row)"
>
<template #reference>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChangecs"
@current-change="handleCurrentChangecs"
:current-page="csform.pageCurrent"
:page-sizes="[10, 20, 30, 50]"
:page-size="csform.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="cstotal"
>
</el-pagination>
</div>
</div>
</div>
<!-- 模型参数新增 修改 -->
<div v-if="dialogcsFormVisible" class="dialog">
<div class="head_box">
<span class="title">{{ iscsEdit ? "修改" : "新增" }}</span>
<div>
<!-- 修改 -->
<el-button
v-if="iscsEdit"
type="primary"
size="small"
@click="updateCsModel"
:loading="buttonLoading"
>保存</el-button
>
<!-- 新增 -->
<el-button
v-else
type="primary"
size="small"
@click="saveCs"
:loading="buttonLoading"
>保存</el-button
>
<el-button size="small" @click="dialogcsFormVisible = false"
>关闭</el-button
>
</div>
</div>
<el-form
ref="elcsform"
class="mosty-from-wrap"
:rules="rules"
:inline="true"
label-position="top"
:model="csform"
>
<el-form-item
class="one"
prop="csmc"
label="参数名称"
label-width="140px"
>
<el-input
v-model="csform.csmc"
placeholder="请输入参数名称"
></el-input>
</el-form-item>
<el-form-item class="one" prop="csz" label="参数值" label-width="140px">
<el-input v-model="csform.csz" placeholder="请输入参数值"></el-input>
</el-form-item>
<el-form-item class="one" prop="csdm" label="参数代码" label-width="140px">
<el-input v-model="csform.csdm" placeholder="请输入参数代码"></el-input>
</el-form-item>
<el-form-item class="one" prop="cslx" label="参数类型">
<el-select
style="width: 100%"
v-model="csform.cslx"
placeholder="请选择参数类型"
>
<el-option
v-for="item in cslxList"
:key="item.value"
:value="item.value"
:label="item.label"
/>
</el-select>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script setup>
import * as rule from "@/utils/rules.js";
import * as MOSTY from "@/components/MyComponents/index";
import { ElMessage } from "element-plus";
import { ref, reactive, onMounted, onUnmounted, getCurrentInstance } from "vue";
import {
getYJModelList,
addYJmodel,
putYJmodel,
delYJModel,
getCsList,
addCs,
putCs,
delCs,
getCsDTQZ
} from "@/api/basicsmanage/yjmodel";
const { proxy } = getCurrentInstance();
const searchBox = ref(null); // 搜索盒子
const keyCount = ref(0); //tabel组件刷新值
const tableHeight = ref(); // 表格高度
//查询参数
const total = ref(0);
const page = ref(1);
const size = ref(20);
const buttonLoading = ref(false);
const currentRow = ref({});
const listQuery = ref({
pageCurrent: 1,
pageSize: 10,
mxmc: ""
});
const elform = ref(null);
const elcsform = ref(null);
//验证
const rules = ref({
ssbmid: [{ required: true, message: "请选择所属辖区", trigger: "change" }],
mxmc: [{ required: true, message: "请输入模型名称", trigger: "change" }],
mxlx: [{ required: true, message: "请选择模型类型", trigger: "change" }],
mxsm: [{ required: true, message: "请输入模型说明", trigger: "change" }],
csmc: [{ required: true, message: "请输入参数名称", trigger: "change" }],
csz: [{ required: true, message: "请输入参数值", trigger: "change" }],
cslx: [{ required: true, message: "请选择参数类型", trigger: "change" }],
id: [{ required: true, message: "请输入模型编号", trigger: "change" }],
csdm: [{required: true, message: "请输入参数代码", trigger: "change"}]
});
// 参数类型
const cslxList = ref([
{
label: "时间(分)",
value: "01"
},
{
label: "次数",
value: "02"
},
{
label: "人数",
value: "03"
},
{
label: "距离(米)",
value: "04"
}
]);
// 参数设置
const csform = ref({});
const csparams = ref({
pageSize: 10,
pageCurrent: 1,
mxid: ""
});
const cstotal = ref(0);
const iscsEdit = ref(false);
const tableCSData = ref([]);
const dialogCSSZTableVisible = ref(false);
const dialogcsFormVisible = ref(false);
function csSet(row) {
csparams.value.mxid = row.id;
dialogCSSZTableVisible.value = true;
searchCs();
}
// 参数查询
function searchCs() {
getCsList(csparams.value).then((res) => {
tableCSData.value = res.records;
cstotal.value = res.total;
});
}
// 参数新增
function addCsModel() {
iscsEdit.value = false;
dialogcsFormVisible.value = true;
csform.value = {
csmc: "",
csz: "",
cslx: ""
};
csform.value.mxid = csparams.value.mxid;
}
function saveCs() {
elcsform.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
addCs(csform.value).then((res) => {
ElMessage.success("新增成功");
csparams.value.pageCurrent = 1;
searchCs();
dialogcsFormVisible.value = false;
});
});
}
// 参数删除
function deleteCs(row) {
delCs(row.id).then((res) => {
csparams.value.pageCurrent = 1;
searchCs();
});
}
// 参数修改
function updateCs(row) {
iscsEdit.value = true;
dialogcsFormVisible.value = true;
csform.value = row;
}
function updateCsModel() {
elcsform.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
putCs(csform.value).then((res) => {
ElMessage.success("修改成功");
csparams.value.pageCurrent = 1;
searchCs();
dialogcsFormVisible.value = false;
});
});
}
// 参数分页相关
/**
* size 改变触发
*/
const handleSizeChangecs = (currentSize) => {
csform.value.pageSize = currentSize;
searchCs();
};
/**
* 页码改变触发
*/
const handleCurrentChangecs = (currentPage) => {
csform.value.pageCurrent = currentPage;
searchCs();
};
// 启动
function startModel(row) {
getCsDTQZ(row.id).then((res) => {
ElMessage.success("启动成功");
handleFilter();
});
}
// 停止
function stopModel(row) {
getCsDTQZ(row.id).then((res) => {
ElMessage.success("停止成功");
handleFilter();
});
}
const isEdit = ref(true);
const dialogForm = ref({});
const reset = () => {
listQuery.value = {
pageCurrent: 1,
pageSize: 10,
mxmc: ""
};
getListData();
};
// 数据相关
const tableData = ref([]);
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
// 获取数据的方法
const getListData = async () => {
const res = await getYJModelList(listQuery.value);
tableData.value = res?.records;
total.value = Number(res.total);
};
const handleFilter = () => {
listQuery.value.pageCurrent = 1;
getListData();
};
getListData();
// 分页相关
/**
* size 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.pageSize = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.pageCurrent = currentPage;
getListData();
};
/**修改字典 */
const updateJob = (row) => {
isEdit.value = true;
dialogForm.value = { ...row };
dialogForm.value.ssbmid = dialogForm.value.ssbmid * 1;
dialogFormVisible.value = true;
};
const addJob = (row) => {
isEdit.value = false;
dialogForm.value = {};
dialogFormVisible.value = true;
};
const onSave = () => {
elform.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
buttonLoading.value = true;
dialogForm.value.ssbmdm = dialogForm.value.ssbmid;
putYJmodel({
...dialogForm.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("修改成功");
buttonLoading.value = false;
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
});
};
const onAdd = () => {
elform.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
buttonLoading.value = true;
dialogForm.value.ssbmdm = dialogForm.value.ssbmid;
addYJmodel({
...dialogForm.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("新增成功");
buttonLoading.value = false;
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
});
};
const delRole = (row) => {
delYJModel(row.id).then((res) => {
ElMessage.success("删除成功");
handleFilter();
});
};
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
};
// 高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 240;
};
onMounted(() => {
tabHeightFn();
window.onresize = function () {
tabHeightFn();
};
proxy.mittBus.on("mittFn", (data) => {
keyCount.value = data;
});
});
onUnmounted(() => {
proxy.mittBus.off("mittFn");
});
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
.user-manage-container {
.table-header-wrap {
margin-bottom: 22px;
}
::v-deep .avatar {
width: 60px;
height: 60px;
border-radius: 50%;
}
::v-deep .el-tag {
margin-right: 6px;
}
.pagination {
margin-top: 20px;
}
}
.cslb_text {
// font-size: 20px;
color: rgb(7, 142, 231);
padding: 10px;
}
.canshu_box {
width: 94%;
display: flex;
justify-content: space-between;
}
.csmxadd {
display: flex;
justify-content: flex-end;
margin: 10px;
}
.mxcs_table {
margin: 10px;
}
</style>

View File

@ -0,0 +1,349 @@
<template>
<div>
<div class="btnBoxss">
<div class="title">系统使用情况</div>
<div class="btnBox">
<el-radio-group v-model="tabPos" @change="getTab">
<el-radio-button label="1">今日</el-radio-button>
<el-radio-button label="2">近7日</el-radio-button>
<el-radio-button label="3">近30日</el-radio-button>
<el-radio-button label="4">近90日</el-radio-button>
</el-radio-group>
</div>
</div>
<div class="chart_box">
<div class="chart_item left_item">
<div class="sy_pep">使用次数</div>
<div class="cen_box">
<pie :data="sbLxData" />
</div>
</div>
<div class="chart_item right_item">
<div class="sy_pep">使用人数</div>
<div class="cen_box">
<div class="content">
<div class="stat_box">
<div>人数</div>
<div class="num-text">{{ peopleNum }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="tablebox" ref="tableList">
<div class="stitle ranktitle">
排行榜
<div class="rankText">
<el-radio-group v-model="radioList" @change="checkActive">
<el-radio :label="1">人员</el-radio>
<el-radio :label="2">部门</el-radio>
<el-radio :label="3">模块</el-radio>
</el-radio-group>
</div>
</div>
<div class="table-List">
<div class="table-header">
<span class="table-item">排名</span>
<span class="table-item">使用成功数</span>
<span class="table-item">使用失败数</span>
<span class="table-item">总数</span>
<span class="table-item" v-if="radioList === 1">人员</span>
<span class="table-item">{{
radioList === 3 ? "模块名称" : "部门名称"
}}</span>
</div>
<div
class="table-body"
:class="index % 2 === 0 ? 'bg' : ''"
v-for="(item, index) in tableData"
:key="index"
>
<div class="table-item">
<img
v-if="index === 0"
:src="require('@/assets/images/gold.png')"
alt=""
width="20"
height="25"
/>
<img
v-else-if="index === 1"
:src="require('@/assets/images/silver.png')"
alt=""
width="20"
height="25"
/>
<img
v-else-if="index === 2"
:src="require('@/assets/images/copper.png')"
alt=""
width="20"
height="25"
/>
<span v-else>{{ index + 1 }}</span>
</div>
<span class="table-item">{{ active ? item.pass : item.aa }}</span>
<span class="table-item">{{ active ? item.noPass : item.a }}</span>
<span class="table-item">{{ active ? item.count : item.a }}</span>
<span class="table-item" v-if="radioList === 1">{{
item.oper_name
}}</span>
<span class="table-item" v-if="radioList != 3">{{ item.ssbm }}</span>
<span class="table-item" v-if="radioList === 3">
<dict-tag :options="D_BZ_FWMC" :value="item.mkmc" :tag="false" />
</span>
</div>
</div>
</div>
</div>
</template>
<script setup>
import pie from "./pie.vue";
import * as rule from "@/utils/rules.js";
import * as MOSTY from "@/components/MyComponents/index";
import ChooseIcon from "@/components/MyComponents/ChooseIcon";
import emitter from "@/utils/eventBus.js";
import { ElMessage } from "element-plus";
import {
ref,
reactive,
watch,
nextTick,
onMounted,
getCurrentInstance,
onUnmounted
} from "vue";
import { useRouter, useRoute } from "vue-router";
const { proxy } = getCurrentInstance();
import {
ryStatistics,
bmStatistics,
mkStatistics,
useStatistics
} from "@/api/sys.js";
const { D_BZ_FWMC } = proxy.$dict("D_BZ_FWMC");
const router = useRouter();
const route = useRoute();
const active = ref(true);
const tabPos = ref("1");
const params = ref({
type: "1"
});
function getTab(val) {
params.value.type = val;
getTableData();
getpie();
}
const tableData = ref([]); //表格数据
function getTableData() {
if (radioList.value === 1) {
ryStatistics(params.value).then((res) => {
tableData.value = res;
});
} else if (radioList.value === 2) {
bmStatistics(params.value).then((res) => {
tableData.value = res;
});
} else if (radioList.value === 3) {
mkStatistics(params.value).then((res) => {
tableData.value = res;
});
}
}
const radioList = ref(1);
function checkActive(val) {
getTableData();
}
const sbLxData = ref([
{
name: "成功次数",
value: 0
},
{
name: "失败次数",
value: 0
}
]);
const peopleNum = ref(0);
function getpie() {
useStatistics(params.value).then((res) => {
peopleNum.value = res.fwrs;
sbLxData.value[0].value = res.qqcgcs;
sbLxData.value[1].value = res.qqsbcs;
});
}
// 表格高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 240;
};
onMounted(() => {
getTableData();
getpie();
});
onUnmounted(() => {});
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
.user-manage-container {
.table-header-wrap {
margin-bottom: 22px;
}
::v-deep .avatar {
width: 60px;
height: 60px;
border-radius: 50%;
}
::v-deep .el-tag {
margin-right: 6px;
}
.pagination {
margin-top: 20px;
}
}
.map {
width: 100%;
height: 400px;
position: relative;
}
.latlng {
width: 100%;
display: flex;
justify-content: space-between;
}
.btnBoxss {
height: 60px;
display: flex;
justify-content: space-between;
position: relative;
z-index: 2;
.title {
height: 60px;
line-height: 60px;
font-size: 18px;
color: #fff;
}
.btnBox {
margin-top: 14px;
}
}
.chart_box {
display: flex;
justify-content: center;
align-items: center;
.chart_item {
flex: 1;
height: 300px;
border: 1px solid #07539a;
padding: 10px;
}
.left_item {
margin-right: 10px;
}
.right_item {
margin-left: 10px;
}
.cen_box {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
.tablebox {
margin-top: 15px;
border: 1px solid #07539a;
height: 54vh;
padding: 10px;
.ranktitle {
display: flex;
justify-content: space-between;
.rankText {
color: #2892ff;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
.rankText:hover {
color: rgb(59, 162, 231);
}
}
.table-List {
margin-top: 10px;
}
}
.table-List {
.table-header {
display: flex;
justify-content: space-between;
align-items: center;
border: 1px solid #54c5ff;
background-color: #004485;
padding: 10px 10px;
}
.table-body {
display: flex;
// justify-content: space-between;
align-items: center;
padding: 9px 10px;
}
.table-item {
flex: 1;
text-align: center;
}
.table-item-dep {
flex: 2;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.bg {
background-color: #002f5b;
}
}
.content {
height: 76.5px;
display: flex;
flex-wrap: nowrap;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
width: 160px;
:last-child {
margin-right: 0vw;
}
}
.stat_box {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border: 1px solid rgba(76, 166, 251, 0.8);
border-radius: 2px;
margin-right: 1vw;
padding: 13px 0;
.num-text {
font-size: 20px;
font-weight: bold;
margin-top: 10px;
background: linear-gradient(to bottom right, #36e5ff, #1092ff);
-webkit-background-clip: text;
color: transparent;
}
}
.sy_pep {
font-size: 18px;
font-weight: bold;
}
</style>

View File

@ -0,0 +1,115 @@
<template>
<div>
<div id="circlecz" style="width: 500px; height: 260px"></div>
</div>
</template>
<script setup>
import * as echarts from "echarts";
import { ref, onMounted, watch, defineProps } from "vue";
const props = defineProps({
data: { type: Array }
});
watch(
() => props.data,
() => {
lineChartFn();
},
{
deep:true
}
);
function lineChartFn() {
var chartDom = document.getElementById("circlecz");
var myChart = echarts.init(chartDom, "dark");
var option;
var scale = 1;
// var echartData = props.data.map((item) => {
// return {
// value: item.value,
// name: item.name
// };
// });
var rich = {
yellow: {
color: "#ffc72b",
fontSize: 14 * scale,
padding: [5, 4],
align: "center"
},
total: {
color: "#ffc72b",
fontSize: 14 * scale,
align: "center"
},
white: {
color: "#fff",
align: "center",
fontSize: 14 * scale,
padding: [0, 0]
},
blue: {
color: "#49dff0",
fontSize: 14 * scale,
align: "center"
}
};
option = {
backgroundColor: "rgba(0,0,0,0)",
// title:{
// show:true,
// text: '使用次数'
// },
legend: {
orient: "vertical",
right: 0,
top: 5
},
series: [
{
name: "使用次数",
type: "pie",
radius: ["32%", "50%"],
hoverAnimation: false,
color: [
"#c487ee",
"#deb140",
"#49dff0",
"#034079",
"#6f81da",
"#00ffb4"
],
label: {
normal: {
formatter: function (params, ticket, callback) {
return (
"{white|" +
params.name +
"}\n{yellow|" +
params.value +
"}\n{blue|" +
params.percent +
"%}"
);
},
rich: rich
}
},
data: props.data
}
]
};
option && myChart.setOption(option);
window.onresize = function () {
myChart.resize();
};
document.getElementById("circlecz").setAttribute("_echarts_instance_", "");
}
onMounted(() => {
lineChartFn();
});
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,127 @@
<template>
<el-dialog title="配置角色" :model-value="modelValue" @close="closed">
<!-- <el-checkbox-group v-model="userRoleTitleList">
<el-checkbox v-for="item in allRoleList" :key="item.id" :label="item.roleName" />
</el-checkbox-group>-->
<el-table max-height="380px" ref="multipleTableRef" :data="allRoleList" style="width: 100%"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" />
<el-table-column property="orderNo" label="角色编号" />
<el-table-column property="roleName" label="角色名称" />
<el-table-column prop="xtZhxgsj" label="更新时间">
<template #default="{ row }">{{ $filters.dateFilter(row.xtZhxgsj) }}</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer">
<el-button @click="closed">取消</el-button>
<el-button type="primary" :loading="buttonLoading" @click="onComfirm">保存</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup>
import { ElMessage } from "element-plus";
import { defineProps, watch, ref, onMounted, nextTick } from "vue";
import {
getRoleList,
getUserRoleList,
grantRoleToUser
} from "@/api/user-manage";
const props = defineProps({
modelValue: {
type: Boolean,
required: true
},
userId: {
type: String,
required: true
}
});
const buttonLoading = ref(false)
const emits = defineEmits(["update:modelValue", "updateRole"]);
const closed = () => {
emits("update:modelValue", false);
};
const multipleTableRef = ref(null)
const multipleSelection = ref([]);
const handleSelectionChange = (val) => {
multipleSelection.value = val;
};
// 为用户分配角色
const onComfirm = () => {
// const roles = userRoleTitleList.value.map((roleName) => {
// return allRoleList.value.find((role) => role.roleName === roleName);
// });
// const ids = roles.map((item) => {
// return item.id;
// });
const ids = multipleSelection.value.map((item) => {
return item.id;
});
let params = {
userId: props.userId,
roleIds: ids
};
buttonLoading.value = true;
grantRoleToUser(params).then((res) => {
ElMessage.success("操作成功");
//通知
buttonLoading.value = false;
emits("updateRole");
});
closed();
};
//当前用户角色
const userRoleTitleList = ref([]);
const getUserRoles = async () => {
const res = await getUserRoleList(Number(props.userId));
userRoleTitleList.value = res.map((item) => item.id);
const hx = [];
allRoleList.value.forEach(item => {
if (userRoleTitleList.value.includes(item.id)) {
hx.push(item)
}
})
toggleSelection(hx)
};
const toggleSelection = (rows) => {
if (rows) {
rows.forEach((row) => {
multipleTableRef.value.toggleRowSelection(row, true)
})
} else {
multipleTableRef.value.clearSelection()
}
}
//所有角色
const allRoleList = ref([]);
const getAllRoleList = async () => {
const params = {
page: 1,
size: 999
};
const res = await getRoleList(params);
allRoleList.value = res?.records;
getUserRoles();
};
watch(
() => props.userId,
(val) => {
if (val) {
getAllRoleList();
}
}
);
</script>
<style>
</style>

View File

@ -0,0 +1,786 @@
<template>
<div>
<div class="titleBox">
<div class="title">用户管理</div>
<div class="btnBox">
<el-button type="primary" @click="addUserHander">
<el-icon><CirclePlus /></el-icon>
<span>新增</span>
</el-button>
</div>
</div>
<div class="searchBox" ref="searchBox">
<el-form :model="listQuery" class="mosty-from-wrap" :inline="true">
<el-form-item label="用户名">
<el-input
placeholder="请输入用户名"
v-model="listQuery.loginName"
clearable
></el-input>
</el-form-item>
<el-form-item label="移动电话">
<el-input
placeholder="请输入移动电话"
v-model="listQuery.phone"
clearable
></el-input>
</el-form-item>
<el-form-item label="身份证号">
<el-input
placeholder="请输入身份证号"
v-model="listQuery.idEntityCard"
clearable
></el-input>
</el-form-item>
<el-form-item label="警号">
<el-input
placeholder="请输入警号"
v-model="listQuery.inDustRialId"
clearable
></el-input>
</el-form-item>
<el-form-item label="是否包含下级">
<el-select v-model="listQuery.isChild">
<el-option
v-for="item in D_BZ_SF"
:key="item"
:label="item.label"
:value="item.value"
>{{ item.label }}</el-option
>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleFilter">查询</el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="main-box">
<div class="treeBox" :style="{ height: treeHeight }">
<MOSTY.DepartmentTree
width="280px"
placeholder="管理部门ID"
clearable
filterable
:isBmId="true"
v-model="listQuery.deptId"
/>
</div>
<div class="tabBox">
<el-table
:data="tableData"
border
style="width: 100%"
:height="tableHeight"
:key="keyCount"
>
<el-table-column
sortable
prop="userName"
align="center"
label="用户名"
></el-table-column>
<el-table-column
sortable
prop="idEntityCard"
align="center"
label="身份证号"
></el-table-column>
<el-table-column
sortable
prop="deptName"
label="部门"
></el-table-column>
<el-table-column
sortable
prop="inDustRialId"
align="center"
label="警号"
>
</el-table-column>
<el-table-column
sortable
prop="mobile"
align="center"
label="电话号码"
></el-table-column>
<el-table-column align="center" sortable label="性别" width="80">
<template #default="{ row }">
<dict-tag :options="D_BZ_XB" :value="row.sex" :tag="false" />
</template>
</el-table-column>
<el-table-column
align="center"
label="操作"
fixed="right"
width="250"
>
<template #default="{ row }">
<el-button @click="updateDict(row)" size="small">编辑</el-button>
<el-dropdown
style="margin-left: 12px; margin-right: 12px"
@command="dropdownAction"
>
<el-button style="" size="small" @click="handleClick">
更多<el-icon class="el-icon--right">
<arrow-down />
</el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item
:command="commandValue('assignRoles', row)"
>分配角色</el-dropdown-item
>
<el-dropdown-item :command="commandValue('restPwd', row)"
>重置密码</el-dropdown-item
>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要删除?"
@confirm="delRole(row)"
>
<template #reference>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
></el-pagination>
</div>
</div>
</div>
<div v-if="dialogFormVisible" class="dialog">
<div class="head_box">
<span class="title">{{ isEdit ? "修改" : "新增" }}</span>
<div>
<!-- 修改 -->
<el-button
v-if="isEdit"
type="primary"
size="small"
@click="onSave"
:loading="buttonLoading"
>修改</el-button
>
<!-- 新增 -->
<el-button v-else type="primary" size="small" @click="onAdd"
>保存</el-button
>
<el-button size="small" @click="closeDialog">关闭</el-button>
</div>
</div>
<el-form
class="mosty-from-wrap"
ref="elform"
:model="dialogForm"
:inline="true"
label-position="top"
:rules="rules"
>
<el-form-item label="部门:" prop="ssbmdm">
<MOSTY.Department
:placeholder="dialogForm.ssbm"
width="280px"
clearable
filterable
v-model="dialogForm.ssbmdm"
/>
</el-form-item>
<el-form-item label="用户昵称:" prop="userName">
<MOSTY.Other
width="280px"
placeholder="请输入用户昵称"
clearable
v-model="dialogForm.userName"
/>
</el-form-item>
<el-form-item label="登录账号:" prop="loginName">
<MOSTY.Other
width="280px"
placeholder="请输入登录账号"
clearable
v-model="dialogForm.loginName"
/>
</el-form-item>
<el-form-item label="密码:" v-if="!isEdit" prop="password">
<MOSTY.Other
width="280px"
placeholder="请输入密码"
show-password
v-model="dialogForm.password"
/>
</el-form-item>
<el-form-item label="身份证号" prop="idEntityCard">
<MOSTY.IdentityCard
width="280px"
v-model="dialogForm.idEntityCard"
@change="fn"
clearable
></MOSTY.IdentityCard>
</el-form-item>
<el-form-item label="警号" prop="inDustRialId">
<MOSTY.Other
width="280px"
placeholder="请输入警号"
v-model="dialogForm.inDustRialId"
/>
</el-form-item>
<el-form-item label="岗位选择">
<MOSTY.StationSelect
width="300px"
clearable
filterable
v-model="dialogForm.positionId"
/>
</el-form-item>
<el-form-item label="用户类型:" prop="userType">
<el-select
style="width: 100%"
v-model="dialogForm.userType"
placeholder="请选择用户类型"
>
<el-option
v-for="dict in D_BZ_YHLX"
:label="dict.label"
:value="dict.value"
:key="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="虚拟用户:" prop="isVirtualUser">
<el-select
style="width: 100%"
v-model="dialogForm.isVirtualUser"
placeholder="请选择"
>
<el-option
v-for="dict in D_BZ_XNYH"
:label="dict.label"
:value="dict.value"
:key="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="电话号码:" prop="telePhone">
<MOSTY.Phone
width="280px"
v-model="dialogForm.telePhone"
maxlength="11"
clearable
></MOSTY.Phone>
</el-form-item>
<el-form-item label="移动电话:" prop="mobile">
<MOSTY.Phone
width="280px"
v-model="dialogForm.mobile"
maxlength="11"
clearable
></MOSTY.Phone>
</el-form-item>
<el-form-item label="民族:" prop="nation">
<MOSTY.PackageSelect
width="280px"
v-model="dialogForm.nation"
dictEnum="NATION"
clearable
filterable
/>
</el-form-item>
<el-form-item label="性别:" prop="sex">
<el-select
style="width: 100%"
v-model="dialogForm.sex"
placeholder="请选择性别"
>
<el-option
v-for="(item, index) in D_BZ_XB"
:key="index"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="文化程度:" prop="whcd">
<MOSTY.PackageSelect
dictEnum="EDUCATION"
width="280px"
v-model="dialogForm.whcd"
clearable
filterable
/>
</el-form-item>
<el-form-item label="E-mail" prop="email">
<MOSTY.Email
v-model="dialogForm.email"
width="280px"
clearable
></MOSTY.Email>
</el-form-item>
<el-form-item label="出生日期" prop="birthday">
<el-date-picker
style="width: 100%"
v-model="dialogForm.birthday"
type="date"
placeholder="出生日期"
format="YYYY/MM/DD"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item label="所属模块:" prop="politic">
<el-select
style="width: 100%"
v-model="dialogForm.politic"
placeholder="请选择"
>
<el-option
v-for="dict in D_BZ_ZZMM"
:label="dict.label"
:value="dict.value"
:key="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="婚姻状况:" prop="marital">
<el-select
style="width: 100%"
v-model="dialogForm.marital"
placeholder="请选择婚姻状况"
>
<el-option
v-for="dict in D_BZ_HYZK"
:label="dict.label"
:value="dict.value"
:key="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="人员类别:" prop="type">
<el-select
style="width: 100%"
v-model="dialogForm.type"
placeholder="请选择人员类别"
>
<el-option
v-for="dict in D_BZ_RYLB"
:label="dict.label"
:value="dict.value"
:key="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="有效期:" prop="endTime">
<el-date-picker
style="width: 100%"
v-model="dialogForm.endTime"
type="datetime"
placeholder="请选择有效期"
format="YYYY/MM/DD hh:mm:ss"
value-format="x"
/>
</el-form-item>
<el-form-item label="是否融合">
<el-select
style="width: 100%"
v-model="dialogForm.sfrh"
placeholder="请选择"
>
<el-option
v-for="dict in D_BZ_SF"
:label="dict.label"
:value="dict.value"
:key="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item style="width: 100%" label="备注">
<el-input
v-model="dialogForm.bz"
show-word-limit
maxlength="200"
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
></el-input>
</el-form-item>
</el-form>
</div>
<RolesDialog
v-model="roleDialogVisible"
:userId="currentUserId"
@updateRole="handleFilter"
></RolesDialog>
</div>
</template>
<script setup>
import * as rule from "@/utils/rules.js";
import * as MOSTY from "@/components/MyComponents/index";
import { ElMessage } from "element-plus";
import {
ref,
reactive,
computed,
watch,
onMounted,
getCurrentInstance,
onUnmounted
} from "vue";
import RolesDialog from "./components/roles.vue";
import {
getSysUserList,
editSysUser,
addUser,
getUserInfoToId,
resetPassword,
deleteSysUser,
selectDeptPage,
getUserRoleList
} from "@/api/user-manage";
const { proxy } = getCurrentInstance();
const {
D_BZ_XB,
D_BZ_YHLX,
D_BZ_XNYH,
D_BZ_RYLB,
D_BZ_SF,
D_BZ_HYZK,
D_BZ_ZZMM
} = proxy.$dict(
"D_BZ_XB",
"D_BZ_YHLX",
"D_BZ_XNYH",
"D_BZ_RYLB",
"D_BZ_SF",
"D_BZ_HYZK",
"D_BZ_ZZMM"
);
const searchBox = ref(null); // 搜索盒子
const keyCount = ref(0); //tabel组件刷新值
const tableHeight = ref(); // 表格高度
const treeHeight = ref(""); // 树高度
const rules = ref({
// ...rule.phoneRule({ validator: true }, "mobile"), // 是否必填 是否进行校验
// ...rule.phoneRule({ validator: true }, "telePhone"), // 是否必填 是否进行校验 如果props与from里面数据不一致可以传第二个参数
// ...rule.identityCardRule({ validator: true }), //身份证校验
// ...rule.addressSelectRule({ require: true }), //地址
// ...rule.emailRule({ validator: true }), //邮箱
userName: [{ required: true, message: "请填写用户昵称" }],
loginName: [{ required: true, message: "请填写登录账号" }],
password: [{ required: true, message: "请填写密码" }],
// nation: [{ required: true, message: "请选择民族" }],
// sex: [{ required: true, message: "请选择性别", trigger: "change" }],
// whcd: [{ required: true, message: "请选择文化程度" }],
// birthday: [{ required: true, message: "请选择出生日期" }],
ssbmdm: [{ required: true, message: "请选择部门" }],
inDustRialId: [{ required: true, message: "请填写警号" }],
managerOrgId: [{ required: true, message: "请选择岗位" }],
positionId: [{ required: true, message: " " }],
userType: [{ required: true, message: "请选择用户类型" }],
isVirtualUser: [{ required: true, message: "请选择虚拟用户" }],
idEntityCard: [{ required: true, message: "请输入身份证号码" }],
packageSelect: [
{
required: true,
message: "请选择",
trigger: "change"
}
],
other: [
{
required: true,
message: "自由发挥哦",
trigger: "blur"
}
]
});
const elform = ref(null);
const buttonLoading = ref(false);
//查询参数
const total = ref(0);
const page = ref(1);
const size = ref(20);
const currentRow = ref({});
const listQuery = ref({
page: 1,
size: 20,
loginName: "",
phone: ""
});
const isEdit = ref(true);
const dialogForm = ref({
userName: ""
});
// 数据相关
const tableData = ref([]);
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
// 获取数据的方法
const getListData = async () => {
const params = listQuery.value;
params.current = params.page;
const res = await getSysUserList(params);
tableData.value = res?.records;
total.value = Number(res.total);
};
getListData();
const reset = () => {
listQuery.value = {
page: 1,
size: 20,
loginName: "",
phone: ""
};
getListData();
};
const handleFilter = () => {
listQuery.value.page = 1;
getListData();
};
const handleSizeChange = (currentSize) => {
listQuery.value.size = currentSize;
getListData();
};
const handleCurrentChange = (currentPage) => {
listQuery.value.page = currentPage;
getListData();
};
/**修改字典 */
const updateDict = async (row) => {
getUserInfoToId(row.id).then((res) => {
dialogForm.value = { ...res };
dialogForm.value.nation = "" + res.nation;
dialogForm.value.isVirtualUser = "" + res.isVirtualUser;
isEdit.value = true;
dialogFormVisible.value = true;
});
};
//身份证号计算出生日期
function getBirthdayFromIdCard(idCard) {
var birthday = "";
if (idCard != null && idCard != "") {
if (idCard.length == 15) {
birthday = "19" + idCard.substr(6, 6);
} else if (idCard.length == 18) {
birthday = idCard.substr(6, 8);
}
birthday = birthday.replace(/(.{4})(.{2})/, "$1-$2-");
}
return birthday;
}
function fn(e) {
let text = 0;
if (e.length >= 17) {
dialogForm.value.birthday = getBirthdayFromIdCard(e);
text = e[e.length - 2] * 1;
if (text % 2 === 0) {
dialogForm.value.sex = "2";
} else {
dialogForm.value.sex = "1";
}
}
}
const commandValue = (type, command) => {
return {
type: type,
command: command
};
};
const dropdownAction = (item) => {
const { type, command } = item;
if (type === "assignRoles") {
assignRoles(command);
} else if (type === "restPwd") {
restPwd(command);
}
};
const addUserHander = (row) => {
isEdit.value = false;
dialogForm.value = {};
dialogFormVisible.value = true;
};
const onSave = () => {
elform.value.validate((valid) => {
if (valid) {
buttonLoading.value = true;
dialogForm.value.positionName = "";
editSysUser({
...dialogForm.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("修改成功");
buttonLoading.value = false;
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
} else {
ElMessage.error("请填写完必填项!");
return false;
}
});
};
//新增人员
const onAdd = () => {
elform.value.validate((valid) => {
if (valid) {
buttonLoading.value = true;
addUser({
...dialogForm.value
})
.then((res) => {
dialogFormVisible.value = false;
ElMessage.success("新增成功");
buttonLoading.value = false;
handleFilter();
})
.finally(() => {
buttonLoading.value = false;
});
} else {
ElMessage.error("请填写完必填项!");
return false;
}
});
};
const delRole = (row) => {
deleteSysUser({
id: Number(row.id)
}).then((res) => {
ElMessage.success("删除成功");
handleFilter();
});
};
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
};
const moreAction = (e, item) => {};
//分配角色
const currentUserId = ref("");
const roleDialogVisible = ref(false);
const assignRoles = (row) => {
roleDialogVisible.value = true;
currentUserId.value = row.id;
};
const restPwd = (row) => {
resetPassword({ userId: row.id }).then((res) => {
dialogFormVisible.value = false;
ElMessage.success("操作成功");
handleFilter();
});
};
const handleClick = (e) => {};
//watch监听路由变化
watch(roleDialogVisible, (val) => {
if (!val) currentUserId.value = "";
});
watch(
() => listQuery.value.deptId,
() => {
handleFilter();
},
{
immediate: true
}
);
// 表格高度计算
const tabHeightFn = () => {
tableHeight.value =
window.innerHeight - searchBox.value.offsetHeight - 250;
};
// 树高度计算
const treeHeightFn = () => {
treeHeight.value = window.innerHeight - searchBox.value.offsetHeight - 213 + "px";
};
onMounted(() => {
tabHeightFn();
treeHeightFn();
window.onresize = function () {
treeHeightFn();
tabHeightFn();
};
proxy.mittBus.on("mittFn", (data) => {
keyCount.value = data;
});
});
onUnmounted(() => {
proxy.mittBus.off("mittFn");
});
</script>
<style lang="scss" scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
// .user-list-page {
// .userListDialog {
// .el-input__inner {
// min-width: 260px;
// }
// }
// .table-header-wrap {
// margin-bottom: 22px;
// }
// ::v-deep .avatar {
// width: 60px;
// height: 60px;
// border-radius: 50%;
// }
// ::v-deep .el-tag {
// margin-right: 6px;
// }
// .pagination {
// margin-top: 20px;
// }
// .twoLine {
// display: flex;
// align-items: flex-start;
// flex-flow: wrap;
// .el-form-item {
// width: 380px;
// }
// }
// }
</style>

View File

@ -0,0 +1,143 @@
<template>
<div class="user-manage-container">
<el-card class="header">
<div>
分配角色
<el-button type="primary"> 新增</el-button>
<el-button type="success"> 查询 </el-button>
</div>
</el-card>
<el-card>
<el-table :data="tableData" border style="width: 100%">
<el-table-column label="#" type="index" />
<el-table-column prop="username" label="姓名"> </el-table-column>
<el-table-column prop="mobile" label="联系方式"> </el-table-column>
<el-table-column label="头像" align="center">
<template v-slot="{ row }">
<el-image
class="avatar"
:src="row.avatar"
:preview-src-list="[row.avatar]"
></el-image>
</template>
</el-table-column>
<el-table-column label="角色">
<template #default="{ row }">
<div v-if="row.role && row.role.length > 0">
<el-tag v-for="item in row.role" :key="item.id" size="mini">{{
item.title
}}</el-tag>
</div>
<div v-else>
<el-tag size="mini">{{ $t("msg.excel.defaultRole") }}</el-tag>
</div>
</template>
</el-table-column>
<el-table-column prop="updateTime" label="更新时间">
<template #default="{ row }">
{{ $filters.dateFilter(row.updateTime) }}
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" width="260">
<template #default>
<el-button type="primary" size="mini">查询</el-button>
<el-button type="info" size="mini">角色</el-button>
<el-button type="danger" size="mini">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="page"
:page-sizes="[10, 20, 50, 100]"
:page-size="size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</el-card>
</div>
</template>
<script setup>
import { ref } from "vue";
// 数据相关
const tableData = ref([
{
username: "何潇",
mobile: "13540652686",
avatar: "man",
role: [{ title: "超级管理员", id: 1 }],
updateTime: "1646472058066"
},
{
username: "何潇",
mobile: "13540652686",
avatar: "man",
role: [{ title: "超级管理员", id: 1 }],
updateTime: "1646472047000"
},
{
username: "何潇",
mobile: "13540652686",
avatar: "man",
role: [{ title: "超级管理员", id: 1 }],
updateTime: "1646472047002"
}
]);
const total = ref(0);
const page = ref(1);
const size = ref(2);
// 获取数据的方法
const getListData = async () => {
// const result = await getUserManageList({
// page: page.value,
// size: size.value
// })
// tableData.value = result.list
// total.value = result.total
};
getListData();
// 分页相关
/**
* size 改变触发
*/
const handleSizeChange = (currentSize) => {
size.value = currentSize;
getListData();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
page.value = currentPage;
getListData();
};
</script>
<style lang="scss" scoped>
.user-manage-container {
.header {
margin-bottom: 22px;
text-align: right;
}
::v-deep .avatar {
width: 60px;
height: 60px;
border-radius: 50%;
}
::v-deep .el-tag {
margin-right: 6px;
}
.pagination {
margin-top: 20px;
}
}
</style>

View File

@ -0,0 +1,153 @@
<template>
<div class="dialog" v-if="dialogForm">
<div class="head_box">
<span class="title">{{ title }}</span>
<div>
<el-button type="primary" size="small" :loading="loading" @click="submit" v-show="!disabledFoem">保存</el-button>
<el-button size="small" @click="close">关闭</el-button>
</div>
</div>
<el-form ref="elform" :model="listQuery" :rules="rules" :inline="true" :disabled="disabledFoem" label-position="top">
<el-form-item style="width: 100%" prop="nr" label="内容">
<el-input v-model="listQuery.nr" placeholder="请输入内容" clearable/>
</el-form-item>
<el-form-item style="width: 100%" prop="dz" label="地址">
<el-input v-model="listQuery.dz" placeholder="请输入地址" style="width: 100%" clearable/>
</el-form-item>
<el-form-item style="width: 100%" prop="jd" label="坐标位置">
<div class="latlng">
<el-input @change="jwdChange" v-model="listQuery.jd" clearable style="width: 45%" />
<el-input @change="jwdChange" v-model="listQuery.wd" clearable style="width: 45%" />
<el-button @click="chackLat">选取坐标</el-button>
</div>
</el-form-item>
<el-form-item style="width: 100%">
<div class="map"> <GdMap /> </div>
</el-form-item>
</el-form>
</div>
</template>
<script setup>
import emitter from "@/utils/eventBus.js";
import * as MOSTY from "@/components/MyComponents/index";
import GdMap from "@/components/GdMap/index.vue";
import { qcckGet, qcckPost ,qcckPut} from "@/api/qcckApi.js";
import * as rule from "@/utils/rules.js";
import { IdCard } from "@/utils/validate.js";
import { ref,defineExpose, reactive,defineProps,getCurrentInstance ,defineEmits, nextTick, onMounted} from 'vue';
const props = defineProps({
dic:{ type:Object, default:{} }
})
const emits = defineEmits(['updateDate'])
const { proxy } = getCurrentInstance();
const title = ref('新增演示警情');
const disabledFoem = ref(false) //表单禁用
const dialogForm = ref(false) //弹窗
const listQuery = ref({ dwlx:'01'}) //表单
const loading = ref(false)
const elform = ref()
const rules = reactive({
ssbmdm: [{ required: true, message: "请选择所属部门", trigger: "change" }],
nr: [{ required: true, message: "请输入内容", trigger: "blur" }],
});
onMounted(()=>{
emitter.on("coordString", (res) => {
if (res.type === "point") {
listQuery.value.jd = res.coord[0];
listQuery.value.wd = res.coord[1];
handleSd(res.coord[0],res.coord[1],listQuery.value.dwlx)
}
});
})
// 初始化数据
const init = (type,row)=> {
dialogForm.value = true
disabledFoem.value = type == 'detail' ? true :false
if(row){
title.value = type == 'edit'?'修改演示警情':'演示警情详情'
getDataById(row) //根据id查询详情
}else{
title.value = '新增演示警情'
}
}
// 根据id查询详情
const getDataById = (row)=>{
listQuery.value = JSON.parse(JSON.stringify(row))
nextTick(()=>{
if (row.jd && row.wd) {
handleSd(row.jd,row.wd)
emitter.emit("setMapCenter", { location: [row.jd, row.wd], zoomLevel: 10 });
}
})
}
//获取经纬度 - 圈层范围清空
function chackLat(type) {
listQuery.value.jd = "";
listQuery.value.wd = "";
emitter.emit("deletePointArea", "kfd");
emitter.emit("drawShape", { type: "point", flag: "point" ,isclear:true});
}
// 经纬度变化回显
function jwdChange() {
if (listQuery.value.jd && listQuery.value.wd) {
handleSd(listQuery.value.jd,listQuery.value.wd,listQuery.value.dwlx)
emitter.emit("setMapCenter", {
location: [listQuery.value.jd, listQuery.value.wd],
zoomLevel: 10
});
}
}
// 处理撒点
function handleSd (jd,wd) {
let icon = require("@/assets/point/kfd.png")
emitter.emit("deletePointArea", "kfd");
emitter.emit("addPointArea", { coords: [{jd, wd}], icon, flag: "kfd" });
}
// 提交
const submit = ()=>{
elform.value.validate((valid) => {
if (!valid) return false;
loading.value = true;
let url = title.value == '新增演示警情' ? '/mosty-jmxf/ysjq/addYsjq' : '/mosty-jmxf/ysjq/editYsjq';
let text = title.value == '新增演示警情' ? '新增成功' : '编辑成功';
qcckPost(listQuery.value,url).then(res=>{
proxy.$message({type: "success", message: text});
close()
emits('updateDate')
loading.value = false;
}).catch(()=>{ loading.value = false; })
});
}
// 关闭
const close = ()=>{
listQuery.value = { dwlx:'01'}
dialogForm.value = false
}
defineExpose({init});
</script>
<style lang='scss' scoped>
@import "~@/assets/css/layout.scss";
@import "~@/assets/css/element-plus.scss";
.map {
width: 100%;
height: 400px;
}
.latlng {
width: 100%;
display: flex;
justify-content: space-between;
}
</style>

View File

@ -0,0 +1,154 @@
<template>
<div>
<div class="titleBox">
<!-- 头部 -->
<PageTitle title="演示警情">
<el-button type="primary" @click="addEdit('add', '')">
<el-icon style="vertical-align: middle"> <CirclePlus /> </el-icon>
<span style="vertical-align: middle">新增</span>
</el-button>
</PageTitle>
</div>
<!-- 搜索 -->
<div ref="searchBox">
<Search :searchArr="searchConfiger" @submit="onSearch" />
</div>
<!-- 表格 -->
<div class="tabBox">
<MyTable
:tableData="pageData.tableData"
:tableColumn="pageData.tableColumn"
:tableHeight="pageData.tableHeight"
:key="pageData.keyCount"
:tableConfiger="pageData.tableConfiger"
:controlsWidth="pageData.controlsWidth"
>
<template #dwlx="{ row }">
<dict-tag :options="D_BZ_KFDLX " :value="row.dwlx" :tag="false" />
</template>
<!-- 操作 -->
<template #controls="{ row }">
<el-button size="small" @click="addEdit('edit', row)">修改</el-button>
<el-button size="small" @click="delDictItem([row.id])">删除</el-button>
</template>
</MyTable>
</div>
<!-- 编辑详情 -->
<EditAddForm ref="addEditDialog" :dic="{D_BZ_KFDLX }" @updateDate="getData"/>
</div>
</template>
<script setup>
import PageTitle from "@/components/aboutTable/PageTitle.vue";
import MyTable from "@/components/aboutTable/MyTable.vue";
import Pages from "@/components/aboutTable/Pages.vue";
import Search from "@/components/aboutTable/Search.vue";
import EditAddForm from './components/editAddForm.vue'
import { qcckGet, qcckPost ,qcckDelete} from "@/api/qcckApi.js";
import { reactive, ref ,onMounted,getCurrentInstance } from 'vue';
const { proxy } = getCurrentInstance();
const addEditDialog = ref();
const searchBox = ref() //搜索框
const searchConfiger = reactive([
{
showType: "input",
prop: "nr",
placeholder: "请输入内容",
label: "内容",
},
])
const queryFrom = ref({})
const pageData = reactive({
tableData: [], //表格数据
keyCount: 0,
tableConfiger: {
rowHieght: 61,
showSelectType:'null',
loading:false
},
total: 0,
pageConfiger: {
pageSize: 20,
pageNum: 1
}, //分页
controlsWidth: 210, //操作栏宽度
tableColumn: [
{
label: "内容",
prop: "nr",
showOverflowTooltip:true
},
{
label: "地址",
prop: "dz",
showOverflowTooltip:true
},
{
label: "经度",
prop: "jd",
showOverflowTooltip:true
},
{
label: "纬度",
prop: "wd",
showOverflowTooltip:true
},
]
});
onMounted(() => {
getData() //获取数据
tabHeightFn();
proxy.mittBus.on("mittFn", (data) => {
pageData.keyCount = data;
});
});
// 搜索
const onSearch = (val)=>{
queryFrom.value = {...val}
pageData.pageConfiger.pageNum = 1
getData() //获取数据
}
// 获取数据
const getData = ()=>{
let pramas = {
...queryFrom.value
}
pageData.tableConfiger.loading = true
qcckPost(pramas,'/mosty-jmxf/ysjq/queryYsjq').then(res=>{
pageData.tableData = res ? [res] : [];
pageData.tableConfiger.loading = false
}).catch(()=> { pageData.tableConfiger.loading = false })
}
// 新增
const addEdit = (type,row)=>{
addEditDialog.value.init(type,row)
}
// 批量删除
function delDictItem(ids) {
proxy.$confirm("确定要删除", "警告", {type: "warning"}).then(() => {
qcckPost(ids,'/mosty-jmxf/ysjq/deleteYsjq').then(() => {
proxy.$message({type: "success", message: "删除成功" });
getData();
});
}).catch(() => {
proxy.$message.info("已取消");
});
}
// 表格高度计算
const tabHeightFn = () => {
pageData.tableHeight = window.innerHeight - searchBox.value.offsetHeight - 240;
window.onresize = function () { tabHeightFn(); };
};
</script>
<style>
.el-loading-mask{
background: rgba(0,0,0,0.3);
}
</style>

View File

@ -0,0 +1,362 @@
<template>
<div>
<div class="titleBox">
<div class="title">重点区域分值列表</div>
<div class="btnBox">
<el-button type="primary" @click="addRole()">
<el-icon><CirclePlus /></el-icon>
<span>新增</span>
</el-button>
</div>
</div>
<div class="searchBox" ref="searchBox">
<el-form :model="listQuery" :inline="true">
<el-form-item label="配置类型">
<el-select
clearable
v-model="dialogForm.pzlx"
placeholder="请选择配置类型"
>
<el-option
v-for="(dict, index) in D_BZ_PZLX"
:key="index"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleFilter"> 查询 </el-button>
<el-button @click="reset()"> 重置 </el-button>
</el-form-item>
</el-form>
</div>
<div class="tabBox">
<el-table
:data="pzList"
border
:height="tableHeight"
style="width: 100%"
:key="keyCount"
>
<el-table-column
prop="orderNo"
label="编号"
show-overflow-tooltip
type="index"
width="120px"
>
</el-table-column>
<el-table-column prop="roleName" label="配置类型" show-overflow-tooltip>
<template #default="{ row }">
<dict-tag :options="D_BZ_PZLX" :value="row.pzlx" :tag="false" />
</template>
</el-table-column>
<el-table-column prop="pzfz" label="配置分值" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="pzsjfw" label="时间范围/分钟"> </el-table-column>
<el-table-column label="操作" fixed="right" width="220">
<template #default="{ row }">
<el-button @click="updateDict(row)" size="small">修改</el-button>
<el-popconfirm
confirm-button-text=""
cancel-button-text=""
icon-color="red"
title="确定要删除?"
@confirm="delRole(row)"
>
<template #reference>
<el-button type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div class="fenye" :style="{ top: tableHeight + 'px' }">
<el-pagination
class="pagination"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="listQuery.page"
:page-sizes="[10, 20, 50, 100]"
:page-size="listQuery.size"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</div>
</div>
<div v-if="dialogFormVisible" class="dialog">
<div class="head_box">
<span class="title">{{ isEdit ? "修改" : "新增" }}</span>
<div>
<!-- 修改 -->
<el-button
v-if="isEdit"
type="primary"
size="small"
@click="onSave"
:loading="buttonLoading"
>保存</el-button
>
<!-- 新增 -->
<el-button
v-else
type="primary"
size="small"
@click="onAdd"
:loading="buttonLoading"
>保存</el-button
>
<el-button size="small" @click="closeDialog">关闭</el-button>
</div>
</div>
<el-form
:rules="rules"
ref="elform"
inline="true"
label-position="top"
:model="dialogForm"
class="mosty-from-wrap"
>
<el-form-item prop="pzlx" class="one" label="配置类型">
<el-select clearable v-model="dialogForm.pzlx" placeholder="请选择">
<el-option
v-for="(dict, index) in D_BZ_PZLX"
:key="index"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item
class="one"
prop="pzsjfw"
label="时间范围(分钟)"
label-width="140px"
>
<el-input
v-model="dialogForm.pzsjfw"
show-word-limit
autocomplete="off"
></el-input>
</el-form-item>
<el-form-item
class="one"
label="配置分值"
prop="pzfz"
label-width="140px"
>
<el-input
v-model="dialogForm.pzfz"
show-word-limit
autocomplete="off"
></el-input>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script setup>
import { ElMessage } from "element-plus";
import { ref, onMounted, getCurrentInstance, onUnmounted } from "vue";
import { getSelectPzfz, addPzfz, updatePzfz, deletePzfz } from "@/api/base.js";
const { proxy } = getCurrentInstance();
const { D_BZ_PZLX } = proxy.$dict("D_BZ_PZLX");
import { useRouter } from "vue-router";
const searchBox = ref(null); // 搜索盒子
const keyCount = ref(0); //tabel组件刷新值
const tableHeight = ref(); // 表格高度
//查询参数
const total = ref(0);
const page = ref(1);
const size = ref(20);
const currentRow = ref({});
const listQuery = ref({
pageCurrent: 1,
pageSize: 20,
pzlx: ""
});
const elform = ref(null);
//验证
const rules = ref({
pzlx: [{ required: true, message: "请选择配置类型", trigger: "change" }],
pzfz: [{ required: true, message: "请输入配置分值", trigger: "change" }],
pzsjfw: [{ required: true, message: "请输入时间范围", trigger: "change" }]
});
const isEdit = ref(true);
const dialogForm = ref({
pzlx: "",
pzfz: "",
pzsjfw: "",
pzlx: "" //筛选条件
});
const pzList = ref([]); //配置分值数据
const buttonLoading = ref(false);
// 数据相关
const dialogFormVisible = ref(false);
const formLabelWidth = "140px";
// 获取分值列表数据的方法
function _getSelectPzfz() {
let data = {
pageSize: listQuery.value.pageSize,
pageCurrent: listQuery.value.pageCurrent,
pzlx: dialogForm.value.pzlx
};
getSelectPzfz(data).then((res) => {
pzList.value = res.records;
});
}
//条件查询
const handleFilter = () => {
listQuery.value.pageCurrent = 1;
_getSelectPzfz();
};
//重置
const reset = () => {
listQuery.value = {
pageCurrent: 1,
pageSize: 20
};
dialogForm.value.pzlx = "";
};
// 分页相关
/**
* size 改变触发
*/
const handleSizeChange = (currentSize) => {
listQuery.value.pageSize = currentSize;
_getSelectPzfz();
};
/**
* 页码改变触发
*/
const handleCurrentChange = (currentPage) => {
listQuery.value.pageSize = currentPage;
listQuery.value.pageCurrent = 1;
_getSelectPzfz();
};
/**修改字典 */
const updateDict = (row) => {
isEdit.value = true;
row.pzlx = "" + row.pzlx;
dialogForm.value = { ...row };
dialogFormVisible.value = true;
};
/**点击新增 */
const addRole = (row) => {
isEdit.value = false;
dialogForm.value = {};
dialogFormVisible.value = true;
};
/**修改 */
const onSave = () => {
elform.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
updatePzfz(dialogForm.value).then((res) => {
ElMessage.success("修改成功");
buttonLoading.value = false;
dialogFormVisible.value = false;
listQuery.value = {
pageCurrent: 1,
pageSize: 20
};
dialogForm.value.pzlx = "";
_getSelectPzfz();
});
});
};
//添加
const onAdd = () => {
elform.value.validate((valid) => {
if (!valid) {
ElMessage.error("请完成必填项!");
return false;
}
buttonLoading.value = true;
addPzfz(dialogForm.value)
.then((res) => {
ElMessage.success("添加成功");
buttonLoading.value = false;
dialogFormVisible.value = false;
listQuery.value = {
pageCurrent: 1,
pageSize: 20
};
dialogForm.value.pzlx = "";
_getSelectPzfz();
})
.catch((err) => {
buttonLoading.value = false;
});
});
};
//删除
const delRole = (row) => {
buttonLoading.value = true;
deletePzfz(row.id).then((res) => {
ElMessage.success("删除成功");
listQuery.value = {
pageCurrent: 1,
pageSize: 20
};
dialogForm.value.pzlx = "";
_getSelectPzfz();
});
};
//关闭弹窗
const closeDialog = () => {
dialogForm.value = {};
dialogFormVisible.value = false;
buttonLoading.value = false;
};
//分配用户
const router = useRouter();
// 高度计算
const tabHeightFn = () => {
tableHeight.value = window.innerHeight - searchBox.value.offsetHeight - 240;
};
onMounted(() => {
tabHeightFn();
window.onresize = function () {
tabHeightFn();
};
_getSelectPzfz();
});
onUnmounted(() => {});
</script>
<style lang="scss" scoped>
@import "@/assets/css/layout.scss";
@import "@/assets/css/element-plus.scss";
.user-manage-container {
.table-header-wrap {
margin-bottom: 22px;
}
::v-deep .avatar {
width: 60px;
height: 60px;
border-radius: 50%;
}
::v-deep .el-tag {
margin-right: 6px;
}
.pagination {
margin-top: 20px;
}
}
</style>