Browse Source

初始框架页面

main
wang 1 month ago
parent
commit
4e0d9a4efd
  1. 170
      smart-flow-web/src/layout/components/top-side-menu/index.vue
  2. 109
      smart-flow-web/src/layout/components/top-side-menu/recursion-menu.vue
  3. 41
      smart-flow-web/src/layout/components/top-side-menu/sub-menu.vue
  4. 483
      smart-flow-web/src/layout/top-side-layout.vue
  5. 155
      smart-flow-web/src/views/jwpy/jwpy/flow/index.vue
  6. 89
      smart-flow-web/src/views/jwpy/jwpy/wtss/index.vue
  7. 89
      smart-flow-web/src/views/jwpy/jwpy/wtzg/index.vue
  8. 89
      smart-flow-web/src/views/jwpy/jwpy/zxdc/index.vue
  9. 89
      smart-flow-web/src/views/jwpy/myda/details/index.vue
  10. 89
      smart-flow-web/src/views/jwpy/myda/police/index.vue
  11. 89
      smart-flow-web/src/views/jwpy/myda/unit/index.vue
  12. 89
      smart-flow-web/src/views/jwpy/mydc/my-survey/index.vue
  13. 89
      smart-flow-web/src/views/jwpy/mydc/questionnaire/index.vue
  14. 89
      smart-flow-web/src/views/jwpy/mydc/sample/index.vue
  15. 89
      smart-flow-web/src/views/jwpy/mydc/web-opinion/index.vue
  16. 89
      smart-flow-web/src/views/jwpy/myrx/desk/index.vue
  17. 109
      smart-flow-web/src/views/jwpy/myrx/flow/index.vue
  18. 89
      smart-flow-web/src/views/jwpy/myrx/wechat/index.vue

170
smart-flow-web/src/layout/components/top-side-menu/index.vue

@ -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>

109
smart-flow-web/src/layout/components/top-side-menu/recursion-menu.vue

@ -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) {
// 使lodashunion
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>

41
smart-flow-web/src/layout/components/top-side-menu/sub-menu.vue

@ -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>

483
smart-flow-web/src/layout/top-side-layout.vue

@ -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>

155
smart-flow-web/src/views/jwpy/jwpy/flow/index.vue

@ -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>

89
smart-flow-web/src/views/jwpy/jwpy/wtss/index.vue

@ -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>

89
smart-flow-web/src/views/jwpy/jwpy/wtzg/index.vue

@ -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>

89
smart-flow-web/src/views/jwpy/jwpy/zxdc/index.vue

@ -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>

89
smart-flow-web/src/views/jwpy/myda/details/index.vue

@ -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>

89
smart-flow-web/src/views/jwpy/myda/police/index.vue

@ -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>

89
smart-flow-web/src/views/jwpy/myda/unit/index.vue

@ -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>

89
smart-flow-web/src/views/jwpy/mydc/my-survey/index.vue

@ -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>

89
smart-flow-web/src/views/jwpy/mydc/questionnaire/index.vue

@ -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>

89
smart-flow-web/src/views/jwpy/mydc/sample/index.vue

@ -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>

89
smart-flow-web/src/views/jwpy/mydc/web-opinion/index.vue

@ -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>

89
smart-flow-web/src/views/jwpy/myrx/desk/index.vue

@ -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>

109
smart-flow-web/src/views/jwpy/myrx/flow/index.vue

@ -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>

89
smart-flow-web/src/views/jwpy/myrx/wechat/index.vue

@ -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…
Cancel
Save