Ver código fonte

叮当国医-会话审计-单聊与群聊查询优化

cgp 1 dia atrás
pai
commit
151491a340

+ 27 - 0
src/api/qw/companySession.js

@@ -47,3 +47,30 @@ export function qwSearchMsg(params) {
   });
 }
 
+// 员工下拉选项(模糊搜索)
+export function qwStaffOptions({ corpId, keyword }) {
+  return request({
+    url: '/weChatSpace/staffOptions',
+    method: 'get',
+    params: { corpId, keyword }
+  });
+}
+
+// 客户下拉选项(模糊搜索,可选 qwUserId 利用索引加速)
+export function qwCustomerOptions({ corpId, qwUserId, keyword }) {
+  return request({
+    url: '/weChatSpace/customerOptions',
+    method: 'get',
+    params: { corpId, qwUserId, keyword }
+  });
+}
+
+// 群聊下拉选项(模糊搜索)
+export function qwGroupChatOptions({ corpId, keyword }) {
+  return request({
+    url: '/weChatSpace/groupChatOptions',
+    method: 'get',
+    params: { corpId, keyword }
+  });
+}
+

+ 193 - 2
src/views/qw/conversationNew/ContentSearchTab.vue

@@ -7,11 +7,72 @@
           <el-input v-model="searchForm.queryWord" placeholder="请输入关键词(至少2个字符)" clearable />
         </el-form-item>
         <el-form-item label="聊天类型">
-          <el-select v-model="searchForm.chatType" placeholder="请选择" clearable>
+          <el-select v-model="searchForm.chatType" placeholder="请选择" clearable @change="onChatTypeChange">
+            <el-option label="全部" :value="null" />
             <el-option label="单聊" :value="1" />
             <el-option label="群聊" :value="2" />
           </el-select>
         </el-form-item>
+        <!-- 单聊条件:员工 + 客户 -->
+        <el-form-item v-if="searchForm.chatType === 1" label="员工">
+          <el-select
+            v-model="searchForm.staffUserId"
+            filterable
+            remote
+            clearable
+            reserve-keyword
+            placeholder="请输入员工名称搜索"
+            :remote-method="searchStaff"
+            :loading="staffSearchLoading"
+            @change="onStaffChange"
+          >
+            <el-option
+              v-for="item in staffOptions"
+              :key="item.qwUserId"
+              :label="item.qwUserName"
+              :value="item.qwUserId"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item v-if="searchForm.chatType === 1" label="客户">
+          <el-select
+            v-model="searchForm.customerId"
+            filterable
+            clearable
+            placeholder="请先选择员工,再搜索客户"
+            :loading="customerPreLoading"
+            :filter-method="filterCustomerLocal"
+            @visible-change="onCustomerDropdownVisible"
+          >
+            <el-option
+              v-for="item in filteredCustomerOptions"
+              :key="item.externalUserId"
+              :label="item.name"
+              :value="item.externalUserId"
+            />
+          </el-select>
+          <span v-if="customerNoMatch" style="color:#E6A23C;font-size:12px;">未匹配到客户</span>
+        </el-form-item>
+        <!-- 群聊条件:群聊 -->
+        <el-form-item v-if="searchForm.chatType === 2" label="群聊">
+          <el-select
+            v-model="searchForm.chatId"
+            filterable
+            remote
+            clearable
+            reserve-keyword
+            placeholder="请输入群聊名称搜索"
+            :remote-method="searchGroupChat"
+            :loading="groupChatSearchLoading"
+          >
+            <el-option
+              v-for="item in groupChatOptions"
+              :key="item.chatId"
+              :label="item.name"
+              :value="item.chatId"
+            />
+          </el-select>
+        </el-form-item>
         <el-form-item label="发送时间">
           <el-date-picker
             v-model="dateRange"
@@ -88,7 +149,7 @@
 </template>
 
 <script>
-import { qwSearchMsg } from "@/api/qw/companySession";
+import { qwSearchMsg, qwStaffOptions, qwCustomerOptions, qwGroupChatOptions } from "@/api/qw/companySession";
 import ConversationPanelPure from "./ConversationPanelPure.vue";
 
 const MSG_TYPE_MAP = {
@@ -134,9 +195,22 @@ export default {
       searchForm: {
         queryWord: "",
         chatType: null,
+        staffUserId: null,
+        customerId: null,
+        chatId: null,
         startTime: null,
         endTime: null,
       },
+      // 下拉选项
+      staffOptions: [],
+      customerOptions: [],           // 员工的所有客户(预加载后本地过滤)
+      filteredCustomerOptions: [],   // 本地过滤后的展示列表
+      customerNoMatch: false,        // 输入关键字后无匹配
+      groupChatOptions: [],
+      staffSearchLoading: false,
+      customerPreLoading: false,     // 预加载员工客户时的 loading
+      customerSearchLoading: false,
+      groupChatSearchLoading: false,
       dateRange: [],
       searching: false,
       tableLoading: false,
@@ -236,6 +310,9 @@ export default {
           corpId: this.corpId,
           queryWord: this.searchForm.queryWord,
           chatType: this.searchForm.chatType || undefined,
+          staffUserId: this.searchForm.staffUserId || undefined,
+          customerId: this.searchForm.customerId || undefined,
+          chatId: this.searchForm.chatId || undefined,
           startTime: this.searchForm.startTime,
           endTime: this.searchForm.endTime,
           limit: 50,
@@ -307,9 +384,17 @@ export default {
       this.searchForm = {
         queryWord: "",
         chatType: null,
+        staffUserId: null,
+        customerId: null,
+        chatId: null,
         startTime: null,
         endTime: null,
       };
+      this.staffOptions = [];
+      this.customerOptions = [];
+      this.filteredCustomerOptions = [];
+      this.customerNoMatch = false;
+      this.groupChatOptions = [];
       this.dateRange = [];
       this.messageList = [];
       this.cursor = null;
@@ -317,6 +402,112 @@ export default {
       this.searchedNoData = false;
     },
 
+    onChatTypeChange(val) {
+      this.searchForm.staffUserId = null;
+      this.searchForm.customerId = null;
+      this.searchForm.chatId = null;
+      this.staffOptions = [];
+      this.customerOptions = [];
+      this.filteredCustomerOptions = [];
+      this.customerNoMatch = false;
+      this.groupChatOptions = [];
+    },
+
+    async onStaffChange(staffUserId) {
+      // 切换员工时清空已选客户,预加载该员工全部客户
+      this.searchForm.customerId = null;
+      this.customerOptions = [];
+      this.filteredCustomerOptions = [];
+      this.customerNoMatch = false;
+
+      if (!staffUserId || !this.corpId) return;
+
+      this.customerPreLoading = true;
+      try {
+        const res = await qwCustomerOptions({ corpId: this.corpId, qwUserId: staffUserId });
+        if (res.code === 200) {
+          this.customerOptions = res.data || [];
+          this.filteredCustomerOptions = this.customerOptions;
+        }
+      } catch (e) {
+        console.error('预加载客户失败', e);
+      } finally {
+        this.customerPreLoading = false;
+      }
+    },
+
+    filterCustomerLocal(keyword) {
+      // 本地过滤,不调后端
+      if (!keyword) {
+        this.filteredCustomerOptions = this.customerOptions;
+        this.customerNoMatch = false;
+      } else {
+        const kw = keyword.toLowerCase();
+        this.filteredCustomerOptions = this.customerOptions.filter(
+          c => c.name && c.name.toLowerCase().includes(kw)
+        );
+        this.customerNoMatch = this.filteredCustomerOptions.length === 0;
+      }
+    },
+
+    onCustomerDropdownVisible(visible) {
+      // 下拉打开时重置为全量
+      if (visible) {
+        this.filteredCustomerOptions = this.customerOptions;
+        this.customerNoMatch = false;
+      }
+    },
+
+    async searchStaff(keyword) {
+      if (!this.corpId) return;
+      this.staffSearchLoading = true;
+      try {
+        const res = await qwStaffOptions({ corpId: this.corpId, keyword });
+        if (res.code === 200) {
+          this.staffOptions = res.data || [];
+        }
+      } catch (e) {
+        console.error('搜索员工失败', e);
+      } finally {
+        this.staffSearchLoading = false;
+      }
+    },
+
+    async searchCustomer(keyword) {
+      // 兼容旧调用:本地已预加载则本地过滤,否则调远端
+      if (this.customerOptions.length > 0) {
+        this.filterCustomerLocal(keyword);
+      } else if (this.corpId) {
+        this.customerSearchLoading = true;
+        try {
+          const res = await qwCustomerOptions({ corpId: this.corpId, keyword });
+          if (res.code === 200) {
+            this.customerOptions = res.data || [];
+            this.filteredCustomerOptions = this.customerOptions;
+          }
+        } catch (e) {
+          console.error('搜索客户失败', e);
+        } finally {
+          this.customerSearchLoading = false;
+        }
+      }
+    },
+
+    async searchGroupChat(keyword) {
+      if (!this.corpId) return;
+      this.groupChatSearchLoading = true;
+      try {
+        const res = await qwGroupChatOptions({ corpId: this.corpId, keyword });
+        if (res.code === 200) {
+          this.groupChatOptions = res.data || [];
+        }
+      } catch (e) {
+        console.error('搜索群聊失败', e);
+      } finally {
+        this.groupChatSearchLoading = false;
+      }
+    },
+
     handleScroll(e) {
       const container = e.target;
       if (container.scrollHeight - container.scrollTop - container.clientHeight < 10) {