Browse Source

合并master

jwyu 2 years ago
parent
commit
ef906c3c4c

+ 71 - 0
api/question.js

@@ -71,4 +71,75 @@ export const apiSetRead = params=>{
  */
 export const apiCountAudioClick = params=>{
     return httpPost('/community/question/audio/log',params)
+}
+
+
+
+/**
+ * 点赞/吐槽
+ *  "community_question_id": 35,
+    "op_type": 1, 1-点赞 2-吐槽
+    "enable": 1, 0取消 1-有效数据
+    "source_agent": 1, 1:小程序,2:小程序 pc 3:弘则研究公众号,4:web pc
+ */
+export const apiSetLike = params => {
+   return httpPost('/community/set_like_or_tease',{ source_agent:1,...params })
+}
+
+/**
+ * 发布评论
+ * @param {*} params 
+ * "community_question_id": 35,
+    "content": "这里是roc的测试评论",
+    "is_show_name": 0,
+    "source_agent": 1,
+ */
+export const apiPublishComment = params => {
+   return httpPost('/community/comment',{ source_agent:1,...params })
+}
+
+/**
+ * 获取设置昵称状态
+ * @param {*} params 
+ */
+export const apiCheckNick = params => {
+   return httpGet('/community/need_anonymous_user_tips')
+}
+
+/**
+ * 不在提醒设置弹窗
+ * @param {*} params 
+ */
+export const apiCanelNickTip = params => {
+   return httpPost('/community/set_anonymous_user_tips')
+}
+
+/**
+ * 删除留言
+ * @param {community_question_comment_id} params 
+ */
+export const apiDelComment = params => {
+   return httpPost('/community/comment/delete',params)
+}
+
+/**
+ * 精选留言列表
+ * @param {*} params
+ * community_question_id 
+ * curr_page
+ * page_size
+ */
+export const apiHotComment = params => {
+   return httpGet('/community/comment/hot',params)
+}
+
+/**
+ * 我的留言列表
+ * @param {*} params
+ * community_question_id 
+ * curr_page
+ * page_size
+ */
+export const apiMyComment = params => {
+   return httpGet('/community/comment/my',params)
 }

+ 112 - 0
components/questionComment/questionComment.vue

@@ -0,0 +1,112 @@
+<!-- 问答评论区 --> 
+
+<template>
+	<view class="question-comment-box">
+		<!-- 第一条评论 -->
+		<view class="first-comment" v-if="data.comment">
+			<!-- <img :src="comment_img" alt="" class="icon"> -->
+			<view class="comment">
+				{{data.comment_user_name}}:
+				{{data.comment}}
+			</view>
+		</view>	
+			
+		<!--  -->
+		<view class="question-comment-wrapper">
+			<view class="commetn-item-wrap" @click.stop="setLikeHandle(2)">
+				<img :src="data.op_type===2?tease_act_img:tease_img" alt="" class="icon">
+				<text v-if="data.tease_total">{{data.tease_total}}</text>
+			</view>
+			<view class="commetn-item-wrap" @click.stop="openCommentHandle" style="justify-content:center;">
+				<img :src="comment_img" alt="" class="icon"> 
+				<text v-if="data.comment_total">{{data.comment_total}}</text>
+			</view>
+			<view class="commetn-item-wrap" @click.stop="setLikeHandle(1)" style="justify-content:flex-end;">
+				<img :src="data.op_type===1?like_act_img:like_img" alt="" class="icon">
+				<text v-if="data.like_total">{{data.like_total}}</text>
+			</view>
+		</view>
+		
+	</view>
+</template>
+
+<script>
+   import * as $api from '@/api/question.js'
+	export default {
+		props: {
+			item: {
+				type: Object,
+			}
+		},
+		data() {
+			return {
+            data: this.item,
+				tease_img: require('@/static/question/tease.png'),
+				tease_act_img: require('@/static/question/tease_act.png'),
+				like_img: require('@/static/question/like.png'),
+				like_act_img: require('@/static/question/like_act.png'),
+				comment_img: require('@/static/question/comment.png'),
+			};
+		},
+		methods: {
+			openCommentHandle() {
+				this.$emit('show_comment',this.data)
+			},
+         
+         /* 吐槽/点赞 */
+         async setLikeHandle(type) {
+            const { community_question_id } = this.data;
+            const { data, code } = await $api.apiSetLike({
+               op_type: type,
+               community_question_id: community_question_id,
+               enable: type === 1 ? Number(this.data.op_type!==1) : Number(this.data.op_type!==2)
+            })
+            
+            if(code !== 200) return
+            
+            const { enabled,op_type,like_total,tease_total } = data;
+            this.data.tease_total = tease_total;
+            this.data.like_total = like_total;
+            this.data.op_type = enabled === 0 ? 0 : op_type ;
+            uni.showToast({
+               title: enabled === 0 ? '取消成功' : op_type=== 1 ? '点赞成功' : '吐槽成功'
+            })
+         },
+         
+         
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+.first-comment {
+   background-color: #f4f4f4;
+   padding: 10rpx;
+	.comment {
+		color: #666;
+		display: flex;
+		flex-wrap: wrap;
+		.commenter {
+			color: #000;
+		}
+	}
+}
+.question-comment-wrapper {
+	color: #999;
+	display: flex;
+	justify-content: space-between;
+	align-items: center;
+	padding: 30rpx 40rpx;
+	.commetn-item-wrap {
+		display: flex;
+		align-items: center;
+      flex: 1;
+		.icon {
+			width: 48rpx;
+			height: 48rpx;
+			margin-right: 10rpx;
+		}
+	}
+}
+
+</style>

+ 38 - 9
pages-sandTable/sandTable.vue

@@ -28,6 +28,10 @@
 				</view>
 			</view>
 		</block>
+		<!-- 部分有权限 分享进来没有权限 -->
+		<block v-if="noAuthor ==4 && isFinished">
+			<!-- 显示空白 一秒钟后跳转至有权限的沙盘图-->
+		</block>
 		<!-- 有权限 -->
 		<view v-show="noAuthor ==0 && isFinished" style="padding-top: 156rpx;">
 			<view style="position: fixed;top: 0;width: 100vw;">
@@ -250,7 +254,7 @@
 			// 获取沙盘图数据
 			getSandBoxList(option){
 				this.isRequseting=true
-				apiSandTableList(this.sandTableQuery).then(({data:{list,paging,type,name,mobile,customer_info},code})=>{
+				apiSandTableList(this.sandTableQuery).then(({data:{list,paging,type,name,mobile,customer_info,jump},code})=>{
 					if(option == 'stopPullDown'){
 						uni.stopPullDownRefresh()
 					}
@@ -264,10 +268,22 @@
 							// 申请
 							this.noAuthor =1
 						}else{
-							// 联系销售
-							this.noAuthor =2
-							this.salesData.name=name
-							this.salesData.phone=mobile
+							if(jump){
+								this.noAuthor =4
+								// jump 跳转,说明该用户是有部分权限,提示“暂无此权限”,跳转至有权限的分类
+								uni.showToast({
+									title:"暂无此权限",
+									icon:'none'
+								})
+								setTimeout(()=>{
+									uni.redirectTo({url:'/pages-sandTable/sandTable'})
+								},1000)
+							}else{
+								// 联系销售
+								this.noAuthor =2
+								this.salesData.name=name
+								this.salesData.phone=mobile
+							}
 						}
 						return 
 					}
@@ -297,10 +313,23 @@
 							// 申请
 							this.noAuthor =1
 						}else{
-							// 联系销售
-							this.noAuthor =2
-							this.salesData.name=data.name
-							this.salesData.phone=data.mobile
+							if(data.jump){
+								// jump 跳转,说明该用户是有部分权限,提示“暂无此权限”,跳转至有权限的分类
+								this.noAuthor =4
+								uni.showToast({
+									title:"暂无此权限",
+									icon:'none'
+								})
+								setTimeout(()=>{
+									uni.redirectTo({url:'/pages-sandTable/sandTable'})
+								},1000)
+							}else{
+								// 联系销售
+								this.noAuthor =2
+								this.salesData.name=data.name
+								this.salesData.phone=data.mobile
+							}
+
 						}
 						return 
 					}

+ 2 - 1
pages.json

@@ -360,7 +360,8 @@
 			"van-checkbox": "/wxcomponents/vant/checkbox/index",
 			"van-transition": "/wxcomponents/vant/transition/index",
 			"van-collapse": "/wxcomponents/vant/collapse/index",
-  			"van-collapse-item": "/wxcomponents/vant/collapse-item/index",
+			"van-collapse-item": "/wxcomponents/vant/collapse-item/index",
+			"van-action-sheet": "/wxcomponents/vant/action-sheet/index",
 			"van-tag": "/wxcomponents/vant/tag/index",
 			"van-row": "/wxcomponents/vant/row/index",
   			"van-col": "/wxcomponents/vant/col/index",

+ 266 - 6
pages/question/question.vue

@@ -36,7 +36,8 @@
 				<view>暂无提问<text v-if="userInfo.is_inner!==1">,快试试提问功能吧</text></view>
 			</view>
 			<view class="question-list" :class="showAudioPop?showAudioBigPop?'list-bot3':'list-bot2':'list-bot1'">
-				<view class="question-item" @click="handleGoDetail(item)" v-for="item in questionList" :key="item.community_question_id">
+				<view class="question-item" v-for="item in questionList" :key="item.community_question_id">
+					<text class="item-time">提问时间:{{ item.create_time }}</text>
 					<view class="question-info">
 						<view style="flex:1;" class="question-title">
 							<text class="item-label">{{item.variety_tag_name}}</text>
@@ -70,7 +71,9 @@
 							</view> -->
 						</view>
 					</view>
-					<text class="item-time">提问时间:{{ item.create_time }}</text>
+					
+					<!-- 评论区域 -->
+					<questionComment :item="item" @show_comment="showCommentHandle"/>
 				</view>
 			</view>
 			<template v-if="isUserResearcher">
@@ -140,18 +143,76 @@
         <view v-if="showPage">
             <audioBox v-if="showAudioPop"/>
         </view>
+		
+		<!-- 评论弹窗 -->
+		<van-action-sheet 
+			:show="isShowComment" 
+			title="全部评论"
+			@close="closeCommentHandle"
+			@clickOverlay="isShowComment=false"
+		>
+			<view class="comment-cont" @touchmove.stop>
+			   <view class="commment-top">
+				   <text class="title">{{comment_obj.title}} {{comment_obj.total}}</text>
+				   <view class="comment-top-right">
+					   <text :class="select_comment_type === 1 && 'act'" @click="changeCommentTypeHandle(1)">精选</text>
+					   <text :class="select_comment_type === 2 && 'act'" @click="changeCommentTypeHandle(2)">我的</text>
+				   </view>
+			   </view>
+				<scroll-view class="comment-list-cont" v-if="comment_obj.total" scroll-y>
+               <view class="comment-list-item" v-for="(item,index) in commentList" :key="item.community_question_comment_id">
+                  <view class="comment">
+                     <text style="color: #333;">{{item.user_name}}:</text>
+                     {{item.content}}
+                  </view>
+                  <view class="del" v-if="select_comment_type === 2"  @click="delCommentHandle(item,index)">删除该评论</view>
+               </view>
+				</scroll-view>
+            <view class="nodata" v-else>
+               <image src="@/static/nodata.png"></image>
+               <view>暂无评论</view>
+            </view>
+				<view class="write-wrap" :style="{bottom: writeBottom+'px'}">
+               <textarea 
+                  v-model="comment_cont" 
+                  placeholder="发布一条友善的评论" 
+                  auto-height
+                  :adjust-position="false"
+                  :show-confirm-bar="false"
+                  :cursor-spacing="20"
+                  class="write-ipt"
+                  @focus="checkNickHandle"
+                  @blur="setWritePosition(50)"
+               />
+				  <view class="confirm-btn" @click="publishMessageHandle">发布</view>
+				</view>
+			</view>
+		</van-action-sheet>
 	</view>
 </template>
 
 <script>
 import mixin from "../../mixin/questionMixin";
-import {apiOptionGroupList,apiBarTotal,apiCountAudioClick} from '@/api/question'
 import {apiGetTagTree} from '@/api/common'
+import {
+   apiOptionGroupList,
+   apiBarTotal,
+   apiHotComment,
+   apiMyComment,
+   apiCheckNick,
+   apiCanelNickTip,
+   apiDelComment,
+   apiPublishComment,
+   apiCountAudioClick
+} from '@/api/question'
+import questionComment from '@/components/questionComment/questionComment.vue'
 import audioBox from '@/components/audioBox/audioBox.vue'
+import { debounce } from '@/utils/common.js';
 export default {
 	mixins: [mixin],
 	components:{
-        audioBox
+        audioBox,
+		questionComment
     },
 	data() {
 		return {
@@ -172,8 +233,21 @@ export default {
 				//seal_name:'梁娜',
 				//seal_mobile:123456,
 			},//mock用户信息 */
+			showPage:false,
 
-			showPage:false
+			waitNum:0,
+			
+			isShowComment: false,
+			comment_cont: '',
+			writeBottom: 50,
+			select_comment_type:1,//默认精选
+			select_question_item: {},
+			comment_obj: {
+				title: '精选评论',
+				total: 0
+			},
+			comment_total: 0,
+			commentList: []
 		}
 	},
 	watch:{
@@ -297,7 +371,113 @@ export default {
 		//跳转详情
 		handleGoDetail(item){
 			uni.navigateTo({ url: `/pages-question/answerDetail?id=${item.community_question_id}` })
-		}
+		},
+		
+		/* 打开评论弹窗 */  
+		showCommentHandle(item) {
+         this.select_question_item = item;
+         this.getComment();
+			this.isShowComment = true;
+		},
+      
+      /* 关闭评论弹窗 */
+      closeCommentHandle() {
+         this.isShowComment = false;
+         this.select_question_item = {};
+         this.comment_cont = '';
+         this.select_comment_type = 1;//默认精选
+      },
+      
+      /* 切换评论类型*/
+      changeCommentTypeHandle(type) {
+         if(type === this.select_comment_type) return
+         this.commentList = [];
+         this.select_comment_type = type;
+         this.getComment();
+      },
+      
+      /* 获取评论 */
+      async getComment() {
+         const params = {
+            community_question_id: this.select_question_item.community_question_id,
+            curr_page: 1,
+            page_size: 10000
+         }
+         const { code,data } = this.select_comment_type===1 ? await apiHotComment(params) : await apiMyComment(params);
+         
+         if(code !== 200) return
+         this.commentList = data.list || [];
+         this.comment_obj = {
+            title: this.select_comment_type === 1 ? '精选评论' : '我的评论',
+            total: data.paging.totals
+         }
+      },
+      
+      /* 删除留言*/
+      delCommentHandle({community_question_comment_id},index) {
+         wx.showModal({
+            title: "",
+            content: "评论删除后不可恢复,确认删除吗?",
+            confirmColor: "#EE3636",
+            cancelColor: '#333',
+            success:  async(res) => {
+               if( res.cancel) return
+               const { code } = await apiDelComment({ community_question_comment_id });
+               if( code !== 200 ) return
+               
+               this.commentList.splice(index,1)
+                        
+               wx.showToast({title: '删除成功'});
+            }
+         })
+      },
+      
+      setWritePosition(val=50) {
+         console.log(val)
+         this.writeBottom = val < 50 ? 50 : val;
+      },
+      
+      /* 校验昵称状态*/
+      async checkNickHandle(e) {
+         this.setWritePosition(e.detail.height);
+         
+         const { data,code } = await apiCheckNick();
+         
+         if(code !== 200) return
+         
+         !data && wx.showModal({
+            title: '',
+            content: '检测到您还未设置头像和昵称,您的留言将发布为匿名,是否立即去设置?',
+            confirmText: '去设置',
+            confirmColor: '#E3B377',
+            cancelText	: '暂时不用',
+            cancelColor: '#666',
+            success: (res)=> {
+               res.confirm && wx.navigateTo({ url:'/pages-user/mysetting' });
+               res.cancel && this.setCancelNickHandle();
+            }
+         })
+      },
+      
+      /* 不在提醒弹窗 */
+      async setCancelNickHandle() {
+         await apiCanelNickTip()
+      },
+      
+      /* 发布留言*/
+      publishMessageHandle: debounce( async function() {
+         if(!this.comment_cont) return wx.showToast({title: '请输入留言内容',icon: 'none'});
+         
+         const { code } = await apiPublishComment({
+            content: this.comment_cont,
+            community_question_id: this.select_question_item.community_question_id
+         })
+         
+         if(code !== 200) return
+         wx.showToast({title: '发布成功'});
+         this.comment_cont = '';
+         this.select_comment_type === 2 && this.getComment();
+      })
 	}
 }
 </script>
@@ -502,4 +682,84 @@ page {
 		}
 	}
 }
+.comment-cont {
+	height: calc(100vh - 250rpx);
+	border-top: 4rpx solid #F4F4F4;
+   position: relative;
+   padding: 24rpx 0;
+   overflow: hidden;
+   .commment-top {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      padding: 0 24rpx;
+      .title {
+         font-weight: bold;
+         font-size: 30rpx;
+         color: #000;
+      }
+      .comment-top-right {
+         display: flex;
+         align-items: center;
+         background-color: #F6F6F6;
+         border: 1px solid #F6F6F6;
+         color: #666;
+         border-radius: 48rpx;
+         text {
+            padding: 0 12rpx;
+            height: 48rpx;
+            line-height: 48rpx;
+            &.act {
+               background-color: #FFFFFF;
+               color: #000;
+               border-radius: 48rpx;
+            }
+         }
+      }
+   }
+   .comment-list-cont {
+      height: calc(100vh - 550rpx);
+      overflow-y: auto;
+      position: relative;
+      padding: 30rpx 0;
+      .comment-list-item {
+				margin-bottom: 30rpx;
+				padding: 0 24rpx;
+				.comment { color: #666; }
+				.del { color: #D80000;margin-top: 10rpx;width: 200rpx; }
+      }
+   }
+   .write-wrap {
+      padding: 0 24rpx;
+      border-top: 4rpx solid #F4F4F4;
+      position: absolute;
+      // bottom: 50px;
+      left: 0;
+      right: 0;
+      display: flex;
+      align-items: center;
+      z-index: 99;
+      background-color: #fff;
+      padding-bottom: calc(5px + constant(safe-area-inset-bottom));
+      padding-bottom: calc(5px + env(safe-area-inset-bottom));
+      ::-webkit-scrollbar {
+         display: none;
+      }
+      .write-ipt {
+         padding: 30rpx 0;
+         flex: 1;
+      }
+      .confirm-btn {
+         width: 100rpx;
+         margin-left: 20rpx;
+         text-align: center;
+         padding: 20rpx 0;
+         color: #E3B377;
+      }
+   }
+}
+.nodata {
+   text-align: center;
+   color: #999;
+}
 </style>

BIN
static/question/comment.png


BIN
static/question/like.png


BIN
static/question/like_act.png


BIN
static/question/tease.png


BIN
static/question/tease_act.png


+ 14 - 0
utils/common.js

@@ -65,3 +65,17 @@ export const hasUpdate = () => {
     });
   });
 };
+
+/**
+ * 
+ * 防抖
+ */
+export const debounce = (fn,t=300) => {
+   let timer = null;
+   return function() {
+      clearTimeout(timer);
+      timer = setTimeout(_ => {
+         fn.call(this, arguments);
+      }, t);
+   };
+}