<script lang="ts" setup>
|
import { computed, onMounted, reactive, toRefs } from 'vue';
|
|
import { ScrollContainer } from '@jnpf/ui';
|
import { usePopup } from '@jnpf/ui/popup';
|
|
import { useUserStore } from '@vben/stores';
|
|
import { getHomeData } from '#/api/system/homeData';
|
import FlowParser from '#/views/workFlow/components/FlowParser.vue';
|
|
import BarPane from './BarPane.vue';
|
import CollectPane from './CollectPane.vue';
|
import CommonPane from './CommonPane.vue';
|
import FlowPane from './FlowPane.vue';
|
import HelpPane from './HelpPane.vue';
|
import MsgPane from './MsgPane.vue';
|
import MyAppPane from './MyAppPane.vue';
|
import NoticePane from './NoticePane.vue';
|
import RolePiePane from './RolePiePane.vue';
|
import ServerInfoPane from './ServerInfoPane.vue';
|
import TeamworkPane from './TeamworkPane.vue';
|
|
interface State {
|
homeData: any;
|
loading: boolean;
|
}
|
|
const userStore = useUserStore();
|
const state = reactive<State>({
|
homeData: {},
|
loading: false,
|
});
|
const { loading, homeData } = toRefs(state);
|
const [registerFlowParser, { openPopup: openFlowParser }] = usePopup();
|
|
const getUserInfo: any = computed(() => userStore.getUserInfo || {});
|
|
function launch(flowId) {
|
const data = {
|
id: '',
|
flowId,
|
opType: '-1',
|
isFlow: 1,
|
};
|
openFlowParser(true, data);
|
}
|
function initData() {
|
state.loading = true;
|
getHomeData()
|
.then((res) => {
|
for (let i = 0; i < res.data.length; i++) {
|
const e = res.data[i];
|
state.homeData[`${e.code}Enable`] = e.enable;
|
if (['commonUse', 'favorites', 'latelyUse'].includes(e.code)) {
|
state.homeData[`${e.code}MenuList`] = e.appList || [];
|
state.homeData[`${e.code}FlowList`] = e.flowList || [];
|
state.homeData[`${e.code}FlowEnabled`] = e.flowEnabled || false;
|
} else if (e.code === 'help') {
|
state.homeData[`${e.code}Data`] = e.data?.help || [];
|
state.homeData[`${e.code}OtherData`] = e.data?.other || [];
|
} else {
|
state.homeData[`${e.code}Data`] = e.data;
|
}
|
}
|
state.loading = false;
|
})
|
.catch(() => {
|
state.loading = false;
|
});
|
}
|
|
onMounted(() => {
|
initData();
|
});
|
</script>
|
<template>
|
<div class="dashboard-container" v-loading="loading">
|
<ScrollContainer>
|
<div class="overflow-hidden p-[-10px]">
|
<a-row :gutter="10">
|
<a-col :span="24" class="-enter-x" v-if="homeData.welcomeEnable">
|
<div class="welcome-pane dashboard-pane">
|
<div class="welcome-pane-text hidden 2xl:block">
|
<div class="welcome-pane-title">Hi,{{ getUserInfo?.userName }} 欢迎使用!</div>
|
<div>{{ getUserInfo?.positionName }}</div>
|
</div>
|
<div class="welcome-pane-guide">
|
<div class="guide-cap">如何开发一套业务系统?</div>
|
<div class="guide-list">
|
<a-tooltip placement="top">
|
<template #title>
|
<p>一个应用就是一套业务系统,先创建应用再进行功能在线开发</p>
|
</template>
|
<div class="guide-item guide-item1">
|
<div class="guide-title">
|
<p class="guide-title-step">1:创建应用</p>
|
<router-link to="/appCenter" class="link-text">去创建</router-link>
|
</div>
|
<div class="guide-desc">一个应用就是一套业务系统</div>
|
</div>
|
</a-tooltip>
|
<img src="@/assets/images/home/welcome-icon.png" class="guide-icon" />
|
<a-tooltip placement="top">
|
<template #title>
|
<p>应用创建后进入应用后台进行功能在线开发设计包含:表单、流程、报表、门户、打印、大屏等</p>
|
</template>
|
<div class="guide-item guide-item2">
|
<div class="guide-title">
|
<p class="guide-title-step">2:应用设计</p>
|
</div>
|
<div class="guide-desc">如表单、流程、报表、门户、打印、 大屏、表单回传等</div>
|
</div>
|
</a-tooltip>
|
<img src="@/assets/images/home/welcome-icon.png" class="guide-icon" />
|
<a-tooltip placement="top">
|
<template #title>
|
<p>(1)功能设计完成后需生成菜单,通过快捷生成或应用菜单中创建;</p>
|
<p>(2)对菜单有权限控制需要的,需配置权限</p>
|
</template>
|
<div class="guide-item guide-item3">
|
<div class="guide-title">
|
<p class="guide-title-step">3:发布应用</p>
|
<router-link to="/permission/auth" class="link-text">去配置</router-link>
|
</div>
|
<div class="guide-desc">将功能发布到菜单并进行权限配置</div>
|
</div>
|
</a-tooltip>
|
<img src="@/assets/images/home/welcome-icon.png" class="guide-icon" />
|
<a-tooltip placement="top">
|
<template #title>
|
<p>应用发布之后即可进入应用前台访问业务系统</p>
|
</template>
|
<div class="guide-item guide-item4">
|
<div class="guide-title">
|
<p class="guide-title-step">4:访问应用</p>
|
</div>
|
<div class="guide-desc">访问使用业务系统</div>
|
</div>
|
</a-tooltip>
|
</div>
|
</div>
|
</div>
|
</a-col>
|
<a-col :span="16">
|
<a-row :gutter="10">
|
<a-col class="-enter-x" :span="homeData.teamworkEnable ? 17 : 24" v-if="homeData.workFlowEnable">
|
<FlowPane :list="homeData.workFlowData || []" />
|
</a-col>
|
<a-col class="-enter-x" :span="homeData.workFlowEnable ? 7 : 24" v-if="homeData.teamworkEnable">
|
<TeamworkPane :list="homeData.teamworkData || []" />
|
</a-col>
|
</a-row>
|
<MyAppPane :list="homeData.systemData || []" class="-enter-x" v-if="homeData.systemEnable" />
|
<CollectPane
|
class="-enter-x"
|
:flow-list="homeData.favoritesFlowList || []"
|
:menu-list="homeData.favoritesMenuList || []"
|
:flow-enabled="homeData.favoritesFlowEnabled"
|
@launch="launch"
|
v-if="homeData.favoritesEnable" />
|
<a-row :gutter="10">
|
<a-col :span="12" class="-enter-x" v-if="homeData.pieChartEnable">
|
<div class="dashboard-pane !p-[30px]">
|
<RolePiePane :data="homeData.pieChartData" />
|
</div>
|
</a-col>
|
<a-col :span="12" class="-enter-x" v-if="homeData.columnChartEnable">
|
<div class="dashboard-pane !p-[30px]">
|
<BarPane :data="homeData.columnChartData" />
|
</div>
|
</a-col>
|
</a-row>
|
<ServerInfoPane class="-enter-x" v-if="homeData.serverEnable" />
|
</a-col>
|
<a-col :span="8">
|
<CommonPane
|
class="-enter-x"
|
:lately-use-flow-list="homeData.latelyUseFlowList || []"
|
:lately-use-menu-list="homeData.latelyUseMenuList || []"
|
:common-use-flow-list="homeData.commonUseFlowList || []"
|
:common-use-menu-list="homeData.commonUseMenuList || []"
|
:flow-enabled="homeData.latelyUseFlowEnabled"
|
@launch="launch"
|
v-if="homeData.latelyUseEnable && homeData.commonUseEnable" />
|
<NoticePane class="-enter-x" :list="homeData.noticeData || []" v-if="homeData.noticeEnable" />
|
<MsgPane class="-enter-x" :list="homeData.messageData || []" v-if="homeData.messageEnable" />
|
<HelpPane class="-enter-x" :list="homeData.helpData" :other-list="homeData.helpOtherData" v-if="homeData.helpEnable" />
|
</a-col>
|
</a-row>
|
</div>
|
</ScrollContainer>
|
<FlowParser @register="registerFlowParser" />
|
</div>
|
</template>
|
|
<style lang="scss">
|
.dashboard-container {
|
position: relative;
|
height: 100%;
|
overflow: hidden;
|
border-radius: 10px;
|
|
.dashboard-pane {
|
padding: 16px 24px;
|
margin-bottom: 10px;
|
overflow: hidden;
|
background-color: var(--component-background);
|
border-radius: 10px;
|
}
|
|
.welcome-pane {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
height: 170px;
|
padding: 0 80px 0 40px;
|
background: url('@/assets/images/home/welcome-bg.png') no-repeat center center;
|
background-size: cover;
|
|
&-text {
|
font-size: 16px;
|
line-height: 22px;
|
color: #d0e1ff;
|
}
|
|
&-title {
|
margin-bottom: 7px;
|
font-size: 30px;
|
font-weight: 500;
|
line-height: 42px;
|
color: #fff;
|
}
|
|
&-guide {
|
.guide-cap {
|
margin-bottom: 10px;
|
margin-left: 10px;
|
font-size: 16px;
|
line-height: 22px;
|
color: #fff;
|
}
|
|
.guide-list {
|
display: flex;
|
align-items: center;
|
|
.guide-icon {
|
width: 18px;
|
height: 20px;
|
margin: 0 10px;
|
}
|
|
.guide-item {
|
height: 100px;
|
padding: 12px;
|
|
.guide-title {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
margin-bottom: 12px;
|
line-height: 22px;
|
|
.guide-title-step {
|
font-size: 16px;
|
font-weight: 500;
|
color: #040c2b;
|
}
|
|
.link-text {
|
text-decoration: underline;
|
}
|
}
|
|
.guide-desc {
|
font-size: 14px;
|
line-height: 21px;
|
color: #292b2f;
|
}
|
}
|
|
.guide-item1 {
|
width: 209px;
|
background: url('@/assets/images/home/welcome-img1.png');
|
}
|
|
.guide-item2 {
|
width: 242px;
|
background: url('@/assets/images/home/welcome-img2.png');
|
}
|
|
.guide-item3 {
|
width: 240px;
|
background: url('@/assets/images/home/welcome-img3.png');
|
}
|
|
.guide-item4 {
|
width: 160px;
|
background: url('@/assets/images/home/welcome-img4.png');
|
}
|
}
|
}
|
}
|
|
.dashboard-header {
|
display: flex;
|
align-items: center;
|
height: 38px;
|
margin-bottom: 16px;
|
|
.dashboard-header-title {
|
flex-shrink: 0;
|
font-size: 18px;
|
font-weight: 500;
|
}
|
|
.dashboard-header-subTitle {
|
margin-top: 4px;
|
margin-left: 20px;
|
color: var(--text-color-label);
|
|
span {
|
padding: 0 8px;
|
}
|
}
|
|
.dashboard-header-tabs {
|
.header-tabs-item {
|
position: relative;
|
display: inline-block;
|
margin-left: 40px;
|
font-size: 14px;
|
line-height: 30px;
|
color: var(--text-color-secondary);
|
cursor: pointer;
|
user-select: none;
|
|
&.header-tabs-item-active {
|
font-weight: 500;
|
color: var(--primary-color);
|
|
&::after {
|
position: absolute;
|
bottom: 0;
|
left: 0;
|
display: block;
|
width: 100%;
|
height: 3px;
|
overflow: hidden;
|
content: '';
|
background-color: var(--primary-color);
|
border-radius: 8px 8px 0 0;
|
}
|
}
|
}
|
}
|
|
.dashboard-header-more {
|
margin-left: auto;
|
font-size: 14px;
|
color: var(--text-color-label);
|
cursor: pointer;
|
user-select: none;
|
|
i {
|
margin-left: 2px;
|
font-size: 14px;
|
}
|
|
&:hover {
|
color: var(--primary-color);
|
}
|
}
|
}
|
|
.flow-pane {
|
.flow-pane-main {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
height: 96px;
|
|
.add-flow {
|
position: relative;
|
display: flex;
|
flex-shrink: 0;
|
flex-direction: column;
|
align-items: center;
|
justify-content: center;
|
height: 96px;
|
padding: 0 6px;
|
cursor: pointer;
|
|
&:hover {
|
color: var(--primary-color);
|
|
.icon-ym {
|
background: rgb(40 193 128 / 10%);
|
}
|
}
|
|
.icon-ym {
|
display: flex;
|
flex-shrink: 0;
|
align-items: center;
|
justify-content: center;
|
width: 56px;
|
height: 56px;
|
margin-bottom: 8px;
|
overflow: hidden;
|
font-size: 28px;
|
color: #3dad3d;
|
background: rgb(40 193 128 / 4%);
|
border-radius: 50%;
|
}
|
}
|
}
|
|
.flow-list {
|
display: flex;
|
flex: 1;
|
align-items: center;
|
justify-content: space-between;
|
height: 96px;
|
|
& + .add-flow {
|
padding-left: 30px;
|
margin-left: 24px;
|
|
&::before {
|
position: absolute;
|
top: 22px;
|
left: 0;
|
display: block;
|
width: 1px;
|
height: 50px;
|
content: '';
|
background: var(--border-color-base);
|
}
|
}
|
|
.flow-item {
|
position: relative;
|
cursor: pointer;
|
|
&:hover {
|
.flow-item-title {
|
color: var(--primary-color);
|
}
|
|
.flow-item-icon {
|
background: rgb(0 136 249 / 10%);
|
}
|
|
&.flow-item-flowToSign {
|
.flow-item-icon {
|
background: rgb(40 193 128 / 10%);
|
}
|
}
|
|
&.flow-item-flowTodo {
|
.flow-item-icon {
|
background: rgb(250 233 213 / 40%);
|
}
|
}
|
|
&.flow-item-flowDoing {
|
.flow-item-icon {
|
background: rgb(127 88 232 / 10%);
|
}
|
}
|
|
&.flow-item-flowDone {
|
.flow-item-icon {
|
background: rgb(230 246 255 / 59%);
|
}
|
}
|
|
&.flow-item-flowCirculate {
|
.flow-item-icon {
|
background: rgb(255 244 237 / 79%);
|
}
|
}
|
}
|
|
&.flow-item-flowToSign {
|
.flow-item-icon {
|
color: #28c180;
|
background: rgb(40 193 128 / 4%);
|
}
|
}
|
|
&.flow-item-flowTodo {
|
.flow-item-icon {
|
color: #f29222;
|
background: rgb(250 233 213 / 16%);
|
}
|
}
|
|
&.flow-item-flowDoing {
|
.flow-item-icon {
|
color: #7f58e8;
|
background: rgb(127 88 232 / 4%);
|
}
|
}
|
|
&.flow-item-flowDone {
|
.flow-item-icon {
|
color: #19aff2;
|
background: rgb(230 246 255 / 39%);
|
}
|
}
|
|
&.flow-item-flowCirculate {
|
.flow-item-icon {
|
color: #ea7453;
|
background: rgb(255 244 237 / 39%);
|
}
|
}
|
|
&-icon {
|
display: flex;
|
flex-shrink: 0;
|
align-items: center;
|
justify-content: center;
|
width: 56px;
|
height: 56px;
|
margin-bottom: 8px;
|
overflow: hidden;
|
color: #0088f9;
|
background: rgb(0 136 249 / 4%);
|
border-radius: 50%;
|
|
i {
|
font-size: 28px;
|
}
|
}
|
|
&-num {
|
position: absolute;
|
top: 0;
|
right: -10px;
|
}
|
|
&-title {
|
line-height: 20px;
|
}
|
}
|
}
|
}
|
|
.teamwork-pane {
|
.teamwork-list {
|
display: flex;
|
align-items: center;
|
justify-content: space-around;
|
height: 94px;
|
|
.teamwork-item {
|
cursor: pointer;
|
|
&:hover {
|
color: var(--primary-color);
|
|
.teamwork-item-icon {
|
background: rgb(0 136 249 / 10%);
|
}
|
|
&.teamwork-item-print {
|
.teamwork-item-icon {
|
background: rgb(250 233 213 / 40%);
|
}
|
}
|
|
&.teamwork-item-document {
|
.teamwork-item-icon {
|
background: rgb(127 88 232 / 10%);
|
}
|
}
|
}
|
|
&.teamwork-item-print {
|
.teamwork-item-icon {
|
color: #f29222;
|
background: rgb(250 233 213 / 16%);
|
}
|
}
|
|
&.teamwork-item-document {
|
.teamwork-item-icon {
|
color: #7f58e8;
|
background: rgb(127 88 232 / 4%);
|
}
|
}
|
|
&-icon {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
width: 56px;
|
height: 56px;
|
margin-bottom: 8px;
|
overflow: hidden;
|
color: #0088f9;
|
background: rgb(0 136 249 / 4%);
|
border-radius: 50%;
|
|
i {
|
font-size: 28px;
|
}
|
}
|
|
&-title {
|
line-height: 20px;
|
text-align: center;
|
}
|
}
|
}
|
}
|
|
.common-pane {
|
.common-list {
|
min-height: 136px;
|
padding: 0 10px;
|
margin-top: -15px;
|
|
.ant-empty-normal {
|
margin-block: 14px;
|
}
|
|
.common-item {
|
display: flex;
|
align-items: center;
|
height: 60px;
|
padding: 0 15px;
|
margin-top: 16px;
|
cursor: pointer;
|
border-radius: 8px;
|
|
&:hover {
|
background-color: var(--app-content-background);
|
}
|
|
.common-item-icon {
|
display: flex;
|
flex-shrink: 0;
|
align-items: center;
|
justify-content: center;
|
width: 32px;
|
height: 32px;
|
margin-right: 6px;
|
font-size: 18px;
|
line-height: 32px;
|
color: #fff;
|
border-radius: 50%;
|
}
|
|
.common-item-text {
|
flex: 1;
|
min-width: 0;
|
|
.common-item-title {
|
overflow: hidden;
|
text-overflow: ellipsis;
|
line-height: 20px;
|
white-space: nowrap;
|
}
|
|
.common-item-desc {
|
margin-top: 4px;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
font-size: 12px;
|
line-height: 17px;
|
color: var(--text-color-label);
|
white-space: nowrap;
|
}
|
}
|
}
|
}
|
}
|
|
.lately-pane {
|
padding: 20px 12px;
|
|
.dashboard-header {
|
justify-content: space-between;
|
|
.lately-tabs {
|
display: flex;
|
align-items: center;
|
|
.lately-tabs-item {
|
width: 88px;
|
height: 36px;
|
margin-right: 10px;
|
font-size: 16px;
|
line-height: 36px;
|
color: var(--text-color-label);
|
text-align: center;
|
cursor: pointer;
|
border-radius: 18px;
|
|
&.lately-tabs-item-active {
|
color: var(--primary-color);
|
background: hsl(var(--primary-100));
|
}
|
|
&:last-child {
|
margin-right: 0;
|
}
|
}
|
}
|
|
.header-tabs-item {
|
margin-left: 20px;
|
|
&:first-child {
|
margin-left: 0;
|
}
|
}
|
}
|
}
|
|
.my-app-pane {
|
.app-list {
|
display: flex;
|
flex-wrap: wrap;
|
place-content: flex-start flex-start;
|
|
.app-item {
|
position: relative;
|
width: 140px;
|
height: 140px;
|
padding: 30px;
|
margin: 0 4px 4px;
|
overflow: hidden;
|
cursor: pointer;
|
border-radius: 8px;
|
|
&:hover {
|
background-color: var(--app-content-background);
|
}
|
|
.item-icon {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
width: 56px;
|
height: 56px;
|
margin: 0 auto 8px;
|
color: #fff;
|
border-radius: 8px;
|
|
i {
|
font-size: 34px;
|
}
|
}
|
|
.app-item-title {
|
overflow: hidden;
|
text-overflow: ellipsis;
|
font-size: 14px;
|
line-height: 20px;
|
color: var(--text-color-label);
|
text-align: center;
|
white-space: nowrap;
|
}
|
}
|
}
|
}
|
|
.server-info-pane {
|
margin-bottom: 0;
|
|
.server-info-item {
|
text-align: center;
|
|
.ant-progress {
|
padding: 10px 0;
|
}
|
}
|
}
|
|
.msg-pane {
|
.msg-list {
|
height: 210px;
|
overflow: hidden;
|
|
.msg-item {
|
display: flex;
|
align-items: center;
|
margin-bottom: 24px;
|
line-height: 20px;
|
|
.item-type {
|
flex-shrink: 0;
|
padding: 0 4px;
|
font-size: 12px;
|
line-height: 20px;
|
background: rgb(237 238 240 / 39%);
|
border-radius: 2px;
|
|
&.item-type-system {
|
color: #1890ff;
|
background: rgb(231 240 254 / 39%);
|
}
|
|
&.item-type-notice {
|
color: #e09f0c;
|
background: rgb(254 247 231 / 39%);
|
}
|
|
&.item-type-flow {
|
color: #33cc51;
|
background: rgb(235 255 241 / 39%);
|
}
|
|
&.item-type-schedule {
|
color: #77f;
|
background: rgb(231 240 254 / 39%);
|
}
|
}
|
|
.item-title {
|
flex: 1;
|
min-width: 0;
|
margin: 0 12px;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
cursor: pointer;
|
|
&:hover {
|
color: var(--primary-color);
|
}
|
}
|
|
.item-user {
|
flex-shrink: 0;
|
margin-right: 12px;
|
color: var(--text-color-secondary);
|
}
|
|
.item-time {
|
flex-shrink: 0;
|
color: var(--text-color-secondary);
|
}
|
}
|
}
|
}
|
|
.help-pane {
|
.help-list {
|
margin-top: -6px;
|
|
&.other-help-list {
|
.help-item {
|
color: var(--primary-color);
|
}
|
}
|
|
.help-item {
|
margin-bottom: 10px;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
line-height: 20px;
|
white-space: nowrap;
|
cursor: pointer;
|
|
i {
|
margin-right: 4px;
|
line-height: 20px;
|
vertical-align: -1px;
|
}
|
|
&:hover {
|
color: var(--primary-color);
|
}
|
}
|
}
|
}
|
}
|
|
.dark,
|
.dark[data-theme='custom'],
|
.dark[data-theme='default'] {
|
.dashboard-container {
|
.flow-item-icon,
|
.teamwork-item-icon,
|
.add-flow .icon-ym {
|
background-color: #333 !important;
|
}
|
}
|
}
|
</style>
|