| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618 |
- <template>
- <div class="container">
- <!-- 评论输入框 -->
- <div class="write-reply" @click="showCommentInput()">
- <i class="el-icon-edit"></i>
- <span class="add-comment">添加新评论</span>
- </div>
- <el-collapse-transition>
- <div class="input-wrapper" v-if="isShowInput">
- <p class="reply-box" v-if="replyUser">{{ replyUser }}:</p>
- <el-input
- ref="inputComment"
- resize="none"
- class="gray-bg-input"
- v-model="inputComment"
- type="textarea"
- :rows="4"
- autofocus
- placeholder="写下你的评论..."
- @paste.native.capture.prevent="pasting"
- >
- </el-input>
- <div class="btn-control">
- <div class="left">
- <el-upload
- v-show="fileList.length > 0"
- ref="upload"
- accept="image/*"
- multiple
- :action="uploadUrl"
- :file-list="fileList"
- list-type="picture-card"
- :on-change="handleImgChange"
- :on-success="handleFrontSuccess"
- :on-remove="handleRemove"
- >
- <i class="el-icon-plus"></i>
- </el-upload>
- <i class="el-icon-picture finger-point" @click="submitUpload"></i>
- </div>
- <div class="right">
- <span class="cancel" @click="cancel">取消</span>
- <el-button
- class="confirm"
- type="success"
- round
- @click="commitComment"
- >确定</el-button
- >
- </div>
- </div>
- </div>
- </el-collapse-transition>
- <div class="comment" ref="commentRoot" :class="{move:item.id==$route.query.id}" v-for="(item, index) in comments" :key="index">
- <div class="info">
- <img
- class="avatar"
- v-if="item.has_one_comment_user"
- :src="item.has_one_comment_user.avatar"
- />
- <div style="margin-left: 10px; flex: 1">
- <div class="right-box">
- <div class="name">{{ item.uname }}</div>
- <div class="date">{{ item.created_at }}</div>
- <div class="control finger-point">
- <!-- 点赞 -->
- <span
- :style="{ color: item.is_praise ? '#ec544a' : '' }"
- @click.stop="praiseBtn(item.id, '', index, '', item.is_praise)"
- >
- <i class="iconfont icon-fontclass-tuijian"></i>
- {{ item.praise_num }}
- </span>
- <!-- 评论 -->
- <span @click.stop="showCommentInput(item)">
- <i class="iconfont icon-fontclass-pinglun2"></i> 回复
- </span>
- <!-- 赞赏 -->
- <span @click.stop="moneyShow(item)" v-if="comment_open == 1">
- <i class="iconfont icon-fontclass-shang"></i> 赞赏
- </span>
- <span v-if="item.is_own == 1" @click.stop="deleteBtn(item)">
- <i class="iconfont icon-fontclass-shanchu"></i>
- </span>
- </div>
- </div>
- <div class="comment-content">{{ item.content }}</div>
- <div class="comment-imgs">
- <el-image
- v-for="(imgItem, index) in item.image"
- :key="index"
- :src="imgItem"
- fit="contain"
- @click.stop="toShowImgViewer(item.image, index)"
- ></el-image>
- </div>
- <div
- class="reply finger-point look-child"
- @click.stop="showChild = true"
- v-if="!showChild && item.child.length > 0"
- >
- 查看该评论回复
- </div>
- <div class="reply" v-if="showChild">
- <div
- class="item"
- v-for="(reply, replyIndex) in item.child"
- :key="replyIndex"
- >
- <div class="flex flex-a-c">
- <div style="display: flex; align-self: flex-start">
- <img
- class="reply-avatar"
- v-if="reply.has_one_comment_user"
- :src="reply.has_one_comment_user.avatar"
- alt=""
- />
- </div>
- <div style="margin-left: 10px; flex: 1">
- <div class="right-box">
- <div class="reply-title">
- <span class="from-name">{{ reply.uname }}</span
- ><span>: </span>
- <span class="to-name" v-if="reply.less_name"
- >@{{ reply.less_name }}</span
- >
- <span class="reply-time">{{ reply.created_at }}</span>
- </div>
- <div class="control finger-point">
- <!-- 点赞 -->
- <span
- :style="{ color: reply.is_praise ? '#ec544a' : '' }"
- @click.stop="
- praiseBtn(
- reply.major_cm_id,
- reply.id,
- index,
- replyIndex,
- reply.is_praise
- )
- "
- >
- <i class="iconfont icon-fontclass-tuijian"></i>
- {{ reply.praise_num }}
- </span>
- <!-- 评论 -->
- <span @click.stop="showCommentInput(item, reply)">
- <i class="iconfont icon-fontclass-pinglun2"></i> 回复
- </span>
- <span
- v-if="reply.is_own == 1"
- @click.stop="deleteBtn(reply)"
- >
- <i class="iconfont icon-fontclass-shanchu"></i>
- </span>
- </div>
- </div>
- <div class="reply-content">{{ reply.content }}</div>
- <div class="comment-imgs">
- <el-image
- v-for="(imgItem, index) in reply.image"
- :key="index"
- :src="imgItem"
- fit="contain"
- @click.stop="toShowImgViewer(reply.image, index)"
- ></el-image>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- <el-image-viewer
- v-if="showViewer"
- :initialIndex="initialIndex"
- @onClose="showViewer = false"
- :url-list="img_list"
- />
- <div class="check-more finger-point" v-if="showMore" @click="loadMore">
- 查看更多
- </div>
- </div>
- </template>
- <script>
- import ElImageViewer from "~/components/default/image-viewer";
- export default {
- props: {
- showMore: {
- type: Boolean,
- default: false,
- },
- comments: {
- type: Array,
- required: true,
- },
- comment_open: {},
- is_detail: {},
- },
- data() {
- return {
- showChild: false,
- img_list: [],
- showViewer: false,
- initialIndex: 0,
- isShowInput: false,
- replyUser: "",
- inputComment: "",//评论内容
- host_comment_id: "",
- second_comment_id: "",
- uploadUrl: "",
- fileList: [],
- imgData: [],
- options_type: "",
- move_flag:true
- };
- },
- components: {
- ElImageViewer,
- },
- mounted() {
- this.uploadUrl = this.fun.getRealUrl("upload.uploadPic", {});
- },
- methods: {
- move_comment_handle(dom=false){
- let ele=this.$refs.commentRoot,y,arr=[];
- if(dom){
- this.$nextTick(()=>{
- for(let i = 0;i<ele.length;i++){
- if(ele[i]._prevClass.indexOf("move")!==-1){
- y = ele[i].offsetTop + document.documentElement.clientHeight/2;
- this.keep_move(ele[i].getBoundingClientRect().top)
- }
- }
- })
- }
- if(ele.length==1){
- y = ele[0].offsetHeight + document.documentElement.clientHeight/2;
- this.keep_move(y)
- }else if(ele && ele.length>1){
- for(let i = 0;i<ele.length;i++){
- if(ele[i]._prevClass.indexOf("move")!==-1){
- y = ele[i].offsetHeight + document.documentElement.clientHeight/2;
- this.keep_move(y)
- }else{
- arr.push(ele[i]._prevClass)
- }
- }
- }
- if(!arr.includes("move")){
- this.move_flag = false;
- this.loadMore(true)
- }
- },
- keep_move(y){
- let timer,speed=1;
- timer = setInterval(() => {
- speed+=10;
- if(speed>=y){
- window.scrollTo(0,y)
- clearInterval(timer)
- }else{
- window.scrollTo(0,speed)
- }
- }, 10);
- },
- pasting(event) {
- let txt = event.clipboardData.getData("Text");
- if (typeof txt == "string") {
- this.inputComment += txt;
- }
- let file = null;
- const items = (event.clipboardData || window.clipboardData).items;
- if (items.length) {
- for (let i = 0; i < items.length; i++) {
- if (items[i].type.indexOf("image") !== -1) {
- file = items[i].getAsFile();
- this.handleChange(file);
- if (!this.canUpload) {
- this.canUpload = !this.canUpload;
- }
- break;
- }
- }
- }
- },
- // 上传
- handleChange(file, filelist) {
- let formData = new FormData();
- formData.append("file", file.raw || file);
- this.fun
- .$post(
- "/addons/yun_shop/api.php?i=1&type=5&shop_id=null&route=upload.uploadPic",
- formData
- )
- .then((res) => {
- if(res.result==1){
- this.fileList.push({url:res.data.img_url,hasSuccess: true})
- this.imgData.push({ url: res.data.img_url, uid: file.uid })
- }else{
- this.$message.error(res.msg);
- }
- })
- .catch((err) => {
- console.log(err);
- });
- },
- toShowImgViewer(list, index) {
- this.img_list = list;
- this.initialIndex = index;
- this.showViewer = true;
- },
- submitUpload() {
- this.$refs["upload"].$children[1].$refs.input.click();
- },
- checkAllSuccess() {
- // 检查图片是否上传完成
- return Object.keys(this.fileList).every(
- (item) => this.fileList[item].hasSuccess
- );
- },
- handleImgChange(file, fileList) {
- this.fileList = fileList;
- },
- handleFrontSuccess(res, file, fileList) {
- if (res.result == 1) {
- this.fileList.map((item, index) => {
- if (item.uid == file.uid) {
- this.fileList[index].hasSuccess = true;
- this.imgData[index] = { url: res.data.img_url, uid: file.uid };
- }
- });
- console.log(fileList,this.imgData)
- } else {
- let ind = 0;
- this.fileList.map((item, index) => {
- if (item.uid == file.uid) {
- ind = index;
- }
- });
- this.fileList.splice(ind, 1);
- fileList.splice(ind, 1);
- this.$message.error(res.msg);
- }
- },
- handleRemove(file) {
- this.imgData = this.imgData.filter((item) => {
- return item.uid != file.uid;
- });
- this.fileList = this.fileList.filter((item) => {
- return item.uid != file.uid;
- });
- },
- // 点赞
- praiseBtn(host_comment_id, second_comment_id, index, chilindex, is_praise) {
- let data = {
- host_comment_id,
- second_comment_id,
- index,
- chilindex,
- is_praise,
- };
- this.$emit("praiseBtn", data);
- },
- // 赞赏
- moneyShow(item) {
- this.$emit("moneyShow", item);
- },
- deleteBtn(item) {
- this.$emit("delReply", item);
- },
- // 加载更多
- loadMore(position=false) {
- this.$emit("loadMore",position);
- },
- // 取消
- cancel() {
- this.host_comment_id = "";
- this.second_comment_id = "";
- this.replyUser = "";
- this.isShowInput = false;
- },
- // 提交评论
- commitComment() {
- if (!this.inputComment) {
- this.$message.error("不能发送空白信息");
- return;
- }
- if (!this.checkAllSuccess()) {
- this.$message("请等待所有图片上传成功!");
- return;
- }
- let _json = {
- content: this.inputComment,
- image: this.imgData.map((item) => {
- return item.url;
- }),
- host_comment_id: this.host_comment_id,
- second_comment_id: this.second_comment_id,
- };
- if (this.options_type) {
- _json.options_type = this.options_type;
- }
- this.$emit("confirm", _json);
- this.inputComment = "";
- this.imgData = [];
- this.fileList = [];
- this.$refs.upload.clearFiles();
- },
- // 显示输入框
- showCommentInput(item, reply, flag) {
- if (reply) {
- this.second_comment_id = reply.id;
- this.host_comment_id = item.id;
- this.options_type = "childReply";
- this.replyUser = "回复@" + reply.uname + " ";
- } else if (item) {
- this.second_comment_id = "";
- this.host_comment_id = item.id;
- this.options_type = "reply";
- this.replyUser = "回复@" + item.uname + " ";
- } else {
- this.host_comment_id = "";
- this.second_comment_id = "";
- this.options_type = "";
- this.replyUser = "";
- }
- this.inputComment = "";
- this.isShowInput = true;
- if (flag != "noFocus") {
- this.$nextTick(() => {
- this.$refs.inputComment.focus();
- });
- }
- },
- },
- updated(){
- if(this.$route.query.move && this.move_flag){
- this.move_comment_handle()
- }
- }
- };
- </script>
- <style lang="scss" rel="stylesheet/scss">
- $color-main: #409eff;
- $text-main: #303133;
- $text-minor: #909399; //次要文字
- .container {
- padding: 0 10px;
- box-sizing: border-box;
- .write-reply {
- display: flex;
- align-items: center;
- font-size: 14px;
- color: $text-minor;
- padding: 10px;
- cursor: pointer;
- &:hover {
- color: $text-main;
- }
- .el-icon-edit {
- margin-right: 5px;
- }
- }
- .input-wrapper {
- padding: 0 10px 10px 10px;
- .reply-box {
- margin-bottom: 5px;
- color: var(--color);
- }
- .gray-bg-input,
- .el-input__inner {
- background-color: #296fd8;
- }
- .btn-control {
- display: flex;
- justify-content: space-between;
- align-items: flex-end;
- padding-top: 10px;
- .el-icon-picture {
- font-size: 24px;
- color: #ababab;
- border-radius: 8px;
- overflow: hidden;
- }
- .cancel {
- font-size: 14px;
- color: #606266;
- margin-right: 20px;
- cursor: pointer;
- &:hover {
- color: #333;
- }
- }
- .confirm {
- font-size: 14px;
- padding: 6px 20px;
- }
- }
- }
- .move{}
- .comment {
- display: flex;
- flex-direction: column;
- padding: 10px;
- border-bottom: 1px solid #f2f6fc;
- .info {
- display: flex;
- // align-items: center;
- .avatar {
- width: 40px;
- height: 40px;
- border-radius: 50%;
- }
- .right-box {
- display: flex;
- align-items: center;
- .name {
- font-size: 14px;
- color: $text-main;
- font-weight: 500;
- }
- .date {
- font-size: 12px;
- margin-left: 20px;
- color: $text-minor;
- }
- .control {
- flex: 1;
- text-align: right;
- }
- .control span {
- margin-right: 10px;
- }
- }
- }
- .comment-content {
- word-break: break-all;
- font-size: 16px;
- color: $text-main;
- line-height: 20px;
- padding: 10px 0;
- }
- .comment-imgs {
- display: flex;
- flex-wrap: wrap;
- .el-image {
- cursor: pointer;
- width: 60px;
- height: 60px;
- border-radius: 2px;
- margin: 0 10px 10px 0;
- }
- }
- .look-child {
- padding-left: 10px;
- color: #666666;
- }
- .look-child:hover {
- color: var(--color);
- }
- .reply {
- margin: 10px 0;
- border-left: 2px solid #dcdfe6;
- .item {
- margin: 0 10px;
- padding: 10px 0;
- border-bottom: 1px dashed #ebeef5;
- .reply-avatar {
- width: 40px;
- height: 40px;
- border-radius: 50%;
- margin-right: 10px;
- }
- .reply-title {
- .from-name {
- color: $color-main;
- }
- .to-name {
- color: $color-main;
- margin-left: 5px;
- margin-right: 5px;
- }
- .reply-time {
- font-size: 12px;
- color: $text-minor;
- }
- }
- .reply-content {
- font-size: 14px;
- color: $text-main;
- padding: 6px 0;
- }
- }
- }
- }
- .check-more {
- padding-top: 10px;
- text-align: center;
- color: #666666;
- }
- .check-more:hover {
- color: var(--color);
- }
- }
- </style>
|