feat: 优化前端布局和代理配置
refactor: 移除调试日志并优化代码结构 style: 调整响应式设计和UI细节 fix: 修复路由和导航相关的问题
This commit is contained in:
@@ -34,12 +34,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="bot" :class="{ 'botrelative': scrollY }">
|
<div id="bot" :class="{ 'botrelative': scrollY }">
|
||||||
<el-tabs v-model="activeName" stretch="true" class="demo-tabs">
|
<el-tabs v-model="activeName" :stretch="true" class="demo-tabs">
|
||||||
<el-tab-pane label="个人简介" name="first">
|
<el-tab-pane label="个人简介" name="first">
|
||||||
<div class="mylogo">
|
<div class="mylogo">
|
||||||
<el-avatar class="mylogo_avatar" :src="state.circleUrl" />
|
<el-avatar class="mylogo_avatar" :src="state.circleUrl" />
|
||||||
</div>
|
</div>
|
||||||
<a href="#">
|
<a href="http://www.qf1121.top/">
|
||||||
<h6 class="mylogo_name logo-text">清疯不颠</h6>
|
<h6 class="mylogo_name logo-text">清疯不颠</h6>
|
||||||
</a>
|
</a>
|
||||||
<h6 class="mylogo_description">重度精神失常患者</h6>
|
<h6 class="mylogo_description">重度精神失常患者</h6>
|
||||||
@@ -128,7 +128,7 @@ const activeIndex = ref('/:type')
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const activeName = ref('first')
|
const activeName = ref('first')
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
circleUrl: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png',
|
circleUrl: '/blogicon.jpg',
|
||||||
squareUrl: 'https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png',
|
squareUrl: 'https://cube.elemecdn.com/9/c2/f0ee8a3c7c9638a54940382568c9dpng.png',
|
||||||
sizeList: ['small', '', 'large'] as const,
|
sizeList: ['small', '', 'large'] as const,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<el-row justify="center">
|
<el-row justify="center">
|
||||||
<el-col :span="6" v-if="windowwidth">
|
<el-col :span="6" v-if="windowwidth">
|
||||||
<div class="grid-content ep-bg-purple-dark">
|
<div class="grid-content ep-bg-purple-dark">
|
||||||
<div class="logo-text"> <a href="/">清疯不颠</a></div>
|
<div class="logo-text"> <a href="http://www.qf1121.top/">清疯不颠</a></div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="14" justify="center">
|
<el-col :span="14" justify="center">
|
||||||
@@ -48,12 +48,13 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Hero 区域 -->
|
<!-- Hero 区域 -->
|
||||||
<div class="hero" :class="{ 'newhero': classhero }" v-if="windowwidth">
|
<div class="hero" :class="{ 'small-hero': classsmallhero }" v-if="windowwidth"
|
||||||
|
:style="{ marginTop: heroMarginTop, marginBottom: heroMarginBottom, transform: heroTransform, transition: 'all 0.3s ease' }">
|
||||||
<h1 class="typewriter">{{ heroText }}</h1>
|
<h1 class="typewriter">{{ heroText }}</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 提示区域 -->
|
<!-- 内容区域 -->
|
||||||
<div id="content-section" :class="{ 'visible': isconts }">
|
<div id="content-section" :class="{ 'visible': iscontentvisible }">
|
||||||
<div class="nonsensetitle" v-if="classnonsenset">
|
<div class="nonsensetitle" v-if="classnonsenset">
|
||||||
<div class="nonsensetitleconst">
|
<div class="nonsensetitleconst">
|
||||||
<h1>{{ Cardtitle }}</h1>
|
<h1>{{ Cardtitle }}</h1>
|
||||||
@@ -100,12 +101,23 @@ const Login = computed(() => globalStore.Login);
|
|||||||
const Cardtitle = ref('');
|
const Cardtitle = ref('');
|
||||||
const classmoduleorrouter = ref(false);
|
const classmoduleorrouter = ref(false);
|
||||||
const classnonsenset = ref(false);
|
const classnonsenset = ref(false);
|
||||||
const classhero = ref(false);
|
const classsmallhero = ref(false);
|
||||||
const elrowtop = ref('transparent');
|
const elrowtop = ref('transparent');
|
||||||
|
// hero区域的margin值,用于实现滚动时动态变化
|
||||||
|
const heroMarginTop = ref('45%');
|
||||||
|
const heroMarginBottom = ref('45%');
|
||||||
|
// hero区域的初始margin值,从CSS变量获取
|
||||||
|
const initialHeroMargin = 45;
|
||||||
|
// hero是否开始向上移动
|
||||||
|
const heroIsMoving = ref(false);
|
||||||
|
// hero的transform值,用于实现向上移动和吸附效果
|
||||||
|
const heroTransform = ref('translateY(0)');
|
||||||
|
// hero的位置状态:static(静态)、moving(移动中)、sticky(吸附顶部)
|
||||||
|
const heroPosition = ref('static');
|
||||||
|
|
||||||
// 布局相关状态
|
// 布局相关状态
|
||||||
const isleftmodluecontainer = ref(true);
|
const isleftmodluecontainer = ref(true);
|
||||||
const isconts = ref(false);
|
const iscontentvisible = ref(false);
|
||||||
const isScrollingleftmodlue = ref(false);
|
const isScrollingleftmodlue = ref(false);
|
||||||
const windowwidth = ref(true);
|
const windowwidth = ref(true);
|
||||||
|
|
||||||
@@ -131,20 +143,20 @@ let heroTimer: number | undefined;
|
|||||||
* 初始化并启动打字机效果
|
* 初始化并启动打字机效果
|
||||||
* @param {string} text - 要显示的完整文本
|
* @param {string} text - 要显示的完整文本
|
||||||
*/
|
*/
|
||||||
const startTypewriter = () => {
|
const startTypewriter = (text: string) => {
|
||||||
// 重置状态
|
// 重置状态
|
||||||
heroText.value = '';
|
heroText.value = '';
|
||||||
heroIndex = 0;
|
heroIndex = 0;
|
||||||
|
|
||||||
// 清除可能存在的定时器
|
// 清除可能存在的定时器
|
||||||
if (heroTimer) {
|
if (heroTimer) {
|
||||||
clearInterval(heroTimer);
|
clearInterval(heroTimer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置新的定时器,逐字显示文本
|
// 设置新的定时器,逐字显示文本
|
||||||
heroTimer = window.setInterval(() => {
|
heroTimer = window.setInterval(() => {
|
||||||
if (heroIndex < fullHeroText.length) {
|
if (heroIndex < text.length) {
|
||||||
heroText.value += fullHeroText[heroIndex];
|
heroText.value += text[heroIndex];
|
||||||
heroIndex++;
|
heroIndex++;
|
||||||
} else {
|
} else {
|
||||||
// 文本显示完毕,清除定时器
|
// 文本显示完毕,清除定时器
|
||||||
@@ -161,8 +173,13 @@ const stopTypewriter = () => {
|
|||||||
if (heroTimer) {
|
if (heroTimer) {
|
||||||
clearInterval(heroTimer);
|
clearInterval(heroTimer);
|
||||||
}
|
}
|
||||||
// 直接显示完整文本
|
// 非首页时清空hero内容
|
||||||
heroText.value = fullHeroText;
|
if (rpsliturl[1] !== localhome) {
|
||||||
|
heroText.value = '';
|
||||||
|
} else {
|
||||||
|
// 首页直接显示完整文本
|
||||||
|
heroText.value = fullHeroText;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========== 导航和路由处理模块 ==========
|
// ========== 导航和路由处理模块 ==========
|
||||||
@@ -184,12 +201,12 @@ const setActiveIndex = (path: string) => {
|
|||||||
globalStore.setValue('localpath', {
|
globalStore.setValue('localpath', {
|
||||||
name: path
|
name: path
|
||||||
});
|
});
|
||||||
|
|
||||||
// 特殊处理消息页面,清除文章信息
|
// 特殊处理消息页面,清除文章信息
|
||||||
if (path === 'message') {
|
if (path === 'message') {
|
||||||
globalStore.removeValue('articleInfo');
|
globalStore.removeValue('articleInfo');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新激活菜单项
|
// 更新激活菜单项
|
||||||
activeIndex.value = path;
|
activeIndex.value = path;
|
||||||
};
|
};
|
||||||
@@ -199,8 +216,7 @@ const setActiveIndex = (path: string) => {
|
|||||||
*/
|
*/
|
||||||
const updatePageState = () => {
|
const updatePageState = () => {
|
||||||
// 根据是否为主页根路径设置hero区域状态
|
// 根据是否为主页根路径设置hero区域状态
|
||||||
classhero.value = !(rpsliturl[1] == localhome && rpsliturl[2] == undefined);
|
classsmallhero.value = !(rpsliturl[1] == localhome && rpsliturl[2] == undefined);
|
||||||
|
|
||||||
// 控制左侧模块容器的显示/隐藏
|
// 控制左侧模块容器的显示/隐藏
|
||||||
isleftmodluecontainer.value = rpsliturl[1] !== "articlesave";
|
isleftmodluecontainer.value = rpsliturl[1] !== "articlesave";
|
||||||
};
|
};
|
||||||
@@ -216,7 +232,7 @@ const updateArticleTitle = () => {
|
|||||||
// 按属性类型获取
|
// 按属性类型获取
|
||||||
articledata = globalStore.getValue('attribute')?.name;
|
articledata = globalStore.getValue('attribute')?.name;
|
||||||
console.log('attributeId参数:', articledata);
|
console.log('attributeId参数:', articledata);
|
||||||
}
|
}
|
||||||
else if (rpsliturl[2] === 'aericletitle') {
|
else if (rpsliturl[2] === 'aericletitle') {
|
||||||
// 按标题搜索获取
|
// 按标题搜索获取
|
||||||
articledata = globalStore.getValue('title')?.name;
|
articledata = globalStore.getValue('title')?.name;
|
||||||
@@ -227,18 +243,18 @@ const updateArticleTitle = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 确定标题区域的显示状态
|
// 确定标题区域的显示状态
|
||||||
const shouldHideTitle =
|
const shouldHideTitle =
|
||||||
// 特殊页面不需要显示标题
|
// 特殊页面不需要显示标题
|
||||||
(rpsliturl[1] === 'article-list' ||
|
(rpsliturl[1] === 'article-list' ||
|
||||||
rpsliturl[1] === 'message' ||
|
rpsliturl[1] === 'message' ||
|
||||||
rpsliturl[1] === 'about') ||
|
rpsliturl[1] === 'about') ||
|
||||||
// 在主页且无标题数据时,不显示标题
|
// 在主页且无标题数据时,不显示标题
|
||||||
(rpsliturl[1] === localhome && !articledata);
|
(rpsliturl[1] === localhome && !articledata);
|
||||||
|
|
||||||
// 更新标题显示状态
|
// 更新标题显示状态
|
||||||
classnonsenset.value = !shouldHideTitle && !!articledata;
|
classnonsenset.value = !shouldHideTitle && !!articledata;
|
||||||
classmoduleorrouter.value = !shouldHideTitle && !!articledata;
|
classmoduleorrouter.value = !shouldHideTitle && !!articledata;
|
||||||
|
|
||||||
// 设置标题内容
|
// 设置标题内容
|
||||||
if (articledata) {
|
if (articledata) {
|
||||||
Cardtitle.value = articledata;
|
Cardtitle.value = articledata;
|
||||||
@@ -293,7 +309,7 @@ const performSearch = () => {
|
|||||||
globalStore.setValue('articleserarch', {
|
globalStore.setValue('articleserarch', {
|
||||||
name: searchKeyword.value
|
name: searchKeyword.value
|
||||||
});
|
});
|
||||||
|
|
||||||
// 跳转到搜索结果页面
|
// 跳转到搜索结果页面
|
||||||
router.push({ path: `/home/aericletitle` });
|
router.push({ path: `/home/aericletitle` });
|
||||||
}
|
}
|
||||||
@@ -316,7 +332,7 @@ const handleResize = () => {
|
|||||||
|
|
||||||
// 首页特殊处理:小屏幕下默认显示内容区
|
// 首页特殊处理:小屏幕下默认显示内容区
|
||||||
if (rpsliturl[1] === localhome) {
|
if (rpsliturl[1] === localhome) {
|
||||||
isconts.value = window.innerWidth <= 768;
|
iscontentvisible.value = window.innerWidth <= 768;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -333,13 +349,53 @@ const handleScroll = () => {
|
|||||||
|
|
||||||
// 大屏幕设备完整处理
|
// 大屏幕设备完整处理
|
||||||
updateNavbarStyle(window.scrollY);
|
updateNavbarStyle(window.scrollY);
|
||||||
|
|
||||||
// 仅在首页根路径应用滚动动画
|
// 仅在首页根路径应用滚动动画
|
||||||
if (rpsliturl[1] === localhome && rpsliturl[2] == undefined) {
|
if (rpsliturl[1] === localhome && rpsliturl[2] == undefined) {
|
||||||
// 控制内容区和左侧模块的滚动状态
|
const scrollY = window.scrollY;
|
||||||
isconts.value = window.scrollY > 200;
|
const windowHeight = window.innerHeight;
|
||||||
isScrollingleftmodlue.value = window.scrollY > 600;
|
|
||||||
|
// 计算滚动距离与窗口高度的比例,用于内容渐显
|
||||||
|
const contentScrollRatio = Math.min(scrollY / windowHeight, 1);
|
||||||
|
// 计算新的底部margin值,从初始值45%逐渐减少到25%
|
||||||
|
const newMarginBottom = Math.max(initialHeroMargin - (initialHeroMargin * contentScrollRatio), 0);
|
||||||
|
// 更新hero的底部margin值
|
||||||
|
heroMarginBottom.value = `${newMarginBottom}%`;
|
||||||
|
// 顶部margin保持不变
|
||||||
|
heroMarginTop.value = `${initialHeroMargin}%`;
|
||||||
|
|
||||||
|
// 内容区域随滚动逐渐显现
|
||||||
|
// 当滚动超过50px时开始显示,滚动到一屏高度时完全显示
|
||||||
|
iscontentvisible.value = scrollY > 50;
|
||||||
|
|
||||||
|
// 计算hero的移动阶段
|
||||||
|
if (scrollY >= 555) {
|
||||||
|
// 滚动超过555px,标题开始向上移动
|
||||||
|
heroIsMoving.value = true;
|
||||||
|
heroPosition.value = 'moving';
|
||||||
|
|
||||||
|
// 计算移动距离:从0到初始marginTop值(45%)
|
||||||
|
// 使用滚动距离减去起始位置(555px),除以移动范围(500px),得到移动比例
|
||||||
|
const moveScrollRatio = Math.min((scrollY - 555) / 500, 1);
|
||||||
|
const moveDistance = initialHeroMargin * moveScrollRatio;
|
||||||
|
heroTransform.value = `translateY(-${moveDistance*10}%)`;
|
||||||
|
|
||||||
|
// 当移动距离达到初始marginTop值时,吸附到顶部
|
||||||
|
if (moveScrollRatio >= 1) {
|
||||||
|
heroPosition.value = 'sticky';
|
||||||
|
heroTransform.value = `translateY(-${initialHeroMargin*10}%)`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 滚动未超过555px,标题保持静态
|
||||||
|
heroIsMoving.value = false;
|
||||||
|
heroPosition.value = 'static';
|
||||||
|
heroTransform.value = 'translateY(0)';
|
||||||
|
}
|
||||||
|
|
||||||
|
// 控制左侧模块的滚动状态
|
||||||
|
isScrollingleftmodlue.value = scrollY > 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -376,12 +432,26 @@ const handleRouteChange = () => {
|
|||||||
// 根据是否为首页决定是否启动打字机效果
|
// 根据是否为首页决定是否启动打字机效果
|
||||||
if (rpsliturl[1] === localhome && rpsliturl[2] == undefined) {
|
if (rpsliturl[1] === localhome && rpsliturl[2] == undefined) {
|
||||||
// 首页启动打字机效果
|
// 首页启动打字机效果
|
||||||
startTypewriter();
|
startTypewriter(fullHeroText);
|
||||||
|
// 重置hero的margin值为初始值
|
||||||
|
heroMarginBottom.value = `${initialHeroMargin}%`;
|
||||||
|
heroMarginTop.value = `${initialHeroMargin}%`;
|
||||||
|
// 重置hero的移动状态
|
||||||
|
heroIsMoving.value = false;
|
||||||
|
heroPosition.value = 'static';
|
||||||
|
heroTransform.value = 'translateY(0)';
|
||||||
|
// 移动端首页默认显示内容区,桌面端初始隐藏
|
||||||
|
iscontentvisible.value = window.innerWidth <= 768;
|
||||||
} else {
|
} else {
|
||||||
// 非首页直接显示完整文本
|
// 非首页直接显示完整文本
|
||||||
isconts.value = true;
|
iscontentvisible.value = true;
|
||||||
stopTypewriter();
|
stopTypewriter();
|
||||||
}
|
}
|
||||||
|
// 不在首页时,hero的margin为0
|
||||||
|
if (rpsliturl[1] !== localhome) {
|
||||||
|
heroMarginBottom.value = '0%';
|
||||||
|
heroMarginTop.value = '0%';
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -392,7 +462,20 @@ const initializePage = () => {
|
|||||||
handleResize();
|
handleResize();
|
||||||
// 启动打字机效果(如果是首页)
|
// 启动打字机效果(如果是首页)
|
||||||
if (rpsliturl[1] === localhome && rpsliturl[2] == undefined) {
|
if (rpsliturl[1] === localhome && rpsliturl[2] == undefined) {
|
||||||
startTypewriter();
|
// 首页启动打字机效果
|
||||||
|
startTypewriter(fullHeroText);
|
||||||
|
// 重置hero的margin值为初始值
|
||||||
|
heroMarginBottom.value = `${initialHeroMargin}%`;
|
||||||
|
heroMarginTop.value = `${initialHeroMargin}%`;
|
||||||
|
// 重置hero的移动状态
|
||||||
|
heroIsMoving.value = false;
|
||||||
|
heroPosition.value = 'static';
|
||||||
|
heroTransform.value = 'translateY(0)';
|
||||||
|
// 移动端首页默认显示内容区,桌面端初始隐藏
|
||||||
|
iscontentvisible.value = window.innerWidth <= 768;
|
||||||
|
} else {
|
||||||
|
// 非首页清空hero内容
|
||||||
|
heroText.value = '';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -404,7 +487,7 @@ const initializePage = () => {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 初始化页面
|
// 初始化页面
|
||||||
initializePage();
|
initializePage();
|
||||||
|
|
||||||
// 添加事件监听器
|
// 添加事件监听器
|
||||||
window.addEventListener('resize', handleResize);
|
window.addEventListener('resize', handleResize);
|
||||||
window.addEventListener('scroll', handleScroll);
|
window.addEventListener('scroll', handleScroll);
|
||||||
@@ -514,9 +597,11 @@ watch(
|
|||||||
.close-btn:hover {
|
.close-btn:hover {
|
||||||
color: #409eff;
|
color: #409eff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-container {
|
.footer-container {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 防止搜索框在小屏幕上重叠 */
|
/* 防止搜索框在小屏幕上重叠 */
|
||||||
@media screen and (max-width: 1200px) {
|
@media screen and (max-width: 1200px) {
|
||||||
.search-box-container.open {
|
.search-box-container.open {
|
||||||
|
|||||||
@@ -1,41 +1,43 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="establish-container">
|
<div class="establish-component-root">
|
||||||
<!-- 弹出的按钮容器 -->
|
<div class="establish-container">
|
||||||
<!-- <div class="expanded-buttons" :class="{ 'show': isExpanded }"> -->
|
<!-- 弹出的按钮容器 -->
|
||||||
<button v-for="(btn, index) in isbuttonsave()" :class="['action-button', { 'show': isExpanded }]"
|
<!-- <div class="expanded-buttons" :class="{ 'show': isExpanded }"> -->
|
||||||
:style="getButtonStyle(index)" :key="btn.id" @click="handleButtonClick(btn)">
|
<button v-for="(btn, index) in isbuttonsave()" :class="['action-button', { 'show': isExpanded }]"
|
||||||
<!-- <i :class="btn.icon"></i> -->
|
:style="getButtonStyle(index)" :key="btn.id" @click="handleButtonClick(btn)">
|
||||||
<span>{{ btn.label }}</span>
|
<!-- <i :class="btn.icon"></i> -->
|
||||||
</button>
|
<span>{{ btn.label }}</span>
|
||||||
<!-- </div> -->
|
</button>
|
||||||
|
<!-- </div> -->
|
||||||
|
|
||||||
<!-- 主圆形按钮 -->
|
<!-- 主圆形按钮 -->
|
||||||
<button class="main-button" :class="{ 'active': isExpanded }" @click="toggleExpand">
|
<button class="main-button" :class="{ 'active': isExpanded }" @click="toggleExpand">
|
||||||
<i class="icon">+</i>
|
<i class="icon">+</i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<!-- 标签蒙板组件 -->
|
<!-- 标签蒙板组件 -->
|
||||||
<Transition name="modal">
|
<Transition name="modal">
|
||||||
<div v-if="showAttributeModal" class="category-modal" @click.self="closeAttributeModal">
|
<div v-if="showAttributeModal" class="category-modal" @click.self="closeAttributeModal">
|
||||||
<div class="category-modal-content">
|
<div class="category-modal-content">
|
||||||
<div class="category-modal-header">
|
<div class="category-modal-header">
|
||||||
<h3>新建标签</h3>
|
<h3>新建标签</h3>
|
||||||
<button class="category-modal-close" @click="closeAttributeModal">×</button>
|
<button class="category-modal-close" @click="closeAttributeModal">×</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="category-modal-body">
|
<div class="category-modal-body">
|
||||||
|
|
||||||
<el-select v-model="CategoryAttributeDto.categoryid" placeholder="请选择">
|
<el-select v-model="CategoryAttributeDto.categoryid" placeholder="请选择">
|
||||||
<el-option v-for="item in categories" :key="item.value" :label="item.label" :value="item.value">
|
<el-option v-for="item in categories" :key="item.value" :label="item.label" :value="item.value">
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
|
|
||||||
<el-input v-model="CategoryAttributeDto.name" placeholder="输入新标签" />
|
<el-input v-model="CategoryAttributeDto.name" placeholder="输入新标签" />
|
||||||
<el-button type="primary"
|
<el-button type="primary"
|
||||||
@click="saveAttribute(CategoryAttributeDto)">保存</el-button>
|
@click="saveAttribute(CategoryAttributeDto)">保存</el-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Transition>
|
||||||
</Transition>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -335,14 +337,14 @@ const createCategory = () => {
|
|||||||
* @param {string} typename - 分类名称
|
* @param {string} typename - 分类名称
|
||||||
*/
|
*/
|
||||||
const saveCategory = (typename) => {
|
const saveCategory = (typename) => {
|
||||||
console.log('保存分类')
|
// console.log('保存分类')
|
||||||
categoryService.createCategory({
|
categoryService.createCategory({
|
||||||
typename: typename
|
typename: typename
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
ElMessage.success('分类创建成功');
|
ElMessage.success('分类创建成功');
|
||||||
// 刷新页面
|
// 刷新页面
|
||||||
router.push({ path: `/aericlelist`});
|
router.push({ path: `/articlelist`});
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(response.message || '创建分类失败');
|
ElMessage.error(response.message || '创建分类失败');
|
||||||
}
|
}
|
||||||
@@ -365,7 +367,7 @@ const createAttribute = async () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleErrorResponse(error, '获取分类失败');
|
handleErrorResponse(error, '获取分类失败');
|
||||||
} finally {
|
} finally {
|
||||||
console.log(categories.value)
|
// console.log(categories.value)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -387,7 +389,7 @@ const saveAttribute = (dto) => {
|
|||||||
closeAttributeModal()
|
closeAttributeModal()
|
||||||
ElMessage.success('标签创建成功');
|
ElMessage.success('标签创建成功');
|
||||||
// 刷新页面
|
// 刷新页面
|
||||||
router.push({ path: `/aericlelist`});
|
router.push({ path: `/articlelist`});
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(response.message || '创建标签失败');
|
ElMessage.error(response.message || '创建标签失败');
|
||||||
}
|
}
|
||||||
@@ -488,7 +490,7 @@ const reloadPage = () => {
|
|||||||
* @param {{id: string, label: string, icon: string}} button - 按钮对象
|
* @param {{id: string, label: string, icon: string}} button - 按钮对象
|
||||||
*/
|
*/
|
||||||
const handleButtonClick = (button) => {
|
const handleButtonClick = (button) => {
|
||||||
console.log('点击了按钮:', button.id, button.label)
|
// console.log('点击了按钮:', button.id, button.label)
|
||||||
|
|
||||||
// 使用按钮ID进行处理,更可靠且易于维护
|
// 使用按钮ID进行处理,更可靠且易于维护
|
||||||
switch (button.id) {
|
switch (button.id) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { ElMessage } from 'element-plus'
|
|||||||
|
|
||||||
// 创建axios实例
|
// 创建axios实例
|
||||||
const api = axios.create({
|
const api = axios.create({
|
||||||
baseURL: 'http://www.qf1121.top/api', // API基础URL
|
baseURL: '/api', // API基础URL,使用相对路径,通过Vite代理转发
|
||||||
timeout: 10000, // 请求超时时间
|
timeout: 10000, // 请求超时时间
|
||||||
withCredentials: true // 允许跨域请求携带凭证(如cookies)
|
withCredentials: true // 允许跨域请求携带凭证(如cookies)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -17,12 +17,14 @@
|
|||||||
/* 内容区圆角 */
|
/* 内容区圆角 */
|
||||||
|
|
||||||
/* 首页 hero 区域高度和间距 */
|
/* 首页 hero 区域高度和间距 */
|
||||||
--hero-height: 768px;
|
--hero-height: 100px;
|
||||||
/* hero 默认高度 */
|
/* hero 默认高度 */
|
||||||
--hero-height-small: 100px;
|
--hero-height-small: 100px;
|
||||||
/* hero 收缩后高度 */
|
/* hero 收缩后高度 */
|
||||||
/* --hero-margin-top: 2%; */
|
--hero-margin: 45% 0;
|
||||||
/* hero 顶部外边距 */
|
/* hero 顶边距 */
|
||||||
|
--hero-min-margin-top: 45%;
|
||||||
|
/* hero 最小顶边距 */
|
||||||
|
|
||||||
/* 标题样式 */
|
/* 标题样式 */
|
||||||
--title-font-size: 3.5rem;
|
--title-font-size: 3.5rem;
|
||||||
@@ -368,18 +370,21 @@ p {
|
|||||||
/* 首页 hero 区域样式 */
|
/* 首页 hero 区域样式 */
|
||||||
.hero {
|
.hero {
|
||||||
height: var(--hero-height);
|
height: var(--hero-height);
|
||||||
|
margin: var(--hero-margin);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: white;
|
color: white;
|
||||||
transition: height 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 999;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hero 收缩状态 */
|
/* hero 收缩状态 */
|
||||||
.hero.newhero {
|
.hero.small-hero {
|
||||||
height: var(--hero-height-small);
|
height: var(--hero-height-small);
|
||||||
margin-top: 10%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 打字机效果 */
|
/* 打字机效果 */
|
||||||
@@ -387,6 +392,10 @@ p {
|
|||||||
white-space: pre;
|
white-space: pre;
|
||||||
min-height: 2.5em;
|
min-height: 2.5em;
|
||||||
font-size: var(--title-font-size, 2rem);
|
font-size: var(--title-font-size, 2rem);
|
||||||
|
/* 水平居中 */
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes blink {
|
@keyframes blink {
|
||||||
@@ -445,8 +454,7 @@ p {
|
|||||||
--nonsense-title-margin-bottom: 15px;
|
--nonsense-title-margin-bottom: 15px;
|
||||||
--nav-padding-small: 0 8px;
|
--nav-padding-small: 0 8px;
|
||||||
--nonsenset-margin-top: 10px;
|
--nonsenset-margin-top: 10px;
|
||||||
--body-background-img: url();
|
--body-background-img: url(../img/bg.jpg);
|
||||||
/* 移动端不显示背景图片 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.elrow-top {
|
.elrow-top {
|
||||||
@@ -505,4 +513,24 @@ p {
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* 移动端适配:屏幕宽度小于820px时生效 */
|
||||||
|
@media (max-width: 820px) {
|
||||||
|
:root {
|
||||||
|
--nav-padding: 0;
|
||||||
|
--hero-height:300px;
|
||||||
|
}
|
||||||
|
.RouterViewpage {
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
.hero {
|
||||||
|
margin-top: 50%;
|
||||||
|
}
|
||||||
|
.el-col-14 {
|
||||||
|
flex: 0 0 0;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
.elrow-top {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<div class="about-content-wrapper">
|
<div class="about-content-wrapper">
|
||||||
<!-- 页面头部 -->
|
<!-- 页面头部 -->
|
||||||
<div class="about-page-header">
|
<div class="about-page-header">
|
||||||
<h1 class="about-page-title">关于</h1>
|
<h3 class="about-page-title">关于</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 关于内容 -->
|
<!-- 关于内容 -->
|
||||||
@@ -281,14 +281,19 @@ const goToMessageBoard = () => {
|
|||||||
.about-page-container {
|
.about-page-container {
|
||||||
padding: 20px 0;
|
padding: 20px 0;
|
||||||
}
|
}
|
||||||
|
.about-page-header{
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
.about-content-wrapper {
|
.about-content-wrapper {
|
||||||
|
width: 100%;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
margin: 0 15px;
|
margin: 0 5%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.about-page-title {
|
.about-page-title {
|
||||||
font-size: 1.8rem;
|
font-size: 1.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.about-page-subtitle {
|
.about-page-subtitle {
|
||||||
@@ -306,7 +311,6 @@ const goToMessageBoard = () => {
|
|||||||
.contact-options {
|
.contact-options {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.skills-display-list {
|
.skills-display-list {
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ const fetchCategories = async () => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
categories.value = processedCategories;
|
categories.value = processedCategories;
|
||||||
console.log('获取分类列表成功:', categories.value);
|
// console.log('获取分类列表成功:', categories.value);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('获取分类列表失败:', err);
|
console.error('获取分类列表失败:', err);
|
||||||
ElMessage.error('获取分类列表失败,请稍后重试');
|
ElMessage.error('获取分类列表失败,请稍后重试');
|
||||||
@@ -118,7 +118,7 @@ const handleCategoryClick = (attribute: any) => {
|
|||||||
id: attribute.attributeid,
|
id: attribute.attributeid,
|
||||||
name: attribute.typename
|
name: attribute.typename
|
||||||
})
|
})
|
||||||
console.log(attribute)
|
// console.log(attribute)
|
||||||
router.push({
|
router.push({
|
||||||
path: '/home/aericletype',
|
path: '/home/aericletype',
|
||||||
|
|
||||||
@@ -385,6 +385,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
.article-content {
|
.article-content {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
height: 600px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.category-group-container {
|
.category-group-container {
|
||||||
|
|||||||
@@ -154,8 +154,8 @@ const loadCategories = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('分类选项:', optionsData);
|
// console.log('分类选项:', optionsData);
|
||||||
console.log('选中的值:', selectedValues.value);
|
// console.log('选中的值:', selectedValues.value);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载分类失败:', error);
|
console.error('加载分类失败:', error);
|
||||||
@@ -196,8 +196,8 @@ const handleSave = (markdown) => {
|
|||||||
markdownscontent: Articleform.value.markdownscontent
|
markdownscontent: Articleform.value.markdownscontent
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('发送文章数据:', articleData);
|
// console.log('发送文章数据:', articleData);
|
||||||
console.log('当前认证token是否存在:', !!localStorage.getItem('token'));
|
// console.log('当前认证token是否存在:', !!localStorage.getItem('token'));
|
||||||
|
|
||||||
// 根据articleid决定调用创建还是更新接口
|
// 根据articleid决定调用创建还是更新接口
|
||||||
const savePromise = Articleform.value.articleid === 0
|
const savePromise = Articleform.value.articleid === 0
|
||||||
@@ -205,7 +205,7 @@ const handleSave = (markdown) => {
|
|||||||
: articleService.updateArticle(Articleform.value.articleid, articleData);
|
: articleService.updateArticle(Articleform.value.articleid, articleData);
|
||||||
savePromise
|
savePromise
|
||||||
.then(res => {
|
.then(res => {
|
||||||
console.log('API响应:', res);
|
// console.log('API响应:', res);
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
ElMessage.success(Articleform.value.articleid === 0 ? '文章创建成功' : '文章更新成功');
|
ElMessage.success(Articleform.value.articleid === 0 ? '文章创建成功' : '文章更新成功');
|
||||||
// 清除全局存储中的article
|
// 清除全局存储中的article
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 分页区域 -->
|
<!-- 分页区域 -->
|
||||||
<PaginationComponent class="pagination-container" :list="articleList" :pageSize="10" @changePage="handleCurrentDataUpdate" />
|
<PaginationComponent class="pagination-container" :list="articleList" :pageSize="10" @changePage="handleCurrentDataUpdate" :key="'pagination'" />
|
||||||
</transition-group>
|
</transition-group>
|
||||||
<!-- 空状态 -->
|
<!-- 空状态 -->
|
||||||
<div v-if="!loading && articleList.length === 0" class="empty-state-container">
|
<div v-if="!loading && articleList.length === 0" class="empty-state-container">
|
||||||
@@ -69,7 +69,7 @@ const loading = ref(false)
|
|||||||
*/
|
*/
|
||||||
const handleCurrentDataUpdate = (data) => {
|
const handleCurrentDataUpdate = (data) => {
|
||||||
displayedArticles.value = data
|
displayedArticles.value = data
|
||||||
console.log('更新后的当前页数据:', data)
|
// console.log('更新后的当前页数据:', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 文章数据获取模块 ==========
|
// ========== 文章数据获取模块 ==========
|
||||||
@@ -81,7 +81,7 @@ const handleCurrentDataUpdate = (data) => {
|
|||||||
const getArticlesByRoute = async () => {
|
const getArticlesByRoute = async () => {
|
||||||
// 检查URL参数,确定获取文章的方式
|
// 检查URL参数,确定获取文章的方式
|
||||||
const pathSegment = route.path.split('/')[2]
|
const pathSegment = route.path.split('/')[2]
|
||||||
console.log('当前路由分段:', pathSegment)
|
// console.log('当前路由分段:', pathSegment)
|
||||||
|
|
||||||
switch (pathSegment) {
|
switch (pathSegment) {
|
||||||
case 'aericletype':
|
case 'aericletype':
|
||||||
@@ -98,7 +98,7 @@ const getArticlesByRoute = async () => {
|
|||||||
return await articleService.getArticlesByStatus(statusData?.status)
|
return await articleService.getArticlesByStatus(statusData?.status)
|
||||||
default:
|
default:
|
||||||
// 默认获取所有文章
|
// 默认获取所有文章
|
||||||
console.log('获取所有文章列表')
|
// console.log('获取所有文章列表')
|
||||||
return await articleService.getAllArticles()
|
return await articleService.getAllArticles()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,7 +189,7 @@ const fetchArticles = async () => {
|
|||||||
console.error('获取文章列表失败:', error)
|
console.error('获取文章列表失败:', error)
|
||||||
ElMessage.error('获取文章列表失败,请稍后重试')
|
ElMessage.error('获取文章列表失败,请稍后重试')
|
||||||
} finally {
|
} finally {
|
||||||
console.log('最终文章列表数据:', articleList.value)
|
// console.log('最终文章列表数据:', articleList.value)
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,7 +230,7 @@ const handleArticleClick = (article) => {
|
|||||||
*/
|
*/
|
||||||
const handleRouteChange = () => {
|
const handleRouteChange = () => {
|
||||||
fetchArticles()
|
fetchArticles()
|
||||||
console.log('路由变化,重新获取文章列表')
|
// console.log('路由变化,重新获取文章列表')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -414,7 +414,6 @@ watch(
|
|||||||
/* 响应式设计 - 平板和手机 */
|
/* 响应式设计 - 平板和手机 */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.article-list-container {
|
.article-list-container {
|
||||||
padding: 0 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.article-card {
|
.article-card {
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ const togglePassword = () => {
|
|||||||
|
|
||||||
// 验证单个字段
|
// 验证单个字段
|
||||||
const validateField = (field) => {
|
const validateField = (field) => {
|
||||||
console.log('validateField', field)
|
// console.log('validateField', field)
|
||||||
errors.value = {}
|
errors.value = {}
|
||||||
|
|
||||||
if (field === 'username' && !loginForm.username) {
|
if (field === 'username' && !loginForm.username) {
|
||||||
@@ -150,7 +150,7 @@ const handleLogin = async () => {
|
|||||||
ElMessage.error('登录失败,请检查用户名和密码')
|
ElMessage.error('登录失败,请检查用户名和密码')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
console.log('登录成功', user)
|
// console.log('登录成功', user)
|
||||||
// 这里应该是实际的登录API调用
|
// 这里应该是实际的登录API调用
|
||||||
// console.log('登录请求数据:', loginForm)
|
// console.log('登录请求数据:', loginForm)
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ const handleLogin = async () => {
|
|||||||
globalStore.setValue('loginhomestatus', {
|
globalStore.setValue('loginhomestatus', {
|
||||||
status: 1 // 2:删除 1:已发布 0:发布登录
|
status: 1 // 2:删除 1:已发布 0:发布登录
|
||||||
})
|
})
|
||||||
console.log('globalStore.Login', globalStore.Login)
|
// console.log('globalStore.Login', globalStore.Login)
|
||||||
// 保存登录状态token
|
// 保存登录状态token
|
||||||
if (user.token) {
|
if (user.token) {
|
||||||
localStorage.setItem('token', user.token)
|
localStorage.setItem('token', user.token)
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="comment-content-text" v-html="comment.content"></div>
|
<div class="comment-content-text" v-html="comment.content"></div>
|
||||||
<div class="comment-actions-bar">
|
<div class="comment-actions-bar">
|
||||||
<span class="like-button" @click="handleLike(comment)">
|
<span class="like-button" v-if="false" @click="handleLike(comment)">
|
||||||
<span v-if="comment.likes && comment.likes > 0" class="like-count">{{ comment.likes
|
<span v-if="comment.likes && comment.likes > 0" class="like-count">{{ comment.likes
|
||||||
}}</span>
|
}}</span>
|
||||||
👍 赞
|
👍 赞
|
||||||
@@ -55,7 +55,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="reply-content-text">{{ reply.content }}</div>
|
<div class="reply-content-text">{{ reply.content }}</div>
|
||||||
<div class="reply-actions-bar">
|
<div class="reply-actions-bar">
|
||||||
<span class="like-button" @click="handleLike(reply)">
|
|
||||||
|
<span class="like-button" v-if="false" @click="handleLike(reply)">
|
||||||
<span v-if="reply.likes && reply.likes > 0" class="like-count">{{ reply.likes
|
<span v-if="reply.likes && reply.likes > 0" class="like-count">{{ reply.likes
|
||||||
}}</span>
|
}}</span>
|
||||||
👍 赞
|
👍 赞
|
||||||
@@ -111,8 +112,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-input-row">
|
<div class="form-input-row">
|
||||||
<el-form-item>
|
<el-form-item class="submit-button-container">
|
||||||
<el-button type="primary" @click="onSubmit" :loading="submitting"
|
<el-button type="primary" @click="onSubmit" class="form-submit-button" :loading="submitting"
|
||||||
:disabled="!form.content || !form.nickname">
|
:disabled="!form.content || !form.nickname">
|
||||||
发送
|
发送
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -600,7 +601,7 @@ const onSubmit = async () => {
|
|||||||
try {
|
try {
|
||||||
// 表单验证
|
// 表单验证
|
||||||
await validateForm()
|
await validateForm()
|
||||||
console.log('提交留言表单:', form)
|
// console.log('提交留言表单:', form)
|
||||||
|
|
||||||
submitting.value = true
|
submitting.value = true
|
||||||
|
|
||||||
@@ -902,16 +903,24 @@ onMounted(() => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 内联表单输入行样式
|
* 内联表单输入行样式
|
||||||
* 用于将表单输入项与标签或其他元素对齐
|
* 用于将表单输入项水平均匀分布
|
||||||
*/
|
*/
|
||||||
.form-input-row--inline {
|
.form-input-row--inline {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-input-row--inline div:nth-child(2) {
|
.form-input-row--inline .el-form-item {
|
||||||
margin-left: 9%;
|
flex: 1;
|
||||||
margin-right: 9%;
|
margin-right: 0;
|
||||||
|
margin-left: 0;
|
||||||
|
width: calc(33.33% - 10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-input-row--inline .el-input {
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 回复项容器 */
|
/* 回复项容器 */
|
||||||
@@ -1055,18 +1064,20 @@ onMounted(() => {
|
|||||||
.comment-form-section {
|
.comment-form-section {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
.el-form-item {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
.form-input-row {
|
.form-input-row {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.comment-header-info,
|
.comment-header-info,
|
||||||
.reply-header-info {
|
.reply-header-info {
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
.form-submit-button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
.user-avatar {
|
.user-avatar {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
|
|||||||
@@ -1,6 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="nonsense-container">
|
<div class="nonsense-container">
|
||||||
<div class="nonsense-list">
|
<div class="nonsense-list">
|
||||||
|
<!-- 加载状态 -->
|
||||||
|
<div v-if="loading" class="loading-state-container">
|
||||||
|
<el-skeleton :count="5" />
|
||||||
|
</div>
|
||||||
|
<!-- 错误状态 -->
|
||||||
|
<div v-if="error" class="error-state-container">
|
||||||
|
<div>加载失败,请稍后重试</div>
|
||||||
|
<el-button type="primary" @click="handleRetry">重试</el-button>
|
||||||
|
</div>
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<div v-if="displayedNonsenseList.length === 0" class="empty-state-container">
|
||||||
|
<div>暂无吐槽内容</div>
|
||||||
|
</div>
|
||||||
<div class="nonsense-item" v-for="item in displayedNonsenseList" :key="item.id">
|
<div class="nonsense-item" v-for="item in displayedNonsenseList" :key="item.id">
|
||||||
<div class="nonsense-meta-info">
|
<div class="nonsense-meta-info">
|
||||||
<span class="nonsense-time">{{ formatRelativeTime(item.time) }}</span>
|
<span class="nonsense-time">{{ formatRelativeTime(item.time) }}</span>
|
||||||
@@ -44,10 +57,21 @@ const charRefs = ref(new Map())
|
|||||||
const charStyles = ref(new Map())
|
const charStyles = ref(new Map())
|
||||||
// 显示的吐槽内容列表
|
// 显示的吐槽内容列表
|
||||||
const displayedNonsenseList = ref([])
|
const displayedNonsenseList = ref([])
|
||||||
|
// 加载状态
|
||||||
|
const loading = ref(false)
|
||||||
|
// 错误状态
|
||||||
|
const error = ref(false)
|
||||||
|
|
||||||
// 处理分页数据更新
|
// 处理分页数据更新
|
||||||
const handleCurrentDataUpdate = (data) => {
|
const handleCurrentDataUpdate = (data) => {
|
||||||
displayedNonsenseList.value = data
|
displayedNonsenseList.value = data
|
||||||
console.log(data)
|
// console.log(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重试加载
|
||||||
|
const handleRetry = () => {
|
||||||
|
error.value = false
|
||||||
|
loadNonsenseList()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定时器引用
|
// 定时器引用
|
||||||
@@ -57,17 +81,24 @@ let colorChangeTimer = null
|
|||||||
* 加载所有吐槽内容
|
* 加载所有吐槽内容
|
||||||
*/
|
*/
|
||||||
const loadNonsenseList = async () => {
|
const loadNonsenseList = async () => {
|
||||||
|
// 设置加载状态
|
||||||
|
loading.value = true
|
||||||
|
error.value = false
|
||||||
try {
|
try {
|
||||||
const response = await nonsenseService.getNonsenseByStatus(1)
|
const response = await nonsenseService.getNonsenseByStatus(1)
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
nonsenseList.value = response.data
|
nonsenseList.value = response.data
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error('加载吐槽内容失败')
|
ElMessage.error('加载吐槽内容失败')
|
||||||
|
error.value = true
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (err) {
|
||||||
console.error('加载吐槽内容失败:', error)
|
console.error('加载吐槽内容失败:', err)
|
||||||
|
error.value = true
|
||||||
} finally {
|
} finally {
|
||||||
console.log('加载吐槽内容完成')
|
// 结束加载状态
|
||||||
|
loading.value = false
|
||||||
|
// console.log('加载吐槽内容完成')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 编辑吐槽内容
|
// 编辑吐槽内容
|
||||||
@@ -357,8 +388,7 @@ onBeforeUnmount(() => {
|
|||||||
/* 响应式设计 */
|
/* 响应式设计 */
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.nonsense-container {
|
.nonsense-container {
|
||||||
padding: 14px 4px 10px 4px;
|
margin: 0;
|
||||||
margin: 0 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.nonsense-header h1 {
|
.nonsense-header h1 {
|
||||||
@@ -370,9 +400,9 @@ onBeforeUnmount(() => {
|
|||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nonsense-list {
|
/* .nonsense-list {
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
} */
|
||||||
|
|
||||||
.nonsense-item {
|
.nonsense-item {
|
||||||
padding: 14px 16px 10px 16px;
|
padding: 14px 16px 10px 16px;
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ const totalPages = computed(() => {
|
|||||||
if (!props.list || props.list.length === 0) return 0
|
if (!props.list || props.list.length === 0) return 0
|
||||||
// 如果列表长度小于pageSize,不进行分组,返回0表示不分页
|
// 如果列表长度小于pageSize,不进行分组,返回0表示不分页
|
||||||
if (props.list.length <= props.pageSize) return 0
|
if (props.list.length <= props.pageSize) return 0
|
||||||
console.log(props.list.length, props.pageSize)
|
// console.log(props.list.length, props.pageSize)
|
||||||
|
|
||||||
// 列表长度小于等于pageSize时,正常计算页数
|
// 列表长度小于等于pageSize时,正常计算页数
|
||||||
// 如果能整除,直接返回商
|
// 如果能整除,直接返回商
|
||||||
|
|||||||
@@ -26,7 +26,15 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
host: '0.0.0.0'
|
host: '0.0.0.0',
|
||||||
|
proxy: {
|
||||||
|
// 配置API代理
|
||||||
|
'/api': {
|
||||||
|
target: 'http://localhost:7071',
|
||||||
|
changeOrigin: true,
|
||||||
|
rewrite: (path) => path
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user