19 changed files with 1586 additions and 277 deletions
-
4app.json
-
10pages/home/home.js
-
267pages/personal/personal.js
-
23pages/personal/personal.wxml
-
49pages/personal/personal.wxss
-
242pagesA/pages/askingSyDetails/askingSyDetails.js
-
256pagesA/pages/askingSyDetails/askingSyDetails.wxml
-
81pagesA/pages/askingSyDetails/askingSyDetails.wxss
-
2pagesA/pages/attestation/attestation.wxss
-
161pagesA/pages/carouselDetail/carouselDetail.js
-
4pagesA/pages/carouselDetail/carouselDetail.json
-
112pagesA/pages/carouselDetail/carouselDetail.wxml
-
284pagesA/pages/carouselDetail/carouselDetail.wxss
-
4pagesA/pages/expertChat/expertChat.wxss
-
120pagesA/pages/todayInquiry/todayInquiry.js
-
4pagesA/pages/todayInquiry/todayInquiry.json
-
59pagesA/pages/todayInquiry/todayInquiry.wxml
-
156pagesA/pages/todayInquiry/todayInquiry.wxss
-
13utils/api.js
@ -1,151 +1,177 @@ |
|||
<view class="xqbox"> |
|||
|
|||
<!-- 页面内容 --> |
|||
<scroll-view class="page-content" scroll-y refresher-enabled refresher-triggered="{{refreshing}}" bindrefresherrefresh="onRefresh"> |
|||
<!-- 页面内容 --> |
|||
<scroll-view class="page-content" scroll-y refresher-enabled refresher-triggered="{{refreshing}}" bindrefresherrefresh="onRefresh"> |
|||
|
|||
<!-- 用户问诊卡片 --> |
|||
<view class="user-query-card card-enter"> |
|||
<!-- 用户信息 --> |
|||
<view class="user-info-section"> |
|||
<view class="avatar-wrapper"> |
|||
<image class="user-avatar" src="/pages/images/tx.png"></image> |
|||
<!-- 用户问诊卡片 --> |
|||
<view class="user-query-card card-enter"> |
|||
<!-- 用户信息 --> |
|||
<view class="user-info-section"> |
|||
<view class="avatar-wrapper"> |
|||
<image class="user-avatar" src="{{diagnosisData.avatar?baseUrl+diagnosisData.avatar:'/pages/images/tx.png'}}"></image> |
|||
</view> |
|||
<view class="user-details"> |
|||
<view class="user-name-row"> |
|||
<text class="user-name">{{diagnosisData.farmerName || '用户'}}</text> |
|||
<view class="status-badge {{diagnosisData.status === '已回复' ? 'status-replied' : 'status-pending'}} pulse"> |
|||
{{diagnosisData.status}} |
|||
</view> |
|||
</view> |
|||
<view class="user-details"> |
|||
<view class="user-name-row"> |
|||
<text class="user-name">{{diagnosisData.farmerName || '用户'}}</text> |
|||
<view class="status-badge {{diagnosisData.status === '已回复' ? 'status-replied' : 'status-pending'}} pulse"> |
|||
{{diagnosisData.status}} |
|||
</view> |
|||
<view class="pet-info"> |
|||
<view class="pet-info-tags"> |
|||
<view class="pet-tag gradient-blue">{{diagnosisData.animalType}}</view> |
|||
<view class="pet-tag gradient-orange">{{diagnosisData.animalAge}}</view> |
|||
<view class="pet-tag gradient-pink">{{diagnosisData.animalGender}}</view> |
|||
</view> |
|||
<view class="pet-info"> |
|||
<view class="pet-info-tags"> |
|||
<view class="pet-tag gradient-blue">{{diagnosisData.animalType}}</view> |
|||
<view class="pet-tag gradient-orange">{{diagnosisData.animalAge}}</view> |
|||
<view class="pet-tag gradient-pink">{{diagnosisData.animalGender}}</view> |
|||
</view> |
|||
<view class="time-info"> |
|||
<text class="time-text">{{diagnosisData.createdTime}}</text> |
|||
</view> |
|||
<view class="time-info"> |
|||
<text class="time-text">{{diagnosisData.createdTime}}</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 症状描述 --> |
|||
<view class="symptom-section"> |
|||
<view class="section-header"> |
|||
<text class="section-title">症状描述</text> |
|||
<view class="title-decoration"></view> |
|||
</view> |
|||
<view class="symptom-content"> |
|||
<view class="quote-left"> |
|||
<text>"</text> |
|||
</view> |
|||
<text class="symptom-text">{{diagnosisData.description}}</text> |
|||
</view> |
|||
<!-- 症状描述 --> |
|||
<view class="symptom-section"> |
|||
<view class="section-header"> |
|||
<text class="section-title">症状描述</text> |
|||
<view class="title-decoration"></view> |
|||
</view> |
|||
|
|||
<!-- 相关图片 --> |
|||
<view class="image-section" wx:if="{{images && images.length > 0}}"> |
|||
<view class="section-header"> |
|||
<text class="section-title">相关图片</text> |
|||
<text class="image-count gradient-blue">{{images.length}}张</text> |
|||
<view class="symptom-content"> |
|||
<view class="quote-left"> |
|||
<text>"</text> |
|||
</view> |
|||
<scroll-view class="images-scroll" scroll-x> |
|||
<view class="images-container"> |
|||
<block wx:for="{{images}}" wx:key="*this" wx:for-index="index"> |
|||
<view class="image-wrapper"> |
|||
<image |
|||
class="symptom-image" |
|||
src="{{baseUrl+item}}" |
|||
mode="aspectFill" |
|||
bindtap="previewImage" |
|||
data-url="{{baseUrl+item}}" |
|||
data-urls="{{images}}" |
|||
></image> |
|||
</view> |
|||
</block> |
|||
</view> |
|||
</scroll-view> |
|||
</view> |
|||
|
|||
<!-- 卡片装饰 --> |
|||
<view class="card-decoration"> |
|||
<view class="decoration-dot dot-1"></view> |
|||
<view class="decoration-dot dot-2"></view> |
|||
<view class="decoration-dot dot-3"></view> |
|||
<text class="symptom-text">{{diagnosisData.description}}</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 兽医回复区域 --> |
|||
<view class="replies-section"> |
|||
<!-- 相关图片 --> |
|||
<view class="image-section" wx:if="{{diagnosisData.images && diagnosisData.images.length > 0}}"> |
|||
<view class="section-header"> |
|||
<text class="section-title">兽医回复</text> |
|||
<view class="reply-count gradient-purple"> |
|||
<text class="count-number">{{replies.length}}</text> |
|||
<text class="count-text">条回复</text> |
|||
<text class="section-title">相关图片</text> |
|||
<text class="image-count gradient-blue">{{diagnosisData.images.length}}张</text> |
|||
</view> |
|||
<scroll-view class="images-scroll" scroll-x> |
|||
<view class="images-container"> |
|||
<block wx:for="{{diagnosisData.images}}" wx:key="*this" wx:for-index="index"> |
|||
<view class="image-wrapper"> |
|||
<image |
|||
class="symptom-image" |
|||
src="{{baseUrl+item}}" |
|||
mode="aspectFill" |
|||
bindtap="previewImage" |
|||
data-url="{{baseUrl+item}}" |
|||
data-urls="{{diagnosisData.images}}" |
|||
data-type="user" |
|||
></image> |
|||
</view> |
|||
</block> |
|||
</view> |
|||
</scroll-view> |
|||
</view> |
|||
|
|||
<!-- 卡片装饰 --> |
|||
<view class="card-decoration"> |
|||
<view class="decoration-dot dot-1"></view> |
|||
<view class="decoration-dot dot-2"></view> |
|||
<view class="decoration-dot dot-3"></view> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 兽医回复区域 --> |
|||
<view class="replies-section"> |
|||
<view class="section-header"> |
|||
<text class="section-title">兽医回复</text> |
|||
<view class="reply-count gradient-purple"> |
|||
<text class="count-number">{{replies.length}}</text> |
|||
<text class="count-text">条回复</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 回复列表 --> |
|||
<view class="replies-list"> |
|||
<block wx:for="{{replies}}" wx:key="id" wx:for-index="index"> |
|||
<view class="vet-reply-card fade-in-up" style="animation-delay: {{index * 0.1}}s;"> |
|||
<!-- 兽医信息 --> |
|||
<view class="vet-info"> |
|||
<view class="avatar-wrapper"> |
|||
<image class="vet-avatar" src="{{item.avatar?baseUrl+item.avatar:'/pages/images/tx.png'}}"></image> |
|||
<view class="vet-verified"></view> |
|||
<!-- 回复列表 --> |
|||
<view class="replies-list"> |
|||
<block wx:for="{{replies}}" wx:key="index" wx:for-index="index"> |
|||
<view class="vet-reply-card fade-in-up" style="animation-delay: {{index * 0.1}}s;"> |
|||
<!-- 兽医信息 --> |
|||
<view class="vet-info"> |
|||
<view class="avatar-wrapper"> |
|||
<image class="vet-avatar" src="{{item.avatar?baseUrl+item.avatar:'/pages/images/tx.png'}}"></image> |
|||
<view class="vet-verified"></view> |
|||
</view> |
|||
<view class="vet-details"> |
|||
<view class="vet-name-row"> |
|||
<text class="vet-name">{{item.replyName || '兽医'}}</text> |
|||
<view class="vet-badge gradient-gold" wx:if="{{item.title}}"> |
|||
<text class="vet-title">{{item.title}}</text> |
|||
</view> |
|||
</view> |
|||
<view class="vet-details"> |
|||
<view class="vet-name-row"> |
|||
<text class="vet-name">{{item.replyName}}</text> |
|||
<view class="vet-badge gradient-gold"> |
|||
<text class="vet-title">{{item.title}}</text> |
|||
</view> |
|||
<view class="vet-meta"> |
|||
<view class="meta-item" wx:if="{{item.hospital}}"> |
|||
<text class="vet-hospital">{{item.hospital}}</text> |
|||
</view> |
|||
<view class="vet-meta"> |
|||
<view class="meta-item"> |
|||
<text class="vet-hospital">{{item.hospital}}</text> |
|||
</view> |
|||
<view class="meta-item"> |
|||
<text class="vet-experience">{{item.experience}}</text> |
|||
</view> |
|||
<view class="meta-item" wx:if="{{item.experience}}"> |
|||
<text class="vet-experience">{{item.experience}}</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 回复内容 --> |
|||
<view class="reply-content"> |
|||
<view class="reply-bubble"> |
|||
<text class="reply-text">{{item.content}}</text> |
|||
</view> |
|||
<!-- 回复内容 --> |
|||
<view class="reply-content"> |
|||
<view class="reply-bubble"> |
|||
<text class="reply-text">{{item.content}}</text> |
|||
</view> |
|||
|
|||
<!-- 回复底部 --> |
|||
<view class="reply-footer"> |
|||
<view class="reply-time"> |
|||
<text class="time-text">{{item.createdAt}}</text> |
|||
<!-- 兽医回复图片 - 优化后的图片网格布局,支持预览 --> |
|||
<view wx:if="{{item.images && item.images.length > 0}}" class="reply-images-section"> |
|||
<view class="reply-images-grid grid-{{item.images.length}}"> |
|||
<block wx:for="{{item.images}}" wx:key="this" wx:for-index="imgIndex"> |
|||
<view class="reply-image-wrapper" |
|||
bindtap="previewReplyImage" |
|||
data-url="{{item}}" |
|||
data-fullurl="{{baseUrl + item}}" |
|||
data-urls="{{item.images}}" |
|||
data-current-index="{{imgIndex}}" |
|||
data-reply-index="{{index}}"> |
|||
<image |
|||
class="reply-image" |
|||
src="{{baseUrl + item}}" |
|||
mode="aspectFill" |
|||
lazy-load |
|||
></image> |
|||
<!-- 如果图片数量大于4且当前是第4张,显示剩余数量遮罩(仅当图片很多时视觉优化,但预览仍全部可看) --> |
|||
<view wx:if="{{item.images.length > 4 && imgIndex === 3}}" class="image-more-mask"> |
|||
<text class="more-count">+{{item.images.length - 4}}</text> |
|||
</view> |
|||
</view> |
|||
</block> |
|||
</view> |
|||
</view> |
|||
|
|||
</view> |
|||
</block> |
|||
|
|||
<!-- 无回复状态 --> |
|||
<view wx:if="{{diagnosisData.replies.length === 0}}" class="no-replies fade-in"> |
|||
<image class="no-replies-icon" src="/images/waiting.png"></image> |
|||
<text class="no-replies-title">等待兽医回复中</text> |
|||
<text class="no-replies-desc">专业兽医通常会在24小时内为您解答</text> |
|||
<view class="waiting-animation"> |
|||
<view class="loading-dot dot-1"></view> |
|||
<view class="loading-dot dot-2"></view> |
|||
<view class="loading-dot dot-3"></view> |
|||
<!-- 回复底部 --> |
|||
<view class="reply-footer"> |
|||
<view class="reply-time"> |
|||
<text class="time-text">{{item.createdAt || item.createTime || ''}}</text> |
|||
</view> |
|||
</view> |
|||
|
|||
</view> |
|||
</block> |
|||
|
|||
<!-- 无回复状态 --> |
|||
<view wx:if="{{replies.length === 0}}" class="no-replies fade-in"> |
|||
<text class="no-replies-title">等待兽医回复中</text> |
|||
<text class="no-replies-desc">专业兽医通常会在24小时内为您解答</text> |
|||
<view class="waiting-animation"> |
|||
<view class="loading-dot dot-1"></view> |
|||
<view class="loading-dot dot-2"></view> |
|||
<view class="loading-dot dot-3"></view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 底部安全区域 --> |
|||
<view class="page-bottom"></view> |
|||
</scroll-view> |
|||
<!-- 底部安全区域 --> |
|||
<view class="page-bottom"></view> |
|||
</scroll-view> |
|||
</view> |
|||
@ -0,0 +1,161 @@ |
|||
import http from '../../../utils/api'; |
|||
const baseUrl = require('../../../utils/baseUrl'); |
|||
|
|||
Page({ |
|||
/** |
|||
* 页面的初始数据 |
|||
*/ |
|||
data: { |
|||
baseUrl: baseUrl, |
|||
detailInfo: {}, |
|||
id: null, |
|||
cardAnimation: {} // 卡片动画数据
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面加载 |
|||
*/ |
|||
onLoad(options) { |
|||
if (options.id) { |
|||
this.setData({ id: options.id }); |
|||
this.getCarouselDetail(options.id); |
|||
this.initAnimation(); |
|||
} else { |
|||
wx.showToast({ |
|||
title: '参数错误', |
|||
icon: 'none' |
|||
}); |
|||
} |
|||
}, |
|||
|
|||
/** |
|||
* 初始化卡片动画 |
|||
*/ |
|||
initAnimation() { |
|||
const animation = wx.createAnimation({ |
|||
duration: 600, |
|||
timingFunction: 'ease-out', |
|||
delay: 100 |
|||
}); |
|||
|
|||
animation.translateY(0).opacity(1).step(); |
|||
|
|||
this.setData({ |
|||
cardAnimation: animation.export() |
|||
}); |
|||
}, |
|||
|
|||
/** |
|||
* 获取轮播详情 |
|||
*/ |
|||
getCarouselDetail(id) { |
|||
wx.showLoading({ title: '加载中...', mask: true }); |
|||
|
|||
http.carouselDetail({ |
|||
data: { id: id }, |
|||
success: (res) => { |
|||
wx.hideLoading(); |
|||
console.log('轮播详情:', res); |
|||
|
|||
if (res && res.code === 200 && res.data) { |
|||
this.setData({ |
|||
detailInfo: res.data |
|||
}); |
|||
|
|||
// 设置导航栏颜色为主题色
|
|||
wx.setNavigationBarColor({ |
|||
frontColor: '#ffffff', |
|||
backgroundColor: res.data.textColor?.replace('#', '') || '2E7D32' |
|||
}); |
|||
|
|||
wx.setNavigationBarTitle({ |
|||
title: res.data.title || '轮播详情' |
|||
}); |
|||
} else { |
|||
wx.showToast({ |
|||
title: res?.msg || '数据加载失败', |
|||
icon: 'none' |
|||
}); |
|||
} |
|||
}, |
|||
fail: (err) => { |
|||
wx.hideLoading(); |
|||
console.error('请求失败:', err); |
|||
wx.showToast({ |
|||
title: '网络错误', |
|||
icon: 'none' |
|||
}); |
|||
} |
|||
}); |
|||
}, |
|||
|
|||
/** |
|||
* 颜色调整函数(用于渐变效果) |
|||
*/ |
|||
adjustColor(hex, percent) { |
|||
if (!hex) return '#4CAF50'; |
|||
// 简单实现:如果传入颜色,返回稍浅的版本
|
|||
// 这里为了简化,直接返回原色稍微变浅,实际项目中可使用颜色处理库
|
|||
return hex; |
|||
}, |
|||
|
|||
/** |
|||
* 图片加载错误处理 |
|||
*/ |
|||
imageLoadError(e) { |
|||
console.warn('图片加载失败', e); |
|||
|
|||
}, |
|||
|
|||
|
|||
/** |
|||
* 返回上一页 |
|||
*/ |
|||
goBack() { |
|||
wx.navigateBack({ |
|||
delta: 1 |
|||
}); |
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面初次渲染完成 |
|||
*/ |
|||
onReady() {}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面显示 |
|||
*/ |
|||
onShow() {}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面隐藏 |
|||
*/ |
|||
onHide() {}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面卸载 |
|||
*/ |
|||
onUnload() {}, |
|||
|
|||
/** |
|||
* 页面相关事件处理函数--监听用户下拉动作 |
|||
*/ |
|||
onPullDownRefresh() {}, |
|||
|
|||
/** |
|||
* 页面上拉触底事件的处理函数 |
|||
*/ |
|||
onReachBottom() {}, |
|||
|
|||
/** |
|||
* 用户点击右上角分享 |
|||
*/ |
|||
onShareAppMessage() { |
|||
const { title, imageUrl } = this.data.detailInfo; |
|||
return { |
|||
title: title || '轮播详情', |
|||
imageUrl: this.data.baseUrl + (imageUrl || ''), |
|||
path: `/pages/carousel/detail/detail?id=${this.data.id}` |
|||
}; |
|||
} |
|||
}); |
|||
@ -0,0 +1,4 @@ |
|||
{ |
|||
"navigationBarTitleText":"轮播详情", |
|||
"usingComponents": {} |
|||
} |
|||
@ -0,0 +1,112 @@ |
|||
<view class="carousel-detail-container" style="--bg-color: {{detailInfo.bgColor || '#F8F9FA'}};"> |
|||
|
|||
<!-- 沉浸式头部,带渐变遮罩和返回按钮 --> |
|||
<view class="hero-section"> |
|||
<image |
|||
class="hero-image" |
|||
src="{{baseUrl + detailInfo.imageUrl}}" |
|||
mode="aspectFill" |
|||
binderror="imageLoadError" |
|||
></image> |
|||
<view class="hero-overlay" style="background: linear-gradient(to bottom, transparent 30%, {{detailInfo.bgColor || '#F8F9FA'}} 90%);"></view> |
|||
|
|||
<!-- 返回按钮 --> |
|||
<view class="nav-back glass" bindtap="goBack"> |
|||
<text class="iconfont icon-back">←</text> |
|||
</view> |
|||
|
|||
<!-- 页面标题 - 仅在需要时显示 --> |
|||
<view class="page-title glass" wx:if="{{detailInfo.adsType}}"> |
|||
<text>{{detailInfo.adsType}}</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 主要内容卡片 --> |
|||
<view class="content-card" animation="{{cardAnimation}}" style="--text-color: {{detailInfo.textColor || '#2E7D32'}};"> |
|||
|
|||
<!-- 标题区域 --> |
|||
<view class="title-section"> |
|||
<text class="main-title" style="color: {{detailInfo.textColor || '#1A1A1A'}};">{{detailInfo.title || '无标题'}}</text> |
|||
<text class="sub-title">{{detailInfo.subtitle || '暂无副标题'}}</text> |
|||
</view> |
|||
|
|||
<!-- 装饰分割线 --> |
|||
<view class="divider"> |
|||
<view class="divider-line" style="background-color: {{detailInfo.textColor || '#2E7D32'}};"></view> |
|||
<view class="divider-dot" style="background-color: {{detailInfo.textColor || '#2E7D32'}};"></view> |
|||
<view class="divider-line" style="background-color: {{detailInfo.textColor || '#2E7D32'}};"></view> |
|||
</view> |
|||
|
|||
<!-- 信息网格 --> |
|||
<view class="info-grid"> |
|||
<!-- 尺寸信息卡片 --> |
|||
<view class="info-item" wx:if="{{detailInfo.imageSize}}"> |
|||
<view class="info-icon">📐</view> |
|||
<view class="info-content"> |
|||
<text class="info-label">图片尺寸</text> |
|||
<text class="info-value">{{detailInfo.imageSize}}</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 展示次数卡片 --> |
|||
<view class="info-item" wx:if="{{detailInfo.displayCount !== undefined}}"> |
|||
<view class="info-icon">👁️</view> |
|||
<view class="info-content"> |
|||
<text class="info-label">展示次数</text> |
|||
<text class="info-value">{{detailInfo.displayCount}}</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 点击次数卡片 --> |
|||
<view class="info-item" wx:if="{{detailInfo.clickCount !== undefined}}"> |
|||
<view class="info-icon">🖱️</view> |
|||
<view class="info-content"> |
|||
<text class="info-label">点击次数</text> |
|||
<text class="info-value">{{detailInfo.clickCount}}</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 创建时间卡片 --> |
|||
<view class="info-item" wx:if="{{detailInfo.createdAt}}"> |
|||
<view class="info-icon">📅</view> |
|||
<view class="info-content"> |
|||
<text class="info-label">创建时间</text> |
|||
<text class="info-value">{{detailInfo.createdAt}}</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 更新时间卡片 --> |
|||
<view class="info-item" wx:if="{{detailInfo.updatedAt}}"> |
|||
<view class="info-icon">🔄</view> |
|||
<view class="info-content"> |
|||
<text class="info-label">更新时间</text> |
|||
<text class="info-value">{{detailInfo.updatedAt}}</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 有效性状态卡片 - 使用优雅的徽章设计 --> |
|||
<view class="info-item status-item" wx:if="{{detailInfo.isActive !== undefined}}"> |
|||
<view class="info-icon">⚡</view> |
|||
<view class="info-content"> |
|||
<text class="info-label">状态</text> |
|||
<view class="status-badge" style="background-color: {{detailInfo.isActive === 1 ? '#4CAF50' : '#9E9E9E'}}20; border-color: {{detailInfo.isActive === 1 ? '#4CAF50' : '#9E9E9E'}};"> |
|||
<text class="status-dot" style="background-color: {{detailInfo.isActive === 1 ? '#4CAF50' : '#9E9E9E'}};"></text> |
|||
<text class="status-text" style="color: {{detailInfo.isActive === 1 ? '#4CAF50' : '#9E9E9E'}};">{{detailInfo.isActive === 1 ? '有效' : '无效'}}</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 描述/备注区域(如果有remark字段) --> |
|||
<view class="remark-section" wx:if="{{detailInfo.remark}}"> |
|||
<view class="remark-icon">📝</view> |
|||
<view class="remark-content">{{detailInfo.remark}}</view> |
|||
</view> |
|||
|
|||
<!-- 辅助信息:始终有效标识 --> |
|||
<view class="always-valid" wx:if="{{detailInfo.isAlwaysValid === 1}}"> |
|||
<text class="valid-icon">✨</text> |
|||
<text class="valid-text">长期有效</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
@ -0,0 +1,284 @@ |
|||
.carousel-detail-container { |
|||
min-height: 100vh; |
|||
background-color: var(--bg-color, #F8F9FA); |
|||
position: relative; |
|||
padding-bottom: 40rpx; |
|||
} |
|||
|
|||
/* 沉浸式头部 */ |
|||
.hero-section { |
|||
position: relative; |
|||
width: 100%; |
|||
height: 600rpx; |
|||
overflow: hidden; |
|||
} |
|||
|
|||
.hero-image { |
|||
width: 100%; |
|||
height: 100%; |
|||
filter: brightness(0.9); |
|||
transition: transform 0.3s ease; |
|||
} |
|||
|
|||
.hero-image:active { |
|||
transform: scale(1.02); |
|||
} |
|||
|
|||
.hero-overlay { |
|||
position: absolute; |
|||
bottom: 0; |
|||
left: 0; |
|||
right: 0; |
|||
height: 200rpx; |
|||
pointer-events: none; |
|||
} |
|||
|
|||
/* 毛玻璃返回按钮 */ |
|||
.nav-back { |
|||
position: absolute; |
|||
top: 60rpx; |
|||
left: 30rpx; |
|||
width: 72rpx; |
|||
height: 72rpx; |
|||
border-radius: 36rpx; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
font-size: 40rpx; |
|||
color: #333; |
|||
z-index: 10; |
|||
} |
|||
|
|||
.glass { |
|||
background: rgba(255, 255, 255, 0.25); |
|||
backdrop-filter: blur(10px); |
|||
-webkit-backdrop-filter: blur(10px); |
|||
border: 1rpx solid rgba(255, 255, 255, 0.3); |
|||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1); |
|||
} |
|||
|
|||
.page-title { |
|||
position: absolute; |
|||
top: 60rpx; |
|||
right: 30rpx; |
|||
padding: 16rpx 32rpx; |
|||
border-radius: 40rpx; |
|||
font-size: 26rpx; |
|||
color: #333; |
|||
font-weight: 500; |
|||
z-index: 10; |
|||
letter-spacing: 1rpx; |
|||
} |
|||
|
|||
/* 主要内容卡片 */ |
|||
.content-card { |
|||
margin: -100rpx 30rpx 0; |
|||
background: rgba(255, 255, 255, 0.95); |
|||
backdrop-filter: blur(20px); |
|||
-webkit-backdrop-filter: blur(20px); |
|||
border-radius: 48rpx; |
|||
padding: 48rpx 32rpx; |
|||
box-shadow: 0 30rpx 60rpx rgba(0, 0, 0, 0.1), |
|||
0 10rpx 30rpx rgba(0, 0, 0, 0.05); |
|||
position: relative; |
|||
z-index: 5; |
|||
border: 1rpx solid rgba(255, 255, 255, 0.5); |
|||
opacity: 0; |
|||
transform: translateY(50rpx); |
|||
animation: cardFloat 0.6s ease-out forwards; |
|||
} |
|||
|
|||
@keyframes cardFloat { |
|||
to { |
|||
opacity: 1; |
|||
transform: translateY(0); |
|||
} |
|||
} |
|||
|
|||
/* 标题区域 */ |
|||
.title-section { |
|||
margin-bottom: 40rpx; |
|||
} |
|||
|
|||
.main-title { |
|||
display: block; |
|||
font-size: 56rpx; |
|||
font-weight: 700; |
|||
line-height: 1.3; |
|||
margin-bottom: 16rpx; |
|||
letter-spacing: -0.5rpx; |
|||
} |
|||
|
|||
.sub-title { |
|||
display: block; |
|||
font-size: 30rpx; |
|||
color: #666; |
|||
line-height: 1.5; |
|||
font-weight: 400; |
|||
opacity: 0.8; |
|||
} |
|||
|
|||
/* 装饰分割线 */ |
|||
.divider { |
|||
display: flex; |
|||
align-items: center; |
|||
margin: 30rpx 0 40rpx; |
|||
} |
|||
|
|||
.divider-line { |
|||
flex: 1; |
|||
height: 2rpx; |
|||
opacity: 0.2; |
|||
} |
|||
|
|||
.divider-dot { |
|||
width: 8rpx; |
|||
height: 8rpx; |
|||
border-radius: 4rpx; |
|||
margin: 0 20rpx; |
|||
opacity: 0.5; |
|||
} |
|||
|
|||
/* 信息网格 */ |
|||
.info-grid { |
|||
display: grid; |
|||
grid-template-columns: repeat(2, 1fr); |
|||
gap: 24rpx; |
|||
margin-bottom: 40rpx; |
|||
} |
|||
|
|||
.info-item { |
|||
background: rgba(0, 0, 0, 0.02); |
|||
border-radius: 28rpx; |
|||
padding: 28rpx 20rpx; |
|||
display: flex; |
|||
align-items: center; |
|||
border: 1rpx solid rgba(0, 0, 0, 0.03); |
|||
transition: all 0.3s ease; |
|||
} |
|||
|
|||
.info-item:active { |
|||
transform: scale(0.98); |
|||
background: rgba(0, 0, 0, 0.04); |
|||
} |
|||
|
|||
.info-icon { |
|||
font-size: 48rpx; |
|||
margin-right: 20rpx; |
|||
filter: drop-shadow(0 4rpx 8rpx rgba(0, 0, 0, 0.1)); |
|||
} |
|||
|
|||
.info-content { |
|||
flex: 1; |
|||
display: flex; |
|||
flex-direction: column; |
|||
} |
|||
|
|||
.info-label { |
|||
font-size: 22rpx; |
|||
color: #999; |
|||
margin-bottom: 8rpx; |
|||
letter-spacing: 0.5rpx; |
|||
} |
|||
|
|||
.info-value { |
|||
font-size: 28rpx; |
|||
font-weight: 600; |
|||
color: #333; |
|||
word-break: break-all; |
|||
} |
|||
|
|||
/* 状态特殊样式 */ |
|||
.status-item .info-content { |
|||
flex-direction: row; |
|||
align-items: center; |
|||
justify-content: space-between; |
|||
} |
|||
|
|||
.status-badge { |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 8rpx 16rpx; |
|||
border-radius: 40rpx; |
|||
border-width: 1rpx; |
|||
border-style: solid; |
|||
background-color: rgba(76, 175, 80, 0.1); |
|||
} |
|||
|
|||
.status-dot { |
|||
width: 16rpx; |
|||
height: 16rpx; |
|||
border-radius: 8rpx; |
|||
margin-right: 8rpx; |
|||
animation: pulse 2s infinite; |
|||
} |
|||
|
|||
@keyframes pulse { |
|||
0%, 100% { opacity: 1; } |
|||
50% { opacity: 0.6; } |
|||
} |
|||
|
|||
.status-text { |
|||
font-size: 24rpx; |
|||
font-weight: 500; |
|||
} |
|||
|
|||
/* 备注区域 */ |
|||
.remark-section { |
|||
background: rgba(0, 0, 0, 0.02); |
|||
border-radius: 28rpx; |
|||
padding: 28rpx; |
|||
margin-bottom: 40rpx; |
|||
display: flex; |
|||
border-left: 8rpx solid var(--text-color, #2E7D32); |
|||
} |
|||
|
|||
.remark-icon { |
|||
font-size: 40rpx; |
|||
margin-right: 20rpx; |
|||
} |
|||
|
|||
.remark-content { |
|||
flex: 1; |
|||
font-size: 28rpx; |
|||
color: #444; |
|||
line-height: 1.6; |
|||
} |
|||
|
|||
|
|||
/* 始终有效标识 */ |
|||
.always-valid { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
margin-top: 30rpx; |
|||
padding: 20rpx; |
|||
background: linear-gradient(135deg, rgba(255, 215, 0, 0.1), rgba(255, 215, 0, 0.05)); |
|||
border-radius: 40rpx; |
|||
border: 1rpx solid rgba(255, 215, 0, 0.3); |
|||
} |
|||
|
|||
.valid-icon { |
|||
font-size: 32rpx; |
|||
margin-right: 12rpx; |
|||
animation: starTwinkle 1.5s infinite; |
|||
} |
|||
|
|||
@keyframes starTwinkle { |
|||
0%, 100% { opacity: 1; transform: scale(1); } |
|||
50% { opacity: 0.7; transform: scale(1.1); } |
|||
} |
|||
|
|||
.valid-text { |
|||
font-size: 26rpx; |
|||
color: #B8860B; |
|||
font-weight: 500; |
|||
} |
|||
|
|||
/* 响应式调整 */ |
|||
@media (min-width: 768px) { |
|||
.content-card { |
|||
max-width: 700rpx; |
|||
margin: -100rpx auto 0; |
|||
} |
|||
} |
|||
@ -0,0 +1,120 @@ |
|||
import http from '../../../utils/api' |
|||
const baseUrl = require('../../../utils/baseUrl') |
|||
|
|||
Page({ |
|||
/** |
|||
* 页面的初始数据 |
|||
*/ |
|||
data: { |
|||
list: [], // 问诊列表数据
|
|||
loading: true, // 首次加载loading
|
|||
hasMore: false, // 是否还有更多数据(根据后端分页逻辑调整,本例简单置false)
|
|||
pageNum: 1, // 当前页码(若需要分页)
|
|||
pageSize: 10, |
|||
total: 0, |
|||
baseUrl: baseUrl || '' // 图片前缀
|
|||
}, |
|||
|
|||
/** |
|||
* 生命周期函数--监听页面加载 |
|||
*/ |
|||
onLoad(options) { |
|||
this.getTodayList() |
|||
}, |
|||
|
|||
/** |
|||
* 获取今日问诊列表(第一页) |
|||
*/ |
|||
getTodayList() { |
|||
this.setData({ loading: false }) |
|||
http.today({ |
|||
data: { |
|||
pageNum: this.data.pageNum, |
|||
pageSize: this.data.pageSize |
|||
// 根据接口实际需要可添加其他参数
|
|||
}, |
|||
success: (res) => { |
|||
console.log('今日问诊接口返回:', res) |
|||
if (res && res.code === 200) { |
|||
const rows = res.rows || [] |
|||
const total = res.total || 0 |
|||
// 处理图片字段可能为空字符串或null
|
|||
rows.forEach(item => { |
|||
if (!item.images) item.images = '' |
|||
}) |
|||
this.setData({ |
|||
list: rows, |
|||
total: total, |
|||
hasMore: rows.length < total && rows.length >= this.data.pageSize // 简单判断
|
|||
}) |
|||
} else { |
|||
wx.showToast({ title: '数据加载失败', icon: 'none' }) |
|||
} |
|||
}, |
|||
fail: (err) => { |
|||
wx.showToast({ title: '网络错误', icon: 'none' }) |
|||
console.error(err) |
|||
}, |
|||
complete: () => { |
|||
this.setData({ loading: false }) |
|||
} |
|||
}) |
|||
}, |
|||
|
|||
/** |
|||
* 加载更多(上拉触底) |
|||
*/ |
|||
loadMore() { |
|||
if (!this.data.hasMore) return |
|||
// 如果有分页需求,可在此累加pageNum再次请求,并将新数据concat
|
|||
// 当前根据接口示例无分页参数,故简单提示
|
|||
wx.showToast({ title: '暂无更多', icon: 'none' }) |
|||
}, |
|||
|
|||
/** |
|||
* 跳转详情页 |
|||
*/ |
|||
// 查看详情
|
|||
goDetail: function (e) { |
|||
console.log(e); |
|||
const data = e.currentTarget.dataset.value |
|||
wx.navigateTo({ |
|||
url: `/pagesA/pages/askingSyDetails/askingSyDetails?data=${encodeURIComponent(JSON.stringify(data))}`, |
|||
}); |
|||
|
|||
}, |
|||
|
|||
|
|||
|
|||
|
|||
/** |
|||
* 预览图片 |
|||
*/ |
|||
previewImage(e) { |
|||
const { src, list } = e.currentTarget.dataset |
|||
wx.previewImage({ |
|||
current: src, // 当前显示图片
|
|||
urls: list // 所有图片列表
|
|||
}) |
|||
}, |
|||
|
|||
/** |
|||
* 下拉刷新(如果需要) |
|||
*/ |
|||
onPullDownRefresh() { |
|||
this.setData({ pageNum: 1 }, () => { |
|||
this.getTodayList() |
|||
wx.stopPullDownRefresh() |
|||
}) |
|||
}, |
|||
|
|||
/** |
|||
* 用户点击右上角分享 |
|||
*/ |
|||
onShareAppMessage() { |
|||
return { |
|||
title: '今日问诊列表', |
|||
path: '/pages/consult/today/today' |
|||
} |
|||
} |
|||
}) |
|||
@ -0,0 +1,4 @@ |
|||
{ |
|||
"navigationBarTitleText":"今日问诊列表", |
|||
"usingComponents": {} |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
<view class="container"> |
|||
<!-- 加载中提示 --> |
|||
<view wx:if="{{loading}}" class="loading"> |
|||
<text>加载中...</text> |
|||
</view> |
|||
|
|||
<!-- 空列表提示 --> |
|||
<view wx:elif="{{list.length === 0}}" class="empty"> |
|||
<text>暂无今日问诊</text> |
|||
</view> |
|||
|
|||
<!-- 问诊列表 --> |
|||
<scroll-view |
|||
wx:else |
|||
scroll-y |
|||
class="scroll-list" |
|||
bindscrolltolower="loadMore" |
|||
lower-threshold="50" |
|||
> |
|||
<view class="list"> |
|||
<view class="card" wx:for="{{list}}" wx:key="formId" data-value="{{item}}" bindtap="goDetail"> |
|||
<!-- 用户信息行:头像、姓名、时间、状态 --> |
|||
<view class="user-row"> |
|||
<image class="avatar" src="{{baseUrl + item.avatar}}" mode="aspectFill" lazy-load></image> |
|||
<view class="user-info"> |
|||
<text class="name">{{item.farmerName}}</text> |
|||
<text class="time">{{item.createdTime}}</text> |
|||
</view> |
|||
<view class="status" data-status="{{item.status}}">{{item.status}}</view> |
|||
</view> |
|||
|
|||
<!-- 病情描述卡片 --> |
|||
<view class="content-block"> |
|||
<view class="desc">{{item.description}}</view> |
|||
<!-- 动物标签 --> |
|||
<view class="tag-group"> |
|||
<text class="tag">{{item.animalType}}</text> |
|||
<text class="tag">{{item.animalGender}}</text> |
|||
<text class="tag">{{item.animalAge}}岁</text> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 底部互动信息 --> |
|||
<view class="card-footer"> |
|||
<text>浏览 {{item.viewCount || 0}}</text> |
|||
<text>回复 {{item.replyCount || 0}}</text> |
|||
</view> |
|||
</view> |
|||
</view> |
|||
|
|||
<!-- 加载更多 --> |
|||
<view class="load-more" wx:if="{{hasMore}}"> |
|||
<text>加载更多...</text> |
|||
</view> |
|||
<view class="no-more" wx:elif="{{list.length > 0}}"> |
|||
<text>没有更多了</text> |
|||
</view> |
|||
</scroll-view> |
|||
</view> |
|||
@ -0,0 +1,156 @@ |
|||
.container { |
|||
min-height: 100vh; |
|||
background-color: #f5f7fa; |
|||
padding: 0 20rpx; |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
.loading, .empty { |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
height: 300rpx; |
|||
color: #999; |
|||
font-size: 28rpx; |
|||
} |
|||
|
|||
.scroll-list { |
|||
height: 100vh; |
|||
} |
|||
|
|||
.list { |
|||
padding: 20rpx 0; |
|||
} |
|||
|
|||
.card { |
|||
background: #fff; |
|||
border-radius: 24rpx; |
|||
margin-bottom: 30rpx; |
|||
padding: 30rpx; |
|||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05); |
|||
} |
|||
|
|||
/* 用户行 */ |
|||
.user-row { |
|||
display: flex; |
|||
align-items: center; |
|||
margin-bottom: 24rpx; |
|||
position: relative; |
|||
} |
|||
|
|||
.avatar { |
|||
width: 72rpx; |
|||
height: 72rpx; |
|||
border-radius: 50%; |
|||
margin-right: 20rpx; |
|||
background-color: #eee; |
|||
} |
|||
|
|||
.user-info { |
|||
flex: 1; |
|||
display: flex; |
|||
flex-direction: column; |
|||
} |
|||
|
|||
.name { |
|||
font-size: 28rpx; |
|||
font-weight: 500; |
|||
color: #333; |
|||
margin-bottom: 4rpx; |
|||
} |
|||
|
|||
.time { |
|||
font-size: 22rpx; |
|||
color: #999; |
|||
} |
|||
|
|||
.status { |
|||
padding: 6rpx 20rpx; |
|||
background-color: #fff1f0; |
|||
border-radius: 30rpx; |
|||
font-size: 24rpx; |
|||
color: #f56c6c; |
|||
border: 1rpx solid #fbc4c4; |
|||
} |
|||
|
|||
/* 根据状态可设置不同颜色,例如 “未回复” 保持红色,“已回复”变绿色 */ |
|||
.status[data-status="未回复"] { |
|||
background-color: #fff1f0; |
|||
color: #f56c6c; |
|||
border-color: #fbc4c4; |
|||
} |
|||
.status[data-status="已回复"] { |
|||
background-color: #e8f7ef; |
|||
color: #2ecc71; |
|||
border-color: #a9e0c0; |
|||
} |
|||
|
|||
/* 内容块 */ |
|||
.content-block { |
|||
margin-bottom: 20rpx; |
|||
} |
|||
|
|||
.desc { |
|||
font-size: 30rpx; |
|||
color: #333; |
|||
line-height: 1.5; |
|||
margin-bottom: 20rpx; |
|||
word-break: break-word; |
|||
} |
|||
|
|||
.tag-group { |
|||
display: flex; |
|||
flex-wrap: wrap; |
|||
margin-bottom: 20rpx; |
|||
} |
|||
|
|||
.tag { |
|||
background-color: #f0f2f5; |
|||
padding: 6rpx 24rpx; |
|||
border-radius: 30rpx; |
|||
font-size: 24rpx; |
|||
color: #666; |
|||
margin-right: 16rpx; |
|||
margin-bottom: 10rpx; |
|||
} |
|||
|
|||
/* 图片九宫格简化版 */ |
|||
.image-grid { |
|||
display: flex; |
|||
flex-wrap: wrap; |
|||
margin-top: 10rpx; |
|||
} |
|||
|
|||
.grid-img { |
|||
width: 200rpx; |
|||
height: 200rpx; |
|||
border-radius: 16rpx; |
|||
margin-right: 16rpx; |
|||
margin-bottom: 16rpx; |
|||
background-color: #eee; |
|||
} |
|||
|
|||
/* 底部栏 */ |
|||
.card-footer { |
|||
display: flex; |
|||
align-items: center; |
|||
font-size: 24rpx; |
|||
color: #999; |
|||
border-top: 2rpx solid #f0f0f0; |
|||
padding-top: 20rpx; |
|||
margin-top: 10rpx; |
|||
} |
|||
|
|||
.card-footer text { |
|||
margin-right: 30rpx; |
|||
} |
|||
|
|||
|
|||
|
|||
/* 加载更多 */ |
|||
.load-more, .no-more { |
|||
text-align: center; |
|||
padding: 30rpx 0 50rpx; |
|||
font-size: 26rpx; |
|||
color: #aaa; |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue