ow
This commit is contained in:
1 parent
08a11abb30
commit
61869f1af0
3 files changed
+172
-51
No files matched your search
@@ -10,7 +10,7 @@
|
|||||||
"DbContexts": {
|
"DbContexts": {
|
||||||
"MasterDbContext": {
|
"MasterDbContext": {
|
||||||
"DbContextTypeName": "MasterDbContext",
|
"DbContextTypeName": "MasterDbContext",
|
||||||
"ConnectionString": "server=nas.youjiala.com;port=3307;database=Furion;uid=root;pwd=Root@1237890;CharSet=utf8mb4;",
|
"ConnectionString": "server=nas.youjiala.com;port=3307;database=builder;uid=root;pwd=Root@1237890;CharSet=utf8mb4;",
|
||||||
"DatabaseType": "MySql",
|
"DatabaseType": "MySql",
|
||||||
"LazyLoadingProxiesEnabled": true,
|
"LazyLoadingProxiesEnabled": true,
|
||||||
"AuditEntityEnabled": true,
|
"AuditEntityEnabled": true,
|
||||||
|
|||||||
@@ -39,17 +39,28 @@ export async function setupRouter(app: App) {
|
|||||||
meta: {
|
meta: {
|
||||||
title: "首页",
|
title: "首页",
|
||||||
},
|
},
|
||||||
children: [
|
children: [...chs],
|
||||||
{
|
});
|
||||||
|
// 欢迎页使用独立外壳,不套用后台的侧边菜单 / 顶栏 / 面包屑
|
||||||
|
router.addRoute({
|
||||||
path: "/dashboard",
|
path: "/dashboard",
|
||||||
name: "dashboard",
|
name: "dashboard",
|
||||||
|
component: () => import("../layout/home.vue"),
|
||||||
|
meta: {
|
||||||
|
title: "首页",
|
||||||
|
role: "*",
|
||||||
|
description: "欢迎页",
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "",
|
||||||
|
name: "dashboardWelcome",
|
||||||
meta: {
|
meta: {
|
||||||
role: "*",
|
role: "*",
|
||||||
description: "欢迎页",
|
description: "欢迎页",
|
||||||
},
|
},
|
||||||
component: () => import("../views/dashboard.vue"),
|
component: () => import("../views/dashboard.vue"),
|
||||||
},
|
},
|
||||||
...chs,
|
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+157
-47
@@ -1,64 +1,174 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="page" :style="{
|
<a-spin :spinning="loading" :delay="200">
|
||||||
height: bsInfo.height - 120 + 'px',
|
<div class="page-container dash-page">
|
||||||
}">
|
<!-- 顶部欢迎区:通栏,滚动时随内容一起上移 -->
|
||||||
<div v-for="(item, index) in fd?.SecurityFunctionDisplayDatas" :key="index">
|
<DashboardHero />
|
||||||
<a-row style="margin-bottom: 10px;">
|
|
||||||
<a-col :span="12">
|
<!-- 功能分组:卡片外壳 / 标题字号沿用 ft-page 体系 -->
|
||||||
<a-button type="default"
|
<div class="page-main ft-page">
|
||||||
style="max-width: 200px;text-align: left;opacity:.6; align-items: center;justify-content: flex-start;display: flex;"
|
<DashboardGroupCard v-for="grp in groups" :id="'grp-' + grp.key" :key="grp.key" :name="grp.name"
|
||||||
size="large" :style="'width:' + (bsInfo.width - 100) + 'px;'"
|
:color="grp.color" :soft="grp.soft" :icon="grp.icon" :layout="grp.layout" :items="grp.items"
|
||||||
@click.prevent="onpush(item.ApiRoute)">
|
@navigate="onpush" />
|
||||||
<cust-icon-font size="26" :type="'icon-' + item.Icon" />
|
|
||||||
<span style="font-weight: 600;color:black;"> {{ item.FunctionLocalName }}</span>
|
<a-empty v-if="!groups.length && !loading" description="没有匹配的功能" />
|
||||||
</a-button>
|
|
||||||
</a-col>
|
|
||||||
</a-row>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 底部快捷栏:与其它页面一致,固定在底部 -->
|
||||||
|
<div class="page-footer dash-footer">
|
||||||
|
<DashboardBottomNav :items="navItems" @jump="onNavClick" />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</a-spin>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
|
||||||
import { reactive, inject, defineComponent, onMounted, onUnmounted, ref, unref, provide, h, computed } from "vue";
|
|
||||||
import {
|
|
||||||
DeleteOutlined, EditOutlined, LoginOutlined, CloseCircleOutlined, LaptopOutlined, ShareAltOutlined, ScissorOutlined, UploadOutlined, FolderAddOutlined, DownloadOutlined,
|
|
||||||
FolderOutlined, FileImageOutlined, NotificationOutlined, CrownOutlined, ArrowUpOutlined, PictureOutlined, UnorderedListOutlined
|
|
||||||
} from "@ant-design/icons-vue";
|
|
||||||
import { useRoute, useRouter } from "vue-router";
|
|
||||||
import securityUserService from "@/service/security/securityUserService";
|
|
||||||
import { SecurityFunctionResultData } from "@/data/auto/securityFunctionResultData";
|
|
||||||
import { bsInfo } from "@/utils/browser"
|
|
||||||
|
|
||||||
const route = useRoute();
|
<script lang="ts" setup>
|
||||||
|
import { ref, computed, onMounted } from "vue";
|
||||||
|
import { useRouter } from "vue-router";
|
||||||
|
import securityUserService from "@/service/security/securityUserService";
|
||||||
|
import type { SecurityFunctionDisplayData } from "@/data/auto/securityFunctionDisplayData";
|
||||||
|
import DashboardHero from "@/components/dashboard/DashboardHero.vue";
|
||||||
|
import DashboardGroupCard from "@/components/dashboard/DashboardGroupCard.vue";
|
||||||
|
import DashboardBottomNav from "@/components/dashboard/DashboardBottomNav.vue";
|
||||||
|
|
||||||
|
interface NavItem {
|
||||||
|
key: string;
|
||||||
|
label: string;
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const fd = ref<SecurityFunctionResultData>();
|
const loading = ref(false);
|
||||||
|
const allItems = ref<SecurityFunctionDisplayData[]>([]);
|
||||||
|
|
||||||
onMounted(async () => {
|
/* ==================== 分组定义 ==================== */
|
||||||
|
type GroupKey = "disk" | "share" | "photo" | "audio" | "video" | "family" | "other";
|
||||||
|
|
||||||
fd.value = await securityUserService.FindMenuByUsername();
|
const groupDefs: {
|
||||||
|
key: GroupKey;
|
||||||
|
name: string;
|
||||||
|
color: string;
|
||||||
|
soft: string;
|
||||||
|
icon: string;
|
||||||
|
layout: 2 | 3;
|
||||||
|
}[] = [
|
||||||
|
{ key: "disk", name: "网盘", color: "#1677ff", soft: "#e6f4ff", icon: "dbank", layout: 2 },
|
||||||
|
{ key: "share", name: "共享中心", color: "#fa8c16", soft: "#fff7e6", icon: "dgroup", layout: 2 },
|
||||||
|
{ key: "photo", name: "相册", color: "#722ed1", soft: "#f9f0ff", icon: "picture", layout: 3 },
|
||||||
|
{ key: "audio", name: "音乐", color: "#eb2f96", soft: "#fff0f6", icon: "foldermp3", layout: 3 },
|
||||||
|
{ key: "video", name: "视频", color: "#13c2c2", soft: "#e6fffb", icon: "foldervideo", layout: 3 },
|
||||||
|
{ key: "family", name: "族谱管理", color: "#52c41a", soft: "#f6ffed", icon: "family", layout: 2 },
|
||||||
|
{ key: "other", name: "更多", color: "#8a919f", soft: "#f5f6f8", icon: "gailan", layout: 3 },
|
||||||
|
];
|
||||||
|
|
||||||
if (fd.value && fd.value.SecurityFunctionDisplayDatas && fd.value.SecurityFunctionDisplayDatas.length > 0) {
|
const GROUP_OF: Record<string, GroupKey> = {
|
||||||
fd.value.SecurityFunctionDisplayDatas = fd.value.SecurityFunctionDisplayDatas.filter(item => item.FunctionIndc !== "N" && item.PageUrl?.indexOf('master') > 0);
|
DmsFileEnquiry: "disk",
|
||||||
}
|
DmsFileDeleteEnquiry: "disk",
|
||||||
});
|
FamilyGroupShare: "share",
|
||||||
|
FamilyShareOperation: "share",
|
||||||
const onpush = (apiRoute: string) => {
|
FamilyGroupOperation: "share",
|
||||||
router.push(apiRoute);
|
FamilyGroupEnquiry: "share",
|
||||||
|
Preview: "photo",
|
||||||
|
PublishPhotoOperation: "photo",
|
||||||
|
PublishPhotoEnquiry: "photo",
|
||||||
|
PreviewAudio: "audio",
|
||||||
|
PublishAudioOperation: "audio",
|
||||||
|
PublishAudioEnquiry: "audio",
|
||||||
|
PreviewVideo: "video",
|
||||||
|
PublishVideoOperation: "video",
|
||||||
|
PublishVideoEnquiry: "video",
|
||||||
|
FamilyPersonEnquiry: "family",
|
||||||
|
FamilyPersonOperation: "family",
|
||||||
|
FamilyTreeEnquiry: "family",
|
||||||
|
FamilyTreeOperation: "family",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const resolveGroup = (it: SecurityFunctionDisplayData): GroupKey =>
|
||||||
|
GROUP_OF[it.FunctionName] ?? "other";
|
||||||
|
|
||||||
|
/* ==================== 分组结果 ==================== */
|
||||||
|
const groups = computed(() => {
|
||||||
|
const taken = new Set<string>();
|
||||||
|
const result: { key: GroupKey; name: string; color: string; soft: string; icon: string; layout: 2 | 3; items: SecurityFunctionDisplayData[] }[] = [];
|
||||||
|
|
||||||
|
for (const g of groupDefs) {
|
||||||
|
const items: SecurityFunctionDisplayData[] = [];
|
||||||
|
for (const it of allItems.value) {
|
||||||
|
if (resolveGroup(it) !== g.key) continue;
|
||||||
|
const label = it.FunctionLocalName || it.FunctionName;
|
||||||
|
if (taken.has(label)) continue;
|
||||||
|
taken.add(label);
|
||||||
|
items.push(it);
|
||||||
|
}
|
||||||
|
if (items.length) result.push({ ...g, items });
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
/** 底部快捷栏只保留五大高频域 */
|
||||||
|
const navItems = computed<NavItem[]>(() =>
|
||||||
|
groupDefs
|
||||||
|
.filter(g => ["disk", "photo", "audio", "video", "family"].includes(g.key))
|
||||||
|
.map(g => {
|
||||||
|
let label = g.name;
|
||||||
|
if (label === "共享中心") label = "共享";
|
||||||
|
if (label === "族谱管理") label = "族谱";
|
||||||
|
return { key: g.key, label, icon: g.icon };
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
/* ==================== 交互 ==================== */
|
||||||
|
const onpush = (apiRoute: string) => {
|
||||||
|
if (apiRoute) router.push(apiRoute);
|
||||||
|
};
|
||||||
|
const onNavClick = (key: string) => {
|
||||||
|
document.getElementById("grp-" + key)?.scrollIntoView({ behavior: "smooth", block: "start" });
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const fd = await securityUserService.FindMenuByUsername();
|
||||||
|
const raw = fd?.SecurityFunctionDisplayDatas ?? [];
|
||||||
|
allItems.value = raw.filter(
|
||||||
|
it => it.FunctionIndc !== "N" && (it.PageUrl?.indexOf("master") ?? -1) > 0
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.page {
|
/* a-spin 会插入两层容器,把高度透传下去,height: 100% 才会生效 */
|
||||||
overflow: auto;
|
.ant-spin-nested-loading {
|
||||||
background-color: bisque;
|
height: 100%;
|
||||||
padding-left: 16px;
|
}
|
||||||
padding-right: 16px;
|
|
||||||
padding-top: 8px;
|
:deep(.ant-spin-container) {
|
||||||
margin-right: 8px;
|
height: 100%;
|
||||||
background-image: url('/images/main/p3.png');
|
}
|
||||||
background-size: cover;
|
|
||||||
width: 100%;
|
/* 独立外壳(layout/home.vue)下没有侧边菜单与面包屑,页面自己撑满整屏 */
|
||||||
z-index: -999;
|
.dash-page {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 卡片区独占剩余高度并内部滚动,底栏因此始终贴底 */
|
||||||
|
.dash-page .page-main {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
min-height: 0;
|
||||||
|
/* 底栏已是列内固定项,不再需要为 fixed 预留的 96px */
|
||||||
|
padding-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 底部快捷栏:沿用 .page-footer,仅取消 fixed,改由 flex 列天然贴底 */
|
||||||
|
.dash-footer {
|
||||||
|
position: relative;
|
||||||
|
bottom: auto;
|
||||||
|
flex: none;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
Reference in new issue
Block a user