系统管理页面样式
This commit is contained in:
parent
e6acb5040b
commit
51cf28daef
28
README.md
28
README.md
@ -31,30 +31,6 @@ yarn dev
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
我已经完成了路由配置的修改,实现了您描述的导航结构:
|
||||
顶部导航栏:
|
||||
平台概览
|
||||
车辆管理
|
||||
系统管理
|
||||
左侧导航栏:
|
||||
点击平台概览时不显示左侧导航栏
|
||||
点击车辆管理时显示:
|
||||
车辆监控
|
||||
车辆管理
|
||||
车辆入库
|
||||
类型管理
|
||||
点击系统管理时显示:
|
||||
角色管理
|
||||
人员管理
|
||||
用户管理
|
||||
驾驶员管理
|
||||
菜单管理
|
||||
操作日志
|
||||
td: 68px
|
||||
|
||||
handleTabClick 点击事件处理的存在问题导致显示不对 之前的菜单是通过SidebarItem来获取的是吗?只是当前我想修改样式 并且将这个原始的导航栏分在不同的Tab栏展示 我觉得可以根据数据库获取到所有的菜单 然后再根据不同的Tab栏来确定是否显示呀
|
||||
|
||||
|
||||
点击平台概览:不显示标签
|
||||
,其余都不显示,只有点击二级菜单的时候才在右侧显示
|
||||
点击系统管理:只显示默认显示"角色管理"标签,其余都不显示只有点击二级菜单的时候才在右侧显示 先理解我的需求 不明白的问我
|
||||
现在我需要修改tagsView的展示:当我点击顶部导航栏车辆管理的时候 默认显示车辆监控5690E7(不可关闭),当我点击车辆管理下的车辆入库,则显示:车辆监控(白色) 车辆入库(5690E7),鼠标滑入显示车辆入库(5690E7)叉号(5690E7),点击叉号返回到车辆监控;点击车辆管理下的类型管理,则显示:车辆监控(白色) 类型管理(5690E7),鼠标滑入显示类型管理(5690E7)叉号(5690E7),点击叉号返回到车辆监控;点击系统管理默认显示角色管理5690E7(不可关闭),当我点击人员管理下的用户管理,则显示:角色管理(白色) 用户管理(5690E7),鼠标滑入显示用户管理(5690E7)叉号(5690E7),点击叉号返回到角色管理;当我点击人员管理下的驾驶员理,则显示:角色管理(白色) 驾驶员管理(5690E7),鼠标滑入显示驾驶员管理(5690E7)叉号(5690E7),点击叉号返回到角色管理;当我点击操作日志则显示:角色管理(白色) 操作日志(5690E7),鼠标滑入显示操作日志(5690E7)叉号(5690E7),点击叉号返回到角色管理 我们可以点击车辆管理:只默认显示"车辆监控"标签理解为将车辆管理下的车辆监控和系统管理下的角色管理作为首页来看
|
||||
1.新增弹窗的label驾驶证类型没有占一行2.人像的矩形右上角的计数器位置与编辑一致
|
||||
75
src/api/system/driver.js
Normal file
75
src/api/system/driver.js
Normal file
@ -0,0 +1,75 @@
|
||||
import request from '@/utils/request'
|
||||
import { parseStrEmpty } from "@/utils/ruoyi";
|
||||
|
||||
// 查询驾驶员列表
|
||||
export function listDriver(query) {
|
||||
return request({
|
||||
url: '/system/driver/list',
|
||||
method: 'get',
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 查询驾驶员详细
|
||||
export function getDriver(driverId) {
|
||||
return request({
|
||||
url: '/system/driver/' + parseStrEmpty(driverId),
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 新增驾驶员
|
||||
export function addDriver(data) {
|
||||
return request({
|
||||
url: '/system/driver',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 修改驾驶员
|
||||
export function updateDriver(data) {
|
||||
return request({
|
||||
url: '/system/driver',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除驾驶员
|
||||
export function delDriver(driverId) {
|
||||
return request({
|
||||
url: '/system/driver/' + driverId,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 驾驶员状态修改
|
||||
export function changeDriverStatus(driverId, status) {
|
||||
const data = {
|
||||
driverId,
|
||||
status
|
||||
}
|
||||
return request({
|
||||
url: '/system/driver/changeStatus',
|
||||
method: 'put',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 用户头像上传
|
||||
export function uploadAvatar(data) {
|
||||
return request({
|
||||
url: '/system/driver/avatar',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取驾驶员初始密码
|
||||
export function getInitPassword() {
|
||||
return request({
|
||||
url: '/system/driver/initPassword',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@ -133,3 +133,11 @@ export function deptTreeSelect() {
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取用户初始密码
|
||||
export function getInitPassword() {
|
||||
return request({
|
||||
url: '/system/user/initPassword',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
BIN
src/assets/images/avatar.png
Normal file
BIN
src/assets/images/avatar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.2 KiB |
@ -93,7 +93,7 @@
|
||||
color: #96A0B5 !important;
|
||||
border-radius: 8px !important;
|
||||
height: 36px !important;
|
||||
border: none !important;
|
||||
border: none;
|
||||
box-shadow: none !important;
|
||||
|
||||
}
|
||||
@ -101,6 +101,13 @@
|
||||
color: #96A0B5 !important;
|
||||
}
|
||||
// to fixed https://github.com/ElemeFE/element/issues/2461
|
||||
.el-overlay-dialog{
|
||||
width:100%!important;
|
||||
height:100%!important;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.el-dialog {
|
||||
transform: none;
|
||||
left: 0;
|
||||
@ -109,9 +116,14 @@
|
||||
border-radius: 12px!important;
|
||||
background: #292C38!important;
|
||||
color: #fff!important;
|
||||
--el-text-color-regular: #96A0B5!important;
|
||||
.el-dialog__title {
|
||||
color: #fff!important;
|
||||
}
|
||||
.el-dialog__header{
|
||||
border-bottom: 1px solid #4C4F5F!important;
|
||||
margin: 0px!important;
|
||||
}
|
||||
.el-dialog__headerbtn .el-dialog__close {
|
||||
color: #fff!important;
|
||||
}
|
||||
@ -119,7 +131,94 @@
|
||||
color:rgba(255,255,255,0.6)!important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-message-box {
|
||||
border-radius: 12px!important;
|
||||
background: #292C38!important;
|
||||
color: #fff!important;
|
||||
border: none!important;
|
||||
--el-messagebox-title-color: #fff!important;
|
||||
--el-color-info: #fff!important;
|
||||
--el-messagebox-content-color: #fff!important;
|
||||
--el-color-warning: #FF4C4C;
|
||||
|
||||
.el-message-box__header {
|
||||
border-bottom: 1px solid #4C4F5F!important;
|
||||
padding: 15px 20px!important;
|
||||
}
|
||||
|
||||
.el-message-box__title {
|
||||
color: #fff!important;
|
||||
font-size: 16px!important;
|
||||
font-weight: normal!important;
|
||||
}
|
||||
|
||||
.el-message-box__content {
|
||||
padding: 20px 48px!important;
|
||||
color: #fff!important;
|
||||
}
|
||||
|
||||
.el-message-box__container {
|
||||
display: flex!important;
|
||||
align-items: center!important;
|
||||
}
|
||||
|
||||
.el-message-box__status {
|
||||
font-size: 64px!important;
|
||||
position: static!important;
|
||||
transform: none!important;
|
||||
margin-right: 15px!important;
|
||||
}
|
||||
|
||||
.el-message-box__message {
|
||||
padding-left: 0!important;
|
||||
color: #fff!important;
|
||||
font-size: 16px!important;
|
||||
}
|
||||
|
||||
.el-message-box__btns {
|
||||
padding: 0px 20px 20px!important;
|
||||
text-align: right!important;
|
||||
|
||||
.el-button {
|
||||
border-radius: 8px!important;
|
||||
padding: 8px 20px!important;
|
||||
margin-left: 10px!important;
|
||||
font-size: 15px!important;
|
||||
height: 36px!important;
|
||||
width: 68px!important;
|
||||
}
|
||||
|
||||
.el-button--default {
|
||||
background-color: #343744!important;
|
||||
border-color: #343744!important;
|
||||
color: #fff!important;
|
||||
|
||||
&:hover {
|
||||
background-color: #3F4254!important;
|
||||
border-color: #3F4254!important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-button--primary {
|
||||
background-color: #347AE2!important;
|
||||
border-color: #347AE2!important;
|
||||
|
||||
&:hover {
|
||||
background-color: #4A7FD5!important;
|
||||
border-color: #4A7FD5!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.el-message-box__close {
|
||||
color: #fff!important;
|
||||
font-size: 18px!important;
|
||||
|
||||
&:hover {
|
||||
color: #5690E7!important;
|
||||
}
|
||||
}
|
||||
}
|
||||
// refine element ui upload
|
||||
.upload-container {
|
||||
.el-upload {
|
||||
|
||||
@ -193,3 +193,39 @@ aside {
|
||||
.multiselect--active {
|
||||
z-index: 1000 !important;
|
||||
}
|
||||
/* 全局滚动条样式 */
|
||||
::-webkit-scrollbar {
|
||||
width: 8px; /* 垂直滚动条的宽度 */
|
||||
height: 8px; /* 水平滚动条的高度 */
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: rgba(144, 147, 153, 0.5);
|
||||
border-radius: 4px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(144, 147, 153, 0.8);
|
||||
}
|
||||
|
||||
/* Firefox 滚动条样式 */
|
||||
* {
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: rgba(144, 147, 153, 0.5) rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* 隐藏特定元素的滚动条但保持可滚动 */
|
||||
.hide-scrollbar {
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
|
||||
.hide-scrollbar::-webkit-scrollbar {
|
||||
display: none; /* Chrome, Safari and Opera */
|
||||
}
|
||||
@ -75,7 +75,7 @@
|
||||
}
|
||||
|
||||
.el-table {
|
||||
min-height: calc(100vh - 310px)!important;
|
||||
min-height: calc(100vh - 295px)!important;
|
||||
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
|
||||
th {
|
||||
word-break: break-word;
|
||||
@ -111,10 +111,13 @@
|
||||
// }
|
||||
|
||||
/* tree border */
|
||||
.el-tree{
|
||||
background: transparent!important;
|
||||
}
|
||||
.tree-border {
|
||||
margin-top: 5px;
|
||||
border: 1px solid #e5e6e7;
|
||||
background: #FFFFFF none;
|
||||
border: none!important;
|
||||
background: transparent!important;
|
||||
border-radius:4px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ function handleCurrentChange(val) {
|
||||
<style lang="scss" scoped>
|
||||
.pagination-container {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
// height: 50px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
|
||||
@ -27,7 +27,7 @@ const tagsViewStore = useTagsViewStore()
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background-color: #343744;
|
||||
padding:0 30px;
|
||||
padding:0 32px;
|
||||
}
|
||||
|
||||
.fixed-header + .app-main {
|
||||
|
||||
@ -106,6 +106,7 @@ function handleTabClick(path) {
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
margin: 0 10px;
|
||||
@ -120,6 +121,8 @@ function handleTabClick(path) {
|
||||
// background-color: rgba(255, 255, 255, 0.2);
|
||||
background: url("../../assets/images/tabs.png") no-repeat;
|
||||
background-size: 100% 100%;
|
||||
color: #A1D1FF;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -95,11 +95,14 @@ defineExpose({
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
:deep(.el-scrollbar__bar) {
|
||||
bottom: 0px;
|
||||
}
|
||||
:deep(.el-scrollbar__wrap) {
|
||||
height: 49px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -14,7 +14,7 @@
|
||||
@contextmenu.prevent="openMenu(tag, $event)"
|
||||
>
|
||||
{{ tag.title }}
|
||||
<span v-if="!isAffix(tag)" @click.prevent.stop="closeSelectedTag(tag)">
|
||||
<span v-if="!isAffix(tag)" @click.prevent.stop="handleCloseTag(tag)">
|
||||
<close class="el-icon-close" style="width: 1em; height: 1em;vertical-align: middle;" />
|
||||
</span>
|
||||
</router-link>
|
||||
@ -186,6 +186,11 @@ function shouldShowTag(tag) {
|
||||
return route.path.startsWith('/system/');
|
||||
}
|
||||
|
||||
// 对于操作日志标签,只有在/system/路径下才显示
|
||||
if (tag.path === '/system/operlog') {
|
||||
return route.path.startsWith('/system/');
|
||||
}
|
||||
|
||||
// 用户管理页面特殊处理 - 只在访问用户管理页面时显示
|
||||
if ((tag.path === '/system/user' || tag.path === '/system/user/index' ||
|
||||
(tag.meta && tag.meta.title === '用户管理'))) {
|
||||
@ -263,6 +268,20 @@ function ensureUserManagementTag() {
|
||||
// 监听路由变化
|
||||
watch(route, (newRoute) => {
|
||||
console.log('Route changed to:', newRoute.path, newRoute.meta?.title);
|
||||
console.log('当前访问标签数:', visitedViews.value.length);
|
||||
console.log('当前访问标签:', visitedViews.value.map(tag => ({path: tag.path, title: tag.title})));
|
||||
|
||||
// 检查并清理菜单管理标签(如果存在)
|
||||
const menuManageTags = visitedViews.value.filter(tag =>
|
||||
tag.title === '菜单管理' || tag.path === '/system/menu'
|
||||
);
|
||||
if (menuManageTags.length > 0) {
|
||||
console.log('发现菜单管理标签,将其移除');
|
||||
useTagsViewStore().visitedViews = visitedViews.value.filter(tag =>
|
||||
tag.title !== '菜单管理' && tag.path !== '/system/menu'
|
||||
);
|
||||
}
|
||||
|
||||
addTags();
|
||||
moveToCurrentTag();
|
||||
|
||||
@ -272,6 +291,7 @@ watch(route, (newRoute) => {
|
||||
ensureUserManagementTag();
|
||||
}
|
||||
});
|
||||
|
||||
watch(visible, (value) => {
|
||||
if (value) {
|
||||
document.body.addEventListener('click', closeMenu)
|
||||
@ -279,6 +299,7 @@ watch(visible, (value) => {
|
||||
document.body.removeEventListener('click', closeMenu)
|
||||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// 动态获取菜单信息
|
||||
const { menuInfo, mainMenus } = getMenuInfoFromRoutes();
|
||||
@ -319,7 +340,9 @@ onMounted(() => {
|
||||
});
|
||||
|
||||
function isActive(r) {
|
||||
return r.path === route.path
|
||||
// 为更好地调试,添加日志
|
||||
console.log('检查标签是否活动:', r.path, '当前路由:', route.path, r.path === route.path);
|
||||
return r.path === route.path;
|
||||
}
|
||||
|
||||
function activeStyle(tag) {
|
||||
@ -341,6 +364,14 @@ function activeStyle(tag) {
|
||||
}
|
||||
|
||||
function isAffix(tag) {
|
||||
// 添加调试日志
|
||||
console.log('检查是否固定标签:', tag.path, tag.title, tag.meta?.affix);
|
||||
|
||||
// 特殊处理操作日志标签,让它可以被关闭
|
||||
if (tag.path === '/system/operlog') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 判断是否为主菜单的默认页面,如果是则不允许关闭
|
||||
return (tag.meta && tag.meta.affix) || isDefaultMenuTag(tag);
|
||||
}
|
||||
@ -514,9 +545,11 @@ function addTags() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 处理系统管理相关页面
|
||||
if (route.path.startsWith('/system/') && route.path !== '/system/role') {
|
||||
// 清除之前的非默认系统管理标签
|
||||
// 特殊处理操作日志页面
|
||||
if (route.path === '/system/operlog' || (route.meta && route.meta.title === '操作日志')) {
|
||||
console.log('特别处理操作日志页面');
|
||||
|
||||
// 清除所有非系统管理相关标签和系统管理默认标签以外的标签
|
||||
const cleanedViews = useTagsViewStore().visitedViews.filter(tag => {
|
||||
// 保留非系统管理相关标签和角色管理标签
|
||||
return !tag.path.startsWith('/system/') || tag.path === '/system/role';
|
||||
@ -531,6 +564,49 @@ function addTags() {
|
||||
meta: { title: '角色管理', affix: true }
|
||||
};
|
||||
|
||||
// 确保roleTag在数组开头
|
||||
const hasRoleTag = useTagsViewStore().visitedViews.some(tag => tag.path === '/system/role');
|
||||
if (!hasRoleTag) {
|
||||
// 找到首页标签的位置,在其后添加角色管理标签
|
||||
const indexPosition = useTagsViewStore().visitedViews.findIndex(tag => tag.path === '/index');
|
||||
if (indexPosition !== -1) {
|
||||
useTagsViewStore().visitedViews.splice(indexPosition + 1, 0, roleTag);
|
||||
} else {
|
||||
useTagsViewStore().visitedViews.unshift(roleTag);
|
||||
}
|
||||
}
|
||||
|
||||
// 添加操作日志标签
|
||||
const operlogTag = {
|
||||
fullPath: '/system/operlog',
|
||||
path: '/system/operlog',
|
||||
name: 'systemOperlog',
|
||||
meta: { title: '操作日志', icon: 'form', affix: false }
|
||||
};
|
||||
|
||||
// 添加到访问视图中
|
||||
useTagsViewStore().addVisitedView(operlogTag);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// 处理系统管理相关页面
|
||||
if (route.path.startsWith('/system/') && route.path !== '/system/role' && route.path !== '/system/operlog') {
|
||||
// 清除之前的非默认系统管理标签
|
||||
const cleanedViews = useTagsViewStore().visitedViews.filter(tag => {
|
||||
// 保留非系统管理相关标签、角色管理标签和操作日志标签
|
||||
return !tag.path.startsWith('/system/') || tag.path === '/system/role' || tag.path === '/system/operlog';
|
||||
});
|
||||
useTagsViewStore().visitedViews = cleanedViews;
|
||||
|
||||
// 确保系统管理的默认标签(角色管理)在前面
|
||||
const roleTag = {
|
||||
fullPath: '/system/role',
|
||||
path: '/system/role',
|
||||
name: 'systemRole',
|
||||
meta: { title: '角色管理', affix: true }
|
||||
};
|
||||
|
||||
// 确保roleTag在数组开头(可能在第1个位置,如果0是首页的话)
|
||||
const hasRoleTag = useTagsViewStore().visitedViews.some(tag => tag.path === '/system/role');
|
||||
if (!hasRoleTag) {
|
||||
@ -614,6 +690,19 @@ function refreshSelectedTag(view) {
|
||||
}
|
||||
|
||||
function closeSelectedTag(view) {
|
||||
// 添加调试日志
|
||||
console.log('关闭标签:', view.path, view.title);
|
||||
|
||||
// 特殊处理操作日志标签
|
||||
if (view.path === '/system/operlog') {
|
||||
console.log('关闭操作日志标签,跳转到角色管理页面');
|
||||
// 从标签列表中移除操作日志标签
|
||||
useTagsViewStore().delVisitedView(view);
|
||||
// 直接跳转到角色管理页面
|
||||
router.push('/system/role');
|
||||
return;
|
||||
}
|
||||
|
||||
proxy.$tab.closePage(view).then(({ visitedViews }) => {
|
||||
if (isActive(view)) {
|
||||
// 获取当前路径所属的主菜单
|
||||
@ -702,15 +791,21 @@ function closeMenu() {
|
||||
function handleScroll() {
|
||||
closeMenu()
|
||||
}
|
||||
|
||||
// 处理关闭标签的点击事件,增加调试信息
|
||||
function handleCloseTag(tag) {
|
||||
console.log('点击关闭标签按钮:', tag.path, tag.title);
|
||||
closeSelectedTag(tag);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
.tags-view-container {
|
||||
height: 70px;
|
||||
line-height: 70px;
|
||||
width: 100%;
|
||||
padding: 0 0 0 20px;
|
||||
padding: 15px 0 15px 20px; /* 上下各15px的padding替代固定高度 */
|
||||
background: #343744;
|
||||
display: flex; /* 使用flexbox布局 */
|
||||
align-items: center; /* 垂直居中对齐 */
|
||||
.tags-view-wrapper {
|
||||
.tags-view-item {
|
||||
display: inline-block;
|
||||
|
||||
@ -52,8 +52,8 @@ export default {
|
||||
ElNotification.warning(content)
|
||||
},
|
||||
// 确认窗体
|
||||
confirm(content) {
|
||||
return ElMessageBox.confirm(content, "系统提示", {
|
||||
confirm(content, title = "系统提示") {
|
||||
return ElMessageBox.confirm(content, title, {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: "warning",
|
||||
|
||||
@ -124,12 +124,6 @@ export const constantRoutes = [
|
||||
component: () => import('@/views/system/user/index'),
|
||||
name: 'User',
|
||||
meta: { title: '用户管理', icon: 'user', affix: false }
|
||||
},
|
||||
{
|
||||
path: 'operlog',
|
||||
component: () => import('@/views/system/operlog/index'),
|
||||
name: 'systemOperlog',
|
||||
meta: { title: '操作日志', icon: 'form', affix: false }
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -148,6 +142,21 @@ export const constantRoutes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
// 操作日志路由(一级路由)
|
||||
{
|
||||
path: '/system/operlog',
|
||||
component: Layout,
|
||||
name: 'systemOperlog',
|
||||
meta: { title: '操作日志', icon: 'form', affix: false },
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
component: () => import('@/views/system/operlog/index'),
|
||||
name: 'SystemOperlogIndex',
|
||||
meta: { title: '操作日志', icon: 'form', affix: false }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: Layout,
|
||||
|
||||
@ -9,6 +9,7 @@ const useTagsViewStore = defineStore(
|
||||
defaultPages: {
|
||||
'/car': '/car/monitor', // 车辆管理 -> 车辆监控
|
||||
'/system': '/system/role', // 系统管理 -> 角色管理
|
||||
'/system/operlog': '/system/operlog' // 操作日志
|
||||
}
|
||||
}),
|
||||
actions: {
|
||||
@ -29,6 +30,10 @@ const useTagsViewStore = defineStore(
|
||||
},
|
||||
// 检查是否为默认页面
|
||||
isDefaultPage(path) {
|
||||
// 为了让操作日志可以被关闭,特殊处理操作日志路径
|
||||
if (path === '/system/operlog') {
|
||||
return false;
|
||||
}
|
||||
return Object.values(this.defaultPages).includes(path);
|
||||
},
|
||||
addView(view) {
|
||||
|
||||
@ -1,7 +1,962 @@
|
||||
<template>
|
||||
<p>车辆入库</p>
|
||||
</template>
|
||||
<script setup>
|
||||
<div class="app-container">
|
||||
<div class="park-container">
|
||||
<!-- 搜索区域 -->
|
||||
<div class="search-area">
|
||||
<el-input
|
||||
v-model="queryParams.carNo"
|
||||
placeholder="请输入车牌号、品牌、所属单位查询"
|
||||
clearable
|
||||
prefix-icon="Search"
|
||||
class="search-input"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
|
||||
<el-select v-model="queryParams.status" placeholder="车辆类型:全部" clearable class="search-select">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option label="在库" value="0" />
|
||||
<el-option label="离库" value="1" />
|
||||
</el-select>
|
||||
|
||||
<div class="search-buttons">
|
||||
<el-button type="primary" class="search-btn" @click="handleQuery">搜索</el-button>
|
||||
<el-button class="reset-btn" @click="resetQuery">重置</el-button>
|
||||
</div>
|
||||
|
||||
<div class="action-buttons">
|
||||
<el-button type="primary" class="search-btn" @click="handleAdd">新增</el-button>
|
||||
<el-button class="reset-btn" plain @click="handleImport">导入</el-button>
|
||||
<el-button class="reset-btn" plain @click="handleExport">导出</el-button>
|
||||
<el-button class="export-btn" type="info" :disabled="multiple" @click="handleDelete">删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 车辆表格 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="parkList"
|
||||
@selection-change="handleSelectionChange"
|
||||
style="width: 100%"
|
||||
class="custom-table"
|
||||
:header-cell-style="{ backgroundColor: '#343744', color: '#fff' }"
|
||||
:bg-color="'#292C38'"
|
||||
>
|
||||
<el-table-column type="selection" width="50" align="left" />
|
||||
<el-table-column label="序号" width="60" align="left">
|
||||
<template #default="scope">
|
||||
{{ scope.$index + 1 }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="120" align="left">
|
||||
<template #default="scope">
|
||||
<el-button link text @click="handleUpdate(scope.row)">编辑</el-button>
|
||||
<el-button link text type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="车牌号" prop="carNo" align="left" />
|
||||
<el-table-column label="类型" prop="carType" align="left" />
|
||||
<el-table-column label="品牌" prop="carBrand" align="left" />
|
||||
|
||||
<el-table-column label="所属单位" prop="company" align="left" />
|
||||
<el-table-column label="负责人" prop="contact" align="left" />
|
||||
<el-table-column label="负责人电话" prop="phonenumber" align="left" />
|
||||
<el-table-column label="创建人" prop="creator" align="left" />
|
||||
<el-table-column label="创建时间" align="left" prop="createTime" width="160">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 添加或修改车辆对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="600px" append-to-body>
|
||||
<el-form :model="form" :rules="rules" ref="parkRef" label-width="100px">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="车牌号" prop="carNo">
|
||||
<el-input
|
||||
v-model="form.carNo"
|
||||
placeholder="请输入车牌号"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="车辆类型" prop="carType">
|
||||
<el-input
|
||||
v-model="form.carType"
|
||||
placeholder="请输入车辆类型"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="车辆品牌" prop="carBrand">
|
||||
<el-input
|
||||
v-model="form.carBrand"
|
||||
placeholder="请输入车辆品牌"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="所属单位" prop="company">
|
||||
<el-input
|
||||
v-model="form.company"
|
||||
placeholder="请输入所属单位"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="负责人" prop="contact">
|
||||
<el-input
|
||||
v-model="form.contact"
|
||||
placeholder="请输入负责人"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="负责人电话" prop="phonenumber">
|
||||
<el-input
|
||||
v-model="form.phonenumber"
|
||||
placeholder="请输入负责人电话"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="车辆图片">
|
||||
<div class="avatar-uploader-box">
|
||||
<div v-if="form.avatar" class="avatar-preview">
|
||||
<img :src="form.avatar" class="avatar" />
|
||||
<div class="avatar-count">1/1</div>
|
||||
<div class="avatar-replace" @click.stop="handleRemoveAvatar">
|
||||
<el-icon><Close /></el-icon>
|
||||
</div>
|
||||
</div>
|
||||
<el-upload
|
||||
v-else
|
||||
class="avatar-uploader"
|
||||
:show-file-list="false"
|
||||
:action="upload.avatarUrl"
|
||||
:headers="upload.headers"
|
||||
:before-upload="beforeAvatarUpload"
|
||||
:on-success="handleAvatarSuccess"
|
||||
>
|
||||
<div class="avatar-upload-placeholder">
|
||||
<el-icon class="avatar-uploader-icon"><Plus /></el-icon>
|
||||
<div class="avatar-count">0/1</div>
|
||||
</div>
|
||||
</el-upload>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button class="export-btn" @click="cancel">取 消</el-button>
|
||||
<el-button class="search-btn" type="primary" @click="submitForm">确 定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 车辆导入对话框 -->
|
||||
<el-dialog :title="upload.title" v-model="upload.open" width="500px" append-to-body class="import-dialog">
|
||||
<div class="import-title">选择需要导入的项目文件</div>
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
:limit="1"
|
||||
accept=".xlsx, .xls"
|
||||
:headers="upload.headers"
|
||||
:action="upload.url + '?updateSupport=' + upload.updateSupport"
|
||||
:disabled="upload.isUploading"
|
||||
:on-progress="handleFileUploadProgress"
|
||||
:on-success="handleFileSuccess"
|
||||
:auto-upload="false"
|
||||
drag
|
||||
class="import-upload"
|
||||
>
|
||||
<div class="upload-content">
|
||||
<el-icon class="upload-icon"><upload-filled /></el-icon>
|
||||
<div class="upload-text">拖拽文件到这里,或</div>
|
||||
<div class="upload-link">
|
||||
<el-icon class="upload-icon-small" style="color: #347AE2"><upload-filled /></el-icon>
|
||||
<span class="click-upload">点此添加</span>
|
||||
</div>
|
||||
</div>
|
||||
</el-upload>
|
||||
<div class="import-footer">
|
||||
<div class="footer-left">
|
||||
<el-checkbox v-model="upload.updateSupport">是否更新已经存在的车辆数据</el-checkbox>
|
||||
</div>
|
||||
<div class="footer-right">
|
||||
<span class="file-format">仅允许导入xls、xlsx格式文件。</span>
|
||||
<el-link type="primary" :underline="false" class="download-link" @click="importTemplate">下载模板</el-link>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button class="export-btn" @click="upload.open = false">取 消</el-button>
|
||||
<el-button class="search-btn" type="primary" @click="submitFileForm">确 定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Park">
|
||||
import { getToken } from "@/utils/auth";
|
||||
import { parseTime } from "@/utils/ruoyi";
|
||||
import { UploadFilled, Plus, Close } from '@element-plus/icons-vue';
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
const parkList = ref([]);
|
||||
const open = ref(false);
|
||||
const loading = ref(true);
|
||||
const ids = ref([]);
|
||||
const single = ref(true);
|
||||
const multiple = ref(true);
|
||||
const total = ref(0);
|
||||
const title = ref("");
|
||||
|
||||
// 模拟数据
|
||||
const mockParkData = [
|
||||
{
|
||||
id: 1,
|
||||
carNo: 'QH001',
|
||||
carType: '物流车',
|
||||
carBrand: '大众',
|
||||
company: '青岛机场物流公司',
|
||||
contact: '张三',
|
||||
phonenumber: '12345678920',
|
||||
creator: '王管理',
|
||||
createTime: '2024-04-17 10:48:30',
|
||||
carImage: ''
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
carNo: 'QH002',
|
||||
carType: '客车',
|
||||
carBrand: '金龙',
|
||||
company: '青岛机场运输公司',
|
||||
contact: '李四',
|
||||
phonenumber: '12345678921',
|
||||
creator: '王管理',
|
||||
createTime: '2024-04-17 10:48:30',
|
||||
carImage: ''
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
carNo: 'QH003',
|
||||
carType: '货车',
|
||||
carBrand: '解放',
|
||||
company: '青岛机场货运部',
|
||||
contact: '王五',
|
||||
phonenumber: '12345678922',
|
||||
creator: '王管理',
|
||||
createTime: '2024-04-17 10:48:30',
|
||||
carImage: ''
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
carNo: 'QH004',
|
||||
carType: '物流车',
|
||||
carBrand: '福特',
|
||||
company: '青岛机场物流公司',
|
||||
contact: '赵六',
|
||||
phonenumber: '12345678923',
|
||||
creator: '王管理',
|
||||
createTime: '2024-04-17 10:48:30',
|
||||
carImage: ''
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
carNo: 'QH005',
|
||||
carType: '客车',
|
||||
carBrand: '宇通',
|
||||
company: '青岛机场运输公司',
|
||||
contact: '钱七',
|
||||
phonenumber: '12345678924',
|
||||
creator: '王管理',
|
||||
createTime: '2024-04-17 10:48:30',
|
||||
carImage: ''
|
||||
}
|
||||
];
|
||||
|
||||
// 车辆导入参数
|
||||
const upload = reactive({
|
||||
open: false,
|
||||
title: "",
|
||||
isUploading: false,
|
||||
updateSupport: 0,
|
||||
headers: { Authorization: "Bearer " + getToken() },
|
||||
url: import.meta.env.VITE_APP_BASE_API + "/car/park/importData"
|
||||
});
|
||||
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
carNo: undefined,
|
||||
status: undefined
|
||||
});
|
||||
|
||||
const form = ref({});
|
||||
|
||||
const rules = ref({
|
||||
carNo: [
|
||||
{ required: true, message: "车牌号不能为空", trigger: "blur" }
|
||||
],
|
||||
carType: [
|
||||
{ required: true, message: "车型不能为空", trigger: "blur" }
|
||||
],
|
||||
company: [
|
||||
{ required: true, message: "所属公司不能为空", trigger: "blur" }
|
||||
],
|
||||
contact: [
|
||||
{ required: true, message: "联系人不能为空", trigger: "blur" }
|
||||
],
|
||||
phonenumber: [
|
||||
{ required: true, message: "联系电话不能为空", trigger: "blur" },
|
||||
{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" }
|
||||
]
|
||||
});
|
||||
|
||||
/** 查询车辆列表 */
|
||||
function getList() {
|
||||
loading.value = true;
|
||||
// 使用模拟数据
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
parkList.value = mockParkData;
|
||||
total.value = mockParkData.length;
|
||||
}, 300);
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
function handleQuery() {
|
||||
queryParams.value.pageNum = 1;
|
||||
getList();
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
function resetQuery() {
|
||||
proxy.resetForm("queryRef");
|
||||
queryParams.value.pageNum = 1;
|
||||
handleQuery();
|
||||
}
|
||||
|
||||
/** 选择条数 */
|
||||
function handleSelectionChange(selection) {
|
||||
ids.value = selection.map(item => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete(row) {
|
||||
const parkIds = row.id || ids.value;
|
||||
proxy.$modal.confirm('确定删除此车辆吗?', '删除').then(function() {
|
||||
// 模拟删除操作
|
||||
getList();
|
||||
proxy.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
}
|
||||
|
||||
/** 新增按钮操作 */
|
||||
function handleAdd() {
|
||||
reset();
|
||||
title.value = "添加车辆";
|
||||
open.value = true;
|
||||
}
|
||||
|
||||
/** 修改按钮操作 */
|
||||
function handleUpdate(row) {
|
||||
reset();
|
||||
const parkId = row.id || ids.value[0];
|
||||
// 使用模拟数据
|
||||
const parkInfo = mockParkData.find(d => d.id === parkId);
|
||||
if (parkInfo) {
|
||||
form.value = {...parkInfo};
|
||||
open.value = true;
|
||||
title.value = "修改车辆";
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
function reset() {
|
||||
form.value = {
|
||||
id: undefined,
|
||||
carNo: undefined,
|
||||
carType: undefined,
|
||||
carBrand: undefined,
|
||||
company: undefined,
|
||||
contact: undefined,
|
||||
phonenumber: undefined,
|
||||
carImage: '',
|
||||
status: "0"
|
||||
};
|
||||
proxy.resetForm("parkRef");
|
||||
}
|
||||
|
||||
/** 提交表单 */
|
||||
function submitForm() {
|
||||
proxy.$refs["parkRef"].validate(valid => {
|
||||
if (valid) {
|
||||
if (form.value.id != undefined) {
|
||||
// 模拟修改操作
|
||||
const index = mockParkData.findIndex(item => item.id === form.value.id);
|
||||
if (index !== -1) {
|
||||
mockParkData[index] = {...form.value};
|
||||
}
|
||||
proxy.$modal.msgSuccess("修改成功");
|
||||
open.value = false;
|
||||
getList();
|
||||
} else {
|
||||
// 模拟新增操作
|
||||
form.value.id = mockParkData.length + 1;
|
||||
form.value.createTime = new Date().toISOString().replace('T', ' ').substring(0, 19);
|
||||
mockParkData.push({...form.value});
|
||||
proxy.$modal.msgSuccess("新增成功");
|
||||
open.value = false;
|
||||
getList();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** 取消按钮 */
|
||||
function cancel() {
|
||||
open.value = false;
|
||||
reset();
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
function handleExport() {
|
||||
proxy.$modal.msgSuccess("导出功能已模拟");
|
||||
}
|
||||
|
||||
/** 导入按钮操作 */
|
||||
function handleImport() {
|
||||
upload.title = "车辆导入";
|
||||
upload.open = true;
|
||||
}
|
||||
|
||||
/** 导入对话框关闭时清除数据 */
|
||||
function handleFileUploadProgress(event, file, fileList) {
|
||||
upload.isUploading = true;
|
||||
}
|
||||
|
||||
/** 导入成功处理 */
|
||||
function handleFileSuccess(response, file, fileList) {
|
||||
upload.open = false;
|
||||
upload.isUploading = false;
|
||||
proxy.$refs["uploadRef"].clearFiles();
|
||||
|
||||
// 模拟导入成功
|
||||
proxy.$modal.msgSuccess("导入成功");
|
||||
mockParkData.push({
|
||||
id: mockParkData.length + 1,
|
||||
carNo: 'QH006',
|
||||
carType: '物流车',
|
||||
status: '0',
|
||||
company: '物流管理公司',
|
||||
contact: '导入用户',
|
||||
phonenumber: '12345678920',
|
||||
createTime: new Date().toISOString().replace('T', ' ').substring(0, 19)
|
||||
});
|
||||
getList();
|
||||
}
|
||||
|
||||
/** 下载导入模板 */
|
||||
function importTemplate() {
|
||||
proxy.$modal.msgSuccess("下载模板功能已模拟");
|
||||
}
|
||||
|
||||
/** 提交上传文件 */
|
||||
function submitFileForm() {
|
||||
proxy.$refs["uploadRef"].submit();
|
||||
}
|
||||
|
||||
// 添加图片上传相关方法
|
||||
const fileInput = ref(null);
|
||||
|
||||
function handleClickUpload() {
|
||||
fileInput.value.click();
|
||||
}
|
||||
|
||||
function handleFileChange(e) {
|
||||
const file = e.target.files[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
form.value.carImage = e.target.result;
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
// 清除input的value,否则选择相同文件时不会触发change事件
|
||||
e.target.value = '';
|
||||
}
|
||||
|
||||
function handleRemoveImg() {
|
||||
form.value.carImage = '';
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
background-color: #292C38;
|
||||
color: #ffffff;
|
||||
min-height: 100%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.park-container {
|
||||
background-color: #292c38;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.search-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.search-input {
|
||||
width: 250px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.search-select {
|
||||
width: 150px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.search-buttons {
|
||||
margin-right: 20px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
// 输入框 下拉框 搜索栏
|
||||
::v-deep(.el-input__wrapper:hover) {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-select) {
|
||||
border:none !important;
|
||||
width:160px !important;
|
||||
// 修改el-select的输入框的border
|
||||
--el-border-color-hover: #343744!important;
|
||||
--el-border-color: #343744!important;
|
||||
}
|
||||
|
||||
::v-deep(.el-select__wrapper.is-focused) {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-select__wrapper) {
|
||||
background: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
border-radius: 8px !important;
|
||||
height: 36px !important;
|
||||
width: 160px;
|
||||
font-size: 15px;
|
||||
border: none !important;
|
||||
border:none !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-input__wrapper) {
|
||||
background: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
border-radius: 8px !important;
|
||||
height: 36px !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-select__placeholder) {
|
||||
color: #96A0B5 !important;
|
||||
}
|
||||
.custom-table {
|
||||
background-color: #292c38 !important;
|
||||
color: #ffffff;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
|
||||
// 防止表格闪白
|
||||
:deep(.el-loading-mask) {
|
||||
background-color: rgba(41, 44, 56, 0.7) !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__empty-block) {
|
||||
background-color: #292c38 !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__empty-text) {
|
||||
color: #96A0B5 !important;
|
||||
}
|
||||
|
||||
// 确保整个表格区域背景色
|
||||
:deep(.el-table) {
|
||||
background-color: #292c38 !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
background-color: #292c38 !important;
|
||||
}
|
||||
|
||||
.avatar-box{
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 6px;
|
||||
|
||||
img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 6px;
|
||||
|
||||
}
|
||||
}
|
||||
:deep(.el-table__inner-wrapper::before) {
|
||||
display: none; /* 隐藏表格顶部的边框线 */
|
||||
}
|
||||
|
||||
:deep(.el-table__header) {
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:deep(.el-table__header-wrapper) {
|
||||
th {
|
||||
background-color: #343744 !important;
|
||||
color: #96A0B5!important;
|
||||
font-weight: normal;
|
||||
border-bottom: none; /* 移除th底部边线 */
|
||||
}
|
||||
|
||||
tr th.el-table__cell:first-child {
|
||||
border-top-left-radius: 6px;
|
||||
|
||||
.cell {
|
||||
border-top-left-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
tr th.el-table__cell:last-child {
|
||||
border-top-right-radius: 4px;
|
||||
|
||||
.cell {
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-table__header th.el-table__cell {
|
||||
background-color: #343744 !important;
|
||||
color: #96A0B5;
|
||||
}
|
||||
|
||||
tr {
|
||||
background-color: #343744 !important;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body-wrapper) {
|
||||
|
||||
td {
|
||||
height: 68px!important;
|
||||
background-color: #292c38;
|
||||
color: #ffffff;
|
||||
border-bottom: 1px solid #4C4F5F;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body tr:hover > td) {
|
||||
background: #2B3B5A!important;
|
||||
|
||||
}
|
||||
|
||||
:deep(.el-button--link) {
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: #347AE2;
|
||||
padding: 0;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
:deep(.el-button.is-text) {
|
||||
background-color: transparent !important;
|
||||
border-color: transparent;
|
||||
color: #347AE2;
|
||||
|
||||
&:hover, &:focus, &:active {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-button.el-button--primary.is-text) {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
|
||||
&:hover {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body tr:hover .el-button--link.is-text) {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
// 弹窗样式优化
|
||||
:deep(.el-dialog) {
|
||||
.el-form-item__label {
|
||||
color: #96A0B5 !important;
|
||||
}
|
||||
.el-radio__label {
|
||||
color: #C8C9CC !important;
|
||||
}
|
||||
|
||||
.el-radio.is-checked .el-radio__label {
|
||||
color: #409EFF !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 导入弹窗样式
|
||||
.import-dialog {
|
||||
:deep(.el-dialog__header) {
|
||||
margin-right: 0;
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #4C4F5F;
|
||||
}
|
||||
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
:deep(.el-dialog__footer) {
|
||||
padding: 20px;
|
||||
border-top: 1px solid #4C4F5F;
|
||||
}
|
||||
|
||||
.import-title {
|
||||
font-size: 14px;
|
||||
color: #96A0B5;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.import-upload {
|
||||
:deep(.el-upload-dragger) {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
background-color: #292C38;
|
||||
border: 1px dashed #4C4F5F;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
border-color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
color: #96A0B5;
|
||||
|
||||
.upload-icon {
|
||||
font-size: 40px;
|
||||
color: #96A0B5;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
font-size: 14px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.upload-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #347AE2;
|
||||
cursor: pointer;
|
||||
|
||||
.upload-icon-small {
|
||||
font-size: 16px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.click-upload {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.import-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 20px;
|
||||
|
||||
.footer-left {
|
||||
:deep(.el-checkbox__label) {
|
||||
color: #96A0B5;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
|
||||
.file-format {
|
||||
color: #96A0B5;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.download-link {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 头像上传样式 */
|
||||
.avatar-uploader-box {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.avatar-uploader {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.avatar-preview {
|
||||
position: relative;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 0;
|
||||
overflow: visible; /* 修改为visible,使计数器可以溢出边界 */
|
||||
|
||||
.avatar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 0;
|
||||
border: 1px solid #343744;
|
||||
}
|
||||
|
||||
.avatar-count {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: -30px;
|
||||
font-size: 14px;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.avatar-replace {
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
right: -8px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
opacity: 1;
|
||||
z-index: 2;
|
||||
|
||||
.el-icon {
|
||||
font-size: 14px;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-upload-placeholder {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border: 1px dashed #4C4F5F;
|
||||
border-radius: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s;
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
overflow: visible; /* 修改为visible,使计数器可以溢出边界 */
|
||||
|
||||
&:hover {
|
||||
border-color: #409EFF;
|
||||
}
|
||||
|
||||
.avatar-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
}
|
||||
|
||||
.avatar-count {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: -30px;
|
||||
font-size: 14px;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
@ -1,7 +1,483 @@
|
||||
<template>
|
||||
<p>车辆类型</p>
|
||||
</template>
|
||||
<script setup>
|
||||
<div class="app-container">
|
||||
<div class="type-container">
|
||||
<!-- 搜索区域 -->
|
||||
<div class="search-area">
|
||||
<el-input
|
||||
v-model="queryParams.typeName"
|
||||
placeholder="请输入类型名称查询"
|
||||
clearable
|
||||
prefix-icon="Search"
|
||||
class="search-input"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
|
||||
<div class="search-buttons">
|
||||
<el-button type="primary" class="search-btn" @click="handleQuery">搜索</el-button>
|
||||
<el-button class="reset-btn" @click="resetQuery">重置</el-button>
|
||||
</div>
|
||||
|
||||
<div class="action-buttons">
|
||||
<el-button type="primary" class="search-btn" @click="handleAdd">新增</el-button>
|
||||
<el-button class="export-btn" type="info" :disabled="multiple" @click="handleDelete">删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 类型表格 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="typeList"
|
||||
@selection-change="handleSelectionChange"
|
||||
style="width: 100%"
|
||||
class="custom-table"
|
||||
:header-cell-style="{ backgroundColor: '#343744', color: '#fff' }"
|
||||
:bg-color="'#292C38'"
|
||||
>
|
||||
<el-table-column type="selection" width="50" align="left" />
|
||||
<el-table-column label="序号" width="60" align="left">
|
||||
<template #default="scope">
|
||||
{{ scope.$index + 1 }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="120" align="left">
|
||||
<template #default="scope">
|
||||
<el-button link text @click="handleUpdate(scope.row)">编辑</el-button>
|
||||
<el-button link text type="primary" @click="handleDelete(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="类型名称" prop="typeName" align="left" />
|
||||
<el-table-column label="类型编码" prop="typeCode" align="left" />
|
||||
<el-table-column label="描述" prop="description" align="left" />
|
||||
<el-table-column label="创建人" prop="creator" align="left" />
|
||||
<el-table-column label="创建时间" align="left" prop="createTime" width="160">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 添加或修改类型对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
<el-form :model="form" :rules="rules" ref="typeRef" label-width="100px">
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="类型名称" prop="typeName">
|
||||
<el-input
|
||||
v-model="form.typeName"
|
||||
placeholder="请输入类型名称"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="类型编码" prop="typeCode">
|
||||
<el-input
|
||||
v-model="form.typeCode"
|
||||
placeholder="请输入类型编码"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="描述" prop="description">
|
||||
<el-input
|
||||
v-model="form.description"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入描述信息"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button class="export-btn" @click="cancel">取 消</el-button>
|
||||
<el-button class="search-btn" type="primary" @click="submitForm">确 定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="CarType">
|
||||
import { getCurrentInstance, ref } from 'vue';
|
||||
import { parseTime } from "@/utils/ruoyi";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
|
||||
const typeList = ref([]);
|
||||
const open = ref(false);
|
||||
const loading = ref(true);
|
||||
const ids = ref([]);
|
||||
const single = ref(true);
|
||||
const multiple = ref(true);
|
||||
const total = ref(0);
|
||||
const title = ref("");
|
||||
|
||||
// 模拟数据
|
||||
const mockTypeData = [
|
||||
{
|
||||
id: 1,
|
||||
typeName: '无人车',
|
||||
typeCode: 'WRC',
|
||||
description: '无人驾驶运输车辆',
|
||||
creator: '系统管理员',
|
||||
createTime: '2024-04-17 10:48:30'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
typeName: '客车',
|
||||
typeCode: 'KC',
|
||||
description: '载客运输车辆',
|
||||
creator: '系统管理员',
|
||||
createTime: '2024-04-17 10:48:30'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
typeName: '特种车',
|
||||
typeCode: 'TZC',
|
||||
description: '特种作业车辆',
|
||||
creator: '系统管理员',
|
||||
createTime: '2024-04-17 10:48:30'
|
||||
}
|
||||
];
|
||||
|
||||
const queryParams = ref({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
typeName: undefined
|
||||
});
|
||||
|
||||
const form = ref({});
|
||||
|
||||
const rules = ref({
|
||||
typeName: [
|
||||
{ required: true, message: "类型名称不能为空", trigger: "blur" }
|
||||
],
|
||||
typeCode: [
|
||||
{ required: true, message: "类型编码不能为空", trigger: "blur" }
|
||||
]
|
||||
});
|
||||
|
||||
/** 查询类型列表 */
|
||||
function getList() {
|
||||
loading.value = true;
|
||||
// 使用模拟数据
|
||||
setTimeout(() => {
|
||||
loading.value = false;
|
||||
typeList.value = mockTypeData;
|
||||
total.value = mockTypeData.length;
|
||||
}, 300);
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
function handleQuery() {
|
||||
queryParams.value.pageNum = 1;
|
||||
getList();
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
function resetQuery() {
|
||||
proxy.resetForm("queryRef");
|
||||
queryParams.value.pageNum = 1;
|
||||
handleQuery();
|
||||
}
|
||||
|
||||
/** 选择条数 */
|
||||
function handleSelectionChange(selection) {
|
||||
ids.value = selection.map(item => item.id);
|
||||
single.value = selection.length != 1;
|
||||
multiple.value = !selection.length;
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete(row) {
|
||||
const typeIds = row.id || ids.value;
|
||||
proxy.$modal.confirm('确定删除此类型吗?', '删除').then(function() {
|
||||
// 模拟删除操作
|
||||
getList();
|
||||
proxy.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
}
|
||||
|
||||
/** 新增按钮操作 */
|
||||
function handleAdd() {
|
||||
reset();
|
||||
title.value = "添加车辆类型";
|
||||
open.value = true;
|
||||
}
|
||||
|
||||
/** 修改按钮操作 */
|
||||
function handleUpdate(row) {
|
||||
reset();
|
||||
const typeId = row.id || ids.value[0];
|
||||
// 使用模拟数据
|
||||
const typeInfo = mockTypeData.find(d => d.id === typeId);
|
||||
if (typeInfo) {
|
||||
form.value = {...typeInfo};
|
||||
open.value = true;
|
||||
title.value = "修改车辆类型";
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
function reset() {
|
||||
form.value = {
|
||||
id: undefined,
|
||||
typeName: undefined,
|
||||
typeCode: undefined,
|
||||
description: undefined
|
||||
};
|
||||
proxy.resetForm("typeRef");
|
||||
}
|
||||
|
||||
/** 提交表单 */
|
||||
function submitForm() {
|
||||
proxy.$refs["typeRef"].validate(valid => {
|
||||
if (valid) {
|
||||
if (form.value.id != undefined) {
|
||||
// 模拟修改操作
|
||||
const index = mockTypeData.findIndex(item => item.id === form.value.id);
|
||||
if (index !== -1) {
|
||||
mockTypeData[index] = {...form.value};
|
||||
}
|
||||
proxy.$modal.msgSuccess("修改成功");
|
||||
open.value = false;
|
||||
getList();
|
||||
} else {
|
||||
// 模拟新增操作
|
||||
form.value.id = mockTypeData.length + 1;
|
||||
form.value.createTime = new Date().toISOString().replace('T', ' ').substring(0, 19);
|
||||
form.value.creator = '系统管理员';
|
||||
mockTypeData.push({...form.value});
|
||||
proxy.$modal.msgSuccess("新增成功");
|
||||
open.value = false;
|
||||
getList();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** 取消按钮 */
|
||||
function cancel() {
|
||||
open.value = false;
|
||||
reset();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
background-color: #292C38;
|
||||
color: #ffffff;
|
||||
min-height: 100%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.type-container {
|
||||
background-color: #292c38;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.search-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.search-input {
|
||||
width: 250px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.search-buttons {
|
||||
margin-right: 20px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
// 输入框 下拉框 搜索栏
|
||||
::v-deep(.el-input__wrapper:hover) {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-input__wrapper) {
|
||||
background: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
border-radius: 8px !important;
|
||||
height: 36px !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.custom-table {
|
||||
background-color: #292c38 !important;
|
||||
color: #ffffff;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
|
||||
// 防止表格闪白
|
||||
:deep(.el-loading-mask) {
|
||||
background-color: rgba(41, 44, 56, 0.7) !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__empty-block) {
|
||||
background-color: #292c38 !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__empty-text) {
|
||||
color: #96A0B5 !important;
|
||||
}
|
||||
|
||||
// 确保整个表格区域背景色
|
||||
:deep(.el-table) {
|
||||
background-color: #292c38 !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
background-color: #292c38 !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__inner-wrapper::before) {
|
||||
display: none; /* 隐藏表格顶部的边框线 */
|
||||
}
|
||||
|
||||
:deep(.el-table__header) {
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:deep(.el-table__header-wrapper) {
|
||||
th {
|
||||
background-color: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
font-weight: normal;
|
||||
border-bottom: none; /* 移除th底部边线 */
|
||||
}
|
||||
|
||||
tr th.el-table__cell:first-child {
|
||||
border-top-left-radius: 6px;
|
||||
|
||||
.cell {
|
||||
border-top-left-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
tr th.el-table__cell:last-child {
|
||||
border-top-right-radius: 4px;
|
||||
|
||||
.cell {
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-table__header th.el-table__cell {
|
||||
background-color: #343744 !important;
|
||||
color: #96A0B5;
|
||||
}
|
||||
|
||||
tr {
|
||||
background-color: #343744 !important;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body-wrapper) {
|
||||
td {
|
||||
height: 68px!important;
|
||||
background-color: #292c38;
|
||||
color: #ffffff;
|
||||
border-bottom: 1px solid #4C4F5F;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body tr:hover > td) {
|
||||
background: #2B3B5A!important;
|
||||
}
|
||||
|
||||
:deep(.el-button--link) {
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: #347AE2;
|
||||
padding: 0;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
:deep(.el-button.is-text) {
|
||||
background-color: transparent !important;
|
||||
border-color: transparent;
|
||||
color: #347AE2;
|
||||
|
||||
&:hover, &:focus, &:active {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-button.el-button--primary.is-text) {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
|
||||
&:hover {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body tr:hover .el-button--link.is-text) {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
// 弹窗样式优化
|
||||
:deep(.el-dialog) {
|
||||
.el-form-item__label {
|
||||
color: #96A0B5 !important;
|
||||
}
|
||||
|
||||
.el-input__wrapper {
|
||||
background-color: #292c38 !important;
|
||||
box-shadow: 0 0 0 1px #565C70 inset !important;
|
||||
|
||||
.el-input__inner {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-textarea__inner {
|
||||
background-color: #292c38 !important;
|
||||
border-color: #565C70 !important;
|
||||
color: #ffffff !important;
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 1px #409EFF inset !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@ -1,456 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 车辆状态卡片 -->
|
||||
<div class="status-cards">
|
||||
<el-card class="status-card online" shadow="hover">
|
||||
<div class="card-header">
|
||||
<div class="card-title">在线</div>
|
||||
<div class="card-value">{{ statistics.online }}</div>
|
||||
</div>
|
||||
<div class="card-indicator">
|
||||
<span class="percentage">+30%</span>
|
||||
<i class="el-icon-arrow-up"></i>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card class="status-card task" shadow="hover">
|
||||
<div class="card-header">
|
||||
<div class="card-title">任务中</div>
|
||||
<div class="card-value">{{ statistics.inTask }}</div>
|
||||
</div>
|
||||
<div class="card-indicator">
|
||||
<span class="percentage">+20%</span>
|
||||
<i class="el-icon-arrow-up"></i>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card class="status-card error" shadow="hover">
|
||||
<div class="card-header">
|
||||
<div class="card-title">故障</div>
|
||||
<div class="card-value">{{ statistics.error }}</div>
|
||||
</div>
|
||||
<div class="card-indicator">
|
||||
<span class="percentage">-10%</span>
|
||||
<i class="el-icon-arrow-down"></i>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card class="status-card offline" shadow="hover">
|
||||
<div class="card-header">
|
||||
<div class="card-title">离线</div>
|
||||
<div class="card-value">{{ statistics.offline }}</div>
|
||||
</div>
|
||||
<div class="card-indicator">
|
||||
<span class="percentage">-5%</span>
|
||||
<i class="el-icon-arrow-down"></i>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
|
||||
<!-- 搜索栏 -->
|
||||
<div class="search-bar">
|
||||
<div class="search-input">
|
||||
<el-input
|
||||
v-model="searchQuery"
|
||||
placeholder="请输入车辆号或者司机"
|
||||
prefix-icon="Search"
|
||||
@keyup.enter="handleSearch"
|
||||
>
|
||||
</el-input>
|
||||
</div>
|
||||
|
||||
<el-select v-model="vehicleState" placeholder="车辆状态" class="search-select">
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="在线" value="online"></el-option>
|
||||
<el-option label="离线" value="offline"></el-option>
|
||||
<el-option label="故障" value="error"></el-option>
|
||||
</el-select>
|
||||
|
||||
<el-select v-model="operationState" placeholder="运行状态" class="search-select">
|
||||
<el-option label="全部" value=""></el-option>
|
||||
<el-option label="任务中" value="running"></el-option>
|
||||
<el-option label="空闲中" value="idle"></el-option>
|
||||
<el-option label="充电中" value="charging"></el-option>
|
||||
<el-option label="维保中" value="maintenance"></el-option>
|
||||
</el-select>
|
||||
|
||||
<div class="search-buttons">
|
||||
<el-button type="primary" @click="handleSearch">搜索</el-button>
|
||||
<el-button @click="resetSearch">重置</el-button>
|
||||
</div>
|
||||
|
||||
<div class="view-buttons">
|
||||
<el-button :icon="List"></el-button>
|
||||
<el-button :icon="Grid"></el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 车辆表格 -->
|
||||
<el-table
|
||||
:data="vehicleList"
|
||||
border
|
||||
stripe
|
||||
style="width: 100%"
|
||||
@selection-change="handleSelectionChange"
|
||||
:header-cell-style="{background:'#292c38',color:'#fff'}"
|
||||
>
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="id" label="序号" width="80" />
|
||||
<el-table-column prop="name" label="车辆" width="100">
|
||||
<template #default="scope">
|
||||
<span class="vehicle-link">{{ scope.row.name }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="vehicleNo" label="车辆号" width="100" />
|
||||
<el-table-column prop="driverName" label="驾驶员" width="100" />
|
||||
<el-table-column prop="vehicleType" label="特性值" width="100" />
|
||||
<el-table-column prop="company" label="所属管理公司" width="150" />
|
||||
<el-table-column prop="seats" label="座位数" width="80" />
|
||||
<el-table-column prop="taskStatus" label="任务状态" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getTaskStatusType(scope.row.taskStatus)">{{ scope.row.taskStatus }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="runStatus" label="在线状态" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getRunStatusType(scope.row.runStatus)">{{ scope.row.runStatus }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="parkStatus" label="停车状态" width="100" />
|
||||
<el-table-column prop="voltage" label="电压" width="100" />
|
||||
<el-table-column prop="current" label="电流" width="100" />
|
||||
<el-table-column prop="battery" label="电量" width="100" />
|
||||
<el-table-column prop="updateTime" label="数据更新时间" width="180" />
|
||||
<el-table-column prop="temperature" label="T3机器" width="100" />
|
||||
<el-table-column prop="status" label="状态" width="80" />
|
||||
<el-table-column prop="deviceId" label="设备标识码" width="150" />
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination-container">
|
||||
<el-pagination
|
||||
v-model:currentPage="currentPage"
|
||||
v-model:page-size="pageSize"
|
||||
:page-sizes="[10, 20, 30, 50]"
|
||||
layout="total, prev, pager, next, jumper"
|
||||
:total="total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
background
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="CarMonitor">
|
||||
import { ref, onMounted, reactive } from 'vue';
|
||||
import { Search, List, Grid } from '@element-plus/icons-vue';
|
||||
|
||||
// 统计数据
|
||||
const statistics = reactive({
|
||||
online: 85,
|
||||
inTask: 57,
|
||||
error: 4,
|
||||
offline: 12
|
||||
});
|
||||
|
||||
// 搜索条件
|
||||
const searchQuery = ref('');
|
||||
const vehicleState = ref('');
|
||||
const operationState = ref('');
|
||||
|
||||
// 分页参数
|
||||
const currentPage = ref(1);
|
||||
const pageSize = ref(10);
|
||||
const total = ref(100);
|
||||
|
||||
// 表格数据
|
||||
const vehicleList = ref([
|
||||
{
|
||||
id: 1,
|
||||
name: '蓝奇',
|
||||
vehicleNo: 'QN001',
|
||||
driverName: '驾驶员1',
|
||||
vehicleType: '电动',
|
||||
company: '青岛管理公司',
|
||||
seats: 3,
|
||||
taskStatus: '任务中',
|
||||
runStatus: '在线',
|
||||
parkStatus: '停车充电',
|
||||
voltage: '360V',
|
||||
current: '200A',
|
||||
battery: '90%',
|
||||
updateTime: '2023-06-17 15:48:30',
|
||||
temperature: '正常',
|
||||
status: '正常',
|
||||
deviceId: '123456789001'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: '蓝奇',
|
||||
vehicleNo: 'QN002',
|
||||
driverName: '驾驶员2',
|
||||
vehicleType: '电动',
|
||||
company: '青岛管理公司',
|
||||
seats: 3,
|
||||
taskStatus: '任务中',
|
||||
runStatus: '在线',
|
||||
parkStatus: '停车充电',
|
||||
voltage: '360V',
|
||||
current: '200A',
|
||||
battery: '85%',
|
||||
updateTime: '2023-06-17 15:45:30',
|
||||
temperature: '正常',
|
||||
status: '正常',
|
||||
deviceId: '123456789002'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: '蓝奇',
|
||||
vehicleNo: 'QN003',
|
||||
driverName: '驾驶员3',
|
||||
vehicleType: '电动',
|
||||
company: '青岛管理公司',
|
||||
seats: 3,
|
||||
taskStatus: '任务中',
|
||||
runStatus: '在线',
|
||||
parkStatus: '停车充电',
|
||||
voltage: '360V',
|
||||
current: '200A',
|
||||
battery: '75%',
|
||||
updateTime: '2023-06-17 15:40:30',
|
||||
temperature: '正常',
|
||||
status: '正常',
|
||||
deviceId: '123456789003'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: '蓝奇',
|
||||
vehicleNo: 'QN004',
|
||||
driverName: '驾驶员4',
|
||||
vehicleType: '电动',
|
||||
company: '青岛管理公司',
|
||||
seats: 3,
|
||||
taskStatus: '闲置中',
|
||||
runStatus: '离线',
|
||||
parkStatus: '停车充电',
|
||||
voltage: '360V',
|
||||
current: '200A',
|
||||
battery: '95%',
|
||||
updateTime: '2023-06-17 15:30:30',
|
||||
temperature: '正常',
|
||||
status: '正常',
|
||||
deviceId: '123456789004'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: '蓝奇',
|
||||
vehicleNo: 'QN005',
|
||||
driverName: '驾驶员5',
|
||||
vehicleType: '电动',
|
||||
company: '青岛管理公司',
|
||||
seats: 3,
|
||||
taskStatus: '闲置中',
|
||||
runStatus: '离线',
|
||||
parkStatus: '停车充电',
|
||||
voltage: '360V',
|
||||
current: '200A',
|
||||
battery: '100%',
|
||||
updateTime: '2023-06-17 15:20:30',
|
||||
temperature: '正常',
|
||||
status: '正常',
|
||||
deviceId: '123456789005'
|
||||
}
|
||||
]);
|
||||
|
||||
// 选中的行
|
||||
const selectedRows = ref([]);
|
||||
|
||||
// 方法
|
||||
function handleSearch() {
|
||||
// 实际应用中这里会调用API获取数据
|
||||
console.log('Search with:', {
|
||||
query: searchQuery.value,
|
||||
vehicleState: vehicleState.value,
|
||||
operationState: operationState.value
|
||||
});
|
||||
// 重置到第一页
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
function resetSearch() {
|
||||
searchQuery.value = '';
|
||||
vehicleState.value = '';
|
||||
operationState.value = '';
|
||||
handleSearch();
|
||||
}
|
||||
|
||||
function handleSelectionChange(selection) {
|
||||
selectedRows.value = selection;
|
||||
}
|
||||
|
||||
function handleSizeChange(val) {
|
||||
pageSize.value = val;
|
||||
// 实际应用中这里会重新获取数据
|
||||
}
|
||||
|
||||
function handleCurrentChange(val) {
|
||||
currentPage.value = val;
|
||||
// 实际应用中这里会重新获取数据
|
||||
}
|
||||
|
||||
function getTaskStatusType(status) {
|
||||
if (status === '任务中') return 'success';
|
||||
if (status === '闲置中') return 'warning';
|
||||
if (status === '等待中') return 'info';
|
||||
return 'info';
|
||||
}
|
||||
|
||||
function getRunStatusType(status) {
|
||||
if (status === '在线') return 'success';
|
||||
if (status === '离线') return 'warning';
|
||||
if (status === '故障') return 'danger';
|
||||
return 'info';
|
||||
}
|
||||
|
||||
// 加载初始数据
|
||||
onMounted(() => {
|
||||
// 实际应用中这里会调用API获取数据
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
background-color: #1e2028;
|
||||
color: #ffffff;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.status-cards {
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
gap: 20px;
|
||||
|
||||
.status-card {
|
||||
flex: 1;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
background-color: #292c38;
|
||||
border: none;
|
||||
|
||||
&.online {
|
||||
.card-header {
|
||||
border-bottom: 2px solid #67c23a;
|
||||
}
|
||||
}
|
||||
|
||||
&.task {
|
||||
.card-header {
|
||||
border-bottom: 2px solid #409eff;
|
||||
}
|
||||
}
|
||||
|
||||
&.error {
|
||||
.card-header {
|
||||
border-bottom: 2px solid #f56c6c;
|
||||
}
|
||||
}
|
||||
|
||||
&.offline {
|
||||
.card-header {
|
||||
border-bottom: 2px solid #e6a23c;
|
||||
}
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-bottom: 10px;
|
||||
|
||||
.card-title {
|
||||
font-size: 14px;
|
||||
color: #96a0b5;
|
||||
}
|
||||
|
||||
.card-value {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.card-indicator {
|
||||
font-size: 12px;
|
||||
margin-top: 10px;
|
||||
color: #67c23a;
|
||||
|
||||
.percentage {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
gap: 15px;
|
||||
align-items: center;
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.search-select {
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.search-buttons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.view-buttons {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table) {
|
||||
background-color: #292c38;
|
||||
color: #fff;
|
||||
|
||||
.el-table__header-wrapper th {
|
||||
background-color: #292c38;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.el-table__row {
|
||||
background-color: #292c38;
|
||||
&:hover > td {
|
||||
background-color: #363945 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-table__row--striped td {
|
||||
background-color: #1e2028;
|
||||
}
|
||||
}
|
||||
|
||||
// .pagination-container {
|
||||
// display: flex;
|
||||
// justify-content: flex-end;
|
||||
// margin-top: 20px;
|
||||
// }
|
||||
|
||||
.vehicle-link {
|
||||
color: #409eff;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -131,7 +131,7 @@
|
||||
|
||||
<!-- 添加或修改参数配置对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
<el-form ref="configRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form ref="configRef" :model="form" :rules="rules" >
|
||||
<el-form-item label="参数名称" prop="configName">
|
||||
<el-input v-model="form.configName" placeholder="请输入参数名称" />
|
||||
</el-form-item>
|
||||
|
||||
@ -1,274 +0,0 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch">
|
||||
<el-form-item label="部门名称" prop="deptName">
|
||||
<el-input
|
||||
v-model="queryParams.deptName"
|
||||
placeholder="请输入部门名称"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="queryParams.status" placeholder="部门状态" clearable style="width: 200px">
|
||||
<el-option
|
||||
v-for="dict in sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</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 :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="Plus"
|
||||
@click="handleAdd"
|
||||
v-hasPermi="['system:dept:add']"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="info"
|
||||
plain
|
||||
icon="Sort"
|
||||
@click="toggleExpandAll"
|
||||
>展开/折叠</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<el-table
|
||||
v-if="refreshTable"
|
||||
v-loading="loading"
|
||||
:data="deptList"
|
||||
row-key="deptId"
|
||||
:default-expand-all="isExpandAll"
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
>
|
||||
<el-table-column prop="deptName" label="部门名称" width="260"></el-table-column>
|
||||
<el-table-column prop="orderNum" label="排序" width="200"></el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="100">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="sys_normal_disable" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="200">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:dept:edit']">修改</el-button>
|
||||
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['system:dept:add']">新增</el-button>
|
||||
<el-button v-if="scope.row.parentId != 0" link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:dept:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 添加或修改部门对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="600px" append-to-body>
|
||||
<el-form ref="deptRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-row>
|
||||
<el-col :span="24" v-if="form.parentId !== 0">
|
||||
<el-form-item label="上级部门" prop="parentId">
|
||||
<el-tree-select
|
||||
v-model="form.parentId"
|
||||
:data="deptOptions"
|
||||
:props="{ value: 'deptId', label: 'deptName', children: 'children' }"
|
||||
value-key="deptId"
|
||||
placeholder="选择上级部门"
|
||||
check-strictly
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="部门名称" prop="deptName">
|
||||
<el-input v-model="form.deptName" placeholder="请输入部门名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="显示排序" prop="orderNum">
|
||||
<el-input-number v-model="form.orderNum" controls-position="right" :min="0" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="负责人" prop="leader">
|
||||
<el-input v-model="form.leader" placeholder="请输入负责人" maxlength="20" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="联系电话" prop="phone">
|
||||
<el-input v-model="form.phone" placeholder="请输入联系电话" maxlength="11" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="部门状态">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio
|
||||
v-for="dict in sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{ dict.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="Dept">
|
||||
import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from "@/api/system/dept";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
|
||||
|
||||
const deptList = ref([]);
|
||||
const open = ref(false);
|
||||
const loading = ref(true);
|
||||
const showSearch = ref(true);
|
||||
const title = ref("");
|
||||
const deptOptions = ref([]);
|
||||
const isExpandAll = ref(true);
|
||||
const refreshTable = ref(true);
|
||||
|
||||
const data = reactive({
|
||||
form: {},
|
||||
queryParams: {
|
||||
deptName: undefined,
|
||||
status: undefined
|
||||
},
|
||||
rules: {
|
||||
parentId: [{ required: true, message: "上级部门不能为空", trigger: "blur" }],
|
||||
deptName: [{ required: true, message: "部门名称不能为空", trigger: "blur" }],
|
||||
orderNum: [{ required: true, message: "显示排序不能为空", trigger: "blur" }],
|
||||
email: [{ type: "email", message: "请输入正确的邮箱地址", trigger: ["blur", "change"] }],
|
||||
phone: [{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" }]
|
||||
},
|
||||
});
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
|
||||
/** 查询部门列表 */
|
||||
function getList() {
|
||||
loading.value = true;
|
||||
listDept(queryParams.value).then(response => {
|
||||
deptList.value = proxy.handleTree(response.data, "deptId");
|
||||
loading.value = false;
|
||||
});
|
||||
}
|
||||
/** 取消按钮 */
|
||||
function cancel() {
|
||||
open.value = false;
|
||||
reset();
|
||||
}
|
||||
/** 表单重置 */
|
||||
function reset() {
|
||||
form.value = {
|
||||
deptId: undefined,
|
||||
parentId: undefined,
|
||||
deptName: undefined,
|
||||
orderNum: 0,
|
||||
leader: undefined,
|
||||
phone: undefined,
|
||||
email: undefined,
|
||||
status: "0"
|
||||
};
|
||||
proxy.resetForm("deptRef");
|
||||
}
|
||||
/** 搜索按钮操作 */
|
||||
function handleQuery() {
|
||||
getList();
|
||||
}
|
||||
/** 重置按钮操作 */
|
||||
function resetQuery() {
|
||||
proxy.resetForm("queryRef");
|
||||
handleQuery();
|
||||
}
|
||||
/** 新增按钮操作 */
|
||||
function handleAdd(row) {
|
||||
reset();
|
||||
listDept().then(response => {
|
||||
deptOptions.value = proxy.handleTree(response.data, "deptId");
|
||||
});
|
||||
if (row != undefined) {
|
||||
form.value.parentId = row.deptId;
|
||||
}
|
||||
open.value = true;
|
||||
title.value = "添加部门";
|
||||
}
|
||||
/** 展开/折叠操作 */
|
||||
function toggleExpandAll() {
|
||||
refreshTable.value = false;
|
||||
isExpandAll.value = !isExpandAll.value;
|
||||
nextTick(() => {
|
||||
refreshTable.value = true;
|
||||
});
|
||||
}
|
||||
/** 修改按钮操作 */
|
||||
function handleUpdate(row) {
|
||||
reset();
|
||||
listDeptExcludeChild(row.deptId).then(response => {
|
||||
deptOptions.value = proxy.handleTree(response.data, "deptId");
|
||||
});
|
||||
getDept(row.deptId).then(response => {
|
||||
form.value = response.data;
|
||||
open.value = true;
|
||||
title.value = "修改部门";
|
||||
});
|
||||
}
|
||||
/** 提交按钮 */
|
||||
function submitForm() {
|
||||
proxy.$refs["deptRef"].validate(valid => {
|
||||
if (valid) {
|
||||
if (form.value.deptId != undefined) {
|
||||
updateDept(form.value).then(response => {
|
||||
proxy.$modal.msgSuccess("修改成功");
|
||||
open.value = false;
|
||||
getList();
|
||||
});
|
||||
} else {
|
||||
addDept(form.value).then(response => {
|
||||
proxy.$modal.msgSuccess("新增成功");
|
||||
open.value = false;
|
||||
getList();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete(row) {
|
||||
proxy.$modal.confirm('是否确认删除名称为"' + row.deptName + '"的数据项?').then(function() {
|
||||
return delDept(row.deptId);
|
||||
}).then(() => {
|
||||
getList();
|
||||
proxy.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
}
|
||||
|
||||
getList();
|
||||
</script>
|
||||
@ -126,7 +126,7 @@
|
||||
|
||||
<!-- 添加或修改参数配置对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
<el-form ref="dataRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form ref="dataRef" :model="form" :rules="rules" >
|
||||
<el-form-item label="字典类型">
|
||||
<el-input v-model="form.dictType" :disabled="true" />
|
||||
</el-form-item>
|
||||
|
||||
@ -141,7 +141,7 @@
|
||||
|
||||
<!-- 添加或修改参数配置对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
<el-form ref="dictRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form ref="dictRef" :model="form" :rules="rules" >
|
||||
<el-form-item label="字典名称" prop="dictName">
|
||||
<el-input v-model="form.dictName" placeholder="请输入字典名称" />
|
||||
</el-form-item>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -111,7 +111,7 @@
|
||||
|
||||
<!-- 添加或修改公告对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="780px" append-to-body>
|
||||
<el-form ref="noticeRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form ref="noticeRef" :model="form" :rules="rules" >
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="公告标题" prop="noticeTitle">
|
||||
|
||||
@ -1,138 +1,82 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
|
||||
<el-form-item label="系统模块" prop="title">
|
||||
<el-input
|
||||
v-model="queryParams.title"
|
||||
placeholder="请输入系统模块"
|
||||
clearable
|
||||
style="width: 240px;"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作人员" prop="operName">
|
||||
<el-input
|
||||
v-model="queryParams.operName"
|
||||
placeholder="请输入操作人员"
|
||||
clearable
|
||||
style="width: 240px;"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="businessType">
|
||||
<el-select
|
||||
v-model="queryParams.businessType"
|
||||
placeholder="操作类型"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in sys_oper_type"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="操作状态"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in sys_common_status"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作时间" style="width: 308px">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
></el-date-picker>
|
||||
</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>
|
||||
<div class="operlog-container">
|
||||
<!-- 搜索区域 -->
|
||||
<div class="search-area">
|
||||
<el-input
|
||||
v-model="queryParams.title"
|
||||
placeholder="请输入系统模块"
|
||||
clearable
|
||||
prefix-icon="Search"
|
||||
class="search-input"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
|
||||
|
||||
|
||||
<div class="search-buttons">
|
||||
<el-button type="primary" class="search-btn" @click="handleQuery">搜索</el-button>
|
||||
<el-button class="reset-btn" @click="resetQuery">重置</el-button>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
v-hasPermi="['monitor:operlog:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
@click="handleClean"
|
||||
v-hasPermi="['monitor:operlog:remove']"
|
||||
>清空</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="Download"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['monitor:operlog:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
<!-- 操作日志表格 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="operlogList"
|
||||
style="width: 100%"
|
||||
class="custom-table"
|
||||
:default-sort="defaultSort"
|
||||
@sort-change="handleSortChange"
|
||||
>
|
||||
|
||||
<el-table-column label="序号" width="60" align="left">
|
||||
<template #default="scope">
|
||||
{{ (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1 }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="left" width="120">
|
||||
<template #default="scope">
|
||||
<el-button link text @click="handleView(scope.row)" v-hasPermi="['monitor:operlog:query']">详细</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="日志编号" align="left" prop="operId" />
|
||||
<el-table-column label="系统模块" align="left" prop="title" />
|
||||
<el-table-column label="操作类型" align="left" prop="businessType">
|
||||
<template #default="scope">
|
||||
<span class="dict-text">{{ typeFormat(scope.row) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="请求方式" align="left" prop="requestMethod" />
|
||||
<el-table-column label="操作人员" align="left" prop="operName" />
|
||||
<el-table-column label="主机" align="left" prop="operIp" width="130" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="操作状态" align="left" prop="status">
|
||||
<template #default="scope">
|
||||
<div class="status-item" :class="{'status-success': scope.row.status === 0}">
|
||||
<span v-if="scope.row.status === 0" class="status-dot"></span>
|
||||
<span class="status-text">{{ statusFormat(scope.row) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作日期" align="left" prop="operTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.operTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
<el-table ref="operlogRef" v-loading="loading" :data="operlogList" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="日志编号" align="center" prop="operId" />
|
||||
<el-table-column label="系统模块" align="center" prop="title" />
|
||||
<el-table-column label="操作类型" align="center" prop="businessType">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="sys_oper_type" :value="scope.row.businessType" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="请求方式" align="center" prop="requestMethod" />
|
||||
<el-table-column label="操作人员" align="center" prop="operName" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" width="100" />
|
||||
<el-table-column label="主机" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="操作状态" align="center" prop="status">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="sys_common_status" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作日期" align="center" prop="operTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.operTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" icon="View" @click="handleView(scope.row, scope.index)" v-hasPermi="['monitor:operlog:query']">详细</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<!-- 分页组件 -->
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 操作日志详细 -->
|
||||
<el-dialog title="操作日志详细" v-model="open" width="700px" append-to-body>
|
||||
@ -159,7 +103,10 @@
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="操作状态:">
|
||||
<div v-if="form.status === 0">正常</div>
|
||||
<div v-if="form.status === 0" class="status-item status-success">
|
||||
<span class="status-dot"></span>
|
||||
<span class="status-text">成功</span>
|
||||
</div>
|
||||
<div v-else-if="form.status === 1">失败</div>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -173,14 +120,14 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="open = false">关 闭</el-button>
|
||||
<el-button class="export-btn" @click="open = false">关 闭</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="systemOperlog">
|
||||
<script setup name="SystemOperlogIndex">
|
||||
import { list, delOperlog, cleanOperlog } from "@/api/monitor/operlog";
|
||||
|
||||
const { proxy } = getCurrentInstance();
|
||||
@ -190,9 +137,7 @@ const operlogList = ref([]);
|
||||
const open = ref(false);
|
||||
const loading = ref(true);
|
||||
const showSearch = ref(true);
|
||||
const ids = ref([]);
|
||||
const single = ref(true);
|
||||
const multiple = ref(true);
|
||||
const total = ref(0);
|
||||
const title = ref("");
|
||||
const dateRange = ref([]);
|
||||
@ -225,6 +170,10 @@ function getList() {
|
||||
function typeFormat(row, column) {
|
||||
return proxy.selectDictLabel(sys_oper_type.value, row.businessType);
|
||||
}
|
||||
/** 操作状态字典翻译 */
|
||||
function statusFormat(row, column) {
|
||||
return proxy.selectDictLabel(sys_common_status.value, row.status);
|
||||
}
|
||||
/** 搜索按钮操作 */
|
||||
function handleQuery() {
|
||||
queryParams.value.pageNum = 1;
|
||||
@ -235,15 +184,10 @@ function resetQuery() {
|
||||
dateRange.value = [];
|
||||
proxy.resetForm("queryRef");
|
||||
queryParams.value.pageNum = 1;
|
||||
proxy.$refs["operlogRef"].sort(defaultSort.value.prop, defaultSort.value.order);
|
||||
}
|
||||
/** 多选框选中数据 */
|
||||
function handleSelectionChange(selection) {
|
||||
ids.value = selection.map(item => item.operId);
|
||||
multiple.value = !selection.length;
|
||||
getList();
|
||||
}
|
||||
/** 排序触发事件 */
|
||||
function handleSortChange(column, prop, order) {
|
||||
function handleSortChange(column) {
|
||||
queryParams.value.orderByColumn = column.prop;
|
||||
queryParams.value.isAsc = column.order;
|
||||
getList();
|
||||
@ -255,7 +199,7 @@ function handleView(row) {
|
||||
}
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete(row) {
|
||||
const operIds = row.operId || ids.value;
|
||||
const operIds = row.operId;
|
||||
proxy.$modal.confirm('是否确认删除日志编号为"' + operIds + '"的数据项?').then(function () {
|
||||
return delOperlog(operIds);
|
||||
}).then(() => {
|
||||
@ -276,8 +220,221 @@ function handleClean() {
|
||||
function handleExport() {
|
||||
proxy.download("monitor/operlog/export",{
|
||||
...queryParams.value,
|
||||
}, `config_${new Date().getTime()}.xlsx`);
|
||||
}, `operlog_${new Date().getTime()}.xlsx`);
|
||||
}
|
||||
|
||||
getList();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
background-color: #292C38;
|
||||
color: #ffffff;
|
||||
min-height: 100%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.operlog-container {
|
||||
background-color: #292c38;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.search-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.search-input {
|
||||
width: 250px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.search-select {
|
||||
width: 150px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.search-buttons {
|
||||
margin-right: 20px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
// 输入框 下拉框 搜索栏
|
||||
::v-deep(.el-input__wrapper:hover) {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-select) {
|
||||
border: none !important;
|
||||
width: 140px !important;
|
||||
// 修改el-select的输入框的border
|
||||
--el-border-color-hover: #343744 !important;
|
||||
--el-border-color: #343744 !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-select__wrapper.is-focused) {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-select__wrapper) {
|
||||
background: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
border-radius: 8px !important;
|
||||
height: 36px !important;
|
||||
width: 140px;
|
||||
font-size: 15px;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-input__wrapper) {
|
||||
background: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
border-radius: 8px !important;
|
||||
height: 36px !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-select__placeholder) {
|
||||
color: #96A0B5 !important;
|
||||
}
|
||||
|
||||
.custom-table {
|
||||
background-color: #292c38;
|
||||
color: #ffffff;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
|
||||
:deep(.el-table__inner-wrapper::before) {
|
||||
display: none; /* 隐藏表格顶部的边框线 */
|
||||
}
|
||||
|
||||
:deep(.el-table__header) {
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:deep(.el-table__header-wrapper) {
|
||||
th {
|
||||
background-color: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
font-weight: normal;
|
||||
border-bottom: none; /* 移除th底部边线 */
|
||||
}
|
||||
|
||||
tr th.el-table__cell:first-child {
|
||||
border-top-left-radius: 6px;
|
||||
|
||||
.cell {
|
||||
border-top-left-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
tr th.el-table__cell:last-child {
|
||||
border-top-right-radius: 4px;
|
||||
|
||||
.cell {
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-table__header th.el-table__cell {
|
||||
background-color: #343744 !important;
|
||||
color: #96A0B5;
|
||||
}
|
||||
|
||||
tr {
|
||||
background-color: #343744 !important;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body-wrapper) {
|
||||
td {
|
||||
height: 68px!important;
|
||||
background-color: #292c38;
|
||||
color: #ffffff;
|
||||
border-bottom: 1px solid #4C4F5F;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body tr:hover > td) {
|
||||
background: #2B3B5A!important;
|
||||
}
|
||||
|
||||
:deep(.el-button--link) {
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: #347AE2;
|
||||
padding: 0;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
:deep(.el-button.is-text) {
|
||||
background-color: transparent !important;
|
||||
border-color: transparent;
|
||||
color: #347AE2;
|
||||
|
||||
&:hover, &:focus, &:active {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-button.el-button--primary.is-text) {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
|
||||
&:hover {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body tr:hover .el-button--link.is-text) {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
// 字典文本样式
|
||||
.dict-text {
|
||||
display: inline-block;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
// 操作状态样式
|
||||
.status-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.status-dot {
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background-color: #27AE60;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.status-text {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&.status-success {
|
||||
.status-text {
|
||||
color: #27AE60;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -111,7 +111,7 @@
|
||||
|
||||
<!-- 添加或修改岗位对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
<el-form ref="postRef" :model="form" :rules="rules" label-width="80px">
|
||||
<el-form ref="postRef" :model="form" :rules="rules" >
|
||||
<el-form-item label="岗位名称" prop="postName">
|
||||
<el-input v-model="form.postName" placeholder="请输入岗位名称" />
|
||||
</el-form-item>
|
||||
|
||||
@ -1,143 +1,71 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<el-form :model="queryParams" ref="queryRef" v-show="showSearch" :inline="true" label-width="68px">
|
||||
<el-form-item label="角色名称" prop="roleName">
|
||||
<el-input
|
||||
v-model="queryParams.roleName"
|
||||
placeholder="请输入角色名称"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="权限字符" prop="roleKey">
|
||||
<el-input
|
||||
v-model="queryParams.roleKey"
|
||||
placeholder="请输入权限字符"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="角色状态"
|
||||
clearable
|
||||
style="width: 240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" style="width: 308px">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
value-format="YYYY-MM-DD"
|
||||
type="daterange"
|
||||
range-separator="-"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
></el-date-picker>
|
||||
</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 :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
icon="Plus"
|
||||
@click="handleAdd"
|
||||
v-hasPermi="['system:role:add']"
|
||||
>新增</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
icon="Edit"
|
||||
:disabled="single"
|
||||
@click="handleUpdate"
|
||||
v-hasPermi="['system:role:edit']"
|
||||
>修改</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
icon="Delete"
|
||||
:disabled="multiple"
|
||||
@click="handleDelete"
|
||||
v-hasPermi="['system:role:remove']"
|
||||
>删除</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="Download"
|
||||
@click="handleExport"
|
||||
v-hasPermi="['system:role:export']"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
<div class="role-container">
|
||||
<!-- 搜索区域 -->
|
||||
<div class="search-area">
|
||||
<el-input
|
||||
v-model="queryParams.roleName"
|
||||
placeholder="请输入角色名称查询"
|
||||
clearable
|
||||
prefix-icon="Search"
|
||||
class="search-input"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
<div class="search-buttons">
|
||||
<el-button type="primary" class="search-btn" @click="handleQuery">搜索</el-button>
|
||||
<el-button class="reset-btn" @click="resetQuery">重置</el-button>
|
||||
</div>
|
||||
|
||||
<div class="action-buttons">
|
||||
<el-button type="primary" class="search-btn" @click="handleAdd" v-hasPermi="['system:role:add']">新增</el-button>
|
||||
<el-button class="export-btn" type="danger" plain :disabled="multiple" @click="handleDelete" v-hasPermi="['system:role:remove']">删除</el-button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 表格数据 -->
|
||||
<el-table v-loading="loading" :data="roleList" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="55" align="center" />
|
||||
<el-table-column label="角色编号" prop="roleId" width="120" />
|
||||
<el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" width="150" />
|
||||
<el-table-column label="权限字符" prop="roleKey" :show-overflow-tooltip="true" width="150" />
|
||||
<el-table-column label="显示顺序" prop="roleSort" width="100" />
|
||||
<el-table-column label="状态" align="center" width="100">
|
||||
<!-- 角色表格 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="roleList"
|
||||
@selection-change="handleSelectionChange"
|
||||
style="width: 100%"
|
||||
class="custom-table"
|
||||
:header-cell-style="{ backgroundColor: '#343744', color: '#fff' }"
|
||||
:bg-color="'#292C38'"
|
||||
>
|
||||
<el-table-column type="selection" width="50" align="left" />
|
||||
<el-table-column label="序号" width="60" align="left">
|
||||
<template #default="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.status"
|
||||
active-value="0"
|
||||
inactive-value="1"
|
||||
@change="handleStatusChange(scope.row)"
|
||||
></el-switch>
|
||||
{{ scope.$index + 1 }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间" align="center" prop="createTime">
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="left" >
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
<el-button link text @click="handleUpdate(scope.row)" v-hasPermi="['system:role:edit']">编辑</el-button>
|
||||
<el-button link text type="primary" @click="handleDelete(scope.row)" v-hasPermi="['system:role:remove']">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="角色名称" prop="roleName" :show-overflow-tooltip="true" align="left" />
|
||||
<el-table-column label="备注" prop="roleKey" :show-overflow-tooltip="true" align="left" />
|
||||
|
||||
<el-table-column label="创建时间" align="left" prop="createTime">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="修改" placement="top" v-if="scope.row.roleId !== 1">
|
||||
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:role:edit']"></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="删除" placement="top" v-if="scope.row.roleId !== 1">
|
||||
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:role:remove']"></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="数据权限" placement="top" v-if="scope.row.roleId !== 1">
|
||||
<el-button link type="primary" icon="CircleCheck" @click="handleDataScope(scope.row)" v-hasPermi="['system:role:edit']"></el-button>
|
||||
</el-tooltip>
|
||||
<el-tooltip content="分配用户" placement="top" v-if="scope.row.roleId !== 1">
|
||||
<el-button link type="primary" icon="User" @click="handleAuthUser(scope.row)" v-hasPermi="['system:role:edit']"></el-button>
|
||||
</el-tooltip>
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<!-- 分页组件 -->
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 添加或修改角色配置对话框 -->
|
||||
<el-dialog :title="title" v-model="open" width="500px" append-to-body>
|
||||
@ -145,33 +73,15 @@
|
||||
<el-form-item label="角色名称" prop="roleName">
|
||||
<el-input v-model="form.roleName" placeholder="请输入角色名称" />
|
||||
</el-form-item>
|
||||
<el-form-item prop="roleKey">
|
||||
<template #label>
|
||||
<span>
|
||||
<el-tooltip content="控制器中定义的权限字符,如:@PreAuthorize(`@ss.hasRole('admin')`)" placement="top">
|
||||
<el-icon><question-filled /></el-icon>
|
||||
</el-tooltip>
|
||||
权限字符
|
||||
</span>
|
||||
</template>
|
||||
<el-input v-model="form.roleKey" placeholder="请输入权限字符" />
|
||||
<el-form-item label="备注信息" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注信息" />
|
||||
</el-form-item>
|
||||
<el-form-item label="角色顺序" prop="roleSort">
|
||||
<el-input-number v-model="form.roleSort" controls-position="right" :min="0" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio
|
||||
v-for="dict in sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>{{ dict.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="菜单权限">
|
||||
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
|
||||
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
|
||||
<el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
|
||||
<el-form-item label="权限">
|
||||
<div class="permission-controls">
|
||||
<el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">展开/折叠</el-checkbox>
|
||||
<el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">全选/全不选</el-checkbox>
|
||||
<el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">父子联动</el-checkbox>
|
||||
</div>
|
||||
<el-tree
|
||||
class="tree-border"
|
||||
:data="menuOptions"
|
||||
@ -183,14 +93,11 @@
|
||||
:props="{ label: 'label', children: 'children' }"
|
||||
></el-tree>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
<el-button type="primary" class="search-btn" @click="submitForm">确 定</el-button>
|
||||
<el-button class="export-btn" @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -233,15 +140,15 @@
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitDataScope">确 定</el-button>
|
||||
<el-button @click="cancelDataScope">取 消</el-button>
|
||||
<el-button type="primary" class="search-btn" @click="submitDataScope">确 定</el-button>
|
||||
<el-button class="export-btn" @click="cancelDataScope">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup name="systemRole">
|
||||
<script setup name="SystemRoleIndex">
|
||||
import { addRole, changeRoleStatus, dataScope, delRole, getRole, listRole, updateRole, deptTreeSelect } from "@/api/system/role";
|
||||
import { roleMenuTreeselect, treeselect as menuTreeselect } from "@/api/system/menu";
|
||||
|
||||
@ -289,8 +196,7 @@ const data = reactive({
|
||||
},
|
||||
rules: {
|
||||
roleName: [{ required: true, message: "角色名称不能为空", trigger: "blur" }],
|
||||
roleKey: [{ required: true, message: "权限字符不能为空", trigger: "blur" }],
|
||||
roleSort: [{ required: true, message: "角色顺序不能为空", trigger: "blur" }]
|
||||
remark: [{ required: false, message: "备注信息", trigger: "blur" }]
|
||||
},
|
||||
});
|
||||
|
||||
@ -319,7 +225,7 @@ function resetQuery() {
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete(row) {
|
||||
const roleIds = row.roleId || ids.value;
|
||||
proxy.$modal.confirm('是否确认删除角色编号为"' + roleIds + '"的数据项?').then(function () {
|
||||
proxy.$modal.confirm('确定删除此角色吗?').then(function () {
|
||||
return delRole(roleIds);
|
||||
}).then(() => {
|
||||
getList();
|
||||
@ -388,19 +294,12 @@ function reset() {
|
||||
}
|
||||
menuExpand.value = false;
|
||||
menuNodeAll.value = false;
|
||||
deptExpand.value = true;
|
||||
deptNodeAll.value = false;
|
||||
form.value = {
|
||||
roleId: undefined,
|
||||
roleName: undefined,
|
||||
roleKey: undefined,
|
||||
roleSort: 0,
|
||||
status: "0",
|
||||
remark: undefined,
|
||||
menuIds: [],
|
||||
deptIds: [],
|
||||
menuCheckStrictly: true,
|
||||
deptCheckStrictly: true,
|
||||
remark: undefined
|
||||
};
|
||||
proxy.resetForm("roleRef");
|
||||
}
|
||||
@ -492,6 +391,10 @@ function submitForm() {
|
||||
if (valid) {
|
||||
if (form.value.roleId != undefined) {
|
||||
form.value.menuIds = getMenuAllCheckedKeys();
|
||||
// 为了兼容原有API,保留必要字段
|
||||
form.value.roleKey = form.value.roleName; // 使用角色名称作为权限字符
|
||||
form.value.roleSort = 0; // 默认排序为0
|
||||
form.value.status = "0"; // 默认状态为正常
|
||||
updateRole(form.value).then(response => {
|
||||
proxy.$modal.msgSuccess("修改成功");
|
||||
open.value = false;
|
||||
@ -499,6 +402,10 @@ function submitForm() {
|
||||
});
|
||||
} else {
|
||||
form.value.menuIds = getMenuAllCheckedKeys();
|
||||
// 为了兼容原有API,保留必要字段
|
||||
form.value.roleKey = form.value.roleName; // 使用角色名称作为权限字符
|
||||
form.value.roleSort = 0; // 默认排序为0
|
||||
form.value.status = "0"; // 默认状态为正常
|
||||
addRole(form.value).then(response => {
|
||||
proxy.$modal.msgSuccess("新增成功");
|
||||
open.value = false;
|
||||
@ -557,3 +464,530 @@ function cancelDataScope() {
|
||||
|
||||
getList();
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
background-color: #292C38;
|
||||
color: #ffffff;
|
||||
min-height: 100%;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.role-container {
|
||||
background-color: #292c38;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.search-area {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.search-input {
|
||||
width: 250px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.search-select {
|
||||
width: 150px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.search-buttons {
|
||||
margin-right: 20px;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
// 输入框 下拉框 搜索栏
|
||||
::v-deep(.el-input__wrapper:hover) {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-select) {
|
||||
border:none !important;
|
||||
width:140px !important;
|
||||
// 修改el-select的输入框的border
|
||||
--el-border-color-hover: #343744!important;
|
||||
--el-border-color: #343744!important;
|
||||
}
|
||||
|
||||
::v-deep(.el-select__wrapper.is-focused) {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-select__wrapper) {
|
||||
background: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
border-radius: 8px !important;
|
||||
height: 36px !important;
|
||||
width: 140px;
|
||||
font-size: 15px;
|
||||
border: none !important;
|
||||
border:none !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-input__wrapper) {
|
||||
background: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
border-radius: 8px !important;
|
||||
height: 36px !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-select__placeholder) {
|
||||
color: #96A0B5 !important;
|
||||
}
|
||||
.custom-table {
|
||||
background-color: #292c38 !important;
|
||||
color: #ffffff;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
|
||||
// 防止表格闪白
|
||||
:deep(.el-loading-mask) {
|
||||
background-color: rgba(41, 44, 56, 0.7) !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__empty-block) {
|
||||
background-color: #292c38 !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__empty-text) {
|
||||
color: #96A0B5 !important;
|
||||
}
|
||||
|
||||
// 确保整个表格区域背景色
|
||||
:deep(.el-table) {
|
||||
background-color: #292c38 !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
background-color: #292c38 !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__inner-wrapper::before) {
|
||||
display: none; /* 隐藏表格顶部的边框线 */
|
||||
}
|
||||
|
||||
:deep(.el-table__header) {
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:deep(.el-table__header-wrapper) {
|
||||
th {
|
||||
background-color: #343744 !important;
|
||||
color: #96A0B5!important;
|
||||
font-weight: normal;
|
||||
border-bottom: none; /* 移除th底部边线 */
|
||||
}
|
||||
|
||||
tr th.el-table__cell:first-child {
|
||||
border-top-left-radius: 6px;
|
||||
|
||||
.cell {
|
||||
border-top-left-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
tr th.el-table__cell:last-child {
|
||||
border-top-right-radius: 4px;
|
||||
|
||||
.cell {
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-table__header th.el-table__cell {
|
||||
background-color: #343744 !important;
|
||||
color: #96A0B5;
|
||||
}
|
||||
|
||||
tr {
|
||||
background-color: #343744 !important;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body-wrapper) {
|
||||
|
||||
td {
|
||||
height: 68px!important;
|
||||
background-color: #292c38;
|
||||
color: #ffffff;
|
||||
border-bottom: 1px solid #4C4F5F;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body tr:hover > td) {
|
||||
background: #2B3B5A!important;
|
||||
|
||||
}
|
||||
|
||||
:deep(.el-button--link) {
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: #347AE2;
|
||||
padding: 0;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
:deep(.el-button.is-text) {
|
||||
background-color: transparent !important;
|
||||
border-color: transparent;
|
||||
color: #347AE2;
|
||||
|
||||
&:hover, &:focus, &:active {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-button.el-button--primary.is-text) {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
|
||||
&:hover {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body tr:hover .el-button--link.is-text) {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
.status-normal {
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.status-disabled {
|
||||
color: #e6a23c;
|
||||
}
|
||||
|
||||
:deep(.el-input__wrapper) {
|
||||
background-color: #292c38;
|
||||
box-shadow: 0 0 0 1px #565C70 inset !important;
|
||||
|
||||
.el-input__inner {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-input__count) {
|
||||
background: transparent !important;
|
||||
color: #C0C4CC !important;
|
||||
|
||||
.el-input__count-inner {
|
||||
background: transparent !important;
|
||||
color: #C0C4CC !important;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-radio__label) {
|
||||
color: #C8C9CC;
|
||||
}
|
||||
|
||||
:deep(.el-radio.is-checked .el-radio__label) {
|
||||
color: #409EFF;
|
||||
}
|
||||
|
||||
:deep(.el-button) {
|
||||
background-color: #292c38;
|
||||
border-color: #4c4f5f;
|
||||
color: #ffffff;
|
||||
|
||||
&.el-button--primary {
|
||||
background-color: #409eff;
|
||||
border-color: #409eff;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-select) {
|
||||
.el-input__wrapper {
|
||||
background-color: #292c38;
|
||||
box-shadow: 0 0 0 1px #565C70 inset !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 弹窗样式优化
|
||||
:deep(.el-dialog) {
|
||||
.el-form-item__label {
|
||||
color: #96A0B5 !important;
|
||||
}
|
||||
.el-radio__label {
|
||||
color: #C8C9CC !important;
|
||||
}
|
||||
|
||||
.el-radio.is-checked .el-radio__label {
|
||||
color: #409EFF !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 保留搜索区域的样式
|
||||
.search-area {
|
||||
:deep(.el-input__wrapper) {
|
||||
background: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
border-radius: 8px !important;
|
||||
height: 36px !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.custom-table {
|
||||
background-color: #292c38;
|
||||
color: #ffffff;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
|
||||
:deep(.el-table__inner-wrapper::before) {
|
||||
display: none; /* 隐藏表格顶部的边框线 */
|
||||
}
|
||||
|
||||
:deep(.el-table__header) {
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:deep(.el-table__header-wrapper) {
|
||||
th {
|
||||
background-color: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
font-weight: normal;
|
||||
border-bottom: none; /* 移除th底部边线 */
|
||||
}
|
||||
|
||||
tr th.el-table__cell:first-child {
|
||||
border-top-left-radius: 6px;
|
||||
|
||||
.cell {
|
||||
border-top-left-radius: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
tr th.el-table__cell:last-child {
|
||||
border-top-right-radius: 4px;
|
||||
|
||||
.cell {
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-table__header th.el-table__cell {
|
||||
background-color: #343744 !important;
|
||||
color: #96A0B5;
|
||||
}
|
||||
|
||||
tr {
|
||||
background-color: #343744 !important;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body-wrapper) {
|
||||
td {
|
||||
background-color: #292c38;
|
||||
color: #ffffff;
|
||||
height: 68px;
|
||||
border-bottom: 1px solid #4C4F5F;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body tr:hover > td) {
|
||||
background: #2B3B5A!important;
|
||||
}
|
||||
|
||||
:deep(.el-button--link) {
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: #347AE2;
|
||||
padding: 0;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
:deep(.el-button.is-text) {
|
||||
background-color: transparent !important;
|
||||
border-color: transparent;
|
||||
color: #347AE2;
|
||||
|
||||
&:hover, &:focus, &:active {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-button.el-button--primary.is-text) {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
|
||||
&:hover {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-table__body tr:hover .el-button--link.is-text) {
|
||||
background-color: transparent !important;
|
||||
color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
// 树形控件样式
|
||||
.tree-border {
|
||||
margin-top: 5px;
|
||||
background-color: #343744;
|
||||
color: #ffffff;
|
||||
border: 1px solid #4C4F5F;
|
||||
border-radius: 4px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
|
||||
:deep(.el-tree) {
|
||||
background-color: transparent;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
:deep(.el-tree-node__content) {
|
||||
background-color: transparent;
|
||||
|
||||
&:hover {
|
||||
background-color: #1e2233;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-tree-node__content.is-current) {
|
||||
background-color: rgba(52, 122, 226, 0.2);
|
||||
}
|
||||
|
||||
:deep(.el-tree-node__label) {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
:deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
|
||||
background-color: #347AE2;
|
||||
border-color: #347AE2;
|
||||
}
|
||||
|
||||
:deep(.el-checkbox__inner) {
|
||||
background-color: #292c38;
|
||||
border-color: #4C4F5F;
|
||||
}
|
||||
}
|
||||
|
||||
.permission-controls {
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
// 对话框样式
|
||||
:deep(.el-dialog) {
|
||||
background-color: #292C38;
|
||||
border-radius: 8px;
|
||||
|
||||
.el-dialog__header {
|
||||
background-color: #292C38;
|
||||
color: #ffffff;
|
||||
border-bottom: 1px solid #4C4F5F;
|
||||
padding: 15px 20px;
|
||||
|
||||
.el-dialog__title {
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.el-dialog__headerbtn .el-dialog__close {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.el-dialog__body {
|
||||
background-color: #292C38;
|
||||
color: #ffffff;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.el-dialog__footer {
|
||||
background-color: #292C38;
|
||||
border-top: 1px solid #4C4F5F;
|
||||
padding: 15px 20px;
|
||||
}
|
||||
|
||||
.el-form-item__label {
|
||||
color: #96A0B5;
|
||||
}
|
||||
|
||||
.el-form-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.el-checkbox {
|
||||
color: #ffffff;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.el-checkbox__label {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
|
||||
.search-btn {
|
||||
width: 100px;
|
||||
background-color: #347AE2;
|
||||
border-color: #347AE2;
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: #4A8BE8;
|
||||
border-color: #4A8BE8;
|
||||
}
|
||||
}
|
||||
|
||||
.export-btn {
|
||||
width: 100px;
|
||||
background-color: transparent;
|
||||
border-color: #4C4F5F;
|
||||
color: #ffffff;
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: rgba(76, 79, 95, 0.2);
|
||||
border-color: #4C4F5F;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 全局表格样式覆盖,防止闪白
|
||||
:deep(.el-table) {
|
||||
--el-table-bg-color: #292c38 !important;
|
||||
--el-table-tr-bg-color: #292c38 !important;
|
||||
--el-table-border-color: #4C4F5F !important;
|
||||
--el-table-header-bg-color: #343744 !important;
|
||||
--el-table-row-hover-bg-color: #2B3B5A !important;
|
||||
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<h4 class="form-header h4">基本信息</h4>
|
||||
<el-form :model="form" label-width="80px">
|
||||
<el-form :model="form" >
|
||||
<el-row>
|
||||
<el-col :span="8" :offset="2">
|
||||
<el-form-item label="用户昵称" prop="nickName">
|
||||
|
||||
@ -5,19 +5,19 @@
|
||||
<div class="search-area">
|
||||
<el-input
|
||||
v-model="queryParams.userName"
|
||||
placeholder="请输入人员名称"
|
||||
placeholder="请输入用户名查询"
|
||||
clearable
|
||||
prefix-icon="Search"
|
||||
class="search-input"
|
||||
/>
|
||||
|
||||
<el-select v-model="queryParams.status" placeholder="状态" clearable class="search-select">
|
||||
<el-select v-model="queryParams.roleId" placeholder="角色" clearable class="search-select">
|
||||
<el-option label="全部" value="" />
|
||||
<el-option
|
||||
v-for="dict in sys_normal_disable"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
v-for="role in roleOptions"
|
||||
:key="role.roleId"
|
||||
:label="role.roleName"
|
||||
:value="role.roleId"
|
||||
/>
|
||||
</el-select>
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
<el-button type="primary" class="search-btn" @click="handleAdd">新增</el-button>
|
||||
<el-button class="reset-btn" plain @click="handleImport">导入</el-button>
|
||||
<el-button class="reset-btn" plain @click="handleExport">导出</el-button>
|
||||
<el-button class="export-btn" type="info" @click="handleDelete">删除</el-button>
|
||||
<el-button class="export-btn" :disabled="multiple" type="info" @click="handleDelete">删除</el-button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@ -43,6 +43,7 @@
|
||||
style="width: 100%"
|
||||
class="custom-table"
|
||||
:header-cell-style="{ backgroundColor: '#343744', color: '#fff' }"
|
||||
:bg-color="'#292C38'"
|
||||
>
|
||||
<el-table-column type="selection" width="50" align="left" />
|
||||
<el-table-column label="序号" width="60" align="left">
|
||||
@ -93,12 +94,18 @@
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="用户名" prop="nickName">
|
||||
<el-input v-model="form.nickName" placeholder="请输入用户昵称" maxlength="30" />
|
||||
<el-input
|
||||
v-model="form.nickName"
|
||||
placeholder="请输入用户昵称"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="手机号" prop="phonenumber">
|
||||
<el-input v-model="form.phonenumber" placeholder="请输入手机号码" maxlength="11" />
|
||||
<el-input
|
||||
v-model="form.phonenumber"
|
||||
placeholder="请输入手机号码"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@ -109,9 +116,12 @@
|
||||
<el-col :span="24">
|
||||
<el-form-item label="角色">
|
||||
<el-radio-group v-model="form.roleId">
|
||||
<el-radio label="1">超级管理员</el-radio>
|
||||
<el-radio label="2">普通用户</el-radio>
|
||||
<el-radio label="3">驾驶员</el-radio>
|
||||
<el-radio
|
||||
v-for="role in roleOptions"
|
||||
:key="role.roleId"
|
||||
:label="role.roleId.toString()">
|
||||
{{ role.roleName }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -141,7 +151,8 @@
|
||||
</el-dialog>
|
||||
|
||||
<!-- 用户导入对话框 -->
|
||||
<el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
|
||||
<el-dialog :title="upload.title" v-model="upload.open" width="500px" append-to-body class="import-dialog">
|
||||
<div class="import-title">选择需要导入的项目文件</div>
|
||||
<el-upload
|
||||
ref="uploadRef"
|
||||
:limit="1"
|
||||
@ -153,23 +164,30 @@
|
||||
:on-success="handleFileSuccess"
|
||||
:auto-upload="false"
|
||||
drag
|
||||
class="import-upload"
|
||||
>
|
||||
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip text-center">
|
||||
<div class="el-upload__tip">
|
||||
<el-checkbox v-model="upload.updateSupport" />是否更新已经存在的用户数据
|
||||
</div>
|
||||
<span>仅允许导入xls、xlsx格式文件。</span>
|
||||
<el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">下载模板</el-link>
|
||||
<div class="upload-content">
|
||||
<el-icon class="upload-icon"><upload-filled /></el-icon>
|
||||
<div class="upload-text">拖拽文件到这里,或</div>
|
||||
<div class="upload-link">
|
||||
<el-icon class="upload-icon-small" style="color: #347AE2"><upload-filled /></el-icon>
|
||||
<span class="click-upload">点此添加</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</el-upload>
|
||||
<div class="import-footer">
|
||||
<div class="footer-left">
|
||||
<el-checkbox v-model="upload.updateSupport">是否更新已经存在的用户数据</el-checkbox>
|
||||
</div>
|
||||
<div class="footer-right">
|
||||
<span class="file-format">仅允许导入xls、xlsx格式文件。</span>
|
||||
<el-link type="primary" :underline="false" class="download-link" @click="importTemplate">下载模板</el-link>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitFileForm">确 定</el-button>
|
||||
<el-button @click="upload.open = false">取 消</el-button>
|
||||
<el-button class="export-btn" @click="upload.open = false">取 消</el-button>
|
||||
<el-button class="search-btn" type="primary" @click="submitFileForm">确 定</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -178,7 +196,18 @@
|
||||
|
||||
<script setup name="User">
|
||||
import { getToken } from "@/utils/auth";
|
||||
import { changeUserStatus, listUser, resetUserPwd, delUser, getUser, updateUser, addUser, deptTreeSelect } from "@/api/system/user";
|
||||
import {
|
||||
changeUserStatus,
|
||||
listUser,
|
||||
resetUserPwd,
|
||||
delUser,
|
||||
getUser,
|
||||
updateUser,
|
||||
addUser,
|
||||
deptTreeSelect,
|
||||
getInitPassword
|
||||
} from "@/api/system/user";
|
||||
import { listRole } from "@/api/system/role";
|
||||
|
||||
const router = useRouter();
|
||||
const { proxy } = getCurrentInstance();
|
||||
@ -196,6 +225,7 @@ const title = ref("");
|
||||
const dateRange = ref([]);
|
||||
const postOptions = ref([]);
|
||||
const roleOptions = ref([]);
|
||||
const initPassword = ref(""); // 初始密码变量
|
||||
|
||||
// 用户导入参数
|
||||
const upload = reactive({
|
||||
@ -224,6 +254,7 @@ const queryParams = ref({
|
||||
userName: undefined,
|
||||
phonenumber: undefined,
|
||||
status: undefined,
|
||||
roleId: undefined,
|
||||
deptId: undefined
|
||||
});
|
||||
|
||||
@ -277,7 +308,7 @@ function handleSelectionChange(selection) {
|
||||
/** 删除按钮操作 */
|
||||
function handleDelete(row) {
|
||||
const userIds = row.userId || ids.value;
|
||||
proxy.$modal.confirm('是否确认删除用户编号为"' + userIds + '"的数据项?').then(function() {
|
||||
proxy.$modal.confirm('确定删除此用户吗?', '删除').then(function() {
|
||||
return delUser(userIds);
|
||||
}).then(() => {
|
||||
getList();
|
||||
@ -291,7 +322,7 @@ function handleBatchDelete() {
|
||||
proxy.$modal.msgError("请选择要删除的数据");
|
||||
return;
|
||||
}
|
||||
proxy.$modal.confirm('是否确认删除选中的' + ids.value.length + '条数据?').then(function() {
|
||||
proxy.$modal.confirm('确定删除选中的用户吗?', '删除').then(function() {
|
||||
return delUser(ids.value);
|
||||
}).then(() => {
|
||||
getList();
|
||||
@ -301,12 +332,16 @@ function handleBatchDelete() {
|
||||
|
||||
/** 新增按钮操作 */
|
||||
function handleAdd() {
|
||||
open.value = true;
|
||||
reset();
|
||||
getInitPassword().then(response => {
|
||||
initPassword.value = response.data.password;
|
||||
open.value = true;
|
||||
if (response && response.data) {
|
||||
initPassword.value = response.data.password;
|
||||
}
|
||||
title.value = "添加用户";
|
||||
open.value = true;
|
||||
}).catch(() => {
|
||||
title.value = "添加用户";
|
||||
open.value = true;
|
||||
});
|
||||
}
|
||||
|
||||
@ -385,13 +420,17 @@ function cancel() {
|
||||
/** 导出按钮操作 */
|
||||
function handleExport() {
|
||||
proxy.download("system/user/export", {
|
||||
...queryParams.value
|
||||
}, `user_${new Date().getTime()}.xlsx`);
|
||||
...queryParams.value,
|
||||
pageNum: undefined,
|
||||
pageSize: undefined
|
||||
}, `用户数据_${new Date().getTime()}.xlsx`);
|
||||
}
|
||||
|
||||
/** 初始化密码 */
|
||||
function getInitPassword() {
|
||||
return proxy.$axios.get("/system/user/initPassword");
|
||||
/** 导入按钮操作 */
|
||||
function handleImport() {
|
||||
upload.title = "用户导入";
|
||||
upload.open = true;
|
||||
upload.isUploading = false;
|
||||
}
|
||||
|
||||
/** 分配角色 */
|
||||
@ -409,8 +448,12 @@ function handleFileSuccess(response, file, fileList) {
|
||||
upload.open = false;
|
||||
upload.isUploading = false;
|
||||
proxy.$refs["uploadRef"].clearFiles();
|
||||
proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
|
||||
getList();
|
||||
if (response.code === 200) {
|
||||
proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
|
||||
getList(); // 刷新列表数据
|
||||
} else {
|
||||
proxy.$modal.msgError(response.msg);
|
||||
}
|
||||
}
|
||||
|
||||
/** 下载导入模板 */
|
||||
@ -431,8 +474,9 @@ onMounted(() => {
|
||||
|
||||
// 获取角色下拉列表
|
||||
function getRoleOptions() {
|
||||
// 这里假设你有API获取角色列表
|
||||
roleOptions.value = [];
|
||||
listRole().then(res => {
|
||||
roleOptions.value = res.rows;
|
||||
});
|
||||
}
|
||||
|
||||
// 获取岗位下拉列表
|
||||
@ -448,7 +492,7 @@ function getPostOptions() {
|
||||
background-color: #292C38;
|
||||
color: #ffffff;
|
||||
min-height: 100%;
|
||||
// border:1px solid red;
|
||||
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
@ -516,56 +560,72 @@ function getPostOptions() {
|
||||
// 输入框 下拉框 搜索栏
|
||||
::v-deep(.el-input__wrapper:hover) {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
::v-deep(.el-select) {
|
||||
border:none !important;
|
||||
width:140px !important;
|
||||
// 修改el-select的输入框的border
|
||||
--el-border-color-hover: #343744!important;
|
||||
--el-border-color: #343744!important;
|
||||
|
||||
}
|
||||
// ::v-deep(.el-input__wrapper) {
|
||||
// background: #343744 !important;
|
||||
// border: none !important;
|
||||
// border-radius: 8px !important;
|
||||
// height: 36px !important;
|
||||
// font-size: 15px;
|
||||
// color: #96A0B5 !important;
|
||||
// box-shadow: none !important;
|
||||
// }
|
||||
::v-deep(.el-select__wrapper.is-focused) {
|
||||
}
|
||||
|
||||
::v-deep(.el-select) {
|
||||
border:none !important;
|
||||
width:140px !important;
|
||||
// 修改el-select的输入框的border
|
||||
--el-border-color-hover: #343744!important;
|
||||
--el-border-color: #343744!important;
|
||||
}
|
||||
|
||||
::v-deep(.el-select__wrapper.is-focused) {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
::v-deep(.el-select__wrapper) {
|
||||
background: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
border-radius: 8px !important;
|
||||
height: 36px !important;
|
||||
width: 140px;
|
||||
font-size: 15px;
|
||||
border: none !important;
|
||||
border:none !important;
|
||||
}
|
||||
::v-deep(.el-input__wrapper) {
|
||||
background: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
border-radius: 8px !important;
|
||||
height: 36px !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
|
||||
}
|
||||
::v-deep(.el-select__placeholder) {
|
||||
color: #96A0B5 !important;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep(.el-select__wrapper) {
|
||||
background: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
border-radius: 8px !important;
|
||||
height: 36px !important;
|
||||
width: 140px;
|
||||
font-size: 15px;
|
||||
border: none !important;
|
||||
border:none !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-input__wrapper) {
|
||||
background: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
border-radius: 8px !important;
|
||||
height: 36px !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
::v-deep(.el-select__placeholder) {
|
||||
color: #96A0B5 !important;
|
||||
}
|
||||
.custom-table {
|
||||
background-color: #292c38;
|
||||
background-color: #292c38 !important;
|
||||
color: #ffffff;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
|
||||
// 防止表格闪白
|
||||
:deep(.el-loading-mask) {
|
||||
background-color: rgba(41, 44, 56, 0.7) !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__empty-block) {
|
||||
background-color: #292c38 !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__empty-text) {
|
||||
color: #96A0B5 !important;
|
||||
}
|
||||
|
||||
// 确保整个表格区域背景色
|
||||
:deep(.el-table) {
|
||||
background-color: #292c38 !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__body) {
|
||||
background-color: #292c38 !important;
|
||||
}
|
||||
|
||||
:deep(.el-table__inner-wrapper::before) {
|
||||
display: none; /* 隐藏表格顶部的边框线 */
|
||||
}
|
||||
@ -613,6 +673,7 @@ function getPostOptions() {
|
||||
:deep(.el-table__body-wrapper) {
|
||||
|
||||
td {
|
||||
height: 68px!important;
|
||||
background-color: #292c38;
|
||||
color: #ffffff;
|
||||
border-bottom: 1px solid #4C4F5F;
|
||||
@ -620,7 +681,8 @@ function getPostOptions() {
|
||||
}
|
||||
|
||||
:deep(.el-table__body tr:hover > td) {
|
||||
background-color: #1e2233 !important;
|
||||
background: #2B3B5A!important;
|
||||
|
||||
}
|
||||
|
||||
:deep(.el-button--link) {
|
||||
@ -668,13 +730,31 @@ function getPostOptions() {
|
||||
|
||||
:deep(.el-input__wrapper) {
|
||||
background-color: #292c38;
|
||||
box-shadow: 0 0 0 1px #4c4f5f inset;
|
||||
box-shadow: 0 0 0 1px #565C70 inset !important;
|
||||
|
||||
.el-input__inner {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-input__count) {
|
||||
background: transparent !important;
|
||||
color: #C0C4CC !important;
|
||||
|
||||
.el-input__count-inner {
|
||||
background: transparent !important;
|
||||
color: #C0C4CC !important;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-radio__label) {
|
||||
color: #C8C9CC;
|
||||
}
|
||||
|
||||
:deep(.el-radio.is-checked .el-radio__label) {
|
||||
color: #409EFF;
|
||||
}
|
||||
|
||||
:deep(.el-button) {
|
||||
background-color: #292c38;
|
||||
border-color: #4c4f5f;
|
||||
@ -689,9 +769,155 @@ function getPostOptions() {
|
||||
:deep(.el-select) {
|
||||
.el-input__wrapper {
|
||||
background-color: #292c38;
|
||||
box-shadow: 0 0 0 1px #4c4f5f inset;
|
||||
box-shadow: 0 0 0 1px #565C70 inset !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 弹窗样式优化
|
||||
:deep(.el-dialog) {
|
||||
.el-form-item__label {
|
||||
color: #96A0B5 !important;
|
||||
}
|
||||
.el-radio__label {
|
||||
color: #C8C9CC !important;
|
||||
}
|
||||
|
||||
.el-radio.is-checked .el-radio__label {
|
||||
color: #409EFF !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 保留搜索区域的样式
|
||||
.search-area {
|
||||
:deep(.el-input__wrapper) {
|
||||
background: #343744 !important;
|
||||
color: #96A0B5 !important;
|
||||
border-radius: 8px !important;
|
||||
height: 36px !important;
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 全局表格样式覆盖,防止闪白
|
||||
:deep(.el-table) {
|
||||
--el-table-bg-color: #292c38 !important;
|
||||
--el-table-tr-bg-color: #292c38 !important;
|
||||
--el-table-border-color: #4C4F5F !important;
|
||||
--el-table-header-bg-color: #343744 !important;
|
||||
--el-table-row-hover-bg-color: #2B3B5A !important;
|
||||
|
||||
&::before {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// 导入弹窗样式
|
||||
.import-dialog {
|
||||
:deep(.el-dialog__header) {
|
||||
margin-right: 0;
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #4C4F5F;
|
||||
}
|
||||
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
:deep(.el-dialog__footer) {
|
||||
padding: 20px;
|
||||
border-top: 1px solid #4C4F5F;
|
||||
}
|
||||
|
||||
.import-title {
|
||||
font-size: 14px;
|
||||
color: #96A0B5;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.import-upload {
|
||||
:deep(.el-upload-dragger) {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
background-color: #292C38;
|
||||
border: 1px dashed #4C4F5F;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
&:hover {
|
||||
border-color: #347AE2;
|
||||
}
|
||||
}
|
||||
|
||||
.upload-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
color: #96A0B5;
|
||||
|
||||
.upload-icon {
|
||||
font-size: 40px;
|
||||
color: #96A0B5;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.upload-text {
|
||||
font-size: 14px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.upload-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #347AE2;
|
||||
cursor: pointer;
|
||||
|
||||
.upload-icon-small {
|
||||
font-size: 16px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.click-upload {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.import-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 20px;
|
||||
|
||||
.footer-left {
|
||||
:deep(.el-checkbox__label) {
|
||||
color: #96A0B5;
|
||||
}
|
||||
}
|
||||
|
||||
.footer-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
|
||||
.file-format {
|
||||
color: #96A0B5;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.download-link {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user