暂时实现功能,代码冗余
This commit is contained in:
parent
8cb632f53a
commit
ae691c6db9
|
|
@ -1,21 +1,22 @@
|
|||
<script lang="ts" setup>
|
||||
import {ref, onMounted} from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { useArticleApi } from '~/composables/useArticleApi'
|
||||
|
||||
// 类型定义
|
||||
interface Article {
|
||||
id: number
|
||||
id: string
|
||||
title: string
|
||||
time: number
|
||||
brief: string | null
|
||||
content: string | null
|
||||
createTime: string
|
||||
code: string
|
||||
status: string | null
|
||||
}
|
||||
|
||||
interface NewsCategory {
|
||||
name: string
|
||||
articleList: Article[]
|
||||
}
|
||||
|
||||
interface NewsApiResponse {
|
||||
code: string
|
||||
data: NewsCategory[]
|
||||
articleList: Article[]
|
||||
}
|
||||
|
||||
// 响应式数据
|
||||
|
|
@ -23,9 +24,16 @@ const newsData = ref<NewsCategory[]>([])
|
|||
const loading = ref(false)
|
||||
const error = ref('')
|
||||
|
||||
// 计算属性 - 格式化时间
|
||||
const formatTime = (timestamp: number): string => {
|
||||
const date = new Date(timestamp * 1000)
|
||||
// 文章类型配置
|
||||
const articleTypes = [
|
||||
{ name: '解决方案', code: 'solution' },
|
||||
{ name: '开发知识', code: 'developKnowledge' },
|
||||
{ name: '行业动态', code: 'industryTrend' }
|
||||
]
|
||||
|
||||
// 格式化时间
|
||||
const formatTime = (timeString: string): string => {
|
||||
const date = new Date(timeString)
|
||||
const Y = date.getFullYear()
|
||||
const M = String(date.getMonth() + 1).padStart(2, '0')
|
||||
const D = String(date.getDate()).padStart(2, '0')
|
||||
|
|
@ -34,31 +42,47 @@ const formatTime = (timestamp: number): string => {
|
|||
return `${Y}-${M}-${D} ${h}:${m}`
|
||||
}
|
||||
|
||||
// 获取文章链接
|
||||
const getArticleLink = (articleId: string): string => {
|
||||
return `/article/${articleId}`
|
||||
}
|
||||
|
||||
// 获取显示的文章列表(每个分类显示前2篇文章)
|
||||
const getDisplayArticles = (articles: Article[]): Article[] => {
|
||||
return articles.slice(0, 2)
|
||||
}
|
||||
|
||||
// 获取新闻数据
|
||||
const fetchNewsData = async (): Promise<void> => {
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
|
||||
try {
|
||||
const response = await fetch('https://article.yuxiit.com/Home/Article/articleList.html', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: 'p1_Num=10'
|
||||
// 并发获取所有类型的文章数据
|
||||
const promises = articleTypes.map(async (type) => {
|
||||
try {
|
||||
const articles = await useArticleApi().getArticles({
|
||||
code: type.code,
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
})
|
||||
return {
|
||||
name: type.name,
|
||||
code: type.code,
|
||||
articleList: articles || []
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`Error fetching ${type.name} articles:`, err)
|
||||
return {
|
||||
name: type.name,
|
||||
code: type.code,
|
||||
articleList: []
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
|
||||
const result: NewsApiResponse = await response.json()
|
||||
|
||||
if (result.code === '10000') {
|
||||
newsData.value = result.data
|
||||
} else {
|
||||
throw new Error('API returned error code: ' + result.code)
|
||||
}
|
||||
const results = await Promise.all(promises)
|
||||
newsData.value = results.filter(category => category.articleList.length > 0)
|
||||
} catch (err) {
|
||||
error.value = err instanceof Error ? err.message : '获取新闻数据失败'
|
||||
console.error('Error fetching news data:', err)
|
||||
|
|
@ -67,16 +91,6 @@ const fetchNewsData = async (): Promise<void> => {
|
|||
}
|
||||
}
|
||||
|
||||
// 获取文章链接
|
||||
const getArticleLink = (articleId: number): string => {
|
||||
return `http://www.yuxiit.com/news/news_${articleId}.html`
|
||||
}
|
||||
|
||||
// 获取显示的文章列表(每个分类显示前2篇文章)
|
||||
const getDisplayArticles = (articles: Article[]): Article[] => {
|
||||
return articles.slice(0, 2)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchNewsData()
|
||||
})
|
||||
|
|
@ -148,7 +162,7 @@ onMounted(() => {
|
|||
:title="article.title"
|
||||
class="cGray f_14"
|
||||
target="_blank">
|
||||
<span class="pull-right">{{ formatTime(article.time) }}</span>
|
||||
<span class="pull-right">{{ formatTime(article.createTime) }}</span>
|
||||
<span class="oneIn oneIn_1">{{ article.title }}</span>
|
||||
<div class="blank20"/>
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,50 @@
|
|||
<script lang="ts" setup>
|
||||
import {onMounted, ref} from "vue";
|
||||
import {onMounted, ref, watch} from "vue";
|
||||
|
||||
// 组件属性
|
||||
interface Props {
|
||||
articleData?: {
|
||||
title: string
|
||||
publishDate: string
|
||||
category: string
|
||||
content: string
|
||||
prevArticle: {
|
||||
title: string
|
||||
url: string
|
||||
}
|
||||
nextArticle: {
|
||||
title: string
|
||||
url: string
|
||||
}
|
||||
}
|
||||
loading?: boolean
|
||||
error?: string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
articleData: () => ({
|
||||
title: '',
|
||||
publishDate: '',
|
||||
category: '',
|
||||
content: '',
|
||||
prevArticle: {
|
||||
title: '',
|
||||
url: '#'
|
||||
},
|
||||
nextArticle: {
|
||||
title: '',
|
||||
url: '#'
|
||||
}
|
||||
}),
|
||||
loading: true,
|
||||
error: ''
|
||||
})
|
||||
|
||||
// API基础地址
|
||||
const API_BASE_URL = 'http://192.168.2.26:4101'
|
||||
|
||||
// 文章数据
|
||||
const articleData = ref({
|
||||
// 内部文章数据(当没有外部传入时使用)
|
||||
const internalArticleData = ref({
|
||||
title: '',
|
||||
publishDate: '',
|
||||
category: '',
|
||||
|
|
@ -20,15 +59,20 @@ const articleData = ref({
|
|||
}
|
||||
})
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(true)
|
||||
const error = ref('')
|
||||
// 内部加载状态
|
||||
const internalLoading = ref(true)
|
||||
const internalError = ref('')
|
||||
|
||||
// 使用外部传入的数据或内部数据
|
||||
const articleData = computed(() => props.articleData || internalArticleData.value)
|
||||
const loading = computed(() => props.loading !== undefined ? props.loading : internalLoading.value)
|
||||
const error = computed(() => props.error || internalError.value)
|
||||
|
||||
// 获取文章详情
|
||||
const fetchArticle = async (id: number) => {
|
||||
try {
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
internalLoading.value = true
|
||||
internalError.value = ''
|
||||
|
||||
const response = await fetch(`${API_BASE_URL}/app/owArticle/get/${id}`)
|
||||
|
||||
|
|
@ -41,19 +85,18 @@ const fetchArticle = async (id: number) => {
|
|||
|
||||
console.log('api请求数据', data)
|
||||
|
||||
|
||||
// 分类映射配置
|
||||
const categoryMapping: Record<string, string> = {
|
||||
'solution': '解决方案',
|
||||
'developKnowledge': '开发知识',
|
||||
'industryTrend': '行业动态',
|
||||
'aboutUs': '关于我们'
|
||||
};
|
||||
}
|
||||
|
||||
data.code = categoryMapping[data.code] || '暂无分类';
|
||||
data.code = categoryMapping[data.code] || '暂无分类'
|
||||
|
||||
// 更新文章数据
|
||||
articleData.value = {
|
||||
// 更新内部文章数据
|
||||
internalArticleData.value = {
|
||||
title: data.title || '暂无标题',
|
||||
publishDate: data.createTime || '暂无日期',
|
||||
category: data.code || '暂无分类',
|
||||
|
|
@ -69,9 +112,9 @@ const fetchArticle = async (id: number) => {
|
|||
}
|
||||
} catch (err) {
|
||||
console.error('获取文章失败:', err)
|
||||
error.value = '获取文章失败,请稍后重试'
|
||||
internalError.value = '获取文章失败,请稍后重试'
|
||||
} finally {
|
||||
loading.value = false
|
||||
internalLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -87,50 +130,50 @@ const recommendedArticles = ref({
|
|||
{
|
||||
title: '创特景区SaaS平台 打造专业景区共享出行综合解决方案',
|
||||
date: '2025-07-08',
|
||||
url: 'http://www.yuxiit.com/news/news_437.html'
|
||||
url: '/article/437'
|
||||
},
|
||||
{title: '景区共享自行车运营方案都有哪些?', date: '2023-05-12', url: 'http://www.yuxiit.com/news/news_407.html'},
|
||||
{title: '景区共享自行车运营方案都有哪些?', date: '2023-05-12', url: '/article/407'},
|
||||
{
|
||||
title: '为什么说景区共享代步车的未来发展空间巨大?',
|
||||
date: '2023-05-08',
|
||||
url: 'http://www.yuxiit.com/news/news_401.html'
|
||||
url: '/article/401'
|
||||
},
|
||||
{
|
||||
title: '景区共享单车具备什么功能特点和收费标准?',
|
||||
date: '2023-04-14',
|
||||
url: 'http://www.yuxiit.com/news/news_394.html'
|
||||
url: '/article/394'
|
||||
},
|
||||
{title: '新冠疫情成为共享电单车行业新契机!', date: '2020-09-08', url: 'http://www.yuxiit.com/news/news_300.html'}
|
||||
{title: '新冠疫情成为共享电单车行业新契机!', date: '2020-09-08', url: '/article/300'}
|
||||
],
|
||||
knowledge: [
|
||||
{
|
||||
title: '共享电动车为何能在共享经济中独树一帜?',
|
||||
date: '2023-06-29',
|
||||
url: 'http://www.yuxiit.com/news/news_426.html'
|
||||
url: '/article/426'
|
||||
},
|
||||
{title: '共享经济项目为何能受到大众的青睐?', date: '2023-05-16', url: 'http://www.yuxiit.com/news/news_409.html'},
|
||||
{title: '景区共享智能代步车运营方案有哪些?', date: '2023-05-10', url: 'http://www.yuxiit.com/news/news_402.html'},
|
||||
{title: '共享经济项目为何能受到大众的青睐?', date: '2023-05-16', url: '/article/409'},
|
||||
{title: '景区共享智能代步车运营方案有哪些?', date: '2023-05-10', url: '/article/402'},
|
||||
{
|
||||
title: '创特景区共享代步车系统具备什么样的优势?',
|
||||
date: '2023-04-07',
|
||||
url: 'http://www.yuxiit.com/news/news_391.html'
|
||||
url: '/article/391'
|
||||
},
|
||||
{title: '做共享电动车能赚到钱吗', date: '2020-03-07', url: 'http://www.yuxiit.com/news/news_308.html'}
|
||||
{title: '做共享电动车能赚到钱吗', date: '2020-03-07', url: '/article/308'}
|
||||
],
|
||||
industry: [
|
||||
{
|
||||
title: '景区共享电动代步车如何引领景区发展趋势?',
|
||||
date: '2024-12-11',
|
||||
url: 'http://www.yuxiit.com/news/news_432.html'
|
||||
url: '/article/432'
|
||||
},
|
||||
{title: '景区共享电动代步车有几种合作模式?', date: '2023-07-19', url: 'http://www.yuxiit.com/news/news_431.html'},
|
||||
{title: '景区共享观光代步车为何如此火爆?', date: '2023-07-13', url: 'http://www.yuxiit.com/news/news_430.html'},
|
||||
{title: '景区共享电动代步车有几种合作模式?', date: '2023-07-19', url: '/article/431'},
|
||||
{title: '景区共享观光代步车为何如此火爆?', date: '2023-07-13', url: '/article/430'},
|
||||
{
|
||||
title: '2023年了,共享电动车项目还具备投资价值吗?',
|
||||
date: '2023-07-04',
|
||||
url: 'http://www.yuxiit.com/news/news_428.html'
|
||||
url: '/article/428'
|
||||
},
|
||||
{title: '共享电动车项目投资大吗?', date: '2023-07-03', url: 'http://www.yuxiit.com/news/news_427.html'}
|
||||
{title: '共享电动车项目投资大吗?', date: '2023-07-03', url: '/article/427'}
|
||||
]
|
||||
})
|
||||
|
||||
|
|
@ -141,8 +184,10 @@ onMounted(() => {
|
|||
// 加载JavaScript文件
|
||||
loadJSFiles()
|
||||
|
||||
// 获取文章详情,使用id=1进行测试
|
||||
fetchArticle(1)
|
||||
// 如果没有外部传入的文章数据,则获取文章详情(使用id=1进行测试)
|
||||
if (!props.articleData || !props.articleData.title) {
|
||||
fetchArticle(1)
|
||||
}
|
||||
})
|
||||
|
||||
const loadJSFiles = () => {
|
||||
|
|
@ -224,7 +269,7 @@ const loadCSSFiles = () => {
|
|||
<li class="dropdown">
|
||||
<a
|
||||
aria-expanded="false" aria-haspopup="true" class="dropdown-toggle"
|
||||
data-toggle="dropdown" href="https://www.yuxiit.com/news/news_437.html#" role="button">定制开发 <span
|
||||
data-toggle="dropdown" href="/article/437#" role="button">定制开发 <span
|
||||
class="caret"/></a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
|
|
@ -262,7 +307,7 @@ const loadCSSFiles = () => {
|
|||
<p>{{ error }}</p>
|
||||
<button
|
||||
style="margin-top: 20px; padding: 10px 20px; background: #ff8200; color: white; border: none; border-radius: 4px; cursor: pointer;"
|
||||
@click="fetchArticle(1)">
|
||||
@click="() => { if (!props.articleData || !props.articleData.title) fetchArticle(1) }">
|
||||
重新加载
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -120,3 +120,43 @@ export const ARTICLE_TYPE_MAP: Record<string, string> = {
|
|||
export const getArticleTypeName = (code: string): string => {
|
||||
return ARTICLE_TYPE_MAP[code] || '未知类型'
|
||||
}
|
||||
|
||||
/**
|
||||
* 文章API Composable
|
||||
* @returns 文章API相关方法
|
||||
*/
|
||||
export const useArticleApi = () => {
|
||||
/**
|
||||
* 获取文章列表
|
||||
* @param params 查询参数
|
||||
* @returns Promise<Article[]>
|
||||
*/
|
||||
const getArticles = async (params: ArticleListParams = {}): Promise<Article[]> => {
|
||||
try {
|
||||
const response = await fetchArticleList(params)
|
||||
return response.data || []
|
||||
} catch (error) {
|
||||
console.error('获取文章列表失败:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取推荐文章(按类型分组)
|
||||
* @param types 文章类型数组
|
||||
* @param pageSize 每页数量
|
||||
* @returns Promise<Record<string, Article[]>>
|
||||
*/
|
||||
const getRecommendedArticles = async (
|
||||
types: string[] = ['solution', 'developKnowledge', 'industryTrend'],
|
||||
pageSize: number = 5
|
||||
): Promise<Record<string, Article[]>> => {
|
||||
return await fetchRecommendedArticles(types, pageSize)
|
||||
}
|
||||
|
||||
return {
|
||||
getArticles,
|
||||
getRecommendedArticles,
|
||||
getArticleTypeName
|
||||
}
|
||||
}
|
||||
|
|
|
|||
106
app/pages/article/[id].vue
Normal file
106
app/pages/article/[id].vue
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
<script lang="ts" setup>
|
||||
// 设置页面布局
|
||||
definePageMeta({
|
||||
layout: 'no-navigation'
|
||||
})
|
||||
|
||||
// 获取路由参数
|
||||
const route = useRoute()
|
||||
const articleId = route.params.id as string
|
||||
|
||||
// 文章数据
|
||||
const articleData = ref({
|
||||
title: '',
|
||||
publishDate: '',
|
||||
category: '',
|
||||
content: '',
|
||||
prevArticle: {
|
||||
title: '',
|
||||
url: '#'
|
||||
},
|
||||
nextArticle: {
|
||||
title: '',
|
||||
url: '#'
|
||||
}
|
||||
})
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(true)
|
||||
const error = ref('')
|
||||
|
||||
// API基础地址
|
||||
const API_BASE_URL = 'http://192.168.2.26:4101'
|
||||
|
||||
// 获取文章详情
|
||||
const fetchArticle = async (id: string) => {
|
||||
try {
|
||||
loading.value = true
|
||||
error.value = ''
|
||||
|
||||
const response = await fetch(`${API_BASE_URL}/app/owArticle/get/${id}`)
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`)
|
||||
}
|
||||
|
||||
const res = await response.json()
|
||||
const data = res.data
|
||||
|
||||
console.log('api请求数据', data)
|
||||
|
||||
// 分类映射配置
|
||||
const categoryMapping: Record<string, string> = {
|
||||
'solution': '解决方案',
|
||||
'developKnowledge': '开发知识',
|
||||
'industryTrend': '行业动态',
|
||||
'aboutUs': '关于我们'
|
||||
}
|
||||
|
||||
data.code = categoryMapping[data.code] || '暂无分类'
|
||||
|
||||
// 更新文章数据
|
||||
articleData.value = {
|
||||
title: data.title || '暂无标题',
|
||||
publishDate: data.createTime || '暂无日期',
|
||||
category: data.code || '暂无分类',
|
||||
content: data.content || '暂无内容',
|
||||
prevArticle: data.prevArticle || {
|
||||
title: '暂无上一篇',
|
||||
url: '#'
|
||||
},
|
||||
nextArticle: data.nextArticle || {
|
||||
title: '暂无下一篇',
|
||||
url: '#'
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('获取文章失败:', err)
|
||||
error.value = '获取文章失败,请稍后重试'
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 组件挂载时获取文章详情
|
||||
onMounted(() => {
|
||||
if (articleId) {
|
||||
fetchArticle(articleId)
|
||||
}
|
||||
})
|
||||
|
||||
// 监听路由变化
|
||||
watch(() => route.params.id, (newId) => {
|
||||
if (newId) {
|
||||
fetchArticle(newId as string)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view>
|
||||
<NewsNew :article-data="articleData" :loading="loading" :error="error" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
88
app/pages/articles.vue
Normal file
88
app/pages/articles.vue
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
<script lang="ts" setup>
|
||||
// 设置页面布局
|
||||
definePageMeta({
|
||||
layout: 'default'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="articles-page">
|
||||
<div class="container" style="padding: 40px 0;">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<h1 class="page-title">文章中心</h1>
|
||||
<p class="page-subtitle">探索最新的技术文章和行业动态</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 推荐文章 -->
|
||||
<div class="row" style="margin-top: 40px;">
|
||||
<div class="col-xs-12">
|
||||
<RecommendedArticles
|
||||
:show-types="['solution', 'developKnowledge', 'industryTrend']"
|
||||
:articles-per-type="6"
|
||||
title="推荐文章"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 按类型分类的文章 -->
|
||||
<div class="row" style="margin-top: 60px;">
|
||||
<div class="col-xs-12 col-md-4">
|
||||
<RecommendedArticles
|
||||
:show-types="['solution']"
|
||||
:articles-per-type="8"
|
||||
title="解决方案"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-4">
|
||||
<RecommendedArticles
|
||||
:show-types="['developKnowledge']"
|
||||
:articles-per-type="8"
|
||||
title="开发知识"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-4">
|
||||
<RecommendedArticles
|
||||
:show-types="['industryTrend']"
|
||||
:articles-per-type="8"
|
||||
title="行业动态"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.articles-page {
|
||||
min-height: 100vh;
|
||||
background: #f8f9fa;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
font-size: 18px;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 768px) {
|
||||
.page-title {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue
Block a user