| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- <template>
- <view class="bs-section">
- <!-- 无数据 -->
- <view v-if="(!articles || articles.length === 0) && !loading" class="bs-empty">
- <text class="bs-empty-text">书册整理中,敬请期待...</text>
- </view>
- <!-- 骨架屏 -->
- <view v-else-if="loading && (!articles || articles.length === 0)" class="bs-shelf-skeleton">
- <view class="bs-skeleton-grid">
- <view v-for="n in 3" :key="n" class="bs-skeleton-card">
- <view class="bs-skeleton-cover"></view>
- <view class="bs-skeleton-line"></view>
- </view>
- </view>
- </view>
- <!-- 四列文章网格 -->
- <view v-else class="bs-grid">
- <view
- v-for="(article, idx) in displayArticles"
- :key="idx"
- class="bs-card"
- @click="$emit('articleClick', article)"
- >
- <view
- class="bs-card-cover"
- :style="{
- background: getBookColor(article, idx)
- }"
- >
- <image
- v-if="article.coverSrc"
- class="bs-cover-img"
- :src="article.coverSrc"
- mode="aspectFill"
- />
- <view v-else class="bs-cover-text">
- <text
- class="bs-cover-title"
- :style="{ color: getTextColor(article, idx) }"
- >{{ article.title }}</text>
- </view>
- <view v-if="article.coverSrc" class="bs-cover-title-bottom">
- <text class="bs-cover-title-overlay">{{ article.title }}</text>
- </view>
- </view>
- <text class="bs-card-name">{{ article.title }}</text>
- </view>
- </view>
- </view>
- </template>
- <script>
- // 五维配色体系(书脊颜色)
- import config from '@/config.js'
- var DIMENSION_COLORS = {
- body: { bg: 'linear-gradient(180deg, #FF8C42 0%, #E8762A 100%)', text: '#FFF5EE' },
- mind: { bg: 'linear-gradient(180deg, #FF6B9D 0%, #E84A7F 100%)', text: '#FFF0F5' },
- wisdom: { bg: 'linear-gradient(180deg, #6366F1 0%, #4F46E5 100%)', text: '#EEF2FF' },
- action: { bg: 'linear-gradient(180deg, #10B981 0%, #059669 100%)', text: '#ECFDF5' },
- wealth: { bg: 'linear-gradient(180deg, #F59E0B 0%, #D97706 100%)', text: '#FFFBEB' }
- }
- // 回退渐变(用于无维度分类的文章)
- var FALLBACK_GRADIENTS = [
- { bg: 'linear-gradient(180deg, #8B5CF6 0%, #7C3AED 100%)', text: '#F5F3FF' },
- { bg: 'linear-gradient(180deg, #06B6D4 0%, #0891B2 100%)', text: '#ECFEFF' },
- { bg: 'linear-gradient(180deg, #EC4899 0%, #DB2777 100%)', text: '#FDF2F8' },
- { bg: 'linear-gradient(180deg, #14B8A6 0%, #0D9488 100%)', text: '#F0FDFA' },
- { bg: 'linear-gradient(180deg, #F97316 0%, #EA580C 100%)', text: '#FFF7ED' }
- ]
- export default {
- name: 'ArticleBookshelf',
- props: {
- articles: { type: Array, default: function() { return [] } },
- loading: { type: Boolean, default: false },
- isLoggedIn: { type: Boolean, default: false }
- },
- data: function() {
- return {}
- },
- computed: {
- displayArticles: function() {
- var list
- if (!this.articles || this.articles.length === 0) {
- list = [
- { title: '培养孩子自驱力的关键', category: '家庭成长', summary: '如何帮助孩子建立内在动机' },
- { title: '五维能量与家庭健康管理', category: '健康科普', summary: '科学理解健康的五个维度' },
- { title: '亲子沟通的心理学智慧', category: '心理养育', summary: '有效的倾听与表达技巧' },
- { title: '规划师推荐的书单', category: '成长规划', summary: '培养未来领导力的阅读路径' },
- { title: '儿童营养均衡完全指南', category: '营养健康', summary: '0-12岁各阶段营养需求' }
- ].slice(0, 3)
- } else {
- list = this.articles.slice(0, 3)
- }
- var self = this
- return list.map(function(a) {
- var item = Object.assign({}, a)
- item.coverSrc = self.getImageUrl(a && a.coverImage)
- return item
- })
- }
- },
- methods: {
- // 提取首个维度 code(兼容字符串 "mind,emotion" / JSON 字符串 / 数组 ['mind','emotion'])
- getFirstDimension: function(article) {
- if (!article || !article.relatedDimensions) return ''
- var raw = article.relatedDimensions
- var first = ''
- if (typeof raw === 'string') {
- var trimmed = raw.trim()
- if (trimmed.indexOf('[') === 0) {
- try {
- var parsed = JSON.parse(trimmed)
- if (Array.isArray(parsed)) first = parsed[0] || ''
- } catch (e) {
- first = ''
- }
- }
- if (!first) {
- first = trimmed.split(',')[0] || ''
- }
- } else if (Array.isArray(raw)) {
- first = raw[0] || ''
- }
- return String(first).trim().toLowerCase()
- },
- getBookColor: function(article, idx) {
- var firstDim = this.getFirstDimension(article)
- if (firstDim && DIMENSION_COLORS[firstDim]) {
- return DIMENSION_COLORS[firstDim].bg
- }
- if (article && article.dimensionCode && DIMENSION_COLORS[article.dimensionCode]) {
- return DIMENSION_COLORS[article.dimensionCode].bg
- }
- return FALLBACK_GRADIENTS[idx % FALLBACK_GRADIENTS.length].bg
- },
- getTextColor: function(article, idx) {
- var firstDim = this.getFirstDimension(article)
- if (firstDim && DIMENSION_COLORS[firstDim]) {
- return DIMENSION_COLORS[firstDim].text
- }
- if (article && article.dimensionCode && DIMENSION_COLORS[article.dimensionCode]) {
- return DIMENSION_COLORS[article.dimensionCode].text
- }
- return FALLBACK_GRADIENTS[idx % FALLBACK_GRADIENTS.length].text
- },
- getImageUrl: function(path) {
- if (!path || path === 'null' || path === 'undefined' || path === '/null') return ''
- var s = String(path).trim()
- if (!s || s === 'null' || s === '/null') return ''
- if (s.indexOf('http://') === 0 || s.indexOf('https://') === 0) return s
- return config.API_BASE_URL + (s.charAt(0) === '/' ? s : '/' + s)
- }
- }
- }
- </script>
- <style scoped>
- /* ======================================
- ArticleBookshelf — 四列网格推荐阅读组件
- 浠艾福 (Care Family) 设计系统
- ====================================== */
- /* ---- Section Container ---- */
- .bs-section {
- margin: 24rpx 0;
- padding: 0 0 16rpx;
- }
- /* ---- Empty State ---- */
- .bs-empty {
- padding: 40rpx 0;
- display: flex;
- justify-content: center;
- }
- .bs-empty-text {
- font-size: 24rpx;
- color: #9CA3AF;
- }
- /* ---- Skeleton ---- */
- .bs-shelf-skeleton {
- padding: 0 28rpx;
- }
- .bs-skeleton-grid {
- display: flex;
- flex-wrap: wrap;
- padding-top: 16rpx;
- }
- .bs-skeleton-card {
- width: calc(33.33% - 12rpx);
- margin-right: 16rpx;
- margin-bottom: 16rpx;
- }
- .bs-skeleton-card:nth-child(3n) {
- margin-right: 0;
- }
- .bs-skeleton-cover {
- width: 100%;
- height: 0;
- padding-top: 133.33%; /* 3:4 书封比例 */
- border-radius: 12rpx;
- background: linear-gradient(180deg, #e8e8e8 0%, #f0f0f0 50%, #e8e8e8 100%);
- background-size: 200% 100%;
- animation: skeleton-wave 1.4s ease-in-out infinite;
- }
- .bs-skeleton-line {
- height: 24rpx;
- margin-top: 10rpx;
- border-radius: 6rpx;
- background: linear-gradient(180deg, #e8e8e8 0%, #f0f0f0 50%, #e8e8e8 100%);
- background-size: 200% 100%;
- animation: skeleton-wave 1.4s ease-in-out infinite;
- }
- @keyframes skeleton-wave {
- 0% { background-position: 200% 0; }
- 100% { background-position: -200% 0; }
- }
- /* ---- 三列文章网格 ---- */
- .bs-grid {
- display: flex;
- flex-wrap: wrap;
- }
- .bs-card {
- width: calc(33.33% - 12rpx);
- margin-right: 16rpx;
- margin-bottom: 16rpx;
- }
- .bs-card:nth-child(3n) {
- margin-right: 0;
- }
- .bs-card-cover {
- width: 100%;
- height: 0;
- padding-top: 133.33%; /* 3:4 书封比例 */
- border-radius: 12rpx;
- position: relative;
- display: flex;
- align-items: center;
- justify-content: center;
- overflow: hidden;
- box-sizing: border-box;
- box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.12);
- transition: transform 0.18s, box-shadow 0.18s;
- }
- .bs-card:active .bs-card-cover {
- transform: translateY(-4rpx) scale(1.02);
- box-shadow: 0 6rpx 16rpx rgba(0,0,0,0.18);
- }
- /* 封面图 */
- .bs-cover-img {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- }
- /* 无封面图时:渐变底 + 书名 */
- .bs-cover-text {
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- padding: 16rpx 12rpx;
- box-sizing: border-box;
- }
- .bs-cover-title {
- font-size: 22rpx;
- font-weight: 700;
- line-height: 1.5;
- letter-spacing: 1rpx;
- text-align: center;
- overflow: hidden;
- text-overflow: ellipsis;
- display: -webkit-box;
- -webkit-line-clamp: 3;
- -webkit-box-orient: vertical;
- word-break: break-all;
- }
- /* 有封面图时:底部叠加文章标题 */
- .bs-cover-title-bottom {
- position: absolute;
- bottom: 0;
- left: 0;
- right: 0;
- display: flex;
- justify-content: center;
- align-items: center;
- padding: 10rpx 8rpx 8rpx;
- background: linear-gradient(180deg, transparent 0%, rgba(0,0,0,0.55) 100%);
- }
- .bs-cover-title-overlay {
- font-size: 18rpx;
- font-weight: 700;
- line-height: 1.4;
- color: #FFFFFF;
- text-align: center;
- overflow: hidden;
- text-overflow: ellipsis;
- display: -webkit-box;
- -webkit-line-clamp: 2;
- -webkit-box-orient: vertical;
- word-break: break-all;
- max-width: 90%;
- }
- /* 卡片底部标题 */
- .bs-card-name {
- display: block;
- margin-top: 8rpx;
- font-size: 22rpx;
- color: #333;
- line-height: 1.4;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- </style>
|