mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 08:13:43 +08:00 
			
		
		
		
	feat: change theme and index style
This commit is contained in:
		
							
								
								
									
										18923
									
								
								web/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										18923
									
								
								web/package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -10,6 +10,7 @@
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@element-plus/icons-vue": "^2.1.0",
 | 
			
		||||
    "@openai/realtime-api-beta": "github:openai/openai-realtime-api-beta",
 | 
			
		||||
    "animate.css": "^4.1.1",
 | 
			
		||||
    "axios": "^0.27.2",
 | 
			
		||||
    "clipboard": "^2.0.11",
 | 
			
		||||
    "compressorjs": "^1.2.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,19 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="zh-cn">
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="utf-8">
 | 
			
		||||
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
 | 
			
		||||
    <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no">
 | 
			
		||||
<html lang="zh-cn" data-theme="light">
 | 
			
		||||
  <head>
 | 
			
		||||
    <meta charset="utf-8" />
 | 
			
		||||
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
 | 
			
		||||
    <meta
 | 
			
		||||
      name="viewport"
 | 
			
		||||
      content="width=device-width,initial-scale=1.0,user-scalable=no"
 | 
			
		||||
    />
 | 
			
		||||
    <title>Geek-AI 创作助手</title>
 | 
			
		||||
</head>
 | 
			
		||||
  </head>
 | 
			
		||||
 | 
			
		||||
<body>
 | 
			
		||||
<noscript>
 | 
			
		||||
    <strong>请开启JavaScript支持</strong>
 | 
			
		||||
</noscript>
 | 
			
		||||
<div id="app"></div>
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
  <body>
 | 
			
		||||
    <noscript>
 | 
			
		||||
      <strong>请开启JavaScript支持</strong>
 | 
			
		||||
    </noscript>
 | 
			
		||||
    <div id="app"></div>
 | 
			
		||||
  </body>
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										9
									
								
								web/src/assets/css/common.styl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								web/src/assets/css/common.styl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
			
		||||
.btn-go{
 | 
			
		||||
  background:  var(--btnColor);
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  border-radius: 5px;
 | 
			
		||||
  padding: 5px 10px;
 | 
			
		||||
  &:hover{
 | 
			
		||||
    color: #fff;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								web/src/assets/css/font.styl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								web/src/assets/css/font.styl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
@font-face {
 | 
			
		||||
  font-family: "OPlusSans3-Regular";
 | 
			
		||||
  src: url("../fonts/OPlusSans3-Regular.ttf") format("truetype");
 | 
			
		||||
  font-weight: normal;
 | 
			
		||||
  font-style: normal;
 | 
			
		||||
}
 | 
			
		||||
@font-face {
 | 
			
		||||
  font-family: "OPlusSans3-Medium";
 | 
			
		||||
  src: url("../fonts/OPlusSans3-Medium.ttf") format("truetype");
 | 
			
		||||
  font-weight: normal;
 | 
			
		||||
  font-style: normal;
 | 
			
		||||
}
 | 
			
		||||
$font-regular = "OPlusSans3-Regular", "PingFangSC-Regular", "Roboto", "sans-serif";
 | 
			
		||||
$font-medium = "OPlusSans3-Medium", "PingFangSC-Medium", "Roboto", "sans-serif";
 | 
			
		||||
 | 
			
		||||
.font-regular {
 | 
			
		||||
  font-family: $font-regular;
 | 
			
		||||
  font-weight: normal;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.font-medium {
 | 
			
		||||
  font-family: $font-medium;
 | 
			
		||||
  font-weight: 500;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +1,8 @@
 | 
			
		||||
 | 
			
		||||
.index-page {
 | 
			
		||||
  margin: 0
 | 
			
		||||
  overflow hidden
 | 
			
		||||
  color #ffffff
 | 
			
		||||
  color var(--text-color)
 | 
			
		||||
  display flex
 | 
			
		||||
  justify-content center
 | 
			
		||||
  align-items baseline
 | 
			
		||||
@@ -47,11 +48,20 @@
 | 
			
		||||
        display flex
 | 
			
		||||
        padding 20px 0
 | 
			
		||||
 | 
			
		||||
        color #ffffff
 | 
			
		||||
        color var(--text-color);
 | 
			
		||||
        .iconfont{
 | 
			
		||||
          color var(--text-color);
 | 
			
		||||
          font-size: 28px;
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        .icon-book{
 | 
			
		||||
          margin-right: 6px;
 | 
			
		||||
        }
 | 
			
		||||
        .title {
 | 
			
		||||
          font-size 24px
 | 
			
		||||
          color var(--text-color);
 | 
			
		||||
          font-size: 24px;
 | 
			
		||||
          padding 10px 10px 0 10px
 | 
			
		||||
          font-weight: 700;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .logo {
 | 
			
		||||
@@ -112,6 +122,34 @@
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      .nav-item-box{
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        border-radius: 8px;
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
        transition:  all 0.2s cubic-bezier(0.645,0.045,0.355,1);
 | 
			
		||||
        aspect-ratio: 1.1028 / 1;
 | 
			
		||||
        background: var( --card-bg)
 | 
			
		||||
       display: flex;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        justify-content: center;
 | 
			
		||||
        min-width: 160px
 | 
			
		||||
        // min-height: 190px;
 | 
			
		||||
        i{
 | 
			
		||||
          display: inline-block
 | 
			
		||||
          min-width: 48px;
 | 
			
		||||
          width: 48px;
 | 
			
		||||
          height: 48px;
 | 
			
		||||
          font-size: 38px
 | 
			
		||||
          border-radius: 24px;
 | 
			
		||||
          color: var(--normal-color)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &:hover{
 | 
			
		||||
          box-shadow: 0 4px 14px 0 rgba(17, 13, 83, .18);
 | 
			
		||||
          transform: translateY(-8px);}
 | 
			
		||||
        
 | 
			
		||||
       }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -121,4 +159,38 @@
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.cursor-ani {
 | 
			
		||||
   position: relative;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
.cursor-ani::after {
 | 
			
		||||
   content: '';
 | 
			
		||||
   position: absolute;
 | 
			
		||||
   width: 1px;
 | 
			
		||||
   height: 28px;
 | 
			
		||||
   background: #333;
 | 
			
		||||
   transform: translateX(3px) translateY(3px);
 | 
			
		||||
   animation: cursor-blinks 0.8s infinite forwards;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@keyframes cursor-blinks {
 | 
			
		||||
   from {
 | 
			
		||||
     opacity: 0;
 | 
			
		||||
   }
 | 
			
		||||
 
 | 
			
		||||
   to {
 | 
			
		||||
     opacity: 1;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
.cursor-ani {
 | 
			
		||||
  display: inline-block;
 | 
			
		||||
  min-height: 34px;
 | 
			
		||||
  font-size: 1.5em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.msg-text span {
 | 
			
		||||
  transition: color 0.3s ease; /* 平滑的颜色过渡 */
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								web/src/assets/css/theme-dark.styl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								web/src/assets/css/theme-dark.styl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
			
		||||
 | 
			
		||||
@import 'font.styl'
 | 
			
		||||
:root[data-theme="dark"]{
 | 
			
		||||
  --text-color: rgba(255, 255, 255, 1) !important; // 主要的文本颜色
 | 
			
		||||
  --normal-color: rgba(163, 174, 208, 1); // 普通颜色
 | 
			
		||||
  p, h1, h2, h3, h4, h5, h6, article {
 | 
			
		||||
    color: var(--text-color) !important;
 | 
			
		||||
     font-family: $font-regular;
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
  html,
 | 
			
		||||
  body,
 | 
			
		||||
  #app,
 | 
			
		||||
  .wrapper {
 | 
			
		||||
   background-color: rgb(13, 20, 53) !important;
 | 
			
		||||
    font-family: $font-regular;
 | 
			
		||||
  }
 | 
			
		||||
  --btnColor: linear-gradient(88deg, #af61f0 1.44%, #5b62ce);
 | 
			
		||||
  --card-bg: rgba(17, 28, 68, 1);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								web/src/assets/css/theme-light.styl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								web/src/assets/css/theme-light.styl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@import 'font.styl'
 | 
			
		||||
:root[data-theme="light"] {
 | 
			
		||||
  // rgba(43, 54, 116, 1)
 | 
			
		||||
  --text-color: #5b62ce; // 主要的文本颜色
 | 
			
		||||
  --normal-color: rgba(43, 54, 116, 1); // 普通颜色
 | 
			
		||||
  p, h1, h2, h3, h4, h5, h6, article {
 | 
			
		||||
    color: var(--text-color) !important;
 | 
			
		||||
    font-family: $font-regular;
 | 
			
		||||
  }
 | 
			
		||||
  html,
 | 
			
		||||
  body,
 | 
			
		||||
  #app,
 | 
			
		||||
  .wrapper {
 | 
			
		||||
      background: linear-gradient(88deg, #fff3f3 1.44%, #e7e8ff);
 | 
			
		||||
    //  background:  linear-gradient(180deg, #fff, #fff4fa 40%, #fbd9fd 55%, #e2d5ff 70%);
 | 
			
		||||
    font-family: $font-regular;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  --btnColor: linear-gradient(88deg, #af61f0 1.44%, #5b62ce);
 | 
			
		||||
  --card-bg:#fff;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										0
									
								
								web/src/assets/css/variables.styl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								web/src/assets/css/variables.styl
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										
											BIN
										
									
								
								web/src/assets/fonts/OPlusSans3-Medium.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								web/src/assets/fonts/OPlusSans3-Medium.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								web/src/assets/fonts/OPlusSans3-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								web/src/assets/fonts/OPlusSans3-Regular.ttf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -1,8 +1,9 @@
 | 
			
		||||
 | 
			
		||||
@font-face {
 | 
			
		||||
  font-family: "iconfont"; /* Project id 4125778 */
 | 
			
		||||
  src: url('iconfont.woff2?t=1731289567907') format('woff2'),
 | 
			
		||||
       url('iconfont.woff?t=1731289567907') format('woff'),
 | 
			
		||||
       url('iconfont.ttf?t=1731289567907') format('truetype');
 | 
			
		||||
  font-family: 'iconfont';  /* Project id 4125778 */
 | 
			
		||||
  src: url('//at.alicdn.com/t/c/font_4125778_gs96jfl3hlc.woff2?t=1732009095144') format('woff2'),
 | 
			
		||||
       url('//at.alicdn.com/t/c/font_4125778_gs96jfl3hlc.woff?t=1732009095144') format('woff'),
 | 
			
		||||
       url('//at.alicdn.com/t/c/font_4125778_gs96jfl3hlc.ttf?t=1732009095144') format('truetype');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.iconfont {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,11 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="foot-container">
 | 
			
		||||
    <div class="footer">
 | 
			
		||||
      <div><span :style="{color:textColor}">{{copyRight}}</span></div>
 | 
			
		||||
      <div>
 | 
			
		||||
        <span>{{ copyRight }}</span>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div v-if="!license.de_copy">
 | 
			
		||||
        <a :href="gitURL" target="_blank" :style="{color:textColor}">
 | 
			
		||||
        <a :href="gitURL" target="_blank">
 | 
			
		||||
          {{ title }} -
 | 
			
		||||
          {{ version }}
 | 
			
		||||
        </a>
 | 
			
		||||
@@ -12,37 +14,45 @@
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script setup>
 | 
			
		||||
import { ref } from "vue";
 | 
			
		||||
import { httpGet } from "@/utils/http";
 | 
			
		||||
import { showMessageError } from "@/utils/dialog";
 | 
			
		||||
import { getLicenseInfo, getSystemInfo } from "@/store/cache";
 | 
			
		||||
 | 
			
		||||
import {ref} from "vue";
 | 
			
		||||
import {httpGet} from "@/utils/http";
 | 
			
		||||
import {showMessageError} from "@/utils/dialog";
 | 
			
		||||
import {getLicenseInfo, getSystemInfo} from "@/store/cache";
 | 
			
		||||
 | 
			
		||||
const title = ref("")
 | 
			
		||||
const version = ref(process.env.VUE_APP_VERSION)
 | 
			
		||||
const gitURL = ref(process.env.VUE_APP_GIT_URL)
 | 
			
		||||
const copyRight = ref('')
 | 
			
		||||
const license = ref({})
 | 
			
		||||
const title = ref("");
 | 
			
		||||
const version = ref(process.env.VUE_APP_VERSION);
 | 
			
		||||
const gitURL = ref(process.env.VUE_APP_GIT_URL);
 | 
			
		||||
const copyRight = ref("");
 | 
			
		||||
const license = ref({});
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
  textColor: {
 | 
			
		||||
    type: String,
 | 
			
		||||
    default: '#ffffff'
 | 
			
		||||
  },
 | 
			
		||||
    default: "#ffffff"
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 获取系统配置
 | 
			
		||||
getSystemInfo().then(res => {
 | 
			
		||||
  title.value = res.data.title??process.env.VUE_APP_TITLE
 | 
			
		||||
  copyRight.value = res.data.copyright.length>1?res.data.copyright:'极客学长 © 2023 - '+new Date().getFullYear()+' All rights reserved.'
 | 
			
		||||
}).catch(e => {
 | 
			
		||||
  showMessageError("获取系统配置失败:" + e.message)
 | 
			
		||||
})
 | 
			
		||||
getSystemInfo()
 | 
			
		||||
  .then((res) => {
 | 
			
		||||
    title.value = res.data.title ?? process.env.VUE_APP_TITLE;
 | 
			
		||||
    copyRight.value =
 | 
			
		||||
      res.data.copyright.length > 1
 | 
			
		||||
        ? res.data.copyright
 | 
			
		||||
        : "极客学长 © 2023 - " +
 | 
			
		||||
          new Date().getFullYear() +
 | 
			
		||||
          " All rights reserved.";
 | 
			
		||||
  })
 | 
			
		||||
  .catch((e) => {
 | 
			
		||||
    showMessageError("获取系统配置失败:" + e.message);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
getLicenseInfo().then(res => {
 | 
			
		||||
  license.value = res.data
 | 
			
		||||
}).catch(e => {
 | 
			
		||||
  showMessageError("获取 License 失败:" + e.message)
 | 
			
		||||
})
 | 
			
		||||
getLicenseInfo()
 | 
			
		||||
  .then((res) => {
 | 
			
		||||
    license.value = res.data;
 | 
			
		||||
  })
 | 
			
		||||
  .catch((e) => {
 | 
			
		||||
    showMessageError("获取 License 失败:" + e.message);
 | 
			
		||||
  });
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="stylus">
 | 
			
		||||
@@ -62,11 +72,15 @@ getLicenseInfo().then(res => {
 | 
			
		||||
    width 100%
 | 
			
		||||
 | 
			
		||||
    a {
 | 
			
		||||
      color:var(--text-color)
 | 
			
		||||
 | 
			
		||||
      &:hover {
 | 
			
		||||
        text-decoration underline
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    span{
 | 
			
		||||
      color:var(--text-color)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</style>
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										56
									
								
								web/src/components/ThemeChange.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								web/src/components/ThemeChange.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="theme-box" @click="toggleTheme">
 | 
			
		||||
    <span class="iconfont icon-yueliang">{{
 | 
			
		||||
      themePage === "light" ? "" : ""
 | 
			
		||||
    }}</span>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import { onMounted, ref } from "vue";
 | 
			
		||||
 | 
			
		||||
// 定义主题状态,初始值从 localStorage 获取
 | 
			
		||||
const themePage = ref(localStorage.getItem("theme") || "light");
 | 
			
		||||
 | 
			
		||||
// 切换主题函数
 | 
			
		||||
const toggleTheme = () => {
 | 
			
		||||
  themePage.value = themePage.value === "light" ? "dark" : "light";
 | 
			
		||||
  document.documentElement.setAttribute("data-theme", themePage.value); // 设置 HTML 的 data-theme 属性
 | 
			
		||||
  localStorage.setItem("theme", themePage.value); // 保存主题到 localStorage
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  document.documentElement.setAttribute("data-theme", themePage.value);
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="stylus" scoped>
 | 
			
		||||
@import '@/assets/iconfont/iconfont.css'
 | 
			
		||||
.theme-box{
 | 
			
		||||
  position: fixed;
 | 
			
		||||
  right: 40px;
 | 
			
		||||
  bottom: 262px;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  background-color: #fff;
 | 
			
		||||
  border: 1px solid #ccc;
 | 
			
		||||
  border-radius: 50%;
 | 
			
		||||
  width 35px;
 | 
			
		||||
  height: 35px;
 | 
			
		||||
  line-height: 35px;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  background-color: rgb(146, 147, 148);
 | 
			
		||||
 | 
			
		||||
  transition: all 0.3s ease;
 | 
			
		||||
  &:hover{
 | 
			
		||||
    transform: scale(1.1);
 | 
			
		||||
  }
 | 
			
		||||
  &:active{
 | 
			
		||||
    transform: scale(0.9);
 | 
			
		||||
  }
 | 
			
		||||
  .iconfont{
 | 
			
		||||
    font-size: 20px;
 | 
			
		||||
    color: yellow;
 | 
			
		||||
    transition: transform 0.3s ease;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
							
								
								
									
										147
									
								
								web/src/main.js
									
									
									
									
									
								
							
							
						
						
									
										147
									
								
								web/src/main.js
									
									
									
									
									
								
							@@ -5,63 +5,74 @@
 | 
			
		||||
// * @Author yangjian102621@163.com
 | 
			
		||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 | 
			
		||||
 | 
			
		||||
import {createApp} from 'vue'
 | 
			
		||||
import ElementPlus from "element-plus"
 | 
			
		||||
import "element-plus/dist/index.css"
 | 
			
		||||
import '@/assets/iconfont/iconfont.css';
 | 
			
		||||
import 'vant/lib/index.css';
 | 
			
		||||
import App from './App.vue'
 | 
			
		||||
import {createPinia} from "pinia";
 | 
			
		||||
import { createApp } from "vue";
 | 
			
		||||
import ElementPlus from "element-plus";
 | 
			
		||||
import "element-plus/dist/index.css";
 | 
			
		||||
import "@/assets/iconfont/iconfont.css";
 | 
			
		||||
import "vant/lib/index.css";
 | 
			
		||||
import App from "./App.vue";
 | 
			
		||||
import { useThemeStore } from "@/store/theme";
 | 
			
		||||
import { createPinia } from "pinia";
 | 
			
		||||
import "animate.css/animate.min.css";
 | 
			
		||||
import {
 | 
			
		||||
    ActionSheet,
 | 
			
		||||
    Badge,
 | 
			
		||||
    Button,
 | 
			
		||||
    Cell,
 | 
			
		||||
    CellGroup,
 | 
			
		||||
    Circle,
 | 
			
		||||
    Col,
 | 
			
		||||
    Collapse,
 | 
			
		||||
    CollapseItem,
 | 
			
		||||
    ConfigProvider,
 | 
			
		||||
    Dialog,
 | 
			
		||||
    Divider,
 | 
			
		||||
    DropdownItem,
 | 
			
		||||
    DropdownMenu,
 | 
			
		||||
    Empty,
 | 
			
		||||
    Field,
 | 
			
		||||
    Form,
 | 
			
		||||
    Grid,
 | 
			
		||||
    GridItem,
 | 
			
		||||
    Icon,
 | 
			
		||||
    Image,
 | 
			
		||||
    ImagePreview,
 | 
			
		||||
    Lazyload,
 | 
			
		||||
    List,
 | 
			
		||||
    Loading,
 | 
			
		||||
    NavBar,
 | 
			
		||||
    NoticeBar,
 | 
			
		||||
    Notify,
 | 
			
		||||
    Overlay,
 | 
			
		||||
    Picker,
 | 
			
		||||
    Popup,
 | 
			
		||||
    Row,
 | 
			
		||||
    Search,
 | 
			
		||||
    ShareSheet,
 | 
			
		||||
    Slider,
 | 
			
		||||
    Sticky,
 | 
			
		||||
    SwipeCell,
 | 
			
		||||
    Switch,
 | 
			
		||||
    Tab,
 | 
			
		||||
    Tabbar,
 | 
			
		||||
    TabbarItem,
 | 
			
		||||
    Tabs,
 | 
			
		||||
    Tag,
 | 
			
		||||
    TextEllipsis,
 | 
			
		||||
    Uploader
 | 
			
		||||
  ActionSheet,
 | 
			
		||||
  Badge,
 | 
			
		||||
  Button,
 | 
			
		||||
  Cell,
 | 
			
		||||
  CellGroup,
 | 
			
		||||
  Circle,
 | 
			
		||||
  Col,
 | 
			
		||||
  Collapse,
 | 
			
		||||
  CollapseItem,
 | 
			
		||||
  ConfigProvider,
 | 
			
		||||
  Dialog,
 | 
			
		||||
  Divider,
 | 
			
		||||
  DropdownItem,
 | 
			
		||||
  DropdownMenu,
 | 
			
		||||
  Empty,
 | 
			
		||||
  Field,
 | 
			
		||||
  Form,
 | 
			
		||||
  Grid,
 | 
			
		||||
  GridItem,
 | 
			
		||||
  Icon,
 | 
			
		||||
  Image,
 | 
			
		||||
  ImagePreview,
 | 
			
		||||
  Lazyload,
 | 
			
		||||
  List,
 | 
			
		||||
  Loading,
 | 
			
		||||
  NavBar,
 | 
			
		||||
  NoticeBar,
 | 
			
		||||
  Notify,
 | 
			
		||||
  Overlay,
 | 
			
		||||
  Picker,
 | 
			
		||||
  Popup,
 | 
			
		||||
  Row,
 | 
			
		||||
  Search,
 | 
			
		||||
  ShareSheet,
 | 
			
		||||
  Slider,
 | 
			
		||||
  Sticky,
 | 
			
		||||
  SwipeCell,
 | 
			
		||||
  Switch,
 | 
			
		||||
  Tab,
 | 
			
		||||
  Tabbar,
 | 
			
		||||
  TabbarItem,
 | 
			
		||||
  Tabs,
 | 
			
		||||
  Tag,
 | 
			
		||||
  TextEllipsis,
 | 
			
		||||
  Uploader
 | 
			
		||||
} from "vant";
 | 
			
		||||
import {router} from "@/router";
 | 
			
		||||
import 'v3-waterfall/dist/style.css'
 | 
			
		||||
import { router } from "@/router";
 | 
			
		||||
import "v3-waterfall/dist/style.css";
 | 
			
		||||
import V3waterfall from "v3-waterfall";
 | 
			
		||||
import "@/assets/css/theme-dark.styl";
 | 
			
		||||
import "@/assets/css/theme-light.styl";
 | 
			
		||||
import "@/assets/css/common.styl";
 | 
			
		||||
 | 
			
		||||
const pinia = createPinia();
 | 
			
		||||
const themeStore = useThemeStore(pinia); // 使用 theme store
 | 
			
		||||
 | 
			
		||||
// 设置初始主题
 | 
			
		||||
document.documentElement.setAttribute("data-theme", themeStore.theme);
 | 
			
		||||
 | 
			
		||||
const app = createApp(App);
 | 
			
		||||
app.use(createPinia());
 | 
			
		||||
@@ -70,12 +81,12 @@ app.use(Tabbar);
 | 
			
		||||
app.use(TabbarItem);
 | 
			
		||||
app.use(NavBar);
 | 
			
		||||
app.use(Search);
 | 
			
		||||
app.use(Cell)
 | 
			
		||||
app.use(Image)
 | 
			
		||||
app.use(TextEllipsis)
 | 
			
		||||
app.use(Notify)
 | 
			
		||||
app.use(Picker)
 | 
			
		||||
app.use(Popup)
 | 
			
		||||
app.use(Cell);
 | 
			
		||||
app.use(Image);
 | 
			
		||||
app.use(TextEllipsis);
 | 
			
		||||
app.use(Notify);
 | 
			
		||||
app.use(Picker);
 | 
			
		||||
app.use(Popup);
 | 
			
		||||
app.use(List);
 | 
			
		||||
app.use(Form);
 | 
			
		||||
app.use(Field);
 | 
			
		||||
@@ -91,12 +102,12 @@ app.use(ShareSheet);
 | 
			
		||||
app.use(Switch);
 | 
			
		||||
app.use(Uploader);
 | 
			
		||||
app.use(Tag);
 | 
			
		||||
app.use(V3waterfall)
 | 
			
		||||
app.use(Overlay)
 | 
			
		||||
app.use(Col)
 | 
			
		||||
app.use(Row)
 | 
			
		||||
app.use(Slider)
 | 
			
		||||
app.use(Badge)
 | 
			
		||||
app.use(V3waterfall);
 | 
			
		||||
app.use(Overlay);
 | 
			
		||||
app.use(Col);
 | 
			
		||||
app.use(Row);
 | 
			
		||||
app.use(Slider);
 | 
			
		||||
app.use(Badge);
 | 
			
		||||
app.use(Collapse);
 | 
			
		||||
app.use(CollapseItem);
 | 
			
		||||
app.use(Grid);
 | 
			
		||||
@@ -111,6 +122,4 @@ app.use(Tabs);
 | 
			
		||||
app.use(Divider);
 | 
			
		||||
app.use(NoticeBar);
 | 
			
		||||
app.use(ActionSheet);
 | 
			
		||||
app.use(router).use(ElementPlus).mount('#app')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
app.use(router).use(ElementPlus).mount("#app");
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								web/src/store/theme.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								web/src/store/theme.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
// src/store/index.js
 | 
			
		||||
import { defineStore } from "pinia";
 | 
			
		||||
 | 
			
		||||
export const useThemeStore = defineStore("theme", {
 | 
			
		||||
  state: () => ({
 | 
			
		||||
    theme: localStorage.getItem("theme") || "light" // 默认从 localStorage 获取主题
 | 
			
		||||
  }),
 | 
			
		||||
  actions: {
 | 
			
		||||
    setTheme(theme) {
 | 
			
		||||
      this.theme = theme;
 | 
			
		||||
      document.documentElement.setAttribute("data-theme", theme);
 | 
			
		||||
      localStorage.setItem("theme", theme); // 保存到 localStorage
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
@@ -1,178 +1,194 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="index-page" :style="{height: winHeight+'px'}">
 | 
			
		||||
    <div :class="theme.imageBg?'color-bg image-bg':'color-bg'" :style="{backgroundImage:'url('+bgStyle.backgroundImage+')', backgroundColor:bgStyle.backgroundColor}"></div>
 | 
			
		||||
  <div class="index-page">
 | 
			
		||||
    <ThemeChange />
 | 
			
		||||
    <div class="menu-box">
 | 
			
		||||
      <el-menu
 | 
			
		||||
          mode="horizontal"
 | 
			
		||||
          :ellipsis="false"
 | 
			
		||||
      >
 | 
			
		||||
      <el-menu mode="horizontal" :ellipsis="false">
 | 
			
		||||
        <div class="menu-item">
 | 
			
		||||
          <el-image :src="logo" class="logo" alt="Geek-AI"/>
 | 
			
		||||
          <div class="title" :style="{color:theme.textColor}">{{ title }}</div>
 | 
			
		||||
          <el-image :src="logo" class="logo" alt="Geek-AI" />
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="menu-item">
 | 
			
		||||
          <span v-if="!license.de_copy">
 | 
			
		||||
            <a :href="docsURL" target="_blank">
 | 
			
		||||
            <el-button :color="theme.btnBgColor" :style="{color: theme.btnTextColor}" class="shadow" round>
 | 
			
		||||
              <i class="iconfont icon-book"></i>
 | 
			
		||||
              <span>文档</span>
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </a>
 | 
			
		||||
 | 
			
		||||
          <a :href="gitURL" target="_blank">
 | 
			
		||||
            <el-button :color="theme.btnBgColor" :style="{color: theme.btnTextColor}" class="shadow" round>
 | 
			
		||||
              <i class="iconfont icon-github"></i>
 | 
			
		||||
              <span>源码</span>
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </a>
 | 
			
		||||
            <el-tooltip
 | 
			
		||||
              v-if="!license.de_copy"
 | 
			
		||||
              class="box-item"
 | 
			
		||||
              effect="light"
 | 
			
		||||
              content="部署文档"
 | 
			
		||||
              placement="bottom"
 | 
			
		||||
            >
 | 
			
		||||
              <a :href="docsURL" class="link-button" target="_blank">
 | 
			
		||||
                <i class="iconfont icon-book"></i>
 | 
			
		||||
              </a>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
            <el-tooltip
 | 
			
		||||
              v-if="!license.de_copy"
 | 
			
		||||
              class="box-item"
 | 
			
		||||
              effect="light"
 | 
			
		||||
              content="项目源码"
 | 
			
		||||
              placement="bottom"
 | 
			
		||||
            >
 | 
			
		||||
              <a :href="gitURL" class="link-button" target="_blank">
 | 
			
		||||
                <i class="iconfont icon-github"></i>
 | 
			
		||||
              </a>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </span>
 | 
			
		||||
 | 
			
		||||
          <span v-if="!isLogin">
 | 
			
		||||
            <el-button :color="theme.btnBgColor" :style="{color: theme.btnTextColor}" @click="router.push('/login')" class="shadow" round>登录</el-button>
 | 
			
		||||
            <el-button :color="theme.btnBgColor" :style="{color: theme.btnTextColor}" @click="router.push('/register')" class="shadow" round>注册</el-button>
 | 
			
		||||
            <!-- <el-button @click="router.push('/login')" class="shadow" round
 | 
			
		||||
              >登录</el-button
 | 
			
		||||
            >
 | 
			
		||||
            <el-button @click="router.push('/register')" class="shadow" round
 | 
			
		||||
              >注册</el-button
 | 
			
		||||
            > -->
 | 
			
		||||
            <el-button
 | 
			
		||||
              @click="router.push('/login')"
 | 
			
		||||
              class="btn-go animate__animated animate__pulse animate__infinite"
 | 
			
		||||
              round
 | 
			
		||||
              >登录/注册</el-button
 | 
			
		||||
            >
 | 
			
		||||
          </span>
 | 
			
		||||
        </div>
 | 
			
		||||
      </el-menu>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="content">
 | 
			
		||||
      <h1 :style="{color:theme.textColor}">欢迎使用 {{ title }}</h1>
 | 
			
		||||
      <p :style="{color:theme.textColor}">{{ slogan }}</p>
 | 
			
		||||
      <h1 class="animate__animated animate__backInDown">
 | 
			
		||||
        {{ title }}
 | 
			
		||||
      </h1>
 | 
			
		||||
      <div class="msg-text cursor-ani">
 | 
			
		||||
        <span
 | 
			
		||||
          v-for="(char, index) in displayedChars"
 | 
			
		||||
          :key="index"
 | 
			
		||||
          :style="{ color: rainbowColor(index) }"
 | 
			
		||||
        >
 | 
			
		||||
          {{ char }}
 | 
			
		||||
        </span>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div class="navs">
 | 
			
		||||
        <el-space wrap>
 | 
			
		||||
          <div v-for="item in navs" :key="item.url" class="nav-item">
 | 
			
		||||
            <el-button @click="router.push(item.url)" :color="theme.btnBgColor" :style="{color: theme.btnTextColor}" class="shadow" :dark="false">
 | 
			
		||||
              <i :class="'iconfont '+iconMap[item.url]"></i>
 | 
			
		||||
              <span>{{item.name}}</span>
 | 
			
		||||
            </el-button>
 | 
			
		||||
      <div class="navs animate__animated animate__backInDown">
 | 
			
		||||
        <el-space wrap :size="14">
 | 
			
		||||
          <div
 | 
			
		||||
            v-for="item in navs"
 | 
			
		||||
            :key="item.url"
 | 
			
		||||
            class="nav-item-box"
 | 
			
		||||
            @click="router.push(item.url)"
 | 
			
		||||
          >
 | 
			
		||||
            <i :class="'iconfont ' + iconMap[item.url]"></i>
 | 
			
		||||
            <div>{{ item.name }}</div>
 | 
			
		||||
          </div>
 | 
			
		||||
        </el-space>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <footer-bar :text-color="theme.textColor" />
 | 
			
		||||
    <footer-bar />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
 | 
			
		||||
import {onMounted, ref} from "vue";
 | 
			
		||||
import {useRouter} from "vue-router";
 | 
			
		||||
import { onMounted, ref } from "vue";
 | 
			
		||||
import { useRouter } from "vue-router";
 | 
			
		||||
import FooterBar from "@/components/FooterBar.vue";
 | 
			
		||||
import {httpGet} from "@/utils/http";
 | 
			
		||||
import {ElMessage} from "element-plus";
 | 
			
		||||
import {checkSession, getLicenseInfo, getSystemInfo} from "@/store/cache";
 | 
			
		||||
import {isMobile} from "@/utils/libs";
 | 
			
		||||
import ThemeChange from "@/components/ThemeChange.vue";
 | 
			
		||||
import { httpGet } from "@/utils/http";
 | 
			
		||||
import { ElMessage } from "element-plus";
 | 
			
		||||
import { checkSession, getLicenseInfo, getSystemInfo } from "@/store/cache";
 | 
			
		||||
import { isMobile } from "@/utils/libs";
 | 
			
		||||
 | 
			
		||||
const router = useRouter()
 | 
			
		||||
const router = useRouter();
 | 
			
		||||
 | 
			
		||||
if (isMobile()) {
 | 
			
		||||
  router.push("/mobile/index")
 | 
			
		||||
  router.push("/mobile/index");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const title = ref("")
 | 
			
		||||
const logo = ref("")
 | 
			
		||||
const slogan = ref("")
 | 
			
		||||
const license = ref({de_copy: true})
 | 
			
		||||
const winHeight = window.innerHeight - 150
 | 
			
		||||
const isLogin = ref(false)
 | 
			
		||||
const docsURL = ref(process.env.VUE_APP_DOCS_URL)
 | 
			
		||||
const gitURL = ref(process.env.VUE_APP_GIT_URL)
 | 
			
		||||
const navs  = ref([])
 | 
			
		||||
const btnColors = ref([
 | 
			
		||||
  {bgColor: "#fff143", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#eaff56", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#bddd22", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#1bd1a5", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#e0eee8", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#7bcfa6", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#bce672", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#44cef6", textColor: "#ffffff"},
 | 
			
		||||
  {bgColor: "#70f3ff", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#fffbf0", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#d6ecf0", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#88ada6", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#30dff3", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#d3e0f3", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#e9e7ef", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#eacd76", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#f2be45", textColor: "#50616D"},
 | 
			
		||||
  {bgColor: "#549688", textColor: "#ffffff"},
 | 
			
		||||
  {bgColor: "#758a99", textColor: "#ffffff"},
 | 
			
		||||
  {bgColor: "#41555d", textColor: "#ffffff"},
 | 
			
		||||
  {bgColor: "#21aa93", textColor: "#ffffff"},
 | 
			
		||||
  {bgColor: "#0aa344", textColor: "#ffffff"},
 | 
			
		||||
  {bgColor: "#f05654", textColor: "#ffffff"},
 | 
			
		||||
  {bgColor: "#db5a6b", textColor: "#ffffff"},
 | 
			
		||||
  {bgColor: "#db5a6b", textColor: "#ffffff"},
 | 
			
		||||
  {bgColor: "#8d4bbb", textColor: "#ffffff"},
 | 
			
		||||
  {bgColor: "#426666", textColor: "#ffffff"},
 | 
			
		||||
  {bgColor: "#177cb0", textColor: "#ffffff"},
 | 
			
		||||
  {bgColor: "#395260", textColor: "#ffffff"},
 | 
			
		||||
  {bgColor: "#519a73", textColor: "#ffffff"},
 | 
			
		||||
  {bgColor: "#75878a", textColor: "#ffffff"},
 | 
			
		||||
])
 | 
			
		||||
const iconMap =ref(
 | 
			
		||||
    {
 | 
			
		||||
      "/chat": "icon-chat",
 | 
			
		||||
      "/mj": "icon-mj",
 | 
			
		||||
      "/sd": "icon-sd",
 | 
			
		||||
      "/dalle": "icon-dalle",
 | 
			
		||||
      "/images-wall": "icon-image",
 | 
			
		||||
      "/suno": "icon-suno",
 | 
			
		||||
      "/xmind": "icon-xmind",
 | 
			
		||||
      "/apps": "icon-app",
 | 
			
		||||
      "/member": "icon-vip-user",
 | 
			
		||||
      "/invite": "icon-share",
 | 
			
		||||
      "/luma": "icon-luma",
 | 
			
		||||
    }
 | 
			
		||||
)
 | 
			
		||||
const bgStyle = {}
 | 
			
		||||
const color = btnColors.value[Math.floor(Math.random() * btnColors.value.length)]
 | 
			
		||||
const theme = ref({bgColor: "#ffffff", btnBgColor: color.bgColor, btnTextColor: color.textColor, textColor: "#ffffff", imageBg:true})
 | 
			
		||||
const title = ref("");
 | 
			
		||||
const logo = ref("");
 | 
			
		||||
const slogan = ref("");
 | 
			
		||||
const license = ref({ de_copy: true });
 | 
			
		||||
 | 
			
		||||
const isLogin = ref(false);
 | 
			
		||||
const docsURL = ref(process.env.VUE_APP_DOCS_URL);
 | 
			
		||||
const gitURL = ref(process.env.VUE_APP_GIT_URL);
 | 
			
		||||
const navs = ref([]);
 | 
			
		||||
 | 
			
		||||
const iconMap = ref({
 | 
			
		||||
  "/chat": "icon-chat",
 | 
			
		||||
  "/mj": "icon-mj",
 | 
			
		||||
  "/sd": "icon-sd",
 | 
			
		||||
  "/dalle": "icon-dalle",
 | 
			
		||||
  "/images-wall": "icon-image",
 | 
			
		||||
  "/suno": "icon-suno",
 | 
			
		||||
  "/xmind": "icon-xmind",
 | 
			
		||||
  "/apps": "icon-app",
 | 
			
		||||
  "/member": "icon-vip-user",
 | 
			
		||||
  "/invite": "icon-share",
 | 
			
		||||
  "/luma": "icon-luma"
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const displayedChars = ref([]);
 | 
			
		||||
const initAnimation = ref("");
 | 
			
		||||
let timer = null; // 定时器句柄
 | 
			
		||||
 | 
			
		||||
// 初始化间隔时间和随机时间数组
 | 
			
		||||
const interTime = ref(50);
 | 
			
		||||
const interArr = [90, 100, 70, 88, 80, 110, 85, 400, 90, 99];
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  getSystemInfo().then(res => {
 | 
			
		||||
    title.value = res.data.title
 | 
			
		||||
    logo.value = res.data.logo
 | 
			
		||||
    if (res.data.index_bg_url === 'color') {
 | 
			
		||||
      // 随机选取一种颜色
 | 
			
		||||
      theme.value.bgColor = color.bgColor
 | 
			
		||||
      theme.value.btnBgColor = color.bgColor
 | 
			
		||||
      theme.value.textColor = color.textColor
 | 
			
		||||
      theme.value.btnTextColor = color.textColor
 | 
			
		||||
      // 设置背景颜色
 | 
			
		||||
      bgStyle.backgroundColor = theme.value.bgColor
 | 
			
		||||
      bgStyle.backgroundImage = "/images/transparent-bg.png"
 | 
			
		||||
      theme.value.imageBg = false
 | 
			
		||||
    } else if (res.data.index_bg_url) {
 | 
			
		||||
      bgStyle.backgroundImage = res.data.index_bg_url
 | 
			
		||||
    } else {
 | 
			
		||||
      bgStyle.backgroundImage = "/images/index-bg.jpg"
 | 
			
		||||
    }
 | 
			
		||||
  getSystemInfo()
 | 
			
		||||
    .then((res) => {
 | 
			
		||||
      title.value = res.data.title;
 | 
			
		||||
      logo.value = res.data.logo;
 | 
			
		||||
      slogan.value = res.data.slogan;
 | 
			
		||||
      if (timer) clearInterval(timer); // 清除定时器
 | 
			
		||||
      timer = setInterval(setContent, interTime.value);
 | 
			
		||||
    })
 | 
			
		||||
    .catch((e) => {
 | 
			
		||||
      ElMessage.error("获取系统配置失败:" + e.message);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    slogan.value = res.data.slogan
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("获取系统配置失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
  getLicenseInfo()
 | 
			
		||||
    .then((res) => {
 | 
			
		||||
      license.value = res.data;
 | 
			
		||||
    })
 | 
			
		||||
    .catch((e) => {
 | 
			
		||||
      license.value = { de_copy: false };
 | 
			
		||||
      ElMessage.error("获取 License 配置失败:" + e.message);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
  getLicenseInfo().then(res => {
 | 
			
		||||
    license.value = res.data
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    license.value = {de_copy: false}
 | 
			
		||||
    ElMessage.error("获取 License 配置失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
  httpGet("/api/menu/list?index=1")
 | 
			
		||||
    .then((res) => {
 | 
			
		||||
      navs.value = res.data;
 | 
			
		||||
    })
 | 
			
		||||
    .catch((e) => {
 | 
			
		||||
      ElMessage.error("获取导航菜单失败:" + e.message);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
  httpGet("/api/menu/list?index=1").then(res => {
 | 
			
		||||
    navs.value = res.data
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("获取导航菜单失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  checkSession().then(() => {
 | 
			
		||||
    isLogin.value = true
 | 
			
		||||
  }).catch(()=>{})
 | 
			
		||||
})
 | 
			
		||||
  checkSession()
 | 
			
		||||
    .then(() => {
 | 
			
		||||
      isLogin.value = true;
 | 
			
		||||
    })
 | 
			
		||||
    .catch(() => {});
 | 
			
		||||
});
 | 
			
		||||
// 打字机内容逐字符显示
 | 
			
		||||
const setContent = () => {
 | 
			
		||||
  if (initAnimation.value.length >= slogan.value.length) {
 | 
			
		||||
    // 文本已全部输出
 | 
			
		||||
    initAnimation.value = "";
 | 
			
		||||
    displayedChars.value = [];
 | 
			
		||||
    if (timer) clearInterval(timer);
 | 
			
		||||
    timer = setInterval(setContent, interTime.value);
 | 
			
		||||
    return;
 | 
			
		||||
  } else {
 | 
			
		||||
    const nextChar = slogan.value.charAt(initAnimation.value.length);
 | 
			
		||||
    initAnimation.value += slogan.value.charAt(initAnimation.value.length); // 逐字符追加
 | 
			
		||||
    displayedChars.value.push(nextChar);
 | 
			
		||||
    interTime.value = interArr[Math.floor(Math.random() * interArr.length)]; // 设置随机间隔
 | 
			
		||||
    if (timer) clearInterval(timer);
 | 
			
		||||
    timer = setInterval(setContent, interTime.value);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
// 计算彩虹色
 | 
			
		||||
const rainbowColor = (index) => {
 | 
			
		||||
  const hue = (index * 40) % 360; // 每个字符间隔40度,形成彩虹色
 | 
			
		||||
  return `hsl(${hue}, 90%, 50%)`; // 色调(hue),饱和度(70%),亮度(50%)
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="stylus" scoped>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,13 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="admin-home" v-if="isLogin">
 | 
			
		||||
    <admin-sidebar/>
 | 
			
		||||
    <admin-sidebar />
 | 
			
		||||
    <div class="content-box" :class="{ 'content-collapse': sidebar.collapse }">
 | 
			
		||||
      <admin-header/>
 | 
			
		||||
      <admin-tags/>
 | 
			
		||||
      <div :class="'content '+theme" :style="{height:contentHeight+'px'}">
 | 
			
		||||
      <admin-header />
 | 
			
		||||
      <admin-tags />
 | 
			
		||||
      <div
 | 
			
		||||
        :class="'content ' + theme"
 | 
			
		||||
        :style="{ height: contentHeight + 'px' }"
 | 
			
		||||
      >
 | 
			
		||||
        <router-view v-slot="{ Component }">
 | 
			
		||||
          <transition name="move" mode="out-in">
 | 
			
		||||
            <keep-alive :include="tags.nameList">
 | 
			
		||||
@@ -17,40 +20,43 @@
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script setup>
 | 
			
		||||
import {useSidebarStore} from '@/store/sidebar';
 | 
			
		||||
import {useTagsStore} from '@/store/tags';
 | 
			
		||||
import { useSidebarStore } from "@/store/sidebar";
 | 
			
		||||
import { useTagsStore } from "@/store/tags";
 | 
			
		||||
import AdminHeader from "@/components/admin/AdminHeader.vue";
 | 
			
		||||
import AdminSidebar from "@/components/admin/AdminSidebar.vue";
 | 
			
		||||
import AdminTags from "@/components/admin/AdminTags.vue";
 | 
			
		||||
import {useRouter} from "vue-router";
 | 
			
		||||
import {checkAdminSession} from "@/store/cache";
 | 
			
		||||
import {ref, watch} from "vue";
 | 
			
		||||
import {useSharedStore} from "@/store/sharedata";
 | 
			
		||||
import { useRouter } from "vue-router";
 | 
			
		||||
import { checkAdminSession } from "@/store/cache";
 | 
			
		||||
import { ref, watch } from "vue";
 | 
			
		||||
import { useSharedStore } from "@/store/sharedata";
 | 
			
		||||
 | 
			
		||||
const sidebar = useSidebarStore();
 | 
			
		||||
const tags = useTagsStore();
 | 
			
		||||
const isLogin = ref(false)
 | 
			
		||||
const contentHeight = window.innerHeight - 80
 | 
			
		||||
const store = useSharedStore()
 | 
			
		||||
const theme = ref(store.adminTheme)
 | 
			
		||||
const isLogin = ref(false);
 | 
			
		||||
const contentHeight = window.innerHeight - 80;
 | 
			
		||||
const store = useSharedStore();
 | 
			
		||||
const theme = ref(store.adminTheme);
 | 
			
		||||
 | 
			
		||||
// 获取会话信息
 | 
			
		||||
const router = useRouter();
 | 
			
		||||
checkAdminSession().then(() => {
 | 
			
		||||
  isLogin.value = true
 | 
			
		||||
}).catch(() => {
 | 
			
		||||
  router.replace('/admin/login')
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
watch(() => store.adminTheme, (val) => {
 | 
			
		||||
  theme.value = val
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
checkAdminSession()
 | 
			
		||||
  .then(() => {
 | 
			
		||||
    isLogin.value = true;
 | 
			
		||||
  })
 | 
			
		||||
  .catch(() => {
 | 
			
		||||
    router.replace("/admin/login");
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
watch(
 | 
			
		||||
  () => store.adminTheme,
 | 
			
		||||
  (val) => {
 | 
			
		||||
    theme.value = val;
 | 
			
		||||
  }
 | 
			
		||||
);
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="stylus">
 | 
			
		||||
@import '@/assets/css/color-dark.styl';
 | 
			
		||||
// @import '@/assets/css/color-dark.styl';
 | 
			
		||||
@import '@/assets/css/main.styl';
 | 
			
		||||
@import '@/assets/iconfont/iconfont.css';
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,31 +1,36 @@
 | 
			
		||||
const {defineConfig} = require('@vue/cli-service')
 | 
			
		||||
let webpack = require('webpack')
 | 
			
		||||
const { defineConfig } = require("@vue/cli-service");
 | 
			
		||||
const path = require("path");
 | 
			
		||||
let webpack = require("webpack");
 | 
			
		||||
module.exports = defineConfig({
 | 
			
		||||
    transpileDependencies: true,
 | 
			
		||||
    lintOnSave: false,   //关闭eslint校验
 | 
			
		||||
    productionSourceMap: false, //在生产模式中禁用 Source Map,既可以减少包大小,也可以加密源码
 | 
			
		||||
    configureWebpack: {
 | 
			
		||||
        // disable performance hints
 | 
			
		||||
        performance: {
 | 
			
		||||
            hints: false
 | 
			
		||||
        },
 | 
			
		||||
        plugins: [
 | 
			
		||||
            new webpack.optimize.MinChunkSizePlugin({minChunkSize: 10000})
 | 
			
		||||
        ]
 | 
			
		||||
  transpileDependencies: true,
 | 
			
		||||
  lintOnSave: false, //关闭eslint校验
 | 
			
		||||
  productionSourceMap: false, //在生产模式中禁用 Source Map,既可以减少包大小,也可以加密源码
 | 
			
		||||
 | 
			
		||||
  configureWebpack: {
 | 
			
		||||
    // disable performance hints
 | 
			
		||||
    performance: {
 | 
			
		||||
      hints: false
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    publicPath: '/',
 | 
			
		||||
 | 
			
		||||
    outputDir: 'dist',
 | 
			
		||||
    crossorigin: "anonymous",
 | 
			
		||||
    devServer: {
 | 
			
		||||
        allowedHosts: "all",
 | 
			
		||||
        port: 8888,
 | 
			
		||||
        proxy: {
 | 
			
		||||
            '/static/upload/': {
 | 
			
		||||
              target:  process.env.VUE_APP_API_HOST,
 | 
			
		||||
              changeOrigin: true,
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
    plugins: [new webpack.optimize.MinChunkSizePlugin({ minChunkSize: 10000 })],
 | 
			
		||||
    resolve: {
 | 
			
		||||
      alias: {
 | 
			
		||||
        "@": path.resolve(__dirname, "src")
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
})
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  publicPath: "/",
 | 
			
		||||
 | 
			
		||||
  outputDir: "dist",
 | 
			
		||||
  crossorigin: "anonymous",
 | 
			
		||||
  devServer: {
 | 
			
		||||
    allowedHosts: "all",
 | 
			
		||||
    port: 8888,
 | 
			
		||||
    proxy: {
 | 
			
		||||
      "/static/upload/": {
 | 
			
		||||
        target: process.env.VUE_APP_API_HOST,
 | 
			
		||||
        changeOrigin: true
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user