init
This commit is contained in:
239
miniprogram/pages/order/comment/index.js
Normal file
239
miniprogram/pages/order/comment/index.js
Normal file
@@ -0,0 +1,239 @@
|
||||
import { createComment } from '../../../services/comments/createComment';
|
||||
import Toast from 'tdesign-miniprogram/toast/index';
|
||||
|
||||
Page({
|
||||
data: {
|
||||
orderItem: null,
|
||||
rating: 5,
|
||||
content: '',
|
||||
images: [],
|
||||
isAnonymous: false,
|
||||
submitting: false,
|
||||
maxImages: 9,
|
||||
maxContentLength: 500
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
console.log('评论页面加载', options);
|
||||
|
||||
// 从页面参数获取订单项信息
|
||||
if (options.orderItemData) {
|
||||
try {
|
||||
const orderItem = JSON.parse(decodeURIComponent(options.orderItemData));
|
||||
this.setData({ orderItem });
|
||||
console.log('订单项信息', orderItem);
|
||||
} catch (e) {
|
||||
console.error('解析订单项数据失败', e);
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '参数错误',
|
||||
icon: 'error-circle',
|
||||
});
|
||||
setTimeout(() => {
|
||||
wx.navigateBack();
|
||||
}, 1500);
|
||||
}
|
||||
} else {
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '缺少订单信息',
|
||||
icon: 'error-circle',
|
||||
});
|
||||
setTimeout(() => {
|
||||
wx.navigateBack();
|
||||
}, 1500);
|
||||
}
|
||||
},
|
||||
|
||||
// 评分变化
|
||||
onRatingChange(e) {
|
||||
this.setData({
|
||||
rating: e.detail.value
|
||||
});
|
||||
},
|
||||
|
||||
// 评论内容输入
|
||||
onContentInput(e) {
|
||||
this.setData({
|
||||
content: e.detail.value
|
||||
});
|
||||
},
|
||||
|
||||
// 匿名评论切换
|
||||
onAnonymousChange(e) {
|
||||
this.setData({
|
||||
isAnonymous: e.detail.value
|
||||
});
|
||||
},
|
||||
|
||||
// 选择图片
|
||||
onChooseImage() {
|
||||
const { images, maxImages } = this.data;
|
||||
const remainCount = maxImages - images.length;
|
||||
|
||||
if (remainCount <= 0) {
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: `最多只能上传${maxImages}张图片`,
|
||||
icon: 'error-circle',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
wx.chooseMedia({
|
||||
count: remainCount,
|
||||
mediaType: ['image'],
|
||||
sourceType: ['album', 'camera'],
|
||||
success: (res) => {
|
||||
const newImages = res.tempFiles.map(file => file.tempFilePath);
|
||||
this.setData({
|
||||
images: [...images, ...newImages]
|
||||
});
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('选择图片失败', err);
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '选择图片失败',
|
||||
icon: 'error-circle',
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 删除图片
|
||||
onDeleteImage(e) {
|
||||
const { index } = e.currentTarget.dataset;
|
||||
const { images } = this.data;
|
||||
images.splice(index, 1);
|
||||
this.setData({ images });
|
||||
},
|
||||
|
||||
// 预览图片
|
||||
onPreviewImage(e) {
|
||||
const { index } = e.currentTarget.dataset;
|
||||
const { images } = this.data;
|
||||
|
||||
wx.previewImage({
|
||||
current: images[index],
|
||||
urls: images
|
||||
});
|
||||
},
|
||||
|
||||
// 上传图片到服务器
|
||||
async uploadImages(images) {
|
||||
const uploadPromises = images.map(imagePath => {
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.uploadFile({
|
||||
url: `${getApp().globalData.config.apiBaseUrl}/upload/image`,
|
||||
filePath: imagePath,
|
||||
name: 'file',
|
||||
header: {
|
||||
'Authorization': `Bearer ${wx.getStorageSync('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);
|
||||
},
|
||||
|
||||
// 提交评论
|
||||
async onSubmit() {
|
||||
const { orderItem, rating, content, images, isAnonymous, submitting } = this.data;
|
||||
|
||||
if (submitting) return;
|
||||
|
||||
if (!content.trim()) {
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '请输入评论内容',
|
||||
icon: 'error-circle',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.setData({ submitting: true });
|
||||
|
||||
try {
|
||||
// 上传图片
|
||||
let uploadedImages = [];
|
||||
if (images.length > 0) {
|
||||
Toast({
|
||||
context: this,
|
||||
selector: '#t-toast',
|
||||
message: '正在上传图片...',
|
||||
icon: 'loading',
|
||||
});
|
||||
uploadedImages = await this.uploadImages(images);
|
||||
}
|
||||
|
||||
// 提交评论
|
||||
const commentData = {
|
||||
orderItemId: orderItem.id,
|
||||
productId: orderItem.product_id,
|
||||
rating,
|
||||
content: content.trim(),
|
||||
images: uploadedImages,
|
||||
isAnonymous
|
||||
};
|
||||
|
||||
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 });
|
||||
}
|
||||
},
|
||||
|
||||
// 返回上一页
|
||||
onBack() {
|
||||
wx.navigateBack();
|
||||
}
|
||||
});
|
||||
13
miniprogram/pages/order/comment/index.json
Normal file
13
miniprogram/pages/order/comment/index.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"usingComponents": {
|
||||
"t-navbar": "tdesign-miniprogram/navbar/navbar",
|
||||
"t-rate": "tdesign-miniprogram/rate/rate",
|
||||
"t-textarea": "tdesign-miniprogram/textarea/textarea",
|
||||
"t-icon": "tdesign-miniprogram/icon/icon",
|
||||
"t-switch": "tdesign-miniprogram/switch/switch",
|
||||
"t-button": "tdesign-miniprogram/button/button",
|
||||
"t-toast": "tdesign-miniprogram/toast/toast",
|
||||
"price": "/components/price/index"
|
||||
},
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
106
miniprogram/pages/order/comment/index.wxml
Normal file
106
miniprogram/pages/order/comment/index.wxml
Normal file
@@ -0,0 +1,106 @@
|
||||
<view class="comment-page">
|
||||
<!-- 导航栏 -->
|
||||
<t-navbar title="评价商品" left-arrow bind:left-click="onBack" />
|
||||
|
||||
<!-- 商品信息 -->
|
||||
<view class="product-info" wx:if="{{orderItem}}">
|
||||
<image class="product-image" src="{{orderItem.product.images[0] || '/assets/placeholder.png'}}" mode="aspectFill" />
|
||||
<view class="product-details">
|
||||
<view class="product-name">{{orderItem.product.name}}</view>
|
||||
<view class="product-spec" wx:if="{{orderItem.product_spec}}">{{orderItem.product_spec}}</view>
|
||||
<view class="product-price">
|
||||
<price price="{{orderItem.price}}" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 评分 -->
|
||||
<view class="rating-section">
|
||||
<view class="section-title">商品评分</view>
|
||||
<t-rate
|
||||
value="{{rating}}"
|
||||
size="60rpx"
|
||||
color="#ff6b35"
|
||||
bind:change="onRatingChange"
|
||||
allow-half="{{false}}"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 评论内容 -->
|
||||
<view class="content-section">
|
||||
<view class="section-title">评价内容</view>
|
||||
<t-textarea
|
||||
value="{{content}}"
|
||||
placeholder="请输入您的评价内容..."
|
||||
maxlength="{{maxContentLength}}"
|
||||
indicator="{{true}}"
|
||||
autosize="{{true}}"
|
||||
bind:change="onContentInput"
|
||||
t-class="comment-textarea"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 图片上传 -->
|
||||
<view class="images-section">
|
||||
<view class="section-title">上传图片(可选)</view>
|
||||
<view class="images-grid">
|
||||
<view
|
||||
class="image-item"
|
||||
wx:for="{{images}}"
|
||||
wx:key="index"
|
||||
bind:tap="onPreviewImage"
|
||||
data-index="{{index}}"
|
||||
>
|
||||
<image src="{{item}}" mode="aspectFill" class="uploaded-image" />
|
||||
<view
|
||||
class="delete-btn"
|
||||
bind:tap="onDeleteImage"
|
||||
data-index="{{index}}"
|
||||
catch:tap="true"
|
||||
>
|
||||
<t-icon name="close" size="24rpx" color="#fff" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="add-image-btn"
|
||||
wx:if="{{images.length < maxImages}}"
|
||||
bind:tap="onChooseImage"
|
||||
>
|
||||
<t-icon name="add" size="48rpx" color="#999" />
|
||||
<text class="add-text">添加图片</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="images-tip">最多可上传{{maxImages}}张图片</view>
|
||||
</view>
|
||||
|
||||
<!-- 匿名评论 -->
|
||||
<view class="anonymous-section">
|
||||
<view class="anonymous-item">
|
||||
<text class="anonymous-label">匿名评论</text>
|
||||
<t-switch
|
||||
value="{{isAnonymous}}"
|
||||
bind:change="onAnonymousChange"
|
||||
size="large"
|
||||
/>
|
||||
</view>
|
||||
<view class="anonymous-tip">开启后,您的用户名将不会显示</view>
|
||||
</view>
|
||||
|
||||
<!-- 提交按钮 -->
|
||||
<view class="submit-section">
|
||||
<t-button
|
||||
theme="primary"
|
||||
size="large"
|
||||
loading="{{submitting}}"
|
||||
disabled="{{submitting}}"
|
||||
bind:tap="onSubmit"
|
||||
t-class="submit-btn"
|
||||
>
|
||||
{{submitting ? '提交中...' : '提交评价'}}
|
||||
</t-button>
|
||||
</view>
|
||||
|
||||
<!-- Toast -->
|
||||
<t-toast id="t-toast" />
|
||||
</view>
|
||||
179
miniprogram/pages/order/comment/index.wxss
Normal file
179
miniprogram/pages/order/comment/index.wxss
Normal file
@@ -0,0 +1,179 @@
|
||||
.comment-page {
|
||||
background-color: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
padding-bottom: 120rpx;
|
||||
}
|
||||
|
||||
/* 商品信息 */
|
||||
.product-info {
|
||||
background: #fff;
|
||||
padding: 32rpx;
|
||||
margin-bottom: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.product-image {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 12rpx;
|
||||
margin-right: 24rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.product-details {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.product-name {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
margin-bottom: 8rpx;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.product-spec {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.product-price {
|
||||
font-size: 28rpx;
|
||||
color: #ff6b35;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 评分区域 */
|
||||
.rating-section {
|
||||
background: #fff;
|
||||
padding: 32rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* 评论内容 */
|
||||
.content-section {
|
||||
background: #fff;
|
||||
padding: 32rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.comment-textarea {
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
/* 图片上传 */
|
||||
.images-section {
|
||||
background: #fff;
|
||||
padding: 32rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.images-grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16rpx;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.image-item {
|
||||
position: relative;
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
}
|
||||
|
||||
.uploaded-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 12rpx;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
position: absolute;
|
||||
top: -8rpx;
|
||||
right: -8rpx;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.add-image-btn {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
border: 2rpx dashed #ddd;
|
||||
border-radius: 12rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.add-text {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.images-tip {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
/* 匿名评论 */
|
||||
.anonymous-section {
|
||||
background: #fff;
|
||||
padding: 32rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.anonymous-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.anonymous-label {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.anonymous-tip {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
/* 提交按钮 */
|
||||
.submit-section {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: #fff;
|
||||
padding: 24rpx 32rpx;
|
||||
border-top: 1rpx solid #eee;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 100%;
|
||||
height: 88rpx;
|
||||
border-radius: 44rpx;
|
||||
}
|
||||
Reference in New Issue
Block a user