文章目录
前言一、意见反馈页面1. 业务逻辑2. 关键技术 二、意见反馈页面代码1.图片上传组件2.页面代码3.效果前言
对于需要收集产品上线后用户实际使用感受的,意见反馈绝对是一个很好用的功能,开发设计成本很低,却能获得比较显著的效果,但就因为是小功能,所以往往不被重视。如果一个产品是有长远发展规划的,个人觉得应该在产品的第一个版本上线的时候就应该配备意见反馈的功能,这里所能收集到的有需求,有 BUG,还有其他的,只要有问题,就能找到解决的办法,没有任何反馈的时候,就只能靠产品的规划和设计师的水平了,当然也不是一味的遵循用户的意见,但绝对是一个非常好的参考来源。
一、意见反馈页面
1. 业务逻辑
点击 + 可以选择本地图⽚,并且显⽰到⻚⾯上点击 提交 可以上传图⽚到 接⼝ 地址 新浪图床 上点击图⽚,会移除⾃⼰点击 tab栏的标题,可以切换选中效果2. 关键技术
⾃定义组件 tab⾃定义组件 图⽚删除组件⼩程序 上传⽂件 api二、意见反馈页面代码
1.图片上传组件
<view class="up_img_wrap"><image src="{{src}}"></image><icon type="clear" size="23" color="red"></icon></view>
// components/UpImg/UpImg.jsComponent({/*** 组件的属性列表*/properties: {src:{type:String,value:""}},/*** 组件的初始数据*/data: {},/*** 组件的方法列表*/methods: {}})
.up_img_wrap{width: 90rpx;height: 90rpx;position: relative;}.up_img_wrap image{width: 100%;height: 100%;border-radius: 15rpx;}.up_img_wrap icon{position: absolute;top:-22rpx;right: -22rpx;}
2.页面代码
<Tabs tabs="{{tabs}}" bindtabsItemChange="handleTabsItemChange" ><view class="fb_main"><view class="fb_title">问题的种类</view><view class="fb_tips"><text>功能建议</text><text>购买遇到问题</text><text>性能问题</text><text>其他</text></view><view class="fb_content"><textarea value="{{textVal}}" bindinput="handleTextInput" placeholder="请描述一下您的问题"> </textarea><view class="fb_tool"><button bindtap="handleChooseImg">+</button><view class="up_img_item"wx:for="{{chooseImgs}}"wx:key="*this"bindtap="handleRemoveImg"data-index="{{index}}"><UpImg src="{{item}}" ></UpImg></view></view></view><view class="form_btn_wrap"><button bindtap="handleFormSubmit" type="warn" ><icon type="success_no_circle" size="23" color="white"></icon>提交</button></view></view></Tabs>
/* 1 点击 “+” 触发tap点击事件1 调用小程序内置的 选择图片的 api2 获取到 图片的路径 数组3 把图片路径 存到 data的变量中4 页面就可以根据 图片数组 进行循环显示 自定义组件2 点击 自定义图片 组件1 获取被点击的元素的索引2 获取 data中的图片数组3 根据索引 数组中删除对应的元素4 把数组重新设置回data中3 点击 “提交”1 获取文本域的内容 类似 输入框的获取1 data中定义变量 表示 输入框内容2 文本域 绑定 输入事件 事件触发的时候 把输入框的值 存入到变量中 2 对这些内容 合法性验证3 验证通过 用户选择的图片 上传到专门的图片的服务器 返回图片外网的链接1 遍历图片数组 2 挨个上传3 自己再维护图片数组 存放 图片上传后的外网的链接4 文本域 和 外网的图片的路径 一起提交到服务器 前端的模拟 不会发送请求到后台。。。 5 清空当前页面6 返回上一页 */Page({data: {tabs: [{id: 0,value: "体验问题",isActive: true},{id: 1,value: "商品、商家投诉",isActive: false}],// 被选中的图片路径 数组chooseImgs: [],// 文本域的内容textVal: ""},// 外网的图片的路径数组UpLoadImgs: [],handleTabsItemChange(e) {// 1 获取被点击的标题索引const {index } = e.detail;// 2 修改源数组let {tabs } = this.data;tabs.forEach((v, i) => i === index ? v.isActive = true : v.isActive = false);// 3 赋值到data中this.setData({tabs})},// 点击 “+” 选择图片handleChooseImg() {// 2 调用小程序内置的选择图片apiwx.chooseImage({// 同时选中的图片的数量count: 9,// 图片的格式 原图 压缩sizeType: ['original', 'compressed'],// 图片的来源 相册 照相机sourceType: ['album', 'camera'],success: (result) => {this.setData({// 图片数组 进行拼接 chooseImgs: [...this.data.chooseImgs, ...result.tempFilePaths]})}});},// 点击 自定义图片组件handleRemoveImg(e) {// 2 获取被点击的组件的索引const {index } = e.currentTarget.dataset;// 3 获取data中的图片数组let {chooseImgs } = this.data;// 4 删除元素chooseImgs.splice(index, 1);this.setData({chooseImgs})},// 文本域的输入的事件handleTextInput(e) {this.setData({textVal: e.detail.value})},// 提交按钮的点击handleFormSubmit() {// 1 获取文本域的内容 图片数组const {textVal, chooseImgs } = this.data;// 2 合法性的验证if (!textVal.trim()) {// 不合法wx.showToast({title: '输入不合法',icon: 'none',mask: true});return;}// 3 准备上传图片 到专门的图片服务器 // 上传文件的 api 不支持 多个文件同时上传 遍历数组 挨个上传 // 显示正在等待的图片wx.showLoading({title: "正在上传中",mask: true});// 判断有没有需要上传的图片数组if (chooseImgs.length != 0) {chooseImgs.forEach((v, i) => {wx.uploadFile({// 图片要上传到哪里url: '/Home/Index/UploadAction/',// 被上传的文件的路径filePath: v,// 上传的文件的名称 后台来获取文件 filename: "file",// 顺带的文本信息formData: {},success: (result) => {console.log(result);let url = JSON.parse(result.data).url;this.UpLoadImgs.push(url);// 所有的图片都上传完毕了才触发 if (i === chooseImgs.length - 1) {wx.hideLoading();console.log("把文本的内容和外网的图片数组 提交到后台中");// 提交都成功了// 重置页面this.setData({textVal: "",chooseImgs: []})// 返回上一个页面wx.navigateBack({delta: 1});}}});})}else{wx.hideLoading();console.log("只是提交了文本");wx.navigateBack({delta: 1});}}})
page {background-color: #eeeeee;}.fb_main {padding: 20rpx;color: #666;}.fb_main .fb_tips {display: flex;flex-wrap: wrap;}.fb_main .fb_tips text {width: 30%;padding: 10rpx;text-align: center;background-color: #fff;margin: 20rpx 10rpx;}.fb_main .fb_content {background-color: #fff;margin-top: 20rpx;}.fb_main .fb_content textarea {padding: 10rpx;}.fb_main .fb_tool {display: flex;flex-wrap: wrap;padding-bottom: 30rpx;}.fb_main .fb_tool button {margin: 0;width: 90rpx;height: 90rpx;font-size: 60rpx;padding: 0;display: flex;justify-content: center;align-items: center;margin-left: 20rpx;margin-top: 20rpx;color: #ccc;}.fb_main .fb_tool .up_img_item {margin-left: 20rpx;margin-top: 20rpx;}.fb_main .form_btn_wrap {margin-top: 20rpx;display: flex;justify-content: flex-end;}.fb_main .form_btn_wrap button {margin: 0;width: 30%;}