|
@@ -1,35 +1,15 @@
|
|
|
<template>
|
|
<template>
|
|
|
<div class="employee-query-tab">
|
|
<div class="employee-query-tab">
|
|
|
- <!-- 公司选择 -->
|
|
|
|
|
|
|
+ <!-- 查询表单 -->
|
|
|
<div class="query-form">
|
|
<div class="query-form">
|
|
|
<el-form :model="queryParams" inline>
|
|
<el-form :model="queryParams" inline>
|
|
|
- <el-form-item label="所属公司" required>
|
|
|
|
|
- <el-select
|
|
|
|
|
- v-model="selectedCompanyId"
|
|
|
|
|
- placeholder="请选择公司"
|
|
|
|
|
- clearable
|
|
|
|
|
- filterable
|
|
|
|
|
- @change="handleCompanyChange"
|
|
|
|
|
- :loading="companyLoading"
|
|
|
|
|
- >
|
|
|
|
|
- <el-option
|
|
|
|
|
- v-for="company in companyList"
|
|
|
|
|
- :key="company.companyId"
|
|
|
|
|
- :label="company.companyName"
|
|
|
|
|
- :value="company.companyId"
|
|
|
|
|
- />
|
|
|
|
|
- </el-select>
|
|
|
|
|
- </el-form-item>
|
|
|
|
|
<el-form-item label="员工">
|
|
<el-form-item label="员工">
|
|
|
<el-select
|
|
<el-select
|
|
|
v-model="queryParams.userId"
|
|
v-model="queryParams.userId"
|
|
|
filterable
|
|
filterable
|
|
|
- remote
|
|
|
|
|
- reserve-keyword
|
|
|
|
|
- placeholder="请输入员工名称"
|
|
|
|
|
- :remote-method="remoteSearchStaff"
|
|
|
|
|
- :loading="staffLoading"
|
|
|
|
|
clearable
|
|
clearable
|
|
|
|
|
+ placeholder="请选择员工"
|
|
|
|
|
+ :loading="staffLoading"
|
|
|
>
|
|
>
|
|
|
<el-option
|
|
<el-option
|
|
|
v-for="item in staffOptions"
|
|
v-for="item in staffOptions"
|
|
@@ -49,7 +29,7 @@
|
|
|
</el-form>
|
|
</el-form>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <!-- 员工列表(后端分页) -->
|
|
|
|
|
|
|
+ <!-- 员工列表(前端分页) -->
|
|
|
<el-table
|
|
<el-table
|
|
|
v-loading="tableLoading"
|
|
v-loading="tableLoading"
|
|
|
:data="staffList"
|
|
:data="staffList"
|
|
@@ -112,7 +92,7 @@
|
|
|
</div>
|
|
</div>
|
|
|
<div class="conversation-panel">
|
|
<div class="conversation-panel">
|
|
|
<ConversationPanelPure
|
|
<ConversationPanelPure
|
|
|
- :corpId="corp && corp.corpId"
|
|
|
|
|
|
|
+ :corpId="currentStaff && currentStaff.corpId"
|
|
|
:customerId="selectedCustomerId"
|
|
:customerId="selectedCustomerId"
|
|
|
:customerAvatar="selectedCustomerAvatar"
|
|
:customerAvatar="selectedCustomerAvatar"
|
|
|
:staffUserId="currentStaff && currentStaff.qwUserId"
|
|
:staffUserId="currentStaff && currentStaff.qwUserId"
|
|
@@ -125,25 +105,21 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
-import { getAllUserlist } from "@/api/company/companyUser";
|
|
|
|
|
-import { selectQwUserListByCondition } from "@/api/qw/qwUser";
|
|
|
|
|
|
|
+import { getAllCompanyUserListNoParams } from "@/api/company/companyUser";
|
|
|
import { listExternalContact } from "@/api/qw/externalContact";
|
|
import { listExternalContact } from "@/api/qw/externalContact";
|
|
|
-import { queryCompanyListByCompanyIds } from "@/api/company/company";
|
|
|
|
|
import ConversationPanelPure from "./ConversationPanelPure.vue";
|
|
import ConversationPanelPure from "./ConversationPanelPure.vue";
|
|
|
import Pagination from "@/components/Pagination";
|
|
import Pagination from "@/components/Pagination";
|
|
|
|
|
|
|
|
export default {
|
|
export default {
|
|
|
name: "EmployeeQueryTab",
|
|
name: "EmployeeQueryTab",
|
|
|
components: { ConversationPanelPure, Pagination },
|
|
components: { ConversationPanelPure, Pagination },
|
|
|
- props: {
|
|
|
|
|
- corp: { type: Object, default: null } // { corpId, companyIds, corpName }
|
|
|
|
|
- },
|
|
|
|
|
data() {
|
|
data() {
|
|
|
return {
|
|
return {
|
|
|
- // 公司相关
|
|
|
|
|
- companyList: [],
|
|
|
|
|
- selectedCompanyId: null,
|
|
|
|
|
- companyLoading: false,
|
|
|
|
|
|
|
+ // 所有员工数据(全量)
|
|
|
|
|
+ allStaffData: [],
|
|
|
|
|
+ // 员工下拉选项
|
|
|
|
|
+ staffOptions: [],
|
|
|
|
|
+ staffLoading: false,
|
|
|
|
|
|
|
|
// 员工查询参数(分页)
|
|
// 员工查询参数(分页)
|
|
|
queryParams: {
|
|
queryParams: {
|
|
@@ -155,8 +131,6 @@ export default {
|
|
|
staffList: [], // 当前页数据
|
|
staffList: [], // 当前页数据
|
|
|
total: 0, // 总记录数
|
|
total: 0, // 总记录数
|
|
|
tableLoading: false,
|
|
tableLoading: false,
|
|
|
- staffOptions: [], // 下拉框选项(远程搜索用)
|
|
|
|
|
- staffLoading: false,
|
|
|
|
|
|
|
|
|
|
// 抽屉相关
|
|
// 抽屉相关
|
|
|
drawerVisible: false,
|
|
drawerVisible: false,
|
|
@@ -171,129 +145,94 @@ export default {
|
|
|
selectedCustomerAvatar: ""
|
|
selectedCustomerAvatar: ""
|
|
|
};
|
|
};
|
|
|
},
|
|
},
|
|
|
- watch: {
|
|
|
|
|
- corp: {
|
|
|
|
|
- immediate: true,
|
|
|
|
|
- handler(newCorp) {
|
|
|
|
|
- if (newCorp && newCorp.companyIds) {
|
|
|
|
|
- this.loadCompanyList(newCorp.companyIds);
|
|
|
|
|
- } else {
|
|
|
|
|
- this.companyList = [];
|
|
|
|
|
- this.selectedCompanyId = null;
|
|
|
|
|
- this.clearStaffData();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
computed: {
|
|
computed: {
|
|
|
filteredCustomerList() {
|
|
filteredCustomerList() {
|
|
|
if (!this.customerKeyword) return this.customerList;
|
|
if (!this.customerKeyword) return this.customerList;
|
|
|
return this.customerList.filter(c => c.name && c.name.includes(this.customerKeyword));
|
|
return this.customerList.filter(c => c.name && c.name.includes(this.customerKeyword));
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
+ mounted() {
|
|
|
|
|
+ this.loadAllStaff();
|
|
|
|
|
+ },
|
|
|
methods: {
|
|
methods: {
|
|
|
- // 根据 companyIds 加载公司列表
|
|
|
|
|
- async loadCompanyList(companyIdsStr) {
|
|
|
|
|
- if (!companyIdsStr) return;
|
|
|
|
|
- const ids = companyIdsStr.split(',').map(Number).filter(id => !isNaN(id));
|
|
|
|
|
- if (ids.length === 0) return;
|
|
|
|
|
- this.companyLoading = true;
|
|
|
|
|
|
|
+ // 加载所有员工(无公司限制)
|
|
|
|
|
+ async loadAllStaff() {
|
|
|
|
|
+ this.staffLoading = true;
|
|
|
|
|
+ this.tableLoading = true;
|
|
|
try {
|
|
try {
|
|
|
- const res = await queryCompanyListByCompanyIds(ids);
|
|
|
|
|
|
|
+ const res = await getAllCompanyUserListNoParams();
|
|
|
|
|
+ // 兼容不同的返回格式
|
|
|
|
|
+ let data = [];
|
|
|
if (res.code === 200) {
|
|
if (res.code === 200) {
|
|
|
- this.companyList = res.companyList || [];
|
|
|
|
|
- if (this.companyList.length > 0) {
|
|
|
|
|
- this.selectedCompanyId = this.companyList[0].companyId;
|
|
|
|
|
- await this.onCompanyChanged();
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- this.companyList = [];
|
|
|
|
|
|
|
+ data = res.data || [];
|
|
|
|
|
+ } else if (Array.isArray(res)) {
|
|
|
|
|
+ data = res;
|
|
|
|
|
+ } else if (res.data && Array.isArray(res.data)) {
|
|
|
|
|
+ data = res.data;
|
|
|
}
|
|
}
|
|
|
- } catch (e) {
|
|
|
|
|
- console.error("加载公司列表失败", e);
|
|
|
|
|
- } finally {
|
|
|
|
|
- this.companyLoading = false;
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- // 切换公司时调用
|
|
|
|
|
- async handleCompanyChange(companyId) {
|
|
|
|
|
- if (!companyId) {
|
|
|
|
|
- this.clearStaffData();
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- this.queryParams = { userId: null, qwUserName: "", pageNum: 1, pageSize: 10 };
|
|
|
|
|
- await this.onCompanyChanged();
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- // 公司变更后的核心处理:重新加载员工下拉选项,并刷新列表第一页
|
|
|
|
|
- async onCompanyChanged() {
|
|
|
|
|
- if (!this.selectedCompanyId) return;
|
|
|
|
|
- await this.loadStaffOptions();
|
|
|
|
|
- await this.getStaffList();
|
|
|
|
|
- },
|
|
|
|
|
|
|
|
|
|
- // 加载全部员工(用于下拉选项)
|
|
|
|
|
- async loadStaffOptions() {
|
|
|
|
|
- if (!this.selectedCompanyId) return;
|
|
|
|
|
- this.staffLoading = true;
|
|
|
|
|
- try {
|
|
|
|
|
- const res = await getAllUserlist({ companyId: this.selectedCompanyId });
|
|
|
|
|
- const data = res.data || [];
|
|
|
|
|
- this.staffOptions = data.map(item => ({
|
|
|
|
|
|
|
+ this.allStaffData = data.map(item => ({
|
|
|
userId: item.userId,
|
|
userId: item.userId,
|
|
|
nickName: item.nickName,
|
|
nickName: item.nickName,
|
|
|
qwUserName: item.qwUserName,
|
|
qwUserName: item.qwUserName,
|
|
|
- qwUserId: item.qwUserId
|
|
|
|
|
|
|
+ qwUserId: item.id,
|
|
|
|
|
+ departmentName: item.departmentName,
|
|
|
|
|
+ corpId: item.corpId
|
|
|
}));
|
|
}));
|
|
|
|
|
+
|
|
|
|
|
+ // 初始化员工下拉选项
|
|
|
|
|
+ this.staffOptions = [...this.allStaffData];
|
|
|
|
|
+
|
|
|
|
|
+ // 加载第一页数据
|
|
|
|
|
+ this.queryParams.pageNum = 1;
|
|
|
|
|
+ this.getStaffList();
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
- console.error("加载员工下拉选项失败", e);
|
|
|
|
|
|
|
+ console.error("加载员工数据失败", e);
|
|
|
|
|
+ this.allStaffData = [];
|
|
|
this.staffOptions = [];
|
|
this.staffOptions = [];
|
|
|
|
|
+ this.staffList = [];
|
|
|
|
|
+ this.total = 0;
|
|
|
} finally {
|
|
} finally {
|
|
|
this.staffLoading = false;
|
|
this.staffLoading = false;
|
|
|
|
|
+ this.tableLoading = false;
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
- // 远程搜索员工(前端过滤)
|
|
|
|
|
- async remoteSearchStaff(query) {
|
|
|
|
|
- if (!this.selectedCompanyId) return;
|
|
|
|
|
- if (!query) {
|
|
|
|
|
- await this.loadStaffOptions();
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- const filtered = this.staffOptions.filter(item =>
|
|
|
|
|
- (item.nickName && item.nickName.includes(query)) ||
|
|
|
|
|
- (item.qwUserName && item.qwUserName.includes(query))
|
|
|
|
|
- );
|
|
|
|
|
- this.staffOptions = filtered;
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- // 获取员工列表(后端分页)
|
|
|
|
|
- async getStaffList() {
|
|
|
|
|
- if (!this.selectedCompanyId) {
|
|
|
|
|
|
|
+ // 获取员工列表(前端过滤 + 分页)
|
|
|
|
|
+ getStaffList() {
|
|
|
|
|
+ if (!this.allStaffData.length) {
|
|
|
this.staffList = [];
|
|
this.staffList = [];
|
|
|
this.total = 0;
|
|
this.total = 0;
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
this.tableLoading = true;
|
|
this.tableLoading = true;
|
|
|
try {
|
|
try {
|
|
|
- const params = {
|
|
|
|
|
- companyId: this.selectedCompanyId,
|
|
|
|
|
- userId: this.queryParams.userId,
|
|
|
|
|
- qwUserName: this.queryParams.qwUserName,
|
|
|
|
|
- pageNum: this.queryParams.pageNum,
|
|
|
|
|
- pageSize: this.queryParams.pageSize
|
|
|
|
|
- };
|
|
|
|
|
- const res = await selectQwUserListByCondition(params);
|
|
|
|
|
- if (res.code === 200 && res.data) {
|
|
|
|
|
- this.staffList = res.data.list || [];
|
|
|
|
|
- this.total = res.data.total || 0;
|
|
|
|
|
- } else {
|
|
|
|
|
- this.staffList = [];
|
|
|
|
|
- this.total = 0;
|
|
|
|
|
|
|
+ // 1. 过滤数据
|
|
|
|
|
+ let filtered = [...this.allStaffData];
|
|
|
|
|
+
|
|
|
|
|
+ // 按员工ID筛选
|
|
|
|
|
+ if (this.queryParams.userId) {
|
|
|
|
|
+ filtered = filtered.filter(item => item.userId === this.queryParams.userId);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // 按企微昵称模糊筛选
|
|
|
|
|
+ if (this.queryParams.qwUserName) {
|
|
|
|
|
+ const keyword = this.queryParams.qwUserName.trim();
|
|
|
|
|
+ filtered = filtered.filter(item =>
|
|
|
|
|
+ item.qwUserName && item.qwUserName.includes(keyword)
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 更新总数
|
|
|
|
|
+ this.total = filtered.length;
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 分页
|
|
|
|
|
+ const start = (this.queryParams.pageNum - 1) * this.queryParams.pageSize;
|
|
|
|
|
+ const end = start + this.queryParams.pageSize;
|
|
|
|
|
+ this.staffList = filtered.slice(start, end);
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
- console.error("获取员工列表失败", e);
|
|
|
|
|
|
|
+ console.error("筛选员工数据失败", e);
|
|
|
this.staffList = [];
|
|
this.staffList = [];
|
|
|
this.total = 0;
|
|
this.total = 0;
|
|
|
} finally {
|
|
} finally {
|
|
@@ -301,11 +240,13 @@ export default {
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
|
|
+ // 查询按钮
|
|
|
handleQuery() {
|
|
handleQuery() {
|
|
|
this.queryParams.pageNum = 1;
|
|
this.queryParams.pageNum = 1;
|
|
|
this.getStaffList();
|
|
this.getStaffList();
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
|
|
+ // 重置查询条件
|
|
|
resetQuery() {
|
|
resetQuery() {
|
|
|
this.queryParams = {
|
|
this.queryParams = {
|
|
|
userId: null,
|
|
userId: null,
|
|
@@ -314,16 +255,9 @@ export default {
|
|
|
pageSize: 10
|
|
pageSize: 10
|
|
|
};
|
|
};
|
|
|
this.getStaffList();
|
|
this.getStaffList();
|
|
|
- this.loadStaffOptions();
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- clearStaffData() {
|
|
|
|
|
- this.staffOptions = [];
|
|
|
|
|
- this.staffList = [];
|
|
|
|
|
- this.total = 0;
|
|
|
|
|
- this.queryParams = {userId: null, qwUserName: "", pageNum: 1, pageSize: 10};
|
|
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
|
|
+ // 打开抽屉,加载客户列表
|
|
|
openDrawer(row) {
|
|
openDrawer(row) {
|
|
|
this.currentStaff = row;
|
|
this.currentStaff = row;
|
|
|
this.drawerVisible = true;
|
|
this.drawerVisible = true;
|
|
@@ -333,6 +267,7 @@ export default {
|
|
|
this.loadCustomerList();
|
|
this.loadCustomerList();
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
|
|
+ // 加载客户列表(使用员工自身的corpId)
|
|
|
async loadCustomerList() {
|
|
async loadCustomerList() {
|
|
|
if (!this.currentStaff) return;
|
|
if (!this.currentStaff) return;
|
|
|
this.customerLoading = true;
|
|
this.customerLoading = true;
|
|
@@ -340,8 +275,8 @@ export default {
|
|
|
const params = {
|
|
const params = {
|
|
|
pageNum: this.customerPageNum,
|
|
pageNum: this.customerPageNum,
|
|
|
pageSize: this.customerPageSize,
|
|
pageSize: this.customerPageSize,
|
|
|
- qwUserId: this.currentStaff.id,
|
|
|
|
|
- corpId: this.corp && this.corp.corpId
|
|
|
|
|
|
|
+ qwUserId: this.currentStaff.qwUserId, // 员工的企微userId
|
|
|
|
|
+ corpId: this.currentStaff.corpId // 员工所属企业的corpId
|
|
|
};
|
|
};
|
|
|
const res = await listExternalContact(params);
|
|
const res = await listExternalContact(params);
|
|
|
if (res.rows) {
|
|
if (res.rows) {
|
|
@@ -353,16 +288,20 @@ export default {
|
|
|
}
|
|
}
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
console.error("获取客户列表失败", e);
|
|
console.error("获取客户列表失败", e);
|
|
|
|
|
+ this.customerList = [];
|
|
|
|
|
+ this.customerTotal = 0;
|
|
|
} finally {
|
|
} finally {
|
|
|
this.customerLoading = false;
|
|
this.customerLoading = false;
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
|
|
+ // 选中客户
|
|
|
handleCustomerClick(row) {
|
|
handleCustomerClick(row) {
|
|
|
this.selectedCustomerId = row.externalUserId;
|
|
this.selectedCustomerId = row.externalUserId;
|
|
|
this.selectedCustomerAvatar = row.avatar;
|
|
this.selectedCustomerAvatar = row.avatar;
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
|
|
+ // 会话登录失效处理
|
|
|
handleLogout() {
|
|
handleLogout() {
|
|
|
this.$message.warning("会话登录已失效,请刷新页面重试");
|
|
this.$message.warning("会话登录已失效,请刷新页面重试");
|
|
|
}
|
|
}
|
|
@@ -376,17 +315,20 @@ export default {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.query-form {
|
|
.query-form {
|
|
|
background: #fff;
|
|
background: #fff;
|
|
|
padding: 16px;
|
|
padding: 16px;
|
|
|
margin-bottom: 16px;
|
|
margin-bottom: 16px;
|
|
|
border-radius: 4px;
|
|
border-radius: 4px;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.drawer-container {
|
|
.drawer-container {
|
|
|
display: flex;
|
|
display: flex;
|
|
|
height: 100%;
|
|
height: 100%;
|
|
|
gap: 16px;
|
|
gap: 16px;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.customer-list {
|
|
.customer-list {
|
|
|
width: 360px;
|
|
width: 360px;
|
|
|
flex-shrink: 0;
|
|
flex-shrink: 0;
|
|
@@ -394,6 +336,7 @@ export default {
|
|
|
flex-direction: column;
|
|
flex-direction: column;
|
|
|
overflow: hidden;
|
|
overflow: hidden;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
.conversation-panel {
|
|
.conversation-panel {
|
|
|
flex: 1;
|
|
flex: 1;
|
|
|
background: #f5f6f7;
|
|
background: #f5f6f7;
|