Initial commit

This commit is contained in:
sjk
2025-11-17 13:32:54 +08:00
commit e788eab6eb
1659 changed files with 171560 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
# 调试页面使用说明
## 硬编码评论测试页面 (hardcoded-comment-test)
### 页面路径
`pages/debug/hardcoded-comment-test`
### 功能说明
这个页面用于测试和调试评论相关功能特别是商品ID验证逻辑。
### 主要功能
#### 1. 商品ID验证测试
- **输入框测试**: 可以手动输入任意商品ID进行验证测试
- **快速测试按钮**: 提供常见的测试用例
- 正常ID(1): 测试正常的正整数
- 零值(0): 测试零值是否被正确处理
- 空字符串: 测试空值情况
- 非数字(abc): 测试非数字字符串
- 负数(-1): 测试负数情况
- 小数(1.5): 测试小数情况
#### 2. 测试结果显示
- 显示每次测试的详细结果
- 包含测试时间、输入值、成功/失败状态
- 成功时显示返回的数据
- 失败时显示具体错误信息
#### 3. 评论组件显示测试
- 可以切换"有评论"和"无评论"模式
- 验证评论组件的显示逻辑
- 显示硬编码的评论数据用于UI测试
### 使用方法
1. 在微信开发者工具中打开小程序
2. 在控制台中输入以下代码跳转到调试页面:
```javascript
wx.navigateTo({
url: '/pages/debug/hardcoded-comment-test'
})
```
3. 或者在任意页面的JS文件中添加跳转代码
### 测试建议
1. **基础验证测试**: 使用快速测试按钮测试所有预设场景
2. **边界值测试**: 测试特殊值如 "0", "", "null", "undefined"
3. **类型测试**: 测试不同数据类型的输入
4. **观察日志**: 在开发者工具控制台查看详细的调试日志
### 调试日志说明
页面会在控制台输出详细的调试信息:
- `[调试页面]` 前缀: 调试页面相关日志
- `[fetchCommentsCount]` 前缀: 评论统计服务相关日志
- `[fetchComments]` 前缀: 评论列表服务相关日志
### 常见问题排查
1. **"商品ID必须是有效的正整数"错误**:
- 检查传入的productId值和类型
- 确认验证逻辑是否正确处理各种输入情况
2. **页面无法加载**:
- 确认页面已在app.json中注册
- 检查文件路径是否正确
3. **测试结果不显示**:
- 检查控制台是否有JavaScript错误
- 确认服务文件路径是否正确

View File

@@ -0,0 +1,189 @@
// pages/debug/api-test.js
const { fetchCommentsCount } = require('../../services/comments/fetchCommentsCount');
const { fetchComments } = require('../../services/comments/fetchComments');
Page({
data: {
spuId: 1, // 测试用的商品ID
testResults: {
statsApiCalled: false,
statsApiSuccess: false,
statsApiError: '',
statsRawData: null,
statsProcessedData: null,
listApiCalled: false,
listApiSuccess: false,
listApiError: '',
listRawData: null,
listProcessedData: null,
finalCommentsStatistics: null,
finalCommentsList: null,
shouldDisplay: false
}
},
onLoad: function (options) {
console.log('API测试页面加载');
if (options.spuId) {
this.setData({
spuId: parseInt(options.spuId)
});
}
},
// 测试评论统计API
async testCommentsStatistics() {
console.log('开始测试评论统计API...');
this.setData({
'testResults.statsApiCalled': true,
'testResults.statsApiSuccess': false,
'testResults.statsApiError': ''
});
try {
const result = await fetchCommentsCount(this.data.spuId);
console.log('评论统计API原始响应:', result);
// 模拟商品详情页的数据处理逻辑
const processedData = {
total_count: result.total_count || 0,
good_count: result.good_count || 0,
medium_count: result.medium_count || 0,
bad_count: result.bad_count || 0,
average_rating: result.average_rating || 0,
image_count: result.image_count || 0
};
const goodRate = processedData.total_count > 0 ?
Math.round((processedData.good_count / processedData.total_count) * 100) : 0;
const commentsStatistics = {
commentCount: processedData.total_count || 0,
goodCount: processedData.good_count || 0,
middleCount: processedData.medium_count || 0,
badCount: processedData.bad_count || 0,
goodRate: goodRate,
hasImageCount: processedData.image_count || 0,
};
this.setData({
'testResults.statsApiSuccess': true,
'testResults.statsRawData': result,
'testResults.statsProcessedData': processedData,
'testResults.finalCommentsStatistics': commentsStatistics,
'testResults.shouldDisplay': commentsStatistics.commentCount > 0
});
console.log('评论统计处理完成:', commentsStatistics);
} catch (error) {
console.error('评论统计API调用失败:', error);
this.setData({
'testResults.statsApiError': error.message || '未知错误'
});
}
},
// 测试评论列表API
async testCommentsList() {
console.log('开始测试评论列表API...');
this.setData({
'testResults.listApiCalled': true,
'testResults.listApiSuccess': false,
'testResults.listApiError': ''
});
try {
const result = await fetchComments({
productId: this.data.spuId,
page: 1,
pageSize: 3
});
console.log('评论列表API原始响应:', result);
// 模拟商品详情页的数据处理逻辑
let commentsList = [];
if (result.comments && Array.isArray(result.comments)) {
commentsList = result.comments.map(comment => ({
id: comment.id,
userName: comment.is_anonymous ? '匿名用户' : (comment.user_name || '用户'),
userHeadUrl: comment.user_avatar || 'https://tdesign.gtimg.com/miniprogram/template/retail/avatar/avatar1.png',
commentScore: comment.rating || 5,
commentContent: comment.content || '',
commentTime: comment.created_at ? this.formatTime(comment.created_at) : '',
specInfo: comment.product_spec || '',
commentResources: comment.images || [],
isAnonymity: comment.is_anonymous || false,
sellerReply: comment.reply_content || '',
goodsDetailInfo: ''
}));
}
this.setData({
'testResults.listApiSuccess': true,
'testResults.listRawData': result,
'testResults.listProcessedData': commentsList,
'testResults.finalCommentsList': commentsList
});
console.log('评论列表处理完成:', commentsList);
} catch (error) {
console.error('评论列表API调用失败:', error);
this.setData({
'testResults.listApiError': error.message || '未知错误'
});
}
},
// 运行完整测试
async runFullTest() {
console.log('开始运行完整API测试...');
await this.testCommentsStatistics();
await this.testCommentsList();
console.log('完整API测试完成');
},
// 清除测试结果
clearResults() {
this.setData({
testResults: {
statsApiCalled: false,
statsApiSuccess: false,
statsApiError: '',
statsRawData: null,
statsProcessedData: null,
listApiCalled: false,
listApiSuccess: false,
listApiError: '',
listRawData: null,
listProcessedData: null,
finalCommentsStatistics: null,
finalCommentsList: null,
shouldDisplay: false
}
});
},
// 格式化时间
formatTime(dateString) {
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
},
// 修改测试商品ID
onSpuIdInput(e) {
this.setData({
spuId: parseInt(e.detail.value) || 1
});
}
});

View File

@@ -0,0 +1,6 @@
{
"navigationBarTitleText": "评论API测试",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"backgroundColor": "#f5f5f5"
}

View File

@@ -0,0 +1,147 @@
<!--pages/debug/api-test.wxml-->
<view class="container">
<view class="header">
<text class="title">评论API测试页面</text>
</view>
<!-- 测试配置 -->
<view class="section">
<view class="section-title">测试配置</view>
<view class="config-item">
<text>商品ID (spuId): </text>
<input class="spu-input" type="number" value="{{spuId}}" bindinput="onSpuIdInput" />
</view>
</view>
<!-- 操作按钮 -->
<view class="section">
<view class="section-title">测试操作</view>
<view class="button-group">
<button class="test-btn" bindtap="testCommentsStatistics">测试评论统计API</button>
<button class="test-btn" bindtap="testCommentsList">测试评论列表API</button>
<button class="test-btn primary" bindtap="runFullTest">运行完整测试</button>
<button class="test-btn secondary" bindtap="clearResults">清除结果</button>
</view>
</view>
<!-- 评论统计API测试结果 -->
<view class="section">
<view class="section-title">评论统计API测试结果</view>
<view class="test-result">
<view class="result-item">
<text class="label">API调用状态:</text>
<text class="value {{testResults.statsApiCalled ? 'called' : 'not-called'}}">
{{testResults.statsApiCalled ? '已调用' : '未调用'}}
</text>
</view>
<view class="result-item" wx:if="{{testResults.statsApiCalled}}">
<text class="label">调用结果:</text>
<text class="value {{testResults.statsApiSuccess ? 'success' : 'error'}}">
{{testResults.statsApiSuccess ? '成功' : '失败'}}
</text>
</view>
<view class="result-item" wx:if="{{testResults.statsApiError}}">
<text class="label">错误信息:</text>
<text class="value error">{{testResults.statsApiError}}</text>
</view>
<view class="result-item" wx:if="{{testResults.statsRawData}}">
<text class="label">原始数据:</text>
<view class="json-data">{{testResults.statsRawData}}</view>
</view>
<view class="result-item" wx:if="{{testResults.finalCommentsStatistics}}">
<text class="label">处理后数据:</text>
<view class="json-data">{{testResults.finalCommentsStatistics}}</view>
</view>
<view class="result-item" wx:if="{{testResults.statsApiCalled}}">
<text class="label">显示条件:</text>
<text class="value {{testResults.shouldDisplay ? 'success' : 'error'}}">
commentCount > 0 = {{testResults.shouldDisplay ? 'true (应该显示)' : 'false (不应该显示)'}}
</text>
</view>
</view>
</view>
<!-- 评论列表API测试结果 -->
<view class="section">
<view class="section-title">评论列表API测试结果</view>
<view class="test-result">
<view class="result-item">
<text class="label">API调用状态:</text>
<text class="value {{testResults.listApiCalled ? 'called' : 'not-called'}}">
{{testResults.listApiCalled ? '已调用' : '未调用'}}
</text>
</view>
<view class="result-item" wx:if="{{testResults.listApiCalled}}">
<text class="label">调用结果:</text>
<text class="value {{testResults.listApiSuccess ? 'success' : 'error'}}">
{{testResults.listApiSuccess ? '成功' : '失败'}}
</text>
</view>
<view class="result-item" wx:if="{{testResults.listApiError}}">
<text class="label">错误信息:</text>
<text class="value error">{{testResults.listApiError}}</text>
</view>
<view class="result-item" wx:if="{{testResults.listRawData}}">
<text class="label">原始数据:</text>
<view class="json-data">{{testResults.listRawData}}</view>
</view>
<view class="result-item" wx:if="{{testResults.finalCommentsList}}">
<text class="label">处理后评论列表 ({{testResults.finalCommentsList.length}}条):</text>
<view class="json-data">{{testResults.finalCommentsList}}</view>
</view>
</view>
</view>
<!-- 模拟评论组件显示 -->
<view class="section" wx:if="{{testResults.finalCommentsStatistics}}">
<view class="section-title">模拟评论组件显示</view>
<view class="comment-simulation">
<view class="display-condition">
<text>显示条件: commentCount({{testResults.finalCommentsStatistics.commentCount}}) > 0 = {{testResults.shouldDisplay}}</text>
</view>
<!-- 模拟的评论组件 -->
<view class="comments-wrap" wx:if="{{testResults.shouldDisplay}}">
<view class="comments-head">
<view class="comments-title">
<text class="comments-title-label">商品评价</text>
<text class="comments-title-count">({{testResults.finalCommentsStatistics.commentCount}})</text>
</view>
<view class="comments-rate-wrap">
<text class="comments-rate-label">好评率</text>
<text class="comments-rate-num">{{testResults.finalCommentsStatistics.goodRate}}%</text>
</view>
</view>
<view class="comment-item-wrap" wx:for="{{testResults.finalCommentsList}}" wx:key="id" wx:if="{{index < 3}}">
<view class="comment-item-head">
<image class="comment-item-avatar" src="{{item.userHeadUrl}}" />
<view class="comment-item-info">
<text class="comment-item-name">{{item.userName}}</text>
<view class="comment-item-rate">
<text class="comment-item-score">{{item.commentScore}}分</text>
</view>
</view>
</view>
<view class="comment-item-content">
<text>{{item.commentContent}}</text>
</view>
<view class="comment-item-time">{{item.commentTime}}</view>
</view>
</view>
<view class="no-comments" wx:else>
<text>评论组件不显示 (commentCount = {{testResults.finalCommentsStatistics.commentCount}})</text>
</view>
</view>
</view>
</view>

View File

@@ -0,0 +1,255 @@
/* pages/debug/api-test.wxss */
.container {
padding: 20rpx;
background-color: #f5f5f5;
min-height: 100vh;
}
.header {
text-align: center;
margin-bottom: 30rpx;
}
.title {
font-size: 36rpx;
font-weight: bold;
color: #333;
}
.section {
background-color: white;
margin-bottom: 20rpx;
border-radius: 10rpx;
padding: 20rpx;
}
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
border-bottom: 2rpx solid #eee;
padding-bottom: 10rpx;
}
/* 配置区域 */
.config-item {
display: flex;
align-items: center;
margin-bottom: 10rpx;
}
.spu-input {
border: 2rpx solid #ddd;
padding: 10rpx;
border-radius: 5rpx;
margin-left: 10rpx;
width: 200rpx;
}
/* 按钮组 */
.button-group {
display: flex;
flex-wrap: wrap;
gap: 10rpx;
}
.test-btn {
flex: 1;
min-width: 200rpx;
margin: 5rpx;
padding: 20rpx;
border-radius: 10rpx;
font-size: 28rpx;
border: none;
}
.test-btn.primary {
background-color: #07c160;
color: white;
}
.test-btn.secondary {
background-color: #ff6b6b;
color: white;
}
/* 测试结果 */
.test-result {
background-color: #f9f9f9;
padding: 15rpx;
border-radius: 8rpx;
}
.result-item {
margin-bottom: 15rpx;
display: flex;
flex-direction: column;
}
.label {
font-weight: bold;
color: #666;
margin-bottom: 5rpx;
}
.value {
color: #333;
}
.value.called {
color: #07c160;
}
.value.not-called {
color: #999;
}
.value.success {
color: #07c160;
}
.value.error {
color: #ff6b6b;
}
.json-data {
background-color: #f0f0f0;
padding: 10rpx;
border-radius: 5rpx;
font-family: monospace;
font-size: 24rpx;
word-break: break-all;
max-height: 300rpx;
overflow-y: auto;
}
/* 评论组件模拟 */
.comment-simulation {
border: 2rpx dashed #ddd;
padding: 20rpx;
border-radius: 10rpx;
}
.display-condition {
background-color: #e3f2fd;
padding: 10rpx;
border-radius: 5rpx;
margin-bottom: 15rpx;
text-align: center;
font-weight: bold;
}
.no-comments {
text-align: center;
color: #999;
padding: 40rpx;
background-color: #f9f9f9;
border-radius: 10rpx;
}
/* 评论组件样式 (复制自商品详情页) */
.comments-wrap {
background-color: #fff;
border-radius: 16rpx;
padding: 32rpx;
margin-top: 20rpx;
}
.comments-head {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 32rpx;
}
.comments-title {
display: flex;
align-items: center;
}
.comments-title-label {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.comments-title-count {
font-size: 28rpx;
color: #666;
margin-left: 8rpx;
}
.comments-rate-wrap {
display: flex;
align-items: center;
}
.comments-rate-label {
font-size: 28rpx;
color: #666;
margin-right: 8rpx;
}
.comments-rate-num {
font-size: 28rpx;
color: #ff6b35;
font-weight: 600;
}
.comment-item-wrap {
border-bottom: 1rpx solid #f0f0f0;
padding-bottom: 24rpx;
margin-bottom: 24rpx;
}
.comment-item-wrap:last-child {
border-bottom: none;
margin-bottom: 0;
}
.comment-item-head {
display: flex;
align-items: center;
margin-bottom: 16rpx;
}
.comment-item-avatar {
width: 64rpx;
height: 64rpx;
border-radius: 50%;
margin-right: 16rpx;
}
.comment-item-info {
flex: 1;
}
.comment-item-name {
font-size: 28rpx;
color: #333;
display: block;
margin-bottom: 4rpx;
}
.comment-item-rate {
display: flex;
align-items: center;
}
.comment-item-score {
font-size: 24rpx;
color: #ff6b35;
}
.comment-item-content {
font-size: 28rpx;
color: #666;
line-height: 1.6;
margin-bottom: 12rpx;
}
.comment-item-time {
font-size: 24rpx;
color: #999;
}

View File

@@ -0,0 +1,186 @@
const { fetchComments } = require('../../services/comments/fetchComments');
const { fetchCommentsCount } = require('../../services/comments/fetchCommentsCount');
Page({
data: {
spuId: 1,
commentsList: [],
commentsStatistics: {
badCount: 0,
commentCount: 0,
goodCount: 0,
goodRate: 0,
hasImageCount: 0,
middleCount: 0,
},
isLoading: false,
debugInfo: {
apiCalled: false,
dataReceived: false,
errorMessage: '',
rawData: null,
processedData: null
}
},
onLoad() {
console.log('评论显示测试页面加载');
this.loadCommentData();
},
async loadCommentData() {
this.setData({
isLoading: true,
'debugInfo.apiCalled': false,
'debugInfo.dataReceived': false,
'debugInfo.errorMessage': '',
'debugInfo.rawData': null,
'debugInfo.processedData': null
});
try {
// 获取评论统计
await this.getCommentsStatistics(this.data.spuId);
// 获取评论列表
await this.getCommentsList(this.data.spuId);
this.setData({
isLoading: false,
'debugInfo.dataReceived': true
});
} catch (error) {
console.error('加载评论数据失败:', error);
this.setData({
isLoading: false,
'debugInfo.errorMessage': error.message || '未知错误'
});
}
},
// 获取评论统计数据 - 复制商品详情页面的逻辑
async getCommentsStatistics(spuId) {
try {
this.setData({ 'debugInfo.apiCalled': true });
console.log('调用 fetchCommentsCountspuId:', spuId);
const res = await fetchCommentsCount(spuId);
console.log('fetchCommentsCount 返回结果:', res);
this.setData({ 'debugInfo.rawData': res });
if (res) {
const goodRate = res.total_count > 0 ? Math.round((res.good_count / res.total_count) * 100) : 0;
const commentsStatistics = {
commentCount: res.total_count || 0,
goodCount: res.good_count || 0,
middleCount: res.medium_count || 0,
badCount: res.bad_count || 0,
goodRate: goodRate,
hasImageCount: res.image_count || 0,
};
console.log('处理后的统计数据:', commentsStatistics);
console.log('显示条件 (commentCount > 0):', commentsStatistics.commentCount > 0);
this.setData({
commentsStatistics: commentsStatistics,
'debugInfo.processedData': commentsStatistics
});
}
} catch (error) {
console.error('获取评论统计失败:', error);
this.setData({
'debugInfo.errorMessage': error.message || '获取评论统计失败',
commentsStatistics: {
commentCount: 0,
goodCount: 0,
middleCount: 0,
badCount: 0,
goodRate: 0,
hasImageCount: 0,
}
});
}
},
// 获取评论列表数据 - 复制商品详情页面的逻辑
async getCommentsList(spuId) {
try {
console.log('调用 fetchComments参数:', { productId: spuId, page: 1, pageSize: 3 });
const res = await fetchComments({ productId: spuId, page: 1, pageSize: 3 });
console.log('fetchComments 返回结果:', res);
if (res && res.comments) {
// 转换评论数据格式
const commentsList = res.comments.map(comment => ({
id: comment.id,
userName: comment.is_anonymous ? '匿名用户' : (comment.user_name || '用户'),
userHeadUrl: comment.user_avatar || 'https://tdesign.gtimg.com/miniprogram/template/retail/avatar/avatar1.png',
commentScore: comment.rating || 5,
commentContent: comment.content || '',
commentTime: comment.created_at ? this.formatTime(comment.created_at) : '',
specInfo: comment.product_spec || '',
commentResources: (comment.images || []).map(imageUrl => ({
src: imageUrl,
type: 'image'
})),
isAnonymity: comment.is_anonymous || false,
sellerReply: comment.reply_content || '',
goodsDetailInfo: ''
}));
console.log('处理后的评论列表:', commentsList);
this.setData({
commentsList: commentsList
});
}
} catch (error) {
console.error('获取评论列表失败:', error);
this.setData({
commentsList: []
});
}
},
// 格式化时间
formatTime(dateString) {
if (!dateString) return '';
try {
const date = new Date(dateString);
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
} catch (error) {
return dateString;
}
},
// 重新加载数据
reloadData() {
this.loadCommentData();
},
// 清除数据
clearData() {
this.setData({
commentsList: [],
commentsStatistics: {
badCount: 0,
commentCount: 0,
goodCount: 0,
goodRate: 0,
hasImageCount: 0,
middleCount: 0,
},
debugInfo: {
apiCalled: false,
dataReceived: false,
errorMessage: '',
rawData: null,
processedData: null
}
});
}
});

View File

@@ -0,0 +1,4 @@
{
"navigationBarTitleText": "评论组件显示测试",
"backgroundColor": "#f5f5f5"
}

View File

@@ -0,0 +1,92 @@
<!--评论显示测试页面-->
<view class="container">
<view class="header">
<text class="title">评论组件显示测试</text>
<text class="subtitle">模拟商品详情页面的评论组件</text>
</view>
<!-- 调试信息 -->
<view class="debug-section">
<text class="section-title">调试信息</text>
<view class="debug-item">
<text class="debug-label">API已调用:</text>
<text class="debug-value {{debugInfo.apiCalled ? 'success' : 'error'}}">{{debugInfo.apiCalled ? '是' : '否'}}</text>
</view>
<view class="debug-item">
<text class="debug-label">数据已接收:</text>
<text class="debug-value {{debugInfo.dataReceived ? 'success' : 'error'}}">{{debugInfo.dataReceived ? '是' : '否'}}</text>
</view>
<view class="debug-item" wx:if="{{debugInfo.errorMessage}}">
<text class="debug-label">错误信息:</text>
<text class="debug-value error">{{debugInfo.errorMessage}}</text>
</view>
<view class="debug-item">
<text class="debug-label">评论数量:</text>
<text class="debug-value">{{commentsStatistics.commentCount}}</text>
</view>
<view class="debug-item">
<text class="debug-label">显示条件:</text>
<text class="debug-value {{commentsStatistics.commentCount > 0 ? 'success' : 'error'}}">
commentCount > 0 = {{commentsStatistics.commentCount > 0}}
</text>
</view>
</view>
<!-- 操作按钮 -->
<view class="action-section">
<button class="action-btn" bindtap="reloadData" disabled="{{isLoading}}">
{{isLoading ? '加载中...' : '重新加载'}}
</button>
<button class="action-btn secondary" bindtap="clearData">清除数据</button>
</view>
<!-- 评论组件 - 复制商品详情页面的结构 -->
<view class="comment-component-section">
<text class="section-title">评论组件 ({{commentsStatistics.commentCount > 0 ? '应该显示' : '应该隐藏'}})</text>
<!-- 这里是关键的显示条件 -->
<view wx:if="{{commentsStatistics.commentCount > 0}}" class="comments-wrap">
<view class="comments-head">
<view class="comments-title-wrap">
<text class="comments-title-label">商品评价</text>
<text class="comments-title-count">({{commentsStatistics.commentCount}})</text>
</view>
<view class="comments-rate-wrap">
<text class="comments-good-rate">{{commentsStatistics.goodRate}}%好评</text>
</view>
</view>
<!-- 评论列表 -->
<view wx:for="{{commentsList}}" wx:key="id" class="comment-item-wrap">
<view class="comment-item-head">
<image class="comment-item-avatar" src="{{item.userHeadUrl}}" mode="aspectFill"></image>
<view class="comment-head-right">
<text class="comment-username">{{item.userName}}</text>
<view class="comment-rating">
<text wx:for="{{[1,2,3,4,5]}}" wx:for-item="star" wx:key="star"
class="star {{star <= item.commentScore ? 'filled' : ''}}">★</text>
</view>
</view>
</view>
<view class="comment-item-content">{{item.commentContent}}</view>
</view>
</view>
<!-- 当没有评论时显示的内容 -->
<view wx:else class="no-comments">
<text class="no-comments-text">暂无评论 (commentCount = {{commentsStatistics.commentCount}})</text>
</view>
</view>
<!-- 原始数据显示 -->
<view class="raw-data-section" wx:if="{{debugInfo.rawData}}">
<text class="section-title">原始API数据</text>
<view class="data-display">{{debugInfo.rawData}}</view>
</view>
<!-- 处理后数据显示 -->
<view class="processed-data-section" wx:if="{{debugInfo.processedData}}">
<text class="section-title">处理后数据</text>
<view class="data-display">{{debugInfo.processedData}}</view>
</view>
</view>

View File

@@ -0,0 +1,265 @@
/* 评论显示测试页面样式 */
.container {
padding: 20rpx;
background-color: #f5f5f5;
min-height: 100vh;
}
.header {
text-align: center;
margin-bottom: 30rpx;
padding: 20rpx;
background: #fff;
border-radius: 16rpx;
}
.title {
display: block;
font-size: 36rpx;
font-weight: 600;
color: #333;
margin-bottom: 10rpx;
}
.subtitle {
display: block;
font-size: 26rpx;
color: #666;
}
.section-title {
display: block;
font-size: 30rpx;
font-weight: 600;
color: #333;
margin-bottom: 20rpx;
padding-bottom: 10rpx;
border-bottom: 2rpx solid #e0e0e0;
}
/* 调试信息样式 */
.debug-section {
background: #fff;
padding: 20rpx;
margin-bottom: 20rpx;
border-radius: 16rpx;
border-left: 4rpx solid #2196F3;
}
.debug-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10rpx 0;
border-bottom: 1rpx solid #f0f0f0;
}
.debug-item:last-child {
border-bottom: none;
}
.debug-label {
font-size: 26rpx;
color: #666;
font-weight: 500;
}
.debug-value {
font-size: 26rpx;
color: #333;
font-weight: 600;
}
.debug-value.success {
color: #4CAF50;
}
.debug-value.error {
color: #F44336;
}
/* 操作按钮样式 */
.action-section {
display: flex;
gap: 20rpx;
margin-bottom: 30rpx;
}
.action-btn {
flex: 1;
height: 80rpx;
line-height: 80rpx;
background: #2196F3;
color: #fff;
border: none;
border-radius: 12rpx;
font-size: 28rpx;
font-weight: 500;
}
.action-btn.secondary {
background: #666;
}
.action-btn[disabled] {
background: #ccc;
}
/* 评论组件样式 */
.comment-component-section {
background: #fff;
padding: 20rpx;
margin-bottom: 20rpx;
border-radius: 16rpx;
}
/* 复制商品详情页面的评论样式 */
.comments-wrap {
margin: 20rpx 0;
padding: 28rpx;
background-color: #fff;
border-radius: 16rpx;
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.06);
border: 1rpx solid #f0f0f0;
}
.comments-wrap .comments-head {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #f5f5f5;
}
.comments-wrap .comments-head .comments-title-wrap {
display: flex;
align-items: center;
}
.comments-title-label {
color: #222222;
font-size: 30rpx;
font-weight: 600;
line-height: 1;
}
.comments-title-count {
color: #666666;
font-size: 26rpx;
font-weight: 400;
line-height: 1;
margin-left: 8rpx;
}
.comments-rate-wrap {
display: flex;
justify-content: center;
align-items: center;
background: #fff5f5;
padding: 8rpx 16rpx;
border-radius: 20rpx;
border: 1rpx solid #ffe5e5;
}
.comments-rate-wrap .comments-good-rate {
color: #fa4126;
font-size: 24rpx;
font-weight: 500;
line-height: 1;
}
.comment-item-wrap {
margin-top: 24rpx;
padding: 20rpx;
background: #fafafa;
border-radius: 12rpx;
border: 1rpx solid #f0f0f0;
}
.comment-item-wrap .comment-item-head {
display: flex;
flex-direction: row;
align-items: center;
}
.comment-item-wrap .comment-item-head .comment-item-avatar {
width: 60rpx;
height: 60rpx;
border-radius: 30rpx;
border: 2rpx solid #fff;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.comment-item-wrap .comment-item-head .comment-head-right {
margin-left: 20rpx;
flex: 1;
}
.comment-head-right .comment-username {
font-size: 26rpx;
color: #333333;
line-height: 1.2;
font-weight: 500;
margin-bottom: 6rpx;
display: block;
}
.comment-rating {
display: flex;
align-items: center;
}
.star {
font-size: 24rpx;
color: #ddd;
margin-right: 2rpx;
}
.star.filled {
color: #FFD700;
}
.comment-item-wrap .comment-item-content {
margin-top: 16rpx;
color: #555555;
line-height: 1.5;
font-size: 26rpx;
font-weight: 400;
padding: 16rpx;
background: #fff;
border-radius: 8rpx;
border-left: 3rpx solid #fa4126;
}
.no-comments {
text-align: center;
padding: 60rpx 20rpx;
background: #f9f9f9;
border-radius: 12rpx;
border: 2rpx dashed #ddd;
}
.no-comments-text {
font-size: 28rpx;
color: #999;
}
/* 数据显示样式 */
.raw-data-section,
.processed-data-section {
background: #fff;
padding: 20rpx;
margin-bottom: 20rpx;
border-radius: 16rpx;
}
.data-display {
background: #f5f5f5;
padding: 20rpx;
border-radius: 8rpx;
font-size: 24rpx;
color: #333;
word-break: break-all;
white-space: pre-wrap;
}

View File

@@ -0,0 +1,106 @@
// 评论服务测试页面
const { fetchComments } = require('../../services/comments/fetchComments');
const { fetchCommentsCount } = require('../../services/comments/fetchCommentsCount');
Page({
data: {
testResults: [],
isLoading: false
},
onLoad() {
console.log('评论测试页面加载');
},
// 测试评论统计
async testCommentsCount() {
this.setData({ isLoading: true });
const results = [...this.data.testResults];
try {
console.log('开始测试 fetchCommentsCount...');
const result = await fetchCommentsCount(1);
console.log('fetchCommentsCount 结果:', result);
// 模拟商品详情页面的数据处理逻辑
const goodRate = result.total_count > 0 ? Math.round((result.good_count / result.total_count) * 100) : 0;
const commentsStatistics = {
commentCount: result.total_count || 0,
goodCount: result.good_count || 0,
middleCount: result.medium_count || 0,
badCount: result.bad_count || 0,
goodRate: goodRate,
hasImageCount: result.image_count || 0,
};
console.log('处理后的统计数据:', commentsStatistics);
console.log('显示条件 (commentCount > 0):', commentsStatistics.commentCount > 0);
results.push({
test: 'fetchCommentsCount',
status: 'success',
data: {
raw: result,
processed: commentsStatistics,
shouldShow: commentsStatistics.commentCount > 0
},
time: new Date().toLocaleTimeString()
});
} catch (error) {
console.error('fetchCommentsCount 错误:', error);
results.push({
test: 'fetchCommentsCount',
status: 'error',
error: error.message,
time: new Date().toLocaleTimeString()
});
}
this.setData({ testResults: results, isLoading: false });
},
// 测试评论列表
async testCommentsList() {
this.setData({ isLoading: true });
const results = [...this.data.testResults];
try {
console.log('开始测试 fetchComments...');
const result = await fetchComments({
productId: 1,
page: 1,
page_size: 3
});
console.log('fetchComments 结果:', result);
results.push({
test: 'fetchComments',
status: 'success',
data: result,
time: new Date().toLocaleTimeString()
});
} catch (error) {
console.error('fetchComments 错误:', error);
results.push({
test: 'fetchComments',
status: 'error',
error: error.message,
time: new Date().toLocaleTimeString()
});
}
this.setData({ testResults: results, isLoading: false });
},
// 清空测试结果
clearResults() {
this.setData({ testResults: [] });
},
// 运行所有测试
async runAllTests() {
this.clearResults();
await this.testCommentsCount();
await this.testCommentsList();
}
});

View File

@@ -0,0 +1,3 @@
{
"usingComponents": {}
}

View File

@@ -0,0 +1,51 @@
<!--评论服务测试页面-->
<view class="container">
<view class="header">
<text class="title">评论服务测试</text>
<text class="subtitle">测试 fetchComments 和 fetchCommentsCount 导入修复</text>
</view>
<view class="test-buttons">
<button class="test-btn" bindtap="testCommentsCount" disabled="{{isLoading}}">
测试评论统计
</button>
<button class="test-btn" bindtap="testCommentsList" disabled="{{isLoading}}">
测试评论列表
</button>
<button class="test-btn primary" bindtap="runAllTests" disabled="{{isLoading}}">
运行所有测试
</button>
<button class="test-btn secondary" bindtap="clearResults">
清空结果
</button>
</view>
<view class="loading" wx:if="{{isLoading}}">
<text>测试中...</text>
</view>
<view class="results" wx:if="{{testResults.length > 0}}">
<text class="results-title">测试结果:</text>
<view class="result-item" wx:for="{{testResults}}" wx:key="index">
<view class="result-header">
<text class="test-name">{{item.test}}</text>
<text class="test-status {{item.status}}">{{item.status}}</text>
<text class="test-time">{{item.time}}</text>
</view>
<view class="result-content" wx:if="{{item.status === 'success'}}">
<text class="data-label">返回数据:</text>
<text class="data-content">{{item.data}}</text>
</view>
<view class="result-content error" wx:if="{{item.status === 'error'}}">
<text class="error-label">错误信息:</text>
<text class="error-content">{{item.error}}</text>
</view>
</view>
</view>
<view class="empty" wx:if="{{testResults.length === 0 && !isLoading}}">
<text>点击上方按钮开始测试</text>
</view>
</view>

View File

@@ -0,0 +1,162 @@
/* 评论服务测试页面样式 */
.container {
padding: 20rpx;
background-color: #f5f5f5;
min-height: 100vh;
}
.header {
text-align: center;
margin-bottom: 40rpx;
padding: 30rpx;
background-color: white;
border-radius: 10rpx;
box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.1);
}
.title {
display: block;
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 10rpx;
}
.subtitle {
display: block;
font-size: 28rpx;
color: #666;
}
.test-buttons {
display: flex;
flex-direction: column;
gap: 20rpx;
margin-bottom: 40rpx;
}
.test-btn {
padding: 20rpx;
border-radius: 10rpx;
font-size: 30rpx;
border: none;
background-color: white;
color: #333;
box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.1);
}
.test-btn.primary {
background-color: #07c160;
color: white;
}
.test-btn.secondary {
background-color: #ff6b6b;
color: white;
}
.test-btn:disabled {
opacity: 0.6;
}
.loading {
text-align: center;
padding: 40rpx;
background-color: white;
border-radius: 10rpx;
margin-bottom: 20rpx;
}
.results {
background-color: white;
border-radius: 10rpx;
padding: 30rpx;
box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.1);
}
.results-title {
display: block;
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
}
.result-item {
border: 1rpx solid #eee;
border-radius: 8rpx;
padding: 20rpx;
margin-bottom: 20rpx;
}
.result-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15rpx;
}
.test-name {
font-size: 28rpx;
font-weight: bold;
color: #333;
}
.test-status {
padding: 8rpx 16rpx;
border-radius: 20rpx;
font-size: 24rpx;
color: white;
}
.test-status.success {
background-color: #07c160;
}
.test-status.error {
background-color: #ff6b6b;
}
.test-time {
font-size: 24rpx;
color: #999;
}
.result-content {
background-color: #f8f9fa;
padding: 15rpx;
border-radius: 6rpx;
}
.result-content.error {
background-color: #fff5f5;
}
.data-label, .error-label {
display: block;
font-size: 26rpx;
font-weight: bold;
color: #333;
margin-bottom: 8rpx;
}
.data-content {
font-size: 24rpx;
color: #666;
word-break: break-all;
}
.error-content {
font-size: 24rpx;
color: #e53e3e;
word-break: break-all;
}
.empty {
text-align: center;
padding: 60rpx;
background-color: white;
border-radius: 10rpx;
color: #999;
font-size: 28rpx;
}

View File

@@ -0,0 +1,230 @@
// pages/debug/hardcoded-comment-test.js
Page({
data: {
// 商品ID测试相关
testProductId: '1',
testResults: [],
// 硬编码的评论统计数据 - 确保有评论
commentsStatistics: {
commentCount: 5,
goodCount: 4,
middleCount: 1,
badCount: 0,
goodRate: 80,
hasImageCount: 2,
},
// 硬编码的评论列表数据
commentsList: [
{
id: 1,
userName: '测试用户1',
userHeadUrl: 'https://tdesign.gtimg.com/miniprogram/template/retail/avatar/avatar1.png',
commentScore: 5,
commentContent: '商品质量很好,物流也很快!',
commentTime: '2024-01-15',
specInfo: '颜色:红色 尺寸:M',
commentResources: [],
isAnonymity: false,
sellerReply: '',
goodsDetailInfo: ''
},
{
id: 2,
userName: '测试用户2',
userHeadUrl: 'https://tdesign.gtimg.com/miniprogram/template/retail/avatar/avatar2.png',
commentScore: 4,
commentContent: '整体不错,性价比很高,推荐购买!',
commentTime: '2024-01-14',
specInfo: '颜色:蓝色 尺寸:L',
commentResources: ['https://example.com/image1.jpg'],
isAnonymity: false,
sellerReply: '感谢您的好评!',
goodsDetailInfo: ''
},
{
id: 3,
userName: '匿名用户',
userHeadUrl: 'https://tdesign.gtimg.com/miniprogram/template/retail/avatar/avatar3.png',
commentScore: 3,
commentContent: '一般般,还可以吧。',
commentTime: '2024-01-13',
specInfo: '颜色:绿色 尺寸:S',
commentResources: [],
isAnonymity: true,
sellerReply: '',
goodsDetailInfo: ''
}
],
// 测试状态
testMode: 'with-comments', // 'with-comments' 或 'no-comments'
debugInfo: {
commentCount: 5,
displayCondition: true,
timestamp: ''
}
},
onLoad: function (options) {
console.log('硬编码评论测试页面加载');
this.updateDebugInfo();
},
// 更新调试信息
updateDebugInfo() {
const { commentsStatistics } = this.data;
this.setData({
'debugInfo.commentCount': commentsStatistics.commentCount,
'debugInfo.displayCondition': commentsStatistics.commentCount > 0,
'debugInfo.timestamp': new Date().toLocaleTimeString()
});
console.log('调试信息更新:', {
commentCount: commentsStatistics.commentCount,
displayCondition: commentsStatistics.commentCount > 0,
shouldShow: commentsStatistics.commentCount > 0 ? '应该显示' : '不应该显示'
});
},
// 切换测试模式
switchTestMode() {
const newMode = this.data.testMode === 'with-comments' ? 'no-comments' : 'with-comments';
if (newMode === 'no-comments') {
// 设置为无评论状态
this.setData({
testMode: newMode,
commentsStatistics: {
commentCount: 0,
goodCount: 0,
middleCount: 0,
badCount: 0,
goodRate: 0,
hasImageCount: 0,
},
commentsList: []
});
} else {
// 设置为有评论状态
this.setData({
testMode: newMode,
commentsStatistics: {
commentCount: 5,
goodCount: 4,
middleCount: 1,
badCount: 0,
goodRate: 80,
hasImageCount: 2,
},
commentsList: [
{
id: 1,
userName: '测试用户1',
userHeadUrl: 'https://tdesign.gtimg.com/miniprogram/template/retail/avatar/avatar1.png',
commentScore: 5,
commentContent: '商品质量很好,物流也很快!',
commentTime: '2024-01-15',
specInfo: '颜色:红色 尺寸:M',
commentResources: [],
isAnonymity: false,
sellerReply: '',
goodsDetailInfo: ''
},
{
id: 2,
userName: '测试用户2',
userHeadUrl: 'https://tdesign.gtimg.com/miniprogram/template/retail/avatar/avatar2.png',
commentScore: 4,
commentContent: '整体不错,性价比很高,推荐购买!',
commentTime: '2024-01-14',
specInfo: '颜色:蓝色 尺寸:L',
commentResources: ['https://example.com/image1.jpg'],
isAnonymity: false,
sellerReply: '感谢您的好评!',
goodsDetailInfo: ''
},
{
id: 3,
userName: '匿名用户',
userHeadUrl: 'https://tdesign.gtimg.com/miniprogram/template/retail/avatar/avatar3.png',
commentScore: 3,
commentContent: '一般般,还可以吧。',
commentTime: '2024-01-13',
specInfo: '颜色:绿色 尺寸:S',
commentResources: [],
isAnonymity: true,
sellerReply: '',
goodsDetailInfo: ''
}
]
});
}
this.updateDebugInfo();
},
// 跳转到评论列表页面(占位函数)
navToCommentsListPage() {
console.log('跳转到评论列表页面');
wx.showToast({
title: '跳转到评论列表',
icon: 'none'
});
},
// 输入框值变化
onProductIdInput(e) {
this.setData({
testProductId: e.detail.value
});
},
// 测试商品ID验证
async testProductIdValidation() {
const { testProductId } = this.data;
console.log(`[调试页面] 开始测试商品ID: "${testProductId}"`);
const testResult = {
productId: testProductId,
timestamp: new Date().toLocaleTimeString(),
success: false,
error: null,
data: null
};
try {
// 导入评论服务
const { fetchCommentsCount } = require('../../services/comments/fetchCommentsCount');
console.log(`[调试页面] 调用 fetchCommentsCount参数: "${testProductId}"`);
const result = await fetchCommentsCount(testProductId);
testResult.success = true;
testResult.data = result;
console.log(`[调试页面] 测试成功:`, result);
} catch (error) {
testResult.success = false;
testResult.error = error.message;
console.error(`[调试页面] 测试失败:`, error);
}
// 更新测试结果
const testResults = [testResult, ...this.data.testResults.slice(0, 9)]; // 保留最近10条
this.setData({ testResults });
},
// 快速测试预设值
async quickTest(e) {
const testValue = e.currentTarget.dataset.value;
this.setData({ testProductId: testValue });
await this.testProductIdValidation();
},
// 清空测试结果
clearTestResults() {
this.setData({ testResults: [] });
}
});

View File

@@ -0,0 +1,6 @@
{
"navigationBarTitleText": "硬编码评论测试",
"navigationBarBackgroundColor": "#ffffff",
"navigationBarTextStyle": "black",
"backgroundColor": "#f5f5f5"
}

View File

@@ -0,0 +1,175 @@
<!--pages/debug/hardcoded-comment-test.wxml-->
<view class="container">
<view class="header">
<text class="title">硬编码评论组件测试</text>
<text class="subtitle">使用硬编码数据测试评论组件显示</text>
</view>
<!-- 测试信息 -->
<view class="section">
<view class="section-title">测试信息</view>
<view class="test-info">
<view class="info-item">
<text class="label">当前模式:</text>
<text class="value">{{testMode === 'with-comments' ? '有评论模式' : '无评论模式'}}</text>
</view>
<view class="info-item">
<text class="label">评论数量:</text>
<text class="value">{{debugInfo.commentCount}}</text>
</view>
<view class="info-item">
<text class="label">显示条件:</text>
<text class="value {{debugInfo.displayCondition ? 'success' : 'error'}}">
commentCount({{debugInfo.commentCount}}) > 0 = {{debugInfo.displayCondition ? 'true (应该显示)' : 'false (不应该显示)'}}
</text>
</view>
<view class="info-item">
<text class="label">更新时间:</text>
<text class="value">{{debugInfo.timestamp}}</text>
</view>
</view>
</view>
<!-- 商品ID测试 -->
<view class="section">
<view class="section-title">商品ID验证测试</view>
<!-- 输入区域 -->
<view class="test-input-area">
<view class="input-row">
<text class="input-label">测试商品ID:</text>
<input class="test-input"
value="{{testProductId}}"
bindinput="onProductIdInput"
placeholder="输入要测试的商品ID" />
</view>
<button class="test-btn" bindtap="testProductIdValidation">测试验证</button>
</view>
<!-- 快速测试按钮 -->
<view class="quick-test-area">
<text class="quick-test-label">快速测试:</text>
<view class="quick-test-buttons">
<button class="quick-btn" bindtap="quickTest" data-value="1">正常ID(1)</button>
<button class="quick-btn" bindtap="quickTest" data-value="0">零值(0)</button>
<button class="quick-btn" bindtap="quickTest" data-value="">空字符串</button>
<button class="quick-btn" bindtap="quickTest" data-value="abc">非数字(abc)</button>
<button class="quick-btn" bindtap="quickTest" data-value="-1">负数(-1)</button>
<button class="quick-btn" bindtap="quickTest" data-value="1.5">小数(1.5)</button>
</view>
</view>
<!-- 测试结果 -->
<view class="test-results" wx:if="{{testResults.length > 0}}">
<view class="results-header">
<text class="results-title">测试结果 ({{testResults.length}}条)</text>
<button class="clear-btn" bindtap="clearTestResults">清空</button>
</view>
<view class="result-item" wx:for="{{testResults}}" wx:key="timestamp">
<view class="result-header">
<text class="result-id">ID: "{{item.productId}}"</text>
<text class="result-time">{{item.timestamp}}</text>
<text class="result-status {{item.success ? 'success' : 'error'}}">
{{item.success ? '✓ 成功' : '✗ 失败'}}
</text>
</view>
<view class="result-content" wx:if="{{item.success}}">
<text class="result-data">返回数据: {{item.data}}</text>
</view>
<view class="result-content" wx:else>
<text class="result-error">错误信息: {{item.error}}</text>
</view>
</view>
</view>
</view>
<!-- 操作按钮 -->
<view class="section">
<view class="section-title">评论组件测试</view>
<button class="switch-btn" bindtap="switchTestMode">
切换到{{testMode === 'with-comments' ? '无评论模式' : '有评论模式'}}
</button>
</view>
<!-- 评论组件显示区域 -->
<view class="section">
<view class="section-title">评论组件显示区域</view>
<!-- 显示条件检查 -->
<view class="condition-check">
<text class="condition-text">
条件检查: commentsStatistics.commentCount = {{commentsStatistics.commentCount}}
</text>
<text class="condition-text">
显示条件: {{commentsStatistics.commentCount > 0 ? 'true (显示)' : 'false (隐藏)'}}
</text>
</view>
<!-- 评论组件 - 完全复制商品详情页的结构 -->
<view class="comments-wrap" wx:if="{{commentsStatistics.commentCount > 0}}">
<view class="comments-head">
<view class="comments-title">
<text class="comments-title-label">商品评价</text>
<text class="comments-title-count">({{commentsStatistics.commentCount}})</text>
</view>
<view class="comments-rate-wrap">
<text class="comments-rate-label">好评率</text>
<text class="comments-rate-num">{{commentsStatistics.goodRate}}%</text>
</view>
</view>
<!-- 评论列表 -->
<view class="comment-item-wrap" wx:for="{{commentsList}}" wx:key="id" wx:if="{{index < 3}}">
<view class="comment-item-head">
<image class="comment-item-avatar" src="{{item.userHeadUrl}}" />
<view class="comment-item-info">
<text class="comment-item-name">{{item.userName}}</text>
<view class="comment-item-rate">
<text class="comment-item-score">{{item.commentScore}}分</text>
</view>
</view>
</view>
<view class="comment-item-content">
<text>{{item.commentContent}}</text>
</view>
<view class="comment-item-spec" wx:if="{{item.specInfo}}">
<text>{{item.specInfo}}</text>
</view>
<view class="comment-item-reply" wx:if="{{item.sellerReply}}">
<text class="reply-label">商家回复:</text>
<text class="reply-content">{{item.sellerReply}}</text>
</view>
<view class="comment-item-time">{{item.commentTime}}</view>
</view>
<!-- 查看更多按钮 -->
<view class="comments-more" bindtap="navToCommentsListPage">
<text>查看全部评价</text>
</view>
</view>
<!-- 无评论时的显示 -->
<view class="no-comments-placeholder" wx:else>
<text class="placeholder-text">评论组件未显示</text>
<text class="placeholder-reason">原因: commentCount = {{commentsStatistics.commentCount}} (不满足 > 0 的条件)</text>
</view>
</view>
<!-- 原始数据显示 -->
<view class="section">
<view class="section-title">原始数据</view>
<view class="data-display">
<view class="data-item">
<text class="data-label">commentsStatistics:</text>
<view class="data-content">{{commentsStatistics}}</view>
</view>
<view class="data-item">
<text class="data-label">commentsList ({{commentsList.length}}条):</text>
<view class="data-content">{{commentsList}}</view>
</view>
</view>
</view>
</view>

View File

@@ -0,0 +1,463 @@
/* pages/debug/hardcoded-comment-test.wxss */
.container {
padding: 20rpx;
background-color: #f5f5f5;
min-height: 100vh;
}
.header {
text-align: center;
margin-bottom: 30rpx;
}
.title {
font-size: 36rpx;
font-weight: bold;
color: #333;
display: block;
margin-bottom: 10rpx;
}
.subtitle {
font-size: 28rpx;
color: #666;
}
.section {
background-color: white;
margin-bottom: 20rpx;
border-radius: 10rpx;
padding: 20rpx;
}
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
border-bottom: 2rpx solid #eee;
padding-bottom: 10rpx;
}
/* 测试信息 */
.test-info {
background-color: #f9f9f9;
padding: 15rpx;
border-radius: 8rpx;
}
.info-item {
display: flex;
margin-bottom: 10rpx;
align-items: center;
}
.info-item:last-child {
margin-bottom: 0;
}
.label {
font-weight: bold;
color: #666;
margin-right: 10rpx;
min-width: 150rpx;
}
.value {
color: #333;
flex: 1;
}
.value.success {
color: #07c160;
}
.value.error {
color: #ff6b6b;
}
/* 操作按钮 */
.switch-btn {
width: 100%;
background-color: #07c160;
color: white;
border: none;
border-radius: 10rpx;
padding: 20rpx;
font-size: 32rpx;
}
/* 条件检查 */
.condition-check {
background-color: #e3f2fd;
padding: 15rpx;
border-radius: 8rpx;
margin-bottom: 20rpx;
}
.condition-text {
font-family: monospace;
font-size: 26rpx;
color: #1976d2;
word-break: break-all;
}
/* 无评论占位符 */
.no-comments-placeholder {
text-align: center;
padding: 60rpx 20rpx;
background-color: #f9f9f9;
border-radius: 10rpx;
border: 2rpx dashed #ddd;
}
.placeholder-text {
display: block;
font-size: 32rpx;
color: #999;
margin-bottom: 10rpx;
}
.placeholder-reason {
font-size: 26rpx;
color: #666;
}
/* 原始数据显示 */
.data-display {
background-color: #f0f0f0;
padding: 15rpx;
border-radius: 8rpx;
}
.data-item {
margin-bottom: 15rpx;
}
.data-item:last-child {
margin-bottom: 0;
}
.data-label {
font-weight: bold;
color: #666;
display: block;
margin-bottom: 5rpx;
}
.data-content {
background-color: white;
padding: 10rpx;
border-radius: 5rpx;
font-family: monospace;
font-size: 24rpx;
word-break: break-all;
max-height: 200rpx;
overflow-y: auto;
}
/* 评论组件样式 - 完全复制商品详情页 */
.comments-wrap {
background-color: #fff;
border-radius: 16rpx;
padding: 32rpx;
margin-top: 20rpx;
border: 3rpx solid #07c160; /* 添加绿色边框以便识别 */
}
.comments-head {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 32rpx;
}
.comments-title {
display: flex;
align-items: center;
}
.comments-title-label {
font-size: 32rpx;
font-weight: 600;
color: #333;
}
.comments-title-count {
font-size: 28rpx;
color: #666;
margin-left: 8rpx;
}
.comments-rate-wrap {
display: flex;
align-items: center;
}
.comments-rate-label {
font-size: 28rpx;
color: #666;
margin-right: 8rpx;
}
.comments-rate-num {
font-size: 28rpx;
color: #ff6b35;
font-weight: 600;
}
.comment-item-wrap {
border-bottom: 1rpx solid #f0f0f0;
padding-bottom: 24rpx;
margin-bottom: 24rpx;
}
.comment-item-wrap:last-child {
border-bottom: none;
margin-bottom: 0;
}
.comment-item-head {
display: flex;
align-items: center;
margin-bottom: 16rpx;
}
.comment-item-avatar {
width: 64rpx;
height: 64rpx;
border-radius: 50%;
margin-right: 16rpx;
}
.comment-item-info {
flex: 1;
}
.comment-item-name {
font-size: 28rpx;
color: #333;
display: block;
margin-bottom: 4rpx;
}
.comment-item-rate {
display: flex;
align-items: center;
}
.comment-item-score {
font-size: 24rpx;
color: #ff6b35;
}
.comment-item-content {
font-size: 28rpx;
color: #666;
line-height: 1.6;
margin-bottom: 12rpx;
}
.comment-item-spec {
font-size: 24rpx;
color: #999;
margin-bottom: 8rpx;
}
.comment-item-reply {
background-color: #f5f5f5;
padding: 12rpx;
border-radius: 8rpx;
margin-bottom: 12rpx;
}
.reply-label {
font-size: 24rpx;
color: #666;
font-weight: bold;
}
.reply-content {
font-size: 24rpx;
color: #333;
margin-left: 10rpx;
}
.comment-item-time {
font-size: 24rpx;
color: #999;
}
.comments-more {
text-align: center;
padding: 20rpx;
color: #07c160;
font-size: 28rpx;
border-top: 1rpx solid #f0f0f0;
margin-top: 20rpx;
}
/* 商品ID测试样式 */
.test-input-area {
background-color: #f9f9f9;
padding: 20rpx;
border-radius: 10rpx;
margin-bottom: 20rpx;
}
.input-row {
display: flex;
align-items: center;
margin-bottom: 15rpx;
}
.input-label {
font-size: 28rpx;
color: #333;
margin-right: 15rpx;
min-width: 180rpx;
}
.test-input {
flex: 1;
background-color: white;
border: 2rpx solid #ddd;
border-radius: 8rpx;
padding: 15rpx;
font-size: 28rpx;
}
.test-btn {
width: 100%;
background-color: #1976d2;
color: white;
border: none;
border-radius: 8rpx;
padding: 15rpx;
font-size: 28rpx;
}
.quick-test-area {
margin-bottom: 20rpx;
}
.quick-test-label {
font-size: 28rpx;
color: #333;
margin-bottom: 15rpx;
display: block;
}
.quick-test-buttons {
display: flex;
flex-wrap: wrap;
gap: 10rpx;
}
.quick-btn {
background-color: #f0f0f0;
color: #333;
border: 1rpx solid #ddd;
border-radius: 6rpx;
padding: 10rpx 15rpx;
font-size: 24rpx;
margin: 0;
flex: 0 0 auto;
}
.quick-btn:active {
background-color: #e0e0e0;
}
.test-results {
border-top: 2rpx solid #eee;
padding-top: 20rpx;
}
.results-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15rpx;
}
.results-title {
font-size: 28rpx;
font-weight: bold;
color: #333;
}
.clear-btn {
background-color: #ff6b6b;
color: white;
border: none;
border-radius: 6rpx;
padding: 8rpx 15rpx;
font-size: 24rpx;
margin: 0;
}
.result-item {
background-color: #f9f9f9;
border-radius: 8rpx;
padding: 15rpx;
margin-bottom: 10rpx;
border-left: 4rpx solid #ddd;
}
.result-item:last-child {
margin-bottom: 0;
}
.result-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10rpx;
}
.result-id {
font-family: monospace;
font-size: 26rpx;
color: #333;
font-weight: bold;
}
.result-time {
font-size: 24rpx;
color: #999;
}
.result-status {
font-size: 24rpx;
font-weight: bold;
padding: 4rpx 8rpx;
border-radius: 4rpx;
}
.result-status.success {
color: #07c160;
background-color: #e8f5e8;
border-left-color: #07c160;
}
.result-status.error {
color: #ff6b6b;
background-color: #ffe8e8;
border-left-color: #ff6b6b;
}
.result-content {
font-family: monospace;
font-size: 24rpx;
word-break: break-all;
line-height: 1.4;
}
.result-data {
color: #07c160;
}
.result-error {
color: #ff6b6b;
}

View File

@@ -0,0 +1,174 @@
import { config } from '../../config/index';
Page({
data: {
testResult: ''
},
// 测试正确的支付参数(标准格式)
testWechatPayment() {
const paymentParams = {
timeStamp: String(Math.floor(Date.now() / 1000)),
nonceStr: 'test_nonce_str_' + Math.random().toString(36).substr(2, 15),
package: 'prepay_id=wx_test_prepay_id_123456789',
signType: 'MD5',
paySign: 'test_pay_sign_123456789'
};
console.log('测试标准支付参数:', paymentParams);
console.log('参数详情:');
console.log('- timeStamp:', paymentParams.timeStamp, '(类型:', typeof paymentParams.timeStamp, ')');
console.log('- nonceStr:', paymentParams.nonceStr, '(长度:', paymentParams.nonceStr.length, ')');
console.log('- package:', paymentParams.package, '(格式检查: prepay_id=前缀)');
console.log('- signType:', paymentParams.signType);
console.log('- paySign:', paymentParams.paySign, '(长度:', paymentParams.paySign.length, ')');
wx.requestPayment({
...paymentParams,
success: (res) => {
console.log('支付成功:', res);
this.setData({
testResult: '支付成功: ' + JSON.stringify(res)
});
},
fail: (err) => {
console.log('支付失败:', err);
console.log('错误详情:');
console.log('- errMsg:', err.errMsg);
console.log('- errCode:', err.errCode);
this.setData({
testResult: '支付失败: ' + JSON.stringify(err) + '\n错误信息: ' + err.errMsg
});
}
});
},
// 测试错误的package格式不含prepay_id前缀
testWrongPackageFormat() {
const paymentParams = {
timeStamp: String(Math.floor(Date.now() / 1000)),
nonceStr: 'test_nonce_str_' + Math.random().toString(36).substr(2, 15),
package: 'wx_test_prepay_id_123456789', // 错误格式缺少prepay_id=前缀
signType: 'MD5',
paySign: 'test_pay_sign_123456789'
};
console.log('测试错误package格式:', paymentParams);
wx.requestPayment({
...paymentParams,
success: (res) => {
console.log('支付成功:', res);
this.setData({
testResult: '支付成功: ' + JSON.stringify(res)
});
},
fail: (err) => {
console.log('支付失败:', err);
this.setData({
testResult: '支付失败: ' + JSON.stringify(err)
});
}
});
},
// 测试空的package参数
testEmptyPackage() {
const paymentParams = {
timeStamp: String(Math.floor(Date.now() / 1000)),
nonceStr: 'test_nonce_str_' + Math.random().toString(36).substr(2, 15),
package: '', // 空的package
signType: 'MD5',
paySign: 'test_pay_sign_123456789'
};
console.log('测试空package参数:', paymentParams);
wx.requestPayment({
...paymentParams,
success: (res) => {
console.log('支付成功:', res);
this.setData({
testResult: '支付成功: ' + JSON.stringify(res)
});
},
fail: (err) => {
console.log('支付失败:', err);
this.setData({
testResult: '支付失败: ' + JSON.stringify(err)
});
}
});
},
// 测试真实的后端API调用
testRealPaymentAPI() {
console.log('开始测试真实后端API...');
wx.request({
url: `${config.apiBase}/payment/create`,
method: 'POST',
header: {
'Content-Type': 'application/json'
},
data: {
amount: 1,
description: '测试支付'
},
success: (res) => {
console.log('后端API返回:', res.data);
if (res.data.code === 200 && res.data.data) {
const paymentData = res.data.data;
console.log('后端返回的支付参数:', paymentData);
console.log('参数验证:');
console.log('- timeStamp:', paymentData.timeStamp, '(类型:', typeof paymentData.timeStamp, ')');
console.log('- nonceStr:', paymentData.nonceStr, '(长度:', paymentData.nonceStr ? paymentData.nonceStr.length : 'undefined', ')');
console.log('- package:', paymentData.package, '(格式:', paymentData.package ? (paymentData.package.startsWith('prepay_id=') ? '正确' : '错误') : 'undefined', ')');
console.log('- signType:', paymentData.signType);
console.log('- paySign:', paymentData.paySign, '(长度:', paymentData.paySign ? paymentData.paySign.length : 'undefined', ')');
// 检查是否包含total_fee参数
if (paymentData.total_fee !== undefined) {
console.warn('⚠️ 发现total_fee参数:', paymentData.total_fee);
}
wx.requestPayment({
...paymentData,
success: (payRes) => {
console.log('支付成功:', payRes);
this.setData({
testResult: '真实API支付成功: ' + JSON.stringify(payRes)
});
},
fail: (payErr) => {
console.log('支付失败:', payErr);
console.log('错误详情:');
console.log('- errMsg:', payErr.errMsg);
console.log('- errCode:', payErr.errCode);
this.setData({
testResult: '真实API支付失败: ' + JSON.stringify(payErr) + '\n错误信息: ' + payErr.errMsg
});
}
});
} else {
console.log('API返回错误:', res.data);
this.setData({
testResult: 'API调用失败: ' + JSON.stringify(res.data)
});
}
},
fail: (err) => {
console.log('API请求失败:', err);
this.setData({
testResult: 'API请求失败: ' + JSON.stringify(err)
});
}
});
},
// 清除测试结果
clearResult() {
this.setData({
testResult: ''
});
}
});

View File

@@ -0,0 +1,3 @@
{
"usingComponents": {}
}

View File

@@ -0,0 +1,35 @@
<view class="container">
<view class="header">
<text class="title">微信支付测试页面</text>
<text class="subtitle">用于诊断total_fee参数问题</text>
</view>
<view class="test-section">
<view class="section-title">测试用例</view>
<button class="test-btn" bindtap="testWechatPayment">
测试标准支付参数
</button>
<button class="test-btn warning" bindtap="testWrongPackageFormat">
测试错误package格式
</button>
<button class="test-btn error" bindtap="testEmptyPackage">
测试空package参数
</button>
<button class="test-btn primary" bindtap="testRealPaymentAPI">
测试真实后端API
</button>
<button class="test-btn secondary" bindtap="clearResult">
清除结果
</button>
</view>
<view class="result-section" wx:if="{{testResult}}">
<view class="section-title">测试结果</view>
<view class="result-content">{{testResult}}</view>
</view>
</view>

View File

@@ -0,0 +1,85 @@
.container {
padding: 40rpx;
background-color: #f5f5f5;
min-height: 100vh;
}
.header {
text-align: center;
margin-bottom: 60rpx;
}
.title {
font-size: 36rpx;
font-weight: bold;
color: #333;
margin-bottom: 20rpx;
}
.subtitle {
font-size: 28rpx;
color: #666;
}
.test-section {
margin-bottom: 60rpx;
}
.section-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 30rpx;
}
.test-btn {
width: 100%;
margin-bottom: 20rpx;
border: none;
border-radius: 8rpx;
padding: 30rpx;
font-size: 32rpx;
text-align: center;
color: white;
background-color: #07c160;
}
.test-btn:active {
opacity: 0.8;
}
.test-btn.primary {
background-color: #1890ff;
}
.test-btn.warning {
background-color: #faad14;
}
.test-btn.error {
background-color: #ff4d4f;
}
.test-btn.secondary {
background-color: #d9d9d9;
color: #333;
}
.result-section {
background-color: white;
border-radius: 12rpx;
padding: 30rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}
.result-content {
font-size: 28rpx;
line-height: 1.6;
color: #666;
white-space: pre-wrap;
word-break: break-all;
background-color: #f8f8f8;
padding: 20rpx;
border-radius: 8rpx;
border: 1rpx solid #e8e8e8;
}

View File

@@ -0,0 +1,124 @@
Page({
data: {
// 模拟有评论的情况
commentsStatistics: {
commentCount: 5,
goodCount: 4,
middleCount: 1,
badCount: 0,
goodRate: 80,
hasImageCount: 2,
},
commentsList: [
{
id: 1,
userName: '测试用户1',
userHeadUrl: 'https://tdesign.gtimg.com/miniprogram/template/retail/avatar/avatar1.png',
commentScore: 5,
commentContent: '商品质量很好,物流也很快!',
commentTime: '2024-01-15',
specInfo: '颜色:红色 尺寸:M',
commentResources: [],
isAnonymity: false,
sellerReply: '',
goodsDetailInfo: ''
},
{
id: 2,
userName: '测试用户2',
userHeadUrl: 'https://tdesign.gtimg.com/miniprogram/template/retail/avatar/avatar1.png',
commentScore: 4,
commentContent: '整体不错,性价比很高。',
commentTime: '2024-01-14',
specInfo: '颜色:蓝色 尺寸:L',
commentResources: [],
isAnonymity: false,
sellerReply: '',
goodsDetailInfo: ''
}
],
testMode: 'with_comments'
},
onLoad() {
console.log('简单评论测试页面加载');
console.log('commentsStatistics:', this.data.commentsStatistics);
console.log('commentsList:', this.data.commentsList);
console.log('显示条件 (commentCount > 0):', this.data.commentsStatistics.commentCount > 0);
},
// 切换测试模式
switchTestMode() {
const currentMode = this.data.testMode;
if (currentMode === 'with_comments') {
// 切换到无评论模式
this.setData({
testMode: 'no_comments',
commentsStatistics: {
commentCount: 0,
goodCount: 0,
middleCount: 0,
badCount: 0,
goodRate: 0,
hasImageCount: 0,
},
commentsList: []
});
console.log('切换到无评论模式');
} else {
// 切换到有评论模式
this.setData({
testMode: 'with_comments',
commentsStatistics: {
commentCount: 5,
goodCount: 4,
middleCount: 1,
badCount: 0,
goodRate: 80,
hasImageCount: 2,
},
commentsList: [
{
id: 1,
userName: '测试用户1',
userHeadUrl: 'https://tdesign.gtimg.com/miniprogram/template/retail/avatar/avatar1.png',
commentScore: 5,
commentContent: '商品质量很好,物流也很快!',
commentTime: '2024-01-15',
specInfo: '颜色:红色 尺寸:M',
commentResources: [],
isAnonymity: false,
sellerReply: '',
goodsDetailInfo: ''
},
{
id: 2,
userName: '测试用户2',
userHeadUrl: 'https://tdesign.gtimg.com/miniprogram/template/retail/avatar/avatar1.png',
commentScore: 4,
commentContent: '整体不错,性价比很高。',
commentTime: '2024-01-14',
specInfo: '颜色:蓝色 尺寸:L',
commentResources: [],
isAnonymity: false,
sellerReply: '',
goodsDetailInfo: ''
}
]
});
console.log('切换到有评论模式');
}
console.log('新的显示条件 (commentCount > 0):', this.data.commentsStatistics.commentCount > 0);
},
// 导航到评论列表页面
navToCommentsListPage() {
console.log('导航到评论列表页面');
wx.showToast({
title: '导航到评论列表',
icon: 'success'
});
}
});

View File

@@ -0,0 +1,4 @@
{
"navigationBarTitleText": "简单评论组件测试",
"backgroundColor": "#f5f5f5"
}

View File

@@ -0,0 +1,86 @@
<!--简单评论测试页面-->
<view class="container">
<view class="header">
<text class="title">简单评论组件测试</text>
<text class="subtitle">测试评论组件的基本显示功能</text>
</view>
<!-- 测试信息 -->
<view class="test-info">
<view class="info-item">
<text class="info-label">当前模式:</text>
<text class="info-value">{{testMode === 'with_comments' ? '有评论' : '无评论'}}</text>
</view>
<view class="info-item">
<text class="info-label">评论数量:</text>
<text class="info-value">{{commentsStatistics.commentCount}}</text>
</view>
<view class="info-item">
<text class="info-label">显示条件:</text>
<text class="info-value {{commentsStatistics.commentCount > 0 ? 'success' : 'error'}}">
commentCount > 0 = {{commentsStatistics.commentCount > 0}}
</text>
</view>
</view>
<!-- 切换按钮 -->
<button class="switch-btn" bindtap="switchTestMode">
切换到{{testMode === 'with_comments' ? '无评论' : '有评论'}}模式
</button>
<!-- 评论组件 - 完全复制商品详情页面的结构 -->
<view class="comment-section">
<text class="section-title">评论组件显示区域</text>
<!-- 关键的显示条件测试 -->
<view wx:if="{{commentsStatistics.commentCount > 0}}" class="comments-wrap">
<view class="comments-head" bindtap="navToCommentsListPage">
<view class="comments-title-wrap">
<view class="comments-title-label">商品评价</view>
<view class="comments-title-count"> ({{ commentsStatistics.commentCount }}) </view>
</view>
<view class="comments-rate-wrap">
<view class="comments-good-rate">{{commentsStatistics.goodRate}}% 好评</view>
<text class="arrow">></text>
</view>
</view>
<!-- 评论列表 -->
<view class="comment-item-wrap" wx:for="{{ commentsList }}" wx:for-item="commentItem" wx:key="id">
<view class="comment-item-head">
<image class="comment-item-avatar" src="{{commentItem.userHeadUrl}}" mode="aspectFill" />
<view class="comment-head-right">
<view class="comment-username">{{commentItem.userName}}</view>
<view class="comment-rating">
<text wx:for="{{[1,2,3,4,5]}}" wx:for-item="star" wx:key="star"
class="star {{star <= commentItem.commentScore ? 'filled' : ''}}">★</text>
</view>
</view>
</view>
<view class="comment-item-content">{{commentItem.commentContent}}</view>
</view>
</view>
<!-- 无评论时的显示 -->
<view wx:else class="no-comments-wrap">
<text class="no-comments-text">暂无评论 (commentCount = {{commentsStatistics.commentCount}})</text>
</view>
</view>
<!-- 调试信息 -->
<view class="debug-info">
<text class="section-title">调试信息</text>
<view class="debug-item">
<text class="debug-text">wx:if 条件: commentsStatistics.commentCount > 0</text>
</view>
<view class="debug-item">
<text class="debug-text">实际值: {{commentsStatistics.commentCount}} > 0</text>
</view>
<view class="debug-item">
<text class="debug-text">结果: {{commentsStatistics.commentCount > 0}}</text>
</view>
<view class="debug-item">
<text class="debug-text">应该显示: {{commentsStatistics.commentCount > 0 ? '是' : '否'}}</text>
</view>
</view>
</view>

View File

@@ -0,0 +1,263 @@
/* 简单评论测试页面样式 */
.container {
padding: 20rpx;
background-color: #f5f5f5;
min-height: 100vh;
}
.header {
text-align: center;
margin-bottom: 30rpx;
padding: 20rpx;
background: #fff;
border-radius: 16rpx;
}
.title {
display: block;
font-size: 36rpx;
font-weight: 600;
color: #333;
margin-bottom: 10rpx;
}
.subtitle {
display: block;
font-size: 26rpx;
color: #666;
}
.section-title {
display: block;
font-size: 30rpx;
font-weight: 600;
color: #333;
margin-bottom: 20rpx;
padding-bottom: 10rpx;
border-bottom: 2rpx solid #e0e0e0;
}
/* 测试信息样式 */
.test-info {
background: #fff;
padding: 20rpx;
margin-bottom: 20rpx;
border-radius: 16rpx;
border-left: 4rpx solid #4CAF50;
}
.info-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10rpx 0;
border-bottom: 1rpx solid #f0f0f0;
}
.info-item:last-child {
border-bottom: none;
}
.info-label {
font-size: 26rpx;
color: #666;
font-weight: 500;
}
.info-value {
font-size: 26rpx;
color: #333;
font-weight: 600;
}
.info-value.success {
color: #4CAF50;
}
.info-value.error {
color: #F44336;
}
/* 切换按钮样式 */
.switch-btn {
width: 100%;
height: 80rpx;
line-height: 80rpx;
background: #2196F3;
color: #fff;
border: none;
border-radius: 12rpx;
font-size: 28rpx;
font-weight: 500;
margin-bottom: 30rpx;
}
/* 评论组件样式 */
.comment-section {
background: #fff;
padding: 20rpx;
margin-bottom: 20rpx;
border-radius: 16rpx;
}
/* 复制商品详情页面的评论样式 */
.comments-wrap {
margin: 20rpx 0;
padding: 28rpx;
background-color: #fff;
border-radius: 16rpx;
box-shadow: 0 2rpx 16rpx rgba(0, 0, 0, 0.06);
border: 1rpx solid #f0f0f0;
}
.comments-wrap .comments-head {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #f5f5f5;
}
.comments-wrap .comments-head .comments-title-wrap {
display: flex;
align-items: center;
}
.comments-title-label {
color: #222222;
font-size: 30rpx;
font-weight: 600;
line-height: 1;
}
.comments-title-count {
color: #666666;
font-size: 26rpx;
font-weight: 400;
line-height: 1;
margin-left: 8rpx;
}
.comments-rate-wrap {
display: flex;
justify-content: center;
align-items: center;
background: #fff5f5;
padding: 8rpx 16rpx;
border-radius: 20rpx;
border: 1rpx solid #ffe5e5;
}
.comments-rate-wrap .comments-good-rate {
color: #fa4126;
font-size: 24rpx;
font-weight: 500;
line-height: 1;
margin-right: 8rpx;
}
.arrow {
color: #BBBBBB;
font-size: 24rpx;
}
.comment-item-wrap {
margin-top: 24rpx;
padding: 20rpx;
background: #fafafa;
border-radius: 12rpx;
border: 1rpx solid #f0f0f0;
}
.comment-item-wrap .comment-item-head {
display: flex;
flex-direction: row;
align-items: center;
}
.comment-item-wrap .comment-item-head .comment-item-avatar {
width: 60rpx;
height: 60rpx;
border-radius: 30rpx;
border: 2rpx solid #fff;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
.comment-item-wrap .comment-item-head .comment-head-right {
margin-left: 20rpx;
flex: 1;
}
.comment-head-right .comment-username {
font-size: 26rpx;
color: #333333;
line-height: 1.2;
font-weight: 500;
margin-bottom: 6rpx;
display: block;
}
.comment-rating {
display: flex;
align-items: center;
}
.star {
font-size: 24rpx;
color: #ddd;
margin-right: 2rpx;
}
.star.filled {
color: #FFD700;
}
.comment-item-wrap .comment-item-content {
margin-top: 16rpx;
color: #555555;
line-height: 1.5;
font-size: 26rpx;
font-weight: 400;
padding: 16rpx;
background: #fff;
border-radius: 8rpx;
border-left: 3rpx solid #fa4126;
}
.no-comments-wrap {
text-align: center;
padding: 60rpx 20rpx;
background: #f9f9f9;
border-radius: 12rpx;
border: 2rpx dashed #ddd;
margin: 20rpx 0;
}
.no-comments-text {
font-size: 28rpx;
color: #999;
}
/* 调试信息样式 */
.debug-info {
background: #fff;
padding: 20rpx;
border-radius: 16rpx;
border-left: 4rpx solid #FF9800;
}
.debug-item {
padding: 8rpx 0;
border-bottom: 1rpx solid #f0f0f0;
}
.debug-item:last-child {
border-bottom: none;
}
.debug-text {
font-size: 24rpx;
color: #666;
font-family: monospace;
}