博客前端

This commit is contained in:
xbx 2024-05-17 19:10:05 +08:00
parent 3f2b4cc5e0
commit 0ff621b43d
59 changed files with 23395 additions and 7183 deletions

13
index.html Normal file
View File

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel ="shortcut icon" type="image/x-icon" href="./src/assets/">
<title>Activiti</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

20311
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -8,8 +8,17 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
"arale-qrcode": "^3.0.5",
"axios": "^1.6.0",
"core-js": "^3.8.3",
"github-markdown-css": "^5.4.0",
"jwt-decode": "^3.1.2",
"markdown-it": "^13.0.2",
"mavon-editor": "^2.10.4",
"sass-loader": "^13.3.2",
"vue": "^2.6.14",
"vue-live2d": "^1.3.1",
"vue-qr": "^4.0.9",
"vue-router": "^3.5.1",
"vuex": "^3.6.2"
},
@ -23,6 +32,10 @@
"@vue/cli-service": "~5.0.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"vue-template-compiler": "^2.6.14"
"less-loader": "^11.1.3",
"stylus": "^0.61.0",
"stylus-loader": "^7.1.3",
"vue-template-compiler": "^2.6.14",
"vuepress-plugin-sakura": "^1.2.1"
}
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 99 KiB

View File

@ -1,17 +0,0 @@
<!DOCTYPE html>
<html lang="">
<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">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@ -1,32 +1,8 @@
<template>
<div id="app">
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
<router-view/>
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
nav {
padding: 30px;
}
nav a {
font-weight: bold;
color: #2c3e50;
}
nav a.router-link-exact-active {
color: #42b983;
}
<style lang="scss">
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 KiB

BIN
src/assets/archieve.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
src/assets/background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

BIN
src/assets/gundam1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
src/assets/gundam2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 KiB

BIN
src/assets/gundam3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 KiB

BIN
src/assets/gundam4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

BIN
src/assets/gundam5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

BIN
src/assets/gundam6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

BIN
src/assets/gundam7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

BIN
src/assets/gundam8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
src/assets/home-bg.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 538 KiB

BIN
src/assets/link-bg.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 436 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 99 KiB

BIN
src/assets/pp.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
src/assets/头像.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View File

@ -0,0 +1,189 @@
<template>
<div class="background-container">
<Menu></Menu>
<div class="centered-text">
<h3>发布博客</h3>
<h13 class="span loader">
<span class="m">W</span><span class="m">E</span><span class="m">L</span><span class="m">C</span><span
class="m">O</span><span class="m">M</span><span class="m">E</span>&nbsp;<span class="m">T</span><span
class="m"></span><span class="m">O</span>&nbsp;<span class="m">X</span><span class="m"></span><span
class="m">u</span><span class="m">b</span><span class="m">x</span><span class="m">'s</span>&nbsp;<span
class="m">B</span><span class="m">L</span><span class="m">O</span><span class="m">G</span>
</h13>
</div>
</div>
</template>
<script>
import Menu from './Menu.vue'
export default {
components:{
Menu,
},
name: "HeaderView",
}
</script>
<style scoped>
.background-container {
position: relative;
height: 420px;
width: 100%;
background-image: url("../assets/about-archive.jpeg");
background-size: cover;
opacity: 0;
/* 初始时设置透明度为0 */
animation: fade-in 1s forwards;
/* 使用动画效果渐变显示背景图 */
/* z-index: 9999; */
}
@keyframes fade-in {
0% {
opacity: 0.5;
/* 动画开始时透明度为0 */
}
100% {
opacity: 1;
/* 动画结束时透明度为1 */
}
}
/* 首页文字 */
.centered-text {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
}
.centered-text h3 {
margin: 0px;
font-family: "Montserrat", sans-serif;
font-weight: 500;
font-size: 50px;
color: #03dac6;
transition: all 0.3s ease;
text-shadow: 5px 5px 10px black;
/* transform: translateX(19%); */
}
.centered-text h3:hover {
/* transform: translate3d(182px, -5px, 0px); */
transform: translateY(-5px);
color: #ff0266;
}
.centered-text h13.span {
padding: 0px 60px;
font-size: 20px;
letter-spacing: 0.7em;
font-family: "ROBOTO", sans-serif;
font-weight: 300;
color: #faebd7;
z-index: 4;
transform: translateX(10%);
}
.loader span {
color: #faebd7;
text-shadow: 0 0 0 #faebd7;
-webkit-animation: loading 1s ease-in-out infinite alternate;
}
@keyframes loading {
to {
text-shadow: 20px 0 70px #ff0202;
color: #ff0266;
}
}
.loader span:nth-child(2) {
-webkit-animation-delay: 0.1s;
}
.loader span:nth-child(3) {
-webkit-animation-delay: 0.2s;
}
.loader span:nth-child(4) {
-webkit-animation-delay: 0.3s;
}
.loader span:nth-child(5) {
-webkit-animation-delay: 0.4s;
}
.loader span:nth-child(6) {
-webkit-animation-delay: 0.5s;
}
.loader span:nth-child(7) {
-webkit-animation-delay: 0.6s;
}
.loader span:nth-child(8) {
-webkit-animation-delay: 0.7s;
}
.loader span:nth-child(9) {
-webkit-animation-delay: 0.8s;
}
.loader span:nth-child(10) {
-webkit-animation-delay: 0.9s;
}
.loader span:nth-child(11) {
-webkit-animation-delay: 1s;
}
.loader span:nth-child(12) {
-webkit-animation-delay: 1.1s;
}
.loader span:nth-child(13) {
-webkit-animation-delay: 1.2s;
}
.loader span:nth-child(14) {
-webkit-animation-delay: 1.3s;
}
.loader span:nth-child(15) {
-webkit-animation-delay: 1.4s;
}
.loader span:nth-child(16) {
-webkit-animation-delay: 1.5s;
}
.loader span:nth-child(17) {
-webkit-animation-delay: 1.6s;
}
.loader span:nth-child(18) {
-webkit-animation-delay: 1.7s;
}
.loader span:nth-child(19) {
-webkit-animation-delay: 1.8s;
}
.loader span:nth-child(20) {
-webkit-animation-delay: 1.9s;
}
.loader span:nth-child(21) {
-webkit-animation-delay: 2s;
}
.loader span:nth-child(22) {
-webkit-animation-delay: 2.1s;
}
</style>

97
src/components/Footer.vue Normal file
View File

@ -0,0 +1,97 @@
<template>
<div>
<div class="body">
<!-- <el-divider></el-divider> -->
<p>Copyright ©2023 Xubx</p>
<a href="https://beian.miit.gov.cn/#/Integrated/index">闽ICP备2023011424号</a>
<br>
<div class="stars" ref="starsRef">
<div class="star" v-for="(item, index) in starsCount" :key="index"></div>
</div>
</div>
</div>
</template>
<script>
import { onMounted, ref } from "vue";
export default {
setup() {
let starsRef = ref(null);
const starsCount = 800; //
const distance = 900; //
onMounted(() => {
let starNodes = Array.from(starsRef.value.children);
starNodes.forEach((item) => {
let speed = 0.2 + Math.random() * 1;
let thisDistance = distance + Math.random() * 300;
item.style.transformOrigin = `0 0 ${thisDistance}px`;
item.style.transform = `
translate3d(0,0,-${thisDistance}px)
rotateY(${Math.random() * 360}deg)
rotateX(${Math.random() * -50}deg)
scale(${speed},${speed})`;
});
});
return {
starsRef,
starsCount,
};
},
name: "FooterView"
}
</script>
<style scoped>
.body {
position: absolute;
width: 100%;
height: 100px;
margin: 0;
padding: 0;
background: radial-gradient(200% 100% at bottom center,
#f7f7b6,
#e96f92,
#1b2947);
background: radial-gradient(200% 105% at top center,
#1b2947 10%,
#75517d 40%,
#e96f92 65%,
#f7f7b6);
background-attachment: fixed;
overflow: hidden;
}
@keyframes rotate {
0% {
transform: perspective(400px) rotateZ(20deg) rotateX(-40deg) rotateY(0);
}
100% {
transform: perspective(400px) rotateZ(20deg) rotateX(-40deg) rotateY(-360deg);
}
}
.stars {
transform: perspective(500px);
transform-style: preserve-3d;
position: absolute;
perspective-origin: 50% 100%;
left: 45%;
animation: rotate 90s infinite linear;
bottom: 0;
}
.star {
width: 2px;
height: 2px;
background: #f7f7b6;
position: absolute;
left: 0;
top: 0;
backface-visibility: hidden;
}
</style>

190
src/components/Header.vue Normal file
View File

@ -0,0 +1,190 @@
<template>
<div class="background-container">
<Menu></Menu>
<div class="centered-text">
<h3>博客详情</h3>
<h13 class="span loader">
<span class="m">W</span><span class="m">E</span><span class="m">L</span><span class="m">C</span><span
class="m">O</span><span class="m">M</span><span class="m">E</span>&nbsp;<span class="m">T</span><span
class="m"></span><span class="m">O</span>&nbsp;<span class="m">X</span><span class="m"></span><span
class="m">u</span><span class="m">b</span><span class="m">x</span><span class="m">'s</span>&nbsp;<span
class="m">B</span><span class="m">L</span><span class="m">O</span><span class="m">G</span>
</h13>
</div>
<br>
</div>
</template>
<script>
import Menu from './Menu.vue'
export default {
components: {
Menu,
},
name: "HeaderView",
}
</script>
<style scoped>
.background-container {
/* z-index: 9999; */
position: relative;
height: 420px;
width: 100%;
background-image: url("../assets/link-bg.jpeg");
background-size: cover;
opacity: 0;
/* 初始时设置透明度为0 */
animation: fade-in 1s forwards;
/* 使用动画效果渐变显示背景图 */
}
@keyframes fade-in {
0% {
opacity: 0.5;
/* 动画开始时透明度为0 */
}
100% {
opacity: 1;
/* 动画结束时透明度为1 */
}
}
/* 首页文字 */
.centered-text {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
}
.centered-text h3 {
margin: 0px;
font-family: "Montserrat", sans-serif;
font-weight: 400;
font-size: 50px;
color: #03dac6;
transition: all 0.3s ease;
text-shadow: 5px 5px 10px black;
/* transform: translateX(19%); */
}
.centered-text h3:hover {
/* transform: translate3d(182px, -5px, 0px); */
transform: translateY(-5px);
color: #ff0266;
}
.centered-text h13.span {
padding: 0px 60px;
font-size: 20px;
letter-spacing: 0.7em;
font-family: "ROBOTO", sans-serif;
font-weight: 300;
color: #faebd7;
z-index: 4;
transform: translateX(10%);
}
.loader span {
color: #faebd7;
text-shadow: 0 0 0 #faebd7;
-webkit-animation: loading 1s ease-in-out infinite alternate;
}
@keyframes loading {
to {
text-shadow: 20px 0 70px #ff0202;
color: #ff0266;
}
}
.loader span:nth-child(2) {
-webkit-animation-delay: 0.1s;
}
.loader span:nth-child(3) {
-webkit-animation-delay: 0.2s;
}
.loader span:nth-child(4) {
-webkit-animation-delay: 0.3s;
}
.loader span:nth-child(5) {
-webkit-animation-delay: 0.4s;
}
.loader span:nth-child(6) {
-webkit-animation-delay: 0.5s;
}
.loader span:nth-child(7) {
-webkit-animation-delay: 0.6s;
}
.loader span:nth-child(8) {
-webkit-animation-delay: 0.7s;
}
.loader span:nth-child(9) {
-webkit-animation-delay: 0.8s;
}
.loader span:nth-child(10) {
-webkit-animation-delay: 0.9s;
}
.loader span:nth-child(11) {
-webkit-animation-delay: 1s;
}
.loader span:nth-child(12) {
-webkit-animation-delay: 1.1s;
}
.loader span:nth-child(13) {
-webkit-animation-delay: 1.2s;
}
.loader span:nth-child(14) {
-webkit-animation-delay: 1.3s;
}
.loader span:nth-child(15) {
-webkit-animation-delay: 1.4s;
}
.loader span:nth-child(16) {
-webkit-animation-delay: 1.5s;
}
.loader span:nth-child(17) {
-webkit-animation-delay: 1.6s;
}
.loader span:nth-child(18) {
-webkit-animation-delay: 1.7s;
}
.loader span:nth-child(19) {
-webkit-animation-delay: 1.8s;
}
.loader span:nth-child(20) {
-webkit-animation-delay: 1.9s;
}
.loader span:nth-child(21) {
-webkit-animation-delay: 2s;
}
.loader span:nth-child(22) {
-webkit-animation-delay: 2.1s;
}
</style>

View File

@ -1,60 +0,0 @@
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-router" target="_blank" rel="noopener">router</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-vuex" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@ -0,0 +1,188 @@
<template>
<div class="background-container">
<Menu></Menu>
<div class="centered-text" >
<h3>欢迎来到Xubx的博客</h3>
<h13 class="span loader">
<span class="m">W</span><span class="m">E</span><span class="m">L</span><span class="m">C</span><span
class="m">O</span><span class="m">M</span><span class="m">E</span>&nbsp;<span class="m">T</span><span
class="m"></span><span class="m">O</span>&nbsp;<span class="m">X</span><span class="m"></span><span
class="m">u</span><span class="m">b</span><span class="m">x</span><span class="m">'s</span>&nbsp;<span
class="m">B</span><span class="m">L</span><span class="m">O</span><span class="m">G</span>
</h13>
</div>
</div>
</template>
<script>
import Menu from './Menu.vue'
export default {
components: {
Menu,
},
name: "HeaderView",
}
</script>
<style scoped>
.background-container {
/* z-index: 0; */
position: relative;
height: 720px;
width: 100%;
background-image: url("../assets/home-bg.jpeg");
background-size: cover;
opacity: 0;
/* 初始时设置透明度为0 */
animation: fade-in 1s forwards;
/* 使用动画效果渐变显示背景图 */
}
@keyframes fade-in {
0% {
opacity: 0.5;
/* 动画开始时透明度为0 */
}
100% {
opacity: 1;
/* 动画结束时透明度为1 */
}
}
/* 首页文字 */
.centered-text {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
}
.centered-text h3 {
margin: 0px;
font-family: "Montserrat", sans-serif;
font-weight: 600;
font-size: 70px;
color: #03dac6;
transition: all 0.3s ease;
text-shadow: 5px 5px 10px black;
/* transform: translateX(19%); */
}
.centered-text h3:hover {
/* transform: translate3d(182px, -5px, 0px); */
transform: translateY(-5px);
color: #ff0266;
}
.centered-text h13.span {
padding: 0px 60px;
font-size: 2vw;
letter-spacing: 0.7em;
font-family: "ROBOTO", sans-serif;
font-weight: 400;
color: #faebd7;
z-index: 4;
transform: translateX(10%);
}
.loader span {
color: #faebd7;
text-shadow: 0 0 0 #faebd7;
-webkit-animation: loading 1s ease-in-out infinite alternate;
}
@keyframes loading {
to {
text-shadow: 20px 0 70px #ff0202;
color: #ff0266;
}
}
.loader span:nth-child(2) {
-webkit-animation-delay: 0.1s;
}
.loader span:nth-child(3) {
-webkit-animation-delay: 0.2s;
}
.loader span:nth-child(4) {
-webkit-animation-delay: 0.3s;
}
.loader span:nth-child(5) {
-webkit-animation-delay: 0.4s;
}
.loader span:nth-child(6) {
-webkit-animation-delay: 0.5s;
}
.loader span:nth-child(7) {
-webkit-animation-delay: 0.6s;
}
.loader span:nth-child(8) {
-webkit-animation-delay: 0.7s;
}
.loader span:nth-child(9) {
-webkit-animation-delay: 0.8s;
}
.loader span:nth-child(10) {
-webkit-animation-delay: 0.9s;
}
.loader span:nth-child(11) {
-webkit-animation-delay: 1s;
}
.loader span:nth-child(12) {
-webkit-animation-delay: 1.1s;
}
.loader span:nth-child(13) {
-webkit-animation-delay: 1.2s;
}
.loader span:nth-child(14) {
-webkit-animation-delay: 1.3s;
}
.loader span:nth-child(15) {
-webkit-animation-delay: 1.4s;
}
.loader span:nth-child(16) {
-webkit-animation-delay: 1.5s;
}
.loader span:nth-child(17) {
-webkit-animation-delay: 1.6s;
}
.loader span:nth-child(18) {
-webkit-animation-delay: 1.7s;
}
.loader span:nth-child(19) {
-webkit-animation-delay: 1.8s;
}
.loader span:nth-child(20) {
-webkit-animation-delay: 1.9s;
}
.loader span:nth-child(21) {
-webkit-animation-delay: 2s;
}
.loader span:nth-child(22) {
-webkit-animation-delay: 2.1s;
}</style>

464
src/components/Menu.vue Normal file
View File

@ -0,0 +1,464 @@
<template>
<div>
<div class="menu">
<div class="brand">
<h3 class="red">BIG</h3>
<h3 class="white">DATA</h3>
</div>
<div class="main-nav">
<router-link to="/" type="primary" class="button-container">
<h2>主页</h2>
</router-link>
<router-link to="/time" type="primary" class="button-container">
<h2>归档</h2>
</router-link>
<router-link to="/add" type="success" class="button-container">
<h2>发布博客</h2>
</router-link>
</div>
<div class="right-nav">
<el-dropdown @command="handleCommand" class="el-dropdown-link">
<span>
<el-avatar v-if="imageUrl" :src="imageUrl" style="width: 50px; height: 50px;"
class="avatar flip animated"></el-avatar>
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</span>
<el-dropdown-menu slot="dropdown">
<p>{{ this.username }}</p>
<el-upload action="http://124.71.135.249:8081/uploadAvatar/" :show-file-list="false"
:on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
<el-dropdown-item divided icon="el-icon-picture-outline-round">更换头像</el-dropdown-item>
</el-upload>
<a @click="nameChangeVisible = true">
<el-dropdown-item divided icon="el-icon-user">
修改昵称
</el-dropdown-item>
</a>
<a @click="passwordChangeVisible = true">
<el-dropdown-item divided icon="el-icon-edit-outline">
修改密码
</el-dropdown-item>
</a>
<router-link to="/login" class="right-nav">
<el-dropdown-item divided icon="el-icon-switch-button">退出登录</el-dropdown-item>
</router-link>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
<el-dialog title="修改昵称" :visible="nameChangeVisible" width="400px" @close="nameChangeVisible = false">
<el-form :model="usernameForm" :rules="usernameRules">
<el-form-item label="请输入昵称" :label-width="200" prop="usernameChange">
<el-input v-model="usernameForm.usernameChange" style="width: 350px;"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="nameChangeVisible = false"> </el-button>
<el-button type="primary" @click="usernameChange()"> </el-button>
</span>
</el-dialog>
<el-dialog title="修改密码" :destroy-on-close="true" :visible="passwordChangeVisible" width="550px"
@close="passwordChangeVisible = false">
<el-form :model="passwordForm" label-width="100px" :rules="passwordRules">
<el-form-item label="原密码" prop="oldPassword">
<el-input v-model="passwordForm.oldPassword" style="width: 350px;"></el-input>
</el-form-item>
<el-form-item label="新密码" prop="newPassword">
<el-input v-model="passwordForm.newPassword" style="width: 350px;"></el-input>
</el-form-item>
<el-form-item label="确认新密码" prop="configurePassword">
<el-input v-model="passwordForm.configurePassword" style="width: 350px;"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="passwordChangeVisible = false"> </el-button>
<el-button type="primary" @click="passwordChange()"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import axios from 'axios';
export default {
data() {
//
var validateConfigurePassword = (rule, value, callback) => {
if (value === "") {
callback(new Error("请再次输入密码")); //callback
} else if (value !== this.passwordForm.newPassword) {
callback(new Error("两次输入密码不一致!"));
} else {
callback();
}
};
var validateUsername = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入用户名"));
} else if (value.length < 3) {
callback(new Error("长度不够"));
} else {
callback();
}
};
return {
imageUrl: '',
username: '',
nameChangeVisible: false,
passwordChangeVisible: false,
usernameForm: {
usernameChange: ''
},
passwordForm: {
oldPassword: '',
newPassword: '',
configurePassword: ''
},
passwordRules: {
oldPassword: [
{ required: true, message: '请输入原密码', trigger: 'blur' },
],
newPassword: [
{ required: true, message: '请输入新密码', trigger: 'blur' },
],
configurePassword: [
{ validator: validateConfigurePassword, trigger: 'blur' },
],
},
usernameRules: {
usernameChange: [
{ validator: validateUsername, trigger: 'blur' }, //trigger: 'blur'
],
}
};
},
methods: {
handleAvatarSuccess(res, file) {
this.imageUrl = URL.createObjectURL(file.raw);
//
window.location.reload();
console.log("自动生成的url:" + URL.createObjectURL(file.raw) + '+this.imageUrl:' + this.imageUrl);
},
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!');
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!');
}
return isJPG && isLt2M;
},
getAvatar() {
axios.get("/getAvatar").then((res) => {
this.imageUrl = 'http://124.71.135.249:8081' + res.data;
console.log("接收的url" + this.imageUrl)
})
},
getUsername() {
axios.get("/getUsername").then((res) => {
this.username = res.data;
console.log(this.username);
})
},
usernameChange() {
axios.get("/usernameChange", {
params: {
username: this.usernameForm.usernameChange
}
}).then((res) => {
if (res.data === "修改成功!") {
this.$message.success(res.data)
} else {
this.$message.error(res.data)
}
this.nameChangeVisible = false;
this.getUsername();
//
this.usernameForm.usernameChange = '';
})
},
passwordChange() {
axios.get("/passwordChange", {
params: {
oldPassword: this.passwordForm.oldPassword,
newPassword: this.passwordForm.newPassword,
}
}).then((res) => {
if (res.data === "修改成功!") {
this.$message.success(res.data);
this.passwordChangeVisible = false;
//
this.passwordForm.oldPassword = '';
this.passwordForm.newPassword = '';
this.passwordForm.configurePassword = '';
} else {
this.$message.error(res.data)
}
})
},
},
created() {
this.getAvatar();
this.getUsername();
},
name: "MenuView",
}
</script>
<style>
/*base code*/
.animated {
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
.animated.infinite {
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.animated.hinge {
-webkit-animation-duration: 2s;
animation-duration: 2s;
}
/*the animation definition*/
@-webkit-keyframes flip {
0% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out
}
40% {
-webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out
}
50% {
-webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in
}
80% {
-webkit-transform: perspective(400px) scale3d(.95, .95, .95);
transform: perspective(400px) scale3d(.95, .95, .95);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in
}
100% {
-webkit-transform: perspective(400px);
transform: perspective(400px);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in
}
}
@keyframes flip {
0% {
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
-ms-transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out
}
40% {
-webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
-ms-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
-webkit-animation-timing-function: ease-out;
animation-timing-function: ease-out
}
50% {
-webkit-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
-ms-transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in
}
80% {
-webkit-transform: perspective(400px) scale3d(.95, .95, .95);
-ms-transform: perspective(400px) scale3d(.95, .95, .95);
transform: perspective(400px) scale3d(.95, .95, .95);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in
}
100% {
-webkit-transform: perspective(400px);
-ms-transform: perspective(400px);
transform: perspective(400px);
-webkit-animation-timing-function: ease-in;
animation-timing-function: ease-in
}
}
.animated.flip {
-webkit-backface-visibility: visible;
-ms-backface-visibility: visible;
backface-visibility: visible;
-webkit-animation-name: flip;
animation-name: flip
}
.el-dropdown-link {
cursor: pointer;
color: #e9ecee;
}
.el-icon-arrow-down {
font-size: 22px;
}
.background-container {
/* z-index: 0; */
position: relative;
height: 720px;
width: 100%;
background-image: url("../assets/home-bg.jpeg");
background-size: cover;
opacity: 0;
/* 初始时设置透明度为0 */
animation: fade-in 1s forwards;
/* 使用动画效果渐变显示背景图 */
}
@keyframes fade-in {
0% {
opacity: 0.5;
/* 动画开始时透明度为0 */
}
100% {
opacity: 1;
/* 动画结束时透明度为1 */
}
}
/* 首页导航 */
.menu {
/* position: absolute;
background-color: transparent; */
width: 100%;
position: fixed;
height: 70px;
background-color: transparent;
display: flex;
align-items: center;
/* z-index: 10000; */
transition: background-color 0.3s;
}
.menu:hover {
background-color: rgba(51, 51, 51, 1);
/* box-shadow: 0px 2px 10px black; */
transition: background-color 0.3s;
}
.menu .brand {
margin-left: 25px;
display: flex;
}
.menu .brand h3 {
font-family: "Anton", sans-serif;
font-size: 35px;
}
.red {
color: #f90606;
}
.white {
/* color: rgba(230, 230, 230, 1); */
color: #efefef;
}
.menu .brand h1 {
font-family: "Anton", sans-serif;
font-size: 35px;
}
.main-nav {
height: 100%;
display: flex;
align-items: center;
margin-left: 50px;
}
.main-nav .button-container {
height: calc(100% - 10px);
margin-top: 5px;
padding: 0px 15px;
display: flex;
align-items: center;
justify-content: center;
border-bottom: 5px solid transparent;
border-bottom-color: transparent;
transition: border-bottom-color 0.3s;
}
.main-nav .button-container:hover {
cursor: pointer;
border-bottom-color: #ed0909;
transition: border-bottom-color 0.3s;
}
.main-nav .button-container h2 {
font-family: "Roboto", sans-serif;
font-size: 26px;
color: white;
}
.menu .right-nav {
margin-left: auto;
display: flex;
align-items: center;
margin-right: 25px;
}
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 50px;
height: 50px;
line-height: 50px;
text-align: center;
}
.avatar {
width: 50px;
height: 50px;
display: block;
}
</style>

View File

@ -0,0 +1,188 @@
<template>
<div class="background-container-Time">
<Menu></Menu>
<div class="centered-text">
<h3>归档</h3>
<h13 class="span loader">
<span class="m">W</span><span class="m">E</span><span class="m">L</span><span class="m">C</span><span
class="m">O</span><span class="m">M</span><span class="m">E</span>&nbsp;<span class="m">T</span><span
class="m"></span><span class="m">O</span>&nbsp;<span class="m">X</span><span class="m"></span><span
class="m">u</span><span class="m">b</span><span class="m">x</span><span class="m">'s</span>&nbsp;<span
class="m">B</span><span class="m">L</span><span class="m">O</span><span class="m">G</span>
</h13>
</div>
</div>
</template>
<script>
import Menu from './Menu.vue'
export default {
components: {
Menu,
},
name: "TimeHeaderView",
}
</script>
<style scoped>
.background-container-Time {
/* z-index: 9999; */
position: relative;
height: 750px;
width: 100%;
background-image: url("../assets/archieve.jpeg");
background-size: cover;
opacity: 0;
/* 初始时设置透明度为0 */
animation: fade-in 1s forwards;
/* 使用动画效果渐变显示背景图 */
}
@keyframes fade-in {
0% {
opacity: 0.5;
/* 动画开始时透明度为0 */
}
100% {
opacity: 1;
/* 动画结束时透明度为1 */
}
}
/* 首页文字 */
.centered-text {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
}
.centered-text h3 {
margin: 0px;
font-family: "Montserrat", sans-serif;
font-weight: 600;
font-size: 70px;
color: #03dac6;
transition: all 0.3s ease;
text-shadow: 5px 5px 10px black;
/* transform: translateX(19%); */
}
.centered-text h3:hover {
/* transform: translate3d(182px, -5px, 0px); */
transform: translateY(-5px);
color: #ff0266;
}
.centered-text h13.span {
padding: 0px 60px;
font-size: 2vw;
letter-spacing: 0.7em;
font-family: "ROBOTO", sans-serif;
font-weight: 400;
color: #faebd7;
z-index: 4;
transform: translateX(10%);
}
.loader span {
color: #faebd7;
text-shadow: 0 0 0 #faebd7;
-webkit-animation: loading 1s ease-in-out infinite alternate;
}
@keyframes loading {
to {
text-shadow: 20px 0 70px #ff0202;
color: #ff0266;
}
}
.loader span:nth-child(2) {
-webkit-animation-delay: 0.1s;
}
.loader span:nth-child(3) {
-webkit-animation-delay: 0.2s;
}
.loader span:nth-child(4) {
-webkit-animation-delay: 0.3s;
}
.loader span:nth-child(5) {
-webkit-animation-delay: 0.4s;
}
.loader span:nth-child(6) {
-webkit-animation-delay: 0.5s;
}
.loader span:nth-child(7) {
-webkit-animation-delay: 0.6s;
}
.loader span:nth-child(8) {
-webkit-animation-delay: 0.7s;
}
.loader span:nth-child(9) {
-webkit-animation-delay: 0.8s;
}
.loader span:nth-child(10) {
-webkit-animation-delay: 0.9s;
}
.loader span:nth-child(11) {
-webkit-animation-delay: 1s;
}
.loader span:nth-child(12) {
-webkit-animation-delay: 1.1s;
}
.loader span:nth-child(13) {
-webkit-animation-delay: 1.2s;
}
.loader span:nth-child(14) {
-webkit-animation-delay: 1.3s;
}
.loader span:nth-child(15) {
-webkit-animation-delay: 1.4s;
}
.loader span:nth-child(16) {
-webkit-animation-delay: 1.5s;
}
.loader span:nth-child(17) {
-webkit-animation-delay: 1.6s;
}
.loader span:nth-child(18) {
-webkit-animation-delay: 1.7s;
}
.loader span:nth-child(19) {
-webkit-animation-delay: 1.8s;
}
.loader span:nth-child(20) {
-webkit-animation-delay: 1.9s;
}
.loader span:nth-child(21) {
-webkit-animation-delay: 2s;
}
.loader span:nth-child(22) {
-webkit-animation-delay: 2.1s;
}
</style>

5
src/css/common.css Normal file
View File

@ -0,0 +1,5 @@
body, div, dl,dt,dd,ul,ol,li,h2,h3,h4,h5,h6,pre,form,fieldset,legend,input,textarea{
margin: 0;padding:0;}
body{text-align: center;}
a{ text-decoration: none;}
li{ list-style: none;}

177
src/js/Sakura.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -2,9 +2,33 @@ import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from 'axios'
import "./css/common.css"
Vue.config.productionTip = false
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
//导入mavon-editor用户Markdown编辑器
import mavonEditor from 'mavon-editor'
//解决Markdown编辑器的图标不出现问题
import "mavon-editor/dist/css/index.css"
Vue.use(mavonEditor)
axios.defaults.baseURL="http://localhost:8081"
//修改标题
router.beforeEach((to, from, next) => {
/* 路由发生变化修改页面title */
if (to.meta.title) {
document.title = to.meta.title
}
next()
})
new Vue({
router,
store,

View File

@ -1,29 +1,109 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
import Login from '../views/LoginView.vue'
import BlogHome from '../views/BlogHomeView.vue'
import BlogDetail from '../views/BlogDetailView.vue'
import BlogEdit from '../views/BlogEditView.vue'
import BlogAdd from '../views/BlogAddView.vue'
import jwt_decode from "jwt-decode";
import BlogTime from '../views/BlogTimeView.vue'
import ProjectWall from '../views/ProjectWallView.vue'
import MobileLogin from '../views/MobileLoginView.vue'
import store from "../store/index.js"
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: HomeView
name: 'Blogs',
component: BlogHome,
meta: {
title: 'Xubx的博客'
}
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
}
path: '/login',
name: 'Login',
component: window.innerWidth < 768 ? MobileLogin : Login ,
meta: {
title: 'Xubx的博客'
}
},
{
path: '/blog/:blogId',
name: 'BlogDetail',
component: BlogDetail,
meta: {
title: 'Xubx的博客'
}
},
{
path: '/blog/:blogId/edit',
name: 'BlogEdit',
component: BlogEdit,
meta: {
title: 'Xubx的博客'
}
},
{
path: '/add',
name: 'BlogAdd',
component: BlogAdd,
meta: {
title: 'Xubx的博客'
}
},
{
path: '/time',
name: 'BlogTest',
component: BlogTime,
meta: {
title: 'Xubx的博客'
}
},
{
path: '/test',
name: 'ProjectWall',
component: ProjectWall,
meta: {
title: 'Xubx的博客'
}
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
mode: 'hash',
routes
})
router.beforeEach((to, from, next) => {
//to 将要访问的路径
//from 代表从哪个路径而来
//next() 代表放行 next('xxx') 强制放行的xxx的路径
if (to.path === '/login') {
next();
} else {
const tokenStr = window.localStorage.getItem('token');
console.log(tokenStr);
if (!tokenStr) {
alert("请你先登陆")
return next('/login')
}
const token = jwt_decode(tokenStr);
const currentTime = Date.now() / 1000;
if (currentTime > token.exp) {
store.commit("delToken"); //删除token
console.log("已超时");
alert("登陆过期,请你重新登陆")
return next('/login')
}
next();
}
})
export default router

View File

@ -5,13 +5,19 @@ Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
}
//定义一个state存储token信息
token: localStorage.getItem('token') ? localStorage.getItem('token') : ''
},
mutations: {
//登录后通过setToken存入token token保存在state和localStorage中
setToken (state,token) {
state.token =token;
localStorage.setItem("token",token.token); //存储token
},
//登出后通过delToken清除token
delToken (state) {
state.token = '';
localStorage.removeItem("token"); //删除token
}
}
})

View File

@ -1,5 +0,0 @@
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>

111
src/views/BlogAddView.vue Normal file
View File

@ -0,0 +1,111 @@
<template>
<div>
<!-- 引用导航 -->
<AddHeader></AddHeader>
<br>
<div class="m_content">
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="标题" prop="title">
<el-input v-model="ruleForm.title"></el-input>
</el-form-item>
<el-form-item label="摘要" prop="description">
<el-input type="textarea" v-model="ruleForm.description"></el-input>
</el-form-item>
<el-form-item label="内容" prop="content">
<!-- 特殊组件 -->
<mavon-editor v-model="ruleForm.content"></mavon-editor>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">立即发布</el-button>
<!-- <el-button @click="resetForm('ruleForm')">重置</el-button> -->
</el-form-item>
</el-form>
</div>
<br>
<Footer></Footer>
<br>
</div>
</template>
<script>
import axios from 'axios';
import AddHeader from "../components/AddHeader";
import Footer from "../components/Footer";
export default {
components: {AddHeader, Footer},
beforeRouteEnter(to, from, next) {
//
window.scrollTo(0, 0);
next();
},
data() {
return {
ruleForm: {
id: "",
title: "",
description: "",
content: "",
},
rules: {
title: [
{ required: true, message: "请输入标题", trigger: "blur" },
{
min: 5,
max: 100,
message: "长度在 5 到 100 个字符",
trigger: "blur",
},
],
description: [
{ required: true, message: "请输入摘要", trigger: "blur" },
],
content: [{ required: true, message: "请输入内容", trigger: "blur" }],
},
};
},
methods: {
submitForm(formName) {
//
this.$refs[formName].validate((valid) => {
if (valid) {
//
axios.post('/addBlog', {
// id: this.ruleForm.id,
title: this.ruleForm.title,
description: this.ruleForm.description,
content: this.ruleForm.content,
created: new Date()
}).then(function (response) {
console.log(response.data)
//
window.location.href = "/"
})
} else {
console.log("error submit!!");
return false;
}
});
},
resetForm(formName) {
console.log(formName)
this.$refs[formName].resetFields();//Element,
}
},
name: "BlogEditView",
};
</script>
<style>
.m_content {
margin: 0 auto;
}
</style>

View File

@ -0,0 +1,353 @@
<template>
<div>
<!-- 引用导航 -->
<Header></Header>
<div style="text-align: left;padding-left: 40px; width: 96%;" class="mblog">
<br>
<h2>{{ blog.title }}</h2>
<br>
<div>
<el-link icon="el-icon-edit">
<!--携带博客ID跳转到编辑页面对博客进行修改-->
<router-link :to="{ name: 'BlogEdit', params: { blogId: blog.id } }">
编辑
</router-link>
</el-link>
<el-divider direction="vertical"></el-divider>
<el-link type="danger" @click="messageHandel" icon="el-icon-delete">
删除
</el-link>
<el-divider direction="vertical"></el-divider>
<el-button type="text" @click="commentGet()" icon="el-icon-chat-line-round">评论区</el-button>
<el-drawer title="评论区" :visible.sync="commentVisible" width="30%">
<!-- 评论功能 -->
<div>
<el-form :model="commentForm" status-icon :rules="rules" label-width="80px" ref="commentForm">
<el-tag style="font-size: 15px;" v-if="showReply">回复@{{ replyComent.replyName }}
<el-button type="text" @click="replyCancel()" icon="el-icon-close"
size="medium"></el-button>
</el-tag>
<el-form-item label="评论" prop="content">
<el-input type="text" v-model="commentForm.content"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitCommentForm()">评论</el-button>
</el-form-item>
</el-form>
</div>
<!-- 评论区展示功能 -->
<div v-for="comment in comments" :key="comment.comment_id">
<div v-if="!comment.parent_id">
<div class="comment-container">
<div class="comment-top">
<el-avatar class="comment-avatar" shape="circle" size="medium"
:src="comment.avatar" />
<el-tag class="comment-username" style="font-size: 17px;">{{ comment.username
}}</el-tag>
<span class="comment-time"> {{ comment.created }}</span>
<!-- 回复评论 -->
<el-button class="reply-button" type="text" icon="el-icon-chat-line-round"
@click="replyVisible(comment)">回复</el-button>
</div>
<span class="comment-content">" {{ comment.content }} "</span>
</div>
<el-divider content-position="center">
<el-button v-if="isClickId !== comment.comment_id" type="text"
@click="viewReplys(comment)">查看回复</el-button>
<el-button v-else type="text" @click="viewReplysCollapse(comment)">收起回复</el-button>
</el-divider>
<!-- 评论回复展示功能 -->
<div v-for="commentReply in commentReplys" :key="commentReply.comment_id">
<div
v-if="(commentReply.parent_id == comment.comment_id) && isClickId === comment.comment_id">
<div class="comment-reply">
<div class="comment-top">
<el-tag class="comment-username" style="font-size: 17px;">{{
commentReply.username }} 回复 @{{
commentReply.parent_name }}</el-tag>
<span class="comment-time"> {{ commentReply.created }}</span>
<el-button class="reply-button" type="text" icon="el-icon-chat-line-round"
@click="replyCommentVisible(commentReply, comment, comments)">回复</el-button>
</div>
<span class="comment-content">" {{ commentReply.content }} "</span>
<br>
<!-- 回复评论 -->
<!-- <el-input v-if="showReplyInput()"></el-input> -->
</div>
</div>
</div>
</div>
</div>
</el-drawer>
</div>
<el-divider></el-divider>
<div class="markdown-body" v-html="blog.content"></div>
<br>
</div>
<br>
<Footer></Footer>
<br>
</div>
</template>
<script>
import axios from 'axios';
//markdown使
import "github-markdown-css/github-markdown.css"
import Header from "../components/Header.vue";
import Footer from "../components/Footer.vue";
export default {
components: { Header, Footer },
beforeRouteEnter(to, from, next) {
//
window.scrollTo(0, 0);
next();
},
data() {
return {
viewReply: false, //
showReply: false, //
blog: {}, //
username: '', //
comments: {}, //
commentForm: { //
id: '',
username: '',
content: '',
created: ''
},
commentVisible: false, //
replyComent: {
comment_id: '',
replyName: '',
},
commentReplys: [],
isClickId: '',
}
},
methods: {
viewReplys(comment) {
this.isClickId = comment.comment_id
const commentReplyAdd = []
this.comments.forEach((commentReply) => {
if ((commentReply.parent_id === comment.comment_id)) {
commentReplyAdd.push(commentReply);
}
});
this.commentReplys = commentReplyAdd
},
viewReplysCollapse() {
this.isClickId = ''
},
replyCancel() {
//
this.showReply = false
this.replyComent.replyName = ''
this.replyComent.comment_id = ''
},
replyVisible(comment) {
this.replyComent.replyName = comment.username
this.replyComent.comment_id = comment.comment_id
console.log("replyComent.comment_id" + this.replyComent.comment_id + "replyComent.replyName" + this.replyComent.replyName)
this.showReply = true
},
replyCommentVisible(commentReply, comment) {
console.log("comment:" + comment + "commentReply:" + commentReply)
this.replyComent.replyName = commentReply.username
this.replyComent.comment_id = comment.comment_id
this.showReply = true
const commentReplyAdd = []
this.comments.forEach((commentReply) => {
if ((commentReply.parent_id === comment.comment_id)) {
commentReplyAdd.push(commentReply);
}
});
this.commentReplys = commentReplyAdd
//
},
showReplyInput() {
if (this.showReply) {
return true
} else {
return false
}
},
messageHandel() {
this.$confirm('此操作将永久删除该博客, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//
// axios.get('/deleteBlog', {
// params: {
// blogId: this.blog.id
// }
// }).then((res) => {
// console.log(res.data)
// this.$message({
// type: 'success',
// message: '!'
// });
// //
// this.$router.push('/')
// })
this.$message({
type: 'success',
message: '该功能暂时不对外开发哦!'
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
},
commentGet() {
this.commentVisible = true
//
axios.get('/getComment', {
params: {
blogId: this.blog.id
}
}).then((res) => {
console.log(res.data)
this.comments = res.data
for (let i = 0; i < this.comments.length; i++) {
if (this.comments[i].avatar == null) {
//
this.comments[i].avatar = 'http://124.71.135.249:8081' + '/images/avatar/default.jpg'
} else {
this.comments[i].avatar = 'http://124.71.135.249:8081' + this.comments[i].avatar
}
console.log("this.comments[i].parent_id" + this.comments[i].parent_id + "this.comments[i].username" + this.comments[i].username)
}
})
},
submitCommentForm() {
//
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
var created = year + "-" + month + "-" + day;
this.commentForm.id = this.blog.id
this.commentForm.username = this.username
this.commentForm.created = created
console.log(this.commentForm)
//
axios.post('/addComment', {
article_id: this.commentForm.id,
parent_id: this.replyComent.comment_id,
parent_name: this.replyComent.replyName,
content: this.commentForm.content,
created: this.commentForm.created
}).then((res) => {
console.log(res.data)
this.$message({
type: 'success',
message: '评论成功!'
});
//
this.commentGet()
//
this.commentForm.content = ''
}).catch((err) => {
console.log(err);
});
},
},
created() {
const blogId = this.$route.params.blogId
const that = this
axios.get('/getBlogDetail', {
params: {
blogId: blogId
}
}).then((res) => {
that.blog = res.data
console.log(res.data)
/**
* 将markdown的文本转为正常文本
* */
//markdown
var markDownIT = require("markdown-it")
var md = new markDownIT() //markdown-it
var result = md.render(that.blog.content) //markdownhtml
that.blog.content = result //
})
// this.commentGet(blogId)
},
}
</script>
<style scoped>
.mblog {
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
width: 100%;
min-height: 760px;
margin: 10px 10px;
}
.comment-container {
margin: 20px;
}
.comment-top {
margin-bottom: 10px;
}
.comment-avatar {
margin-right: 10px;
margin-top: 5px;
}
.comment-username {
padding-bottom: 5px;
}
.comment-time {
margin-left: 5px;
font-size: 10px;
}
.reply-button {
display: none;
float: right;
}
.comment-container:hover .reply-button {
display: inline-block;
}
.comment-content {
padding: 20px;
}
.comment-reply {
margin: 20px;
padding-left: 20px
}
.comment-reply:hover .reply-button {
display: inline-block;
}
</style>

139
src/views/BlogEditView.vue Normal file
View File

@ -0,0 +1,139 @@
<template>
<div>
<!-- 引用导航 -->
<Header></Header>
<br>
<div class="m_content">
<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="标题" prop="title">
<el-input v-model="ruleForm.title"></el-input>
</el-form-item>
<el-form-item label="摘要" prop="description">
<el-input type="textarea" v-model="ruleForm.description"></el-input>
</el-form-item>
<el-form-item label="内容" prop="content">
<!-- 特殊组件 -->
<mavon-editor v-model="ruleForm.content"></mavon-editor>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">编辑提交</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
</div>
<br>
<Footer></Footer>
<br>
</div>
</template>
<script>
import axios from 'axios';
import Header from "../components/Header";
import Footer from "../components/Footer";
export default {
components: { Header, Footer },
beforeRouteEnter(to, from, next) {
//
window.scrollTo(0, 0);
next();
},
data() {
return {
ruleForm: {
id: "",
title: "",
description: "",
content: "",
},
rules: {
title: [
{ required: true, message: "请输入标题", trigger: "blur" },
{
min: 5,
max: 100,
message: "长度在 5 到 100 个字符",
trigger: "blur",
},
],
description: [
{ required: true, message: "请输入摘要", trigger: "blur" },
],
content: [{ required: true, message: "请输入内容", trigger: "blur" }],
},
};
},
methods: {
submitForm(formName) {
//
// this.$refs[formName].validate((valid) => {
// if (valid) {
// //
// axios.post('/updateBlog', {
// id: this.ruleForm.id,
// title: this.ruleForm.title,
// description: this.ruleForm.description,
// content: this.ruleForm.content,
// created: new Date()
// }).then(function (response) {
// console.log(response.data)
// //
// window.location.href = "/"
// })
// } else {
// console.log("error submit!!");
// return false;
// }
// });
console.log(formName);
this.$message({
type: 'success',
message: '该功能暂时不对外开发哦!'
});
},
resetForm(formName) {
console.log(formName)
// this.$refs[formName].resetFields();//Element,
this.$message({
type: 'success',
message: '该功能暂时不对外开发哦!'
});
}
},
//
created() {
//
///blog/{id}/edit
///blog/add
const blogId = this.$route.params.blogId
const that = this
if (blogId !== undefined && blogId !== null && blogId !== '') {
console.log(blogId)
axios.get('/getBlogDetail', {
params: {
blogId: blogId
}
}).then(function (response) {
console.log(response.data)
that.ruleForm.id = response.data.id
that.ruleForm.title = response.data.title
that.ruleForm.description = response.data.description
that.ruleForm.content = response.data.content
})
}
},
name: "BlogEditView",
};
</script>
<style>
.m_content {
margin: 0 auto;
}
</style>

314
src/views/BlogHomeView.vue Normal file
View File

@ -0,0 +1,314 @@
<template>
<div>
<HomeHeader></HomeHeader>
<br>
<div class="container">
<!-- 引用导航 -->
<el-row>
<div class="live2d-container">
<el-col :span="1">
<live2d style="position: absolute; left: 0; bottom: 0;"
:model="['Potion-Maker/Pio', 'school-2017-costume-yellow']" :direction="direction" :size="size">
</live2d>
</el-col>
</div>
<el-col :span="23">
<el-card :body-style="{ padding: '0px' }" v-for="blog in pagedBlogs" style="margin-bottom: 20px;"
:key="blog.id">
<el-col :span="12">
<router-link :to="{ name: 'BlogDetail', params: { blogId: blog.id } }">
<img :src="blog.imageUrl" class="pulse animated image" />
</router-link>
</el-col>
<el-col :span="12">
<!-- 路由跳转 -->
<br>
<router-link :to="{ name: 'BlogDetail', params: { blogId: blog.id } }">
<h4 style="font-size: 20px">{{ blog.title }} </h4>
</router-link>
<el-divider></el-divider>
<div class="bottom">
<p>{{ blog.description }}</p>
</div>
</el-col>
</el-card>
</el-col>
</el-row>
<el-pagination background layout="prev, pager, next" :total="total" :page-size="pageSize"
:current-page="currentPage" hide-on-single-page="true" @current-change="handleCurrentChange">
</el-pagination>
</div>
<br>
<Footer></Footer>
<br>
</div>
</template>
<script>
import axios from "axios";
import HomeHeader from "../components/HomeHeader";
import Footer from "../components/Footer";
//
import live2d from 'vue-live2d'
import { startSakura } from "../js/Sakura"
export default {
components: {
HomeHeader,
Footer,
live2d
},
beforeRouteEnter(to, from, next) {
//
window.scrollTo(0, 0);
next();
},
created() {
this.getBlogs();
},
mounted() {
this.show();
this.note();
startSakura()
},
beforeRouteLeave(to, from, next) {
//
//
next();
},
data() {
return {
blogs: {},
currentPage: 1, //
total: 0, //
pageSize: 3, //
pagedBlogs: [],
imageUrls: [
require("../assets/gundam1.png"),
require("../assets/gundam2.png"),
require("../assets/gundam3.png"),
require("../assets/gundam4.png"),
require("../assets/gundam5.png"),
require("../assets/gundam6.png"),
require("../assets/gundam7.png"),
require("../assets/gundam8.png"),
],
direction: 'right',
width: 500,
height: 500,
size: 350,
tips: {
mouseover: [{
selector: '.vue-live2d',
texts: ['这样可以修改默认语句']
}]
},
}
},
methods: {
getBlogs() {
const that = this;
axios.get("/getBlogs").then((response) => {
that.blogs = response.data;
for (let index in that.blogs) {
that.blogs[index].imageUrl = this.imageUrls[index % 8];
console.log(that.blogs[index].imageUrl);
}
that.total = that.blogs.length; //
that.handleCurrentChange(that.currentPage); //
});
},
handleCurrentChange(page) {
const startIndex = (page - 1) * this.pageSize; //
const endIndex = startIndex + this.pageSize; //
this.pagedBlogs = this.blogs.slice(startIndex, endIndex); //
},
show() {
!function () {
function n(n, e, t) {
return n.getAttribute(e) || t
}
function e(n) {
return document.getElementsByTagName(n)
}
function t() {
var t = e("script"), o = t.length, i = t[o - 1];
return { l: o, z: n(i, "zIndex", -1), o: n(i, "opacity", .5), c: n(i, "color", "0,0,0"), n: n(i, "count", 99) }
}
function o() {
a = m.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth, c = m.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
}
function i() {
r.clearRect(0, 0, a, c);
var n, e, t, o, m, l;
s.forEach(function (i, x) {
for (i.x += i.xa, i.y += i.ya, i.xa *= i.x > a || i.x < 0 ? -1 : 1, i.ya *= i.y > c || i.y < 0 ? -1 : 1, r.fillRect(i.x - .5, i.y - .5, 1, 1), e = x + 1; e < u.length; e++) n = u[e], null !== n.x && null !== n.y && (o = i.x - n.x, m = i.y - n.y, l = o * o + m * m, l < n.max && (n === y && l >= n.max / 2 && (i.x -= .03 * o, i.y -= .03 * m), t = (n.max - l) / n.max, r.beginPath(), r.lineWidth = t / 2, r.strokeStyle = "rgba(" + d.c + "," + (t + .2) + ")", r.moveTo(i.x, i.y), r.lineTo(n.x, n.y), r.stroke()))
}), x(i)
}
var a, c, u, m = document.createElement("canvas"), d = t(), l = "c_n" + d.l, r = m.getContext("2d"),
x = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (n) {
window.setTimeout(n, 1e3 / 45)
}, w = Math.random, y = { x: null, y: null, max: 2e4 };
m.id = l, m.style.cssText = "position:fixed;top:0;left:0;z-index:" + d.z + ";opacity:" + d.o, e("body")[0].appendChild(m), o(), window.onresize = o, window.onmousemove = function (n) {
n = n || window.event, y.x = n.clientX, y.y = n.clientY
}, window.onmouseout = function () {
y.x = null, y.y = null
};
for (var s = [], f = 0; d.n > f; f++) {
var h = w() * a, g = w() * c, v = 2 * w() - 1, p = 2 * w() - 1;
s.push({ x: h, y: g, xa: v, ya: p, max: 6e3 })
}
u = s.concat([y]), setTimeout(function () {
i()
}, 100)
}();
},
note() {
(function () {
var a_idx = 0;
window.onclick = function (event) {
var A = new Array("富强", "民主", "文明", "和谐", "自由", "平等", "公正", "法治", "爱国", "敬业", "诚信", "友善");
var heart = document.createElement("b"); //b
heart.onselectstart = new Function('event.returnValue=false'); //
document.body.appendChild(heart).innerHTML = A[a_idx]; //b
a_idx = (a_idx + 1) % A.length;
heart.style.cssText = "position: fixed;left:-100%;"; //p
var f = 16, //
x = event.clientX - f / 2, //
y = event.clientY - f, //
c = randomColor(), //
a = 1, //
s = 1.2; //
var timer = setInterval(function () { //
if (a <= 0) {
document.body.removeChild(heart);
clearInterval(timer);
} else {
heart.style.cssText = "font-size:16px;cursor: default;position: fixed;color:" +
c + ";left:" + x + "px;top:" + y + "px;opacity:" + a + ";transform:scale(" +
s + ");";
y--;
a -= 0.016;
s += 0.002;
}
}, 15)
}
//
function randomColor() {
return "rgb(" + (~~(Math.random() * 255)) + "," + (~~(Math.random() * 255)) + "," + (~~(Math
.random() * 255)) + ")";
}
}());
},
},
name: "BlogTestView",
};
</script>
<style>
/*base code*/
.animated {
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
.animated.infinite {
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.animated.hinge {
-webkit-animation-duration: 2s;
animation-duration: 2s;
}
/*the animation definition*/
@-webkit-keyframes pulse {
0% {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1)
}
50% {
-webkit-transform: scale3d(1.05, 1.05, 1.05);
transform: scale3d(1.05, 1.05, 1.05)
}
100% {
-webkit-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1)
}
}
@keyframes pulse {
0% {
-webkit-transform: scale3d(1, 1, 1);
-ms-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1)
}
50% {
-webkit-transform: scale3d(1.05, 1.05, 1.05);
-ms-transform: scale3d(1.05, 1.05, 1.05);
transform: scale3d(1.05, 1.05, 1.05)
}
100% {
-webkit-transform: scale3d(1, 1, 1);
-ms-transform: scale3d(1, 1, 1);
transform: scale3d(1, 1, 1)
}
}
.pulse:hover {
-webkit-animation-name: pulse;
animation-name: pulse
}
.live2d-container {
position: fixed;
left: 0;
bottom: 0;
z-index: 9999;
}
.container {
/* 居中显示 */
margin: 0 auto;
width: 60%;
z-index: 10;
}
.bottom {
margin-top: 10px;
}
.image {
width: 100%;
display: block;
}
</style>

108
src/views/BlogTimeView.vue Normal file
View File

@ -0,0 +1,108 @@
<template>
<div>
<!-- 引用导航 -->
<TimeHeader></TimeHeader>
<br>
<div>
<div class="live2d-container">
<el-col :span="1">
<live2d style="position: absolute; left: 0; bottom: 0;"
:model="['Potion-Maker/Pio', 'school-2017-costume-yellow']" :direction="direction" :size="size">
</live2d>
</el-col>
</div>
<div class="block" style="width: 60%; margin: 0 auto">
<el-timeline style="text-align: left" :reverse="false">
<eltimeline-item :timestamp="new Date()" placement="bottom">
<el-card>
<h style="font-size: 15px">目前共计{{ total }}篇文章继续加油</h>
</el-card>
</eltimeline-item>
<br>
<el-timeline-item :timestamp="new Date(blog.created)" placement="top" v-for="blog in pagedBlogs"
:key="blog.title">
<el-card>
<!-- 路由跳转 -->
<router-link :to="{ name: 'BlogDetail', params: { blogId: blog.id } }">
<h4 style="font-size: 20px">{{ blog.title }}</h4>
</router-link>
<p>{{ blog.description }}</p>
</el-card>
</el-timeline-item>
</el-timeline>
</div>
<el-pagination background layout="prev, pager, next" :total="total" :page-size="pageSize"
:current-page="currentPage" hide-on-single-page="true" @current-change="handleCurrentChange">
</el-pagination>
</div>
<br>
<Footer></Footer>
<br>
</div>
</template>
<script>
import axios from "axios";
import TimeHeader from "../components/TimeHeader.vue";
import Footer from "../components/Footer.vue";
import live2d from 'vue-live2d'
export default {
components: { TimeHeader, Footer, live2d },
beforeRouteEnter(to, from, next) {
//
window.scrollTo(0, 0);
next();
},
created() {
this.getBlogs();
},
data() {
return {
blogs: {},
currentPage: 1, //
total: 0, //
pageSize: 5, //
pagedBlogs: [],
direction: 'right',
width: 500,
height: 500,
size: 350,
tips: {
mouseover: [{
selector: '.vue-live2d',
texts: ['这样可以修改默认语句']
}]
}
};
},
methods: {
getBlogs() {
const that = this;
axios.get("/getBlogs").then((response) => {
that.blogs = response.data;
that.total = that.blogs.length; //
that.handleCurrentChange(that.currentPage); //
});
},
handleCurrentChange(page) {
const startIndex = (page - 1) * this.pageSize; //
const endIndex = startIndex + this.pageSize; //
this.pagedBlogs = this.blogs.slice(startIndex, endIndex); //
},
},
name: "BlogHomeView",
};
</script>
<style>
.live2d-container {
position: fixed;
left: 0;
bottom: 0;
z-index: 9999;
}
</style>

View File

@ -1,18 +0,0 @@
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>
</template>
<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
export default {
name: 'HomeView',
components: {
HelloWorld
}
}
</script>

239
src/views/LoginView.vue Normal file
View File

@ -0,0 +1,239 @@
<template>
<!-- <div class="container">
<div class="login"> -->
<div class="body">
<el-card class="box-card transparent-card">
<div>
<span>个人博客(正在开发)</span>
</div>
<div>
<el-tabs stretch>
<el-tab-pane label="登陆">
<el-form :model="loginForm" status-icon :rules="rules" label-width="80px" ref="loginForm">
<el-form-item label="用户名" prop="username">
<el-input type="text" v-model="loginForm.username"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" v-model="loginForm.password"></el-input>
</el-form-item>
<el-form-item>
<el-button style="margin-right: 50px;" type="primary"
@click="submitLoginForm()">登陆</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
<el-tab-pane label="注册">
<el-form :model="registerForm" status-icon :rules="rules" label-width="80px">
<el-form-item label="用户名" prop="username">
<el-input type="text" v-model="registerForm.username"></el-input>
</el-form-item>
<el-form-item label="密码" prop="password">
<el-input type="password" v-model="registerForm.password"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="configurePassword">
<el-input type="password" v-model="registerForm.configurePassword"></el-input>
</el-form-item>
<el-form-item>
<el-button style="margin-right: 50px;" type="primary"
@click="submitRegisterForm()">注册</el-button>
</el-form-item>
</el-form>
</el-tab-pane>
</el-tabs>
</div>
</el-card>
<div class="stars" ref="starsRef">
<div class="star" v-for="(item, index) in starsCount" :key="index"></div>
</div>
</div>
</template>
<script>
import axios from 'axios';
import { mapMutations } from 'vuex';//vuex
import { onMounted, ref } from "vue";
export default {
setup() {
let starsRef = ref(null);
const starsCount = 2000; //
const distance = 900; //
onMounted(() => {
let starNodes = Array.from(starsRef.value.children);
starNodes.forEach((item) => {
let speed = 0.2 + Math.random() * 1;
let thisDistance = distance + Math.random() * 300;
item.style.transformOrigin = `0 0 ${thisDistance}px`;
item.style.transform = `
translate3d(0,0,-${thisDistance}px)
rotateY(${Math.random() * 360}deg)
rotateX(${Math.random() * -50}deg)
scale(${speed},${speed})`;
});
});
return {
starsRef,
starsCount,
};
},
data() {
//
var validateUsername = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入用户名"));
} else if (value.length < 3) {
callback(new Error("长度不够"));
} else {
callback();
}
};
var validateConfigurePassword = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.registerForm.password) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
loginForm: {
username: "",
password: "",
},
registerForm: {
username: "",
password: "",
configurePassword: "",
},
rules: {
username: [
{ validator: validateUsername, trigger: 'blur' }, //trigger: 'blur'
],
password: [
{ required: true, message: '请输入密码', trigger: 'blur' },
],
configurePassword: [
{ validator: validateConfigurePassword, trigger: 'blur' },
]
}
}
},
methods: {
//mapMutations Vuex mutations
// - Vuex mutations
...mapMutations(['setToken']),
...mapMutations(['delToken']),
submitLoginForm() {
const that = this
axios.post("/login", {
username: this.loginForm.username,
password: this.loginForm.password
}).then(res => {
var jsonObject = res.data;
var jsonString = JSON.stringify(jsonObject)
if (jsonString !== "false") {
window.localStorage.setItem("token", jsonString);
that.setToken({ token: jsonString })
this.$router.push({ path: "/" })
this.$message.success("登陆成功!")
} else {
alert("账号或密码错误!")
}
})
},
submitRegisterForm() {
axios.post("/register", {
username: this.registerForm.username,
password: this.registerForm.password,
}).then(res => {
if (res.data === "注册成功") {
this.$message.success(res.data)
} else {
this.$message.error(res.data)
}
})
},
},
//token
created() {
const that = this
that.delToken({ token: "123" })
},
name: "LoginView",
}
</script>
<style lang="css" scoped>
.body {
position: absolute;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
background: radial-gradient(200% 100% at bottom center,
#f7f7b6,
#e96f92,
#1b2947);
background: radial-gradient(200% 105% at top center,
#1b2947 10%,
#75517d 40%,
#e96f92 65%,
#f7f7b6);
background-attachment: fixed;
overflow: hidden;
}
@keyframes rotate {
0% {
transform: perspective(400px) rotateZ(20deg) rotateX(-40deg) rotateY(0);
}
100% {
transform: perspective(400px) rotateZ(20deg) rotateX(-40deg) rotateY(-360deg);
}
}
.stars {
transform: perspective(500px);
transform-style: preserve-3d;
position: absolute;
perspective-origin: 50% 100%;
left: 45%;
animation: rotate 90s infinite linear;
bottom: 0;
}
.star {
width: 2px;
height: 2px;
background: #f7f7b6;
position: absolute;
left: 0;
top: 0;
backface-visibility: hidden;
}
.box-card {
width: 500px;
margin: 0 auto;
transform: translateY(150px);
}
.transparent-card {
background-color: rgba(255, 255, 255, 0.5);
}
</style>

View File

@ -0,0 +1,26 @@
<template>
<div>
<!-- //PC -->
<p>移动端未开发请移步PC端</p>
</div>
</template>
<script>
export default {
}
</script>
<style scoped>
p{
text-align: center;
margin-top: 100px;
font-family: "Montserrat", sans-serif;
font-weight: 500;
font-size: 30px;
color: #03dac6;
transition: all 0.3s ease;
text-shadow: 5px 5px 10px black;
}
</style>

View File

@ -0,0 +1,126 @@
<!-- <template>
<div id="imgwrap">
<img src="../assets/gundam1.png" alt="" />
<img src="../assets/gundam2.png" alt="" />
<img src="../assets/gundam3.png" alt="" />
<img src="../assets/gundam4.png" alt="" />
<img src="../assets/gundam5.png" alt="" />
<img src="../assets/gundam6.png" alt="" />
<img src="../assets/gundam7.png" alt="" />
<img src="../assets/gundam8.png" alt="" />
<img src="../assets/gundam1.png alt="" />
<img src="../assets/gundam1.png" alt="" />
<img src="../assets/gundam1.png" alt="" />
<img src="../assets/gundam1.png" alt="" />
<img src="../assets/gundam1.png" alt="" />
<img src="../assets/gundam1.png" alt="" />
</div>
<div>
<button onclick="Act()">开始</button>
</div>
</template>
<script>
export default {
data() {
return {
allEnd: 0, //
on: true, //
imgs: document.querySelectorAll('#imgwrap img')
}
},
methods: {
Act() {
var endNum = 0; //
var on = false; //
if (!on) {
return;
}
for (var i = 0; i < imgs.length; i++) {
(function (i) {
setTimeout(function () {
montion(imgs[i], '10ms', function () {
this.style.transform = "scale(0)"; //0
}, function () {
//
montion(this, '1s', function () {
this.style.transform = "scale(1)";
this.style.opacity = 0;
}, function () {
endNum++; //1
if (endNum == imgs.length) {
toBig();
}
});
});
}, Math.random() * 1000); //500
})(i)
}
},
toBig() {
for (var i = 0; i < imgs.length; i++) {
imgs[i].style.transition = "";
//css3
imgs[i].style.transform = 'rotateY(0deg)translateZ(-' + Math.random() * 500 + 'px)';
//i
(function (i) {
setTimeout(function () {
montion(imgs[i], '2s', function () {
this.style.opacity = 1;
this.style.transform = 'rotateY(-360deg) translateZ(0)';
}, function () {
allEnd++;
if (allEnd == imgs.length) {
//
on = true; //
}
});
}, Math.random() * 1000);
})(i);
}
},
montion(obj, time, doFn, callBack) {
obj.style.transition = time;
doFn.call(obj); //,thisobj
var called = false; //transitionendbug
obj.addEventListener('transitionend', function () {
if (!called) {
callBack && callBack.call(obj);
called = true;
}
}, false);
},
name: "ProjectWallView"
}
}
</script>
<style type="text/css">
#imgwrap {
width: 1480px;
height: 440px;
margin: 50px auto;
perspective: 880px;
}
#imgwrap img {
width: 358px;
height: 188px;
float: left;
}
#btn {
width: 100px;
text-align: center;
font: 16px/40px "微软雅黑";
color: white;
padding: 0 20px;
margin: 0 auto;
border-radius: 5px;
background: rgb(0, 100, 0);
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.5);
cursor: pointer;
}
</style> -->

View File

@ -2,3 +2,14 @@ const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true
})
module.exports = {
pwa: {
iconPaths: {
favicon32: 'favicon.ico',
favicon16: 'favicon.ico',
appleTouchIcon: 'favicon.ico',
maskIcon: 'favicon.ico',
msTileImage: 'favicon.ico'
}
}
};