暂时实现功能,代码冗余

This commit is contained in:
WindowBird 2025-10-11 09:42:31 +08:00
parent 8cb632f53a
commit ae691c6db9
5 changed files with 366 additions and 73 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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
View 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
View 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>