feat: 市场调研落地——趋势AI人话解读(plainExplain/takeAway,采集自动生成+SSR+小程序卡)+ 首页今日知识卡
This commit is contained in:
@@ -82,6 +82,20 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 今日知识卡:每天一条,读了答对就点亮 -->
|
||||
<view class="kcard" v-if="todayKnowledge" @tap="goTodayKnowledge">
|
||||
<view class="kcard-head">
|
||||
<AppIcon name="book" :size="14" />
|
||||
<text class="kcard-label">今日知识卡</text>
|
||||
<text class="kcard-dim">{{ todayDimName }}</text>
|
||||
</view>
|
||||
<text class="kcard-title">{{ todayKnowledge.title }}</text>
|
||||
<text class="kcard-desc">{{ todayKnowledge.content }}</text>
|
||||
<view class="kcard-foot">
|
||||
<text class="kcard-cta">去读一读 · 答对点亮 →</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 今日快讯 -->
|
||||
<view class="section-header">
|
||||
<text class="section-title">今日快讯</text>
|
||||
@@ -114,6 +128,18 @@ const dimensions = ref(DIMENSIONS)
|
||||
|
||||
const newsList = ref([])
|
||||
const byDim = ref({}) // 各星域知识总数
|
||||
const todayKnowledge = ref<any>(null)
|
||||
|
||||
const todayDimName = computed(() => {
|
||||
const d = DIMENSIONS.find(x => x.id === todayKnowledge.value?.dim)
|
||||
return d ? d.name : ''
|
||||
})
|
||||
|
||||
function goTodayKnowledge() {
|
||||
if (todayKnowledge.value?._id) {
|
||||
uni.navigateTo({ url: `/pages/detail/detail?id=${todayKnowledge.value._id}` })
|
||||
}
|
||||
}
|
||||
const userStats = ref(null) // { totalLit, litByDim, streak }
|
||||
const lastRead = ref(null)
|
||||
|
||||
@@ -128,9 +154,21 @@ const todayLit = computed(() => !!uni.getStorageSync('lit_today'))
|
||||
onShow(() => {
|
||||
loadStats()
|
||||
loadNews()
|
||||
loadTodayKnowledge()
|
||||
lastRead.value = uni.getStorageSync('last_read') || null
|
||||
})
|
||||
|
||||
// 今日知识卡:按日期取当日第 N 条(同一天所有人看到同一条,形成"每日一词"共识感)
|
||||
async function loadTodayKnowledge() {
|
||||
try {
|
||||
const data = await knowledgeApi.list({ limit: 50, page: 1 })
|
||||
const items = (data.items || []).filter((x) => x.content)
|
||||
if (!items.length) return
|
||||
const dayIndex = Math.floor(Date.now() / 86400000)
|
||||
todayKnowledge.value = items[dayIndex % items.length]
|
||||
} catch (e) { /* 静默 */ }
|
||||
}
|
||||
|
||||
onPullDownRefresh(async () => {
|
||||
await Promise.all([loadStats(), loadNews()])
|
||||
uni.stopPullDownRefresh()
|
||||
@@ -468,3 +506,42 @@ onShareTimeline(() => ({
|
||||
|
||||
.bottom-spacer { height: 30px; }
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
.kcard {
|
||||
background: linear-gradient(135deg, rgba(91, 95, 248, 0.08), rgba(139, 92, 246, 0.05));
|
||||
border: 1px solid var(--glass-hover-border);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 14px 16px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.kcard-head { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; }
|
||||
.kcard-label { font-size: 12px; font-weight: 700; color: var(--color-brand); }
|
||||
.kcard-dim {
|
||||
margin-left: auto;
|
||||
font-size: 10px;
|
||||
color: var(--text-tertiary);
|
||||
background: var(--glass-bg);
|
||||
border-radius: 999px;
|
||||
padding: 2px 8px;
|
||||
}
|
||||
.kcard-title {
|
||||
display: block;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
color: var(--text-primary);
|
||||
line-height: 1.5;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.kcard-desc {
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
color: var(--text-tertiary);
|
||||
line-height: 1.6;
|
||||
}
|
||||
.kcard-foot { margin-top: 8px; }
|
||||
.kcard-cta { font-size: 11px; font-weight: 600; color: var(--color-brand); }
|
||||
</style>
|
||||
|
||||
@@ -41,6 +41,18 @@
|
||||
{{ item.summary }}
|
||||
</text>
|
||||
|
||||
<!-- 人话解读:一句话说清 + 对你意味着什么 -->
|
||||
<view class="card-plain" v-if="item.plainExplain">
|
||||
<view class="plain-line">
|
||||
<text class="plain-tag">人话</text>
|
||||
<text class="plain-text">{{ item.plainExplain }}</text>
|
||||
</view>
|
||||
<view class="plain-line" v-if="item.takeAway">
|
||||
<text class="plain-tag alt">对你</text>
|
||||
<text class="plain-text">{{ item.takeAway }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 底部信息 -->
|
||||
<view class="card-footer">
|
||||
<text class="card-date">{{ formatDate(item.newsDate) }}</text>
|
||||
@@ -403,3 +415,29 @@ onShareAppMessage(() => {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style scoped>
|
||||
.card-plain {
|
||||
margin-top: 8px;
|
||||
background: var(--color-brand-bg);
|
||||
border: 1px solid var(--glass-hover-border);
|
||||
border-radius: 10px;
|
||||
padding: 8px 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
.plain-line { display: flex; align-items: flex-start; gap: 6px; }
|
||||
.plain-tag {
|
||||
flex-shrink: 0;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
background: var(--color-brand);
|
||||
border-radius: 5px;
|
||||
padding: 1px 6px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
.plain-tag.alt { background: var(--dim3-color); }
|
||||
.plain-text { font-size: 12px; color: var(--text-primary); line-height: 1.6; }
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user