Ver Fonte

Merge branch 'yb11.5'

jwyu há 2 anos atrás
pai
commit
c4b5bd4762

+ 1 - 0
api/common.js

@@ -57,6 +57,7 @@ export const apiGetSceneToParams=params=>{
 
 
 /**
 /**
  * 获取标签树
  * 获取标签树
+ * @param community_question_id 问答id
  */
  */
 export const apiGetTagTree = params=>{
 export const apiGetTagTree = params=>{
     return httpGet('/public/get_variety_tag_tree',params)
     return httpGet('/public/get_variety_tag_tree',params)

+ 22 - 0
api/question.js

@@ -24,6 +24,8 @@ export const apiOptionGroupList = params=>{
 /**
 /**
  * 发布提问
  * 发布提问
  * @param question_content
  * @param question_content
+ * @param variety_classify_id 
+ * @param variety_tag_id
  */
  */
  export const apiPubAsk=params=>{
  export const apiPubAsk=params=>{
     return httpPost('/community/question/ask',params)
     return httpPost('/community/question/ask',params)
@@ -146,4 +148,24 @@ export const apiHotComment = params => {
  */
  */
 export const apiMyComment = params => {
 export const apiMyComment = params => {
    return httpGet('/community/comment/my',params)
    return httpGet('/community/comment/my',params)
+}
+
+/**
+ * 终止问题
+ * @param community_question_id
+ * @param reason
+ */
+export const apiQuestionStop=params=>{
+   return httpPost('/community/question/stop',params)
+}
+
+/**
+ * 问题转移给其他研究员
+ * @param community_question_id 问答id
+ * @param variety_classify_id
+ * @param variety_tag_id
+ * @param admin_id
+ */
+export const apiQuestionTransfer=params=>{
+   return httpPost('/community/question/transfer',params)
 }
 }

+ 95 - 5
pages-question/answerDetail.vue

@@ -1,6 +1,13 @@
 <template>
 <template>
   <view class="answerdetail-page flex-column">
   <view class="answerdetail-page flex-column">
     <template v-if="questionItem&&hasAuth">
     <template v-if="questionItem&&hasAuth">
+      <template v-if="questionItem.replier_user_id!=userInfo.user_id">
+        <view style="padding-top:100rpx;text-align:center">
+          <image style="width:200rpx;margin-bottom:20rpx" :src="globalImgUrls.chartWait" mode="widthFix" lazy-load="false" binderror="" bindload="" />
+          <view>问题已转移!</view>
+        </view>
+      </template>
+      <template v-else>
       <view class="question-wrap">
       <view class="question-wrap">
         <view class="question-item">
         <view class="question-item">
           <view class="question-info">
           <view class="question-info">
@@ -76,6 +83,9 @@
               style="width: 90rpx; height: 180rpx"
               style="width: 90rpx; height: 180rpx"
             />
             />
             <view>无录音(录音时长超过三分钟自动结束)</view>
             <view>无录音(录音时长超过三分钟自动结束)</view>
+
+            <view class="black-btn" style="margin-top:100rpx" @click.stop="showRemoveQ=true">转移问题</view>
+            <view class="black-btn" style="margin-top:50rpx" @click.stop="stopQuestion.show=true">终止问答</view>
           </view>
           </view>
           <!-- <view class="record-time" v-else>{{ audioTime }}</view> -->
           <!-- <view class="record-time" v-else>{{ audioTime }}</view> -->
           <view class="recode-image" v-else>
           <view class="recode-image" v-else>
@@ -234,6 +244,7 @@
           </view>
           </view>
         </view>
         </view>
       </view>
       </view>
+      </template>
     </template>
     </template>
     <!-- 没有该问题权限 -->
     <!-- 没有该问题权限 -->
     <template v-else-if="!hasAuth">
     <template v-else-if="!hasAuth">
@@ -248,20 +259,46 @@
 				<view class="apply" @click="handleGoApply" v-else>立即申请</view>
 				<view class="apply" @click="handleGoApply" v-else>立即申请</view>
 			</view>
 			</view>
     </template>
     </template>
+
+    <!-- 终止问答弹窗 -->
+    <van-dialog
+      use-slot
+      title="终止问答"
+      :show="stopQuestion.show"
+      show-cancel-button
+      confirm-button-open-type="getUserInfo"
+      @close="stopQuestion.show=false;stopQuestion.reason=''"
+      @confirm="handleConfirmStopQuestion"
+    >
+      <view style="padding:48rpx">
+        <textarea 
+          style="background: #F7F8FA;border-radius: 8px;padding: 20rpx;display:block;box-sizing:border-box;width:100%" 
+          maxlength="-1" 
+          cols="30" 
+          rows="10" 
+          placeholder="请输入终止理由"
+          v-model="stopQuestion.reason"
+        ></textarea>
+      </view>
+    </van-dialog>
+    <!-- 转移问答弹窗 -->
+    <removeQuestionDig :show="showRemoveQ" :qid="qid" @close="showRemoveQ=false" ></removeQuestionDig>
   </view>
   </view>
 </template>
 </template>
 
 
 <script>
 <script>
 import mixin from "../mixin/questionMixin";
 import mixin from "../mixin/questionMixin";
-import { apiReplayAsk, apiGetQuestion, apiSetRead,apiCountAudioClick } from "@/api/question";
+import { apiReplayAsk, apiGetQuestion, apiSetRead,apiCountAudioClick,apiQuestionStop } from "@/api/question";
 import { apiApplyPermission} from '@/api/user';
 import { apiApplyPermission} from '@/api/user';
 import {apiGetSceneToParams} from "../api/common.js"
 import {apiGetSceneToParams} from "../api/common.js"
 import { uploadAudioToServer } from "@/utils/upload";
 import { uploadAudioToServer } from "@/utils/upload";
 import audioBox from '@/components/audioBox/audioBox.vue'
 import audioBox from '@/components/audioBox/audioBox.vue'
+import removeQuestionDig from './components/removeQuestionDig.vue'
 export default {
 export default {
   mixins: [mixin],
   mixins: [mixin],
   components:{
   components:{
-    audioBox
+    audioBox,
+    removeQuestionDig
   },
   },
   computed:{
   computed:{
 		showAudioPop(){//是否显示音频弹窗
 		showAudioPop(){//是否显示音频弹窗
@@ -286,6 +323,7 @@ export default {
 	},
 	},
   data() {
   data() {
     return {
     return {
+      qid:0,
       questionItem: null /* {
       questionItem: null /* {
         recordStatus: 1, //1:未录音;2:正在录音;3:已暂停;4:完成录音
         recordStatus: 1, //1:未录音;2:正在录音;3:已暂停;4:完成录音
         permission_info:{
         permission_info:{
@@ -321,6 +359,12 @@ export default {
 				is_suspend:1,
 				is_suspend:1,
 				is_researcher:0,
 				is_researcher:0,
 			}, *///mock用户信息
 			}, *///mock用户信息
+
+      stopQuestion:{
+        show:false,
+        reason:'',
+      },//终止问答
+      showRemoveQ:false,//展示转移问题弹窗
     };
     };
   },
   },
   async onLoad(options) {
   async onLoad(options) {
@@ -333,6 +377,7 @@ export default {
 				obj=JSON.parse(res.data)
 				obj=JSON.parse(res.data)
 			}
 			}
 		}
 		}
+    this.qid=obj.id || options.id
     this.getQuestionItem(obj.id || options.id);
     this.getQuestionItem(obj.id || options.id);
   },
   },
   onShow(){
   onShow(){
@@ -510,7 +555,7 @@ export default {
         question_id: id,
         question_id: id,
       });
       });
       if (res.code === 200) {
       if (res.code === 200) {
-        this.questionItem = res.data;
+        this.questionItem = {...res.data,recordStatus:1};
         const { audio_list } = res.data;
         const { audio_list } = res.data;
         let temp = {};
         let temp = {};
         if (audio_list.length > 0) {
         if (audio_list.length > 0) {
@@ -756,6 +801,7 @@ export default {
     //录音计时
     //录音计时
     clockTime() {
     clockTime() {
       console.log("开始录音计时");
       console.log("开始录音计时");
+      if(this.timer) return
       this.timer = setInterval(() => {
       this.timer = setInterval(() => {
         if (this.timer) {
         if (this.timer) {
           this.audioCount += 30;
           this.audioCount += 30;
@@ -767,7 +813,8 @@ export default {
     //清除录音计时
     //清除录音计时
     cleanTime() {
     cleanTime() {
       console.log("结束录音计时");
       console.log("结束录音计时");
-      clearTimeout(this.timer);
+      clearInterval(this.timer);
+      this.timer=null
       this.playIconKey++; //更新录音暂停播放图标
       this.playIconKey++; //更新录音暂停播放图标
       //this.audioTime = this.dayjs(this.audioCount).format("mm:ss.SS");
       //this.audioTime = this.dayjs(this.audioCount).format("mm:ss.SS");
     },
     },
@@ -812,6 +859,37 @@ export default {
           }
           }
       }
       }
     },
     },
+    // 终止问答
+    async handleConfirmStopQuestion(){
+      console.log('stop question');
+      if(!this.stopQuestion.reason){
+        uni.showToast({
+          title:"请填写终止理由",
+          icon:"none"
+        })
+        return
+      }
+      const res=await apiQuestionStop({
+        community_question_id:this.questionItem.community_question_id,
+        reason:this.stopQuestion.reason
+      })
+      if(res.code===200){
+        uni.showToast({
+          title:"成功终止",
+          icon:"success"
+        })
+        setTimeout(() => {
+          uni.navigateBack({
+            delta:1,
+            fail(){
+              uni.switchTab({
+                url: '/pages/question/question'
+              })
+            }
+          })
+        }, 1500);
+      }
+    }
   },
   },
 };
 };
 </script>
 </script>
@@ -842,10 +920,22 @@ export default {
         text-align: center;
         text-align: center;
         color: #999999ff;
         color: #999999ff;
         font-size: 28rpx;
         font-size: 28rpx;
-        height:130rpx;
+        // height:130rpx;
         image {
         image {
           width: 94rpx;
           width: 94rpx;
         }
         }
+
+        .black-btn{
+          width: 100%;
+          height: 80rpx;
+          line-height: 80rpx;
+          background: #333333;
+          box-shadow: 0px 4rpx 20rpx rgba(160, 126, 84, 0.25);
+          border-radius: 40rpx;
+          color: #E3B377;
+          text-align: center;
+          font-size: 32rpx;
+        }
       }
       }
     /*   .record-time {
     /*   .record-time {
         justify-self: flex-end;
         justify-self: flex-end;

+ 32 - 24
pages-question/answerList.vue

@@ -26,7 +26,6 @@
             <view style="flex: 1" class="question-title">
             <view style="flex: 1" class="question-title">
               <text
               <text
                 class="item-label"
                 class="item-label"
-                v-if="(item.reply_status === 3 || item.replier_user_id == userInfo.user_id) && questionStatus!=2"
                 >{{ item.variety_tag_name }}</text
                 >{{ item.variety_tag_name }}</text
               >
               >
               {{ item.question_content }}
               {{ item.question_content }}
@@ -68,6 +67,8 @@
             </view>
             </view>
           </view>
           </view>
           <text class="item-time">提问时间:{{ item.create_time }}</text>
           <text class="item-time">提问时间:{{ item.create_time }}</text>
+          <view class="item-time stop-reason" v-if="item.reply_status === 4">终止理由:{{item.stop_reason}}</view>
+            
         </view>
         </view>
       </view>
       </view>
     </template>
     </template>
@@ -189,27 +190,29 @@ export default {
     },
     },
     //点击bar
     //点击bar
     changeBar({ key }) {
     changeBar({ key }) {
-		if (key === this.selectKey) return;
-		this.selectKey = key;
-		this.questionList = [];
-		this.page = 1;
-		// 重新获取数量
-		apiBarTotal().then(res=>{
-		  if(res.code == 200){
-			  const { replied, wait, total,distribute } = res.data;
-			  for (const bar of this.barList) {
-				if(bar.label == '已回答'){
-				  bar.num = replied
-				}else if(bar.label == '未回答'){
-				  bar.num = wait
-				}else if(bar.label == '全部'){
-				  bar.num = total
-				}else if(bar.label == '待回答'){
-				  bar.num = distribute
-				}
-			  }
-		  }
-		});
+      if (key === this.selectKey) return;
+      this.selectKey = key;
+      this.questionList = [];
+      this.page = 1;
+      // 重新获取数量
+      apiBarTotal().then(res=>{
+        if(res.code == 200){
+          const { replied, wait, total,distribute,stop } = res.data;
+          for (const bar of this.barList) {
+            if(bar.label == '已回答'){
+              bar.num = replied
+            }else if(bar.label == '未回答'){
+              bar.num = wait
+            }else if(bar.label == '全部'){
+              bar.num = total
+            }else if(bar.label == '待回答'){
+              bar.num = distribute
+            }else if(bar.label=='已终止'){
+              bar.num=stop
+            }
+          }
+        }
+      });
       this.resetAudio();
       this.resetAudio();
       this.getQuestionData();
       this.getQuestionData();
     },
     },
@@ -223,7 +226,7 @@ export default {
     async getBarList() {
     async getBarList() {
       const res = await apiBarTotal();
       const res = await apiBarTotal();
       if (res.code !== 200) return;
       if (res.code !== 200) return;
-      const { replied, wait, total,distribute } = res.data;
+      const { replied, wait, total,distribute,stop } = res.data;
       //客户: 已回答 未回答 全部
       //客户: 已回答 未回答 全部
       const customBar = [
       const customBar = [
         {
         {
@@ -259,6 +262,11 @@ export default {
           key: "Replied",
           key: "Replied",
           num: replied,
           num: replied,
         },
         },
+        {
+          label: "已终止",
+          key: "Stop",
+          num: stop,
+        },
         {
         {
           label: "全部",
           label: "全部",
           key: "Total",
           key: "Total",
@@ -268,7 +276,7 @@ export default {
       this.barList = this.isUserResearcher ? researBar : customBar;
       this.barList = this.isUserResearcher ? researBar : customBar;
     },
     },
     async getQuestionData() {
     async getQuestionData() {
-      const reply_status = { Wait: 2, Replied: 3, Total: 0 ,Distribute:4};
+      const reply_status = { Wait: 2, Replied: 3, Total: 0 ,Distribute:4,Stop:5};
 	  this.questionStatus = reply_status[this.selectKey]
 	  this.questionStatus = reply_status[this.selectKey]
       await this.getQuestionList(reply_status[this.selectKey],1);
       await this.getQuestionList(reply_status[this.selectKey],1);
       this.setQuestionsRead()
       this.setQuestionsRead()

+ 178 - 0
pages-question/components/removeQuestionDig.vue

@@ -0,0 +1,178 @@
+<template>
+    <van-popup 
+        :show="show" 
+        position="bottom"  
+        :close-on-click-overlay="true"
+        closeable
+        @close="handleClose"
+        round
+    >
+        <view class="remove-question-wrap">
+            <view class="title">转移问题</view>
+            <view class="main-box">
+                <view class="left">
+                    <view 
+                        :class="['item',index==fIndex&&'active']" 
+                        v-for="(item,index) in opts" 
+                        :key="item.classify_id" 
+                        @click="fIndex=index,adminId=0,secIndex=0"
+                    >{{item.classify_name}}</view>
+                </view>
+                <view class="center">
+                    <view 
+                        :class="['item',index==secIndex&&'active']" 
+                        v-for="(item,index) in opts[fIndex].tags" 
+                        :key="item.tag_id" 
+                        @click="secIndex=index,adminId=0"
+                    >{{item.tag_name}}</view>
+                </view>
+                <view class="right">
+                    <view 
+                        :class="['item',item.admin_id==adminId&&'active',!item.allow_select&&'disabled']" 
+                        v-for="item in opts[fIndex].tags[secIndex].researcher_list" 
+                        :key="item.admin_id" 
+                        @click="handleSelectAdmin(item)"
+                    >{{item.admin_name}}</view>
+                </view>
+            </view>
+            <view class="btn" @click="handleConfirmTrans">确定</view>
+              
+        </view>
+    </van-popup>
+      
+</template>
+
+<script>
+import {apiGetTagTree} from '@/api/common'
+import {apiQuestionTransfer} from '@/api/question'
+export default {
+    props:{
+        qid:{
+            default:0
+        },
+        show:{
+            type:Boolean,
+            default:false
+        }
+    },
+    watch:{
+        qid(){
+            this.getOpts()
+        }
+    },
+    data() {
+        return {
+            opts:[],
+            fIndex:0,
+            secIndex:0,
+            adminId:0,//选择的人id
+        }
+    },
+    methods: {
+        async getOpts(){
+            const res=await apiGetTagTree({
+                community_question_id:this.qid||0
+            })
+            if(res.code===200){
+                this.opts=res.data||[]
+            }
+        },
+
+        // 选择转移人
+        handleSelectAdmin(item){
+            if(!item.allow_select) return
+            this.adminId=item.admin_id
+        },
+        
+        //确认转移
+        async handleConfirmTrans(){
+            if(!this.adminId){
+                uni.showToast({
+                    title:"请选择转移人",
+                    icon:'none'
+                })
+                return
+            }
+            const res=await apiQuestionTransfer({
+                community_question_id:Number(this.qid),
+                variety_classify_id:this.opts[this.fIndex].classify_id,
+                variety_tag_id:this.opts[this.fIndex].tags[this.secIndex].tag_id,
+                admin_id:this.adminId
+            })
+            if(res.code===200){
+                uni.showToast({
+                    title:"转移成功",
+                    icon:'none'
+                })
+                this.handleClose()
+                setTimeout(()=>{
+                    uni.navigateBack({
+                        delta:1,
+                        fail(){
+                            uni.switchTab({
+                                url: '/pages/question/question'
+                            })
+                        }
+                    })
+                },1500)
+            }
+        },
+
+
+        handleClose(){
+            this.$emit('close')
+        }
+    },
+
+}
+</script>
+
+<style  lang="scss">
+.remove-question-wrap{
+    .title{
+        padding: 30rpx 0 10rpx 0;
+        font-size: 32rpx;
+        text-align: center;
+    }
+    .main-box{
+        height: 30vh;
+        display: flex;
+        .left,.center,.right{
+            flex: 1;
+            height: 100%;
+            overflow-y: auto;
+            &::-webkit-scrollbar{
+                width: 0;
+                height: 0;
+                display: none;
+            }
+            .item{
+                padding: 20rpx 10rpx;
+                font-size: 32rpx;
+            }
+            .active{
+                color: #E3B377;
+            }
+            .disabled{
+                color: #999;
+            }
+        }
+        .center{
+            border-left: 1px solid #ededed;
+            border-right: 1px solid #ededed;
+        }
+    }
+    .btn{
+        margin-top: 20rpx;
+        width: 80%;
+        text-align: center;
+        background: #333333;
+        border-radius: 40px;
+        margin-left: auto;
+        margin-right: auto;
+        color: #E3B377;
+        line-height: 80rpx;
+        font-size: 32rpx;
+    }
+}
+</style>

+ 125 - 6
pages-question/hasQuestion.vue

@@ -1,5 +1,7 @@
 <template>
 <template>
   <view class="hasquestion-wrap">
   <view class="hasquestion-wrap">
+    <van-cell title="所属品种" :value="varietyVal||'请选择问题所属品种'" is-link @click="showFilter=true"/>
+    <view style="padding:34rpx">
     <view class="title">问题描述<van-icon @click="showHint" coloe="rgba(0, 0, 0, 0.2)" name="question" />
     <view class="title">问题描述<van-icon @click="showHint" coloe="rgba(0, 0, 0, 0.2)" name="question" />
       <view class="hint" v-if="hintShow">实际发布的问题会以提炼出的精简内容为准</view>
       <view class="hint" v-if="hintShow">实际发布的问题会以提炼出的精简内容为准</view>
     </view>
     </view>
@@ -14,20 +16,58 @@
     <view class="btn-wrap">
     <view class="btn-wrap">
       <view class="btn" :class="{'active':textlength>0}" @click="handleClick">完成</view> 
       <view class="btn" :class="{'active':textlength>0}" @click="handleClick">完成</view> 
     </view>
     </view>
+    </view>
+
+    <!-- 选择品种 -->
+    <van-popup 
+      :show="showFilter" 
+      position="bottom" 
+      closeable 
+      :close-on-click-overlay="true"
+      @close="showFilter = false"
+      round
+    >
+      <view class="fliter-wrap-list">
+        <view class="flex top">
+          <text style="color:#000">选择所属品种</text>
+        </view>
+        <van-tree-select
+          :items="options"
+          :main-active-index="mainActiveIndex"
+          :active-id="activeId"
+          @click-nav="onClickNav"
+          @click-item="onClickItem"
+          main-active-class="main-active-class"
+          content-active-class="content-active-class"
+        />
+      </view>
+    </van-popup>
   </view>
   </view>
 </template>
 </template>
 
 
 <script>
 <script>
 import {apiPubAsk} from '@/api/question.js'
 import {apiPubAsk} from '@/api/question.js'
+import {apiGetTagTree} from '@/api/common'
 export default {
 export default {
   data() {
   data() {
     return {
     return {
       text:'',
       text:'',
       textlength:0,
       textlength:0,
-      maxlength:50,
-      hintShow:false
+      maxlength:40,
+      hintShow:false,
+      
+
+      showFilter:false,
+      options:[],
+      mainActiveIndex:0,
+      activeId:0,//选择的品种id
+      variety_classify_id:0,
+      varietyVal:'',
     };
     };
   },
   },
+  onLoad(){
+    this.getOptionsList()
+  },
   methods: {
   methods: {
     async handleClick(){
     async handleClick(){
       if(!this.textlength){
       if(!this.textlength){
@@ -37,11 +77,26 @@ export default {
         })
         })
         return
         return
       }
       }
+      if(!this.activeId){
+        uni.showToast({
+          title: '请选择问题所属品种',
+          icon: 'none',
+        })
+        return
+      }
       const res = await apiPubAsk({
       const res = await apiPubAsk({
-        question_content:this.text
+        question_content:this.text,
+        variety_classify_id:this.variety_classify_id,
+        variety_tag_id:this.activeId
       })
       })
       if(res.code===200){
       if(res.code===200){
-        uni.navigateBack({delta:1})
+        uni.showToast({
+          title:"发布成功",
+          icon:'success'
+        })
+        setTimeout(() => {
+          uni.navigateBack({delta:1})
+        }, 1500);
       }
       }
       
       
     },
     },
@@ -62,7 +117,45 @@ export default {
      setTimeout(()=>{
      setTimeout(()=>{
        this.hintShow = false
        this.hintShow = false
      },1000)
      },1000)
-    }
+    },
+
+    //获取品种筛选
+    async getOptionsList(){
+      const res = await apiGetTagTree()
+			if(res.code===200){
+				const arr = res.data||[]
+        this.options=arr.map(item=>{
+          let obj={
+              text:'',
+              children:[]
+          }
+          obj.text=item.classify_name
+          obj.children=item.tags.map(_item=>{
+            return {
+              text:_item.tag_name,
+              id:_item.tag_id,
+              variety_classify_id:_item.classify_id
+            }
+          })
+          return obj
+        })
+
+			}
+    },
+    onClickNav({detail}){
+      console.log(detail);
+      this.mainActiveIndex=detail.index
+    },
+
+    onClickItem({detail}){
+      console.log(detail);
+      this.activeId=detail.id
+      this.varietyVal=this.options[this.mainActiveIndex].text+'/'+detail.text
+      this.variety_classify_id=detail.variety_classify_id
+      this.showFilter=false
+    },
+
+
   },
   },
 };
 };
 </script>
 </script>
@@ -73,11 +166,37 @@ export default {
       color:rgba(0, 0, 0, 0.2);
       color:rgba(0, 0, 0, 0.2);
     }
     }
   }
   }
+  .van-cell{
+    border-bottom: 1px solid #e5e5e5;
+  }
+  .fliter-wrap-list{
+        background-color: #fff;
+        padding-top: 28rpx;
+        padding-bottom: 100rpx;
+        .top{
+            font-size: 32rpx;
+            justify-content: center;
+            margin-bottom: 40rpx;
+            padding: 0 34rpx;
+            position: relative;
+        }
+        .van-sidebar{
+            flex-shrink: 0;
+        }
+        .van-tree-select__content{
+            overflow-x: hidden;
+        }
+        .main-active-class{
+            border-color: #E3B377;
+        }
+        .content-active-class{
+            color: #E3B377;
+        }
+  }
 }
 }
 </style>
 </style>
 <style scoped lang="scss">
 <style scoped lang="scss">
 .hasquestion-wrap{
 .hasquestion-wrap{
-  padding:40rpx 34rpx;
   .title{
   .title{
     margin-bottom: 20rpx;
     margin-bottom: 20rpx;
     font-size: 32rpx;
     font-size: 32rpx;