| @ -0,0 +1,308 @@ | |||
| <template> | |||
| <view> | |||
| <uv-popup ref="popup" mode="bottom" bgColor="none" > | |||
| <view class="popup__view"> | |||
| <view class="flex header"> | |||
| <view class="title">评价</view> | |||
| <button class="btn" @click="close">关闭</button> | |||
| </view> | |||
| <view class="form"> | |||
| <uv-form | |||
| ref="form" | |||
| :model="form" | |||
| :rules="rules" | |||
| errorType="toast" | |||
| > | |||
| <view class="section"> | |||
| <productCard :data="detail"></productCard> | |||
| </view> | |||
| <view class="section"> | |||
| <view class="form-item"> | |||
| <uv-form-item prop="tripNum" :customStyle="formItemStyle"> | |||
| <view class="flex row"> | |||
| <view class="form-item-label">行程</view> | |||
| <view class="form-item-content"> | |||
| <formRate v-model="form.tripNum"></formRate> | |||
| </view> | |||
| </view> | |||
| </uv-form-item> | |||
| </view> | |||
| <view class="form-item"> | |||
| <uv-form-item prop="spotNum" :customStyle="formItemStyle"> | |||
| <view class="flex row"> | |||
| <view class="form-item-label">景点</view> | |||
| <view class="form-item-content"> | |||
| <formRate v-model="form.spotNum"></formRate> | |||
| </view> | |||
| </view> | |||
| </uv-form-item> | |||
| </view> | |||
| <view class="form-item"> | |||
| <uv-form-item prop="mentorNum" :customStyle="formItemStyle"> | |||
| <view class="flex row"> | |||
| <view class="form-item-label">导师</view> | |||
| <view class="form-item-content"> | |||
| <formRate v-model="form.mentorNum"></formRate> | |||
| </view> | |||
| </view> | |||
| </uv-form-item> | |||
| </view> | |||
| </view> | |||
| <view class="form-item"> | |||
| <uv-form-item prop="content" :customStyle="formItemStyle"> | |||
| <view class="form-item-content"> | |||
| <view class="tags"> | |||
| <view | |||
| v-for="(item, oIdx) in options" :key="oIdx" | |||
| :class="['tag', item === form.content ? 'is-active' : '']" | |||
| @click="onSelectContent(item)" | |||
| > | |||
| {{ item }} | |||
| </view> | |||
| </view> | |||
| </view> | |||
| </uv-form-item> | |||
| </view> | |||
| </uv-form> | |||
| </view> | |||
| <view class="footer"> | |||
| <button class="flex btn" @click="onPublish">发布</button> | |||
| </view> | |||
| </view> | |||
| </uv-popup> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import productCard from '@/pages_order/order/components/productCard.vue' | |||
| import formRate from '@/pages_order/components/formRate.vue' | |||
| export default { | |||
| components: { | |||
| productCard, | |||
| formRate, | |||
| }, | |||
| data() { | |||
| return { | |||
| id: null, | |||
| // todo: fetch | |||
| detail: {}, | |||
| form: { | |||
| tripNum: null, | |||
| spotNum: null, | |||
| mentorNum: null, | |||
| content: null, | |||
| }, | |||
| rules: { | |||
| 'tripNum': { | |||
| type: 'number', | |||
| required: true, | |||
| message: '请为行程打分', | |||
| }, | |||
| 'spotNum': { | |||
| type: 'number', | |||
| required: true, | |||
| message: '请为景点打分', | |||
| }, | |||
| 'mentorNum': { | |||
| type: 'number', | |||
| required: true, | |||
| message: '请为导师打分', | |||
| }, | |||
| 'content': { | |||
| type: 'string', | |||
| required: true, | |||
| message: '请选择评语', | |||
| }, | |||
| }, | |||
| // todo: fetch | |||
| options: [], | |||
| } | |||
| }, | |||
| methods: { | |||
| async getData() { | |||
| // todo: fetch order product | |||
| }, | |||
| async open(id) { | |||
| this.id = id | |||
| await this.getData() | |||
| this.form = { | |||
| tripNum: null, | |||
| spotNum: null, | |||
| mentorNum: null, | |||
| content: null, | |||
| } | |||
| this.$refs.popup.open() | |||
| }, | |||
| close() { | |||
| this.$refs.popup.close() | |||
| }, | |||
| onSelectContent(content) { | |||
| this.form.content = content | |||
| }, | |||
| async onPublish() { | |||
| try { | |||
| await this.$refs.form.validate() | |||
| const { | |||
| } = this.form | |||
| const params = { | |||
| } | |||
| // todo: fetch | |||
| // await this.$fetch('updateAddress', params) | |||
| uni.showToast({ | |||
| icon: 'success', | |||
| title: '发布成功', | |||
| }); | |||
| this.$emit('submitted') | |||
| this.close() | |||
| } catch (err) { | |||
| console.log('onSave err', err) | |||
| } | |||
| }, | |||
| }, | |||
| } | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| .popup__view { | |||
| width: 100vw; | |||
| display: flex; | |||
| flex-direction: column; | |||
| box-sizing: border-box; | |||
| background: #FFFFFF; | |||
| border-top-left-radius: 32rpx; | |||
| border-top-right-radius: 32rpx; | |||
| } | |||
| .header { | |||
| position: relative; | |||
| width: 100%; | |||
| padding: 24rpx 0; | |||
| box-sizing: border-box; | |||
| border-bottom: 2rpx solid #EEEEEE; | |||
| .title { | |||
| font-family: PingFang SC; | |||
| font-weight: 500; | |||
| font-size: 34rpx; | |||
| line-height: 1.4; | |||
| color: #181818; | |||
| } | |||
| .btn { | |||
| font-family: PingFang SC; | |||
| font-weight: 500; | |||
| font-size: 32rpx; | |||
| line-height: 1.4; | |||
| color: #8B8B8B; | |||
| position: absolute; | |||
| top: 26rpx; | |||
| left: 40rpx; | |||
| } | |||
| } | |||
| .section { | |||
| & + & { | |||
| margin-top: 24rpx; | |||
| } | |||
| } | |||
| .form { | |||
| max-height: 75vh; | |||
| padding: 32rpx 40rpx; | |||
| box-sizing: border-box; | |||
| overflow-y: auto; | |||
| &-item { | |||
| &-label { | |||
| margin-bottom: 14rpx; | |||
| display: flex; | |||
| align-items: center; | |||
| font-family: PingFang SC; | |||
| font-weight: 400; | |||
| font-size: 26rpx; | |||
| line-height: 1.4; | |||
| color: #181818; | |||
| .icon { | |||
| margin-right: 8rpx; | |||
| width: 16rpx; | |||
| height: auto; | |||
| } | |||
| } | |||
| &-content { | |||
| } | |||
| } | |||
| } | |||
| .row { | |||
| justify-content: space-between; | |||
| padding: 4rpx 0; | |||
| & + & { | |||
| margin-top: 4rpx; | |||
| } | |||
| .form-label { | |||
| margin: 0; | |||
| } | |||
| } | |||
| .tags { | |||
| display: grid; | |||
| grid-template-columns: repeat(2, 1fr); | |||
| gap: 24rpx; | |||
| } | |||
| .tag { | |||
| min-width: 0; | |||
| padding: 16rpx; | |||
| font-size: 26rpx; | |||
| line-height: 1.4; | |||
| color: #252545; | |||
| background: #F5F8FF; | |||
| border-radius: 24rpx; | |||
| &.is-active { | |||
| color: #FFFFFF; | |||
| background: #00A9FF; | |||
| } | |||
| } | |||
| .footer { | |||
| width: 100%; | |||
| padding: 32rpx 40rpx; | |||
| box-sizing: border-box; | |||
| border-top: 2rpx solid #F1F1F1; | |||
| .btn { | |||
| width: 100%; | |||
| padding: 14rpx 0; | |||
| box-sizing: border-box; | |||
| font-family: PingFang SC; | |||
| font-weight: 500; | |||
| font-size: 36rpx; | |||
| line-height: 1.4; | |||
| color: #FFFFFF; | |||
| background-image: linear-gradient(to right, #21FEEC, #019AF9); | |||
| border: 2rpx solid #00A9FF; | |||
| border-radius: 41rpx; | |||
| } | |||
| } | |||
| </style> | |||
| @ -1,270 +0,0 @@ | |||
| <template> | |||
| <view class="page__view"> | |||
| <navbar title="立即评价" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="#F3F2F7" /> | |||
| <view class="main form"> | |||
| <uv-form | |||
| ref="form" | |||
| :model="form" | |||
| :rules="rules" | |||
| errorType="toast" | |||
| > | |||
| <view class="card info"> | |||
| <view class="card-header">评价信息</view> | |||
| <view class="form-item"> | |||
| <uv-form-item prop="content" :customStyle="formItemStyle"> | |||
| <view class="form-item-label">评价内容</view> | |||
| <view class="form-item-content"> | |||
| <formTextarea v-model="form.content"></formTextarea> | |||
| </view> | |||
| </uv-form-item> | |||
| </view> | |||
| <view class="form-item"> | |||
| <uv-form-item prop="images" :customStyle="formItemStyle"> | |||
| <view class="form-item-label">上传图片/视频(选填)</view> | |||
| <view class="form-item-content"> | |||
| <formUpload v-model="form.images"></formUpload> | |||
| </view> | |||
| </uv-form-item> | |||
| </view> | |||
| </view> | |||
| <view class="card"> | |||
| <view class="form-item"> | |||
| <uv-form-item prop="productNum" :customStyle="formItemStyle"> | |||
| <view class="flex row"> | |||
| <view class="form-item-label">产品服务度</view> | |||
| <view class="form-item-content"> | |||
| <uv-rate v-model="form.productNum" size="48rpx" gutter="16rpx" activeColor="#F7BA1E" :allowHalf="true" :minCount="0.5" ></uv-rate> | |||
| </view> | |||
| </view> | |||
| </uv-form-item> | |||
| </view> | |||
| <view class="form-item"> | |||
| <uv-form-item prop="paperNum" :customStyle="formItemStyle"> | |||
| <view class="flex row"> | |||
| <view class="form-item-label">问卷体验</view> | |||
| <view class="form-item-content"> | |||
| <uv-rate v-model="form.paperNum" size="48rpx" gutter="16rpx" activeColor="#F7BA1E" :allowHalf="true" :minCount="0.5" ></uv-rate> | |||
| </view> | |||
| </view> | |||
| </uv-form-item> | |||
| </view> | |||
| <view class="form-item"> | |||
| <uv-form-item prop="logisticsNum" :customStyle="formItemStyle"> | |||
| <view class="flex row"> | |||
| <view class="form-item-label">物流速度</view> | |||
| <view class="form-item-content"> | |||
| <uv-rate v-model="form.logisticsNum" size="48rpx" gutter="16rpx" activeColor="#F7BA1E" :allowHalf="true" :minCount="0.5" ></uv-rate> | |||
| </view> | |||
| </view> | |||
| </uv-form-item> | |||
| </view> | |||
| </view> | |||
| </uv-form> | |||
| </view> | |||
| <view class="bottom"> | |||
| <button class="btn" @click="onSubmit">提交申请</button> | |||
| </view> | |||
| </view> | |||
| </template> | |||
| <script> | |||
| import { mapState } from 'vuex' | |||
| import formTextarea from '@/pages_order/components/formTextarea.vue' | |||
| import formUpload from '@/pages_order/components/formUpload.vue' | |||
| export default { | |||
| components: { | |||
| formTextarea, | |||
| formUpload, | |||
| }, | |||
| data() { | |||
| return { | |||
| orderId: null, | |||
| form: { | |||
| content: null, | |||
| images: [], | |||
| productNum: null, | |||
| paperNum: null, | |||
| logisticsNum: null, | |||
| }, | |||
| rules: { | |||
| 'content': { | |||
| type: 'string', | |||
| required: true, | |||
| message: '请输入评价', | |||
| }, | |||
| 'productNum': { | |||
| type: 'number', | |||
| required: true, | |||
| message: '请为【产品服务度】打分', | |||
| }, | |||
| 'paperNum': { | |||
| type: 'number', | |||
| required: true, | |||
| message: '请为【问卷体验】打分', | |||
| }, | |||
| 'logisticsNum': { | |||
| type: 'number', | |||
| required: true, | |||
| message: '请为【物流速度】打分', | |||
| }, | |||
| }, | |||
| formItemStyle: { padding: 0 }, | |||
| } | |||
| }, | |||
| computed: { | |||
| ...mapState(['userInfo']), | |||
| }, | |||
| onLoad(arg) { | |||
| const { orderId } = arg | |||
| this.orderId = orderId | |||
| }, | |||
| methods: { | |||
| async onSubmit() { | |||
| try { | |||
| await this.$refs.form.validate() | |||
| const { | |||
| content, | |||
| images, | |||
| productNum, | |||
| paperNum, | |||
| logisticsNum, | |||
| } = this.form | |||
| const params = { | |||
| orderId: this.orderId, | |||
| content, | |||
| image: images.join(','), | |||
| productNum, | |||
| paperNum, | |||
| logisticsNum, | |||
| } | |||
| await this.$fetch('evaluateOrder', params) | |||
| uni.showToast({ | |||
| icon: 'success', | |||
| title: '提交成功', | |||
| }); | |||
| setTimeout(() => { | |||
| this.$utils.navigateBack() | |||
| }, 800) | |||
| } catch (err) { | |||
| console.log('onSubmit err', err) | |||
| } | |||
| }, | |||
| }, | |||
| } | |||
| </script> | |||
| <style scoped lang="scss"> | |||
| .page__view { | |||
| width: 100vw; | |||
| min-height: 100vh; | |||
| background-color: $uni-bg-color; | |||
| position: relative; | |||
| /deep/ .nav-bar__view { | |||
| position: fixed; | |||
| top: 0; | |||
| left: 0; | |||
| } | |||
| } | |||
| .main { | |||
| padding: calc(var(--status-bar-height) + 144rpx) 32rpx 236rpx 32rpx; | |||
| } | |||
| .card { | |||
| padding: 32rpx; | |||
| background: #FFFFFF; | |||
| border: 2rpx solid #FFFFFF; | |||
| border-radius: 32rpx; | |||
| & + & { | |||
| margin-top: 40rpx; | |||
| } | |||
| &-header { | |||
| font-family: PingFang SC; | |||
| font-weight: 500; | |||
| font-size: 36rpx; | |||
| line-height: 1.4; | |||
| color: #252545; | |||
| margin-bottom: 32rpx; | |||
| } | |||
| } | |||
| .form { | |||
| &-item { | |||
| border-bottom: 2rpx solid #EEEEEE; | |||
| &:last-child { | |||
| border: none; | |||
| } | |||
| & + & { | |||
| margin-top: 32rpx; | |||
| } | |||
| &-label { | |||
| font-family: PingFang SC; | |||
| font-weight: 400; | |||
| font-size: 26rpx; | |||
| line-height: 1.4; | |||
| color: #181818; | |||
| } | |||
| } | |||
| } | |||
| .info { | |||
| .form-item + .form-item { | |||
| margin-top: 40rpx; | |||
| } | |||
| .form-item-content { | |||
| margin-top: 16rpx; | |||
| } | |||
| } | |||
| .row { | |||
| justify-content: space-between; | |||
| } | |||
| .bottom { | |||
| position: fixed; | |||
| left: 0; | |||
| bottom: 0; | |||
| width: 100vw; | |||
| // height: 200rpx; | |||
| padding: 24rpx 40rpx; | |||
| padding-bottom: calc(env(safe-area-inset-bottom) + 24rpx); | |||
| background: #FFFFFF; | |||
| box-sizing: border-box; | |||
| .btn { | |||
| width: 100%; | |||
| padding: 16rpx 0; | |||
| box-sizing: border-box; | |||
| font-family: PingFang SC; | |||
| font-weight: 500; | |||
| font-size: 36rpx; | |||
| line-height: 1; | |||
| color: #FFFFFF; | |||
| background-image: linear-gradient(to right, #4B348F, #845CFA); | |||
| border-radius: 41rpx; | |||
| } | |||
| } | |||
| </style> | |||