mrr.sj.front/pages/evaluate/comment.vue

616 lines
15 KiB
Vue
Raw Normal View History

2026-03-24 11:45:13 +08:00
<template>
<view class="container">
<!-- 顶部导航栏 -->
<custom-navbar title="发布评价" :show-back="true" title-color="#333333" BackText="取消"></custom-navbar>
<!-- <view class="header">
<text class="cancel" @click="cancel">取消</text>
<text class="title">发布评价</text>
<text class="placeholder"></text>
</view> -->
<!-- 打星区域 -->
<view class="rating-section">
<view class="rating-item" v-for="(item, index) in ratings" :key="index">
<view class="rating-item-left">
<text class="rating-label">{{ item.label }}</text>
<view class="stars">
<image v-for="n in 5" :key="n" :src="getStarSrc(index, n)" class="star-img"
:class="{ 'star-animate': activeIndex === index }" @click="rate(index, $event, n)" />
</view>
</view>
<text class="star-text" :class="{ 'text-animate': item.value > 0 }">
{{ item.value > 0 ? item.text : "" }}
</text>
</view>
</view>
<!-- 猜你想说 -->
<view class="guess-section">
<view class="guess-tags">
<view class="guess-title">猜你想说:</view>
<view class="guess-tag" v-for="(tag, index) in guessTags" :key="index" @tap.stop="insertTag(tag.text)">
<image class="tag-icon" :src="tag.icon" />
<text class="tag-text">{{ tag.text }}</text>
</view>
</view>
</view>
<!-- 评论输入 -->
<view class="comment-section">
<highlight-textarea ref="commentInput" placeholder="请描述您对此服务的评价......" type="textarea" @blur="blur" v-model="formData.describe"
:highlightKey="highlightKey">
</highlight-textarea>
<!-- <textarea
class="comment-input"
maxlength="1000"
placeholder="请描述您对此服务的评价......"
v-model="formData.describe"
></textarea> -->
<!-- 上传与匿名 -->
<view class="comment-footer">
<!-- 上传图片 -->
<label class="upload-label">
<input type="file" @change="uploadImage" multiple style="display: none" />
<!-- <image class="upload-icon" src="/static/images/上传图片.png" /> -->
<ali-oss-uploader2 v-model="formData.images" :max-count="9" :max-size="5" :width="'654rpx'"
:user-id="formData.evaluator_id" button-text="上传图片" tips="最多上传9张图片每张不超过5MB"
@success="onUploadSuccess" @error="onUploadError" @delete="onFileDelete"
@ckeckisShowPer="ckeckisShowPer" @ckecknowQer="ckecknowQer">
</ali-oss-uploader2>
</label>
<!-- 匿名评价 -->
<view class="anonymous-wrapper">
<radio class="small-radio" :checked="formData.anonymity == 1"
:color="formData.anonymity == 1 ? '#e10011' : '#ccc'"
@click="formData.anonymity = formData.anonymity == 1 ? 2 : 1" />
<text class="anonymous-text">匿名评价</text>
<text class="tips">隐藏你的头像和名称</text>
</view>
</view>
</view>
<!-- 发布按钮 -->
<view class="submitPage">
<button class="submit-button" @click="submit">发布</button>
</view>
<!-- 获取权限提示匡内容 -->
<view class="permission" :class="{ transform: isShowPer && nowQer === 'xc' }">
<view class="per-tit">美融融plus 对储存空间/照片权限申请说明</view>
<view class="per-cont">便于您使用该功能上传您的照片/图片/视频以及用于更换头像发布商品等场景中读取相册和文件内容</view>
</view>
<view class="permission" :class="{ transform: isShowPer && nowQer === 'xj' }">
<view class="per-tit">美融融plus 对相机拍摄权限申请说明</view>
<view class="per-cont">便于您使用该功能上传您的照片/图片/视频以及用于更换头像发布商品等场景中所需内容</view>
</view>
</view>
</template>
<script>
import highlightTextarea from "@/components/highlight-textarea/highlight-textarea.vue";
import AliOssUploader2 from "./components/ali-oss-uploader-2.vue";
import request from "../../utils/request";
export default {
components: {
AliOssUploader2,
highlightTextarea
},
data() {
return {
highlightKey: ['团队', '组织'], //违禁词列表
ratings: [{
label: "服务过程",
value: 0,
text: ""
},
{
label: "服务态度",
value: 0,
text: ""
},
{
label: "服务技术",
value: 0,
text: ""
},
{
label: "服务效果",
value: 0,
text: ""
},
],
// 猜你想说标签数据
guessTags: [
{ icon: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/3b272e9b-e75b-4093-b3c0-0b3bc790a829.png", text: "服务态度好" },
{ icon: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/3b272e9b-e75b-4093-b3c0-0b3bc790a829.png", text: "技术高超" },
{ icon: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/3b272e9b-e75b-4093-b3c0-0b3bc790a829.png", text: "卫生安全" },
{ icon: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/3b272e9b-e75b-4093-b3c0-0b3bc790a829.png", text: "预约简单" },
{ icon: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/3b272e9b-e75b-4093-b3c0-0b3bc790a829.png", text: "操作规范" },
{ icon: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/3b272e9b-e75b-4093-b3c0-0b3bc790a829.png", text: "卫生安全" },
{ icon: "https://mrrplus.oss-cn-beijing.aliyuncs.com/photo/system/3b272e9b-e75b-4093-b3c0-0b3bc790a829.png", text: "卫生安全" }
],
formData: {
images: [], //图片逗号分隔(没有传空字符)
anonymity: 2, //1匿名 2不匿名
evaluator_id: null, //评价人id
order_id: null, //订单id
evaluator_type: 3, //评价人类型 1手艺人 2商家 3用户
order_type: 1, //1:order表用户订单 2:sjorder表商家订单 3:work_hour_order表工时订单 4:work_seat_order表工位订单
describe: "", //评论描述
},
order_kind:1,//是否到店1是到家2是到店
isShowPer: false,
nowQer: "xc",
commentText: "",
anonymous: false,
uploadedImages: [],
activeIndex: null, // 控制当前动画星星组
userInfo: {},
};
},
onLoad(options) {
if (options.id) {
this.formData.order_id = Number(options.id);
}
if (options.evaluator_type) {
this.formData.evaluator_type = Number(options.evaluator_type);
}
if (options.order_type) {
this.formData.order_type = Number(options.order_type);
}
if(options.order_kind==2){
this.order_kind = options.order_kind
this.ratings.push({
label: "门店环境",
value: 0,
text: ""
})
}
this.getUserInfo();
},
methods: {
getUserInfo() {
request.post("/user/getuser", {
type: 1
}).then((result) => {
this.userInfo = result.data;
this.formData.evaluator_id = this.userInfo.id;
});
},
// 插入标签到评论框
insertTag(tagText) {
console.log('点击标签:', tagText);
// 获取当前值
let currentValue = this.formData.describe || '';
let newValue = currentValue ? currentValue + ' ' + tagText : tagText;
// 调用组件的方法
if (this.$refs.commentInput && this.$refs.commentInput.setValue) {
this.$refs.commentInput.setValue(newValue);
}
// 更新父组件的数据
this.formData.describe = newValue;
console.log('当前评论内容:', newValue);
},
ckecknowQer(value) {
this.nowQer = value;
},
ckeckisShowPer(value) {
console.log("ckeckisShowPer==========", value);
this.isShowPer = value;
},
onUploadSuccess(file) {
console.log("添加的图片", this.formData.photo);
},
onUploadError(error) {
console.error("上传失败:", error);
uni.showToast({
title: "上传失败",
icon: "none",
});
},
onFileDelete(file, index) {
console.log("删除文件:", this.formData.photo, index);
},
getStarSrc(index, n) {
const val = this.ratings[index].value;
if (val >= n) return "/static/images/evaluate/star_red2.png";
else if (val >= n - 0.5) return "/static/images/evaluate/star.png";
else return "/static/images/evaluate/star_ash.png";
},
rate(index, e) {
const query = uni.createSelectorQuery().in(this);
query
.selectAll(".stars")
.boundingClientRect((rects) => {
const rect = rects[index];
if (!rect) return;
const x = e.detail.x;
const offsetX = x - rect.left;
const totalWidth = rect.width;
const starWidth = totalWidth / 5;
let rawVal = offsetX / starWidth;
let val = Math.floor(rawVal) + (rawVal % 1 > 0.5 ? 1 : 0.5);
if (val > 5) val = 5;
if (val < 1) val = 1;
this.ratings[index].value = val;
this.ratings[index].text = this.getStarText(val);
// 触发星星动画
this.activeIndex = index;
setTimeout(() => (this.activeIndex = null), 400);
})
.exec();
},
getStarText(value) {
if (value >= 5) return "超预期";
else if (value >= 4) return "还可以";
else if (value >= 3) return "一般";
else if (value >= 1.5) return "较差";
else return "很糟糕";
},
uploadImage(event) {
const files = event.target.files;
if (files.length) {
for (let i = 0; i < files.length; i++) {
this.uploadedImages.push(files[i]);
}
}
console.log("Uploaded images:", this.uploadedImages);
},
cancel() {
console.log("Cancel clicked");
},
async blur(){ // 这个方法不注释会导致点击猜你想说tag时就出现违禁词警告
// 判断违禁词
// let bannedWords = await request.post("/user/orderEvaluate/bannedWords", {
// describe: this.formData.describe
// }).then((res) => {
// if (res.code == 500) {
// this.highlightKey = res.data
// return true
// }
// })
// if (bannedWords) {
// uni.showToast({
// title: `包含违禁词不可发布`,
// icon: "none",
// });
// return;
// }
},
async submit() {
// 判断所有value是否都大于0
let allValuesGreaterThanZero = this.ratings.every(
(item) => item.value > 0
);
if (!allValuesGreaterThanZero) {
uni.showToast({
title: `请选择评价`,
icon: "none",
});
return;
}
// 判断违禁词
let bannedWords = await request.post("/user/orderEvaluate/bannedWords", {
describe: this.formData.describe
}).then((res) => {
if (res.code == 500) {
this.highlightKey = res.data
return true
}
})
if (bannedWords) {
uni.showToast({
title: `包含违禁词不可发布`,
icon: "none",
});
return;
}
let obj = {
...this.formData
};
obj.process = this.ratings[0].value;
obj.attitude = this.ratings[1].value;
obj.technology = this.ratings[2].value;
obj.effect = this.ratings[3].value;
if(this.order_kind==2){
obj.environment = this.ratings[4].value;
}
obj.images = obj.images.join(",");
// obj.environment = this.ratings[4].value
request
.post("/user/orderEvaluate/add", obj)
.then((result) => {
console.log("--", result);
if (result.code == 200) {
// 修改上一页页面信息
const pages = getCurrentPages();
const prevPage = pages[pages.length - 2];
if (prevPage) {
if (prevPage.$vm && typeof prevPage.$vm.getOrderDetail === "function") {
prevPage.$vm.getOrderDetail(); // 存在则调用
}
if (prevPage.$vm && typeof prevPage.$vm.loadOrders === "function") {
prevPage.$vm.loadOrders(); // 存在则调用
}
uni.navigateBack();
}
} else {
uni.showToast({
title: `提交失败`,
icon: "none",
});
}
}).catch((err) => {
console.log(err);
uni.showToast({
title: `提交失败`,
icon: "none",
});
});
console.log(obj);
},
},
};
</script>
<style scoped lang="less">
.container {
background-color: #f8f8f8;
min-height: 100vh;
padding-bottom: 40rpx;
}
/* 顶部导航栏 */
.header {
display: flex;
align-items: center;
justify-content: space-between;
background-color: #fff;
padding: 24rpx 32rpx;
border-bottom: 1rpx solid #f0f0f0;
position: sticky;
top: 0;
z-index: 10;
}
.cancel {
color: #666;
font-size: 30rpx;
}
.placeholder {
width: 60rpx;
}
.title {
font-size: 34rpx;
font-weight: 600;
color: #000;
text-align: center;
flex: 1;
}
/* 打星区域 */
.rating-section {
background-color: #fff;
// padding: 40rpx 30rpx 1rpx 40rpx;
padding: 30rpx 30rpx 1rpx 20rpx;
margin: 20rpx;
border-radius: 20rpx;
}
.rating-item {
display: flex;
align-items: center;
margin-bottom: 52rpx;
justify-content: space-between;
}
.rating-item-left{
display: flex;
align-items: center;
gap: 22rpx;
}
.rating-label {
font-size: 28rpx;
color: #333;
word-break: keep-all;
}
.stars {
display: flex;
gap: 45rpx;
flex-shrink: 0;
}
/* 星星图片基础样式 */
.star-img {
width: 48rpx;
height: 48rpx;
transition: transform 0.2s ease, opacity 0.2s ease;
}
/* 星星点击动画 */
.star-animate {
transform: scale(1.2);
opacity: 0.9;
}
/* 星星描述文字 */
.star-text {
width: 100rpx;
font-size: 26rpx;
text-align: right;
color: #a7a7a7;
opacity: 0;
transform: scale(0.3);
transition: opacity 0.3s ease, transform 0.3s ease;
}
/* 字体动画 */
.text-animate {
opacity: 1;
transform: scale(1);
}
/* 猜你想说 */
.guess-section {
padding: 8rpx 0rpx;
margin: 20rpx;
}
.guess-title {
font-family: PingFangSC, PingFang SC;
font-weight: 400;
font-size: 30rpx;
color: #000000;
line-height: 42rpx;
text-align: left;
font-style: normal;
flex-shrink: 0;
margin: 10rpx 10rpx 0rpx 5rpx ;
}
.guess-tags {
display: flex;
flex-wrap: wrap;
gap: 11rpx;
}
.guess-tag {
display: flex;
align-items: center;
background-color: #f1f1f1f1;
border-radius: 10rpx;
padding: 12rpx 14rpx;
gap: 12rpx;
margin: 3rpx 0;
}
.tag-icon {
width: 26rpx;
height: 26rpx;
}
.tag-text {
font-size: 26rpx;
color: #666;
}
/* 评论区 */
.comment-section {
background-color: #fff;
padding: 24rpx 32rpx;
margin: 20rpx;
border-radius: 12rpx;
position: relative;
}
.comment-input {
width: 100%;
height: 390rpx;
}
/* 评论区底部功能 */
.comment-footer {
display: flex;
flex-direction: column;
gap: 5rpx;
}
/* 上传图片按钮 */
.upload-label {
display: inline-block;
}
.upload-icon {
width: 140rpx;
height: 140rpx;
}
/* 匿名评价 */
.anonymous-wrapper {
display: flex;
align-items: center;
gap: 4rpx;
}
.anonymous-text {
font-size: 26rpx;
color: #666;
font-weight: bold;
}
.tips {
font-weight: 400;
font-size: 20rpx;
color: #C3C3C3;
text-align: left;
font-style: normal;
}
/* 发布按钮 */
.submitPage{
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 27rpx 0;
background-color: #fff;
.submit-button {
width: 670rpx;
margin: 0 40rpx;
display: block;
background-color: #e10011;
color: #fff;
border: none;
border-radius: 50rpx;
font-size: 32rpx;
font-weight: bold;
}
}
.small-radio {
border: none;
transform: scale(0.7);
}
/* #ifdef APP-PLUS */
.permission.transform {
top: calc(var(--status-bar-height) + 88rpx + 30rpx);
opacity: 1;
visibility: visible;
}
/* #endif */
</style>