今日新增修改:121

This commit is contained in:
乘风
2026-05-09 18:17:46 +08:00
parent 0cc8e2b270
commit c594bfb7e2
5 changed files with 25 additions and 181 deletions

View File

@@ -14,7 +14,8 @@
<text class="audit-banner-sub" wx:if="{{auditRejectReason}}">{{auditRejectReason}}</text>
<view wx:if="{{showAuditEdit}}" class="audit-edit-btn" bindtap="goEditArticle">重新编辑并提交</view>
</view>
<text class="title">{{article.title}}</text>
<text class="title" wx:if="{{article.title}}">{{article.title}}</text>
<text class="title title-muted" wx:else>动态</text>
<text class="meta">{{article.authorNickname || '超级个体'}} · {{article.createdAtText}}</text>
<view class="img-gallery" wx:if="{{galleryItems.length}}">

View File

@@ -40,6 +40,7 @@
background: linear-gradient(135deg, #00ced1, #20b2aa);
}
.title { font-size: 36rpx; font-weight: 700; line-height: 1.4; display: block; }
.title-muted { color: #94a3b8; font-weight: 600; }
.meta { margin-top: 12rpx; font-size: 22rpx; color: #94a3b8; display: block; }
.img-gallery {
margin-top: 20rpx;

View File

@@ -4,7 +4,6 @@
const app = getApp()
const PAGE_SIZE = 10
const THUMB_MAX = 3
function relativeTime(iso) {
if (!iso) return ''
@@ -28,65 +27,15 @@ function auditLabel(st) {
return '已发布'
}
function parseImagesField(images) {
if (images == null) return []
if (typeof images === 'string') {
const s = images.trim()
if (!s) return []
try {
const p = JSON.parse(s)
return Array.isArray(p) ? p : []
} catch (_) {
return []
}
}
return Array.isArray(images) ? images : []
}
function normalizeArticleImageSrc(raw) {
const u = String(raw || '').trim()
if (!u || u === 'undefined' || u === 'null') return ''
if (/^https?:\/\//i.test(u)) return u
if (u.startsWith('//')) return `https:${u}`
if (u.startsWith('wxfile://') || u.startsWith('cloud://')) return u
const base = String((app.globalData && app.globalData.baseUrl) || '').replace(/\/$/, '')
if (u.startsWith('/') && base) return `${base}${u}`
return u
}
function buildThumbSlots(imagesField) {
const rawList = parseImagesField(imagesField)
const n = Math.min(rawList.length, THUMB_MAX)
const thumbSlots = []
for (let i = 0; i < n; i++) {
const srcNorm = normalizeArticleImageSrc(String(rawList[i] || '').trim())
const ok =
!!srcNorm &&
(/^https?:\/\//i.test(srcNorm) ||
srcNorm.startsWith('wxfile://') ||
srcNorm.startsWith('cloud://'))
thumbSlots.push({ slotIdx: i, src: ok ? srcNorm : '', loadFailed: false })
}
return {
showThumbRow: rawList.length > 0,
thumbSlots,
thumbMoreCount: rawList.length > THUMB_MAX ? rawList.length - THUMB_MAX : 0,
}
}
function mapRows(rows) {
return (rows || []).map((r) => {
const st = String(r.auditStatus || 'approved').toLowerCase()
const thumb = buildThumbSlots(r.images)
return Object.assign({}, r, {
auditStatus: st === 'pending' || st === 'rejected' ? st : 'approved',
auditLabel: auditLabel(st),
timeText: relativeTime(r.createdAt),
preview: String(r.preview || '').trim(),
rejectReason: String(r.rejectReason || '').trim(),
showThumbRow: thumb.showThumbRow,
thumbSlots: thumb.thumbSlots,
thumbMoreCount: thumb.thumbMoreCount,
})
})
}
@@ -134,6 +83,8 @@ Page({
wx.navigateBack({ fail: () => wx.switchTab({ url: '/pages/my/my' }) })
},
noop() {},
openDetail(e) {
const id = e.currentTarget?.dataset?.id
if (!id) return
@@ -187,26 +138,6 @@ Page({
})
},
onThumbError(e) {
const rowIdx = Number(e.currentTarget.dataset.rowidx)
const slotIdx = Number(e.currentTarget.dataset.slotidx)
if (Number.isNaN(rowIdx) || Number.isNaN(slotIdx)) return
this.setData({ [`list[${rowIdx}].thumbSlots[${slotIdx}].loadFailed`]: true })
},
previewRowImages(e) {
const rowIdx = Number(e.currentTarget.dataset.rowidx)
if (Number.isNaN(rowIdx)) return
const row = this.data.list[rowIdx]
if (!row) return
const urls = parseImagesField(row.images)
.map((u) => normalizeArticleImageSrc(String(u || '').trim()))
.filter((u) => /^https?:\/\//i.test(u))
if (!urls.length) return
const current = String(e.currentTarget.dataset.current || '').trim() || urls[0]
wx.previewImage({ urls, current })
},
async reload() {
const userId = app.globalData.userInfo?.id
if (!userId || !app.globalData.isLoggedIn) {

View File

@@ -25,44 +25,18 @@
<text class="empty-sub">点击上方「发动态」写一条吧</text>
</view>
<block wx:for="{{list}}" wx:for-index="rowIdx" wx:key="id">
<view class="feed-item">
<block wx:for="{{list}}" wx:key="id">
<view class="feed-item" hover-class="feed-item-hover" bindtap="openDetail" data-id="{{item.id}}">
<view class="feed-head">
<text class="audit-tag audit-{{item.auditStatus}}">{{item.auditLabel}}</text>
<text class="feed-time">{{item.timeText}}</text>
</view>
<text class="feed-title" wx:if="{{item.title}}">{{item.title}}</text>
<text class="feed-preview">{{item.preview}}</text>
<text class="feed-title feed-title-fallback" wx:elif="{{item.preview}}">{{item.preview}}</text>
<text class="feed-title feed-title-fallback" wx:else>动态</text>
<text class="feed-teaser-hint">正文与配图请在详情页查看</text>
<view class="feed-thumb-row" wx:if="{{item.showThumbRow}}" catchtap="">
<view class="thumb-cell" wx:for="{{item.thumbSlots}}" wx:for-item="th" wx:key="slotIdx">
<block wx:if="{{th.src && !th.loadFailed}}">
<image
class="thumb-img"
mode="aspectFill"
src="{{th.src}}"
data-rowidx="{{rowIdx}}"
data-slotidx="{{index}}"
data-current="{{th.src}}"
binderror="onThumbError"
bindtap="previewRowImages"
/>
</block>
<view wx:else class="thumb-ph">
<text class="thumb-ph-text">{{th.loadFailed ? '加载失败' : '无效'}}</text>
</view>
</view>
<view wx:if="{{item.thumbMoreCount > 0}}" class="thumb-more">
<text>+{{item.thumbMoreCount}}</text>
</view>
</view>
<view class="reject-box" wx:if="{{item.auditStatus === 'rejected' && item.rejectReason}}">
<text class="reject-label">驳回说明</text>
<text class="reject-text">{{item.rejectReason}}</text>
</view>
<view class="feed-actions">
<view class="feed-btn ghost" data-id="{{item.id}}" bindtap="openDetail">查看</view>
<view class="feed-actions" catchtap="noop">
<view
wx:if="{{item.auditStatus === 'rejected' || item.auditStatus === 'pending'}}"
class="feed-btn primary"

View File

@@ -106,6 +106,10 @@
border: 1px solid rgba(34, 211, 238, 0.12);
}
.feed-item-hover {
opacity: 0.92;
}
.feed-head {
display: flex;
align-items: center;
@@ -147,85 +151,23 @@
font-weight: 600;
color: rgba(255, 255, 255, 0.92);
margin-bottom: 6px;
}
.feed-preview {
display: block;
font-size: 14px;
color: rgba(255, 255, 255, 0.55);
line-height: 1.45;
}
.feed-thumb-row {
display: flex;
flex-direction: row;
align-items: center;
flex-wrap: wrap;
gap: 8px;
margin-top: 10px;
}
.thumb-cell {
width: 72px;
height: 72px;
border-radius: 8px;
overflow: hidden;
flex-shrink: 0;
background: rgba(15, 23, 42, 0.55);
text-overflow: ellipsis;
white-space: nowrap;
}
.thumb-img {
width: 100%;
height: 100%;
.feed-title-fallback {
font-weight: 500;
color: rgba(255, 255, 255, 0.78);
}
.feed-teaser-hint {
display: block;
box-sizing: border-box;
border: 2rpx solid rgba(34, 211, 238, 0.32);
}
.thumb-ph {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
border: 1px dashed rgba(148, 163, 184, 0.35);
box-sizing: border-box;
}
.thumb-ph-text {
font-size: 10px;
color: #64748b;
transform: scale(0.92);
}
.thumb-more {
font-size: 13px;
font-weight: 600;
color: rgba(34, 211, 238, 0.88);
padding: 0 6px;
}
.reject-box {
margin-top: 10px;
padding: 10px;
border-radius: 10px;
background: rgba(248, 113, 113, 0.08);
border: 1px solid rgba(248, 113, 113, 0.22);
}
.reject-label {
display: block;
font-size: 11px;
color: #fca5a5;
font-size: 12px;
color: rgba(148, 163, 184, 0.85);
margin-bottom: 4px;
}
.reject-text {
font-size: 13px;
color: rgba(255, 255, 255, 0.72);
line-height: 1.4;
}
.feed-actions {
display: flex;
justify-content: flex-end;
@@ -239,11 +181,6 @@
border-radius: 999px;
}
.feed-btn.ghost {
color: rgba(34, 211, 238, 0.85);
border: 1px solid rgba(34, 211, 238, 0.35);
}
.feed-btn.primary {
color: #0a0a0c;
background: linear-gradient(135deg, #00ced1, #20b2aa);