小程序做线上商城就离不开交互,包括最重要的支付和订单评价系统。订单评价简单的只有商品评价,比较齐全的是商品和商家一起评价。
本文介绍的目录包含,商品评价,商家评价,星级评分,上传照片,以及评论字数限制。
目录:
(一)星级评分的写法
(二)评论区的字数显示和限制
(三)图片张数限制和上传到服务器
(四)完整代码
看看开发工具中的样品图:
在评论页中展示商品和商家两栏的评价内容,并且提交评价的时候也要区分开,将商品和商家的评论内容用数组的形式提交。
注意array和[object,object]的数据格式。
先说逻辑,因为两块其实是同一个功能,只不过是把方法名字区分为A和B,A和B的函数内容一样的,只有数据内容不一样。
所以这里是只讲A方法。
(一)先说星级评分方法;
<view class='stars'> <view class='text'>评分</view> <view class='star_list'> <block wx:for="{{stars}}" wx:key> <image class="star-image" name="defen" value="{{key}}" style="left: {{item*30}}rpx" src="{{key > item ?(key-item == 0?normalSrc:selectedSrc) : normalSrc}}"> <view class="item" style="left:0rpx" data-key="{{item+1}}" bindtap="selectRight"></view> </image> </block> </view> </view>
用数组来存储图片,wx:for来循环图片列表,五星,列表长度就是0-4总共5,10星则是0-9。
两张图片。一张是带颜色的作为点亮状态,一张是默认的作为默认状态。设置选中函数selectRight。点星星一次则将星星图片的位置从left位移多少个单位到点击的对应位置。反之则取消对应的星星选中。
函数:
//点击右边递增,否则递减,评分,商品+商家B selectRight (e) { var key = e.currentTarget.dataset.key; //评分 if (this.data.key == 1 && e.currentTarget.dataset.key == 1) { //只有一颗星的时候,再次点击,变为0颗 key = 0; } this.setData({ key: key }) },
(二)评论区的字数显示和限制。
方法,给textarea一个最大的length.max-length =300.然后给输入域一个获取输入的事件,bindInput。通过获取bindInput的value长度,来限制。
<view class='textarea'> <textarea id='advice' name="advice" type="text" maxlength="{{max}}" bindinput="inputs" value="{{advice}}" placeholder="请输入评价内容..." placeholder-class='p_s'></textarea> <view class='fontNum'>{{fontNum}}</view> </view>
JS中通过最大长度与输入长度的减法来动态改变fontNum剩余字数。
//字数限制 商品+商家B inputs (e) { var value = e.detail.value, len = parseInt(value.length); //最多字数限制 if (len > this.data.max) return; this.setData({ fontNum: 300-len //当前字数 }); },
(三)上传多张图片并发送到服务器
默认的API即可,但是图片地址需要转化。wx.chooseImage所给出的图片地址是本地,并没有存到服务器上,还需要保存到服务器上。
使用wx.request的方法。在回调的结果中,取出地址链接,存为数组或者单个url信息。与其他内容一起进行表单提交。
$uploadFile({ filePath: tempFilePaths[0], formData: { evaluateType: 'store' }, name: 'evaluteImage', url: 'v4/shop/file/uploadBySmall' }).then((res) => { if (res.isSuccess) { let url = res.resultData that.setData({ imgboxB: [url], imgboxB: imgboxB, }) //$toast('图片上传成功') } else { //$toast(res.message) } })
(四)完整代码
wxml:
<!--pages/addProComment/addProComment.wxml--> <form bindsubmit="hrSubmit"> <view class='content'> <view class='form'> <view class='stores'> <image src='{{goodsImg}}'></image> <view class='stor_t'>{{gooodsName}}</view> </view> <view class='stars'> <view class='text'>评分</view> <view class='star_list'> <block wx:for="{{stars}}" wx:key> <image class="star-image" name="defen" value="{{key}}" style="left: {{item*30}}rpx" src="{{key > item ?(key-item == 0?normalSrc:selectedSrc) : normalSrc}}"> <view class="item" style="left:0rpx" data-key="{{item+1}}" bindtap="selectRight"></view> </image> </block> </view> </view> <view class='textarea'> <textarea id='advice' name="advice" type="text" maxlength="{{max}}" bindinput="inputs" value="{{advice}}" placeholder="请输入评价内容..." placeholder-class='p_s'></textarea> <view class='fontNum'>{{fontNum}}</view> </view> <view class='up-pic'> <view class='flex pic-box'> <block wx:key="imgbox" wx:for="{{imgbox}}"> <view class='ap-box'> <view class='add-pic' name="Pics" value="{{item}}"> <image class='add-pic' src='{{item}}'></image> <view class='img-de' bindtap="clearPic" data-deindex='{{index}}'> <image class='img' src='/images/error.png'></image> </view> </view> </view> </block> <view class='add-pic add-photo' bindtap="uploadPic" wx:if="{{imgbox.length<4}}"> <image src='../../images/add.png' /> </view> </view> </view> </view> </view> <!-- 商家信息 --> <view class='content' wx:if="{{isTrue}}"> <view class='form'> <view class='stores'> <image src='{{goodsImg}}'></image> <view class='stor_t'>{{storeName}}</view> </view> <view class='stars'> <view class='text'>评分</view> <view class='star_list'> <block wx:for="{{starsB}}" wx:key> <image class="star-image" style="left: {{item*30}}rpx" src="{{keyB > item ?(keyB-item == 0?normalSrc:selectedSrc) : normalSrc}}"> <view class="item" style="left:0rpx" data-key="{{item+1}}" bindtap="selectRightB"></view> </image> </block> </view> </view> <view class='textarea'> <textarea id='advice' name="adviceB" type="text" maxlength="{{max}}" bindinput="inputsB" value="{{adviceB}}" placeholder="请输入评价内容..." placeholder-class='p_s'></textarea> <view class='fontNum'>{{fontNumB}}</view> </view> <view class='up-pic'> <view class='flex pic-box'> <block wx:key="imgboxB" wx:for="{{imgboxB}}"> <view class='ap-box'> <view class='add-pic'> <image class='add-pic' src='{{item}}'></image> <view class='img-de' bindtap="clearPicB" data-deindex='{{index}}'> <image class='img' src='/images/error.png'></image> </view> </view> </view> </block> <view class='add-pic add-photo' bindtap="uploadPicB" wx:if="{{imgbox.length<4}}"> <image src='../../images/add.png' /> </view> </view> </view> </view> </view> <button class='submit' formType="submit"> 发布 </button> </form>
WXSS:
/* pages/addProComment/addProComment.wxss */ page{ background:#F5F5F2; } button::after{ border:none; } .content{ width:100%; margin:20rpx 0 0 0; background:#ffffff; } .form{ width:95%; margin:0 auto; padding:0 20rpx 0 20rpx; } .stores{ width:100%; display:flex; align-items: center; padding-top:30rpx; padding-bottom:30rpx; } .stores image{ width:45px; height:45px; border:1px solid #EBEBEB; } .stores .stor_t{ font-size:28rpx; color:#000; margin-left:30rpx; } .stars{ width:100%; height:40px; display:flex; align-items: center; border-top:1px solid #EBEBEB; border-bottom:1px solid #EBEBEB; } .stars .text{ font-size:30rpx; flex:1; } .stars .star_list{ flex:1; position:relative; margin-left:100rpx; } .textarea{ width: 100%; display: -webkit-flex; display: flex; -webkit-flex-direction: row; flex-direction: row; padding-top:20rpx; } .textarea .fontNum{ font-size:30rpx; line-height:40rpx; color:#333; } .textarea textarea{ -webkit-flex: 1; flex: 1; height:240rpx; font-size:26rpx; line-height: 42rpx; text-align: left; } .p_s{ font-size:30rpx; line-height:40rpx; color:#CCCCCC; } .submit { width: 100%; height:45px; margin:0 auto; margin-top: 25rpx; background:#00DF8C; color:#fff; font-size:32rpx; line-height:45px; border-radius:0; } .star-image { position: relative; width: 30rpx; height: 30rpx; } .item { position: absolute; top:0; width: 30rpx; height: 30rpx; } /* 上传图片 */ .flex{ display: flex; } .up-pic{ width: 100%; justify-content: center; } .pic-box{ flex-flow:wrap; width:100%; } .ap-box{ position: relative; width: 150rpx; height: 150rpx; margin:0 15rpx 20rpx 10rpx; } .add-pic{ width: 150rpx; height: 150rpx; position: relative; display: flex; align-items: center; justify-content: center; border-radius: 5rpx; } .add-photo{ margin-bottom:20rpx;border: 1px solid #DDDDDD;} .add-photo image{ width:100rpx; height:100rpx; } /* 删除图片 */ .img-de{ width:45rpx; height:45rpx; border-radius:50%; position:absolute; right:-30rpx; top:-15rpx; z-index:999; } .img-de .img { width:30rpx; height:30rpx; }
JS:
// pages/addProComment/addProComment.js const app = getApp() const $http = app.$http const $toast = app.$toast const $getLocation = app.$getLocation const setStorage = app.setStorage const getStorage = app.getStorage const cdnPath = app.cdnPath const makePhoneCall = app.makePhoneCall const $uploadFile = app.$uploadFile import wxx from '../../utils/wx.js' import { parseParam } from '../../utils/index.js' const baseUrl = app.baseUrl Page({ data: { cdnPath: cdnPath, goodsId: '', gooodsName: '', storeName: '', goodsImg: '', orderSn:'', openId: '', memberId: '', fontNum:300, fontNumB: 300, stars: [0, 1, 2, 3, 4], starsB: [0, 1, 2, 3, 4], normalSrc: cdnPath+'img/addProcoment/nostar.png', selectedSrc: cdnPath +'img/addProcoment/star.png', key: 0,//评分 keyB: 0,//评分 isTrue:true, //是否多个商家 imgbox: '', imgboxB: '' }, onLoad (opt) { if (opt.length == 2){ that.setData({ isTrue: true, }) } this.setData({ src: '', gooodsName: opt.gooodsName, storeName: opt.storeName, goodsImg: opt.goodsImage, goodsId: opt.goodsId, orderSn: opt.orderSn, openId: wx.getStorageSync('openId') || '', memberId: 1000000000243316 //wx.getStorageSync('memberId') || '' }) }, //点击右边递增,否则递减,评分,商品+商家B selectRight (e) { var key = e.currentTarget.dataset.key; //评分 if (this.data.key == 1 && e.currentTarget.dataset.key == 1) { //只有一颗星的时候,再次点击,变为0颗 key = 0; } this.setData({ key: key }) }, selectRightB (e) { var keyB = e.currentTarget.dataset.key; if (this.data.keyB == 1 && e.currentTarget.dataset.keyB == 1) { keyB = 0; } this.setData({ keyB: keyB }) }, //字数限制 商品+商家B inputs (e) { var value = e.detail.value, len = parseInt(value.length); //最多字数限制 if (len > this.data.max) return; this.setData({ fontNum: 300-len //当前字数 }); }, inputsB (e) { var value = e.detail.value, len = parseInt(value.length); if (len > this.data.max) return; this.setData({ fontNumB: 300 - len }); }, //发布评论不验证图片 hrSubmit (t) { //提交发布,商品+商家 var d = t.detail.value, orderSn = this.data.orderSn, memberId = this.data.memberId, evaG = JSON.stringify({ evaGoodsInfo: [{ goodsId: this.data.goodsId, evaGoodsGrade: this.data.key, evaGoodsContent: d.advice, evaGoodsImage: this.data.imgbox }]}), evaS = JSON.stringify({ evaStoreInfo: { evaServiceGrade: this.data.keyB, evaServiceContent: d.adviceB, evaStoreImage: this.data.imgboxB }}); $http({ url: `v4/shop/evaluate/goodsOrStore/${orderSn}/${memberId}`, //{orderSn}/{memberId} method: 'POST', data: { evaGoodsInfo:evaG, //商品评价 evaStoreInfo: evaS, //商家评价 inway:2 } }).then(response => { if (response.isSuccess === true) { $toast('评价成功!') setTimeout(() => { wx.navigateTo({ url: '/pages/myOrder/myOrder'}) }, 1000) } }).catch((error) => { console.log(error) }) }, //上传图片,商品+商家B uploadPic: function (e) { var that = this; var imgbox = this.data.imgbox; var picid = e.currentTarget.dataset.pic; var n = 4; if (4 > imgbox.length > 0) { n = 4 - imgbox.length; } else if (imgbox.length == 4) { n = 1; } wx.chooseImage({ count: n, // 默认数量 sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 success: function (res) { var tempFilePaths = res.tempFilePaths; if (imgbox.length == 0) { imgbox = tempFilePaths } else if (4 > imgbox.length) { imgbox = imgbox.concat(tempFilePaths); } else { imgbox[picid] = tempFilePaths[0]; } $uploadFile({ filePath: tempFilePaths[0], formData: { evaluateType: 'store' }, name: 'evaluteImage', url: 'v4/shop/file/uploadBySmall' }).then((res) => { if (res.isSuccess) { let url = res.resultData that.setData({ imgbox: [url], imgbox: imgbox, }) //$toast('图片上传成功') } else { //$toast(res.message) } }) } }) }, uploadPicB: function (e) { var that = this; var imgboxB = this.data.imgboxB; var picid = e.currentTarget.dataset.pic; var n = 4; if (4 > imgboxB.length > 0) { n = 4 - imgboxB.length; } else if (imgboxB.length == 4) { n = 1; } wx.chooseImage({ count: n, // 默认图片数量 sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success: function (res) { var tempFilePaths = res.tempFilePaths; if (imgboxB.length == 0) { imgboxB = tempFilePaths; } else if (4 > imgboxB.length) { imgboxB = imgboxB.concat(tempFilePaths); } else { imgboxB[picid] = tempFilePaths[0]; } $uploadFile({ filePath: tempFilePaths[0], formData: { evaluateType: 'store' }, name: 'evaluteImage', url: 'v4/shop/file/uploadBySmall' }).then((res) => { if (res.isSuccess) { let url = res.resultData that.setData({ imgboxB: [url], imgboxB: imgboxB, }) //$toast('图片上传成功') } else { //$toast(res.message) } }) } }) }, // 上传图片 uploadImgSuccess(res, file, fileList) { if (res.isSuccess) { let arr = res.resultData.split('/') this.data.imageListHD.push(arr[arr.length - 1]) } else { fileList.splice(-1, 1) $toast(res.message) return } }, //删除图片 clearPic: function (e) {//删除图片 let that = this; let index = e.currentTarget.dataset.deindex; let imgbox = this.data.imgbox; imgbox.splice(index, 1) that.setData({ imgbox: imgbox }); }, clearPicB: function (e) {//删除图片 let that = this; let index = e.currentTarget.dataset.deindex; let imgboxB = this.data.imgboxB; imgboxB.splice(index, 1) that.setData({ imgboxB: imgboxB }); }, onShareAppMessage: function () { } })
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自由互联。