This commit is contained in:
2025-08-14 16:49:58 +08:00
parent b2009403d8
commit 26c1ac5ced
15 changed files with 1144 additions and 351 deletions

View File

@@ -0,0 +1,84 @@
<template>
<view class="bottom_input_box" :style="show ? 'bottom: 430rpx' : ''">
<!-- <image src="../static/audio.png" mode=""></image> -->
<image src="./emoji.png" @click="emojichet" mode=""></image><Emoji :show="show" @emoji="emojiChange" @emojiblur="emojiblur" />
</view>
</template>
<script>
import Emoji from './emoji.vue'
export default {
data() {
return {
show: false, // 表示 emoji 列表是否显示
inputValue: '', // 输入框的值
focus: false, // 是否获得焦点
};
},
components: {
Emoji
},
methods: {
confirm() {
this.$emit('inputvalue', this.inputValue); // 发送按钮点击时把input的值传递给父组件
},
emojiblur() {
this.show = false; // 关闭 emoji 列表
},
emojiChange(e) {
this.inputValue += e; // 添加 emoji 到输入框中
},
keychange() {
this.show = false; // 关闭 emoji 列表并打开键盘
this.focus = true;
},
emojichet() {
this.show = true; // 打开 emoji 列表
}
}
};
</script>
<style scoped lang="scss">
.bottom_input_box {
position: fixed;
bottom: 0;
height: 160rpx;
width: 100%;
z-index: 99;
background: #fff;
display: flex;
align-items: center;
justify-content: space-around;
border-radius: 20rpx 20rpx 0px 0px;
image {
height: 62rpx;
width: 62rpx;
}
.input_ {
height: 62rpx;
width: calc(100% - 300rpx);
border: 1rpx solid #bbbbbb;
border-radius: 30rpx;
input {
width: 90%;
height: 100%;
margin: 0 auto;
}
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,79 @@
<template>
<view class="emoji_blur" @click="emoji_blur" v-if="show">
<view class="emoji_box">
<scroll-view class="scrool" scroll-y="true">
<view class="emojis">
<text
@click.stop="tap(item)"
v-for="(item, index) in list"
:key="index"
>
{{ item }}
</text>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
export default {
props: {
show: Boolean
},
data() {
return {
list: [
'😃', '😆', '😅', '🤣', '😂', '🙂', '🙃', '😉', '😊', '😇', '🥰', '😍', '🤩', '😘', '😗', '☺️', '😚', '😙',
'😋', '😛', '😜', '🤪', '😝', '🤑', '😩', '😖', '😨', '😭', '😞', '🤓', '🤠', '😎', '🥳', '😵', '🤧', '🤕',
'🤗', '🤭', '🤫', '🤔', '🤐', '🤨', '😐', '😑', '😶', '😏', '😒', '🙄', '😬', '🤥', '😶‍🌫️', '😮‍🌫️', '😴',
'🤮', '❤️', '💯', '💔', '💩', '🤡', '🤖', '👻', '🙈', '🙉', '🙊', '💣', '💋', '😡', '🤬', '😠'
]
};
},
methods: {
tap(item) {
this.$emit('emoji', item); // 触发 emoji 事件,将选择的 emoji 传给父组件
},
emoji_blur() {
this.$emit('emojiblur'); // 触发 emojiblur 事件,告诉父组件关闭 emoji 选择器
}
}
};
</script>
<style scoped lang="less">
.emoji_blur {
height: 100vh;
width: 100%;
position: absolute;
top: 0;
background: transparent;
}
.emoji_box {
height: 430rpx;
background: #f6f6f6;
position: fixed;
bottom: 0;
left: 0;
}
.scrool {
height: 400rpx;
width: 100%;
margin-top: 30rpx;
}
.emojis {
width: 95%;
margin: 0 auto;
font-size: 40rpx;
display: flex;
flex-wrap: wrap;
gap: 10rpx 25rpx;
flex-shrink: 3;
padding-bottom: 50rpx;
}
</style>

View File

@@ -1,5 +1,9 @@
<template>
<view class="hb-comment" style="height: 60vh">
<view
class="hb-comment"
:style="isDisable || isShowList || isPopup ? 'height:auto' : 'height: 70vh'"
id="commentData"
>
<!-- 阅读数-start -->
<!-- 阅读数-end -->
@@ -11,7 +15,21 @@
</view> -->
<!-- 阅读数下边那条线-end -->
<!-- 评论主体-start -->
<view class="comment-list" v-if="commentData.comment.length != 0">
<view
class="comment-list"
:style="
isDisable || isShowList
? ' background-color: #f7f7f7;padding: 4px 10px;display: flex;align-items:flex-start'
: ''
"
v-if="commentData.comment.length != 0"
>
<uni-icons
v-if="isDisable || isShowList"
type="chat"
size="22"
style="color: #5188e5; margin-right: 10rpx; margin-top: 10rpx"
></uni-icons>
<!-- 评论主体-顶部数量及发表评论按钮-start -->
<!-- <view class="comment-num">
<view> {{ commentData.commentSize }} 条评论</view>
@@ -23,191 +41,213 @@
</view> -->
<!-- 评论主体-顶部数量及发表评论按钮-end -->
<!-- 评论列表-start -->
<view class="comment-box" v-for="(item, index) in commentData.comment">
<view class="comment-box-item">
<view>
<image
v-if="item.user.avatar"
:src="item.user.avatar"
mode="aspectFill"
class="avatar"
></image>
<image
v-else
src="/static/icon/noIcon.png"
mode="aspectFill"
class="avatar"
></image>
</view>
<view class="comment-main">
<!-- 父评论体-start -->
<view class="comment-main-top">
<view class="nick-name-box">
<view class="nick-name"
>{{ item.user.nickname ? item.user.nickname : "普通用户" }}
<text
class="zuozhe"
v-if="user.userId || user.id == item.user.userId"
>作者</text
></view
>
</view>
<view :style="isDisable || isShowList ? 'width:calc(100% - 46rpx);' : ''">
<view class="comment-box" v-for="(item, index) in commentData.comment">
<view class="comment-box-item">
<view>
<image
v-if="item.user.avatar"
:src="item.user.avatar"
mode="aspectFill"
class="avatar"
></image>
<image
v-else
src="/static/icon/noIcon.png"
mode="aspectFill"
class="avatar"
></image>
</view>
<view
class="comment-main-content"
style="color: #232325; line-height: 38rpx"
@click="reply(item.user.nickname, item.user.nickname, item.id)"
>
{{ item.content }}
<!-- {{
<view class="comment-main">
<!-- 父评论体-start -->
<view class="comment-main-top">
<view class="nick-name-box">
<view class="nick-name"
>{{ item.user.nickname ? item.user.nickname : "普通用户" }}
<text class="zuozhe" v-if="articleUserId == item.userId"
>作者</text
></view
>
</view>
</view>
<view
class="comment-main-content"
style="color: #232325; line-height: 38rpx"
@click="reply(item.user.nickname, item.user.nickname, item.id)"
>
{{ item.content }}
<!-- {{
item.content.length > 60
? item.content.slice(0, 59)
: item.content
}} -->
<!-- <span v-if="item.content.length > 60">
<!-- <span v-if="item.content.length > 60">
{{ item.hasShowMore ? item.content.slice(59) : "..." }}
<span class="foot-btn" @click="showMore(item.id)" style="color: #5188e5 !important;">
{{ item.hasShowMore ? "收起" : "展开" }}
</span>
</span> -->
</view>
<view class="comment-main-foot">
<view
class="foot-time"
style="color: #b7b8ba; letter-spacing: 1rpx; font-size: 24rpx"
>{{ item.createTime }}</view
>
<view
class="foot-btn"
style="color: #777775"
@click="reply(item.user.nickname, item.user.nickname, item.id)"
>回复</view
>
<!-- <view
</view>
<view class="comment-main-foot">
<view
@click="
reply(item.user.nickname, item.user.nickname, item.id)
"
class="foot-time"
style="color: #b7b8ba; letter-spacing: 1rpx; font-size: 24rpx"
>{{ item.createTime }}</view
>
<view
class="foot-btn"
style="color: #777775"
v-if="!isDisable"
@click="
reply(item.user.nickname, item.user.nickname, item.id)
"
>回复</view
>
<!-- <view
class="foot-btn"
v-if="item.owner"
@click="confirmDelete(item.id)"
>删除</view
> -->
</view>
<!-- 父评论体-end -->
<!-- 子评论列表-start -->
<view class="comment-sub-box" v-if="item.children.length != 0">
<view class="comment-sub-item" v-for="each in item.children">
<view>
<image
v-if="each.user.avatar"
:src="each.user.avatar"
mode="aspectFill"
class="avatar"
></image>
<image
v-else
src="/static/icon/noIcon.png"
mode="aspectFill"
class="avatar"
></image>
</view>
<view class="comment-main">
<view class="sub-comment-main-top">
<view class="nick-name" v-if="each.user"
>{{
each.user.nickname ? each.user.nickname : "普通用户"
}}
<text
class="zuozhe"
v-if="user.userId || user.id == each.user.userId"
>作者</text
>
</view>
<!-- 父评论体-end -->
<!-- 子评论列表-start -->
<view class="comment-sub-box" v-if="item.children.length != 0">
<view class="comment-sub-item" v-for="each in item.children">
<view>
<image
v-if="each.user.avatar"
:src="each.user.avatar"
mode="aspectFill"
class="avatar"
></image>
<image
v-else
src="/static/icon/noIcon.png"
mode="aspectFill"
class="avatar"
></image>
</view>
<view class="comment-main">
<view class="sub-comment-main-top">
<view class="nick-name" v-if="each.user"
>{{
each.user.nickname ? each.user.nickname : "普通用户"
}}
<text class="zuozhe" v-if="articleUserId == each.userId"
>作者</text
>
</view>
</view>
</view>
<view
class="comment-main-content"
style="color: #232325 !important; line-height: 38rpx"
>
{{ each.content }}
</view>
<view class="comment-main-foot">
<view
class="foot-time"
style="
color: #b7b8ba;
letter-spacing: 1rpx;
font-size: 24rpx;
"
>{{ each.createTime }}</view
>
<view
class="foot-btn"
style="color: #777775"
v-if="each.user"
class="comment-main-content"
style="color: #232325 !important; line-height: 38rpx"
@click="
reply(each.user.nickname, each.user.nickname, item.id)
"
>
回复</view
>
<!-- <view
{{ each.content }}
</view>
<view class="comment-main-foot">
<view
@click="
reply(each.user.nickname, each.user.nickname, item.id)
"
class="foot-time"
style="
color: #b7b8ba;
letter-spacing: 1rpx;
font-size: 24rpx;
"
>{{ each.createTime }}</view
>
<view
class="foot-btn"
style="color: #777775"
v-if="each.user && !isDisable"
@click="
reply(each.user.nickname, each.user.nickname, item.id)
"
>
回复</view
>
<!-- <view
class="foot-btn"
v-if="each.owner"
@click="confirmDelete(each.id)"
>删除
</view> -->
</view>
</view>
</view>
</view>
<!-- 子评论列表-end -->
</view>
<!-- 子评论列表-end -->
</view>
</view>
</view>
<!-- 评论列表-end -->
</view>
<!-- 评论主体-end -->
<!-- 无评论-start -->
<view class="comment-none">
<image v-if="user.icon"
<view
class="comment-none"
@click="
showInput = false;
commentContent = '';
"
v-if="!isDisable"
style="background-color: #fafafa"
>
<!-- <image
v-if="user.icon"
:src="user.icon"
style="
width: 60rpx;
height: 60rpx;
width: 64rpx;
height: 64rpx;
margin: 0 8rpx;
display: block;
border-radius: 60rpx;
border-radius: 64rpx;
margin-top: 4rpx;
"
/>
<image v-else
<image
v-else
src="/static/icon/noIcon.png"
style="
width: 60rpx;
height: 60rpx;
width: 64rpx;
height: 64rpx;
margin: 0 8rpx;
display: block;
border-radius: 60rpx;margin-top: 4rpx;
border-radius: 64rpx;
margin-top: 4rpx;
"
/>
/> -->
<!-- background-color: #dadada59; -->
<view
style="
width: calc(100% - 100rpx);
width: calc(100% - 20rpx);
margin-right: 20rpx;
position: relative;
padding: 14rpx 20rpx;
border-radius: 10rpx;
"
>
<view v-if="currentInputComment" style="position: absolute; top: 10rpx"
<!-- <view v-if="currentInputComment" style="position: absolute; top: 10rpx"
><text @click="currentInputComment = ''">清空</text
><text @click="sendComment">发送</text></view
>
> -->
<!-- @click="showInput = true" -->
<view
style="font-size: 30rpx; width: calc(100%)"
@click="reply('', '', 0)"
style="font-size: 28rpx; width: calc(100%)"
@click.stop="reply('', '', 0)"
v-if="!showInput"
>评论...</view
>发表评论...</view
>
</view>
<view
@@ -215,18 +255,51 @@
:style="{ bottom: keyboardHeight + 'px' }"
v-if="showInput"
>
<view style="overflow: hidden; margin-bottom: 4rpx;font-size: 26rpx"
<view style="overflow: hidden; margin-bottom: 4rpx; font-size: 28rpx"
><text
@click="
@click.stop="
showInput = false;
commentContent = '';
"
style="float: left"
>取消</text
><text @click="sendComment" style="float: right; color: #1985fd"
>
<text @click.stop="sendComment" style="float: right; color: #1985fd"
>发送</text
></view
>
<image v-if="!show"
src="./emoji.png"
@click.stop="emojichet()"
mode=""
style="
height: 52rpx;
width: 52rpx;
object-fit: fill;
float: right;
margin-right: 2%;
margin-top: -4rpx;
"
></image
>
<image v-else
src="./jianpan.png"
@click.stop="emojichet()"
mode=""
style="
height: 52rpx;
width: 52rpx;
object-fit: fill;
float: right;
margin-right: 2%;
margin-top: -4rpx;
"
></image
>
</view>
<view>
<textarea
auto-height
@@ -234,19 +307,37 @@
v-model="commentContent"
class="comment-input"
maxlength="-1"
:placeholder="placeholder ? placeholder : '评论...'"
@focus="onInputFocus"
@blur="onInputBlur"
:placeholder="placeholder ? placeholder : '发表评论...'"
@focus.stop="onInputFocus"
@blur.stop="onInputBlur"
:auto-focus="showInput"
/>
</view>
<view
class="emoji_box"
v-if="show"
:style="{ height: keyboardHeight + 'px' }"
>
<scroll-view class="scrool" scroll-y="true">
<view class="emojis">
<text
@click.stop="tap(item)"
v-for="(item, index) in list"
:key="index"
>
{{ item }}
</text>
</view>
</scroll-view>
</view>
</view>
<!-- 暂无评论<span @click="commentInput" style="color: #007AFF;">立即评论</span> -->
</view>
<!-- 无评论-end -->
<!-- 新增评论-start -->
<view class="comment-submit-box" v-if="submit" @click="closeInput">
<view class="comment-submit-box" v-if="submit" @click.stop="closeInput">
<!-- 下边的click.stop.prevent用于让上边的click不传下去以防点到下边的空白处触发closeInput方法 -->
<view
class="comment-add"
@@ -271,19 +362,21 @@
:placeholder="placeholder"
:adjust-position="false"
:show-confirm-bar="false"
@blur="blur"
@focus="focusOn"
@blur.stop="blur"
@focus.stop="focusOn"
:focus="focus"
maxlength="800"
></textarea>
</view>
</view>
<!-- <Emoji :show="show" @emoji="emojiChange" @emojiblur="emojiblur" /> -->
<!-- 新增评论-end -->
</view>
</template>
<script>
import text from "uview-ui/libs/config/props/text";
import Emoji from "./emoji.vue";
export default {
name: "hb-comment",
@@ -294,12 +387,35 @@ export default {
return null;
},
},
isDisable: {
type: Boolean,
default: () => {
return false;
},
},
isShowList: {
type: Boolean,
default: () => {
return false;
},
},
isPopup: {
type: Boolean,
default: () => {
return false;
},
},
user: {
type: Object,
default: () => {
return null;
},
},
articleUserId: {
default: () => {
return null;
},
},
deleteTip: {
type: String,
default: () => {
@@ -315,9 +431,84 @@ export default {
immediate: true,
},
},
components: {
Emoji,
},
data() {
return {
list: [
"😃",
"😆",
"😅",
"🤣",
"😂",
"🙂",
"🙃",
"😉",
"😊",
"😇",
"🥰",
"😍",
"🤩",
"😘",
"😗",
"☺️",
"😚",
"😙",
"😋",
"😛",
"😜",
"🤪",
"😝",
"🤑",
"😩",
"😖",
"😨",
"😭",
"😞",
"🤓",
"🤠",
"😎",
"🥳",
"😵",
"🤧",
"🤕",
"🤗",
"🤭",
"🤫",
"🤔",
"🤐",
"🤨",
"😐",
"😑",
"😶",
"😏",
"😒",
"🙄",
"😬",
"🤥",
"😶‍🌫️",
"😮‍🌫️",
"😴",
"🤮",
"❤️",
"💯",
"💔",
"💩",
"🤡",
"🤖",
"👻",
"🙈",
"🙉",
"🙊",
"💣",
"💋",
"😡",
"🤬",
"😠",
],
pId: 0,
show: false, // 是否显示输入框
showInput: false, // 是否显示输入框
commentContent: "", // 评论内容
keyboardHeight: 0, // 软键盘高度
@@ -339,7 +530,7 @@ export default {
mounted: function () {
this.pId = 0;
this.showInput = false;
this.placeholder = "评论...";
this.placeholder = "发表评论...";
this.commentContent = "";
this.keyboardListener = uni.onKeyboardHeightChange((res) => {
@@ -356,16 +547,44 @@ export default {
}
},
methods: {
tap(item) {
console.log("item at line 515:", item);
this.commentContent += item;
// this.$emit("emoji", item); // 触发 emoji 事件,将选择的 emoji 传给父组件
},
emojichet() {
// this.reply("", "", 0);
this.show = !this.show; // 打开 emoji 列表
},
scrollToView(callback) {
const query = uni.createSelectorQuery().in(this);
query
.select("#commentData")
.boundingClientRect((rect) => {
if (rect) {
callback(rect);
}
})
.exec();
},
onInputFocus() {
// 可以在这里添加额外的逻辑,如滚动到输入框位置
},
// 输入框失去焦点
onInputBlur() {
console.log(11111111111);
setTimeout(() => {
if (!this.commentContent.trim() && !this.show) {
this.showInput = false;
}
}, 200);
// 如果输入框为空,点击空白处关闭输入框
if (!this.commentContent.trim()) {
this.showInput = false;
}
},
// 发送评论
@@ -378,6 +597,8 @@ export default {
// 发送成功后清空并隐藏输入框
this.commentContent = "";
this.showInput = false;
} else {
this.$commonJS.showToast("请输入评论");
}
},
// 初始化评论
@@ -394,6 +615,9 @@ export default {
stopPrevent() {},
// 回复评论
reply(pUser, reUser, pId) {
if (this.isDisable) {
return false;
}
this.pUser = pUser;
this.commentReq.pId = pId;
this.pId = pId;
@@ -402,7 +626,7 @@ export default {
this.placeholder = "回复 " + str + ":";
} else {
var str = "";
this.placeholder = "评论...";
this.placeholder = "发表评论...";
}
// if (reUser) {
@@ -585,14 +809,14 @@ export default {
}
.comment-main {
width: calc(100% - 70rpx);
width: calc(100% - 64rpx);
padding-left: 20rpx;
}
.comment-main-top {
width: 600rpx;
padding-top: 12rpx;
width: 100%;
padding-top: 4rpx;
display: flex;
justify-content: space-between;
}
@@ -605,8 +829,8 @@ export default {
}
.avatar {
width: 70rpx;
height: 70rpx;
width: 64rpx;
height: 64rpx;
border-radius: 50%;
}
@@ -709,11 +933,12 @@ export default {
}
.comment-none {
height: auto;
padding: 4rpx 0;
width: 100%;
// text-align: center;
color: #999999;
position: absolute;
position: fixed;
bottom: 0;
left: 0;
display: flex;
@@ -826,4 +1051,37 @@ export default {
line-height: 20rpx;
margin-top: -4rpx;
}
.emoji_blur {
height: 100vh;
width: 100%;
position: absolute;
top: 0;
background: transparent;
}
.emoji_box {
height: 440rpx;
background: #f6f6f6;
position: fixed;
bottom: 0;
left: 0;
}
.scrool {
height: 400rpx;
width: 100%;
margin-top: 30rpx;
}
.emojis {
width: 95%;
margin: 0 auto;
font-size: 40rpx;
display: flex;
flex-wrap: wrap;
gap: 10rpx 25rpx;
flex-shrink: 3;
// padding-bottom: 50rpx;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 966 B