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 name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<title>墨思留痕</title>
</head>
<body>
<noscript>

View File

@ -1,6 +1,6 @@
<template>
<div id="app">
<main>
<main>
<router-view />
<trigger></trigger>
</main>
@ -13,8 +13,13 @@
<script>
import trigger from '@/components/trigger.vue'
import basePage from './components/base.vue'
export default {
export default {
data () {
return {
}
},
components: {
trigger,
basePage
@ -23,22 +28,5 @@ export default {
</script>
<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>

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
})
}
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;
margin: 0;
list-style: none;
}
* {
padding: 0;
margin: 0;
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]
}
},
mounted () {
// localStorage
const savedLockState = localStorage.getItem('isLocked')
if (savedLockState !== null) {
this.isLocked = JSON.parse(savedLockState)
}
},
methods: {
searchMusic () {
//
@ -93,8 +100,7 @@ export default {
},
prevSong () {
this.currentSongIndex =
(this.currentSongIndex - 1 + this.playlist.length) %
this.playlist.length
(this.currentSongIndex - 1 + this.playlist.length) % this.playlist.length
this.isPlaying = true //
},
nextSong () {
@ -104,6 +110,8 @@ export default {
},
toggleLock () {
this.isLocked = !this.isLocked
// localStorage
localStorage.setItem('isLocked', JSON.stringify(this.isLocked))
}
}
}

View File

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

View File

View File

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

View File

@ -1,4 +1,6 @@
import axios from 'axios'
import { Message } from 'element-ui'
import router from '../router'
// 创建一个 axios 实例
const service = axios.create({
@ -9,27 +11,29 @@ const service = axios.create({
// 请求拦截器
service.interceptors.request.use(
config => {
// 从 localStorage 中获取 token
const token = localStorage.getItem('user-token')
const token = localStorage.getItem('token')
if (token) {
// 将 token 添加到请求头中
config.headers.Authorization = `Bearer ${token}`
}
return config
},
error => {
// 对请求错误做些什么
return Promise.reject(error)
}
)
// 响应拦截器
service.interceptors.response.use(
response => {
// 对响应数据做点什么
return response
},
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)
}
)

View File

@ -3,7 +3,6 @@
<navigationBar />
<div class="box">
<el-tabs type="border-card">
<el-tab-pane label="个人信息">
<div class="AboutUs-left">
<div class="AboutUs-img">
@ -117,8 +116,27 @@
</div>
</div>
</el-tab-pane>
</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>
<musIc />
@ -139,6 +157,8 @@ export default {
birthday: '',
region: '',
city: '',
dialogVisible: false,
imageUrl: '',
avatar: require('@/assets/images/789.jpg'), //
users: [
{
@ -163,10 +183,6 @@ export default {
//
this.$message.success('保存成功')
},
changeAvatar () {
//
this.$message.success('更换成功')
},
//
handleAdd () {
if (this.newTodo.trim() !== '') {
@ -190,6 +206,32 @@ export default {
} else {
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>
.wtbDone {
width: 400px;
width: 700px;
height: 500px;
border: 1px solid black;
margin: auto;
@ -207,7 +249,7 @@ export default {
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
input {
width: 300px;
width: 550px;
height: 40px;
padding: 5px;
margin-top: 20px;
@ -219,61 +261,61 @@ export default {
border: 1px solid #007bff;
}
}
}
}
ul {
list-style: none;
padding: 0;
width: 350px;
height: 310px;
margin: 20px auto;
overflow-y: scroll;
border: 1px solid #ddd;
border-radius: 4px;
ul {
list-style: none;
padding: 0;
width: 600px;
height: 310px;
margin: 20px auto;
overflow-y: scroll;
border: 1px solid #ddd;
border-radius: 4px;
li {
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;
li {
width: 100%;
height: 40px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 4px;
margin-left: 5px;
line-height: 40px;
text-align: center;
background-color: #f5f5f5;
border-bottom: 1px solid #ddd;
cursor: pointer;
transition: background-color 0.3s;
&: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 {
background-color: #f5f5f5;
@ -445,4 +487,28 @@ hr {
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>

View File

@ -17,65 +17,23 @@
</template>
<script>
import { interList } from '@/api/interlinkage'
export default {
name: 'interLinkage',
data () {
return {
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'
}
]
contentList: []
}
},
created () {
this.getList()
},
methods: {
getList () {
interList().then(res => {
this.contentList = res.data
})
},
goLink (url) {
window.open(url)
}

View File

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

View File

@ -35,7 +35,7 @@
</div>
<div class="tool">
<div>
<el-checkbox v-model="checked" @change="remenber" v-if="!create"
<el-checkbox v-model="checked" @change="remember" v-if="!create"
>记住密码</el-checkbox
>
</div>
@ -56,7 +56,7 @@
</template>
<script>
import { login } from '@/api/login' //
import { login, autoLogin } from '@/api/login'
import dayjs from 'dayjs'
export default {
@ -91,33 +91,110 @@ export default {
setInterval(() => {
this.postDate = dayjs().format('HH : mm : ss')
}, 1000)
this.loadRememberedCredentials()
//
const token = localStorage.getItem('token')
if (token) {
this.autoLogin(token)
}
},
methods: {
login () {
//
login(this.form).then(response => {
//
console.log(response) //
this.$router.push('/')
loadRememberedCredentials () {
const rememberedUsername = localStorage.getItem('rememberedUsername')
const rememberedPassword = localStorage.getItem('rememberedPassword')
const rememberMeChecked = localStorage.getItem('rememberMeChecked')
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({
message: '登陆成功',
message: '自动登录成功',
type: 'success'
})
}).catch(error => {
//
console.error('登录失败:', error)
console.error('自动登录失败:', error)
localStorage.removeItem('token')
this.$message({
message: '登录失败,请检查账号或密码',
message: '自动登录失败,请重新登录',
type: 'error'
})
})
},
remenber (data) {
this.checked = data
if (this.checked) {
localStorage.setItem('news', JSON.stringify(this.form))
login () {
if (this.form.username === '' || this.form.password === '') {
this.$message({
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 {
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 () {
@ -128,22 +205,19 @@ export default {
},
register () {
if (this.create) {
window.location.reload()
} else if (
this.form.username ||
this.form.password ||
this.form.repassword
) {
//
//
this.create = false
this.loadRememberedCredentials()
} else {
//
this.create = true
this.form.username = ''
this.form.password = ''
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); /* 上部阴影 */
width: 400px;
height: 300px;
height: 350px;
padding: 30px;
border-radius: 10px;
transform: translate(-50%);

View File

@ -23,16 +23,26 @@
</div>
</div>
<div class="gallery">
<div class="pointer" :style="pointerStyle"></div>
<div
class="gallery-item"
v-for="(item, index) in photos"
:key="index"
:class="item.sizeClass"
@mouseover="onMouseOver($event, item.sizeClass)"
@mouseleave="onMouseLeave"
@click="openImageViewer(item.src)"
ref="photoItems"
>
<img :data-src="item.src" :alt="item.alt" class="lazy" />
</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 />
</div>
</template>
@ -42,6 +52,7 @@ export default {
name: 'photoGallery',
data () {
return {
//
photos: [
{ src: require('@/assets/images/789.jpg'), alt: 'Photo 1', sizeClass: 'medium' },
{ 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' }
],
newPhoto: {
src: '',
alt: ''
src: '', // URL
alt: '' //
},
newPhotoFile: null,
showModal: false
newPhotoFile: null, //
showModal: false, //
showImageViewer: false, //
currentImage: '', // URL
pointerStyle: {
display: 'none', //
top: '0px',
left: '0px',
width: '0px',
height: '0px',
borderColor: '' //
}
}
},
methods: {
//
loadImages () {
const images = this.$refs.photoItems
const images = this.$refs.photoItems //
const options = {
root: null,
rootMargin: '0px',
threshold: 0.1
threshold: 0.1 //
}
// IntersectionObserver
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target.querySelector('img')
img.src = img.getAttribute('data-src')
observer.unobserve(entry.target)
img.src = img.getAttribute('data-src') //
observer.unobserve(entry.target) //
}
})
}, options)
images.forEach(image => {
observer.observe(image)
observer.observe(image) //
})
},
//
onFileChange (e) {
const file = e.target.files[0]
if (file) {
this.newPhotoFile = URL.createObjectURL(file)
this.newPhotoFile = URL.createObjectURL(file) // URL
}
},
//
addPhoto () {
if (this.newPhotoFile && this.newPhoto.alt) {
const sizeClasses = ['small', 'medium', 'large']
@ -117,24 +142,61 @@ export default {
alt: this.newPhoto.alt,
sizeClass: sizeClass
})
this.newPhotoFile = null
this.newPhoto.alt = ''
this.showModal = false
document.body.classList.remove('no-scroll')
this.newPhotoFile = null //
this.newPhoto.alt = '' //
this.showModal = false //
document.body.classList.remove('no-scroll') //
this.$nextTick(() => {
this.loadImages()
this.loadImages() //
})
}
},
//
openModal () {
this.showModal = true
document.body.classList.add('no-scroll')
document.body.classList.add('no-scroll') //
},
//
closeModal () {
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 () {
this.loadImages()
}
@ -184,6 +246,7 @@ header {
display: flex;
justify-content: center;
align-items: center;
z-index: 10000; /* Ensure modal is on top */
}
.modal-content {
@ -194,6 +257,7 @@ header {
width: 400px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
animation: fadeIn 0.3s;
z-index: 10001; /* Ensure modal content is on top */
}
@keyframes fadeIn {
@ -257,6 +321,12 @@ button:hover {
.gallery {
column-count: 4;
column-gap: 16px;
position: relative;
}
.pointer {
position: absolute;
border: 2px solid;
}
.gallery-item {
@ -270,7 +340,7 @@ button:hover {
}
.gallery-item:hover {
transform: translateY(-5px);
transform: scale(1.05);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
@ -291,4 +361,39 @@ button:hover {
.gallery-item.large img {
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>

View File

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