feat(文章编辑): 添加文章简介输入框并优化样式

- 在文章编辑页面新增简介输入区域
- 移除home.vue中多余的webkit-line-clamp属性
- 统一代码格式和间距
This commit is contained in:
qingfeng1121
2025-11-14 15:42:27 +08:00
parent 1dc5bdd93f
commit 109ac3c009
2 changed files with 44 additions and 31 deletions

View File

@@ -14,7 +14,7 @@
</span> </span>
<span class="meta-item status-item"> <span class="meta-item status-item">
<i class="el-icon-document"></i> <i class="el-icon-document"></i>
<el-select v-model="Articleform.status" placeholder="请选择状态" class="meta-select"> <el-select v-model="Articleform.status" placeholder="请选择状态" class="meta-select">
<el-option v-for="item in statusoptions" :key="item.value" :label="item.label" :value="item.value"> <el-option v-for="item in statusoptions" :key="item.value" :label="item.label" :value="item.value">
</el-option> </el-option>
</el-select> </el-select>
@@ -30,11 +30,21 @@
</el-cascader> </el-cascader>
</span> </span>
</div> </div>
<div class="article-summary-section">
<!-- 文章简介 -->
<span class="meta-item summary-item">
<el-input type="textarea" :autosize="{ minRows: 2, maxRows: 4 }" placeholder="请输入简介"
v-model="Articleform.content">
</el-input>
</span>
</div>
</div> </div>
<div class="editor-container"> <div class="editor-container">
<!-- 编辑区域 --> <!-- 编辑区域 -->
<MdEditor v-model="Articleform.markdownscontent" class="markdown-editor" @on-save="handleSave" noImgZoomIn noKatex /> <MdEditor v-model="Articleform.markdownscontent" class="markdown-editor" @on-save="handleSave" noImgZoomIn
<!-- 预览 --> noKatex />
<!-- 预览 -->
</div> </div>
</div> </div>
</div> </div>
@@ -42,9 +52,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref } from 'vue'; import { reactive, ref } from 'vue';
import { MdEditor } from 'md-editor-v3'; import { MdEditor } from 'md-editor-v3';
import 'md-editor-v3/lib/style.css'; import 'md-editor-v3/lib/style.css';
import { categoryService, categoryAttributeService, articleService } from '@/services'; import { categoryService, categoryAttributeService, articleService } from '@/services';
import type { Article } from '@/types/index.ts'; import type { Article } from '@/types/index.ts';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import { useGlobalStore } from '@/store/globalStore' import { useGlobalStore } from '@/store/globalStore'
@@ -128,7 +138,7 @@ const loadCategories = async () => {
}) })
); );
categorieoptions.value = optionsData; categorieoptions.value = optionsData;
// 如果是编辑模式且有attributeid设置级联选择器的默认值 // 如果是编辑模式且有attributeid设置级联选择器的默认值
if (Articleform.value.articleid !== 0 && Articleform.value.attributeid !== 0) { if (Articleform.value.articleid !== 0 && Articleform.value.attributeid !== 0) {
// 查找属性所属的分类 // 查找属性所属的分类
@@ -141,7 +151,7 @@ const loadCategories = async () => {
} }
} }
} }
console.log('分类选项:', optionsData); console.log('分类选项:', optionsData);
console.log('选中的值:', selectedValues.value); console.log('选中的值:', selectedValues.value);
} }
@@ -165,13 +175,13 @@ loadCategories();
const handleSave = (markdown) => { const handleSave = (markdown) => {
Articleform.value.markdownscontent = markdown; Articleform.value.markdownscontent = markdown;
// 验证必填字段 // 验证必填字段
if (!Articleform.value.title || !Articleform.value.attributeid) { if (!Articleform.value.title || !Articleform.value.attributeid) {
ElMessage.warning('请填写必填字段:标题和分类属性'); ElMessage.warning('请填写必填字段:标题和分类属性');
return; return;
} }
// 构建请求数据 // 构建请求数据
const articleData = { const articleData = {
articleid: Articleform.value.articleid, articleid: Articleform.value.articleid,
@@ -183,12 +193,12 @@ const handleSave = (markdown) => {
likes: 0, likes: 0,
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
? articleService.createArticle(articleData) ? articleService.createArticle(articleData)
: articleService.updateArticle(Articleform.value.articleid, articleData); : articleService.updateArticle(Articleform.value.articleid, articleData);
savePromise savePromise
@@ -213,7 +223,7 @@ const handleSave = (markdown) => {
}; };
selectedValues.value = []; selectedValues.value = [];
} }
// 返回列表页 // 返回列表页
router.push('/home'); router.push('/home');
} else { } else {
@@ -226,9 +236,9 @@ const handleSave = (markdown) => {
if (err.response) { if (err.response) {
console.error('错误状态码:', err.response.status); console.error('错误状态码:', err.response.status);
console.error('错误响应数据:', err.response.data); console.error('错误响应数据:', err.response.data);
const operationType = Articleform.value.articleid === 0 ? '创建' : '更新'; const operationType = Articleform.value.articleid === 0 ? '创建' : '更新';
if (err.response.status === 401) { if (err.response.status === 401) {
ElMessage.error('未授权访问,请先登录'); ElMessage.error('未授权访问,请先登录');
} else if (err.response.status === 403) { } else if (err.response.status === 403) {
@@ -353,85 +363,89 @@ const handleSave = (markdown) => {
margin: 0 15px; margin: 0 15px;
border-radius: 10px; border-radius: 10px;
} }
.article-main-title { .article-main-title {
font-size: 2rem; font-size: 2rem;
line-height: 1.4; line-height: 1.4;
} }
.article-meta-info { .article-meta-info {
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
gap: 15px; gap: 15px;
} }
.meta-item { .meta-item {
justify-content: center; justify-content: center;
width: 100%; width: 100%;
} }
.meta-select, .meta-select,
.meta-cascader { .meta-cascader {
width: 100%; width: 100%;
max-width: 300px; max-width: 300px;
} }
} }
/* 文章简介区域 */
.article-summary-section {
margin-top: 30px;
padding: 0 30px 0 30px;
}
/* 响应式设计 - 手机 */ /* 响应式设计 - 手机 */
@media (max-width: 480px) { @media (max-width: 480px) {
.article-save-container { .article-save-container {
padding: 15px 0; padding: 15px 0;
} }
.article-content-wrapper { .article-content-wrapper {
padding: 20px 15px; padding: 20px 15px;
margin: 0 10px; margin: 0 10px;
border-radius: 8px; border-radius: 8px;
} }
.article-main-title { .article-main-title {
font-size: 1.75rem; font-size: 1.75rem;
line-height: 1.5; line-height: 1.5;
} }
.article-meta-info { .article-meta-info {
font-size: 0.9rem; font-size: 0.9rem;
gap: 12px; gap: 12px;
} }
.meta-select, .meta-select,
.meta-cascader { .meta-cascader {
max-width: 100%; max-width: 100%;
} }
} }
/* 深色模式支持 */ /* 深色模式支持 */
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
.article-save-container { .article-save-container {
background-color: #1a1a1a; background-color: #1a1a1a;
} }
.article-content-wrapper { .article-content-wrapper {
background-color: #2d2d2d; background-color: #2d2d2d;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
} }
.article-header-section { .article-header-section {
border-bottom-color: #444; border-bottom-color: #444;
} }
.article-main-title { .article-main-title {
color: #f0f0f0; color: #f0f0f0;
} }
.article-main-title::placeholder { .article-main-title::placeholder {
color: #666; color: #666;
} }
.article-meta-info { .article-meta-info {
color: #bbb; color: #bbb;
} }
.meta-item:hover { .meta-item:hover {
color: #4a9eff; color: #4a9eff;
} }

View File

@@ -376,7 +376,6 @@ watch(
margin: 0; margin: 0;
font-size: 0.95rem; font-size: 0.95rem;
display: -webkit-box; display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;