|
|
@@ -0,0 +1,156 @@
|
|
|
+<template>
|
|
|
+ <view class="posts-container">
|
|
|
+ <scroll-view scroll-y class="posts-list" @scrolltolower="onLoadMore">
|
|
|
+ <view v-if="loading && posts.length === 0" class="loading-wrap">
|
|
|
+ <text class="loading-text">加载中...</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view v-else-if="posts.length === 0" class="empty-wrap">
|
|
|
+ <text class="empty-icon">📝</text>
|
|
|
+ <text class="empty-text">还没有发布过记录</text>
|
|
|
+ <button class="write-btn" @click="goEdit">写一篇</button>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view v-else class="post-list">
|
|
|
+ <view v-for="item in posts" :key="item.id" class="post-card">
|
|
|
+ <image
|
|
|
+ v-if="item.coverImage"
|
|
|
+ class="post-cover"
|
|
|
+ :src="item.coverImage"
|
|
|
+ mode="aspectFill"
|
|
|
+ />
|
|
|
+ <view class="post-body">
|
|
|
+ <text class="post-title">{{ item.title }}</text>
|
|
|
+ <view class="post-meta">
|
|
|
+ <text class="post-date">{{ formatDate(item.publishedAt || item.createdAt) }}</text>
|
|
|
+ <text
|
|
|
+ :class="['post-status', getStatusClass(item)]"
|
|
|
+ >
|
|
|
+ {{ getStatusText(item) }}
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ <text v-if="item.auditStatus === 'rejected' && item.auditReason" class="post-reason">
|
|
|
+ 驳回原因:{{ item.auditReason }}
|
|
|
+ </text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view v-if="loadingMore" class="loading-more">
|
|
|
+ <text class="loading-text">加载中...</text>
|
|
|
+ </view>
|
|
|
+ <view v-if="noMore && posts.length > 0" class="no-more">
|
|
|
+ <text class="no-more-text">— 没有更多了 —</text>
|
|
|
+ </view>
|
|
|
+ </scroll-view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { getMyPosts } from '@/utils/api.js'
|
|
|
+
|
|
|
+export default {
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ posts: [],
|
|
|
+ page: 1,
|
|
|
+ size: 20,
|
|
|
+ total: 0,
|
|
|
+ loading: false,
|
|
|
+ loadingMore: false,
|
|
|
+ noMore: false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLoad() {
|
|
|
+ this.loadPosts()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ async loadPosts(isLoadMore) {
|
|
|
+ if (!isLoadMore) {
|
|
|
+ if (this.loading) return
|
|
|
+ this.loading = true
|
|
|
+ } else {
|
|
|
+ if (this.loadingMore || this.noMore) return
|
|
|
+ this.loadingMore = true
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ var res = await getMyPosts({ page: this.page, size: this.size })
|
|
|
+ if (res.code === 200 && res.data) {
|
|
|
+ var list = res.data.records || []
|
|
|
+ if (this.page === 1) {
|
|
|
+ this.posts = list
|
|
|
+ } else {
|
|
|
+ this.posts = this.posts.concat(list)
|
|
|
+ }
|
|
|
+ this.total = res.data.total || 0
|
|
|
+ this.noMore = this.posts.length >= this.total
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ uni.showToast({ title: '加载失败', icon: 'none' })
|
|
|
+ } finally {
|
|
|
+ this.loading = false
|
|
|
+ this.loadingMore = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLoadMore() {
|
|
|
+ if (this.noMore || this.loading || this.loadingMore) return
|
|
|
+ this.page++
|
|
|
+ this.loadPosts(true)
|
|
|
+ },
|
|
|
+ goEdit() {
|
|
|
+ uni.navigateTo({ url: '/pages/article-center/article-edit' })
|
|
|
+ },
|
|
|
+ formatDate(dateStr) {
|
|
|
+ if (!dateStr) return ''
|
|
|
+ return dateStr.slice(0, 10)
|
|
|
+ },
|
|
|
+ getStatusText(item) {
|
|
|
+ if (item.status === 'draft' && (!item.auditStatus || item.auditStatus === 'pending')) {
|
|
|
+ return '审核中'
|
|
|
+ }
|
|
|
+ if (item.auditStatus === 'rejected') return '已驳回'
|
|
|
+ if (item.status === 'published') return '已发布'
|
|
|
+ return '草稿'
|
|
|
+ },
|
|
|
+ getStatusClass(item) {
|
|
|
+ if (item.auditStatus === 'approved' || item.status === 'published') return 'status-approved'
|
|
|
+ if (item.auditStatus === 'pending') return 'status-pending'
|
|
|
+ if (item.auditStatus === 'rejected') return 'status-rejected'
|
|
|
+ return 'status-draft'
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.posts-container { min-height: 100vh; background: #f5f7fa; }
|
|
|
+.posts-list { height: 100vh; }
|
|
|
+.loading-wrap, .empty-wrap { display: flex; flex-direction: column; align-items: center; padding-top: 200rpx; }
|
|
|
+.loading-text { font-size: 26rpx; color: #999; }
|
|
|
+.empty-icon { font-size: 100rpx; margin-bottom: 24rpx; }
|
|
|
+.empty-text { font-size: 28rpx; color: #999; margin-bottom: 30rpx; }
|
|
|
+.write-btn { width: 240rpx; height: 72rpx; line-height: 72rpx; background: #5B9BD5; color: #fff; font-size: 28rpx; border-radius: 36rpx; border: none; }
|
|
|
+.write-btn::after { border: none; }
|
|
|
+.post-list { padding: 20rpx 24rpx; }
|
|
|
+.post-card {
|
|
|
+ display: flex;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 16rpx;
|
|
|
+ overflow: hidden;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04);
|
|
|
+}
|
|
|
+.post-cover { width: 200rpx; height: 160rpx; flex-shrink: 0; }
|
|
|
+.post-body { flex: 1; padding: 20rpx; display: flex; flex-direction: column; justify-content: center; }
|
|
|
+.post-title { font-size: 28rpx; font-weight: bold; color: #333; line-height: 1.4; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-bottom: 8rpx; }
|
|
|
+.post-meta { display: flex; align-items: center; font-size: 22rpx; }
|
|
|
+.post-date { color: #999; margin-right: 16rpx; }
|
|
|
+.post-status { padding: 2rpx 12rpx; border-radius: 8rpx; }
|
|
|
+.status-approved { color: #22c55e; background: rgba(34,197,94,0.1); }
|
|
|
+.status-pending { color: #f59e0b; background: rgba(245,158,11,0.1); }
|
|
|
+.status-rejected { color: #ef4444; background: rgba(239,68,68,0.1); }
|
|
|
+.status-draft { color: #999; background: rgba(153,153,153,0.1); }
|
|
|
+.post-reason { font-size: 20rpx; color: #ef4444; margin-top: 6rpx; display: block; }
|
|
|
+.loading-more, .no-more { text-align: center; padding: 30rpx; }
|
|
|
+.no-more-text { font-size: 24rpx; color: #ccc; }
|
|
|
+</style>
|