|
@@ -0,0 +1,221 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <CustomNav title="图文资讯" leftType="back" />
|
|
|
|
|
+ <view class="page-container">
|
|
|
|
|
+ <view class="news-detail-card">
|
|
|
|
|
+ <view class="news-header">
|
|
|
|
|
+ <text class="news-title">{{ newsTitle }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="news-content">
|
|
|
|
|
+ <view class="news-desc">
|
|
|
|
|
+ <view v-for="(item, index) in parsedMarkdown" :key="index" :class="item.type">
|
|
|
|
|
+ <text v-if="item.type === 'h1'">{{ item.content }}</text>
|
|
|
|
|
+ <text v-if="item.type === 'h2'">{{ item.content }}</text>
|
|
|
|
|
+ <text v-if="item.type === 'h3'">{{ item.content }}</text>
|
|
|
|
|
+ <text v-if="item.type === 'p'">{{ item.content }}</text>
|
|
|
|
|
+ <view v-if="item.type === 'ul'">
|
|
|
|
|
+ <view v-for="(li, liIndex) in item.content" :key="liIndex">
|
|
|
|
|
+ <text>● </text><text>{{ li }}</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <text v-if="item.type === 'blockquote'">{{ item.content }}</text>
|
|
|
|
|
+ <image v-if="item.type === 'img'" :src="item.src" :alt="item.alt" />
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script setup lang="ts">
|
|
|
|
|
+import { ref, computed } from 'vue'
|
|
|
|
|
+import CustomNav from '@/components/custom-nav.vue'
|
|
|
|
|
+
|
|
|
|
|
+// 处理内联markdown
|
|
|
|
|
+const processInline = (text: string) => {
|
|
|
|
|
+ return text.replace(/\*\*(.*?)\*\*/g, '$1').replace(/\*(.*?)\*/g, '$1');
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// 简单的markdown解析函数,返回组件数组
|
|
|
|
|
+const markdownToComponents = (markdown: string) => {
|
|
|
|
|
+ const blocks = markdown.split(/\n\n+/);
|
|
|
|
|
+ const components = [];
|
|
|
|
|
+ for (const block of blocks) {
|
|
|
|
|
+ const trimmed = block.trim();
|
|
|
|
|
+ if (!trimmed) continue;
|
|
|
|
|
+ if (trimmed.startsWith('# ')) {
|
|
|
|
|
+ components.push({ type: 'h1', content: processInline(trimmed.substring(2)) });
|
|
|
|
|
+ } else if (trimmed.startsWith('## ')) {
|
|
|
|
|
+ components.push({ type: 'h2', content: processInline(trimmed.substring(3)) });
|
|
|
|
|
+ } else if (trimmed.startsWith('### ')) {
|
|
|
|
|
+ components.push({ type: 'h3', content: processInline(trimmed.substring(4)) });
|
|
|
|
|
+ } else if (trimmed.startsWith('- ')) {
|
|
|
|
|
+ const lines = trimmed.split('\n');
|
|
|
|
|
+ const items = lines.map(line => processInline(line.startsWith('- ') ? line.substring(2) : line));
|
|
|
|
|
+ components.push({ type: 'ul', content: items });
|
|
|
|
|
+ } else if (trimmed.startsWith('> ')) {
|
|
|
|
|
+ components.push({ type: 'blockquote', content: processInline(trimmed.substring(2)) });
|
|
|
|
|
+ } else if (trimmed.match(/!\[.*\]\(.*\)/)) {
|
|
|
|
|
+ const imgMatch = trimmed.match(/!\[([^\]]*)\]\(([^)]+)\)/);
|
|
|
|
|
+ if (imgMatch) {
|
|
|
|
|
+ components.push({ type: 'img', src: imgMatch[2], alt: imgMatch[1] });
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ components.push({ type: 'p', content: processInline(trimmed) });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return components;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+interface NewsItem {
|
|
|
|
|
+ desc: string
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const news = ref<NewsItem>({
|
|
|
|
|
+ desc: `# 健康饮食指南
|
|
|
|
|
+
|
|
|
|
|
+## 均衡饮食的重要性
|
|
|
|
|
+
|
|
|
|
|
+了解均衡饮食的重要性,掌握健康饮食的基本原则。
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+### 什么是均衡饮食?
|
|
|
|
|
+
|
|
|
|
|
+均衡饮食是指摄入各种营养素的比例适当,既能满足机体需要,又不会造成营养过剩或缺乏。
|
|
|
|
|
+
|
|
|
|
|
+## 合理的饮食结构
|
|
|
|
|
+
|
|
|
|
|
+合理的饮食结构应包括以下五大类食物:
|
|
|
|
|
+
|
|
|
|
|
+- **谷物**:碳水化合物的主要来源,提供能量
|
|
|
|
|
+- **蔬菜和水果**:富含维生素、矿物质和纤维素,有助于预防慢性疾病
|
|
|
|
|
+- **肉类**:提供优质蛋白质和铁等营养素
|
|
|
|
|
+- **奶制品**:钙的重要来源
|
|
|
|
|
+- **油脂类**:提供必需脂肪酸
|
|
|
|
|
+
|
|
|
|
|
+### 饮食建议
|
|
|
|
|
+
|
|
|
|
|
+1. 每天摄入足够的蔬菜和水果
|
|
|
|
|
+2. 控制糖和盐的摄入量
|
|
|
|
|
+3. 选择全谷物食品
|
|
|
|
|
+4. 适量饮水,保持身体水分平衡
|
|
|
|
|
+
|
|
|
|
|
+> **温馨提示**:良好的饮食习惯是健康的基础,建议定期咨询专业营养师制定个性化饮食方案。
|
|
|
|
|
+`
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const newsTitle = computed(() => {
|
|
|
|
|
+ const match = news.value.desc.match(/^# (.+)$/m)
|
|
|
|
|
+ return match ? match[1] : '图文资讯'
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const parsedMarkdown = computed(() => {
|
|
|
|
|
+ let desc = news.value.desc
|
|
|
|
|
+ const match = desc.match(/^# (.+)$/m)
|
|
|
|
|
+ if (match) {
|
|
|
|
|
+ desc = desc.replace(/^# .+\n/, '').trimStart()
|
|
|
|
|
+ }
|
|
|
|
|
+ return markdownToComponents(desc)
|
|
|
|
|
+})
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+.page-container {
|
|
|
|
|
+ min-height: 100vh;
|
|
|
|
|
+ background-color: #f5f5f5;
|
|
|
|
|
+ padding-top: calc(var(--status-bar-height) + 44px);
|
|
|
|
|
+ padding-bottom: 40rpx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.news-detail-card {
|
|
|
|
|
+ background-color: #fff;
|
|
|
|
|
+ margin: 20rpx;
|
|
|
|
|
+ border-radius: 20rpx;
|
|
|
|
|
+ box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.news-header {
|
|
|
|
|
+ padding: 40rpx;
|
|
|
|
|
+ border-bottom: 1rpx solid #eee;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.news-content {
|
|
|
|
|
+ padding-inline: 40rpx;
|
|
|
|
|
+}
|
|
|
|
|
+.news-desc {
|
|
|
|
|
+ font-size: 32rpx;
|
|
|
|
|
+ color: #666;
|
|
|
|
|
+ line-height: 2.0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.news-title {
|
|
|
|
|
+ font-size: 56rpx;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.h1 {
|
|
|
|
|
+ border-block: 1rpx solid #0c0c0c5a;
|
|
|
|
|
+ font-size: 56rpx;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ margin: 40rpx 0 0 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.h2 {
|
|
|
|
|
+ font-size: 48rpx;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ margin: 30rpx 0 0 0;
|
|
|
|
|
+ border-bottom: 1rpx solid #0c0c0c15;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.h3 {
|
|
|
|
|
+ font-size: 32rpx;
|
|
|
|
|
+ font-weight: bold;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ margin: 25rpx 0 12rpx 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.p {
|
|
|
|
|
+ margin: 20rpx 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.ul {
|
|
|
|
|
+ margin: 20rpx 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.li {
|
|
|
|
|
+ margin-left: 30rpx;
|
|
|
|
|
+ margin-bottom: 5rpx;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: flex-start;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.blockquote {
|
|
|
|
|
+ border-left: 4rpx solid #ddd;
|
|
|
|
|
+ padding-left: 20rpx;
|
|
|
|
|
+ margin: 20rpx 0;
|
|
|
|
|
+ color: #666;
|
|
|
|
|
+ font-style: italic;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.img {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ margin: 10rpx 0;
|
|
|
|
|
+ border-radius: 8rpx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.empty-state {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ padding: 100rpx 40rpx;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.empty-text {
|
|
|
|
|
+ font-size: 32rpx;
|
|
|
|
|
+ color: #666;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|