Explorar o código

回收公海+外呼记录查看录音修复

lmx hai 4 días
pai
achega
be19753a33

+ 8 - 0
src/api/crm/customerAll.js

@@ -7,3 +7,11 @@ export function getCustomerAllList(query) {
     params: query
   })
 }
+
+export function recoverAll(data) {
+  return request({
+    url: '/crm/customerAll/recover',
+    method: 'post',
+    data: data
+  })
+}

+ 1 - 1
src/views/aiSipCall/aiSipCallManualOutbound.vue

@@ -1407,7 +1407,7 @@ export default {
                 if (res && (res.code === 200 || res.code === 0)) {
                     this.callResultRecorded = true;
                     console.log('[syncByUuid] 记录成功:', res);
-                    this.$message.success(status === 2 ? '外呼执行成功记录' : '外呼执行失败已记录');
+                    this.$message.success(status === 2 ? '外呼执行成功正在获取记录' : '外呼执行失败已记录');
                 } else {
                     console.error('[syncByUuid] 记录失败:', res);
                     this.$message.error((res && res.msg) || '外呼记录失败');

+ 26 - 9
src/views/crm/components/CustomerSelect.vue

@@ -316,13 +316,17 @@ export default {
   methods: {
     setRows(rows){
       this.shows = true;
-      this.rows = rows;
+      this.rows = rows || [];
+      this.ids = (rows || []).map(item => item.customerId);
+      this.names = (rows || []).map(item => item.customerName);
       this.getList();
     },
     setRowsDesignatedCompany(rows,companyId){
       this.designatedCompany = true;
       this.shows = true;
-      this.rows = rows;
+      this.rows = rows || [];
+      this.ids = (rows || []).map(item => item.customerId);
+      this.names = (rows || []).map(item => item.customerName);
       this.queryParams.companyId = companyId;
       this.companyChange(companyId);
       this.getList();
@@ -336,12 +340,10 @@ export default {
       }
       this.isSyncingSelection = true;
       const selectedIds = new Set((this.rows || []).map(item => item.customerId));
-      this.$refs.table.clearSelection();
       this.$nextTick(() => {
         this.customerList.forEach(row => {
-          if (selectedIds.has(row.customerId)) {
-            this.$refs.table.toggleRowSelection(row, true);
-          }
+          const shouldBeSelected = selectedIds.has(row.customerId);
+          this.$refs.table.toggleRowSelection(row, shouldBeSelected);
         });
         this.$nextTick(() => {
           this.isSyncingSelection = false;
@@ -461,9 +463,17 @@ export default {
       if (this.isSyncingSelection) {
         return;
       }
-      this.rows = selection;
-      this.ids = selection.map(item => item.customerId);
-      this.names = selection.map(item => item.customerName);
+      // 当前页所有行的ID集合
+      const currentPageIds = new Set(this.customerList.map(item => item.customerId));
+      // 保留非当前页的已选数据(这些行不在selection中是因为不在当前页,而非用户取消选中)
+      const otherPageRows = (this.rows || []).filter(item => !currentPageIds.has(item.customerId));
+      // 合并:其他页已选行 + 当前页selection(以selection为准反映用户实际操作)
+      const rowMap = new Map();
+      otherPageRows.forEach(row => rowMap.set(row.customerId, row));
+      selection.forEach(row => rowMap.set(row.customerId, row));
+      this.rows = Array.from(rowMap.values());
+      this.ids = this.rows.map(item => item.customerId);
+      this.names = this.rows.map(item => item.customerName);
       this.single = selection.length !== 1;
       this.multiple = !selection.length;
     },
@@ -496,7 +506,11 @@ export default {
       this.shows = false;
       this.$nextTick(() => {
         if (this.$refs.table) {
+          this.isSyncingSelection = true;
           this.$refs.table.clearSelection();
+          this.$nextTick(() => {
+            this.isSyncingSelection = false;
+          });
         }
       });
     },
@@ -509,6 +523,9 @@ export default {
         this.rows = resList;
         this.ids = resList.map(item => item.customerId);
         this.names = resList.map(item => item.customerName);
+        if (this.$refs.table) {
+          this.$refs.table.clearSelection();
+        }
         this.syncTableSelection();
         if (resList.length === 0) {
           this.$message.warning("当前筛选条件下没有可选择的客户");

+ 38 - 21
src/views/crm/customer/customerAll.vue

@@ -119,45 +119,49 @@
       </el-row>
 
       <el-table height="500" border v-loading="loading" :data="customerList">
-        <el-table-column label="客户编码" align="center" prop="customerCode" />
-        <el-table-column label="客户名称" align="center" prop="customerName" :show-overflow-tooltip="true">
+        <el-table-column label="客户编码" align="center" prop="customerCode" width="110" />
+        <el-table-column label="客户名称" align="center" prop="customerName" :show-overflow-tooltip="true" min-width="100">
           <template slot-scope="scope">
             <el-link @click="handleShow(scope.row)" :underline="false" type="primary">{{ scope.row.isDuplicate==1?getCustomerName(scope.row.customerName)+"[从]":getCustomerName(scope.row.customerName) }}</el-link>
           </template>
         </el-table-column>
-        <el-table-column label="手机" width="120px" align="center" prop="mobile">
-          <template slot-scope="scope">
-            {{scope.row.mobile}}
-          </template>
-        </el-table-column>
-        <el-table-column label="客户来源" align="center" prop="source">
+        <el-table-column label="手机" align="center" prop="mobile" width="120" />
+        <el-table-column label="客户来源" align="center" prop="source" width="90">
           <template slot-scope="scope">
               <el-tag prop="status" v-for="(item, index) in sourceOptions" v-if="scope.row.source==item.dictValue">{{item.dictLabel}}</el-tag>
           </template>
         </el-table-column>
-        <el-table-column label="跟进阶段" align="center" prop="visitStatus">
+        <el-table-column label="跟进阶段" align="center" prop="visitStatus" width="90">
           <template slot-scope="scope">
               <el-tag prop="visitStatus" v-for="(item, index) in visitStatusOptions" v-if="scope.row.visitStatus==item.dictValue">{{item.dictLabel}}</el-tag>
             </template>
         </el-table-column>
-        <el-table-column label="客户类型" align="center" prop="customerType">
+        <el-table-column label="客户类型" align="center" prop="customerType" width="90">
           <template slot-scope="scope">
               <el-tag prop="status" v-for="(item, index) in typeOptions" v-if="scope.row.customerType==item.dictValue">{{item.dictLabel}}</el-tag>
           </template>
         </el-table-column>
-        <el-table-column label="标签" align="center" prop="tags" />
-        <el-table-column label="备注" align="center" prop="remark" width="120" />
-        <el-table-column label="进线客户详情" align="center" :show-overflow-tooltip="true" prop="registerDesc" />
-        <el-table-column label="分配销售" align="center" prop="companyUserNickName" :show-overflow-tooltip="true" />
-        <el-table-column label="领取时间" align="center" prop="startTime" />
-        <el-table-column label="进线客户提交日期" align="center" prop="registerSubmitTime" width="130" />
-        <el-table-column label="创建时间" align="center" prop="createTime" width="100" />
-        <el-table-column label="最后一次跟进时间" align="center" prop="receiveTime" width="100" />
-        <el-table-column label="入公海时间" align="center" prop="poolTime" width="100" />
-        <el-table-column label="操作" align="center" width="180">
+        <el-table-column label="标签" align="center" prop="tags" width="90" :show-overflow-tooltip="true" />
+        <el-table-column label="备注" align="center" prop="remark" width="120" :show-overflow-tooltip="true" />
+        <el-table-column label="进线客户详情" align="center" :show-overflow-tooltip="true" prop="registerDesc" min-width="120" />
+        <el-table-column label="分配销售" align="center" prop="companyUserNickName" :show-overflow-tooltip="true" width="90" />
+        <el-table-column label="领取时间" align="center" prop="startTime" width="135" />
+        <el-table-column label="提交日期" align="center" prop="registerSubmitTime" width="110" />
+        <el-table-column label="创建时间" align="center" prop="createTime" width="135" />
+        <el-table-column label="最后跟进时间" align="center" prop="receiveTime" width="135" />
+        <el-table-column label="入公海时间" align="center" prop="poolTime" width="135" />
+        <el-table-column label="操作" align="center" fixed="right" width="220">
           <template slot-scope="scope">
             <el-button size="mini" type="text" icon="el-icon-phone-outline" @click="handleViewCallLog(scope.row)">外呼记录</el-button>
             <el-button size="mini" type="text" icon="el-icon-view" @click="handleViewPhone(scope.row)">查看手机号</el-button>
+            <el-button
+              v-if="scope.row.customerUserId"
+              size="mini"
+              type="text"
+              icon="el-icon-s-release"
+              @click="handleRecover(scope.row)"
+              v-hasPermi="['crm:customer:recover']"
+            >回收公海</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -182,7 +186,7 @@
 </template>
 
 <script>
-import { getCustomerAllList } from "@/api/crm/customerAll";
+import { getCustomerAllList,recoverAll } from "@/api/crm/customerAll";
 import { getMyCustomerPhone,getTradeDicts } from "@/api/crm/customer";
 import customerDetails from '../components/customerDetails.vue';
 import customerCallLogList from '../components/customerCallLogList.vue';
@@ -318,6 +322,19 @@ export default {
         return "";
       }
       return customerName;
+    },
+    handleRecover(row) {
+      this.$confirm('是否确认回收客户"' + row.customerName + '"?', "警告", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning"
+      }).then(function() {
+        var data = { customerUserId: row.customerUserId };
+        return recoverAll(data);
+      }).then(() => {
+        this.getList();
+        this.msgSuccess("操作成功");
+      }).catch(function() {});
     }
   }
 };

+ 9 - 2
src/views/taskStatistics/callLog/index.vue

@@ -45,7 +45,7 @@
             <el-col :xs="12" :sm="12" :lg="6" class="ivu-mb">
                 <el-card shadow="hover" class="stat-card">
                     <div slot="header" class="card-header">
-                        <span>今日发送</span>
+                        <span>今日外呼</span>
                     </div>
 
                     <div class="content" v-loading="loadingCount">
@@ -661,7 +661,14 @@ export default {
             };
         },
         handleRecordPath(url) {
-            return 'http://129.28.164.235:8899/recordings/files?filename=' + url;
+            if (!url) return '';
+            let fullUrl = '';
+            if (url.startsWith('http')) {
+                fullUrl = url;
+            } else {
+                fullUrl = 'http://129.28.164.235:8899/recordings/files?filename=' + url;
+            }
+            return process.env.VUE_APP_BASE_API + '/common/proxy/recording?url=' + encodeURIComponent(fullUrl);
         },
         parseCallTime(val) {
             if (val === null || val === undefined || val === '') return null;