Files
rating/components/AttitudePanel/AttitudePanel.vue

246 lines
5.1 KiB
Vue
Raw Normal View History

2026-05-24 23:45:47 +08:00
<template>
<view class="attitude-panel card">
<text class="section-title">你的态度</text>
<view class="action-group">
<view
class="action-item"
v-for="(action, index) in actions"
:key="index"
:class="{ active: currentAction === action.label }"
@tap="handleAction(action)"
>
<view class="emoji-wrap">
<text class="emoji">{{ action.emoji }}</text>
</view>
<text class="action-name">{{ action.label }}</text>
</view>
</view>
2026-06-15 07:59:47 +08:00
<view v-if="replyTarget" class="reply-banner">
<view class="reply-banner-main">
<text class="reply-banner-label">正在回复</text>
<text class="reply-banner-user">@{{ replyTarget.replyToName || replyTarget.name }}</text>
</view>
<text class="reply-banner-cancel" @tap="handleCancelReply">取消</text>
</view>
2026-05-24 23:45:47 +08:00
<view class="quick-comment">
<input
class="comment-input"
type="text"
v-model="commentText"
2026-06-10 01:24:41 +08:00
:disabled="sending"
2026-06-15 07:59:47 +08:00
:placeholder="inputPlaceholder"
2026-05-24 23:45:47 +08:00
placeholder-class="input-placeholder"
/>
2026-06-10 01:24:41 +08:00
<button class="send-btn" :class="{ 'is-disabled': sending }" :disabled="sending" @tap="handleSend">
{{ sending ? '发送中...' : '发送' }}
</button>
2026-05-24 23:45:47 +08:00
</view>
</view>
</template>
<script setup>
2026-06-15 07:59:47 +08:00
import { computed, ref, watch } from 'vue';
2026-05-24 23:45:47 +08:00
const props = defineProps({
initialAction: {
type: String,
default: ''
2026-06-10 01:24:41 +08:00
},
sending: {
type: Boolean,
default: false
2026-06-15 07:59:47 +08:00
},
replyTarget: {
type: Object,
default: null
2026-05-24 23:45:47 +08:00
}
});
2026-06-15 07:59:47 +08:00
const emit = defineEmits(['action-change', 'send-comment', 'cancel-reply']);
2026-05-24 23:45:47 +08:00
const currentAction = ref(props.initialAction);
// 监听父组件传入的 initialAction 的变化
watch(() => props.initialAction, (newVal) => {
currentAction.value = newVal;
});
const commentText = ref('');
2026-06-15 07:59:47 +08:00
const inputPlaceholder = computed(() => {
if (props.replyTarget?.replyToName || props.replyTarget?.name) {
return `回复 @${props.replyTarget.replyToName || props.replyTarget.name}...`;
}
return '说点什么吧...';
});
2026-05-24 23:45:47 +08:00
const actions = [
{ label: '拉', value: 'terrible', emoji: '👎', score: 2, scoreType:1 },
{ label: 'NPC', value: 'bad', emoji: '😐', score: 4, scoreType: 2},
{ label: '人上人', value: 'ok', emoji: '🙂', score: 6, scoreType: 3},
{ label: '顶级', value: 'good', emoji: '🔥', score: 8, scoreType: 4},
{ label: '夯', value: 'god', emoji: '👑', score: 10, scoreType: 5 }
];
const handleAction = (action) => {
emit('action-change', action);
};
const handleSend = () => {
2026-06-10 01:24:41 +08:00
const content = commentText.value.trim();
if (!content) {
2026-05-24 23:45:47 +08:00
uni.showToast({
title: '请输入评论内容',
icon: 'none'
});
return;
}
2026-06-10 01:24:41 +08:00
if (props.sending) return;
2026-05-24 23:45:47 +08:00
emit('send-comment', {
action: currentAction.value,
2026-06-10 01:24:41 +08:00
content
2026-05-24 23:45:47 +08:00
});
};
2026-06-10 01:24:41 +08:00
2026-06-15 07:59:47 +08:00
const handleCancelReply = () => {
emit('cancel-reply');
};
2026-06-10 01:24:41 +08:00
const resetComment = () => {
commentText.value = '';
};
defineExpose({
resetComment
});
2026-05-24 23:45:47 +08:00
</script>
<style lang="scss" scoped>
.card {
background-color: #fff;
border-radius: 32rpx;
padding: 32rpx;
margin-bottom: 24rpx;
}
.section-title {
font-size: 34rpx;
font-weight: 700;
color: #111;
margin-bottom: 32rpx;
display: block;
font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif;
}
.action-group {
display: flex;
justify-content: space-between;
margin-bottom: 32rpx;
}
.action-item {
display: flex;
flex-direction: column;
align-items: center;
transition: transform 0.2s;
}
.emoji-wrap {
margin-bottom: 12rpx;
}
.emoji {
font-size: 56rpx;
filter: grayscale(100%);
opacity: 0.6;
}
.action-name {
font-size: 24rpx;
color: #999;
}
.action-item.active .emoji {
filter: grayscale(0%);
opacity: 1;
transform: scale(1.2);
}
.action-item.active .action-name {
color: #2953ff;
font-weight: bold;
}
.quick-comment {
display: flex;
align-items: center;
background-color: #f0f2f7;
border-radius: 16rpx;
padding: 8rpx 8rpx 8rpx 32rpx;
}
2026-06-15 07:59:47 +08:00
.reply-banner {
margin-bottom: 18rpx;
padding: 16rpx 20rpx;
border-radius: 18rpx;
background: linear-gradient(135deg, rgba(29, 78, 216, 0.08) 0%, rgba(124, 58, 237, 0.08) 100%);
display: flex;
align-items: center;
justify-content: space-between;
gap: 20rpx;
}
.reply-banner-main {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 10rpx;
}
.reply-banner-label {
font-size: 22rpx;
color: #6b7280;
}
.reply-banner-user {
font-size: 24rpx;
font-weight: 700;
color: #4338ca;
}
.reply-banner-cancel {
flex-shrink: 0;
font-size: 24rpx;
font-weight: 600;
color: #111827;
}
2026-05-24 23:45:47 +08:00
.comment-input {
flex: 1;
height: 72rpx;
font-size: 28rpx;
}
.input-placeholder {
color: #999;
}
.send-btn {
background-color: #4d44f1;
color: #fff;
font-size: 26rpx;
border-radius: 12rpx;
padding: 0 40rpx;
height: 64rpx;
line-height: 64rpx;
margin: 0;
}
2026-06-10 01:24:41 +08:00
.send-btn.is-disabled {
opacity: 0.7;
}
2026-05-24 23:45:47 +08:00
.send-btn::after {
border: none;
}
2026-06-10 01:24:41 +08:00
</style>