您的位置:首页 > 文旅 > 美景 > 工程项目信息查询_常德网站建设_企业公司网站建设_竞价托管哪家公司好

工程项目信息查询_常德网站建设_企业公司网站建设_竞价托管哪家公司好

2025/2/13 11:53:37 来源:https://blog.csdn.net/2403_88462732/article/details/145601761  浏览:    关键词:工程项目信息查询_常德网站建设_企业公司网站建设_竞价托管哪家公司好
工程项目信息查询_常德网站建设_企业公司网站建设_竞价托管哪家公司好

一、文章分类架子--PageContainer

学习PageContainer组件的封装,这一组件用于搭建页面基础结构,为后续内容展示提供统一布局。它可能包含通用的页面样式、导航栏、侧边栏等基础元素的结构搭建。

 在Vue组件中, <template> 标签内定义基础结构

<template><div class="page-container"><!-- 导航栏部分 --><div class="nav-bar">...</div><!-- 内容区域 --><div class="content-area"><!-- 这里后续会放置文章分类相关内容 --></div></div>
</template>
<script setup>
// 组件逻辑代码,可能包含数据定义、方法等
</script>
<style scoped>
.page-container {display: flex;flex-direction: column;min-height: 100vh;
}
.nav-bar {height: 60px;background-color: #333;color: white;display: flex;align-items: center;justify-content: space-between;padding: 0 20px;
}
.content-area {flex: 1;padding: 20px;
}
</style>

二、文章分类渲染

 

<template><div class="category-list"><div v-for="category in categories" :key="category.id" class="category-item">{{ category.name }}</div></div>
</template>
<script setup>
import { ref } from 'vue';
// 模拟数据,实际开发中从接口获取
const categories = ref([{ id: 1, name: '技术' },{ id: 2, name: '生活' },{ id: 3, name: '娱乐' }
]);
</script>
<style scoped>
.category-list {list-style: none;padding: 0;
}
.category-item {padding: 10px;border-bottom: 1px solid #ccc;
}
</style>

三、添加分类

(一)显示弹层封装弹层组件

 创建添加分类的弹层组件,实现点击按钮弹出弹层,用于用户输入新分类信息。包括弹层的显示隐藏逻辑、样式设计以及与父组件的交互。

弹层组件 <AddCategoryModal>

<template><div v-if="isVisible" class="add-category-modal"><div class="modal-content"><h2>添加分类</h2><input v-model="newCategoryName" placeholder="请输入分类名称"><button @click="handleAdd">添加</button><button @click="handleClose">关闭</button></div></div>
</template>
<script setup>
import { ref } from 'vue';
const isVisible = ref(false);
const newCategoryName = ref('');
const handleAdd = () => {// 这里可以添加将新分类数据发送到后端的逻辑console.log('添加分类:', newCategoryName.value);handleClose();
};
const handleClose = () => {isVisible.value = false;newCategoryName.value = '';
};
</script>
<style scoped>
.add-category-modal {position: fixed;top: 0;left: 0;width: 100vw;height: 100vh;background-color: rgba(0, 0, 0, 0.5);display: flex;align-items: center;justify-content: center;
}
.modal-content {background-color: white;padding: 20px;border-radius: 5px;box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
}
</style>

(二)添加完成

 处理添加分类的逻辑,在用户点击添加按钮后,将新分类数据发送到后端保存,并在成功后更新前端分类列表,实现数据的实时同步。

<template><!-- 同176集弹层模板,主要修改handleAdd方法 -->
</template>
<script setup>
import { ref } from 'vue';
import axios from 'axios';
const isVisible = ref(false);
const newCategoryName = ref('');
const handleAdd = async () => {try {const response = await axios.post('/api/categories', { name: newCategoryName.value });if (response.status === 200) {// 假设获取到新分类数据const newCategory = response.data;// 这里更新前端分类列表,假设在父组件中定义了categories数组// 并通过props传递到当前组件,需要更新后重新传递console.log('添加成功,新分类:', newCategory);}} catch (error) {console.error('添加分类失败:', error);}handleClose();
};
const handleClose = () => {isVisible.value = false;newCategoryName.value = '';
};
</script>

四、删除分类

 为每个分类添加删除功能,点击删除按钮后,向后端发送删除请求,并同步更新前端分类列表,确保前后端数据一致。

<template><div class="category-list"><div v-for="category in categories" :key="category.id" class="category-item">{{ category.name }}<button @click="handleDelete(category.id)">删除</button></div></div>
</template>
<script setup>
import { ref } from 'vue';
import axios from 'axios';
// 假设从父组件获取分类数据
const categories = ref([{ id: 1, name: '技术' },{ id: 2, name: '生活' },{ id: 3, name: '娱乐' }
]);
const handleDelete = async (categoryId) => {try {const response = await axios.delete(`/api/categories/${categoryId}`);if (response.status === 200) {// 更新前端分类列表,过滤掉被删除的分类categories.value = categories.value.filter(category => category.id!== categoryId);console.log('删除成功');}} catch (error) {console.error('删除分类失败:', error);}
};
</script>

五、文章管理--静态结构搭建

 

<template><div class="article - management"><h1 class="page - title">文章管理</h1><div class="article - list"></div><button class="add - article - btn">添加文章</button></div>
</template>
<style scoped>
.article - management {padding: 20px;
}
.page - title {font - size: 24px;margin - bottom: 20px;
}
.article - list {border: 1px solid #ccc;padding: 10px;min - height: 300px;
}
.add - article - btn {background - color: #007BFF;color: white;border: none;padding: 10px 20px;border - radius: 5px;margin - top: 20px;cursor: pointer;
}
</style>

六、中文国际化处理和文章分类组件封装

 使用工具(如vue - i18n)实现中文国际化,根据语言环境切换页面文字显示;封装文章分类组件,提高代码复用性,将分类展示逻辑抽离到单独组件。

<template><div><span>{{ $t('articleList') }}</span><ArticleCategory></ArticleCategory></div>
</template>
<script setup>
import { useI18n } from 'vue - i18n';
import ArticleCategory from './ArticleCategory.vue';
const { t } = useI18n();
</script>

 

<template><div class="category - list"><div v - for="category in categories" : key="category.id" class="category - item">{{ category.name }}</div></div>
</template>
<script setup>
const categories = [{ id: 1, name: '技术' },{ id: 2, name: '生活' }
];
</script>
<style scoped>
.category - list {list - style: none;padding: 0;
}
.category - item {padding: 5px 0;
}
</style>

七、文章列表

(一)封装API接口,请求渲染

1.封装文章列表数据请求的API接口,使用 axios 库发送HTTP请求获取文章数据,在组件中调用接口并将数据渲染到页面。

2.创建 api/article.js 封装接口

import axios from 'axios';
export const getArticleList = () => {return axios.get('/api/articles');
};

 

<template><div class="article - list"><div v - for="article in articles" : key="article.id" class="article - item">{{ article.title }}</div></div>
</template>
<script setup>
import { getArticleList } from '@/api/article.js';
import { ref } from 'vue';
const articles = ref([]);
const fetchArticles = async () => {try {const response = await getArticleList();articles.value = response.data;} catch (error) {console.error('获取文章列表失败', error);}
};
fetchArticles();
</script>
<style scoped>
.article - list {list - style: none;padding: 0;
}
.article - item {padding: 10px 0;border - bottom: 1px solid #ccc;
}
</style>

(二)分页渲染

 

<template><div class="article - management"><div class="article - list"><div v - for="article in articles" : key="article.id" class="article - item">{{ article.title }}</div></div><div class="pagination"><button @click="prevPage" : disabled="page === 1">上一页</button><span>{{ page }}</span><button @click="nextPage">下一页</button></div></div>
</template>
<script setup>
import { getArticleList } from '@/api/article.js';
import { ref } from 'vue';
const articles = ref([]);
const page = ref(1);
const fetchArticles = async () => {try {const response = await getArticleList(page.value);articles.value = response.data;} catch (error) {console.error('获取文章列表失败', error);}
};
const prevPage = () => {if (page.value > 1) {page.value--;fetchArticles();}
};
const nextPage = () => {page.value++;fetchArticles();
};
fetchArticles();
</script>
<style scoped>
.pagination {margin - top: 20px;
}
.pagination button {margin: 0 5px;
}
</style>

(三)添加loading和处理搜索重置

 在文章数据请求时展示loading状态,让用户知道数据正在加载;添加搜索功能和重置按钮,实现根据关键词搜索文章,重置按钮用于清空搜索条件。

<template><div class="article - management"><input v - model="searchKey" placeholder="搜索文章"><button @click="resetSearch">重置</button><div v - if="loading" class="loading">加载中...</div><div class="article - list"><div v - for="article in filteredArticles" : key="article.id" class="article - item">{{ article.title }}</div></div><div class="pagination"><button @click="prevPage" : disabled="page === 1">上一页</button><span>{{ page }}</span><button @click="nextPage">下一页</button></div></div>
</template>
<script setup>
import { getArticleList } from '@/api/article.js';
import { ref } from 'vue';
const articles = ref([]);
const filteredArticles = ref([]);
const searchKey = ref('');
const page = ref(1);
const loading = ref(false);
const fetchArticles = async () => {loading.value = true;try {const response = await getArticleList(page.value);articles.value = response.data;filteredArticles.value = articles.value.filter(article => article.title.includes(searchKey.value));} catch (error) {console.error('获取文章列表失败', error);} finally {loading.value = false;}
};
const resetSearch = () => {searchKey.value = '';fetchArticles();
};
const prevPage = () => {if (page.value > 1) {page.value--;fetchArticles();}
};
const nextPage = () => {page.value++;fetchArticles();
};
fetchArticles();
</script>
<style scoped>
.loading {text - align: center;margin - top: 20px;
}
</style>

八、文章新增

(一)准备抽屉组件--封装抽屉组件

 

<template><div v-if="isOpen" class="drawer"><div class="drawer - content"><button @click="closeDrawer">关闭</button><h2>新增文章</h2><!-- 后续添加表单内容 --></div></div>
</template>
<script setup>
import { ref } from 'vue';
const isOpen = ref(false);
const closeDrawer = () => {isOpen.value = false;
};
</script>
<style scoped>
.drawer {position: fixed;top: 0;right: 0;width: 300px;height: 100vh;background - color: #fff;box - shadow: -5px 0 10px rgba(0, 0, 0, 0.3);z - index: 1000;transition: transform 0.3s ease - in - out;transform: translateX(100%);&.open {transform: translateX(0);}
}
.drawer - content {padding: 20px;
}
</style>

(二)完善抽屉表单结构

 

<template><div v-if="isOpen" class="drawer"><div class="drawer - content"><button @click="closeDrawer">关闭</button><h2>新增文章</h2><form><label for="title">标题:</label><input type="text" id="title" v - model="article.title"><label for="category">分类:</label><select id="category" v - model="article.category"><option value="技术">技术</option><option value="生活">生活</option></select><label for="summary">摘要:</label><textarea id="summary" v - model="article.summary"></textarea></form></div></div>
</template>
<script setup>
import { ref } from 'vue';
const isOpen = ref(false);
const article = ref({title: '',category: '',summary: ''
});
const closeDrawer = () => {isOpen.value = false;
};
</script>

(三)上传文件

 借助 input 的文件选择和 FormData 对象,将文件数据发送到后端服务器。

<template><div v-if="isOpen" class="drawer"><div class="drawer - content"><button @click="closeDrawer">关闭</button><h2>新增文章</h2><form><!-- 其他表单元素 --><label for="file">上传图片:</label><input type="file" id="file" @change="handleFileUpload"></form></div></div>
</template>
<script setup>
import { ref } from 'vue';
import axios from 'axios';
const isOpen = ref(false);
const selectedFile = ref(null);
const handleFileUpload = (e) => {selectedFile.value = e.target.files[0];
};
const uploadFile = async () => {if (selectedFile.value) {const formData = new FormData();formData.append('file', selectedFile.value);try {const response = await axios.post('/api/upload', formData, {headers: {'Content - Type':'multipart/form - data'}});console.log('文件上传成功', response.data);} catch (error) {console.error('文件上传失败', error);}}
};
</script>

(四)富文本编辑器--vue-quill

 

<template><div v-if="isOpen" class="drawer"><div class="drawer - content"><button @click="closeDrawer">关闭</button><h2>新增文章</h2><form><!-- 其他表单元素 --><vue - quill - editor v - model="article.content"></vue - quill - editor></form></div></div>
</template>
<script setup>
import { ref } from 'vue';
import VueQuillEditor from 'vue - quill - editor';
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
const isOpen = ref(false);
const article = ref({title: '',category: '',summary: '',content: ''
});
const closeDrawer = () => {isOpen.value = false;
};
</script>

(五)添加文章完成

 

<template><div v-if="isOpen" class="drawer"><div class="drawer - content"><button @click="closeDrawer">关闭</button><h2>新增文章</h2><form @submit.prevent="addArticle"><!-- 表单元素和富文本编辑器 --><button type="submit">提交</button></form></div></div>
</template>
<script setup>
import { ref } from 'vue';
import axios from 'axios';
const isOpen = ref(false);
const article = ref({title: '',category: '',summary: '',content: ''
});
const closeDrawer = () => {isOpen.value = false;
};
const addArticle = async () => {try {const response = await axios.post('/api/articles', article.value);console.log('文章添加成功', response.data);closeDrawer();} catch (error) {console.error('文章添加失败', error);}
};
</script>

九、文章编辑--编辑文章完成

实现文章编辑功能,从后端获取文章原有数据填充到编辑表单和富文本编辑器中,用户修改后提交更新请求,后端更新数据。

<template><div v-if="isOpen" class="drawer"><div class="drawer - content"><button @click="closeDrawer">关闭</button><h2>编辑文章</h2><form @submit.prevent="editArticle"><!-- 表单元素和富文本编辑器,绑定文章数据 --><button type="submit">保存</button></form></div></div>
</template>
<script setup>
import { ref } from 'vue';
import axios from 'axios';
const isOpen = ref(false);
const articleId = ref(null);
const article = ref({title: '',category: '',summary: '',content: ''
});
const closeDrawer = () => {isOpen.value = false;
};
const getArticleData = async (id) => {articleId.value = id;try {const response = await axios.get(`/api/articles/${id}`);article.value = response.data;isOpen.value = true;} catch (error) {console.error('获取文章数据失败', error);}
};
const editArticle = async () => {try {const response = await axios.put(`/api/articles/${articleId.value}`, article.value);console.log('文章编辑成功', response.data);closeDrawer();} catch (error) {console.error('文章编辑失败', error);}
};
</script>

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com