This commit is contained in:
ahui
2025-12-01 10:41:43 +08:00
10 changed files with 254 additions and 120 deletions

BIN
web/src/assets/home-bg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

View File

@@ -1,7 +1,7 @@
<template>
<div class="layout-logo" v-if="setShowLogo" @click="onThemeConfigChange">
<img :src="siteLogo" class="layout-logo-medium-img" />
<span style="font-size: x-large">{{ getSystemConfig['login.site_title'] || themeConfig.globalTitle }}</span>
<span style="font-size: x-large; ">{{ getSystemConfig['login.site_title'] || themeConfig.globalTitle }}</span>
</div>
<div class="layout-logo-size" v-else @click="onThemeConfigChange">
<img :src="siteLogo" class="layout-logo-size-img" />

View File

@@ -591,10 +591,13 @@ watch(
<style scoped lang="scss">
.layout-navbars-tagsview {
background-color: var(--el-color-white);
border-bottom: 1px solid var(--next-border-color-light);
position: relative;
z-index: 4;
height: 45px;
border-radius: 8px;
margin-left: 15px;
margin-right: 15px;
:deep(.el-scrollbar__wrap) {
overflow-x: auto !important;
}
@@ -602,7 +605,7 @@ watch(
list-style: none;
margin: 0;
padding: 0;
height: 34px;
height: 36px;
display: flex;
align-items: center;
color: var(--el-text-color-regular);
@@ -610,7 +613,7 @@ watch(
white-space: nowrap;
padding: 0 15px;
&-li {
height: 26px;
height: 30px;
line-height: 26px;
display: flex;
align-items: center;

View File

@@ -18,7 +18,7 @@ export const useThemeConfig = defineStore('themeConfig', {
* 全局主题
*/
// 默认 primary 主题颜色
primary: '#409eff',
primary: "#193755",
// 是否开启深色模式
isIsDark: false,
@@ -26,9 +26,9 @@ export const useThemeConfig = defineStore('themeConfig', {
* 顶栏设置
*/
// 默认顶栏导航背景颜色
topBar: '#ffffff',
topBar: "#f8f8f8",
// 默认顶栏导航字体颜色
topBarColor: '#606266',
topBarColor: "#000000",
// 是否开启顶栏背景颜色渐变
isTopBarColorGradual: false,
@@ -36,11 +36,11 @@ export const useThemeConfig = defineStore('themeConfig', {
* 菜单设置
*/
// 默认菜单导航背景颜色
menuBar: '#334054',
menuBar: "#f8f8f8",
// 默认菜单导航字体颜色
menuBarColor: '#eaeaea',
menuBarColor: "#000000",
// 默认菜单高亮背景色
menuBarActiveColor: 'rgba(0, 0, 0, 0.2)',
menuBarActiveColor: "rgba(0, 48, 255, 0.38)",
// 是否开启菜单背景颜色渐变
isMenuBarColorGradual: false,
@@ -48,9 +48,9 @@ export const useThemeConfig = defineStore('themeConfig', {
* 分栏设置
*/
// 默认分栏菜单背景颜色
columnsMenuBar: '#334054',
columnsMenuBar:"#334054",
// 默认分栏菜单字体颜色
columnsMenuBarColor: '#e6e6e6',
columnsMenuBarColor: "#e6e6e6",
// 是否开启分栏菜单背景颜色渐变
isColumnsMenuBarColorGradual: false,
// 是否开启分栏菜单鼠标悬停预加载(预览菜单)

View File

@@ -29,7 +29,7 @@
.el-form {
// 用于修改弹窗时表单内容间隔太大问题,如系统设置的新增菜单弹窗里的表单内容
.el-form-item:last-of-type {
margin-bottom: 22px !important;
margin-bottom: 24px !important;
}
// 修复行内表单最后一个 el-form-item 位置下移问题
&.el-form--inline {
@@ -38,12 +38,12 @@
}
.el-form-item--default.el-form-item:last-of-type,
.el-form-item--small.el-form-item:last-of-type {
margin-bottom: 18px !important;
margin-bottom: 6px !important;
}
}
// https://gitee.com/lyt-top/vue-next-admin/issues/I5K1PM
.el-form-item .el-form-item__label .el-icon {
margin-right: 0px;
margin-right: 0;
}
}
@@ -76,12 +76,16 @@
width: 220px;
}
.el-menu-item {
height: 56px !important;
line-height: 56px !important;
height: 46px !important;
line-height: 46px !important;
border-radius:12px;
}
.el-menu-item,
.el-sub-menu__title {
height: 46px !important;
line-height: 46px !important;
color: var(--next-bg-menuBarColor);
border-radius:12px;
}
// 修复点击左侧菜单折叠再展开时,宽度不跟随问题
.el-menu--collapse {

View File

@@ -1,54 +1,96 @@
<template>
<div class="home-container">
<el-row :gutter="15" class="home-card-one mb15">
<el-col
:xs="24"
:sm="12"
:md="12"
:lg="6"
:xl="6"
v-for="(v, k) in homeOne"
:key="k"
:class="{ 'home-media home-media-lg': k > 1, 'home-media-sm': k === 1 }"
<div class="home-container">
<div style="margin: 15px; font-size: 16px; font-weight: 700">
欢迎回来{{ userInfo.userInfos.name }}
<span style="font-size: 12px; color: grey"> 这里是您的工作台请愉快的工作吧</span>
</div>
<el-row>
<el-col :span="16">
<el-row :gutter="15" class="home-card-one mb15">
<el-col
:xs="24"
:sm="12"
:md="12"
:lg="8"
:xl="6"
v-for="(v, k) in homeOne"
:key="k"
:class="{ 'home-media home-media-lg': k > 1, 'home-media-sm': k === 1 }"
>
<div class="home-card-item flex">
<div class="home-card-item flex" style="padding: 0;">
<div class="flex-margin flex w100" :class="` home-one-animation${k}`">
<div class="flex-auto">
<span class="font30">{{ v.num1 }}</span>
<span class="ml5 font16" :style="{ color: v.color1 }">{{ v.num2 }}%</span>
<div class="mt10">{{ v.num3 }}</div>
<div class="home-card-item-icon flex" style="margin: 10px;" :style="{ background: `var(${v.color2})` }">
<i class="flex-margin font24" :class="v.num4" :style="{ color: `var(${v.color3})` }"></i>
</div>
<div class="home-card-item-icon flex" :style="{ background: `var(${v.color2})` }">
<i class="flex-margin font32" :class="v.num4" :style="{ color: `var(${v.color3})` }"></i>
<div class="flex-auto">
<span class="font24">{{ v.num1 }}</span>
<span class="ml5 font14" :style="{ color: v.color1 }">{{ v.num2 }}%</span>
<div class="mt10">{{ v.num3 }}</div>
</div>
</div>
</div>
</el-col>
</el-row>
<el-row :gutter="15" class="home-card-two mb15">
<el-col :xs="24" :sm="14" :md="14" :lg="16" :xl="16">
<el-row :gutter="15" class="home-card-two mb15">
<el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="24">
<div class="home-card-item">
<div style="height: 100%" ref="homeLineRef"></div>
</div>
</el-col>
</el-row>
<el-row :gutter="15" class="home-card-three">
<el-col :span="24" :xs="24" :sm="24" :md="24" :lg="24" :xl="24" class="home-media">
<div class="home-card-item">
<div style="height: 100%" ref="homeLineRef"></div>
</div>
</el-col>
<el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="8" class="home-media">
<div class="home-card-item">
<div style="height: 100%" ref="homePieRef"></div>
<div style="height: 100%" ref="homeBarRef"></div>
</div>
</el-col>
</el-row>
<el-row :gutter="15" class="home-card-three">
<el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="8">
<div class="home-card-item">
</el-col>
<el-col :span="8">
<div style="margin-left: 15px">
<el-row :gutter="100" class="home-card-one mb15">
<el-col :span="24">
<div class="home-card-item flex" style="padding: 0; width:350px; height:200px">
<img :src="HomeBg" style="padding: 0; margin: 0;">
</div>
</el-col>
</el-row>
<el-row :gutter="100" class="home-card-one mb15">
<el-col :span="24" >
<div class="home-card-item" style=" width:350px; height: 100%; max-height: 320px">
<div class="home-card-item-title">消息通知
<button type="button" class="el-button" style=" float: right; border-color: transparent; margin-top: -2px;" @click="msgMore">
<span>更多
<i class="el-icon fs-icon fs-button-icon-right"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path fill="currentColor" d="M512 160c320 0 512 352 512 352S832 864 512 864 0 512 0 512s192-352 512-352m0 64c-225.28 0-384.128 208.064-436.8 288 52.608 79.872 211.456 288 436.8 288 225.28 0 384.128-208.064 436.8-288-52.608-79.872-211.456-288-436.8-288m0 64a224 224 0 1 1 0 448 224 224 0 0 1 0-448m0 64a160.19 160.19 0 0 0-160 160c0 88.192 71.744 160 160 160s160-71.808 160-160-71.744-160-160-160"></path></svg></i>
</span>
</button>
</div>
<div v-for="(v, k) in newsInfoList" :key="k" class="personal-info-li flex-margin flex w100" >
<div class="home-card-item-icon flex" style="margin: 5px;" :style="{ background: `#f8f8f8` }">
<i class="flex-margin font24" :class="`fa fa-commenting-o`" :style="{ color: `#5d8b22` }"></i>
</div>
<div class="flex-auto" style="margin-top: 10px">
<span class="font14">[{{ v.creator_name }}]</span>
<span style=" color: grey; float: right; font-style:italic;">&nbsp;{{ v.create_datetime }}&nbsp;&nbsp;</span>
<div class="text-container"> {{ v.title }}</div>
</div>
</div>
</div>
</el-col>
</el-row>
<el-row :gutter="100" class="home-card-one mb15">
<el-col :span="24">
<div class="home-card-item" style=" width:350px; height: 100%">
<div class="home-card-item-title">快捷导航工具</div>
<div class="home-monitor">
<div class="flex-warp">
<div class="flex-warp-item" v-for="(v, k) in homeThree" :key="k">
<div class="flex-warp-item-box" :class="`home-animation${k}`">
<div class="flex-margin">
<i :class="v.icon" :style="{ color: v.iconColor }"></i>
<span class="pl5">{{ v.label }}</span>
<div class="mt10">{{ v.value }}</div>
<div class="home-card-item-icon flex" style="margin: 20px;" :style="{ background: '#f8f8f8' }">
<i class="flex-margin font24" :class="v.icon" :style="{ color: v.iconColor}"></i>
</div>
<span class="pl20" :style="{ fontSize: 'clamp(0.875rem, 2vw, 1rem)' }">{{ v.label }}</span>
</div>
</div>
</div>
@@ -56,13 +98,11 @@
</div>
</div>
</el-col>
<el-col :xs="24" :sm="14" :md="14" :lg="16" :xl="16" class="home-media">
<div class="home-card-item">
<div style="height: 100%" ref="homeBarRef"></div>
</div>
</el-col>
</el-row>
</div>
</el-row>
</div>
</el-col>
</el-row>
</div>
</template>
<script lang="ts">
@@ -71,6 +111,7 @@ import * as echarts from 'echarts';
import { storeToRefs } from 'pinia';
import { useThemeConfig } from '/@/stores/themeConfig';
import { useTagsViewRoutes } from '/@/stores/tagsViewRoutes';
import HomeBg from '/@/assets/home-bg.png';
let global: any = {
homeChartOne: null,
@@ -79,9 +120,21 @@ let global: any = {
dispose: [null, '', undefined],
};
import { useUserInfo } from '/@/stores/userInfo';
import {useRouter} from "vue-router";
import * as api from "/@/views/system/personal/api";
// 定义消息类型
interface NewsItem {
creator_name: string;
create_datetime: string;
title: string;
}
export default defineComponent({
name: 'home',
setup() {
const userInfo = useUserInfo();
const homeLineRef = ref();
const homePieRef = ref();
const homeBarRef = ref();
@@ -89,7 +142,11 @@ export default defineComponent({
const storesThemeConfig = useThemeConfig();
const { themeConfig } = storeToRefs(storesThemeConfig);
const { isTagsViewCurrenFull } = storeToRefs(storesTagsViewRoutes);
const router = useRouter(); // 将router移到组件级别
const defaultNewsItems: NewsItem[] = [];
const state = reactive({
newsInfoList: [...defaultNewsItems] as NewsItem[],
homeOne: [
{
num1: '125,12',
@@ -109,15 +166,6 @@ export default defineComponent({
color2: '--next-color-success-lighter',
color3: '--el-color-success',
},
{
num1: '125,65',
num2: '+17.32',
num3: '年度计划信息',
num4: 'iconfont icon-zaosheng',
color1: '#6690F9',
color2: '--next-color-warning-lighter',
color3: '--el-color-warning',
},
{
num1: '520,43',
num2: '-10.01',
@@ -131,57 +179,48 @@ export default defineComponent({
homeThree: [
{
icon: 'iconfont icon-yangan',
label: '浅粉红',
value: '2.1%OBS/M',
iconColor: '#F72B3F',
label: '用户管理',
iconColor: 'gray',
},
{
icon: 'iconfont icon-wendu',
label: '深红(猩红)',
value: '30℃',
iconColor: '#91BFF8',
label: '部门管理',
iconColor: 'gray',
},
{
icon: 'iconfont icon-shidu',
label: '淡紫红',
value: '57%RH',
iconColor: '#88D565',
label: '权限管理',
iconColor: 'gray',
},
{
icon: 'iconfont icon-shidu',
label: '弱紫罗兰红',
value: '107w',
iconColor: '#88D565',
label: '日志管理',
iconColor: 'gray',
},
{
icon: 'iconfont icon-zaosheng',
label: '中紫罗兰红',
value: '57DB',
iconColor: '#FBD4A0',
label: '菜单管理',
iconColor: 'gray',
},
{
icon: 'iconfont icon-zaosheng',
label: '紫罗兰',
value: '57PV',
iconColor: '#FBD4A0',
label: '消息中心',
iconColor: 'gray',
},
{
icon: 'iconfont icon-zaosheng',
label: '暗紫罗兰',
value: '517Cpd',
iconColor: '#FBD4A0',
label: '接口管理',
iconColor: 'gray',
},
{
icon: 'iconfont icon-zaosheng',
label: '幽灵白',
value: '12kg',
iconColor: '#FBD4A0',
label: '下载中心',
iconColor: 'gray',
},
{
icon: 'iconfont icon-zaosheng',
label: '海军蓝',
value: '64fm',
iconColor: '#FBD4A0',
label: '系统管理',
iconColor: 'gray',
},
],
myCharts: [],
@@ -506,6 +545,7 @@ export default defineComponent({
// 页面加载时
onMounted(() => {
initEchartsResize();
getMsg(); // 确保组件挂载时立即获取消息列表
});
// 由于页面缓存原因keep-alive
onActivated(() => {
@@ -542,11 +582,47 @@ export default defineComponent({
immediate: true,
}
);
// 获取消息列表
const getMsg = (): void => {
// 先重置为默认数据
state.newsInfoList = [...defaultNewsItems];
// 尝试从API获取最新数据
api.GetSelfReceive({}).then((res: any) => {
const { data } = res || {};
// 严格检查返回数据的有效性
if (data && Array.isArray(data) && data.length > 0) {
try {
// 安全地进行类型转换并更新状态
state.newsInfoList = data.map((item: any): NewsItem => ({
creator_name: String(item.creator_name || '未知用户'),
create_datetime: String(item.create_datetime || ''),
title: String(item.title || '')
}));
} catch (typeError) {
console.error('数据类型转换失败:', typeError);
// 类型转换失败时保持默认数据
}
}
}).catch((error: Error) => {
console.error('获取消息列表失败,保持默认数据:', error);
// 错误时保持已设置的默认数据
});
};
// 跳转消息中心
const msgMore = (): void => {
router.push({ path: '/messageCenter' });
};
return {
homeLineRef,
homePieRef,
homeBarRef,
...toRefs(state),
homeLineRef,
homePieRef,
homeBarRef,
userInfo,
...toRefs(state),
HomeBg,
msgMore,
};
},
});
@@ -554,6 +630,20 @@ export default defineComponent({
<style scoped lang="scss">
$homeNavLengh: 8;
.text-container {
width: 420px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.text-container:hover {
animation: scrollText 5s linear infinite;
}
@keyframes scrollText {
0% { transform: translateX(0); }
100% { transform: translateX(-100%); }
}
.home-container {
overflow: hidden;
.home-card-one,
@@ -561,21 +651,21 @@ $homeNavLengh: 8;
.home-card-three {
.home-card-item {
width: 100%;
height: 130px;
border-radius: 4px;
height: 120px;
transition: all ease 0.3s;
padding: 20px;
overflow: hidden;
background: var(--el-color-white);
color: var(--el-text-color-primary);
border: 1px solid var(--next-border-color-light);
border-radius: 24px;
&:hover {
box-shadow: 0 2px 12px var(--next-color-dark-hover);
transition: all ease 0.3s;
}
&-icon {
width: 70px;
height: 70px;
width: 55px;
height: 55px;
border-radius: 100%;
flex-shrink: 1;
i {
@@ -583,13 +673,15 @@ $homeNavLengh: 8;
}
}
&-title {
font-size: 15px;
font-size: 16px;
font-weight: bold;
height: 30px;
}
}
}
.home-card-one {
left:15px;
right: 15px;
@for $i from 0 through 3 {
.home-one-animation#{$i} {
opacity: 0;
@@ -602,6 +694,9 @@ $homeNavLengh: 8;
}
.home-card-two,
.home-card-three {
position: relative;
left: 15px;
right: 15px;
.home-card-item {
height: 400px;
width: 100%;
@@ -626,7 +721,7 @@ $homeNavLengh: 8;
transition: all 0.3s ease;
}
}
@for $i from 0 through $homeNavLengh {
@for $i from 0 through 3 {
.home-animation#{$i} {
opacity: 0;
animation-name: error-num;
@@ -641,3 +736,4 @@ $homeNavLengh: 8;
}
}
</style>

View File

@@ -187,8 +187,8 @@ export default defineComponent({
// 初始化登录成功时间问候语
let currentTimeInfo = currentTime.value;
// 登录成功,跳到转首页
const pwd_change_count = userInfos.value.pwd_change_count
if(pwd_change_count>0){
const pwd_change_count = userInfos.value.pwd_change_count ?? 0
if(pwd_change_count > 0){
// 如果是复制粘贴的路径,非首页/登录页,那么登录成功后重定向到对应的路径中
if (route.query?.redirect) {
router.push({
@@ -234,16 +234,37 @@ export default defineComponent({
</script>
<style scoped lang="scss">
// 定义error-num动画的关键帧
@keyframes error-num {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.login-content-form {
margin-top: 20px;
// 为输入框添加圆角和设置字体大小
:deep(.el-input__wrapper) {
border-radius: 8px !important;
}
// 设置输入框文字大小
:deep(.el-input__inner) {
font-size: 12px !important; // Element Plus large尺寸的默认字体大小
}
@for $i from 1 through 4 {
.login-animation#{$i} {
opacity: 0;
animation-name: error-num;
animation-duration: 0.5s;
animation-fill-mode: forwards;
animation-delay: calc($i/10) + s;
animation-delay: #{$i/10}s;
}
}
@@ -253,7 +274,7 @@ export default defineComponent({
cursor: pointer;
&:hover {
color: #909399;
color: #909397;
}
}
@@ -262,6 +283,7 @@ export default defineComponent({
padding: 0;
font-weight: bold;
letter-spacing: 5px;
border-radius: 8px !important;
}
.login-content-submit {
@@ -269,6 +291,7 @@ export default defineComponent({
letter-spacing: 2px;
font-weight: 800;
margin-top: 15px;
border-radius:8px;
}
}
</style>

View File

@@ -239,6 +239,15 @@ export default defineComponent({
.login-content-form {
margin-top: 20px;
// 为输入框添加圆角和设置字体大小
:deep(.el-input__wrapper) {
border-radius: 8px !important;
}
// 设置输入框文字大小
:deep(.el-input__inner) {
font-size: 12px !important; // Element Plus large尺寸的默认字体大小
}
@for $i from 1 through 5 {
.login-animation#{$i} {
opacity: 0;
@@ -264,6 +273,7 @@ export default defineComponent({
padding: 0;
font-weight: bold;
letter-spacing: 5px;
border-radius: 8px !important;
}
.login-content-submit {
@@ -271,6 +281,7 @@ export default defineComponent({
letter-spacing: 2px;
font-weight: 800;
margin-top: 15px;
border-radius:8px;
}
}
</style>

View File

@@ -5,8 +5,6 @@
<img :src="siteLogo" />
<div class="login-left-logo-text">
<span>{{ getSystemConfig['login.site_title'] || getThemeConfig.globalViceTitle }}</span>
<span class="login-left-logo-text-msg" style="margin-top: 5px;">{{
getSystemConfig['login.site_name'] || getThemeConfig.globalViceTitleMsg }}</span>
</div>
</div>
</div>
@@ -16,7 +14,9 @@
<!-- <span class="login-right-warp-two"></span>-->
<div class="login-right-warp-mian">
<div class="login-right-warp-main-title">
{{userInfos.pwd_change_count===0?'初次登录修改密码':'欢迎登录'}}
<span>{{getSystemConfig['login.site_name'] || getThemeConfig.globalViceTitleMsg }}</span>
<br>
<span>{{userInfos.pwd_change_count===0?'初次登录请修改密码':'欢迎登录'}}</span>
</div>
<div class="login-right-warp-main-form">
<div v-if="!state.isScan">
@@ -168,14 +168,11 @@ onMounted(() => {
span {
margin-left: 10px;
font-size: 16px;
font-size: 24px;
color: var(--el-color-primary);
}
.login-left-logo-text-msg {
font-size: 12px;
color: var(--el-color-primary);
}
}
}
@@ -280,10 +277,10 @@ onMounted(() => {
flex-direction: column;
height: 100%;
.login-right-warp-main-title {
height: 130px;
line-height: 130px;
font-size: 32px;
font-size: 24px;
font-weight: 600;
text-align: center;
letter-spacing: 3px;
@@ -347,7 +344,7 @@ onMounted(() => {
text-align: center;
p {
font-size: 14px;
font-size: 12px;
color: rgba(0, 0, 0, 0.5);
}

View File

@@ -2,7 +2,7 @@ import vue from '@vitejs/plugin-vue';
import { resolve } from 'path';
import { defineConfig, loadEnv, ConfigEnv } from 'vite';
import vueSetupExtend from 'vite-plugin-vue-setup-extend';
import vueJsx from '@vitejs/plugin-vue-jsx'
// import vueJsx from '@vitejs/plugin-vue-jsx'
import { generateVersionFile } from "/@/utils/upgrade";
const pathResolve = (dir: string) => {
@@ -22,7 +22,7 @@ const viteConfig = defineConfig((mode: ConfigEnv) => {
// 当Vite构建时生成版本文件
generateVersionFile()
return {
plugins: [vue(), vueJsx(), vueSetupExtend()],
plugins: [vue(), /* vueJsx(), */ vueSetupExtend()],
root: process.cwd(),
resolve: { alias },
base: mode.command === 'serve' ? './' : env.VITE_PUBLIC_PATH,