Browse Source

sop任务语音功能新增下拉框选择

luolinsong 6 days ago
parent
commit
379a52005a
3 changed files with 194 additions and 17 deletions
  1. 14 0
      src/api/qw/sop.js
  2. 95 10
      src/views/qw/sop/sop.vue
  3. 85 7
      src/views/qw/sopUserLogsInfo/sendMsgSopOpenTool.vue

+ 14 - 0
src/api/qw/sop.js

@@ -162,7 +162,21 @@ export function getSopVoiceList(params) {
     params
   })
 }
+export function getVoiceList(params) {
+  return request({
+    url: '/qw/sop/getVoiceList' ,
+    method: 'get',
+    params
+  })
+}
 
+export function getVoiceListByQwUserIds(params) {
+  return request({
+    url: '/qw/sop/getVoiceListByQwUserIds',
+    method: 'get',
+    params
+  })
+}
 
 // 修改企微sop
 export function updateSopQwUser(data) {

+ 95 - 10
src/views/qw/sop/sop.vue

@@ -917,14 +917,49 @@
                         </video>
                       </el-form-item>
                     </div>
-                    <div v-if="item.contentType == 7 ">
-                      <el-input
-                        v-model="item.value"
-                        type="textarea" :rows="3" maxlength="66" show-word-limit
-                        placeholder="输入要转为语音的内容" style="width: 90%;margin-top: 10px;"
-                        @input="handleInputVideoText(item.value,item)"/>
+                    <div v-if="item.contentType == 7">
+                      <el-form-item label="输入方式" style="margin-bottom: 10px;">
+                        <el-radio-group v-model="item.voiceInputMode" size="small">
+                          <el-radio-button label="dropdown">选择语音</el-radio-button>
+                          <el-radio-button label="input">手动输入</el-radio-button>
+                        </el-radio-group>
+                      </el-form-item>
+
+                      <!-- 下拉框选择语音 -->
+                      <div v-if="item.voiceInputMode === 'dropdown' || !item.voiceInputMode">
+                        <el-select
+                          v-model="item.value"
+                          placeholder="请选择语音内容"
+                          filterable
+                          clearable
+                          size="small"      style="width: 100%;"
+                          v-loading="voiceLoading"
+                          @focus="loadVoiceOptions(item)"
+                        >
+                          <el-option
+                            v-for="voice in voiceList"
+                            :key="voice.id"
+                            :label="voice.voiceTxt || voice.name"
+                            :value="voice.voiceTxt"
+                          />
+                        </el-select>
+                      </div>
+
+                      <!-- 手动输入语音 -->
+                      <div v-if="item.voiceInputMode === 'input'">
+                        <el-input
+                          v-model="item.value"
+                          type="textarea"
+                          :rows="3"
+                          maxlength="66"
+                          show-word-limit
+                          placeholder="输入要转为语音的内容"
+                          style="width: 100%; margin-top: 5px;"
+                          @input="handleInputVideoText(item.value,item)"/>
+                      </div>
                     </div>
 
+
                     <div v-if="item.contentType == 10 ">
                       <el-card class="box-card">
                         <el-form-item label="链接标题:"  label-width="100px">
@@ -1021,7 +1056,7 @@ import {
   updateStatus,
   videoList,
   handleSkipSop,
-  getSop
+  getSop, getVoiceList
 } from '@/api/qw/sop'
 import {sendMsgSop} from "@/api/qw/sopUserLogsInfo";
 import {listSopTemp} from "@/api/qw/sopTemp";
@@ -1041,7 +1076,8 @@ export default {
   components: {CustomerGroupDetails, qwUserList, ImageUpload, sopLogsDetails, SendMsgSopOpenTool},
   data() {
     return {
-
+      voiceOptions: [], // 语音选项数据
+      voiceLoading: false, // 语音加载状态
       skipSopDialog: {
       open: false,
       title: "跳过SOP操作",
@@ -1132,6 +1168,7 @@ export default {
       // 是否显示弹出层
       open: false,
       companyUserList: [],
+      voiceList: [],
       // 状态字典
       statusOptions: [],
       //sop状态
@@ -1273,6 +1310,46 @@ export default {
     }
   },
   methods: {
+    loadVoiceOptions(item) {
+      if (!this.voiceList) {
+        this.voiceList = []; // 如果未定义,立即初始化
+      }
+      // 如果已加载过语音选项,则不再重复加载
+      if (this.voiceList.length > 0) {
+        return;
+      }
+
+      this.voiceLoading = true;
+
+      // 从当前对话框中获取 chatId
+      const chatId = this.sendMsgOpen.row.chatId;
+      console.info('参数chatId',chatId)
+      console.log('参数chatId',chatId)
+      if (!chatId) {
+        this.$message.warning('无法获取群聊ID,无法加载语音选项');
+        this.voiceLoading = false;
+        return;
+      }
+      const params ={
+        chatId: chatId
+      }
+      // 调用接口获取语音列表
+      getVoiceList(params).then(response => {
+        this.voiceList = response.rows || [];
+
+        // 如果语音列表为空,给出提示
+        if (this.voiceList.length === 0) {
+          this.$message.info('暂无可用的语音内容');
+        }
+      }).catch(error => {
+        console.error('加载语音选项失败:', error);
+        this.$message.error('加载语音选项失败');
+        this.voiceList = []; // 确保列表为空
+      }).finally(() => {
+        this.voiceLoading = false;
+      });
+    },
+
   handleSkipSop(row) {
       const ids = row.id || this.ids;
       // 获取原始数据详情
@@ -1422,9 +1499,13 @@ export default {
      * SOP任务营期一键群发
      */
     handleCampSendMsg(){
-
+      const qwUserIds = [...new Set(
+        this.selectionMap
+          .filter(e => e.filterMode == 1 && e.qwUserIds)
+          .flatMap(e => e.qwUserIds.split(","))
+      )];
       setTimeout(() => {
-        this.$refs.sendMsgSopOpenTool.oneClickGroupSending(this.ids,2,this.queryParams.corpId,0);
+        this.$refs.sendMsgSopOpenTool.oneClickGroupSending(this.ids,2,this.queryParams.corpId,0,qwUserIds);
       }, 500);
 
     },
@@ -1704,6 +1785,7 @@ export default {
       const newSetting = {
         contentType:'1',
         value: '',
+        voiceInputMode: 'dropdown'  // 默认为下拉框选择模式
       };
       // 将新设置项添加到 content.setting 数组中
       this.setting.push(newSetting);
@@ -1716,6 +1798,9 @@ export default {
       if (this.msgForm.courseId != null ) {
         const selectedCourse = this.courseList.find(course => parseInt(course.dictValue) === this.msgForm.courseId);
         for (let i = 0; i < this.setting.length; i++) {
+          if (this.setting[i].contentType == 7 && !this.setting[i].voiceInputMode) {
+            this.$set(this.setting[i], 'voiceInputMode', 'dropdown');
+          }
           //响应式直接给链接的标题/封面上值
           if (selectedCourse && this.setting[i].contentType == 3 && this.msgForm.courseId != null) {
             this.$set(this.setting[i], 'linkTitle', selectedCourse.dictLabel);

+ 85 - 7
src/views/qw/sopUserLogsInfo/sendMsgSopOpenTool.vue

@@ -157,12 +157,47 @@
                       </el-form-item>
                     </div>
                     <div v-if="item.contentType == 7 || item.contentType == 16">
-                      <el-input
-                        v-model="item.value"
-                        type="textarea" :rows="3" maxlength="66" show-word-limit
-                        placeholder="输入要转为语音的内容" style="width: 90%;margin-top: 10px;"
-                        @input="handleInputVideoText(item.value,item)"/>
+                      <el-form-item label="输入方式" style="margin-bottom: 10px;">
+                        <el-radio-group v-model="item.voiceInputMode" size="small">
+                          <el-radio-button label="dropdown">选择语音</el-radio-button>
+                          <el-radio-button label="input">手动输入</el-radio-button>
+                        </el-radio-group>
+                      </el-form-item>
+
+                      <!-- 下拉框选择语音 -->
+                      <div v-if="item.voiceInputMode === 'dropdown' || !item.voiceInputMode">
+                        <el-select
+                          v-model="item.value"
+                          placeholder="请选择语音内容"
+                          filterable
+                          clearable
+                          size="small"      style="width: 100%;"
+                          v-loading="voiceLoading"
+                          @focus="loadVoiceOptions()"
+                        >
+                          <el-option
+                            v-for="voice in voiceList"
+                            :key="voice.id"
+                            :label="voice.voiceTxt || voice.name"
+                            :value="voice.voiceTxt"
+                          />
+                        </el-select>
+                      </div>
+
+                      <!-- 手动输入语音 -->
+                      <div v-if="item.voiceInputMode === 'input'">
+                        <el-input
+                          v-model="item.value"
+                          type="textarea"
+                          :rows="3"
+                          maxlength="66"
+                          show-word-limit
+                          placeholder="输入要转为语音的内容"
+                          style="width: 100%; margin-top: 5px;"
+                          @input="handleInputVideoText(item.value,item)"/>
+                      </div>
                     </div>
+
                     <div v-if="item.contentType == 8">
                       <el-button type="primary"
                                  style="margin-bottom: 1%"
@@ -325,7 +360,7 @@
 <script>
 import { sendMsg,} from "../../../api/qw/sopUserLogsInfo";
 import ImageUpload from "@/views/qw/sop/ImageUpload.vue";
-import {courseList, videoList} from "@/api/qw/sop";
+import { courseList, getVoiceList, getVoiceListByQwUserIds, videoList } from '@/api/qw/sop'
 import userVideo from "@/views/qw/userVideo/userVideo";
 import {listReward} from "@/api/qw/luckyBag";
 
@@ -335,6 +370,8 @@ export default {
   components: {ImageUpload,userVideo},
   data() {
     return {
+      voiceList: [],
+      voiceOptions: [], // 语音选项数据
       queryParams1: {
         pageNum: 1,
         pageSize: 10,
@@ -426,6 +463,7 @@ export default {
         startTime: null,
         sendTime: null,
         draftStrategy:1,
+        qwUserIds: null,
       },
       // 表单校验
       rules: {},
@@ -454,6 +492,45 @@ export default {
     });
   },
   methods: {
+
+    loadVoiceOptions() {
+      const qwUserIds = this.msgForm.qwUserIds; // string数组
+      const corpId = this.msgForm.corpId;
+      const params ={
+        qwUserIds: JSON.stringify(qwUserIds), // 转为 "[xxx,xxx]" 格式
+        corpId
+      }
+      if (!this.voiceList) {
+        this.voiceList = []; // 如果未定义,立即初始化
+      }
+      // 如果已加载过语音选项,则不再重复加载
+      if (this.voiceList.length > 0) {
+        return;
+      }
+
+      this.voiceLoading = true;
+      if (!qwUserIds || (Array.isArray(qwUserIds) && qwUserIds.length === 0)) {
+        this.$message.warning('无个人qw_user_id,无法加载语音选项');
+        return; // 提前返回,不继续执行
+      }
+
+      // 调用接口获取语音列表
+      getVoiceListByQwUserIds(params).then(response => {
+        this.voiceList = response.rows || [];
+
+        // 如果语音列表为空,给出提示
+        if (this.voiceList.length === 0) {
+          this.$message.info('暂无可用的语音内容');
+        }
+      }).catch(error => {
+        console.error('加载语音选项失败:', error);
+        this.$message.error('加载语音选项失败');
+        this.voiceList = []; // 确保列表为空
+      }).finally(() => {
+        this.voiceLoading = false;
+      });
+    },
+
     getLuckyBagStatus(content) {
       const selectedLuckyBag = this.luckyBagList.find(item => item.id === content.luckyBagId);
       if (selectedLuckyBag) {
@@ -482,13 +559,14 @@ export default {
       this.videoNumOptions.open = false;
 
     },
-    oneClickGroupSending(val,type,corpId,isMine){
+    oneClickGroupSending(val,type,corpId,isMine,qwUserIds){
 
       this.sendMsgOpen.open= true;
       this.msgForm.sopIds = val;
       this.msgForm.type = type;
       this.msgForm.corpId = corpId;
       this.msgForm.isMine = isMine;
+      this.msgForm.qwUserIds = qwUserIds;
     },
     courseChange() {
       if (this.msgForm.courseId != null ) {