- 前端: 更新AI营养师、计算器、打卡、食物详情等页面 - 前端: 更新食物百科、知识详情、营养知识页面 - 前端: 更新社区首页 - 后端: 更新ToolKieAIServiceImpl服务 - API: 更新models-api.js和user.js
165 lines
3.6 KiB
Vue
165 lines
3.6 KiB
Vue
<template>
|
|
<view class="knowledge-detail-page">
|
|
<scroll-view class="content-scroll" scroll-y v-if="detail.title">
|
|
<view class="detail-header">
|
|
<view class="detail-title">{{ detail.title }}</view>
|
|
<view class="detail-meta">
|
|
<text class="meta-item">{{ detail.time }}</text>
|
|
<text class="meta-dot">·</text>
|
|
<text class="meta-item">{{ detail.views }} 阅读</text>
|
|
</view>
|
|
<image
|
|
v-if="detail.coverImage || detail.cover_image"
|
|
class="detail-cover"
|
|
:src="detail.coverImage || detail.cover_image"
|
|
mode="widthFix"
|
|
/>
|
|
</view>
|
|
<view class="detail-body">
|
|
<jyf-parser :html="detail.content || ''" :tag-style="tagStyle" />
|
|
</view>
|
|
</scroll-view>
|
|
<view v-else-if="loading" class="loading-wrap">
|
|
<text>加载中...</text>
|
|
</view>
|
|
<view v-else-if="error" class="error-wrap">
|
|
<text>{{ error }}</text>
|
|
</view>
|
|
<view v-else class="empty-wrap">
|
|
<text>暂无内容</text>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import { getKnowledgeDetail } from '@/api/tool.js';
|
|
import parser from '@/components/jyf-parser/jyf-parser';
|
|
|
|
export default {
|
|
components: {
|
|
'jyf-parser': parser
|
|
},
|
|
data() {
|
|
return {
|
|
id: '',
|
|
detail: {},
|
|
loading: true,
|
|
error: '',
|
|
tagStyle: {
|
|
img: 'width:100%;display:block;',
|
|
table: 'width:100%',
|
|
video: 'width:100%'
|
|
}
|
|
};
|
|
},
|
|
onLoad(options) {
|
|
const rawId = options.id;
|
|
if (rawId != null && rawId !== '' && String(rawId).trim() !== '' && String(rawId) !== 'undefined') {
|
|
this.id = String(rawId).trim();
|
|
} else {
|
|
this.loading = false;
|
|
this.error = '缺少文章 ID';
|
|
}
|
|
},
|
|
onShow() {
|
|
if (this.id) {
|
|
this.loadDetail();
|
|
}
|
|
},
|
|
methods: {
|
|
formatTime(val) {
|
|
if (!val) return '';
|
|
const d = new Date(val);
|
|
if (isNaN(d.getTime())) return String(val);
|
|
const y = d.getFullYear();
|
|
const m = String(d.getMonth() + 1).padStart(2, '0');
|
|
const day = String(d.getDate()).padStart(2, '0');
|
|
return `${y}-${m}-${day}`;
|
|
},
|
|
async loadDetail() {
|
|
this.loading = true;
|
|
this.error = '';
|
|
try {
|
|
const res = await getKnowledgeDetail(this.id);
|
|
if (res && res.data) {
|
|
const d = res.data;
|
|
this.detail = {
|
|
...d,
|
|
time: this.formatTime(d.publishedAt || d.updatedAt || d.createdAt),
|
|
views: d.viewCount != null ? d.viewCount : (d.views != null ? d.views : 0),
|
|
coverImage: d.coverImage || d.cover_image || ''
|
|
};
|
|
uni.setNavigationBarTitle({
|
|
title: (d.title || '知识详情').substring(0, 12) + (d.title && d.title.length > 12 ? '...' : '')
|
|
});
|
|
} else {
|
|
this.error = '加载失败';
|
|
}
|
|
} catch (e) {
|
|
console.error('知识详情加载失败:', e);
|
|
this.error = (e && (e.message || e.msg)) || '加载失败,请重试';
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.knowledge-detail-page {
|
|
min-height: 100vh;
|
|
background: #f4f5f7;
|
|
}
|
|
.content-scroll {
|
|
height: 100vh;
|
|
}
|
|
.detail-header {
|
|
padding: 24rpx 30rpx;
|
|
background: #fff;
|
|
margin-bottom: 16rpx;
|
|
}
|
|
.detail-title {
|
|
font-size: 36rpx;
|
|
font-weight: bold;
|
|
color: #282828;
|
|
line-height: 1.4;
|
|
margin-bottom: 16rpx;
|
|
}
|
|
.detail-meta {
|
|
font-size: 24rpx;
|
|
color: #999;
|
|
margin-bottom: 20rpx;
|
|
}
|
|
.meta-dot {
|
|
margin: 0 8rpx;
|
|
}
|
|
.detail-cover {
|
|
width: 100%;
|
|
border-radius: 16rpx;
|
|
display: block;
|
|
}
|
|
.detail-body {
|
|
padding: 24rpx 30rpx;
|
|
background: #fff;
|
|
min-height: 200rpx;
|
|
font-size: 30rpx;
|
|
line-height: 1.6;
|
|
color: #333;
|
|
}
|
|
.loading-wrap,
|
|
.error-wrap,
|
|
.empty-wrap {
|
|
padding: 80rpx 30rpx;
|
|
text-align: center;
|
|
color: #999;
|
|
font-size: 28rpx;
|
|
}
|
|
.error-wrap {
|
|
color: #f56c6c;
|
|
}
|
|
.empty-wrap {
|
|
color: #9fa5c0;
|
|
}
|
|
</style>
|