Explorar el Código

系统视频外呼

baiwenju %!s(int64=2) %!d(string=hace) años
padre
commit
0d681eeb21

+ 13 - 4
MidWare_WinStandard1.0-zmd/ACD/AcdCore.cpp

@@ -802,11 +802,20 @@ void CAcdCore::__onCmdAgentReqExten(CPduEntity * a_pCmd)
802 802
 
803 803
 void CAcdCore::__onCmdAgentReqAgent(CPduEntity * a_pCmd)
804 804
 {
805
-	uint32_t agentId;
806
-	uint32_t extenId;
807
-	bool ret = m_AgentOffice.getFreeAgent(agentId,extenId);
805
+	uint32_t agentId=0;
806
+	uint32_t extenId=0;
807
+	bool ret = false;
808
+	auto group = a_pCmd->GetDataString(4); // 请求的该组空闲坐席
809
+	if (group == "" || group.IsEmpty()) {
810
+		ret = m_AgentOffice.getFreeAgent(agentId, extenId);
811
+	}
812
+	else {
813
+		ret = m_AgentOffice.getFreeAgentByGroup(agentId, extenId,group);
814
+	}
815
+	
808 816
 	a_pCmd->SetDataBool(0, ret);
809
-	a_pCmd->SetDataUInt(2, extenId);
817
+	a_pCmd->SetDataUInt(2, extenId); // 请求到的空闲分机号
818
+	a_pCmd->SetDataUInt(3, agentId); // 请求到的空闲坐席号
810 819
 	std::cout << agentId << "-" << extenId << std::endl;
811 820
 	CNetworkAcd::GetInstance().send2Server(a_pCmd);
812 821
 }

+ 2 - 0
MidWare_WinStandard1.0-zmd/ACD/AcdCore.h

@@ -16,6 +16,7 @@
16 16
 #include "VideoOffice.h"
17 17
 #include "DepttelextOffice.h"
18 18
 
19
+
19 20
 class CAgent;
20 21
 class CExten;
21 22
 /*************************************************************************
@@ -94,6 +95,7 @@ private:
94 95
 
95 96
 	CVideoOffice m_VideoOffice;                     // ÊÓÆµÕ˺ŹÜÀíÀà
96 97
 	CDepttelextOffice m_DepttelextOffice;
98
+	
97 99
 	SoftAuther m_Auther;                 //ÊÚȨ
98 100
 };
99 101
 

+ 33 - 1
MidWare_WinStandard1.0-zmd/ACD/AgentOffice.cpp

@@ -132,7 +132,7 @@ void CAgentOffice::clearAgent( void )
132 132
 	}
133 133
 
134 134
 	m_AgentMap.RemoveAll();
135
-	 
135
+	m_GroupMap.clear(); // 2023-06-19
136 136
 }
137 137
 
138 138
 /*****************************************************************
@@ -157,6 +157,14 @@ BOOL CAgentOffice::insertAgent( UINT a_AgentID, UINT a_ExtID, LPCTSTR a_GroupID,
157 157
 	CAgent* pAgent = new CAgent(a_AgentID, a_ExtID, a_GroupID, a_AgentType, a_TimePostProcessing);
158 158
 	m_AgentMap.SetAt(pAgent->id(), pAgent);		// 座席添加到全体座席索引
159 159
 	
160
+	auto ret = m_GroupMap.equal_range(a_GroupID);
161
+	for (auto it = ret.first; it != ret.second; ++it) {
162
+		if (it->second->id() == a_AgentID) {
163
+			m_GroupMap.erase(it);
164
+		}
165
+	}
166
+	m_GroupMap.insert(std::make_pair(a_GroupID, pAgent));  // 2023-06-19 保存坐席组-坐席
167
+
160 168
 	CAcdCore::GetInstance().getQueueMgr().addAgent(pAgent);
161 169
 
162 170
 	pAgent->onAssoExtStatusUpdated(a_ExtStatus);// 设置座席当前状态
@@ -200,10 +208,18 @@ BOOL CAgentOffice::removeAgent( UINT a_AgentID, UINT a_HostAgent )
200 208
 
201 209
 	CSingleLock Lock(&m_Cs4AgentMap, TRUE);
202 210
 
211
+
203 212
 	if(m_AgentMap.Lookup(a_AgentID, pAgent))
204 213
 	{
205 214
 		CAcdCore::GetInstance().getQueueMgr().delAgent(pAgent);		
206 215
 
216
+		// 2023-06-19 视频电话相关
217
+		auto ret = m_GroupMap.equal_range(pAgent->group());
218
+		for (auto it = ret.first; it != ret.second; ++it) {
219
+			m_GroupMap.erase(it);
220
+			break;
221
+		}
222
+
207 223
 		m_AgentMap.RemoveKey(a_AgentID);		// 从全体座席索引中删除
208 224
 		pAgent->release(a_HostAgent);
209 225
 		delete pAgent;                                                
@@ -365,6 +381,22 @@ bool CAgentOffice::getFreeAgent(uint32_t & AgentId, uint32_t & ExtenId)
365 381
 	return false;
366 382
 }
367 383
 
384
+bool CAgentOffice::getFreeAgentByGroup(uint32_t & AgentId, uint32_t & ExtenId, const LPCTSTR & a_GroupID)
385
+{
386
+	auto ret = m_GroupMap.equal_range(a_GroupID);
387
+	for (auto it = ret.first; it != ret.second; ++it) {
388
+		auto pAgent = it->second;
389
+		if (pAgent&&pAgent->isFree() && pAgent->lock()) {
390
+			m_GroupMap.erase(it);
391
+			m_GroupMap.insert(std::make_pair(a_GroupID, pAgent));
392
+			AgentId = pAgent->id();
393
+			ExtenId = pAgent->assoExten();
394
+			return true;
395
+		}
396
+	}
397
+	return false;
398
+}
399
+
368 400
 /*****************************************************************
369 401
 **【函数名称】	getStateSpecAgentList
370 402
 **【函数功能】	获取指定状态的座席列表

+ 6 - 0
MidWare_WinStandard1.0-zmd/ACD/AgentOffice.h

@@ -11,6 +11,8 @@
11 11
 #include "IMsgObserver.h"
12 12
 #include<vector>
13 13
 #include <map>
14
+#include <unordered_map>
15
+
14 16
 class CAgent;
15 17
 class CStrategyAD;
16 18
 class CAgentProperty;
@@ -58,6 +60,8 @@ public:
58 60
 
59 61
 	// 分配空闲坐席
60 62
 	bool getFreeAgent(uint32_t &AgentId, uint32_t &ExtenId);
63
+	// 根据坐席组获取空闲坐席,视频通话使用 2023-06-19
64
+	bool getFreeAgentByGroup(uint32_t &AgentId, uint32_t &ExtenId, const LPCTSTR&a_GroupID);
61 65
 
62 66
 	// 获取指定状态的座席列表
63 67
 	void getStateSpecAgentList(AGENT_LIST_SPEC_STATE SpecState, CString& AgentList);
@@ -75,5 +79,7 @@ private:
75 79
 	CCriticalSection m_Cs4AgentMap;	
76 80
 	CMap<UINT, UINT, CAgent*, CAgent*> m_AgentMap;	// 座席索引表
77 81
 	//std::map<UINT, CAgentProperty> m_AgentPropertyMap; // 坐席号,业务属性
82
+
83
+	std::unordered_multimap<std::string, CAgent*> m_GroupMap; // 2023-06-19 坐席组-坐席
78 84
 };
79 85
 

+ 10 - 8
MidWare_WinStandard1.0-zmd/ACD/DepttelextOffice.cpp

@@ -20,15 +20,18 @@ CDepttelextOffice::~CDepttelextOffice()
20 20
 bool CDepttelextOffice::InitDepttelext()
21 21
 {
22 22
 	CString sql;
23
-	sql.Format("SELECT [Id],[Name],[Telephone],[Extension] ,[CreateTime] FROM  [dbo].[tel_depttelext]");
23
+	sql = "if not exists (select * from sysobjects where id = object_id('tel_depttelext') " \
24
+		"and OBJECTPROPERTY(id, 'IsUserTable') = 1) begin " \
25
+		"create table  tel_depttelext(Id int, Name varchar(50), Telephone varchar(50), Extension varchar(50), primary key (id))" \
26
+		"end";
27
+	IOtlConnection::getInstance()->ExecCommand(sql);
28
+	std::cout << sql.GetBuffer(0) << std::endl;
29
+	sql.Format("SELECT [Id],[Name],[Telephone],[Extension] FROM  [dbo].[tel_depttelext]");
24 30
 	IOtlConnection* pConn = IOtlConnection::getInstance();
25 31
 	IOtlRecordset* record = pConn->QueryRecords(sql);
26 32
 	ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{CDepttelextOffice}: 分机号码列表开始初始化"));
27
-	if (record == NULL)
28
-	{
29
-		return false;
30
-	}
31
-	while (!record->IsEOF())
33
+	std::cout << sql.GetBuffer(0) << std::endl;
34
+	while (record && !record->IsEOF())
32 35
 	{
33 36
 		record->MoveNextRow();
34 37
 		 
@@ -37,7 +40,7 @@ bool CDepttelextOffice::InitDepttelext()
37 40
 		pDeptTelext->Telephone = record->GetValueStr("Telephone");
38 41
 		pDeptTelext->Extension = record->GetValueStr("Extension");
39 42
 		pDeptTelext->State = 8;// 默认移除
40
-
43
+		pDeptTelext->print();
41 44
 		UINT extenId = _ttoi(pDeptTelext->Extension);
42 45
 		m_DeptTelextmap.insert(std::make_pair(extenId, pDeptTelext));
43 46
 
@@ -47,7 +50,6 @@ bool CDepttelextOffice::InitDepttelext()
47 50
 	ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{CDepttelextOffice}: 分机号码列表结束初始化"));
48 51
 	IOtlRecordset::DestroyInstance(record);		// 释放记录集
49 52
 	return true;
50
-	return false;
51 53
 }
52 54
 
53 55
 void CDepttelextOffice::UpdateDepttelext(UINT extno, int state)

+ 4 - 0
MidWare_WinStandard1.0-zmd/ACD/DepttelextOffice.h

@@ -1,6 +1,7 @@
1 1
 #pragma once
2 2
 #include <map>
3 3
 #include <string>
4
+#include <iostream>
4 5
 
5 6
 class CDepttelextOffice
6 7
 {
@@ -20,6 +21,9 @@ private:
20 21
 		CString Extension;
21 22
 		CString AgentID;
22 23
 		int State;
24
+		void print() {
25
+			std::cout << Name << "-" << Telephone << "-" << Extension << "-" << AgentID << "-" << State << std::endl;
26
+		}
23 27
 	}DeptTelext;
24 28
 
25 29
 	std::map<UINT, DeptTelext*> m_DeptTelextmap;  // 2022-09-01

+ 9 - 0
MidWare_WinStandard1.0-zmd/FsLink/FsProxy.cpp

@@ -672,6 +672,15 @@ void CFsProxy::unregBusyChan(CVirtualChan* pChan)
672 672
 	m_MapBusyChan.RemoveKey(pChan->chanId());
673 673
 }
674 674
 
675
+bool CFsProxy::ExtenVideoCall(LONG JobId, CVirtualChan * pChan, LPCTSTR CallerNum, LPCTSTR CalleeNum)
676
+{
677
+	CString EslCmd;
678
+	EslCmd.Format(_T("bgapi originate {origination_caller_id_number=%lu,absolute_codec_string=^^:VP8:h264:pcma:pcmu}user/%lu %s XML %s\r\n%s: %ld"),
679
+		pChan->no(), pChan->no(), CalleeNum, CConfig::extContext(), ESL_HEADER_JOB_UUID, JobId);
680
+
681
+	return m_Gateway.sendCmd(EslCmd);
682
+}
683
+
675 684
 /*****************************************************************
676 685
 **【函数名称】	ExtenCall
677 686
 **【函数功能】	分机呼叫

+ 2 - 0
MidWare_WinStandard1.0-zmd/FsLink/FsProxy.h

@@ -66,6 +66,8 @@ public:
66 66
 	void regBusyChan(CVirtualChan* pChan);
67 67
 	void unregBusyChan(CVirtualChan* pChan);
68 68
 
69
+	// 发起话机视频呼叫
70
+	bool ExtenVideoCall(LONG JobId, CVirtualChan* pChan, LPCTSTR CallerNum, LPCTSTR CalleeNum);
69 71
 	// 语音操作接口
70 72
 	bool ExtenCall(LONG JobId, CVirtualChan* pChan, LPCTSTR CallerNum, LPCTSTR CalleeNum);
71 73
 	bool PredictionCall(LONG JobId, CString CallerNum, CString CalleeNum);

+ 2 - 1
MidWare_WinStandard1.0-zmd/FsLink/OpMakeCall.cpp

@@ -69,7 +69,8 @@ bool COpMakeCall::start( LineOpParam* pParam )
69 69
 
70 70
 	m_pHostChan->opNumber() = pParam->szParam2;
71 71
 
72
-	return CFsProxy::GetInstance().ExtenCall(uniqueId(), m_pHostChan, CallerNum, m_DestNumber);
72
+	//return CFsProxy::GetInstance().ExtenCall(uniqueId(), m_pHostChan, CallerNum, m_DestNumber);
73
+	return CFsProxy::GetInstance().ExtenVideoCall(uniqueId(), m_pHostChan, CallerNum, m_DestNumber);
73 74
 }
74 75
 
75 76
 /*****************************************************************

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1234 - 0
MidWare_WinStandard1.0-zmd/sql/video.sql