This commit is contained in:
sjk
2025-11-17 14:11:46 +08:00
commit ad4a600af9
1659 changed files with 171560 additions and 0 deletions

View File

@@ -0,0 +1,222 @@
import { createComment } from '../../../../services/comments/createComment';
import Toast from 'tdesign-miniprogram/toast/index';
Page({
data: {
serviceRateValue: 5,
goodRateValue: 5,
conveyRateValue: 5,
isAnonymous: false,
uploadFiles: [],
images: [],
gridConfig: {
width: 218,
height: 218,
column: 3,
},
isAllowedSubmit: false,
submitting: false,
imgUrl: '',
title: '',
goodsDetail: '',
orderNo: '',
goodsId: '',
maxImages: 9,
imageProps: {
mode: 'aspectFit',
},
},
onLoad(options) {
console.log('评价页面加载参数:', options);
this.setData({
imgUrl: options.imgUrl ? decodeURIComponent(options.imgUrl) : '',
title: options.title ? decodeURIComponent(options.title) : '',
goodsDetail: options.specs ? decodeURIComponent(options.specs) : '',
orderNo: options.orderNo || '',
goodsId: options.goodsId || '',
});
this.updateButtonStatus();
},
onRateChange(e) {
const { value } = e?.detail;
const item = e?.currentTarget?.dataset?.item;
this.setData({ [item]: value }, () => {
this.updateButtonStatus();
});
},
onAnonymousChange(e) {
const status = !!e?.detail?.checked;
this.setData({ isAnonymous: status });
},
handleSuccess(e) {
// 兼容原有的上传组件
const { files } = e.detail;
const images = files.map(file => file.url);
this.setData({
uploadFiles: files,
images
});
},
handleRemove(e) {
const { index } = e.detail;
const { uploadFiles, images } = this.data;
uploadFiles.splice(index, 1);
images.splice(index, 1);
this.setData({
uploadFiles,
images
});
},
// 上传图片到服务器
async uploadImages(images) {
if (!images || images.length === 0) return [];
const uploadPromises = images.map(imagePath => {
return new Promise((resolve, reject) => {
const uploadUrl = `${getApp().globalData.config.apiBaseUrl}/upload/image`;
const token = wx.getStorageSync('token');
console.log('上传URL:', uploadUrl);
console.log('Token:', token);
wx.uploadFile({
url: uploadUrl,
filePath: imagePath,
name: 'file',
header: {
'Authorization': `Bearer ${token}`
},
success: (res) => {
try {
const data = JSON.parse(res.data);
if (data.code === 200) {
resolve(data.data.url);
} else {
reject(new Error(data.message || '上传失败'));
}
} catch (e) {
reject(new Error('解析上传结果失败'));
}
},
fail: reject
});
});
});
return Promise.all(uploadPromises);
},
onTextAreaChange(e) {
const value = e?.detail?.value;
this.textAreaValue = value;
this.updateButtonStatus();
},
updateButtonStatus() {
const { serviceRateValue, goodRateValue, conveyRateValue, submitting } = this.data;
const { textAreaValue } = this;
const temp = serviceRateValue && goodRateValue && conveyRateValue && textAreaValue && !submitting;
this.setData({ isAllowedSubmit: temp });
},
async onSubmitBtnClick() {
const {
isAllowedSubmit,
submitting,
serviceRateValue,
goodRateValue,
conveyRateValue,
isAnonymous,
images,
orderNo,
goodsId
} = this.data;
if (!isAllowedSubmit || submitting) return;
const content = this.textAreaValue;
if (!content || !content.trim()) {
Toast({
context: this,
selector: '#t-toast',
message: '请输入评价内容',
icon: 'error-circle',
});
return;
}
this.setData({ submitting: true });
this.updateButtonStatus();
try {
// 上传图片
let uploadedImages = [];
if (images.length > 0) {
Toast({
context: this,
selector: '#t-toast',
message: '正在上传图片...',
icon: 'loading',
});
uploadedImages = await this.uploadImages(images);
}
// 计算综合评分(取三个评分的平均值)
const averageRating = Math.round((serviceRateValue + goodRateValue + conveyRateValue) / 3);
// 提交评论
const commentData = {
orderNo: orderNo,
productId: goodsId,
rating: averageRating,
content: content.trim(),
images: uploadedImages,
isAnonymous: isAnonymous
};
console.log('提交评论数据:', commentData);
await createComment(commentData);
Toast({
context: this,
selector: '#t-toast',
message: '评价提交成功',
icon: 'check-circle',
});
// 设置上一页刷新标志
const pages = getCurrentPages();
const prevPage = pages[pages.length - 2]; // 上一页(订单详情页)
if (prevPage) {
prevPage.setData({ backRefresh: true });
}
// 延迟返回上一页
setTimeout(() => {
wx.navigateBack({
delta: 1
});
}, 1500);
} catch (error) {
console.error('提交评价失败:', error);
Toast({
context: this,
selector: '#t-toast',
message: error.message || '提交失败,请重试',
icon: 'error-circle',
});
} finally {
this.setData({ submitting: false });
this.updateButtonStatus();
}
},
});

View File

@@ -0,0 +1,13 @@
{
"navigationBarTitleText": "评价商品",
"usingComponents": {
"t-image": "/components/webp-image/index",
"t-rate": "tdesign-miniprogram/rate/rate",
"t-textarea": "tdesign-miniprogram/textarea/textarea",
"t-checkbox": "tdesign-miniprogram/checkbox/checkbox",
"t-button": "tdesign-miniprogram/button/button",
"t-upload": "tdesign-miniprogram/upload/upload",
"t-icon": "tdesign-miniprogram/icon/icon",
"t-toast": "tdesign-miniprogram/toast/toast"
}
}

View File

@@ -0,0 +1,93 @@
<view class="page-container">
<view class="comment-card">
<view class="goods-info-container">
<view class="goods-image-container">
<t-image t-class="goods-image" src="{{imgUrl}}" />
</view>
<view class="goods-title-container">
<view class="goods-title">{{title}}</view>
<view class="goods-detail">{{goodsDetail}}</view>
</view>
</view>
<view class="rate-container">
<text class="rate-title">商品评价</text>
<view class="rate">
<t-rate
value="{{goodRateValue}}"
bind:change="onRateChange"
size="26"
gap="6"
color="{{['#ffc51c', '#ddd']}}"
data-item="goodRateValue"
/>
</view>
</view>
<view class="textarea-container">
<t-textarea
t-class="textarea"
maxlength="{{500}}"
indicator
placeholder="对商品满意吗?评论一下"
bind:change="onTextAreaChange"
/>
</view>
<view class="upload-container">
<t-upload
media-type="{{['image']}}"
files="{{uploadFiles}}"
bind:remove="handleRemove"
bind:success="handleSuccess"
gridConfig="{{gridConfig}}"
imageProps="{{imageProps}}"
max="{{maxImages}}"
/>
</view>
<view class="anonymous-box">
<t-checkbox bind:change="onAnonymousChange" checked="{{isAnonymous}}" color="#FA4126" />
<view class="name">匿名评价</view>
</view>
</view>
</view>
<view class="comment-card convey-card">
<view class="convey-comment-title">物流服务评价</view>
<view class="rate-container">
<text class="rate-title">物流评价</text>
<view class="rate">
<t-rate
value="{{conveyRateValue}}"
bind:change="onRateChange"
variant="filled"
size="26"
gap="6"
color="{{['#ffc51c', '#ddd']}}"
data-item="conveyRateValue"
/>
</view>
</view>
<view class="rate-container">
<text class="rate-title">服务评价</text>
<view class="rate">
<t-rate
value="{{serviceRateValue}}"
bind:change="onRateChange"
size="26"
gap="6"
color="{{['#ffc51c', '#ddd']}}"
data-item="serviceRateValue"
/>
</view>
</view>
</view>
<view class="submit-button-container">
<t-button
content="{{submitting ? '提交中...' : '提交'}}"
block
shape="round"
loading="{{submitting}}"
disabled="{{!isAllowedSubmit || submitting}}"
t-class="submit-button{{isAllowedSubmit && !submitting ? '' : '-disabled'}}"
bind:tap="onSubmitBtnClick"
/>
</view>
<t-toast id="t-toast" />

View File

@@ -0,0 +1,168 @@
page {
background-color: #f5f5f5;
}
.page-container .comment-card {
padding: 24rpx 32rpx 28rpx;
background-color: #ffffff;
}
.comment-card .goods-info-container .goods-image {
width: 112rpx;
height: 112rpx;
border-radius: 8rpx;
}
.comment-card .goods-info-container {
display: flex;
align-items: center;
}
.comment-card .goods-info-container .goods-title-container {
padding-left: 24rpx;
}
.comment-card .goods-info-container .goods-title {
font-size: 28rpx;
font-weight: normal;
}
.comment-card .goods-info-container .goods-detail {
font-size: 24rpx;
font-weight: normal;
color: #999999;
margin-top: 16rpx;
}
.comment-card .rate-container {
display: flex;
align-items: center;
margin-top: 22rpx;
}
.comment-card .rate-container .rate-title {
font-size: 28rpx;
font-weight: bold;
margin-right: 12rpx;
}
.comment-card .textarea-container {
margin-top: 22rpx;
}
.comment-card .textarea-container .textarea {
height: 294rpx;
background-color: #f5f5f5;
border-radius: 16rpx;
font-size: 28rpx;
font-weight: normal;
}
.page-container .t-checkbox__bordered {
display: none;
}
.page-container .anonymous-box {
display: flex;
align-items: center;
padding-top: 52rpx;
}
.page-container .anonymous-box .name {
font-size: 28rpx;
font-weight: normal;
color: #999999;
padding-left: 28rpx;
}
.page-container .t-checkbox {
padding: 0rpx !important;
}
.page-container .t-checkbox__content {
display: none;
}
.comment-card .convey-comment-title {
font-size: 28rpx;
font-weight: bold;
}
.convey-card {
background-color: #ffffff;
margin-top: 24rpx;
padding: 32rpx;
padding-bottom: calc(env(safe-area-inset-bottom) + 140rpx);
}
.convey-card .rate-container .rate-title {
font-weight: normal;
}
.page-container .t-checkbox__icon-left {
margin-right: 0rpx !important;
}
.submit-button-container {
padding: 12rpx 32rpx;
display: flex;
width: 100vw;
box-sizing: border-box;
justify-content: center;
position: fixed;
bottom: 0;
padding-bottom: calc(env(safe-area-inset-bottom) + 20rpx);
background-color: #ffffff;
z-index: 99;
}
.submit-button-container .submit-button {
--td-button-default-color: #fff;
--td-button-default-bg-color: #fa4126;
--td-button-default-border-color: #fa4126;
--td-button-default-active-bg-color: #fa42269c;
}
.submit-button-container .submit-button-disabled {
--td-button-default-color: #fff;
--td-button-default-bg-color: #ccc;
--td-button-default-border-color: #ccc;
--td-button-default-active-bg-color: rgba(204, 204, 204, 0.789);
}
.page-container .upload-container {
margin-top: 24rpx;
}
.page-container .t-upload__wrapper {
border-radius: 8rpx;
overflow: hidden;
}
.page-container .submmit-bar {
position: fixed;
left: 0;
right: 0;
bottom: 0;
z-index: 12;
padding: 12rpx 32rpx;
padding-bottom: env(safe-area-inset-bottom);
background-color: #fff;
height: 112rpx;
}
.page-container .submmit-bar-button {
border-radius: 48rpx !important;
padding: 0 !important;
}
.page-container .t-upload__close-btn {
background-color: rgba(0, 0, 0, 0.4);
border-bottom-left-radius: 8rpx;
width: 36rpx;
height: 36rpx;
}
.upload-container .upload-addcontent-slot {
font-size: 26rpx;
}