18 changed files with 2135 additions and 0 deletions
@ -0,0 +1,170 @@ |
|||
<!-- |
|||
* 双层混合菜单-侧栏包装器 |
|||
* |
|||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 |
|||
--> |
|||
<template> |
|||
<div class="top-side-menu-container"> |
|||
<!-- 1、菜单区域: 使用递归菜单解决 --> |
|||
<div class="menu-list-wrapper"> |
|||
<RecursionMenu :collapsed="collapsed" :menuTree="menuTree" ref="menuRef" /> |
|||
</div> |
|||
|
|||
<!-- 2、底部用户卡片(仅未收缩时展示,类似于原型中的 user-card) --> |
|||
<div class="side-menu-footer" v-if="!collapsed"> |
|||
<div class="user-card"> |
|||
<div class="user-avatar">{{ avatarName }}</div> |
|||
<div class="user-info"> |
|||
<div class="user-name">{{ actualName }}</div> |
|||
<div class="user-role">{{ administratorFlag ? '系统管理员' : '普通用户' }}</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { computed, nextTick, ref, watch } from 'vue'; |
|||
import RecursionMenu from './recursion-menu.vue'; |
|||
import { useAppConfigStore } from '/@/store/modules/system/app-config'; |
|||
import { useUserStore } from '/@/store/modules/system/user'; |
|||
|
|||
const props = defineProps({ |
|||
collapsed: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
activeCategoryId: { |
|||
type: [Number, String], |
|||
default: '', |
|||
}, |
|||
}); |
|||
|
|||
const userStore = useUserStore(); |
|||
const actualName = computed(() => userStore.actualName || '用户'); |
|||
const avatarName = computed(() => actualName.value.charAt(0)); |
|||
const administratorFlag = computed(() => userStore.administratorFlag); |
|||
|
|||
// 计算当前一级分类下的子菜单树 |
|||
const menuTree = computed(() => { |
|||
if (!props.activeCategoryId) { |
|||
return []; |
|||
} |
|||
const allMenuTree = userStore.getMenuTree || []; |
|||
const currentRoot = allMenuTree.find((item) => String(item.menuId) === String(props.activeCategoryId)); |
|||
return currentRoot ? currentRoot.children || [] : []; |
|||
}); |
|||
|
|||
const menuRef = ref(); |
|||
|
|||
watch( |
|||
() => props.collapsed, |
|||
(newValue) => { |
|||
if (!newValue) { |
|||
nextTick(() => menuRef.value && menuRef.value.updateOpenKeysAndSelectKeys()); |
|||
} |
|||
} |
|||
); |
|||
|
|||
watch( |
|||
() => props.activeCategoryId, |
|||
() => { |
|||
nextTick(() => menuRef.value && menuRef.value.updateOpenKeysAndSelectKeys()); |
|||
} |
|||
); |
|||
|
|||
defineExpose({ |
|||
updateOpenKeysAndSelectKeys: () => { |
|||
if (menuRef.value) { |
|||
menuRef.value.updateOpenKeysAndSelectKeys(); |
|||
} |
|||
}, |
|||
}); |
|||
</script> |
|||
|
|||
<style lang="less" scoped> |
|||
.top-side-menu-container { |
|||
height: 100%; |
|||
display: flex; |
|||
flex-direction: column; |
|||
justify-content: space-between; |
|||
background: transparent; |
|||
} |
|||
|
|||
.menu-list-wrapper { |
|||
flex: 1; |
|||
overflow-y: auto; |
|||
overflow-x: hidden; |
|||
padding: 10px 4px; |
|||
|
|||
&::-webkit-scrollbar { |
|||
width: 4px; |
|||
} |
|||
&::-webkit-scrollbar-thumb { |
|||
border-radius: 10px; |
|||
background: rgba(0, 0, 0, 0.1); |
|||
} |
|||
} |
|||
|
|||
.side-menu-footer { |
|||
padding: 16px; |
|||
border-top: 1px solid rgba(226, 232, 240, 0.5); |
|||
background: rgba(255, 255, 255, 0.4); |
|||
backdrop-filter: blur(10px); |
|||
border-radius: 0 0 0 12px; |
|||
} |
|||
|
|||
.user-card { |
|||
display: flex; |
|||
align-items: center; |
|||
gap: 10px; |
|||
padding: 10px; |
|||
background: rgba(255, 255, 255, 0.6); |
|||
border-radius: 8px; |
|||
border: 1px solid rgba(226, 232, 240, 0.6); |
|||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04); |
|||
transition: all 0.3s ease; |
|||
|
|||
&:hover { |
|||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); |
|||
transform: translateY(-1px); |
|||
} |
|||
} |
|||
|
|||
.user-avatar { |
|||
width: 32px; |
|||
height: 32px; |
|||
border-radius: 50%; |
|||
background: linear-gradient(135deg, #2563eb 0%, #8b5cf6 100%); |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
font-weight: 600; |
|||
font-size: 13px; |
|||
flex-shrink: 0; |
|||
box-shadow: 0 2px 6px rgba(37, 99, 235, 0.2); |
|||
} |
|||
|
|||
.user-info { |
|||
flex: 1; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.user-name { |
|||
font-size: 13px; |
|||
font-weight: 600; |
|||
color: #1e293b; |
|||
white-space: nowrap; |
|||
text-overflow: ellipsis; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.user-role { |
|||
font-size: 11px; |
|||
color: #64748b; |
|||
white-space: nowrap; |
|||
text-overflow: ellipsis; |
|||
overflow: hidden; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,109 @@ |
|||
<!-- |
|||
* 双层混合导航-递归菜单 |
|||
* |
|||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 |
|||
--> |
|||
<template> |
|||
<a-menu :open-keys="openKeys" v-model:selectedKeys="selectedKeys" class="smart-menu" mode="inline" :theme="theme" @openChange="onOpenChange"> |
|||
<template v-for="item in menuTree" :key="item.menuId"> |
|||
<template v-if="item.visibleFlag && !item.disabledFlag"> |
|||
<template v-if="$lodash.isEmpty(item.children)"> |
|||
<a-menu-item :key="item.menuId" @click="turnToPage(item)"> |
|||
<template #icon> |
|||
<component :is="$antIcons[item.icon]" /> |
|||
</template> |
|||
{{ item.menuName }} |
|||
</a-menu-item> |
|||
</template> |
|||
<template v-else> |
|||
<SubMenu :menu-info="item" :key="item.menuId" @turnToPage="turnToPage" /> |
|||
</template> |
|||
</template> |
|||
</template> |
|||
</a-menu> |
|||
</template> |
|||
<script setup> |
|||
import _ from 'lodash'; |
|||
import { computed, ref, watch } from 'vue'; |
|||
import { useRoute } from 'vue-router'; |
|||
import SubMenu from './sub-menu.vue'; |
|||
import { router } from '/@/router/index'; |
|||
import { useAppConfigStore } from '/@/store/modules/system/app-config'; |
|||
import { useUserStore } from '/@/store/modules/system/user'; |
|||
|
|||
const theme = computed(() => useAppConfigStore().$state.sideMenuTheme); |
|||
const flatPattern = computed(() => useAppConfigStore().$state.flatPattern); |
|||
|
|||
const props = defineProps({ |
|||
collapsed: { |
|||
type: Boolean, |
|||
default: false, |
|||
}, |
|||
menuTree: { |
|||
type: Array, |
|||
default: () => [], |
|||
}, |
|||
}); |
|||
|
|||
const rootSubmenuKeys = computed(() => props.menuTree.map(item => item.menuId)); |
|||
|
|||
// 展开的菜单 |
|||
let currentRoute = useRoute(); |
|||
const selectedKeys = ref([]); |
|||
const openKeys = ref([]); |
|||
|
|||
// 页面跳转 |
|||
function turnToPage(menu) { |
|||
useUserStore().deleteKeepAliveIncludes(menu.menuId.toString()); |
|||
router.push({ path: menu.path }); |
|||
} |
|||
|
|||
function updateOpenKeysAndSelectKeys() { |
|||
// 更新选中 |
|||
selectedKeys.value = [_.toNumber(currentRoute.name)]; |
|||
|
|||
// 获取需要展开的menu key集合 |
|||
let menuParentIdListMap = useUserStore().getMenuParentIdListMap; |
|||
let parentList = menuParentIdListMap.get(currentRoute.name) || []; |
|||
|
|||
// 如果是折叠菜单的话,则不需要设置openkey |
|||
if (!props.collapsed) { |
|||
// 使用lodash的union函数,进行 去重合并两个数组 |
|||
let needOpenKeys = _.map(parentList, 'name').map(Number); |
|||
openKeys.value = _.union(openKeys.value, needOpenKeys); |
|||
} |
|||
} |
|||
|
|||
watch( |
|||
currentRoute, |
|||
() => { |
|||
updateOpenKeysAndSelectKeys(); |
|||
}, |
|||
{ |
|||
immediate: true, |
|||
} |
|||
); |
|||
|
|||
function onOpenChange(openKeysParams) { |
|||
if (flatPattern.value) { |
|||
return; |
|||
} |
|||
const latestOpenKey = openKeysParams.find(key => openKeys.value.indexOf(key) === -1); |
|||
if (rootSubmenuKeys.value.indexOf(latestOpenKey) === -1) { |
|||
openKeys.value = openKeysParams; |
|||
} else { |
|||
openKeys.value = latestOpenKey ? [latestOpenKey] : []; |
|||
} |
|||
} |
|||
|
|||
defineExpose({ |
|||
updateOpenKeysAndSelectKeys, |
|||
}); |
|||
</script> |
|||
<style lang="less" scoped> |
|||
.smart-menu { |
|||
position: relative; |
|||
border-right: none; |
|||
background: transparent; |
|||
} |
|||
</style> |
|||
@ -0,0 +1,41 @@ |
|||
<!-- |
|||
* 双层混合菜单-子菜单递归 |
|||
* |
|||
* @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 |
|||
--> |
|||
<template> |
|||
<a-sub-menu :key="menuInfo.menuId"> |
|||
<template #icon> |
|||
<component :is="$antIcons[menuInfo.icon]" /> |
|||
</template> |
|||
<template #title>{{ menuInfo.menuName }}</template> |
|||
<template v-for="item in menuInfo.children" :key="item.menuId"> |
|||
<template v-if="item.visibleFlag && !item.disabledFlag"> |
|||
<template v-if="!item.children"> |
|||
<a-menu-item :key="item.menuId" @click="turnToPage(item)"> |
|||
<template #icon> |
|||
<component :is="$antIcons[item.icon]" /> |
|||
</template> |
|||
{{ item.menuName }} |
|||
</a-menu-item> |
|||
</template> |
|||
<template v-else> |
|||
<SubMenu :menu-info="item" :key="item.menuId" @turnToPage="turnToPage" /> |
|||
</template> |
|||
</template> |
|||
</template> |
|||
</a-sub-menu> |
|||
</template> |
|||
<script setup> |
|||
const props = defineProps({ |
|||
menuInfo: { |
|||
type: Object, |
|||
default: () => ({}), |
|||
}, |
|||
}); |
|||
|
|||
const emits = defineEmits(['turnToPage']); |
|||
const turnToPage = (menu) => { |
|||
emits('turnToPage', menu); |
|||
}; |
|||
</script> |
|||
@ -0,0 +1,483 @@ |
|||
<template> |
|||
<a-layout class="app-container" style="min-height: 100vh"> |
|||
<!-- 动态背景网格 --> |
|||
<div class="bg-mesh"></div> |
|||
|
|||
<!-- ========== 左侧侧边栏(全高贯穿,完美对齐) ========== --> |
|||
<a-layout-sider |
|||
:theme="sideMenuTheme" |
|||
:class="['side-menu', { collapsed: collapsed }]" |
|||
:width="220" |
|||
v-model:collapsed="collapsed" |
|||
:trigger="null" |
|||
v-show="!fullScreenFlag" |
|||
> |
|||
<!-- 侧栏顶部 Logo 区域(跟随侧栏折叠) --> |
|||
<div class="logo-area" @click="goHome"> |
|||
<div class="logo-icon">S</div> |
|||
<span class="logo-text" v-if="!collapsed">{{ websiteName }}</span> |
|||
</div> |
|||
|
|||
<!-- 侧栏二三级导航 --> |
|||
<TopSideMenu :collapsed="collapsed" :activeCategoryId="activeCategoryId" /> |
|||
</a-layout-sider> |
|||
|
|||
<!-- ========== 右侧主容器 ========== --> |
|||
<a-layout class="main-container"> |
|||
<!-- 顶部大分类导航(在侧栏右侧,包含折叠按钮) --> |
|||
<a-layout-header class="top-nav" v-show="!fullScreenFlag"> |
|||
<div class="top-nav-left"> |
|||
<!-- 折叠侧栏按钮 --> |
|||
<div class="collapse-btn" @click="collapsed = !collapsed"> |
|||
<menu-unfold-outlined v-if="collapsed" /> |
|||
<menu-fold-outlined v-else /> |
|||
</div> |
|||
|
|||
<!-- 一级大分类菜单 --> |
|||
<div class="main-categories"> |
|||
<div |
|||
v-for="item in menuTree" |
|||
:key="item.menuId" |
|||
class="category-item" |
|||
:class="{ active: String(activeCategoryId) === String(item.menuId) }" |
|||
@click="handleCategoryClick(item)" |
|||
> |
|||
{{ item.menuName }} |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 顶部右侧用户空间 --> |
|||
<div class="top-nav-right"> |
|||
<HeaderUserSpace /> |
|||
</div> |
|||
</a-layout-header> |
|||
|
|||
<!-- 中间主内容区 --> |
|||
<a-layout-content class="main-content"> |
|||
<!-- 面包屑栏 --> |
|||
<div class="breadcrumb-bar" v-show="!fullScreenFlag && breadCrumbFlag"> |
|||
<MenuLocationBreadcrumb /> |
|||
</div> |
|||
|
|||
<!-- 页面标签页 (Tabs) --> |
|||
<div class="page-tags-bar" v-show="!fullScreenFlag && pageTagFlag"> |
|||
<PageTag /> |
|||
</div> |
|||
|
|||
<!-- 内容滚动与渲染区 --> |
|||
<div class="content-scroll" :id="LAYOUT_ELEMENT_IDS.content"> |
|||
<!--不keepAlive的iframe--> |
|||
<IframeIndex v-if="iframeNotKeepAlivePageFlag" :key="route.name" :name="route.name" :url="route.meta.frameUrl" /> |
|||
<!--keepAlive的iframe--> |
|||
<IframeIndex |
|||
v-for="item in keepAliveIframePages" |
|||
v-show="route.name === item.name" |
|||
:key="item.name" |
|||
:name="item.name" |
|||
:url="item.meta.frameUrl" |
|||
/> |
|||
<!--非iframe使用router-view--> |
|||
<div v-show="!iframeNotKeepAlivePageFlag && keepAliveIframePages.every((e) => route.name != e.name)" style="height: 100%;" class="admin-content"> |
|||
<router-view v-slot="{ Component }"> |
|||
<keep-alive :include="keepAliveIncludes"> |
|||
<component :is="Component" :key="route.name" /> |
|||
</keep-alive> |
|||
</router-view> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- footer 版权公司信息 --> |
|||
<footer class="layout-footer" v-show="footerFlag && !fullScreenFlag"> |
|||
<smart-footer /> |
|||
</footer> |
|||
</a-layout-content> |
|||
</a-layout> |
|||
</a-layout> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { computed, nextTick, onMounted, ref, watch } from 'vue'; |
|||
import { useRoute, useRouter } from 'vue-router'; |
|||
import { useAppConfigStore } from '../store/modules/system/app-config'; |
|||
import { useUserStore } from '../store/modules/system/user'; |
|||
import HeaderUserSpace from './components/header-user-space/index.vue'; |
|||
import MenuLocationBreadcrumb from './components/menu-location-breadcrumb/index.vue'; |
|||
import PageTag from './components/page-tag/index.vue'; |
|||
import TopSideMenu from './components/top-side-menu/index.vue'; |
|||
import SmartFooter from './components/smart-footer/index.vue'; |
|||
import { smartKeepAlive } from './components/smart-keep-alive'; |
|||
import IframeIndex from '/@/components/framework/iframe/iframe-index.vue'; |
|||
import watermark from '../lib/smart-watermark'; |
|||
import { HOME_PAGE_NAME } from '/@/constants/system/home-const'; |
|||
import { LAYOUT_ELEMENT_IDS } from '/@/layout/layout-const.js'; |
|||
|
|||
const route = useRoute(); |
|||
const router = useRouter(); |
|||
const appConfigStore = useAppConfigStore(); |
|||
const userStore = useUserStore(); |
|||
|
|||
const websiteName = computed(() => appConfigStore.websiteName); |
|||
const sideMenuTheme = computed(() => appConfigStore.sideMenuTheme); |
|||
const windowHeight = ref(window.innerHeight); |
|||
|
|||
// 状态变量与系统配置 |
|||
const fullScreenFlag = computed(() => appConfigStore.fullScreenFlag); |
|||
const pageTagFlag = computed(() => appConfigStore.pageTagFlag); |
|||
const breadCrumbFlag = computed(() => appConfigStore.breadCrumbFlag); |
|||
const footerFlag = computed(() => appConfigStore.footerFlag); |
|||
const watermarkFlag = computed(() => appConfigStore.watermarkFlag); |
|||
|
|||
const collapsed = ref(false); |
|||
const activeCategoryId = ref(''); |
|||
|
|||
// 菜单树数据(根节点为一级分类) |
|||
const menuTree = computed(() => userStore.getMenuTree || []); |
|||
|
|||
// 递归寻找第一个叶子节点页面 |
|||
function findFirstLeafPath(menuItem) { |
|||
if (!menuItem.children || menuItem.children.length === 0) { |
|||
return menuItem.path ? menuItem : null; |
|||
} |
|||
for (const child of menuItem.children) { |
|||
const leaf = findFirstLeafPath(child); |
|||
if (leaf) return leaf; |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
// 点击顶部大分类 |
|||
function handleCategoryClick(category) { |
|||
activeCategoryId.value = category.menuId; |
|||
const targetMenu = findFirstLeafPath(category); |
|||
if (targetMenu && targetMenu.path) { |
|||
userStore.deleteKeepAliveIncludes(targetMenu.menuId.toString()); |
|||
router.push({ path: targetMenu.path }); |
|||
} |
|||
} |
|||
|
|||
// 监听路由反推高亮一级菜单 |
|||
watch( |
|||
() => route.name, |
|||
(routeName) => { |
|||
if (!routeName) return; |
|||
const menuParentIdListMap = userStore.getMenuParentIdListMap; |
|||
const parentList = menuParentIdListMap.get(routeName) || []; |
|||
if (parentList.length > 0) { |
|||
activeCategoryId.value = parentList[0].name; |
|||
} else { |
|||
const matched = menuTree.value.find((item) => String(item.menuId) === String(routeName) || item.path === route.path); |
|||
if (matched) { |
|||
activeCategoryId.value = matched.menuId; |
|||
} else { |
|||
// 默认高亮第一个 |
|||
if (!activeCategoryId.value && menuTree.value.length > 0) { |
|||
activeCategoryId.value = menuTree.value[0].menuId; |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
{ immediate: true } |
|||
); |
|||
|
|||
onMounted(() => { |
|||
if (watermarkFlag.value) { |
|||
watermark.set(LAYOUT_ELEMENT_IDS.content, userStore.actualName); |
|||
} else { |
|||
watermark.clear(); |
|||
} |
|||
}); |
|||
|
|||
watch( |
|||
() => watermarkFlag.value, |
|||
(newValue) => { |
|||
if (newValue) { |
|||
watermark.set(LAYOUT_ELEMENT_IDS.content, userStore.actualName); |
|||
} else { |
|||
watermark.clear(); |
|||
} |
|||
} |
|||
); |
|||
|
|||
function goHome() { |
|||
router.push({ name: HOME_PAGE_NAME }); |
|||
} |
|||
|
|||
window.addEventListener('resize', function () { |
|||
windowHeight.value = window.innerHeight; |
|||
}); |
|||
|
|||
// keep-alive 与 iframe |
|||
let { keepAliveIncludes, iframeNotKeepAlivePageFlag, keepAliveIframePages } = smartKeepAlive(); |
|||
</script> |
|||
|
|||
<style lang="less" scoped> |
|||
/* 整体布局 */ |
|||
.app-container { |
|||
height: 100vh; |
|||
overflow: hidden; |
|||
position: relative; |
|||
background: #f0f4f8; /* 调整为莫兰迪灰蓝色底色,与原型一致 */ |
|||
} |
|||
|
|||
.main-container { |
|||
background: transparent !important; /* 强力清除Antd Layout默认灰色底 */ |
|||
height: 100vh; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
/* 动态背景网格 */ |
|||
.bg-mesh { |
|||
position: absolute; |
|||
top: 0; |
|||
left: 0; |
|||
width: 100%; |
|||
height: 100%; |
|||
z-index: 1; |
|||
pointer-events: none; |
|||
background: |
|||
radial-gradient(ellipse at 20% 20%, rgba(37, 99, 235, 0.08) 0%, transparent 50%), |
|||
radial-gradient(ellipse at 80% 80%, rgba(139, 92, 246, 0.07) 0%, transparent 50%), |
|||
radial-gradient(ellipse at 50% 50%, rgba(6, 182, 212, 0.04) 0%, transparent 60%); |
|||
} |
|||
|
|||
/* ========== 左侧侧边栏 (全高毛玻璃效果) ========== */ |
|||
.side-menu { |
|||
height: 100vh; |
|||
background: rgba(255, 255, 255, 0.75) !important; |
|||
backdrop-filter: blur(20px); |
|||
-webkit-backdrop-filter: blur(20px); |
|||
border-right: 1px solid rgba(226, 232, 240, 0.8); |
|||
display: flex; |
|||
flex-direction: column; |
|||
z-index: 50; |
|||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); |
|||
|
|||
&.collapsed { |
|||
width: 64px; |
|||
min-width: 64px !important; |
|||
max-width: 64px !important; |
|||
} |
|||
} |
|||
|
|||
/* Logo 区域 */ |
|||
.logo-area { |
|||
height: 64px; |
|||
padding: 0 16px; |
|||
display: flex; |
|||
align-items: center; |
|||
gap: 10px; |
|||
cursor: pointer; |
|||
user-select: none; |
|||
border-bottom: 1px solid rgba(226, 232, 240, 0.6); |
|||
overflow: hidden; |
|||
white-space: nowrap; |
|||
|
|||
.collapsed & { |
|||
justify-content: center; |
|||
padding: 0; |
|||
} |
|||
} |
|||
|
|||
.logo-icon { |
|||
width: 32px; |
|||
height: 32px; |
|||
background: linear-gradient(135deg, #2563eb 0%, #8b5cf6 100%); |
|||
border-radius: 8px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
font-weight: 700; |
|||
font-size: 16px; |
|||
box-shadow: 0 3px 8px rgba(37, 99, 235, 0.25); |
|||
flex-shrink: 0; |
|||
} |
|||
|
|||
.logo-text { |
|||
font-size: 16px; |
|||
font-weight: 700; |
|||
background: linear-gradient(135deg, #2563eb 0%, #8b5cf6 100%); |
|||
-webkit-background-clip: text; |
|||
-webkit-text-fill-color: transparent; |
|||
background-clip: text; |
|||
} |
|||
|
|||
/* ========== 右侧头部大导航栏 ========== */ |
|||
.top-nav { |
|||
height: 64px; |
|||
line-height: 64px; |
|||
background: rgba(255, 255, 255, 0.75) !important; |
|||
backdrop-filter: blur(20px); |
|||
-webkit-backdrop-filter: blur(20px); |
|||
border-bottom: 1px solid rgba(226, 232, 240, 0.7); |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
padding: 0 20px; |
|||
z-index: 40; |
|||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.01); |
|||
} |
|||
|
|||
.top-nav-left { |
|||
display: flex; |
|||
align-items: center; |
|||
gap: 20px; |
|||
height: 100%; |
|||
} |
|||
|
|||
/* 折叠侧栏按钮 */ |
|||
.collapse-btn { |
|||
width: 32px; |
|||
height: 32px; |
|||
border-radius: 8px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
cursor: pointer; |
|||
color: #475569; |
|||
background: rgba(241, 245, 249, 0.8); |
|||
border: 1px solid rgba(226, 232, 240, 0.8); |
|||
transition: all 0.2s; |
|||
|
|||
&:hover { |
|||
color: #2563eb; |
|||
background: rgba(37, 99, 235, 0.05); |
|||
border-color: rgba(37, 99, 235, 0.2); |
|||
} |
|||
|
|||
svg { |
|||
width: 16px; |
|||
height: 16px; |
|||
} |
|||
} |
|||
|
|||
/* 顶栏大分类菜单 */ |
|||
.main-categories { |
|||
display: flex; |
|||
align-items: center; |
|||
gap: 4px; |
|||
height: 100%; |
|||
} |
|||
|
|||
.category-item { |
|||
height: 38px; |
|||
line-height: 38px; |
|||
padding: 0 16px; |
|||
border-radius: 8px; |
|||
font-size: 14px; |
|||
font-weight: 500; |
|||
color: #475569; |
|||
cursor: pointer; |
|||
transition: all 0.25s ease; |
|||
position: relative; |
|||
user-select: none; |
|||
|
|||
&:hover { |
|||
color: #2563eb; |
|||
background: rgba(37, 99, 235, 0.05); |
|||
border-color: transparent; |
|||
} |
|||
|
|||
&.active { |
|||
color: #2563eb; |
|||
background: rgba(37, 99, 235, 0.08); |
|||
font-weight: 600; |
|||
|
|||
&::after { |
|||
content: ''; |
|||
position: absolute; |
|||
bottom: -13px; |
|||
left: 50%; |
|||
transform: translateX(-50%); |
|||
width: 16px; |
|||
height: 3px; |
|||
background: linear-gradient(90deg, #2563eb 0%, #8b5cf6 100%); |
|||
border-radius: 2px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
.top-nav-right { |
|||
display: flex; |
|||
align-items: center; |
|||
gap: 12px; |
|||
} |
|||
|
|||
/* ========== 主内容区 ========== */ |
|||
.main-content { |
|||
flex: 1; |
|||
display: flex; |
|||
flex-direction: column; |
|||
overflow: hidden; |
|||
z-index: 10; |
|||
background: transparent !important; /* 强力清除Antd Content默认白底 */ |
|||
} |
|||
|
|||
.breadcrumb-bar { |
|||
height: 40px; |
|||
background: transparent !important; /* 背景透明,拉开层次 */ |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 0 16px; /* 精准对齐为 16px */ |
|||
flex-shrink: 0; |
|||
} |
|||
|
|||
.page-tags-bar { |
|||
padding: 6px 16px 2px 16px; /* 精准对齐为 16px */ |
|||
background: transparent !important; /* 背景透明,拉开层次 */ |
|||
flex-shrink: 0; |
|||
} |
|||
|
|||
/* 内容滚动区域 */ |
|||
.content-scroll { |
|||
flex: 1; |
|||
overflow-y: auto; |
|||
overflow-x: hidden; |
|||
padding: 16px; /* 稍微增大边距 */ |
|||
} |
|||
|
|||
.admin-content { |
|||
height: 100%; |
|||
} |
|||
|
|||
.layout-footer { |
|||
padding: 10px 0; |
|||
display: flex; |
|||
justify-content: center; |
|||
background: transparent; |
|||
border-top: 1px solid rgba(226, 232, 240, 0.4); |
|||
} |
|||
|
|||
/* Custom styles for Ant Design Vue menu components inside side layout */ |
|||
:deep(.ant-menu) { |
|||
background: transparent !important; |
|||
} |
|||
|
|||
:deep(.ant-menu-item) { |
|||
border-radius: 8px !important; |
|||
margin: 4px 8px !important; |
|||
color: #475569 !important; |
|||
transition: all 0.25s ease !important; |
|||
|
|||
&:hover { |
|||
color: #2563eb !important; |
|||
background: rgba(37, 99, 235, 0.05) !important; |
|||
transform: translateX(3px); |
|||
} |
|||
} |
|||
|
|||
:deep(.ant-menu-item-selected) { |
|||
background: rgba(37, 99, 235, 0.08) !important; |
|||
color: #2563eb !important; |
|||
font-weight: 600 !important; |
|||
|
|||
&::after { |
|||
border-right: 3px solid #2563eb !important; |
|||
left: 0; |
|||
right: auto !important; |
|||
height: 16px !important; |
|||
top: 12px !important; |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,155 @@ |
|||
<template> |
|||
<div class="page-container"> |
|||
<div class="glass-card"> |
|||
<div class="header"> |
|||
<a-space size="middle"> |
|||
<div class="icon-wrapper"> |
|||
<CommentOutlined class="icon" /> |
|||
</div> |
|||
<div> |
|||
<h2 class="title">{{ pageTitle }} - 评议工单管理</h2> |
|||
<p class="subtitle">数据来源大类:警务评议 | 业务来源小类:{{ currentBizTypeName }}</p> |
|||
</div> |
|||
</a-space> |
|||
</div> |
|||
|
|||
<div class="content-box"> |
|||
<!-- 头部查询区域 --> |
|||
<a-form layout="inline" class="query-form"> |
|||
<a-form-item label="工单编号"> |
|||
<a-input placeholder="请输入工单编号" /> |
|||
</a-form-item> |
|||
<a-form-item label="满意度"> |
|||
<a-select placeholder="请选择" style="width: 120px"> |
|||
<a-select-option value="1">满意</a-select-option> |
|||
<a-select-option value="2">基本满意</a-select-option> |
|||
<a-select-option value="3">不满意</a-select-option> |
|||
</a-select> |
|||
</a-form-item> |
|||
<a-form-item> |
|||
<a-button type="primary">查询</a-button> |
|||
<a-button style="margin-left: 8px">重置</a-button> |
|||
</a-form-item> |
|||
</a-form> |
|||
|
|||
<!-- 数据表格占位 --> |
|||
<div class="table-placeholder"> |
|||
<a-empty description="暂无物理数据,业务表 t_jwpy_order 物理开发与关联联调中" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref, computed, onMounted } from 'vue'; |
|||
import { useRoute } from 'vue-router'; |
|||
import { CommentOutlined } from '@ant-design/icons-vue'; |
|||
|
|||
const route = useRoute(); |
|||
|
|||
// 根据不同的路由地址自动适配页面标题与小类名 |
|||
const pageTitle = computed(() => { |
|||
const path = route.path; |
|||
if (path.includes('/jcj')) return '110接处警评议'; |
|||
if (path.includes('/hz')) return '户政窗口评议'; |
|||
if (path.includes('/crj')) return '出入境评议'; |
|||
if (path.includes('/cjg')) return '车驾管评议'; |
|||
if (path.includes('/za')) return '治安管理评议'; |
|||
if (path.includes('/js')) return '监所管理评议'; |
|||
if (path.includes('/xl')) return '巡逻防控评议'; |
|||
if (path.includes('/xzsp')) return '行政审批评议'; |
|||
if (path.includes('/ajbl')) return '案件办理评议'; |
|||
if (path.includes('/xf')) return '信访评议'; |
|||
if (path.includes('/wq')) return '民辅警维权'; |
|||
if (path.includes('/sqfw')) return '涉企服务评议'; |
|||
return '警务评议通用'; |
|||
}); |
|||
|
|||
const currentBizTypeName = computed(() => { |
|||
const path = route.path; |
|||
if (path.includes('/jcj')) return '110接处警 (CZZX_SJLY_03)'; |
|||
if (path.includes('/hz')) return '户政窗口 (CZZX_SJLY_06)'; |
|||
if (path.includes('/crj')) return '出入境 (CZZX_SJLY_10)'; |
|||
if (path.includes('/cjg')) return '车驾管 (CZZX_SJLY_04)'; |
|||
if (path.includes('/za')) return '治安管理 (CZZX_SJLY_12)'; |
|||
if (path.includes('/js')) return '监所管理 (CZZX_SJLY_13)'; |
|||
if (path.includes('/xl')) return '巡逻防控 (CZZX_SJLY_14)'; |
|||
if (path.includes('/xzsp')) return '行政审批 (CZZX_SJLY_11)'; |
|||
if (path.includes('/ajbl')) return '案件办理 (CZZX_SJLY_07)'; |
|||
if (path.includes('/xf')) return '信访 (CZZX_SJLY_08)'; |
|||
if (path.includes('/wq')) return '民辅警维权 (CZZX_SJLY_17)'; |
|||
if (path.includes('/sqfw')) return '涉企服务 (CZZX_SJLY_18)'; |
|||
return '未定义'; |
|||
}); |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.page-container { |
|||
padding: 16px; |
|||
min-height: calc(100vh - 120px); |
|||
} |
|||
|
|||
.glass-card { |
|||
background: rgba(255, 255, 255, 0.65); |
|||
backdrop-filter: blur(12px); |
|||
-webkit-backdrop-filter: blur(12px); |
|||
border: 1px solid rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
padding: 24px; |
|||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.06); |
|||
} |
|||
|
|||
.header { |
|||
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
|||
padding-bottom: 16px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.icon-wrapper { |
|||
background: linear-gradient(135deg, #3f86f8 0%, #1890ff 100%); |
|||
width: 48px; |
|||
height: 48px; |
|||
border-radius: 10px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.25); |
|||
} |
|||
|
|||
.icon { |
|||
font-size: 24px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
color: #1a1a1a; |
|||
margin: 0; |
|||
} |
|||
|
|||
.subtitle { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin: 4px 0 0 0; |
|||
} |
|||
|
|||
.query-form { |
|||
margin-bottom: 20px; |
|||
padding: 16px; |
|||
background: rgba(255, 255, 255, 0.4); |
|||
border-radius: 8px; |
|||
border: 1px solid rgba(0, 0, 0, 0.03); |
|||
} |
|||
|
|||
.table-placeholder { |
|||
min-height: 250px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
border: 1px dashed rgba(0, 0, 0, 0.08); |
|||
border-radius: 8px; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,89 @@ |
|||
<template> |
|||
<div class="page-container"> |
|||
<div class="glass-card"> |
|||
<div class="header"> |
|||
<a-space size="middle"> |
|||
<div class="icon-wrapper"> |
|||
<InfoCircleOutlined class="icon" /> |
|||
</div> |
|||
<div> |
|||
<h2 class="title">问题申诉管理</h2> |
|||
<p class="subtitle">各基层单位对下发的评议问题或考核不满意件有异议时,在此发起申诉与审核流程。</p> |
|||
</div> |
|||
</a-space> |
|||
</div> |
|||
|
|||
<div class="content-box"> |
|||
<div class="table-placeholder"> |
|||
<a-empty description="问题申诉管理模块物理页面开发中,已配置菜单与数据路由" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { InfoCircleOutlined } from '@ant-design/icons-vue'; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.page-container { |
|||
padding: 16px; |
|||
min-height: calc(100vh - 120px); |
|||
} |
|||
|
|||
.glass-card { |
|||
background: rgba(255, 255, 255, 0.65); |
|||
backdrop-filter: blur(12px); |
|||
-webkit-backdrop-filter: blur(12px); |
|||
border: 1px solid rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
padding: 24px; |
|||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.06); |
|||
} |
|||
|
|||
.header { |
|||
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
|||
padding-bottom: 16px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.icon-wrapper { |
|||
background: linear-gradient(135deg, #faad14 0%, #ffe58f 100%); |
|||
width: 48px; |
|||
height: 48px; |
|||
border-radius: 10px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
box-shadow: 0 4px 12px rgba(250, 173, 20, 0.25); |
|||
} |
|||
|
|||
.icon { |
|||
font-size: 24px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
color: #1a1a1a; |
|||
margin: 0; |
|||
} |
|||
|
|||
.subtitle { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin: 4px 0 0 0; |
|||
} |
|||
|
|||
.table-placeholder { |
|||
min-height: 250px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
border: 1px dashed rgba(0, 0, 0, 0.08); |
|||
border-radius: 8px; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,89 @@ |
|||
<template> |
|||
<div class="page-container"> |
|||
<div class="glass-card"> |
|||
<div class="header"> |
|||
<a-space size="middle"> |
|||
<div class="icon-wrapper"> |
|||
<CheckCircleOutlined class="icon" /> |
|||
</div> |
|||
<div> |
|||
<h2 class="title">问题整改管理</h2> |
|||
<p class="subtitle">针对警务评议中收集到的不满意工单进行派发整改、期限反馈与审核销号。</p> |
|||
</div> |
|||
</a-space> |
|||
</div> |
|||
|
|||
<div class="content-box"> |
|||
<div class="table-placeholder"> |
|||
<a-empty description="问题整改模块物理页面开发中,已配置菜单与数据路由" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { CheckCircleOutlined } from '@ant-design/icons-vue'; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.page-container { |
|||
padding: 16px; |
|||
min-height: calc(100vh - 120px); |
|||
} |
|||
|
|||
.glass-card { |
|||
background: rgba(255, 255, 255, 0.65); |
|||
backdrop-filter: blur(12px); |
|||
-webkit-backdrop-filter: blur(12px); |
|||
border: 1px solid rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
padding: 24px; |
|||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.06); |
|||
} |
|||
|
|||
.header { |
|||
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
|||
padding-bottom: 16px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.icon-wrapper { |
|||
background: linear-gradient(135deg, #ff4d4f 0%, #ff7875 100%); |
|||
width: 48px; |
|||
height: 48px; |
|||
border-radius: 10px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
box-shadow: 0 4px 12px rgba(255, 77, 79, 0.25); |
|||
} |
|||
|
|||
.icon { |
|||
font-size: 24px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
color: #1a1a1a; |
|||
margin: 0; |
|||
} |
|||
|
|||
.subtitle { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin: 4px 0 0 0; |
|||
} |
|||
|
|||
.table-placeholder { |
|||
min-height: 250px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
border: 1px dashed rgba(0, 0, 0, 0.08); |
|||
border-radius: 8px; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,89 @@ |
|||
<template> |
|||
<div class="page-container"> |
|||
<div class="glass-card"> |
|||
<div class="header"> |
|||
<a-space size="middle"> |
|||
<div class="icon-wrapper"> |
|||
<SearchOutlined class="icon" /> |
|||
</div> |
|||
<div> |
|||
<h2 class="title">单位自行调查</h2> |
|||
<p class="subtitle">各业务大队与派出所自主发起的内部业务抽查、电话回访及专项问卷调查。</p> |
|||
</div> |
|||
</a-space> |
|||
</div> |
|||
|
|||
<div class="content-box"> |
|||
<div class="table-placeholder"> |
|||
<a-empty description="单位自行调查模块物理页面开发中,已配置菜单与数据路由" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { SearchOutlined } from '@ant-design/icons-vue'; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.page-container { |
|||
padding: 16px; |
|||
min-height: calc(100vh - 120px); |
|||
} |
|||
|
|||
.glass-card { |
|||
background: rgba(255, 255, 255, 0.65); |
|||
backdrop-filter: blur(12px); |
|||
-webkit-backdrop-filter: blur(12px); |
|||
border: 1px solid rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
padding: 24px; |
|||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.06); |
|||
} |
|||
|
|||
.header { |
|||
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
|||
padding-bottom: 16px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.icon-wrapper { |
|||
background: linear-gradient(135deg, #722ed1 0%, #b37feb 100%); |
|||
width: 48px; |
|||
height: 48px; |
|||
border-radius: 10px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
box-shadow: 0 4px 12px rgba(114, 46, 209, 0.25); |
|||
} |
|||
|
|||
.icon { |
|||
font-size: 24px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
color: #1a1a1a; |
|||
margin: 0; |
|||
} |
|||
|
|||
.subtitle { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin: 4px 0 0 0; |
|||
} |
|||
|
|||
.table-placeholder { |
|||
min-height: 250px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
border: 1px dashed rgba(0, 0, 0, 0.08); |
|||
border-radius: 8px; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,89 @@ |
|||
<template> |
|||
<div class="page-container"> |
|||
<div class="glass-card"> |
|||
<div class="header"> |
|||
<a-space size="middle"> |
|||
<div class="icon-wrapper"> |
|||
<UnorderedListOutlined class="icon" /> |
|||
</div> |
|||
<div> |
|||
<h2 class="title">归档工单明细台账</h2> |
|||
<p class="subtitle">汇集并展示已审核销号、已结案的所有历史满意与不满意工单的总台账明细。</p> |
|||
</div> |
|||
</a-space> |
|||
</div> |
|||
|
|||
<div class="content-box"> |
|||
<div class="table-placeholder"> |
|||
<a-empty description="归档工单总台账明细数据流加载中" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { UnorderedListOutlined } from '@ant-design/icons-vue'; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.page-container { |
|||
padding: 16px; |
|||
min-height: calc(100vh - 120px); |
|||
} |
|||
|
|||
.glass-card { |
|||
background: rgba(255, 255, 255, 0.65); |
|||
backdrop-filter: blur(12px); |
|||
-webkit-backdrop-filter: blur(12px); |
|||
border: 1px solid rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
padding: 24px; |
|||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.06); |
|||
} |
|||
|
|||
.header { |
|||
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
|||
padding-bottom: 16px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.icon-wrapper { |
|||
background: linear-gradient(135deg, #1890ff 0%, #096dd9 100%); |
|||
width: 48px; |
|||
height: 48px; |
|||
border-radius: 10px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.25); |
|||
} |
|||
|
|||
.icon { |
|||
font-size: 24px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
color: #1a1a1a; |
|||
margin: 0; |
|||
} |
|||
|
|||
.subtitle { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin: 4px 0 0 0; |
|||
} |
|||
|
|||
.table-placeholder { |
|||
min-height: 250px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
border: 1px dashed rgba(0, 0, 0, 0.08); |
|||
border-radius: 8px; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,89 @@ |
|||
<template> |
|||
<div class="page-container"> |
|||
<div class="glass-card"> |
|||
<div class="header"> |
|||
<a-space size="middle"> |
|||
<div class="icon-wrapper"> |
|||
<UserOutlined class="icon" /> |
|||
</div> |
|||
<div> |
|||
<h2 class="title">民警民意档案(一人一档)</h2> |
|||
<p class="subtitle">记录全警每一名民警在各渠道回访、热线举报等收集到的满意与不满意工单历史记录,形成民警个人民意电子画像。</p> |
|||
</div> |
|||
</a-space> |
|||
</div> |
|||
|
|||
<div class="content-box"> |
|||
<div class="table-placeholder"> |
|||
<a-empty description="民警个人民意电子档案管理与画像模块开发中" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { UserOutlined } from '@ant-design/icons-vue'; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.page-container { |
|||
padding: 16px; |
|||
min-height: calc(100vh - 120px); |
|||
} |
|||
|
|||
.glass-card { |
|||
background: rgba(255, 255, 255, 0.65); |
|||
backdrop-filter: blur(12px); |
|||
-webkit-backdrop-filter: blur(12px); |
|||
border: 1px solid rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
padding: 24px; |
|||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.06); |
|||
} |
|||
|
|||
.header { |
|||
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
|||
padding-bottom: 16px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.icon-wrapper { |
|||
background: linear-gradient(135deg, #1890ff 0%, #0050b3 100%); |
|||
width: 48px; |
|||
height: 48px; |
|||
border-radius: 10px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.25); |
|||
} |
|||
|
|||
.icon { |
|||
font-size: 24px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
color: #1a1a1a; |
|||
margin: 0; |
|||
} |
|||
|
|||
.subtitle { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin: 4px 0 0 0; |
|||
} |
|||
|
|||
.table-placeholder { |
|||
min-height: 250px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
border: 1px dashed rgba(0, 0, 0, 0.08); |
|||
border-radius: 8px; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,89 @@ |
|||
<template> |
|||
<div class="page-container"> |
|||
<div class="glass-card"> |
|||
<div class="header"> |
|||
<a-space size="middle"> |
|||
<div class="icon-wrapper"> |
|||
<ApartmentOutlined class="icon" /> |
|||
</div> |
|||
<div> |
|||
<h2 class="title">单位民意档案(一所一档)</h2> |
|||
<p class="subtitle">汇聚各分局、派出所、警种部门的历史满意率趋势、高发诉求问题及整改合规档案。</p> |
|||
</div> |
|||
</a-space> |
|||
</div> |
|||
|
|||
<div class="content-box"> |
|||
<div class="table-placeholder"> |
|||
<a-empty description="单位民意综合电子档案模块开发中" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ApartmentOutlined } from '@ant-design/icons-vue'; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.page-container { |
|||
padding: 16px; |
|||
min-height: calc(100vh - 120px); |
|||
} |
|||
|
|||
.glass-card { |
|||
background: rgba(255, 255, 255, 0.65); |
|||
backdrop-filter: blur(12px); |
|||
-webkit-backdrop-filter: blur(12px); |
|||
border: 1px solid rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
padding: 24px; |
|||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.06); |
|||
} |
|||
|
|||
.header { |
|||
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
|||
padding-bottom: 16px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.icon-wrapper { |
|||
background: linear-gradient(135deg, #1890ff 0%, #69c0ff 100%); |
|||
width: 48px; |
|||
height: 48px; |
|||
border-radius: 10px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
box-shadow: 0 4px 12px rgba(24, 144, 255, 0.25); |
|||
} |
|||
|
|||
.icon { |
|||
font-size: 24px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
color: #1a1a1a; |
|||
margin: 0; |
|||
} |
|||
|
|||
.subtitle { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin: 4px 0 0 0; |
|||
} |
|||
|
|||
.table-placeholder { |
|||
min-height: 250px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
border: 1px dashed rgba(0, 0, 0, 0.08); |
|||
border-radius: 8px; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,89 @@ |
|||
<template> |
|||
<div class="page-container"> |
|||
<div class="glass-card"> |
|||
<div class="header"> |
|||
<a-space size="middle"> |
|||
<div class="icon-wrapper"> |
|||
<SolutionOutlined class="icon" /> |
|||
</div> |
|||
<div> |
|||
<h2 class="title">我的调查任务</h2> |
|||
<p class="subtitle">基层民警或专职调查员在此认领、填报以及提交派发给自身的问卷调查任务。</p> |
|||
</div> |
|||
</a-space> |
|||
</div> |
|||
|
|||
<div class="content-box"> |
|||
<div class="table-placeholder"> |
|||
<a-empty description="我的问卷调查填报表单及任务列表加载中" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { SolutionOutlined } from '@ant-design/icons-vue'; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.page-container { |
|||
padding: 16px; |
|||
min-height: calc(100vh - 120px); |
|||
} |
|||
|
|||
.glass-card { |
|||
background: rgba(255, 255, 255, 0.65); |
|||
backdrop-filter: blur(12px); |
|||
-webkit-backdrop-filter: blur(12px); |
|||
border: 1px solid rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
padding: 24px; |
|||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.06); |
|||
} |
|||
|
|||
.header { |
|||
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
|||
padding-bottom: 16px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.icon-wrapper { |
|||
background: linear-gradient(135deg, #d4380d 0%, #ff7a45 100%); |
|||
width: 48px; |
|||
height: 48px; |
|||
border-radius: 10px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
box-shadow: 0 4px 12px rgba(212, 56, 13, 0.25); |
|||
} |
|||
|
|||
.icon { |
|||
font-size: 24px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
color: #1a1a1a; |
|||
margin: 0; |
|||
} |
|||
|
|||
.subtitle { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin: 4px 0 0 0; |
|||
} |
|||
|
|||
.table-placeholder { |
|||
min-height: 250px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
border: 1px dashed rgba(0, 0, 0, 0.08); |
|||
border-radius: 8px; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,89 @@ |
|||
<template> |
|||
<div class="page-container"> |
|||
<div class="glass-card"> |
|||
<div class="header"> |
|||
<a-space size="middle"> |
|||
<div class="icon-wrapper"> |
|||
<FormOutlined class="icon" /> |
|||
</div> |
|||
<div> |
|||
<h2 class="title">问卷设计与管理</h2> |
|||
<p class="subtitle">用于民意调查问卷的在线可视化设计、大区抽样方案及问卷库管理。</p> |
|||
</div> |
|||
</a-space> |
|||
</div> |
|||
|
|||
<div class="content-box"> |
|||
<div class="table-placeholder"> |
|||
<a-empty description="问卷设计可视化组件及表单设计器初始化中" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { FormOutlined } from '@ant-design/icons-vue'; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.page-container { |
|||
padding: 16px; |
|||
min-height: calc(100vh - 120px); |
|||
} |
|||
|
|||
.glass-card { |
|||
background: rgba(255, 255, 255, 0.65); |
|||
backdrop-filter: blur(12px); |
|||
-webkit-backdrop-filter: blur(12px); |
|||
border: 1px solid rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
padding: 24px; |
|||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.06); |
|||
} |
|||
|
|||
.header { |
|||
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
|||
padding-bottom: 16px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.icon-wrapper { |
|||
background: linear-gradient(135deg, #fa8c16 0%, #ffd666 100%); |
|||
width: 48px; |
|||
height: 48px; |
|||
border-radius: 10px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
box-shadow: 0 4px 12px rgba(250, 140, 22, 0.25); |
|||
} |
|||
|
|||
.icon { |
|||
font-size: 24px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
color: #1a1a1a; |
|||
margin: 0; |
|||
} |
|||
|
|||
.subtitle { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin: 4px 0 0 0; |
|||
} |
|||
|
|||
.table-placeholder { |
|||
min-height: 250px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
border: 1px dashed rgba(0, 0, 0, 0.08); |
|||
border-radius: 8px; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,89 @@ |
|||
<template> |
|||
<div class="page-container"> |
|||
<div class="glass-card"> |
|||
<div class="header"> |
|||
<a-space size="middle"> |
|||
<div class="icon-wrapper"> |
|||
<ContactsOutlined class="icon" /> |
|||
</div> |
|||
<div> |
|||
<h2 class="title">调查样本库管理</h2> |
|||
<p class="subtitle">维护评议和回访电话号码段、常住/暂住人口样本及导入抽样黑名单过滤规则。</p> |
|||
</div> |
|||
</a-space> |
|||
</div> |
|||
|
|||
<div class="content-box"> |
|||
<div class="table-placeholder"> |
|||
<a-empty description="调查抽样样本库物理管理页面导入中" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ContactsOutlined } from '@ant-design/icons-vue'; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.page-container { |
|||
padding: 16px; |
|||
min-height: calc(100vh - 120px); |
|||
} |
|||
|
|||
.glass-card { |
|||
background: rgba(255, 255, 255, 0.65); |
|||
backdrop-filter: blur(12px); |
|||
-webkit-backdrop-filter: blur(12px); |
|||
border: 1px solid rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
padding: 24px; |
|||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.06); |
|||
} |
|||
|
|||
.header { |
|||
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
|||
padding-bottom: 16px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.icon-wrapper { |
|||
background: linear-gradient(135deg, #096dd9 0%, #3f86f8 100%); |
|||
width: 48px; |
|||
height: 48px; |
|||
border-radius: 10px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
box-shadow: 0 4px 12px rgba(9, 109, 217, 0.25); |
|||
} |
|||
|
|||
.icon { |
|||
font-size: 24px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
color: #1a1a1a; |
|||
margin: 0; |
|||
} |
|||
|
|||
.subtitle { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin: 4px 0 0 0; |
|||
} |
|||
|
|||
.table-placeholder { |
|||
min-height: 250px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
border: 1px dashed rgba(0, 0, 0, 0.08); |
|||
border-radius: 8px; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,89 @@ |
|||
<template> |
|||
<div class="page-container"> |
|||
<div class="glass-card"> |
|||
<div class="header"> |
|||
<a-space size="middle"> |
|||
<div class="icon-wrapper"> |
|||
<GlobalOutlined class="icon" /> |
|||
</div> |
|||
<div> |
|||
<h2 class="title">网络民意监测</h2> |
|||
<p class="subtitle">采集贴吧、微博、论坛等网络平台的警务负面舆情,并生成督察监测警报。</p> |
|||
</div> |
|||
</a-space> |
|||
</div> |
|||
|
|||
<div class="content-box"> |
|||
<div class="table-placeholder"> |
|||
<a-empty description="网络民意监测中心/涉警舆情预警系统对接中" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { GlobalOutlined } from '@ant-design/icons-vue'; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.page-container { |
|||
padding: 16px; |
|||
min-height: calc(100vh - 120px); |
|||
} |
|||
|
|||
.glass-card { |
|||
background: rgba(255, 255, 255, 0.65); |
|||
backdrop-filter: blur(12px); |
|||
-webkit-backdrop-filter: blur(12px); |
|||
border: 1px solid rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
padding: 24px; |
|||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.06); |
|||
} |
|||
|
|||
.header { |
|||
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
|||
padding-bottom: 16px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.icon-wrapper { |
|||
background: linear-gradient(135deg, #0050b3 0%, #096dd9 100%); |
|||
width: 48px; |
|||
height: 48px; |
|||
border-radius: 10px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
box-shadow: 0 4px 12px rgba(0, 80, 179, 0.25); |
|||
} |
|||
|
|||
.icon { |
|||
font-size: 24px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
color: #1a1a1a; |
|||
margin: 0; |
|||
} |
|||
|
|||
.subtitle { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin: 4px 0 0 0; |
|||
} |
|||
|
|||
.table-placeholder { |
|||
min-height: 250px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
border: 1px dashed rgba(0, 0, 0, 0.08); |
|||
border-radius: 8px; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,89 @@ |
|||
<template> |
|||
<div class="page-container"> |
|||
<div class="glass-card"> |
|||
<div class="header"> |
|||
<a-space size="middle"> |
|||
<div class="icon-wrapper"> |
|||
<CustomerServiceOutlined class="icon" /> |
|||
</div> |
|||
<div> |
|||
<h2 class="title">热线客服工作台</h2> |
|||
<p class="subtitle">话务坐席专用,集成来电弹屏、电话接听、通话历史及现场快速登记工单。</p> |
|||
</div> |
|||
</a-space> |
|||
</div> |
|||
|
|||
<div class="content-box"> |
|||
<div class="table-placeholder"> |
|||
<a-empty description="坐席客服工作台加载中,软电话条及来电弹屏模块开发中" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { CustomerServiceOutlined } from '@ant-design/icons-vue'; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.page-container { |
|||
padding: 16px; |
|||
min-height: calc(100vh - 120px); |
|||
} |
|||
|
|||
.glass-card { |
|||
background: rgba(255, 255, 255, 0.65); |
|||
backdrop-filter: blur(12px); |
|||
-webkit-backdrop-filter: blur(12px); |
|||
border: 1px solid rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
padding: 24px; |
|||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.06); |
|||
} |
|||
|
|||
.header { |
|||
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
|||
padding-bottom: 16px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.icon-wrapper { |
|||
background: linear-gradient(135deg, #13c2c2 0%, #87e8de 100%); |
|||
width: 48px; |
|||
height: 48px; |
|||
border-radius: 10px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
box-shadow: 0 4px 12px rgba(19, 194, 194, 0.25); |
|||
} |
|||
|
|||
.icon { |
|||
font-size: 24px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
color: #1a1a1a; |
|||
margin: 0; |
|||
} |
|||
|
|||
.subtitle { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin: 4px 0 0 0; |
|||
} |
|||
|
|||
.table-placeholder { |
|||
min-height: 250px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
border: 1px dashed rgba(0, 0, 0, 0.08); |
|||
border-radius: 8px; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,109 @@ |
|||
<template> |
|||
<div class="page-container"> |
|||
<div class="glass-card"> |
|||
<div class="header"> |
|||
<a-space size="middle"> |
|||
<div class="icon-wrapper"> |
|||
<PhoneOutlined class="icon" /> |
|||
</div> |
|||
<div> |
|||
<h2 class="title">{{ pageTitle }} - 热线工单流转</h2> |
|||
<p class="subtitle">数据来源大类:民意热线 | 热线业务小类:{{ currentBizTypeName }}</p> |
|||
</div> |
|||
</a-space> |
|||
</div> |
|||
|
|||
<div class="content-box"> |
|||
<div class="table-placeholder"> |
|||
<a-empty :description="`${pageTitle}业务处理及流转数据加载中`" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { ref, computed } from 'vue'; |
|||
import { useRoute } from 'vue-router'; |
|||
import { PhoneOutlined } from '@ant-design/icons-vue'; |
|||
|
|||
const route = useRoute(); |
|||
|
|||
const pageTitle = computed(() => { |
|||
const path = route.path; |
|||
if (path.includes('/12389')) return '12389热线评议'; |
|||
if (path.includes('/12345')) return '12345热线评议'; |
|||
if (path.includes('/jbts')) return '110举报投诉'; |
|||
return '民意热线评议'; |
|||
}); |
|||
|
|||
const currentBizTypeName = computed(() => { |
|||
const path = route.path; |
|||
if (path.includes('/12389')) return '12389热线 (CZZX_SJLY_01)'; |
|||
if (path.includes('/12345')) return '12345热线 (CZZX_SJLY_02)'; |
|||
if (path.includes('/jbts')) return '110举报投诉 (CZZX_SJLY_05)'; |
|||
return '未定义'; |
|||
}); |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.page-container { |
|||
padding: 16px; |
|||
min-height: calc(100vh - 120px); |
|||
} |
|||
|
|||
.glass-card { |
|||
background: rgba(255, 255, 255, 0.65); |
|||
backdrop-filter: blur(12px); |
|||
-webkit-backdrop-filter: blur(12px); |
|||
border: 1px solid rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
padding: 24px; |
|||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.06); |
|||
} |
|||
|
|||
.header { |
|||
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
|||
padding-bottom: 16px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.icon-wrapper { |
|||
background: linear-gradient(135deg, #389e0d 0%, #52c41a 100%); |
|||
width: 48px; |
|||
height: 48px; |
|||
border-radius: 10px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
box-shadow: 0 4px 12px rgba(82, 196, 26, 0.25); |
|||
} |
|||
|
|||
.icon { |
|||
font-size: 24px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
color: #1a1a1a; |
|||
margin: 0; |
|||
} |
|||
|
|||
.subtitle { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin: 4px 0 0 0; |
|||
} |
|||
|
|||
.table-placeholder { |
|||
min-height: 250px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
border: 1px dashed rgba(0, 0, 0, 0.08); |
|||
border-radius: 8px; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
</style> |
|||
@ -0,0 +1,89 @@ |
|||
<template> |
|||
<div class="page-container"> |
|||
<div class="glass-card"> |
|||
<div class="header"> |
|||
<a-space size="middle"> |
|||
<div class="icon-wrapper"> |
|||
<WechatOutlined class="icon" /> |
|||
</div> |
|||
<div> |
|||
<h2 class="title">工作微信管理</h2> |
|||
<p class="subtitle">拉取并登记企业微信或微警务端推送的互动留言及民意投诉线索。</p> |
|||
</div> |
|||
</a-space> |
|||
</div> |
|||
|
|||
<div class="content-box"> |
|||
<div class="table-placeholder"> |
|||
<a-empty description="微信记录获取及待办流程接口对接中" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup> |
|||
import { WechatOutlined } from '@ant-design/icons-vue'; |
|||
</script> |
|||
|
|||
<style scoped> |
|||
.page-container { |
|||
padding: 16px; |
|||
min-height: calc(100vh - 120px); |
|||
} |
|||
|
|||
.glass-card { |
|||
background: rgba(255, 255, 255, 0.65); |
|||
backdrop-filter: blur(12px); |
|||
-webkit-backdrop-filter: blur(12px); |
|||
border: 1px solid rgba(255, 255, 255, 0.4); |
|||
border-radius: 12px; |
|||
padding: 24px; |
|||
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.06); |
|||
} |
|||
|
|||
.header { |
|||
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
|||
padding-bottom: 16px; |
|||
margin-bottom: 20px; |
|||
} |
|||
|
|||
.icon-wrapper { |
|||
background: linear-gradient(135deg, #096dd9 0%, #1890ff 100%); |
|||
width: 48px; |
|||
height: 48px; |
|||
border-radius: 10px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
color: white; |
|||
box-shadow: 0 4px 12px rgba(9, 109, 217, 0.25); |
|||
} |
|||
|
|||
.icon { |
|||
font-size: 24px; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 18px; |
|||
font-weight: 600; |
|||
color: #1a1a1a; |
|||
margin: 0; |
|||
} |
|||
|
|||
.subtitle { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin: 4px 0 0 0; |
|||
} |
|||
|
|||
.table-placeholder { |
|||
min-height: 250px; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
border: 1px dashed rgba(0, 0, 0, 0.08); |
|||
border-radius: 8px; |
|||
background: rgba(255, 255, 255, 0.2); |
|||
} |
|||
</style> |
|||
Loading…
Reference in new issue