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