- 新增订单取消弹窗组件,支持用户取消订单并填写取消原因 - 添加订单评价页面,用户可对已完成订单进行星级评分和文字评价 - 新增伴宠师选择页面,用户可选择之前服务过的伴宠师 - 在订单详情页和订单列表页集成取消订单和评价订单功能 - 优化订单操作流程,提升用户体验master
| @ -0,0 +1,55 @@ | |||||
| <template> | |||||
| <view class="configPopup"> | |||||
| <uv-popup :show="showConfirmOrder" mode="bottom" @close="close" :round="10" :closeable="true" | |||||
| > | |||||
| <view class="content"> | |||||
| <up-parse :content="content"></up-parse> | |||||
| </view> | |||||
| </uv-popup> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import { mapState, mapGetters } from 'vuex' | |||||
| export default { | |||||
| name: 'configPoup', | |||||
| data() { | |||||
| return { | |||||
| content : '', | |||||
| showConfirmOrder : false, | |||||
| } | |||||
| }, | |||||
| onShow(){ | |||||
| }, | |||||
| methods: { | |||||
| //打开配置信息菜单 | |||||
| open(key){ | |||||
| this.content = this.configList[key].paramValueArea | |||||
| this.showConfirmOrder = true | |||||
| }, | |||||
| openText(content){ | |||||
| this.content = content | |||||
| this.showConfirmOrder = true | |||||
| }, | |||||
| close(){ | |||||
| this.showConfirmOrder = false | |||||
| }, | |||||
| }, | |||||
| computed : { | |||||
| ...mapGetters(['configList']) | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .configPopup { | |||||
| .content{ | |||||
| min-height: 50vh; | |||||
| max-height: 70vh; | |||||
| padding: 30rpx 20rpx; | |||||
| overflow: scroll; | |||||
| height: 100%; | |||||
| box-sizing: border-box; | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,216 @@ | |||||
| <template> | |||||
| <uv-popup ref="popup" :safeAreaInsetBottom="false" :round="10"> | |||||
| <view class="cancel-popup"> | |||||
| <view class="popup-content"> | |||||
| <view class="popup-header"> | |||||
| <text class="popup-title">取消订单</text> | |||||
| </view> | |||||
| <view class="popup-body"> | |||||
| <text class="popup-text">请添加客服微信,方便为您解决订单疑问或退订服务</text> | |||||
| <view class="qrcode-container"> | |||||
| <image class="qrcode-image" :src="qrCodeUrl" mode="aspectFit" :show-menu-by-longpress="true"></image> | |||||
| </view> | |||||
| <text class="popup-text">取消订单原因(选填)</text> | |||||
| <view class="reason-container"> | |||||
| <textarea class="reason-input" v-model="cancelReason" placeholder="请填写取消原因,方便我们提升服务"></textarea> | |||||
| </view> | |||||
| </view> | |||||
| <view class="popup-footer"> | |||||
| <view class="popup-btn cancel-btn" @click="close"> | |||||
| <text>不取消</text> | |||||
| </view> | |||||
| <view class="popup-btn confirm-btn" @click="confirmCancel"> | |||||
| <text>确认取消</text> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </uv-popup> | |||||
| </template> | |||||
| <script> | |||||
| import { cancelOrder } from "@/api/system/user.js" | |||||
| export default { | |||||
| props: { | |||||
| qrCodeUrl: { | |||||
| type: String, | |||||
| default: 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/details/QR_Code.png' | |||||
| } | |||||
| }, | |||||
| data(){ | |||||
| return { | |||||
| order : {}, | |||||
| cancelReason: '', | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| // 打开弹窗 | |||||
| open(order){ | |||||
| this.order = order; | |||||
| this.$refs.popup.open(); | |||||
| }, | |||||
| // 关闭弹窗 | |||||
| close() { | |||||
| this.cancelReason = ''; // 清空取消原因 | |||||
| this.$refs.popup.close(); | |||||
| }, | |||||
| // 确认取消订单 | |||||
| confirmCancel() { | |||||
| if (!this.order || !this.order.id) { | |||||
| uni.showToast({ | |||||
| title: '订单信息不完整', | |||||
| icon: 'none' | |||||
| }); | |||||
| return; | |||||
| } | |||||
| // 显示加载中 | |||||
| uni.showLoading({ | |||||
| title: '处理中...' | |||||
| }); | |||||
| // 调用取消订单API | |||||
| cancelOrder(this.order.id, this.cancelReason).then(res => { | |||||
| uni.hideLoading(); | |||||
| if (res && res.code === 200) { | |||||
| // 成功 | |||||
| uni.showToast({ | |||||
| title: '订单已取消', | |||||
| icon: 'success' | |||||
| }); | |||||
| // 通知父组件订单已取消 | |||||
| this.$emit('cancel', this.order, this.cancelReason); | |||||
| // 关闭弹窗 | |||||
| this.close(); | |||||
| } else { | |||||
| // 失败 | |||||
| uni.showToast({ | |||||
| title: res?.msg || '取消失败,请联系客服', | |||||
| icon: 'none' | |||||
| }); | |||||
| } | |||||
| }).catch(error => { | |||||
| uni.hideLoading(); | |||||
| uni.showToast({ | |||||
| title: '取消失败,请稍后再试', | |||||
| icon: 'none' | |||||
| }); | |||||
| }); | |||||
| } | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .cancel-popup { | |||||
| // position: fixed; | |||||
| // top: 0; | |||||
| // left: 0; | |||||
| // right: 0; | |||||
| // bottom: 0; | |||||
| // z-index: 999; | |||||
| display: flex; | |||||
| justify-content: center; | |||||
| align-items: center; | |||||
| .popup-content { | |||||
| position: relative; | |||||
| width: 600rpx; | |||||
| background-color: #FFFFFF; | |||||
| border-radius: 12rpx; | |||||
| overflow: hidden; | |||||
| z-index: 1000; | |||||
| } | |||||
| .popup-header { | |||||
| padding: 30rpx; | |||||
| text-align: center; | |||||
| background-color: #FFAA48; | |||||
| } | |||||
| .popup-title { | |||||
| font-size: 32rpx; | |||||
| font-weight: bold; | |||||
| color: #fff; | |||||
| } | |||||
| .popup-body { | |||||
| padding: 30rpx; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| align-items: center; | |||||
| } | |||||
| .popup-text { | |||||
| font-size: 28rpx; | |||||
| color: #333333; | |||||
| margin-bottom: 20rpx; | |||||
| text-align: center; | |||||
| } | |||||
| .popup-subtext { | |||||
| font-size: 24rpx; | |||||
| color: #999999; | |||||
| margin-bottom: 20rpx; | |||||
| text-align: center; | |||||
| } | |||||
| .qrcode-container { | |||||
| width: 300rpx; | |||||
| height: 300rpx; | |||||
| margin: 20rpx 0; | |||||
| display: flex; | |||||
| justify-content: center; | |||||
| align-items: center; | |||||
| } | |||||
| .qrcode-image { | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| } | |||||
| .popup-footer { | |||||
| display: flex; | |||||
| border-top: 1px solid #EEEEEE; | |||||
| } | |||||
| .popup-btn { | |||||
| flex: 1; | |||||
| padding: 30rpx 0; | |||||
| text-align: center; | |||||
| font-size: 28rpx; | |||||
| } | |||||
| .cancel-btn { | |||||
| color: #666666; | |||||
| border-right: 1px solid #EEEEEE; | |||||
| } | |||||
| .confirm-btn { | |||||
| color: #FFAA48; | |||||
| } | |||||
| .reason-container { | |||||
| width: 100%; | |||||
| margin-bottom: 20rpx; | |||||
| background-color: #F7F7F7; | |||||
| border-radius: 8rpx; | |||||
| } | |||||
| .reason-input { | |||||
| width: 100%; | |||||
| height: 150rpx; | |||||
| font-size: 28rpx; | |||||
| color: #666; | |||||
| line-height: 1.5; | |||||
| padding: 20rpx; | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,190 @@ | |||||
| <template> | |||||
| <uv-popup ref="popup" :round="10"> | |||||
| <view class="companion-popup" v-if="type == 0"> | |||||
| <view class="popup-header"> | |||||
| <text class="popup-title">是否指定之前服务过的伴宠师</text> | |||||
| <view class="popup-close" @click="close"> | |||||
| <uni-icons type="close" size="20" color="#999"></uni-icons> | |||||
| </view> | |||||
| </view> | |||||
| <view class="popup-content"> | |||||
| <view class="option-item" @click="selectOption('yes')"> | |||||
| <text class="option-text">是</text> | |||||
| <view class="option-circle" :class="{'selected': selectedOption === 'yes'}"> | |||||
| <view class="option-inner" v-if="selectedOption === 'yes'"></view> | |||||
| </view> | |||||
| </view> | |||||
| <view class="option-item" @click="selectOption('no')"> | |||||
| <text class="option-text">否</text> | |||||
| <view class="option-circle" :class="{'selected': selectedOption === 'no'}"> | |||||
| <view class="option-inner" v-if="selectedOption === 'no'"></view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <view class="companion-popup" v-else> | |||||
| <view class="popup-header"> | |||||
| <text class="popup-title">请选择您喜欢的下单方式</text> | |||||
| <view class="popup-close" @click="close"> | |||||
| <uni-icons type="close" size="20" color="#999"></uni-icons> | |||||
| </view> | |||||
| </view> | |||||
| <view class="popup-content"> | |||||
| <view class="option-item" @click="selectOption('yes')"> | |||||
| <text class="option-text">系统下单</text> | |||||
| <view class="option-circle" :class="{'selected': selectedOption === 'yes'}"> | |||||
| <view class="option-inner" v-if="selectedOption === 'yes'"></view> | |||||
| </view> | |||||
| </view> | |||||
| <view class="option-item" @click="selectOption('no')"> | |||||
| <text class="option-text">指定伴宠师</text> | |||||
| <view class="option-circle" :class="{'selected': selectedOption === 'no'}"> | |||||
| <view class="option-inner" v-if="selectedOption === 'no'"></view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </uv-popup> | |||||
| </template> | |||||
| <script> | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| selectedOption: '', | |||||
| type : 0, | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| // 打开弹窗 | |||||
| open() { | |||||
| this.selectedOption = ''; | |||||
| this.type = 0; | |||||
| this.$refs.popup.open('bottom'); | |||||
| }, | |||||
| // 关闭弹窗 | |||||
| close() { | |||||
| this.$refs.popup.close(); | |||||
| }, | |||||
| // 选择选项 | |||||
| selectOption(option) { | |||||
| this.selectedOption = option; | |||||
| if(this.type == 1){ | |||||
| if (option === 'yes') { | |||||
| this.close(); | |||||
| setTimeout(() => { | |||||
| uni.navigateTo({ | |||||
| url: '/pages/newOrder/serviceNew' | |||||
| }); | |||||
| }, 300); | |||||
| } else if (option === 'no') { | |||||
| this.close(); | |||||
| setTimeout(() => { | |||||
| uni.navigateTo({ | |||||
| url: '/pages/companionPetList/companionPetList' | |||||
| }); | |||||
| }, 300); | |||||
| } | |||||
| return | |||||
| } | |||||
| // 如果选择"是",跳转到伴宠师选择页面 | |||||
| if (option === 'yes') { | |||||
| this.close(); | |||||
| setTimeout(() => { | |||||
| uni.navigateTo({ | |||||
| url: '/pages_order/order/companionSelect' | |||||
| }); | |||||
| }, 300); | |||||
| } else if (option === 'no') { | |||||
| this.type = 1; | |||||
| this.selectedOption = ''; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .companion-popup { | |||||
| position: relative; | |||||
| background-color: #FFFFFF; | |||||
| border-radius: 20rpx; | |||||
| .popup-header { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| padding: 30rpx 20rpx; | |||||
| position: relative; | |||||
| .popup-title { | |||||
| font-size: 32rpx; | |||||
| font-weight: bold; | |||||
| color: #333; | |||||
| text-align: center; | |||||
| } | |||||
| .popup-close { | |||||
| position: absolute; | |||||
| right: 20rpx; | |||||
| top: 30rpx; | |||||
| } | |||||
| } | |||||
| .popup-content { | |||||
| padding: 20rpx 30rpx 50rpx; | |||||
| .option-item { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: space-between; | |||||
| height: 100rpx; | |||||
| border-radius: 10rpx; | |||||
| background-color: #F8F8F8; | |||||
| margin-bottom: 20rpx; | |||||
| padding: 0 30rpx; | |||||
| // &:first-child { | |||||
| // background-color: #FFF9E6; | |||||
| // .option-text { | |||||
| // color: #FFAA48; | |||||
| // } | |||||
| // } | |||||
| &:last-child { | |||||
| margin-bottom: 0; | |||||
| } | |||||
| .option-text { | |||||
| font-size: 28rpx; | |||||
| color: #333; | |||||
| } | |||||
| .option-circle { | |||||
| width: 36rpx; | |||||
| height: 36rpx; | |||||
| border-radius: 50%; | |||||
| border: 2rpx solid #DDDDDD; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| &.selected { | |||||
| border-color: #FFAA48; | |||||
| } | |||||
| .option-inner { | |||||
| width: 24rpx; | |||||
| height: 24rpx; | |||||
| border-radius: 50%; | |||||
| background-color: #FFAA48; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,434 @@ | |||||
| <template> | |||||
| <view class="companion-select-page"> | |||||
| <!-- 顶部警告提示 --> | |||||
| <view class="warning-tip"> | |||||
| <view class="warning-icon"> | |||||
| <uni-icons type="info" size="16" color="#A94F20"></uni-icons> | |||||
| </view> | |||||
| <view class="warning-text"> | |||||
| <text>相距距离仅供参考!伴宠师位置可能不是实时位置,请提前10天下单!</text> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 伴宠师列表 --> | |||||
| <scroll-view scroll-y class="companion-scroll"> | |||||
| <view class="companion-list"> | |||||
| <view | |||||
| class="companion-item" | |||||
| v-for="(item, index) in companionList" | |||||
| :key="index" | |||||
| @click="selectCompanion(item)" | |||||
| :class="{'selected': selectedCompanionId === item.id}" | |||||
| > | |||||
| <!-- 左侧选中标记 --> | |||||
| <view class="select-icon"> | |||||
| <view class="radio-circle" :class="{'checked': selectedCompanionId === item.id}"> | |||||
| <view class="radio-inner" v-if="selectedCompanionId === item.id"></view> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 伴宠师卡片内容 --> | |||||
| <view class="companion-card"> | |||||
| <!-- 头像和基本信息 --> | |||||
| <view class="card-header"> | |||||
| <view class="companion-avatar"> | |||||
| <image :src="item.avatar" mode="aspectFill"></image> | |||||
| <image v-if="item.verified" class="verified-icon" src="/static/images/details/verified.svg"></image> | |||||
| </view> | |||||
| <view class="companion-basic-info"> | |||||
| <view class="companion-name-row"> | |||||
| <text class="companion-name">{{item.name}}</text> | |||||
| <image :src="item.gender === '男生' ? '/static/images/details/boy.svg' : '/static/images/details/girl.svg'" class="gender-icon"></image> | |||||
| </view> | |||||
| <view class="companion-rating"> | |||||
| <text class="client-rating">客户点赞: {{item.likes}}</text> | |||||
| <image src="/static/images/details/like.svg" class="like-icon"></image> | |||||
| </view> | |||||
| <view class="companion-distance"> | |||||
| <text>距离您: {{item.distance}} km</text> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 描述信息 --> | |||||
| <view class="companion-desc"> | |||||
| <text>{{item.description || '简介:有一只3岁金猫-忽悠,热爱小宠物...'}}</text> | |||||
| </view> | |||||
| <!-- 伴宠师经验描述 --> | |||||
| <view class="companion-experience"> | |||||
| <text>{{item.experience}}</text> | |||||
| </view> | |||||
| <!-- 查看详情按钮 --> | |||||
| <view class="view-detail-btn" @click.stop="viewCompanionDetail(item.id)"> | |||||
| <text>查看详情</text> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 无数据提示 --> | |||||
| <view class="no-data" v-if="companionList.length === 0"> | |||||
| <image src="/static/images/personal/no-data.png" mode="aspectFit"></image> | |||||
| <text>暂无伴宠师数据</text> | |||||
| </view> | |||||
| </view> | |||||
| </scroll-view> | |||||
| <!-- 底部按钮 --> | |||||
| <view class="footer-buttons"> | |||||
| <view class="cancel-btn" @click="cancel"> | |||||
| <text>取消</text> | |||||
| </view> | |||||
| <view class="confirm-btn" @click="confirm"> | |||||
| <text>确定</text> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| companionList: [ | |||||
| { | |||||
| id: '1', | |||||
| name: '宠物宝贝', | |||||
| gender: '男生', | |||||
| avatar: 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/details/QR_Code.png', | |||||
| verified: true, | |||||
| rating: 5.0, | |||||
| likes: 5601, | |||||
| distance: 10.8, | |||||
| description: '简介:有一只3岁金猫-忽悠,热爱小宠物...', | |||||
| experience: '养宠4年 | 评价11条 | 服务小结13份' | |||||
| }, | |||||
| { | |||||
| id: '2', | |||||
| name: '宠物宝贝', | |||||
| gender: '女生', | |||||
| avatar: 'https://catmdogf.oss-cn-shanghai.aliyuncs.com/CMDF/front/details/QR_Code.png', | |||||
| verified: true, | |||||
| rating: 5.0, | |||||
| likes: 5601, | |||||
| distance: 10.8, | |||||
| description: '简介:有一只3岁金猫-忽悠,热爱小宠物...', | |||||
| experience: '养宠4年 | 评价11条 | 服务小结13份' | |||||
| } | |||||
| ], | |||||
| selectedCompanionId: '', | |||||
| }; | |||||
| }, | |||||
| computed: { | |||||
| // 获取当前选中的伴宠师 | |||||
| selectedCompanion() { | |||||
| if (!this.selectedCompanionId) return null; | |||||
| return this.companionList.find(item => item.id === this.selectedCompanionId); | |||||
| } | |||||
| }, | |||||
| onLoad(options) { | |||||
| // 获取选择过的伴宠师列表 | |||||
| this.getServicedCompanions(); | |||||
| }, | |||||
| methods: { | |||||
| // 获取服务过的伴宠师 | |||||
| getServicedCompanions() { | |||||
| // 实际项目中应调用API获取服务过的伴宠师列表 | |||||
| // 示例代码: | |||||
| /* | |||||
| getServicedCompanions().then(res => { | |||||
| if (res && res.code === 200) { | |||||
| this.companionList = res.data || []; | |||||
| } | |||||
| }).catch(err => { | |||||
| console.error('获取服务过的伴宠师失败', err); | |||||
| }); | |||||
| */ | |||||
| // 使用模拟数据 | |||||
| console.log('获取服务过的伴宠师列表'); | |||||
| }, | |||||
| // 选择伴宠师 | |||||
| selectCompanion(companion) { | |||||
| this.selectedCompanionId = companion.id; | |||||
| }, | |||||
| // 取消选择 | |||||
| cancel() { | |||||
| uni.navigateBack(); | |||||
| }, | |||||
| // 确认选择 | |||||
| confirm() { | |||||
| if (!this.selectedCompanionId) { | |||||
| uni.showToast({ | |||||
| title: '请选择伴宠师', | |||||
| icon: 'none' | |||||
| }); | |||||
| return; | |||||
| } | |||||
| // 将选择的伴宠师信息返回给上一页 | |||||
| // 实际项目中应根据需求处理 | |||||
| // 示例代码: | |||||
| /* | |||||
| const pages = getCurrentPages(); | |||||
| const prevPage = pages[pages.length - 2]; | |||||
| prevPage.$vm.setSelectedCompanion(this.selectedCompanion); | |||||
| */ | |||||
| uni.navigateBack(); | |||||
| }, | |||||
| // 查看伴宠师详情 | |||||
| viewCompanionDetail(companionId) { | |||||
| // 跳转到伴宠师详情页面 | |||||
| uni.navigateTo({ | |||||
| url: `/pages/companionPetList/companionPetInfo?id=${companionId}` | |||||
| }); | |||||
| } | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .companion-select-page { | |||||
| background-color: #F5F5F5; | |||||
| min-height: 100vh; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| padding-bottom: 120rpx; | |||||
| } | |||||
| .warning-tip { | |||||
| background-color: #FFF4E5; | |||||
| padding: 20rpx 30rpx; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| margin: 20rpx; | |||||
| .warning-icon { | |||||
| margin-right: 10rpx; | |||||
| } | |||||
| .warning-text { | |||||
| flex: 1; | |||||
| font-size: 24rpx; | |||||
| color: #A94F20; | |||||
| line-height: 1.4; | |||||
| } | |||||
| } | |||||
| .companion-scroll { | |||||
| flex: 1; | |||||
| height: calc(100vh - 250rpx); | |||||
| } | |||||
| .companion-list { | |||||
| padding: 20rpx; | |||||
| } | |||||
| .companion-item { | |||||
| background-color: #FFFFFF; | |||||
| border-radius: 16rpx; | |||||
| padding: 20rpx; | |||||
| margin-bottom: 20rpx; | |||||
| display: flex; | |||||
| align-items: flex-start; | |||||
| box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); | |||||
| border: 2rpx solid #fff; | |||||
| .select-icon { | |||||
| width: 40rpx; | |||||
| height: 40rpx; | |||||
| margin-right: 20rpx; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| .radio-circle { | |||||
| width: 32rpx; | |||||
| height: 32rpx; | |||||
| border: 2rpx solid #DDDDDD; | |||||
| border-radius: 50%; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| &.checked { | |||||
| border-color: #FFAA48; | |||||
| } | |||||
| .radio-inner { | |||||
| width: 18rpx; | |||||
| height: 18rpx; | |||||
| background-color: #FFAA48; | |||||
| border-radius: 50%; | |||||
| } | |||||
| } | |||||
| } | |||||
| &.selected { | |||||
| border: 2rpx solid #FFAA48; | |||||
| } | |||||
| .companion-card { | |||||
| flex: 1; | |||||
| } | |||||
| .card-header { | |||||
| display: flex; | |||||
| margin-bottom: 16rpx; | |||||
| } | |||||
| .companion-avatar { | |||||
| position: relative; | |||||
| width: 100rpx; | |||||
| height: 100rpx; | |||||
| margin-right: 20rpx; | |||||
| image { | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| border-radius: 10rpx; | |||||
| } | |||||
| .verified-icon { | |||||
| position: absolute; | |||||
| right: -10rpx; | |||||
| bottom: -10rpx; | |||||
| width: 30rpx; | |||||
| height: 30rpx; | |||||
| } | |||||
| } | |||||
| .companion-basic-info { | |||||
| flex: 1; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| justify-content: center; | |||||
| } | |||||
| .companion-name-row { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| margin-bottom: 6rpx; | |||||
| .companion-name { | |||||
| font-size: 32rpx; | |||||
| font-weight: bold; | |||||
| color: #333; | |||||
| margin-right: 10rpx; | |||||
| } | |||||
| .gender-icon { | |||||
| width: 24rpx; | |||||
| height: 24rpx; | |||||
| } | |||||
| } | |||||
| .companion-rating { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| margin-bottom: 6rpx; | |||||
| .client-rating { | |||||
| font-size: 24rpx; | |||||
| color: #666; | |||||
| margin-right: 6rpx; | |||||
| } | |||||
| .like-icon { | |||||
| width: 24rpx; | |||||
| height: 24rpx; | |||||
| } | |||||
| } | |||||
| .companion-distance { | |||||
| font-size: 24rpx; | |||||
| color: #999; | |||||
| } | |||||
| .companion-desc { | |||||
| font-size: 24rpx; | |||||
| color: #666; | |||||
| margin-bottom: 16rpx; | |||||
| line-height: 1.4; | |||||
| } | |||||
| .companion-experience { | |||||
| font-size: 24rpx; | |||||
| color: #999; | |||||
| background-color: #FFF9E6; | |||||
| padding: 16rpx; | |||||
| border-radius: 8rpx; | |||||
| margin-bottom: 16rpx; | |||||
| color: #be721b; | |||||
| text-align: center; | |||||
| } | |||||
| .view-detail-btn { | |||||
| align-self: flex-end; | |||||
| background-color: #FFAA48; | |||||
| color: #FFFFFF; | |||||
| font-size: 26rpx; | |||||
| padding: 12rpx 30rpx; | |||||
| border-radius: 30rpx; | |||||
| text-align: center; | |||||
| width: fit-content; | |||||
| margin-left: auto; | |||||
| } | |||||
| } | |||||
| .no-data { | |||||
| text-align: center; | |||||
| padding: 100rpx 0; | |||||
| image { | |||||
| width: 200rpx; | |||||
| height: 200rpx; | |||||
| margin-bottom: 20rpx; | |||||
| } | |||||
| text { | |||||
| font-size: 28rpx; | |||||
| color: #999; | |||||
| } | |||||
| } | |||||
| .footer-buttons { | |||||
| position: fixed; | |||||
| bottom: 0; | |||||
| left: 0; | |||||
| right: 0; | |||||
| display: flex; | |||||
| padding: 20rpx 30rpx; | |||||
| background-color: #FFFFFF; | |||||
| box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05); | |||||
| .cancel-btn, .confirm-btn { | |||||
| flex: 1; | |||||
| height: 88rpx; | |||||
| line-height: 88rpx; | |||||
| text-align: center; | |||||
| border-radius: 44rpx; | |||||
| font-size: 30rpx; | |||||
| } | |||||
| .cancel-btn { | |||||
| background-color: #FFFFFF; | |||||
| color: #666; | |||||
| border: 1px solid #DDDDDD; | |||||
| margin-right: 20rpx; | |||||
| } | |||||
| .confirm-btn { | |||||
| background-color: #FFAA48; | |||||
| color: #FFFFFF; | |||||
| box-shadow: 0 4rpx 8rpx rgba(255, 170, 72, 0.3); | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,407 @@ | |||||
| <template> | |||||
| <view class="order-modify-page"> | |||||
| <!-- 页面头部 --> | |||||
| <view class="page-header"> | |||||
| <text class="header-title">修改订单</text> | |||||
| </view> | |||||
| <!-- 订单内容区域 --> | |||||
| <view class="order-modify-content"> | |||||
| <!-- 订单修改说明 --> | |||||
| <view class="modify-notice"> | |||||
| <view class="notice-item"> | |||||
| <text class="notice-icon">🐾</text> | |||||
| <text class="notice-text">您可以对<text class="highlight-text">未服务或未支付</text>的订单进行修改或取消</text> | |||||
| </view> | |||||
| <view class="notice-item"> | |||||
| <text class="notice-icon">🐾</text> | |||||
| <text class="notice-text">若需修改已支付的服务项目,如「增加服务时间/服务项目」,可点击下方按钮【<text class="highlight-text">联系客服</text>】寻求帮助,感谢!</text> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 服务修改信息 --> | |||||
| <view class="modify-info-card"> | |||||
| <view class="card-title"> | |||||
| <text>服务修改信息</text> | |||||
| </view> | |||||
| <view class="info-content"> | |||||
| <view class="info-item"> | |||||
| <text class="info-label">联系人</text> | |||||
| <text class="info-value">{{modifyInfo.contactName}}</text> | |||||
| </view> | |||||
| <view class="info-item"> | |||||
| <text class="info-label">联系方式</text> | |||||
| <text class="info-value">{{modifyInfo.contactPhone}}</text> | |||||
| </view> | |||||
| <view class="info-item payment-method"> | |||||
| <text class="info-label">销售支持方式</text> | |||||
| <view class="info-value payment-value"> | |||||
| <text>{{modifyInfo.paymentMethod}}</text> | |||||
| <text class="arrow-right">></text> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 修改原因 --> | |||||
| <view class="modify-reason-card"> | |||||
| <view class="card-title"> | |||||
| <text>修改原因</text> | |||||
| </view> | |||||
| <view class="reason-content"> | |||||
| <textarea | |||||
| class="reason-input" | |||||
| v-model="modifyReason" | |||||
| placeholder="请输入修改原因(选填)" | |||||
| maxlength="200" | |||||
| ></textarea> | |||||
| <view class="word-count"> | |||||
| <text>{{modifyReason.length}}/200</text> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 底部按钮区域 --> | |||||
| <view class="order-modify-footer"> | |||||
| <view class="footer-btn cancel-service-btn" @click="$refs.cancelPopup.open()"> | |||||
| <text>取消服务</text> | |||||
| </view> | |||||
| <view class="footer-btn confirm-modify-btn" @click="confirmModify"> | |||||
| <text>确认修改</text> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 取消订单弹窗 --> | |||||
| <cancel-order-popup | |||||
| ref="cancelPopup" | |||||
| @cancel="handleCancelOrder" | |||||
| ></cancel-order-popup> | |||||
| <!-- 客服组件 --> | |||||
| <Kefu></Kefu> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import CancelOrderPopup from '../../components/order/CancelOrderPopup.vue'; | |||||
| export default { | |||||
| components: { | |||||
| CancelOrderPopup | |||||
| }, | |||||
| data() { | |||||
| return { | |||||
| orderId: '', // 订单ID | |||||
| modifyInfo: { | |||||
| contactName: '张小二', | |||||
| contactPhone: '18888888888', | |||||
| paymentMethod: '存子快递宝' | |||||
| }, | |||||
| modifyReason: '', // 修改原因 | |||||
| showCancelOrderPopup: false // 是否显示取消订单弹窗 | |||||
| }; | |||||
| }, | |||||
| onLoad(options) { | |||||
| // 获取路由参数中的订单ID | |||||
| if (options.id) { | |||||
| this.orderId = options.id; | |||||
| // 加载订单数据 | |||||
| this.loadOrderData(); | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| // 加载订单数据 | |||||
| loadOrderData() { | |||||
| // 这里应该调用API获取订单详情 | |||||
| // 示例代码: | |||||
| /* | |||||
| const params = { | |||||
| openId: getOpenIdKey(), | |||||
| orderId: this.orderId | |||||
| }; | |||||
| getOrderDetail(params).then(res => { | |||||
| if (res && res.code === 200) { | |||||
| // 设置订单信息 | |||||
| this.modifyInfo = { | |||||
| contactName: res.data.contactName, | |||||
| contactPhone: res.data.contactPhone, | |||||
| paymentMethod: res.data.paymentMethod | |||||
| }; | |||||
| } | |||||
| }).catch(err => { | |||||
| console.error('获取订单详情失败', err); | |||||
| uni.showToast({ | |||||
| title: '获取订单信息失败', | |||||
| icon: 'none' | |||||
| }); | |||||
| }); | |||||
| */ | |||||
| // 这里使用模拟数据 | |||||
| console.log('加载订单数据,ID:', this.orderId); | |||||
| }, | |||||
| // 确认修改订单 | |||||
| confirmModify() { | |||||
| // 这里应该调用API修改订单 | |||||
| // 示例代码: | |||||
| /* | |||||
| const params = { | |||||
| openId: getOpenIdKey(), | |||||
| orderId: this.orderId, | |||||
| reason: this.modifyReason | |||||
| }; | |||||
| modifyOrder(params).then(res => { | |||||
| if (res && res.code === 200) { | |||||
| uni.showToast({ | |||||
| title: '订单修改成功', | |||||
| icon: 'success' | |||||
| }); | |||||
| // 修改成功后返回订单详情页 | |||||
| setTimeout(() => { | |||||
| uni.navigateBack(); | |||||
| }, 1500); | |||||
| } | |||||
| }).catch(err => { | |||||
| console.error('修改订单失败', err); | |||||
| uni.showToast({ | |||||
| title: '修改订单失败', | |||||
| icon: 'none' | |||||
| }); | |||||
| }); | |||||
| */ | |||||
| // 这里使用模拟数据,显示修改成功提示 | |||||
| uni.showToast({ | |||||
| title: '订单修改成功', | |||||
| icon: 'success' | |||||
| }); | |||||
| // 1.5秒后返回订单详情页 | |||||
| setTimeout(() => { | |||||
| uni.navigateBack(); | |||||
| }, 1500); | |||||
| }, | |||||
| // 处理取消订单 | |||||
| handleCancelOrder(orderId) { | |||||
| this.hideCancelPopup(); | |||||
| // 这里应该调用API取消订单 | |||||
| // 示例代码: | |||||
| /* | |||||
| const params = { | |||||
| openId: getOpenIdKey(), | |||||
| orderId: this.orderId, | |||||
| reason: this.modifyReason | |||||
| }; | |||||
| cancelOrder(params).then(res => { | |||||
| if (res && res.code === 200) { | |||||
| uni.showToast({ | |||||
| title: '订单已取消', | |||||
| icon: 'success' | |||||
| }); | |||||
| // 取消成功后返回订单列表页 | |||||
| setTimeout(() => { | |||||
| uni.navigateBack({delta: 2}); | |||||
| }, 1500); | |||||
| } | |||||
| }).catch(err => { | |||||
| console.error('取消订单失败', err); | |||||
| }); | |||||
| */ | |||||
| // 这里使用模拟数据,显示取消成功提示 | |||||
| uni.showToast({ | |||||
| title: '订单已取消', | |||||
| icon: 'success' | |||||
| }); | |||||
| // 1.5秒后返回订单列表页 | |||||
| setTimeout(() => { | |||||
| uni.navigateBack({delta: 2}); | |||||
| }, 1500); | |||||
| } | |||||
| } | |||||
| }; | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .order-modify-page { | |||||
| background-color: #f5f5f5; | |||||
| min-height: 100vh; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| } | |||||
| .page-header { | |||||
| background-color: #FFAA48; | |||||
| padding: 20rpx 30rpx; | |||||
| color: #FFFFFF; | |||||
| .header-title { | |||||
| font-size: 36rpx; | |||||
| font-weight: bold; | |||||
| } | |||||
| } | |||||
| .order-modify-content { | |||||
| flex: 1; | |||||
| padding: 20rpx; | |||||
| } | |||||
| .modify-notice { | |||||
| background-color: #FFF9F0; | |||||
| border-radius: 20rpx; | |||||
| padding: 20rpx; | |||||
| margin-bottom: 20rpx; | |||||
| .notice-item { | |||||
| display: flex; | |||||
| align-items: flex-start; | |||||
| margin-bottom: 10rpx; | |||||
| &:last-child { | |||||
| margin-bottom: 0; | |||||
| } | |||||
| .notice-icon { | |||||
| margin-right: 10rpx; | |||||
| font-size: 28rpx; | |||||
| } | |||||
| .notice-text { | |||||
| font-size: 26rpx; | |||||
| color: #666; | |||||
| line-height: 1.5; | |||||
| flex: 1; | |||||
| .highlight-text { | |||||
| color: #FFAA48; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .modify-info-card, .modify-reason-card { | |||||
| background-color: #FFFFFF; | |||||
| border-radius: 20rpx; | |||||
| padding: 30rpx; | |||||
| margin-bottom: 20rpx; | |||||
| box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); | |||||
| } | |||||
| .card-title { | |||||
| font-size: 32rpx; | |||||
| font-weight: bold; | |||||
| color: #333; | |||||
| margin-bottom: 20rpx; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| &::before { | |||||
| content: ''; | |||||
| display: inline-block; | |||||
| width: 8rpx; | |||||
| height: 32rpx; | |||||
| background-color: #FFAA48; | |||||
| margin-right: 16rpx; | |||||
| border-radius: 4rpx; | |||||
| } | |||||
| } | |||||
| .info-content { | |||||
| .info-item { | |||||
| display: flex; | |||||
| justify-content: space-between; | |||||
| align-items: center; | |||||
| padding: 20rpx 0; | |||||
| border-bottom: 1px solid #EEEEEE; | |||||
| &:last-child { | |||||
| border-bottom: none; | |||||
| } | |||||
| .info-label { | |||||
| font-size: 28rpx; | |||||
| color: #666; | |||||
| } | |||||
| .info-value { | |||||
| font-size: 28rpx; | |||||
| color: #333; | |||||
| } | |||||
| &.payment-method { | |||||
| .payment-value { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| .arrow-right { | |||||
| margin-left: 10rpx; | |||||
| color: #999; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .reason-content { | |||||
| .reason-input { | |||||
| width: 100%; | |||||
| height: 200rpx; | |||||
| background-color: #F8F8F8; | |||||
| border-radius: 10rpx; | |||||
| padding: 20rpx; | |||||
| font-size: 28rpx; | |||||
| color: #333; | |||||
| box-sizing: border-box; | |||||
| } | |||||
| .word-count { | |||||
| text-align: right; | |||||
| margin-top: 10rpx; | |||||
| text { | |||||
| font-size: 24rpx; | |||||
| color: #999; | |||||
| } | |||||
| } | |||||
| } | |||||
| .order-modify-footer { | |||||
| display: flex; | |||||
| justify-content: space-between; | |||||
| align-items: center; | |||||
| padding: 20rpx 30rpx; | |||||
| background-color: #FFFFFF; | |||||
| border-top: 1px solid #EEEEEE; | |||||
| .footer-btn { | |||||
| padding: 16rpx 30rpx; | |||||
| border-radius: 30rpx; | |||||
| font-size: 28rpx; | |||||
| text-align: center; | |||||
| width: 45%; | |||||
| } | |||||
| .cancel-service-btn { | |||||
| background-color: #F5F5F5; | |||||
| color: #666; | |||||
| border: 1px solid #DDDDDD; | |||||
| } | |||||
| .confirm-modify-btn { | |||||
| background-color: #FFAA48; | |||||
| color: #FFFFFF; | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,308 @@ | |||||
| <template> | |||||
| <view class="order-review-page"> | |||||
| <!-- 伴宠师信息区域 --> | |||||
| <view class="companion-info-card"> | |||||
| <view class="profile-header"> | |||||
| <view class="companion-avatar"> | |||||
| <image :src="companion.avatar" mode="aspectFill"></image> | |||||
| </view> | |||||
| <view class="companion-detail"> | |||||
| <view class="companion-name"> | |||||
| <text>{{companion.name}}</text> | |||||
| <image v-if="companion.gender" :src="companion.gender === '男生' ? '/static/images/details/boy.svg' : '/static/images/details/girl.svg'" class="gender-icon"></image> | |||||
| <view class="companion-tag" v-if="companion.isOfficial"> | |||||
| <text>初级伴宠师</text> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 评价内容区域 --> | |||||
| <view class="review-content"> | |||||
| <!-- 评分 --> | |||||
| <view class="review-item"> | |||||
| <text class="review-label">评价星级</text> | |||||
| <view class="review-stars"> | |||||
| <uni-rate | |||||
| v-model="rating" | |||||
| :size="24" | |||||
| :value="rating" | |||||
| :max="5" | |||||
| :margin="5" | |||||
| :is-fill="true" | |||||
| :touchable="true" | |||||
| @change="ratingChange" | |||||
| ></uni-rate> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 评价内容 --> | |||||
| <view class="review-item"> | |||||
| <text class="review-label">评价内容</text> | |||||
| <view class="review-textarea-box"> | |||||
| <textarea | |||||
| class="review-textarea" | |||||
| v-model="reviewContent" | |||||
| placeholder="服务态度,态度满意,环境满意" | |||||
| maxlength="500" | |||||
| ></textarea> | |||||
| <view class="word-count"> | |||||
| <text>{{reviewContent.length}}/500</text> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 底部按钮区域 --> | |||||
| <view class="review-footer"> | |||||
| <view class="submit-btn" @click="submitReview"> | |||||
| <text>提交评价</text> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import { getOpenIdKey } from '@/utils/auth' | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| orderId: null, | |||||
| rating: 5, | |||||
| reviewContent: '', | |||||
| companion: { | |||||
| name: '宠小二', | |||||
| avatar: '/static/images/personal/pet.png', | |||||
| isOfficial: true, | |||||
| gender: '女生' | |||||
| } | |||||
| }; | |||||
| }, | |||||
| onLoad(options) { | |||||
| if (options.id) { | |||||
| this.orderId = options.id; | |||||
| this.getOrderInfo(); | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| // 获取订单信息 | |||||
| getOrderInfo() { | |||||
| // 实际项目中应调用API获取订单详情和伴宠师信息 | |||||
| // 示例代码: | |||||
| /* | |||||
| const params = { | |||||
| openId: getOpenIdKey(), | |||||
| orderId: this.orderId | |||||
| }; | |||||
| getOrderDetail(params).then(res => { | |||||
| if (res && res.code === 200) { | |||||
| this.companion = res.data.companion; | |||||
| } | |||||
| }).catch(err => { | |||||
| console.error('获取订单详情失败', err); | |||||
| }); | |||||
| */ | |||||
| // 这里使用模拟数据 | |||||
| console.log('获取订单详情,ID:', this.orderId); | |||||
| }, | |||||
| // 评分变化 | |||||
| ratingChange(e) { | |||||
| this.rating = e.value; | |||||
| }, | |||||
| // 提交评价 | |||||
| submitReview() { | |||||
| if (this.rating === 0) { | |||||
| uni.showToast({ | |||||
| title: '请选择评分', | |||||
| icon: 'none' | |||||
| }); | |||||
| return; | |||||
| } | |||||
| if (!this.reviewContent.trim()) { | |||||
| uni.showToast({ | |||||
| title: '请输入评价内容', | |||||
| icon: 'none' | |||||
| }); | |||||
| return; | |||||
| } | |||||
| // 实际项目中应调用API提交评价 | |||||
| // 示例代码: | |||||
| /* | |||||
| const params = { | |||||
| openId: getOpenIdKey(), | |||||
| orderId: this.orderId, | |||||
| rating: this.rating, | |||||
| content: this.reviewContent | |||||
| }; | |||||
| submitOrderReview(params).then(res => { | |||||
| if (res && res.code === 200) { | |||||
| uni.showToast({ | |||||
| title: '评价成功', | |||||
| icon: 'success' | |||||
| }); | |||||
| // 评价成功后返回订单列表页 | |||||
| setTimeout(() => { | |||||
| uni.navigateBack(); | |||||
| }, 1500); | |||||
| } | |||||
| }).catch(err => { | |||||
| console.error('提交评价失败', err); | |||||
| }); | |||||
| */ | |||||
| // 这里使用模拟数据,显示评价成功提示 | |||||
| uni.showToast({ | |||||
| title: '评价成功', | |||||
| icon: 'success' | |||||
| }); | |||||
| // 1.5秒后返回订单列表页 | |||||
| setTimeout(() => { | |||||
| uni.navigateBack(); | |||||
| }, 1500); | |||||
| } | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .order-review-page { | |||||
| background: linear-gradient(180deg, #FFBF60 0%, #FFF5E6 20%, #FFFFFF 50%); | |||||
| min-height: 100vh; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| padding-bottom: 120rpx; | |||||
| } | |||||
| .companion-info-card { | |||||
| padding: 30rpx; | |||||
| margin-bottom: 20rpx; | |||||
| background-color: transparent; | |||||
| .profile-header { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| } | |||||
| .companion-avatar { | |||||
| width: 100rpx; | |||||
| height: 100rpx; | |||||
| border-radius: 50%; | |||||
| overflow: hidden; | |||||
| margin-right: 20rpx; | |||||
| border: 2rpx solid #FFFFFF; | |||||
| box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.1); | |||||
| image { | |||||
| width: 100%; | |||||
| height: 100%; | |||||
| } | |||||
| } | |||||
| .companion-detail { | |||||
| flex: 1; | |||||
| .companion-name { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| font-size: 32rpx; | |||||
| font-weight: bold; | |||||
| color: #333; | |||||
| .gender-icon { | |||||
| width: 32rpx; | |||||
| height: 32rpx; | |||||
| margin-left: 10rpx; | |||||
| } | |||||
| .companion-tag { | |||||
| background-color: #FF9500; | |||||
| color: #FFFFFF; | |||||
| font-size: 20rpx; | |||||
| padding: 4rpx 10rpx; | |||||
| border-radius: 20rpx; | |||||
| margin-left: 16rpx; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .review-content { | |||||
| background-color: #FFFFFF; | |||||
| padding: 30rpx; | |||||
| border-radius: 16rpx 16rpx 0 0; | |||||
| margin-top: 20rpx; | |||||
| .review-item { | |||||
| margin-bottom: 40rpx; | |||||
| .review-label { | |||||
| font-size: 28rpx; | |||||
| color: #333; | |||||
| margin-bottom: 20rpx; | |||||
| display: block; | |||||
| font-weight: bold; | |||||
| } | |||||
| .review-stars { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| } | |||||
| .review-textarea-box { | |||||
| position: relative; | |||||
| .review-textarea { | |||||
| width: 100%; | |||||
| height: 200rpx; | |||||
| background-color: #F7F7F7; | |||||
| border-radius: 12rpx; | |||||
| padding: 20rpx; | |||||
| font-size: 28rpx; | |||||
| color: #666; | |||||
| box-sizing: border-box; | |||||
| } | |||||
| .word-count { | |||||
| position: absolute; | |||||
| bottom: 10rpx; | |||||
| right: 20rpx; | |||||
| font-size: 24rpx; | |||||
| color: #999; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .review-footer { | |||||
| position: fixed; | |||||
| bottom: 0; | |||||
| left: 0; | |||||
| right: 0; | |||||
| background-color: #FFFFFF; | |||||
| padding: 20rpx 30rpx; | |||||
| box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05); | |||||
| .submit-btn { | |||||
| background-color: #FFAA48; | |||||
| color: #FFFFFF; | |||||
| height: 88rpx; | |||||
| line-height: 88rpx; | |||||
| border-radius: 44rpx; | |||||
| text-align: center; | |||||
| font-size: 32rpx; | |||||
| font-weight: bold; | |||||
| box-shadow: 0 4rpx 8rpx rgba(255, 170, 72, 0.3); | |||||
| } | |||||
| } | |||||
| </style> | |||||