文件
yjyf/yjyf-app/pages/order/review.vue
YuanWen 9ae2b976a8 feat: 重构首页与全局UI,新增服务选择抽屉与统一导航组件
新增统一导航栏组件YjyfNavBar,替换各页面原生导航
新增服务选择抽屉组件GoodsPickerDrawer,实现分类选品流程
新增tabbar图标矢量资源,优化底部导航样式
新增后端运力统计接口与多商品下单逻辑
修复页面跳转逻辑,统一使用switchTab/redirectTo
优化订单创建与评价页的UI组件化,提升一致性
2026-11-02 18:27:37 +08:00

101 行
3.8 KiB
Vue

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

<template>
<view class="page">
<!-- 统一顶部导航栏(安全距离自适应) -->
<YjyfNavBar theme="white" title="服务评价" :border="true" />
<view class="card">
<view class="title">给本次服务打分</view>
<view class="stars">
<image v-for="i in 5" :key="i" class="star-icon" :src="i <= score ? '/static/icons/star-orange.svg' : '/static/icons/star-gray.svg'" mode="aspectFit" @tap="score = i" />
</view>
<text class="score-txt">{{ scoreText }}</text>
</view>
<view class="card">
<view class="title">服务标签</view>
<view class="tags">
<view v-for="t in tagList" :key="t" class="tag" :class="{ on: tags.indexOf(t) > -1 }" @tap="toggleTag(t)">
<text class="tag-txt">{{ t }}</text>
</view>
</view>
</view>
<view class="card">
<view class="title">评价内容</view>
<textarea class="ta" v-model="content" maxlength="200" placeholder="说说师傅的服务、专业度和态度..." />
<view class="anon">
<text class="anon-txt">匿名评价</text>
<switch :checked="anonymous" color="#F0710D" @change="e => (anonymous = e.detail.value)" />
</view>
</view>
<view class="submit clickable-hover" :class="{ disabled: submitting }" @tap="submit">{{ submitting ? '提交中...' : '提交评价' }}</view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import api from '@/utils/api.js';
const score = ref(5);
const tags = ref([]);
const content = ref('');
const anonymous = ref(false);
const submitting = ref(false);
const tagList = ['准时', '专业', '态度好', '收费透明', '干净利落', '值得推荐'];
let orderId = 0;
const scoreText = computed(() => ['', '非常不满意', '不满意', '一般', '满意', '非常满意'][score.value]);
function toggleTag(t) {
const i = tags.value.indexOf(t);
if (i > -1) tags.value.splice(i, 1);
else tags.value.push(t);
}
async function submit() {
if (submitting.value) return;
submitting.value = true;
try {
await api.reviewCreate({
order_id: orderId,
score: score.value,
content: content.value,
tags: tags.value.join(','),
is_anonymous: anonymous.value ? 1 : 0
});
uni.showToast({ title: '评价成功' });
setTimeout(() => uni.navigateBack(), 600);
} catch (e) {
} finally {
submitting.value = false;
}
}
onLoad((o) => { orderId = Number(o.id || 0); });
</script>
<style scoped>
.page { min-height: 100vh; background: #F5F6F8; padding: 22rpx 28rpx 60rpx; }
.card { padding: 26rpx 24rpx; background: #fff; border-radius: 20rpx; margin-bottom: 20rpx; box-shadow: 0 6rpx 20rpx rgba(240,129,31,0.06); }
.title { font-size: 28rpx; font-weight: 700; color: #1F1F1F; }
.stars { display: flex; justify-content: center; align-items: center; padding: 24rpx 0 12rpx; }
.star-icon { width: 56rpx; height: 56rpx; margin: 0 12rpx; }
.score-txt { display: block; text-align: center; font-size: 24rpx; color: #F0710D; }
.tags { display: flex; flex-wrap: wrap; padding-top: 14rpx; }
.tag { padding: 0 22rpx; line-height: 56rpx; margin: 0 14rpx 14rpx 0; border-radius: 28rpx; background: #F5F5F5; }
.tag.on { background: #FFF3E6; }
.tag-txt { font-size: 24rpx; color: #666; }
.tag.on .tag-txt { color: #E36B0C; font-weight: 600; }
.ta { width: 100%; height: 180rpx; margin-top: 14rpx; font-size: 26rpx; color: #333; line-height: 38rpx; }
.anon { display: flex; align-items: center; justify-content: space-between; margin-top: 10rpx; }
.anon-txt { font-size: 26rpx; color: #666; }
.submit {
height: 96rpx; margin-top: 30rpx; display: flex; align-items: center; justify-content: center;
border-radius: 48rpx; color: #fff; font-size: 32rpx; font-weight: 600;
background: linear-gradient(135deg, #FFA93F 0%, #F0710D 100%);
box-shadow: 0 10rpx 24rpx rgba(240,113,13,0.3);
}
.submit.disabled { opacity: 0.7; }
</style>