This commit is contained in:
username 2024-06-15 16:53:22 +08:00
parent f255121dff
commit 952447ec70
17 changed files with 518 additions and 246 deletions

View File

@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0"> <meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title> <title>墨思留痕</title>
</head> </head>
<body> <body>
<noscript> <noscript>

View File

@ -1,6 +1,6 @@
<template> <template>
<div id="app"> <div id="app">
<main> <main>
<router-view /> <router-view />
<trigger></trigger> <trigger></trigger>
</main> </main>
@ -13,8 +13,13 @@
<script> <script>
import trigger from '@/components/trigger.vue' import trigger from '@/components/trigger.vue'
import basePage from './components/base.vue' import basePage from './components/base.vue'
export default {
export default {
data () {
return {
}
},
components: { components: {
trigger, trigger,
basePage basePage
@ -23,22 +28,5 @@ export default {
</script> </script>
<style lang="less"> <style lang="less">
*{
box-sizing: border-box;
}
/* 针对 WebKit 浏览器 */
::-webkit-scrollbar {
width: 5px; /* 滚动条宽度 */
}
::-webkit-scrollbar-thumb {
background: #2ee600; /* 滑块颜色 */
border-radius: 10px; /* 滑块圆角 */
}
::-webkit-scrollbar-track {
background: #f1f1f1ef; /* 轨道颜色 */
border-radius: 10px; /* 轨道圆角 */
}
</style> </style>

9
src/api/interlinkage.js Normal file
View File

@ -0,0 +1,9 @@
import request from '../utils/request'
export function interList (data) {
return request({
url: '/interList',
method: 'get',
data
})
}

View File

@ -7,3 +7,11 @@ export function login (data) {
data data
}) })
} }
export function autoLogin (token) {
return request({
url: '/auto-login',
method: 'post',
data: { token }
})
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,14 +1,35 @@
*{ * {
padding: 0; padding: 0;
margin: 0; margin: 0;
list-style: none; list-style: none;
} box-sizing: border-box;
}
body{
background-color: #eeeeee; /* 针对 WebKit 浏览器 */
} ::-webkit-scrollbar {
width: 5px;
a { /* 滚动条宽度 */
text-decoration: inherit; }
color: inherit;
} ::-webkit-scrollbar-thumb {
background: #2ee600;
/* 滑块颜色 */
border-radius: 10px;
/* 滑块圆角 */
}
::-webkit-scrollbar-track {
background: #f1f1f1ef;
/* 轨道颜色 */
border-radius: 10px;
/* 轨道圆角 */
}
body {
background-color: #eeeeee;
}
a {
text-decoration: inherit;
color: inherit;
}

View File

@ -80,6 +80,13 @@ export default {
return this.playlist[this.currentSongIndex] return this.playlist[this.currentSongIndex]
} }
}, },
mounted () {
// localStorage
const savedLockState = localStorage.getItem('isLocked')
if (savedLockState !== null) {
this.isLocked = JSON.parse(savedLockState)
}
},
methods: { methods: {
searchMusic () { searchMusic () {
// //
@ -93,8 +100,7 @@ export default {
}, },
prevSong () { prevSong () {
this.currentSongIndex = this.currentSongIndex =
(this.currentSongIndex - 1 + this.playlist.length) % (this.currentSongIndex - 1 + this.playlist.length) % this.playlist.length
this.playlist.length
this.isPlaying = true // this.isPlaying = true //
}, },
nextSong () { nextSong () {
@ -104,6 +110,8 @@ export default {
}, },
toggleLock () { toggleLock () {
this.isLocked = !this.isLocked this.isLocked = !this.isLocked
// localStorage
localStorage.setItem('isLocked', JSON.stringify(this.isLocked))
} }
} }
} }

View File

@ -102,9 +102,10 @@ export default {
}, },
// 退 // 退
handleOut () { handleOut () {
this.$router.push({ path: '/login' }) localStorage.removeItem('token')
this.$router.push('/login')
this.$message({ this.$message({
message: '退出成功', message: '您已退出',
type: 'success' type: 'success'
}) })
}, },

View File

View File

@ -12,6 +12,8 @@ Vue.use(ElementUI)
Vue.component('navigationBar', navigationBar) Vue.component('navigationBar', navigationBar)
Vue.component('musIc', music) Vue.component('musIc', music)
document.title = '墨思留痕'
Vue.config.productionTip = false Vue.config.productionTip = false
new Vue({ new Vue({

View File

@ -1,4 +1,6 @@
import axios from 'axios' import axios from 'axios'
import { Message } from 'element-ui'
import router from '../router'
// 创建一个 axios 实例 // 创建一个 axios 实例
const service = axios.create({ const service = axios.create({
@ -9,27 +11,29 @@ const service = axios.create({
// 请求拦截器 // 请求拦截器
service.interceptors.request.use( service.interceptors.request.use(
config => { config => {
// 从 localStorage 中获取 token const token = localStorage.getItem('token')
const token = localStorage.getItem('user-token')
if (token) { if (token) {
// 将 token 添加到请求头中
config.headers.Authorization = `Bearer ${token}` config.headers.Authorization = `Bearer ${token}`
} }
return config return config
}, },
error => { error => {
// 对请求错误做些什么
return Promise.reject(error) return Promise.reject(error)
} }
) )
// 响应拦截器
service.interceptors.response.use( service.interceptors.response.use(
response => { response => {
// 对响应数据做点什么
return response return response
}, },
error => { error => {
if (error.response && error.response.status === 401) {
Message.error('认证已过期,请重新登录')
localStorage.removeItem('token')
router.push('/login')
} else {
Message.error(error.message)
}
return Promise.reject(error) return Promise.reject(error)
} }
) )

View File

@ -3,7 +3,6 @@
<navigationBar /> <navigationBar />
<div class="box"> <div class="box">
<el-tabs type="border-card"> <el-tabs type="border-card">
<el-tab-pane label="个人信息"> <el-tab-pane label="个人信息">
<div class="AboutUs-left"> <div class="AboutUs-left">
<div class="AboutUs-img"> <div class="AboutUs-img">
@ -117,8 +116,27 @@
</div> </div>
</div> </div>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<!-- 头像上传 -->
<el-dialog title="更换头像" :visible.sync="dialogVisible" width="30%">
<el-upload
class="avatar-uploader"
action="https://jsonplaceholder.typicode.com/posts/"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
>
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="handleAddAvatar"
> </el-button
>
</span>
</el-dialog>
</div> </div>
<musIc /> <musIc />
@ -139,6 +157,8 @@ export default {
birthday: '', birthday: '',
region: '', region: '',
city: '', city: '',
dialogVisible: false,
imageUrl: '',
avatar: require('@/assets/images/789.jpg'), // avatar: require('@/assets/images/789.jpg'), //
users: [ users: [
{ {
@ -163,10 +183,6 @@ export default {
// //
this.$message.success('保存成功') this.$message.success('保存成功')
}, },
changeAvatar () {
//
this.$message.success('更换成功')
},
// //
handleAdd () { handleAdd () {
if (this.newTodo.trim() !== '') { if (this.newTodo.trim() !== '') {
@ -190,6 +206,32 @@ export default {
} else { } else {
this.$message.error('请选择要删除的待办事项') this.$message.error('请选择要删除的待办事项')
} }
},
changeAvatar () {
//
this.dialogVisible = true
},
handleAvatarSuccess (res, file) {
this.imageUrl = URL.createObjectURL(file.raw)
},
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
},
handleAddAvatar () {
this.$message({
message: '上传成功',
type: 'success'
})
this.dialogVisible = false
} }
} }
} }
@ -197,7 +239,7 @@ export default {
<style lang="less" scoped> <style lang="less" scoped>
.wtbDone { .wtbDone {
width: 400px; width: 700px;
height: 500px; height: 500px;
border: 1px solid black; border: 1px solid black;
margin: auto; margin: auto;
@ -207,7 +249,7 @@ export default {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
input { input {
width: 300px; width: 550px;
height: 40px; height: 40px;
padding: 5px; padding: 5px;
margin-top: 20px; margin-top: 20px;
@ -219,61 +261,61 @@ export default {
border: 1px solid #007bff; border: 1px solid #007bff;
} }
} }
} }
ul { ul {
list-style: none; list-style: none;
padding: 0; padding: 0;
width: 350px; width: 600px;
height: 310px; height: 310px;
margin: 20px auto; margin: 20px auto;
overflow-y: scroll; overflow-y: scroll;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 4px; border-radius: 4px;
li { li {
width: 100%; width: 100%;
height: 40px;
line-height: 40px;
text-align: center;
background-color: #f5f5f5;
border-bottom: 1px solid #ddd;
cursor: pointer;
transition: background-color 0.3s;
&:hover {
background-color: #e6e6e6;
}
&.selected {
background-color: #d3e5ff;
}
}
}
.wtbDone-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20px;
padding: 10px;
}
button {
width: 70px;
height: 40px; height: 40px;
background-color: #007bff; line-height: 40px;
color: #fff; text-align: center;
border: none; background-color: #f5f5f5;
border-radius: 4px; border-bottom: 1px solid #ddd;
margin-left: 5px;
cursor: pointer; cursor: pointer;
transition: background-color 0.3s; transition: background-color 0.3s;
&:hover { &:hover {
background-color: #0056b3; background-color: #e6e6e6;
}
&.selected {
background-color: #d3e5ff;
} }
} }
}
.wtbDone-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 20px;
padding: 10px;
}
button {
width: 120px;
height: 40px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 4px;
margin-left: 5px;
cursor: pointer;
transition: background-color 0.3s;
&:hover {
background-color: #0056b3;
}
}
.box { .box {
background-color: #f5f5f5; background-color: #f5f5f5;
@ -445,4 +487,28 @@ hr {
background-color: #218838; background-color: #218838;
} }
} }
.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: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style> </style>

View File

@ -17,65 +17,23 @@
</template> </template>
<script> <script>
import { interList } from '@/api/interlinkage'
export default { export default {
name: 'interLinkage', name: 'interLinkage',
data () { data () {
return { return {
contentList: [ contentList: []
{
img: require('@/assets/images/kecheng/C.jpg'),
name: '百度一下,你就知道',
url: 'http://www.baidu.com'
},
{
img: require('@/assets/images/kecheng/C.jpg'),
name: '4399小游戏',
url: 'http://www.4399.com'
},
{
img: require('@/assets/images/kecheng/C.jpg'),
name: '百度一下,你就知道',
url: 'http://www.baidu.com'
},
{
img: require('@/assets/images/kecheng/C.jpg'),
name: '4399小游戏',
url: 'http://www.4399.com'
},
{
img: require('@/assets/images/kecheng/C.jpg'),
name: '百度一下,你就知道',
url: 'http://www.baidu.com'
},
{
img: require('@/assets/images/kecheng/C.jpg'),
name: '4399小游戏',
url: 'http://www.4399.com'
},
{
img: require('@/assets/images/kecheng/C.jpg'),
name: '百度一下,你就知道',
url: 'http://www.baidu.com'
},
{
img: require('@/assets/images/kecheng/C.jpg'),
name: '4399小游戏',
url: 'http://www.4399.com'
},
{
img: require('@/assets/images/kecheng/C.jpg'),
name: '百度一下,你就知道',
url: 'http://www.baidu.com'
},
{
img: require('@/assets/images/kecheng/C.jpg'),
name: '4399小游戏',
url: 'http://www.4399.com'
}
]
} }
}, },
created () {
this.getList()
},
methods: { methods: {
getList () {
interList().then(res => {
this.contentList = res.data
})
},
goLink (url) { goLink (url) {
window.open(url) window.open(url)
} }

View File

@ -10,8 +10,9 @@
</header> </header>
<div class="box-bd"> <div class="box-bd">
<ul class="clearfix"> <ul class="clearfix">
<li v-for="(item, index) in items" :key="index" > <li v-for="(item, index) in items" :key="index">
<router-link :to="`/paiListPage/${index + 1}`"> <!-- 这里的index + 1对应着表的序号 --> <router-link :to="`/paiListPage/${index + 1}`">
<!-- 这里的index + 1对应着表的序号 -->
<img :src="item.url" :alt="item.title" /> <img :src="item.url" :alt="item.title" />
<h4>{{ item.title }}</h4> <h4>{{ item.title }}</h4>
</router-link> </router-link>
@ -25,7 +26,19 @@
<button @click="openDialog">添加笔记</button> <button @click="openDialog">添加笔记</button>
</div> </div>
<!-- 其他代码 --> <!-- 添加笔记弹窗 -->
<el-dialog title="提示" :visible.sync="dialogVisible" width="30%">
<el-form ref="form" :model="form" label-width="80px" :rules="rules">
<el-form-item label="笔记标题" prop="addContent">
<el-input v-model="form.addContent"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="handleAdd"> </el-button>
</span>
</el-dialog>
<musIc /> <musIc />
</div> </div>
</template> </template>
@ -35,14 +48,11 @@ import { getTags } from '@/api/tags'
export default { export default {
data () { data () {
return { return {
items: [ items: [],
],
drawer: false,
direction: 'ltr',
dialogVisible: false, dialogVisible: false,
form: {}, form: {
addContent: '', addContent: ''
},
rules: { rules: {
addContent: [ addContent: [
{ required: true, message: '请输入标题', trigger: 'blur' } { required: true, message: '请输入标题', trigger: 'blur' }
@ -55,7 +65,7 @@ export default {
}, },
methods: { methods: {
fetchTags () { fetchTags () {
getTags().then(res => { getTags().then((res) => {
this.items = res.data this.items = res.data
}) })
}, },
@ -63,17 +73,12 @@ export default {
this.dialogVisible = true this.dialogVisible = true
}, },
handleAdd () { handleAdd () {
this.$refs.form.validate((valid) => { this.dialogVisible = false
if (valid) { this.$message({
this.$message({ message: '添加成功',
message: '添加成功', type: 'success'
type: 'success'
})
this.dialogVisible = false
} else {
this.$message.error('请检查输入项')
}
}) })
this.form.addContent = ''
} }
} }
} }

View File

@ -35,7 +35,7 @@
</div> </div>
<div class="tool"> <div class="tool">
<div> <div>
<el-checkbox v-model="checked" @change="remenber" v-if="!create" <el-checkbox v-model="checked" @change="remember" v-if="!create"
>记住密码</el-checkbox >记住密码</el-checkbox
> >
</div> </div>
@ -56,7 +56,7 @@
</template> </template>
<script> <script>
import { login } from '@/api/login' // import { login, autoLogin } from '@/api/login'
import dayjs from 'dayjs' import dayjs from 'dayjs'
export default { export default {
@ -91,33 +91,110 @@ export default {
setInterval(() => { setInterval(() => {
this.postDate = dayjs().format('HH : mm : ss') this.postDate = dayjs().format('HH : mm : ss')
}, 1000) }, 1000)
this.loadRememberedCredentials()
//
const token = localStorage.getItem('token')
if (token) {
this.autoLogin(token)
}
}, },
methods: { methods: {
login () { loadRememberedCredentials () {
// const rememberedUsername = localStorage.getItem('rememberedUsername')
login(this.form).then(response => { const rememberedPassword = localStorage.getItem('rememberedPassword')
// const rememberMeChecked = localStorage.getItem('rememberMeChecked')
console.log(response) //
this.$router.push('/') if (rememberedUsername && rememberedPassword && rememberMeChecked) {
this.form.username = rememberedUsername
this.form.password = rememberedPassword
this.checked = JSON.parse(rememberMeChecked)
}
},
autoLogin (token) {
autoLogin(token).then(response => {
console.log(response)
if (this.$route.path !== '/') {
this.$router.push('/')
}
this.$message({ this.$message({
message: '登陆成功', message: '自动登录成功',
type: 'success' type: 'success'
}) })
}).catch(error => { }).catch(error => {
// console.error('自动登录失败:', error)
console.error('登录失败:', error) localStorage.removeItem('token')
this.$message({ this.$message({
message: '登录失败,请检查账号或密码', message: '自动登录失败,请重新登录',
type: 'error' type: 'error'
}) })
}) })
}, },
remenber (data) { login () {
this.checked = data if (this.form.username === '' || this.form.password === '') {
if (this.checked) { this.$message({
localStorage.setItem('news', JSON.stringify(this.form)) message: '账号或密码不能为空',
type: 'error'
})
return
}
//
if (!this.create) {
login({ ...this.form }).then(response => {
console.log(response)
localStorage.setItem('token', response.data.token)
if (this.checked) {
localStorage.setItem('rememberedUsername', this.form.username)
localStorage.setItem('rememberedPassword', this.form.password)
localStorage.setItem('rememberMeChecked', true)
} else {
localStorage.removeItem('rememberedUsername')
localStorage.removeItem('rememberedPassword')
localStorage.removeItem('rememberMeChecked')
}
if (this.$route.path !== '/') {
this.$router.push('/')
}
this.$message({
message: '登陆成功',
type: 'success'
})
}).catch(error => {
console.error('登录失败:', error)
if (error.response && error.response.status === 401) {
this.$message({
message: '账号或密码错误',
type: 'error'
})
} else {
this.$message({
message: '服务器错误,请稍后再试',
type: 'error'
})
}
})
} else { } else {
localStorage.removeItem('news') this.$message({
message: '暂未开放注册,请联系管理员',
type: 'warning'
})
}
},
remember () {
if (this.checked) {
this.$message({
message: '将会记住您的登录信息',
type: 'info'
})
} else {
localStorage.removeItem('rememberedUsername')
localStorage.removeItem('rememberedPassword')
localStorage.removeItem('rememberMeChecked')
this.$message({
message: '已取消记住密码',
type: 'info'
})
} }
}, },
forgetpas () { forgetpas () {
@ -128,22 +205,19 @@ export default {
}, },
register () { register () {
if (this.create) { if (this.create) {
window.location.reload() //
} else if ( this.create = false
this.form.username || this.loadRememberedCredentials()
this.form.password || } else {
this.form.repassword //
) { this.create = true
//
this.form.username = '' this.form.username = ''
this.form.password = '' this.form.password = ''
this.form.repassword = '' this.form.repassword = ''
this.$refs.form.clearValidate('username')
this.$refs.form.clearValidate('password')
this.$refs.form.clearValidate('repassword')
} }
this.create = !this.create
//
this.$refs.form.clearValidate('username')
this.$refs.form.clearValidate('password')
this.$refs.form.clearValidate('repassword')
} }
} }
} }
@ -180,7 +254,7 @@ export default {
/* 左侧阴影 */ 5px -5px 10px rgba(0, 0, 0, 0.1), /* 左侧阴影 */ 5px -5px 10px rgba(0, 0, 0, 0.1),
/* 下部阴影 */ -5px -5px 10px rgba(0, 0, 0, 0.1); /* 上部阴影 */ /* 下部阴影 */ -5px -5px 10px rgba(0, 0, 0, 0.1); /* 上部阴影 */
width: 400px; width: 400px;
height: 300px; height: 350px;
padding: 30px; padding: 30px;
border-radius: 10px; border-radius: 10px;
transform: translate(-50%); transform: translate(-50%);

View File

@ -23,16 +23,26 @@
</div> </div>
</div> </div>
<div class="gallery"> <div class="gallery">
<div class="pointer" :style="pointerStyle"></div>
<div <div
class="gallery-item" class="gallery-item"
v-for="(item, index) in photos" v-for="(item, index) in photos"
:key="index" :key="index"
:class="item.sizeClass" :class="item.sizeClass"
@mouseover="onMouseOver($event, item.sizeClass)"
@mouseleave="onMouseLeave"
@click="openImageViewer(item.src)"
ref="photoItems" ref="photoItems"
> >
<img :data-src="item.src" :alt="item.alt" class="lazy" /> <img :data-src="item.src" :alt="item.alt" class="lazy" />
</div> </div>
</div> </div>
<div v-if="showImageViewer" class="image-viewer" @click.self="closeImageViewer">
<div class="image-viewer-content">
<span class="close" @click="closeImageViewer">&times;</span>
<img :src="currentImage" />
</div>
</div>
<musIc /> <musIc />
</div> </div>
</template> </template>
@ -42,6 +52,7 @@ export default {
name: 'photoGallery', name: 'photoGallery',
data () { data () {
return { return {
//
photos: [ photos: [
{ src: require('@/assets/images/789.jpg'), alt: 'Photo 1', sizeClass: 'medium' }, { src: require('@/assets/images/789.jpg'), alt: 'Photo 1', sizeClass: 'medium' },
{ src: require('@/assets/images/789.jpg'), alt: 'Photo 2', sizeClass: 'large' }, { src: require('@/assets/images/789.jpg'), alt: 'Photo 2', sizeClass: 'large' },
@ -72,42 +83,56 @@ export default {
{ src: require('@/assets/images/789.jpg'), alt: 'Photo 27', sizeClass: 'small' } { src: require('@/assets/images/789.jpg'), alt: 'Photo 27', sizeClass: 'small' }
], ],
newPhoto: { newPhoto: {
src: '', src: '', // URL
alt: '' alt: '' //
}, },
newPhotoFile: null, newPhotoFile: null, //
showModal: false showModal: false, //
showImageViewer: false, //
currentImage: '', // URL
pointerStyle: {
display: 'none', //
top: '0px',
left: '0px',
width: '0px',
height: '0px',
borderColor: '' //
}
} }
}, },
methods: { methods: {
//
loadImages () { loadImages () {
const images = this.$refs.photoItems const images = this.$refs.photoItems //
const options = { const options = {
root: null, root: null,
rootMargin: '0px', rootMargin: '0px',
threshold: 0.1 threshold: 0.1 //
} }
// IntersectionObserver
const observer = new IntersectionObserver((entries, observer) => { const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => { entries.forEach(entry => {
if (entry.isIntersecting) { if (entry.isIntersecting) {
const img = entry.target.querySelector('img') const img = entry.target.querySelector('img')
img.src = img.getAttribute('data-src') img.src = img.getAttribute('data-src') //
observer.unobserve(entry.target) observer.unobserve(entry.target) //
} }
}) })
}, options) }, options)
images.forEach(image => { images.forEach(image => {
observer.observe(image) observer.observe(image) //
}) })
}, },
//
onFileChange (e) { onFileChange (e) {
const file = e.target.files[0] const file = e.target.files[0]
if (file) { if (file) {
this.newPhotoFile = URL.createObjectURL(file) this.newPhotoFile = URL.createObjectURL(file) // URL
} }
}, },
//
addPhoto () { addPhoto () {
if (this.newPhotoFile && this.newPhoto.alt) { if (this.newPhotoFile && this.newPhoto.alt) {
const sizeClasses = ['small', 'medium', 'large'] const sizeClasses = ['small', 'medium', 'large']
@ -117,24 +142,61 @@ export default {
alt: this.newPhoto.alt, alt: this.newPhoto.alt,
sizeClass: sizeClass sizeClass: sizeClass
}) })
this.newPhotoFile = null this.newPhotoFile = null //
this.newPhoto.alt = '' this.newPhoto.alt = '' //
this.showModal = false this.showModal = false //
document.body.classList.remove('no-scroll') document.body.classList.remove('no-scroll') //
this.$nextTick(() => { this.$nextTick(() => {
this.loadImages() this.loadImages() //
}) })
} }
}, },
//
openModal () { openModal () {
this.showModal = true this.showModal = true
document.body.classList.add('no-scroll') document.body.classList.add('no-scroll') //
}, },
//
closeModal () { closeModal () {
this.showModal = false this.showModal = false
document.body.classList.remove('no-scroll') document.body.classList.remove('no-scroll') //
},
//
openImageViewer (src) {
this.currentImage = src
this.showImageViewer = true
document.body.classList.add('no-scroll') //
},
//
closeImageViewer () {
this.showImageViewer = false
document.body.classList.remove('no-scroll') //
},
//
onMouseOver (event, sizeClass) {
const galleryItem = event.currentTarget
const rect = galleryItem.getBoundingClientRect()
const scrollTop = window.pageYOffset || document.documentElement.scrollTop
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft
//
const randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16)
this.pointerStyle = {
display: 'block',
top: `${rect.top + scrollTop - 85}px`,
left: `${rect.left + scrollLeft - 205}px`,
width: `${rect.width + 30}px`,
height: `${rect.height + 30}px`,
borderColor: randomColor //
}
},
//
onMouseLeave () {
this.pointerStyle.display = 'none'
} }
}, },
//
mounted () { mounted () {
this.loadImages() this.loadImages()
} }
@ -184,6 +246,7 @@ header {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
z-index: 10000; /* Ensure modal is on top */
} }
.modal-content { .modal-content {
@ -194,6 +257,7 @@ header {
width: 400px; width: 400px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
animation: fadeIn 0.3s; animation: fadeIn 0.3s;
z-index: 10001; /* Ensure modal content is on top */
} }
@keyframes fadeIn { @keyframes fadeIn {
@ -257,6 +321,12 @@ button:hover {
.gallery { .gallery {
column-count: 4; column-count: 4;
column-gap: 16px; column-gap: 16px;
position: relative;
}
.pointer {
position: absolute;
border: 2px solid;
} }
.gallery-item { .gallery-item {
@ -270,7 +340,7 @@ button:hover {
} }
.gallery-item:hover { .gallery-item:hover {
transform: translateY(-5px); transform: scale(1.05);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
} }
@ -291,4 +361,39 @@ button:hover {
.gallery-item.large img { .gallery-item.large img {
height: 250px; height: 250px;
} }
.image-viewer {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.8);
display: flex;
justify-content: center;
align-items: center;
z-index: 10000;
}
.image-viewer-content {
position: relative;
max-width: 95%;
max-height: 95%;
z-index: 10001;
}
.image-viewer img {
width: 100%;
height: auto;
display: block;
}
.image-viewer .close {
position: absolute;
top: 10px;
right: 10px;
font-size: 20px;
color: white;
cursor: pointer;
}
</style> </style>

View File

@ -9,9 +9,7 @@
</path> </path>
</svg> </svg>
<div class="ana"> <div class="ana">
<p> <p>{{ user }}</p>
{{ user }}
</p>
</div> </div>
</div> </div>
<div class="article" v-for="(item, index) in articleS" :key="index"> <div class="article" v-for="(item, index) in articleS" :key="index">
@ -27,15 +25,14 @@
</div> </div>
</div> </div>
<el-pagination <el-pagination
background background
layout="prev, pager, next" layout="prev, pager, next"
:total="total" :total="total"
style="margin: 10px auto; width: 80%; text-align: center" style="margin: 10px auto; width: 80%; text-align: center"
prev-text="上一页" prev-text="上一页"
next-text="下一页" next-text="下一页"
hide-on-single-page hide-on-single-page
/> />
<musIc /> <musIc />
</div> </div>
</template> </template>
@ -45,40 +42,66 @@ import { getSubject } from '@/api/subject'
import { fetchUser } from '@/api/dailySentence' import { fetchUser } from '@/api/dailySentence'
export default { export default {
name: 'subJect', name: 'Subject',
data () { data () {
return { return {
articleS: [], articleS: [],
total: 0, total: 0,
user: '' user: '',
lastUpdateTime: localStorage.getItem('lastUpdateTime') || null
} }
}, },
created () { created () {
this.getList() this.checkAndFetchUser() //
// this.getList() //
this.user = localStorage.getItem('userContent') || ''
// 8 // 8
setInterval(() => { const now = new Date()
this.fetchUser() const nextUpdate = new Date()
}, 1000 * 60 * 60 * 24) // 24 nextUpdate.setHours(8, 0, 0, 0) // 8
if (now > nextUpdate) {
nextUpdate.setDate(nextUpdate.getDate() + 1) // 88
}
const timeToNextUpdate = nextUpdate - now
setTimeout(() => {
this.fetchUser() //
setInterval(() => {
this.fetchUser()
}, 1000 * 60 * 60 * 24) // 24
}, timeToNextUpdate)
}, },
methods: { methods: {
getList () { getList () {
getSubject().then(res => { getSubject().then(res => {
this.articleS = res.data this.articleS = res.data
this.total = res.data.length this.total = res.data.length
}).catch(error => {
console.error('获取文章列表失败:', error)
}) })
}, },
fetchUser () { fetchUser () {
fetchUser() fetchUser()
.then(response => { .then(response => {
this.user = response.data.result.content this.user = response.data.result.content
// //
localStorage.setItem('userContent', this.user) localStorage.setItem('userContent', this.user)
localStorage.setItem('lastUpdateTime', new Date().toISOString())
}) })
.catch(error => { .catch(error => {
console.log(error) console.error('获取用户内容失败:', error)
}) })
},
checkAndFetchUser () {
const lastUpdate = new Date(this.lastUpdateTime)
const now = new Date()
const oneDay = 1000 * 60 * 60 * 24
if (!this.lastUpdateTime || (now - lastUpdate > oneDay)) {
this.fetchUser()
} else {
this.user = localStorage.getItem('userContent') || ''
}
} }
} }
} }
@ -130,10 +153,10 @@ export default {
background-color: #e5e5f7; background-color: #e5e5f7;
opacity: 0.7; opacity: 0.7;
background-image: linear-gradient(-45deg, background-image: linear-gradient(-45deg,
#e5e5f7, #e5e5f7,
#e5e5f7 50%, #e5e5f7 50%,
#d6d7e5 50%, #d6d7e5 50%,
#d6d7e5); #d6d7e5);
background-size: 8px 8px; background-size: 8px 8px;
img { img {
@ -186,7 +209,7 @@ export default {
color: rgb(143, 143, 143); color: rgb(143, 143, 143);
margin-top: 10px; margin-top: 10px;
.content{ .content {
font-size: 16px; font-size: 16px;
font-weight: 400; font-weight: 400;
font-family: Cambria, Cochin, Georgia, Times, "Times New Roman", serif; font-family: Cambria, Cochin, Georgia, Times, "Times New Roman", serif;