1
0
鏡像自 https://github.com/ialley-workshop-open/uni-halo.git 已同步 2026-06-12 13:19:31 +08:00

fix: 修复文章归档功能

此提交包含在:
小莫唐尼
2024-10-17 17:19:39 +08:00
父節點 a98254e6cc
當前提交 e28ea6ca08
共有 2 個檔案被更改,包括 1039 行新增897 行删除
+39 -37
查看文件
@@ -84,21 +84,25 @@
</template>
<script>
import {checkHasAdminLogin} from '@/utils/auth.js';
import CheckAppUpdate from '@/uni_modules/uni-upgrade-center-app/utils/check-update';
import {CheckWxUpdate} from '@/utils/update.js';
import {
checkHasAdminLogin
} from '@/utils/auth.js';
import CheckAppUpdate from '@/uni_modules/uni-upgrade-center-app/utils/check-update';
import {
CheckWxUpdate
} from '@/utils/update.js';
import tmGrouplist from '@/tm-vuetify/components/tm-grouplist/tm-grouplist.vue';
import tmListitem from '@/tm-vuetify/components/tm-listitem/tm-listitem.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmPoup from '@/tm-vuetify/components/tm-poup/tm-poup.vue';
import tmMore from '@/tm-vuetify/components/tm-more/tm-more.vue';
import tmFlop from '@/tm-vuetify/components/tm-flop/tm-flop.vue';
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
import wave from '@/components/wave/wave.vue';
import tmGrouplist from '@/tm-vuetify/components/tm-grouplist/tm-grouplist.vue';
import tmListitem from '@/tm-vuetify/components/tm-listitem/tm-listitem.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmPoup from '@/tm-vuetify/components/tm-poup/tm-poup.vue';
import tmMore from '@/tm-vuetify/components/tm-more/tm-more.vue';
import tmFlop from '@/tm-vuetify/components/tm-flop/tm-flop.vue';
import tmButton from '@/tm-vuetify/components/tm-button/tm-button.vue';
import tmIcons from '@/tm-vuetify/components/tm-icons/tm-icons.vue';
import wave from '@/components/wave/wave.vue';
export default {
export default {
components: {
tmGrouplist,
tmListitem,
@@ -186,7 +190,7 @@ export default {
path: '/pagesA/archives/archives',
isAdmin: false,
type: 'page',
show: false
show: true
}, {
key: 'love',
title: '恋爱日记',
@@ -358,8 +362,7 @@ export default {
url: '/pagesB/login/login'
});
})
.catch(err => {
});
.catch(err => {});
return;
}
@@ -380,8 +383,7 @@ export default {
this.navList.find(x => x.key == 'cache').rightText =
uni.getStorageInfoSync().currentSize + 'KB';
})
.catch(err => {
});
.catch(err => {});
break;
case 'update':
// #ifdef APP-PLUS
@@ -440,16 +442,16 @@ export default {
});
}
}
};
};
</script>
<style scoped lang="scss">
.app-page {
.app-page {
width: 100vw;
min-height: 100vh;
}
}
.blogger-info {
.blogger-info {
position: relative;
width: 100%;
height: 600rpx;
@@ -496,9 +498,9 @@ export default {
mix-blend-mode: screen;
height: 100rpx;
}
}
}
.profile-card {
.profile-card {
position: relative;
background-color: #fff;
overflow: hidden;
@@ -534,20 +536,20 @@ export default {
}
}
.photos-img + .photos-img {
.photos-img+.photos-img {
margin-left: 12rpx;
}
}
}
}
.statistics-wrap {
.statistics-wrap {
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
border-radius: 0rpx 0rpx 24rpx 24rpx;
overflow: hidden;
.statistics {
&.has-solid {
.item + .item {
.item+.item {
border-left: 2rpx solid #fafafa;
}
}
@@ -566,9 +568,9 @@ export default {
}
}
}
}
}
.quick-nav {
.quick-nav {
background-color: #fff;
box-sizing: border-box;
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
@@ -581,18 +583,18 @@ export default {
border-radius: 50%;
font-size: 80rpx;
}
}
}
.nav-wrap {
.nav-wrap {
box-shadow: 0rpx 2rpx 24rpx rgba(0, 0, 0, 0.03);
background-color: #fff;
}
}
.copyright {
.copyright {
color: #c0c4c7;
}
}
.right-value-btn {
.right-value-btn {
background-color: transparent;
border: none;
padding: 0;
@@ -607,5 +609,5 @@ export default {
border-radius: 0;
transform: initial;
}
}
}
</style>
+215 -75
查看文件
@@ -1,7 +1,8 @@
<template>
<view class="app-page">
<view class="e-fixed">
<tm-tabs color="light-blue" v-model="tab.activeIndex" :list="tab.list" align="center" @change="fnOnTabChange"></tm-tabs>
<tm-tabs color="light-blue" v-model="tab.activeIndex" :list="tab.list" align="center"
@change="fnOnTabChange"></tm-tabs>
</view>
<!-- 占位区域 -->
<view style="width: 100vw;height: 90rpx;"></view>
@@ -23,34 +24,41 @@
<view class="tm-timeline-item tm-timeline-item--leftDir">
<view style="width: 160rpx;">
<view :style="{ width: '24rpx', height: '24rpx' }" :class="[black_tmeme ? 'bk' : '']"
class="flex-center rounded tm-timeline-jidian border-white-a-2 grey-lighten-2 light-blue shadow-primary-4"></view>
class="flex-center rounded tm-timeline-jidian border-white-a-2 grey-lighten-2 light-blue shadow-primary-4">
</view>
<view :style="{ marginTop: '-24rpx' }"
:class="[index !== dataList.length - 1 ? 'tm-timeline-item-boder' : '', black_tmeme ? 'bk' : '']"
class="grey-lighten-2"></view>
</view>
<view class="tm-timeline-item-content relative">
<view class="tm-timeline-item-left">
<view class="time text-weight-b mb-24">
{{ item.year }}
<block v-if="tab.activeIndex == 0">{{ item.month }}</block>
<text class="text-size-s text-grey-darken-1 ml-24">共发布 {{ item.posts.length }} 篇文章</text>
<view class="flex time text-weight-b mb-24">
<text>{{ item.year }}</text>
<text v-if="tab.activeIndex == 0">{{ item.month }}</text>
<view class="text-size-s text-grey-darken-1 ml-12">
{{ item.posts.length }} 篇文章
</view>
</view>
<block v-if="item.posts.length != 0">
<block v-for="(post, postIndex) in item.posts" :key="post.id">
<block v-for="(post, postIndex) in item.posts" :key="post.metadata.name">
<tm-translate animation-name="fadeUp" :wait="calcAniWait(postIndex)">
<view class="flex post shadow-3 pa-24 mb-24" :class="[globalAppSettings.layout.cardType]"
<view class="flex post shadow-3 pa-24 mb-24"
:class="[globalAppSettings.layout.cardType]"
@click="fnToArticleDetail(post)">
<image class="post-thumbnail" :src="$utils.checkThumbnailUrl(post.thumbnail)"
mode="aspectFill"></image>
<image class="post-thumbnail"
:src="$utils.checkThumbnailUrl(post.spec.cover)" mode="aspectFill">
</image>
<view class="post-info pl-20">
<view class="post-info_title text-overflow">{{ post.title }}</view>
<view class="post-info_summary text-overflow-2 mt-12 text-size-s text-grey-darken-1">
{{ post.summary }}
<view class="post-info_title text-overflow">{{ post.spec.title }}
</view>
<view
class="post-info_summary text-overflow-2 mt-12 text-size-s text-grey-darken-1">
{{ post.status.excerpt }}
</view>
<view class="post-info_time mt-12 text-size-s text-grey-darken-1">
<text class="iconfont icon-clock text-size-s mr-6"></text>
<text class="time-label">发布时间</text>
{{ {d: post.createTime, f: 'yyyy年MM月dd日 星期w'} | formatTime }}
{{ {d: post.spec.publishTime, f: 'yyyy年MM月dd日 星期w'} | formatTime }}
</view>
</view>
</view>
@@ -63,20 +71,23 @@
</view>
</block>
</view>
<view class="load-text mt-12">{{ loadMoreText }}</view>
<!-- 返回顶部 -->
<tm-flotbutton @click="fnToTopPage" size="m" color="bg-gradient-light-blue-accent" icon="icon-angle-up"></tm-flotbutton>
<tm-flotbutton @click="fnToTopPage" size="m" color="bg-gradient-light-blue-accent"
icon="icon-angle-up"></tm-flotbutton>
</block>
</view>
</template>
<script>
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import tmSkeleton from '@/tm-vuetify/components/tm-skeleton/tm-skeleton.vue';
import tmTranslate from '@/tm-vuetify/components/tm-translate/tm-translate.vue';
import tmFlotbutton from '@/tm-vuetify/components/tm-flotbutton/tm-flotbutton.vue';
import tmTabs from '@/tm-vuetify/components/tm-tabs/tm-tabs.vue';
import tmEmpty from '@/tm-vuetify/components/tm-empty/tm-empty.vue';
import qs from 'qs'
export default {
export default {
components: {
tmSkeleton,
tmTranslate,
@@ -93,18 +104,20 @@ export default {
},
queryParams: {
size: 10,
page: 0
page: 1
},
result: null,
dataList: [],
api: 'getMonthArchives'
result: {},
cacheDataList: [], // 所有请求的缓存数据
dataList: [], // 显示的数据
isLoadMore: false,
loadMoreText: "加载中..."
};
},
computed: {
black_tmeme: function () {
black_tmeme: function() {
return this.$tm.vx.state().tmVuetify.black;
},
color_tmeme: function () {
color_tmeme: function() {
return this.$tm.vx.state().tmVuetify.color;
}
},
@@ -112,79 +125,203 @@ export default {
this.fnGetData();
},
onPullDownRefresh() {
this.isLoadMore = false;
this.queryParams.page = 1;
this.fnGetData();
this.queryParams.page = 0;
},
onReachBottom(e) {
if (this.result.hasNext) {
this.queryParams.page += 1;
this.isLoadMore = true;
this.fnGetData();
} else {
uni.showToast({
icon: 'none',
title: '没有更多数据了'
});
}
},
methods: {
fnOnTabChange(index) {
this.fnResetSetAniWaitIndex();
const _api = ['getMonthArchives', 'getYearArchives'];
this.api = _api[index];
this.queryParams.page = 0;
this.fnGetData();
this.dataList = this.handleGetShowDataList(this.handleGetPosts(this.cacheDataList))
},
fnGetData() {
if (this.isLoadMore) {
uni.showLoading({
title: "加载中..."
})
} else {
this.loading = 'loading';
// uni.showLoading({
// mask: true,
// title: '加载中...'
// });
this.$httpApi[this.api](this.queryParams)
.then(res => {
this.result = res.data;
this.dataList = res.data;
setTimeout(() => {
this.loadMoreText = "加载中...";
}
const paramsStr = qs.stringify(this.queryParams, {
allowDots: true,
encodeValuesOnly: true,
skipNulls: true,
encode: true,
arrayFormat: 'repeat'
})
uni.request({
url: this.$baseApiUrl + '/apis/api.content.halo.run/v1alpha1/posts?' + paramsStr,
method: 'GET',
success: (res) => {
const data = res.data;
this.result = data;
const posts = this.handleGetPosts(data.items)
const showDataList = this.handleGetShowDataList(posts)
if (this.isLoadMore) {
this.cacheDataList = this.cacheDataList.concat(data.items);
this.handleMergeDataList2(showDataList)
} else {
this.dataList = []
this.cacheDataList = data.items;
this.dataList = showDataList
}
this.loading = 'success';
}, 500);
})
.catch(err => {
console.error(err);
this.loading = 'error';
})
.finally(() => {
setTimeout(() => {
this.loadMoreText = data.hasNext ? '上拉加载更多' : '呜呜,没有更多数据啦~';
uni.hideLoading();
uni.stopPullDownRefresh();
}, 500);
});
},
//跳转文章详情
fail: (err) => {
this.loading = 'error';
this.loadMoreText = '加载失败,请下拉刷新!';
uni.$tm.toast(err.message || '数据加载失败!');
uni.hideLoading();
uni.stopPullDownRefresh();
}
})
},
// 处理数据分类
handleGetPosts(dataList) {
const posts = {}
const postLabelYearKey = "content.halo.run/archive-year"
const postLabelMonthKey = "content.halo.run/archive-month"
dataList.forEach(item => {
let postItemKey = ""
if (this.tab.activeIndex == 0) {
postItemKey =
`${item.metadata.labels[postLabelYearKey]}-${item.metadata.labels[postLabelMonthKey]}`
} else {
postItemKey = `${item.metadata.labels[postLabelYearKey]}`
}
if (posts[postItemKey]) {
posts[postItemKey].push(item)
} else {
posts[postItemKey] = [item]
}
})
return posts;
},
// 根据分类的数据,处理成显示的数据
handleGetShowDataList(posts) {
const dataListResult = []
Object.keys(posts).forEach((key) => {
const postData = {
sort: 0,
key: key,
year: key,
month: "",
posts: posts[key]
}
if (this.tab.activeIndex == 0) {
const splitDate = key.split("-")
postData.year = splitDate[0]
postData.month = splitDate[1]
postData.sort = Number(key.replace("-", ""))
} else {
postData.sort = Number(key)
}
dataListResult.push(postData)
})
if (this.tab.activeIndex == 1) {
dataListResult.sort((a, b) => {
return Number(b.year) - Number(a.year)
})
}
return dataListResult;
},
handleMergeDataList(list1, list2) {
// 将list1转换为以key为键的对象
let merged = list1.reduce((acc, item) => {
acc[item.key] = {
...item
};
return acc;
}, {});
// 遍历list2,合并posts数组或添加新对象
list2.forEach(item => {
if (merged[item.key]) {
// 如果key已存在,合并posts数组
merged[item.key].posts = [...merged[item.key].posts, ...item.posts];
} else {
// 如果key不存在,添加新对象
merged[item.key] = {
...item
};
}
});
// 将对象转换回数组
return Object.values(merged);
},
handleMergeDataList2(list) {
const tempList = [...list]
this.dataList.forEach((item, index) => {
const find = this.dataList.find(x => x.key == item.key)
if (find) {
item.posts.forEach(post => {
if (!find.posts.some(x => x.metadata.name == post.metadata.name)) {
find.posts.push(post)
}
})
tempList.splice(index, 1)
}
})
tempList.forEach(post => {
this.dataList.push(post)
})
console.log("this.dataList", this.dataList)
},
fnToArticleDetail(article) {
uni.navigateTo({
url: '/pagesA/article-detail/article-detail?articleId=' + article.id,
url: '/pagesA/article-detail/article-detail?name=' + article.metadata.name,
animationType: 'slide-in-right'
});
}
}
};
};
</script>
<style lang="scss" scoped>
.app-page {
.app-page {
width: 100vw;
min-height: 100vh;
display: flex;
flex-direction: column;
background-color: #fafafd;
}
}
.loading-wrap {
.loading-wrap {
padding: 24rpx;
}
}
.list-empty {
.list-empty {
width: 100vw;
height: 100vh;
}
}
.statistics {
.statistics {
background-color: #ffffff;
}
}
.e-timeline {
.e-timeline {
::v-deep {
.tm-timeline-item > view:first-child {
.tm-timeline-item>view:first-child {
width: 110rpx !important;
}
@@ -193,9 +330,9 @@ export default {
width: 100% !important;
}
}
}
}
.tm-timeline {
.tm-timeline {
.tm-timeline-item {
.tm-timeline-item-left,
@@ -249,15 +386,14 @@ export default {
}
}
}
}
}
.post {
.post {
width: 560rpx;
border-radius: 12rpx;
background-color: #fff;
&.lr_image_text {
}
&.lr_image_text {}
&.lr_text_image {
.post-thumbnail {
@@ -347,15 +483,15 @@ export default {
display: none;
}
}
}
}
.post-thumbnail {
.post-thumbnail {
border-radius: 6rpx;
width: 200rpx;
height: 170rpx;
}
}
.post-info {
.post-info {
width: 0;
flex-grow: 1;
@@ -375,5 +511,9 @@ export default {
display: none;
}
}
}
}
.time {
align-items: center;
}
</style>