mirror of
https://github.com/chatopera/cosin.git
synced 2025-06-16 18:30:03 +08:00
init new opensouce version code
This commit is contained in:
parent
26ddc81aa8
commit
4e764b6c0a
4
.gitignore
vendored
4
.gitignore
vendored
@ -15,3 +15,7 @@ sftp-config.json
|
||||
~$*.xls*
|
||||
~$*.ppt*
|
||||
~$*.doc*
|
||||
backups/
|
||||
.env
|
||||
build.gradle
|
||||
.vscode/
|
||||
|
242
INTRODUCTION.md
Normal file
242
INTRODUCTION.md
Normal file
@ -0,0 +1,242 @@
|
||||
[](https://microbadger.com/images/chatopera/contact-center:develop "Get your own image badge on microbadger.com") [](https://microbadger.com/images/chatopera/contact-center:develop "Get your own version badge on microbadger.com") [](https://hub.docker.com/r/chatopera/contact-center/) [](https://hub.docker.com/r/chatopera/contact-center/) [](https://microbadger.com/images/chatopera/contact-center:develop "Get your own commit badge on microbadger.com")
|
||||
|
||||
<p align="center">
|
||||
<b>春松客服QQ交流群:185659917, <a href="https://jq.qq.com/?_wv=1027&k=5I1cJLP" target="_blank">点击链接加入群聊</a></b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44917177-432d9700-ad6a-11e8-9420-46b0281073e6.png" width="200">
|
||||
</p>
|
||||
|
||||
# 春松客服: 全渠道智能客服
|
||||
|
||||
春松客服是帮助中小型企业快速而低成本的获得好用的智能客服系统。
|
||||
|
||||
春松客服是Chatopera自主研发以及基于且增强其它开源软件的方式实现的,春松客服会不断增强客服系统的智能化,这包括利用自然语言处理、机器学习和语音识别等技术让客服工作更有效率、客服满意度更高、成本更低。
|
||||
|
||||
**项目地址:** [https://github.com/samurais/cosinee](https://github.com/samurais/cosinee)
|
||||
|
||||
**开发环境搭建:** [https://github.com/samurais/cosinee/wiki/春松客服:开发环境](https://github.com/samurais/cosinee/wiki/%E6%98%A5%E6%9D%BE%E5%AE%A2%E6%9C%8D%EF%BC%9A%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83)
|
||||
|
||||
|
||||
## 内容结构
|
||||
|
||||
[产品演示](https://github.com/samurais/cosinee#%E4%BA%A7%E5%93%81%E6%BC%94%E7%A4%BA)
|
||||
|
||||
[功能](https://github.com/samurais/cosinee#%E5%8A%9F%E8%83%BD)
|
||||
|
||||
[开发文档](https://github.com/samurais/cosinee#%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3)
|
||||
|
||||
[产品截图](https://github.com/samurais/cosinee#%E4%BA%A7%E5%93%81%E6%88%AA%E5%9B%BE)
|
||||
|
||||
[产品体系](https://github.com/samurais/cosinee#%E4%BA%A7%E5%93%81%E4%BD%93%E7%B3%BB)
|
||||
|
||||
[立即部署](https://github.com/samurais/cosinee#%E7%AB%8B%E5%8D%B3%E9%83%A8%E7%BD%B2)
|
||||
|
||||
[鸣谢](https://github.com/samurais/cosinee#%E9%B8%A3%E8%B0%A2)
|
||||
|
||||
[开源许可协议](https://github.com/samurais/cosinee#%E5%BC%80%E6%BA%90%E8%AE%B8%E5%8F%AF%E5%8D%8F%E8%AE%AE)
|
||||
|
||||
## 产品演示
|
||||
* 坐席工作台
|
||||
|
||||
[http://cc.chatopera.com/](http://cc.chatopera.com/)
|
||||
|
||||
| **登录账号** | **密码** |
|
||||
| --- | --- |
|
||||
| admin | admin1234 |
|
||||
|
||||
* 网页端访客程序
|
||||
|
||||
[http://cc.chatopera.com/testclient.html](http://cc.chatopera.com/testclient.html)
|
||||
|
||||
## 功能
|
||||
|
||||
* 账号及组织机构管理:按组织、角色分配账号权限
|
||||
|
||||
* 联系人管理:细粒度维护客户信息
|
||||
|
||||
* 网页聊天组件:一分钟接入对话窗口
|
||||
|
||||
* 坐席工作台:汇聚多渠道访客请求
|
||||
|
||||
* 机器人客服:集成机器人平台服务,完成多轮对话和知识库问答
|
||||
|
||||
* 外呼系统:自动外呼,手动外呼,监听和报表等
|
||||
|
||||
<b> 《春松客服产品系列视频》 </b>
|
||||
<table align="center">
|
||||
<tr>
|
||||
<th>序号</th>
|
||||
<th>内容</th>
|
||||
<th>腾讯视频</th>
|
||||
<th>百度网盘</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 1</td>
|
||||
<td>产品概述</td>
|
||||
<td><a href="https://v.qq.com/x/page/z0776g0osqu.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1BzUveFSkCtfyeU1gUIjp1Q" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 2</td>
|
||||
<td>安装部署</td>
|
||||
<td><a href="https://v.qq.com/x/page/b07760u7f8t.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1CnZBIIuWpDWATjKTMluzUA" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 3</td>
|
||||
<td>功能演示</td>
|
||||
<td><a href="https://v.qq.com/x/page/h077670ceg2.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1bCAqUWwk_KQGyfUyvUMt9w" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 4</td>
|
||||
<td>账号体系</td>
|
||||
<td><a href="https://v.qq.com/x/page/b0776jwl6w1.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/18QA9jvXYtwa8Zt78Di9wrg" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 5</td>
|
||||
<td>客户关系管理</td>
|
||||
<td><a href="https://v.qq.com/x/page/d0776p8ghpr.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1stfkufWkF4byWqvF-ch9Dw" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 6</td>
|
||||
<td>即时通信</td>
|
||||
<td><a href="https://v.qq.com/x/page/r0776rdgt6z.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1eYEO5OtVu0gyxDI9a-xqJQ" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 7</td>
|
||||
<td>呼叫中心</td>
|
||||
<td><a href="https://v.qq.com/x/page/i07785u58jm.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1qQOSNMHgcNdXuq0Xib1wXA" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 8</td>
|
||||
<td>数据报表</td>
|
||||
<td><a href="https://v.qq.com/x/page/e0778ptg6b0.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1iQOz9HR3dkO4lgf5VI4CVw" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
[*下载视频合集*](https://pan.baidu.com/s/1YH7d7nMm5wZQp7P8kID3KA)
|
||||
|
||||
## 使用说明
|
||||
|
||||
关于产品的具体使用说明,请参考[文档中心](https://docs.chatopera.com/omni-channel-customer-support-system.html)。
|
||||
|
||||
## 来自真实用户的反馈
|
||||
|
||||
```
|
||||
项目代码写的挺好的,容易维护,是不错的开源项目。
|
||||
```
|
||||
|
||||
-- 海洋 (深圳银之杰项目经理)
|
||||
|
||||
|
||||
```
|
||||
Amazing! 要的就是这个效果。
|
||||
```
|
||||
|
||||
-- 常经理 (某电器世界五百强企业)
|
||||
|
||||
|
||||
```
|
||||
我要在APP内集成,我看了好多项目了,就你们这个最好,基本就是一个商用化的项目。
|
||||
```
|
||||
|
||||
-- Engine X (某二手车出售平台技术负责人)
|
||||
|
||||
|
||||
## 开发文档
|
||||
|
||||
<p align="center">
|
||||
<b><a href="https://github.com/samurais/cosinee/wiki" target="_blank">开发文档</a></b><br>
|
||||
<a href="https://github.com/samurais/cosinee/wiki" target="_blank">
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44992890-38be0800-afcb-11e8-8fde-a5a671d29764.png" width="300">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 产品截图
|
||||
|
||||
<p align="center">
|
||||
<b>欢迎页</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44915395-6bff5d80-ad65-11e8-817a-8abb812fb5ee.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>坐席工作台</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44915582-eb8d2c80-ad65-11e8-8876-86c8b5bb5cc7.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>坐席监控</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44915711-432b9800-ad66-11e8-899b-1ea02244925d.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>外呼计划</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44915831-ab7a7980-ad66-11e8-88a5-a2cd23b8c689.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>通话记录</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44915218-feebc800-ad64-11e8-90fc-36ce96b0c09a.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>集成客服机器人</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/51080565-4b82df00-1719-11e9-8cc4-dbbec0459224.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>客服机器人应答</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/51080567-50479300-1719-11e9-85d8-d209370c9d10.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>更多功能,敬请期待 ...</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44916014-28a5ee80-ad67-11e8-936a-a2cdbe62f529.png" width="900">
|
||||
</p>
|
||||
|
||||
## 产品体系
|
||||
|
||||
<p align="center">
|
||||
<b>观看视频介绍</b><br>
|
||||
<a href="https://pan.baidu.com/s/1tqxqfYSvtjDGhh6bDQ-Vog" target="_blank">
|
||||
<img src="https://user-images.githubusercontent.com/3538629/45403926-6a039b80-b68f-11e8-86e2-5d1f04e3a7c7.png" width="900">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 立即部署
|
||||
|
||||
* 企业版
|
||||
|
||||
通过青云AppCenter部署,青云AppCenter是开发运维一体化(DevOps)管理企业应用的平台,Chatopera的春松客服在2018年10月登录AppCenter,并借助PaaS平台强大的计算能力实现计算节点集群、存储节点HADR。从而保证了服务高可靠性、高性能、动态伸缩、一键备份和一键回滚等功能。
|
||||
|
||||
青云AppCenter以其提供的资源秒级计算特点,企业使用AppCenter中的春松客服应用,可以按需付费,灵活升配和降配,Chatopera也非常推荐客户使用青云服务。
|
||||
|
||||
<p align="center">
|
||||
<b>春松客服 on QingCloud</b><br>
|
||||
<a href="https://appcenter.qingcloud.com/apps/app-zdh88kz7/%E6%98%A5%E6%9D%BE%E5%AE%A2%E6%9C%8D" target="_blank">
|
||||
<img src="https://user-images.githubusercontent.com/3538629/47984143-a17f4900-e110-11e8-95c9-d8302e000c34.png" width="900">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
更为详细的部署文档见[春松客服上架青云AppCenter](https://github.com/samurais/cosinee/wiki/%E6%98%A5%E6%9D%BE%E5%AE%A2%E6%9C%8D%E4%B8%8A%E6%9E%B6%E9%9D%92%E4%BA%91AppCenter)。
|
||||
|
||||
* 社区版
|
||||
|
||||
参考部署[开源社区版本文档](https://github.com/samurais/cosinee/wiki/%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%83%A8%E7%BD%B2)。
|
||||
|
||||
## 鸣谢
|
||||
|
||||
[优客服](https://gitee.com/beimigame/ukefu)
|
||||
|
||||
[FreeSWITCH中国社区](http://www.freeswitch.org.cn/)
|
||||
|
||||
## 软件许可协议
|
||||
|
||||
Copyright (2018) <a href="https://www.chatopera.com/" target="_blank">北京华夏春松科技有限公司</a>
|
||||
|
||||
[LICENSE](https://github.com/samurais/cosinee/blob/master/LICENSE)
|
208
LICENSE
208
LICENSE
@ -1,201 +1,7 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright (2018) 北京华夏春松科技有限公司
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
Copyright 2019 Chatopera Inc. <https://www.chatopera.com>. All rights reserved.
|
||||
This software and related documentation are provided under a license agreement containing
|
||||
restrictions on use and disclosure and are protected by intellectual property laws.
|
||||
Except as expressly permitted in your license agreement or allowed by law, you may not use,
|
||||
copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform,
|
||||
publish, or display any part, in any form, or by any means. Reverse engineering, disassembly,
|
||||
or decompilation of this software, unless required by law for interoperability, is prohibited.
|
||||
|
254
README.md
254
README.md
@ -1,252 +1,8 @@
|
||||
[](https://microbadger.com/images/chatopera/contact-center:develop "Get your own image badge on microbadger.com") [](https://microbadger.com/images/chatopera/contact-center:develop "Get your own version badge on microbadger.com") [](https://hub.docker.com/r/chatopera/contact-center/) [](https://hub.docker.com/r/chatopera/contact-center/) [](https://microbadger.com/images/chatopera/contact-center:develop "Get your own commit badge on microbadger.com")
|
||||
# 春松客服企业版
|
||||
|
||||
<p align="center">
|
||||
<b>春松客服QQ交流群:185659917, <a href="https://jq.qq.com/?_wv=1027&k=5I1cJLP" target="_blank">点击链接加入群聊</a></b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44917177-432d9700-ad6a-11e8-9420-46b0281073e6.png" width="200">
|
||||
</p>
|
||||
https://gitlab.chatopera.com/chatopera
|
||||
|
||||
# 春松客服: 全渠道智能客服
|
||||
## License
|
||||
|
||||
春松客服是帮助中小型企业快速而低成本的获得好用的智能客服系统。
|
||||
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/3538629/61031891-fc311900-a3f2-11e9-80cf-c8d0700538a0.png" width="600">
|
||||
|
||||
|
||||
春松客服是Chatopera自主研发以及基于且增强其它开源软件的方式实现的,春松客服会不断增强客服系统的智能化,这包括利用自然语言处理、机器学习和语音识别等技术让客服工作更有效率、客服满意度更高、成本更低。
|
||||
|
||||
**开源项目地址:** [https://github.com/chatopera/cosin](https://github.com/chatopera/cosin)
|
||||
|
||||
**开发环境搭建:** [https://github.com/chatopera/cosin/wiki/春松客服:开发环境](https://github.com/chatopera/cosin/wiki/%E6%98%A5%E6%9D%BE%E5%AE%A2%E6%9C%8D%EF%BC%9A%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83)
|
||||
|
||||
|
||||
## 内容结构
|
||||
|
||||
[产品演示](https://github.com/chatopera/cosin#%E4%BA%A7%E5%93%81%E6%BC%94%E7%A4%BA)
|
||||
|
||||
[功能](https://github.com/chatopera/cosin#%E5%8A%9F%E8%83%BD)
|
||||
|
||||
[开发文档](https://github.com/chatopera/cosin#%E5%BC%80%E5%8F%91%E6%96%87%E6%A1%A3)
|
||||
|
||||
[产品截图](https://github.com/chatopera/cosin#%E4%BA%A7%E5%93%81%E6%88%AA%E5%9B%BE)
|
||||
|
||||
[产品体系](https://github.com/chatopera/cosin#%E4%BA%A7%E5%93%81%E4%BD%93%E7%B3%BB)
|
||||
|
||||
[立即部署](https://github.com/chatopera/cosin#%E7%AB%8B%E5%8D%B3%E9%83%A8%E7%BD%B2)
|
||||
|
||||
[鸣谢](https://github.com/chatopera/cosin#%E9%B8%A3%E8%B0%A2)
|
||||
|
||||
[开源许可协议](https://github.com/chatopera/cosin#%E5%BC%80%E6%BA%90%E8%AE%B8%E5%8F%AF%E5%8D%8F%E8%AE%AE)
|
||||
|
||||
## 产品演示
|
||||
* 坐席工作台
|
||||
|
||||
[http://cc.chatopera.com/](http://cc.chatopera.com/)
|
||||
|
||||
| **登录账号** | **密码** |
|
||||
| --- | --- |
|
||||
| admin | admin1234 |
|
||||
|
||||
* 网页端访客程序
|
||||
|
||||
[http://cc.chatopera.com/testclient.html](http://cc.chatopera.com/testclient.html)
|
||||
|
||||
|
||||
## 功能
|
||||
|
||||
* 账号及组织机构管理:按组织、角色分配账号权限
|
||||
|
||||
* 联系人管理:细粒度维护客户信息
|
||||
|
||||
* 网页聊天组件:一分钟接入对话窗口
|
||||
|
||||
* 坐席工作台:汇聚多渠道访客请求
|
||||
|
||||
* 机器人客服:集成机器人平台服务,完成多轮对话和知识库问答
|
||||
|
||||
* 外呼系统:自动外呼,手动外呼,监听和报表等
|
||||
|
||||
<b> 《春松客服产品系列视频》 </b>
|
||||
<table align="center">
|
||||
<tr>
|
||||
<th>序号</th>
|
||||
<th>内容</th>
|
||||
<th>腾讯视频</th>
|
||||
<th>百度网盘</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 1</td>
|
||||
<td>产品概述</td>
|
||||
<td><a href="https://v.qq.com/x/page/z0776g0osqu.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1BzUveFSkCtfyeU1gUIjp1Q" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 2</td>
|
||||
<td>安装部署</td>
|
||||
<td><a href="https://v.qq.com/x/page/b07760u7f8t.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1CnZBIIuWpDWATjKTMluzUA" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 3</td>
|
||||
<td>功能演示</td>
|
||||
<td><a href="https://v.qq.com/x/page/h077670ceg2.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1bCAqUWwk_KQGyfUyvUMt9w" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 4</td>
|
||||
<td>账号体系</td>
|
||||
<td><a href="https://v.qq.com/x/page/b0776jwl6w1.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/18QA9jvXYtwa8Zt78Di9wrg" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 5</td>
|
||||
<td>客户关系管理</td>
|
||||
<td><a href="https://v.qq.com/x/page/d0776p8ghpr.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1stfkufWkF4byWqvF-ch9Dw" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 6</td>
|
||||
<td>即时通信</td>
|
||||
<td><a href="https://v.qq.com/x/page/r0776rdgt6z.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1eYEO5OtVu0gyxDI9a-xqJQ" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 7</td>
|
||||
<td>呼叫中心</td>
|
||||
<td><a href="https://v.qq.com/x/page/i07785u58jm.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1qQOSNMHgcNdXuq0Xib1wXA" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>No. 8</td>
|
||||
<td>数据报表</td>
|
||||
<td><a href="https://v.qq.com/x/page/e0778ptg6b0.html" target="_blank">观看</a></td>
|
||||
<td><a href="https://pan.baidu.com/s/1iQOz9HR3dkO4lgf5VI4CVw" target="_blank">下载</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
[*下载视频合集*](https://pan.baidu.com/s/1YH7d7nMm5wZQp7P8kID3KA)
|
||||
|
||||
## 使用说明
|
||||
|
||||
关于产品的具体使用说明,请参考[文档中心](https://docs.chatopera.com/omni-channel-customer-support-system.html)。
|
||||
|
||||
## 来自真实用户的反馈
|
||||
|
||||
```
|
||||
项目代码写的挺好的,容易维护,是不错的开源项目。
|
||||
```
|
||||
|
||||
-- 海洋 (深圳银之杰项目经理)
|
||||
|
||||
|
||||
```
|
||||
Amazing! 要的就是这个效果。
|
||||
```
|
||||
|
||||
-- 常经理 (某电器世界五百强企业)
|
||||
|
||||
|
||||
```
|
||||
我要在APP内集成,我看了好多项目了,就你们这个最好,基本就是一个商用化的项目。
|
||||
```
|
||||
|
||||
-- Engine X (某二手车出售平台技术负责人)
|
||||
|
||||
|
||||
## 开发文档
|
||||
|
||||
<p align="center">
|
||||
<b><a href="https://github.com/chatopera/cosin/wiki" target="_blank">开发文档</a></b><br>
|
||||
<a href="https://github.com/chatopera/cosin/wiki" target="_blank">
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44992890-38be0800-afcb-11e8-8fde-a5a671d29764.png" width="300">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 产品截图
|
||||
|
||||
<p align="center">
|
||||
<b>欢迎页</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44915395-6bff5d80-ad65-11e8-817a-8abb812fb5ee.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>坐席工作台</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44915582-eb8d2c80-ad65-11e8-8876-86c8b5bb5cc7.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>坐席监控</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44915711-432b9800-ad66-11e8-899b-1ea02244925d.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>外呼计划</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44915831-ab7a7980-ad66-11e8-88a5-a2cd23b8c689.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>通话记录</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44915218-feebc800-ad64-11e8-90fc-36ce96b0c09a.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>集成客服机器人</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/51080565-4b82df00-1719-11e9-8cc4-dbbec0459224.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>客服机器人应答</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/51080567-50479300-1719-11e9-85d8-d209370c9d10.png" width="900">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<b>更多功能,敬请期待 ...</b><br>
|
||||
<img src="https://user-images.githubusercontent.com/3538629/44916014-28a5ee80-ad67-11e8-936a-a2cdbe62f529.png" width="900">
|
||||
</p>
|
||||
|
||||
## 产品体系
|
||||
|
||||
<p align="center">
|
||||
<b>观看视频介绍</b><br>
|
||||
<a href="https://pan.baidu.com/s/1tqxqfYSvtjDGhh6bDQ-Vog" target="_blank">
|
||||
<img src="https://user-images.githubusercontent.com/3538629/45403926-6a039b80-b68f-11e8-86e2-5d1f04e3a7c7.png" width="900">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 立即部署
|
||||
|
||||
* 企业版
|
||||
|
||||
通过青云AppCenter部署,青云AppCenter是开发运维一体化(DevOps)管理企业应用的平台,Chatopera的春松客服在2018年10月登录AppCenter,并借助PaaS平台强大的计算能力实现计算节点集群、存储节点HADR。从而保证了服务高可靠性、高性能、动态伸缩、一键备份和一键回滚等功能。
|
||||
|
||||
青云AppCenter以其提供的资源秒级计算特点,企业使用AppCenter中的春松客服应用,可以按需付费,灵活升配和降配,Chatopera也非常推荐客户使用青云服务。
|
||||
|
||||
<p align="center">
|
||||
<b>春松客服 on QingCloud</b><br>
|
||||
<a href="https://appcenter.qingcloud.com/apps/app-zdh88kz7/%E6%98%A5%E6%9D%BE%E5%AE%A2%E6%9C%8D" target="_blank">
|
||||
<img src="https://user-images.githubusercontent.com/3538629/47984143-a17f4900-e110-11e8-95c9-d8302e000c34.png" width="900">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
更为详细的部署文档见[春松客服上架青云AppCenter](https://github.com/chatopera/cosin/wiki/%E6%98%A5%E6%9D%BE%E5%AE%A2%E6%9C%8D%E4%B8%8A%E6%9E%B6%E9%9D%92%E4%BA%91AppCenter)。
|
||||
|
||||
* 社区版
|
||||
|
||||
参考部署[开源社区版本文档](https://github.com/chatopera/cosin/wiki/%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%83%A8%E7%BD%B2)。
|
||||
|
||||
## 鸣谢
|
||||
|
||||
[优客服](https://gitee.com/beimigame/ukefu)
|
||||
|
||||
[FreeSWITCH中国社区](http://www.freeswitch.org.cn/)
|
||||
|
||||
## 开源许可协议
|
||||
|
||||
Copyright (2018) <a href="https://www.chatopera.com/" target="_blank">北京华夏春松科技有限公司</a>
|
||||
|
||||
[Apache License Version 2.0](https://github.com/chatopera/cosin/blob/master/LICENSE)
|
||||
|
||||
[![chatoper banner][co-banner-image]][co-url]
|
||||
|
||||
[co-banner-image]: https://user-images.githubusercontent.com/3538629/42383104-da925942-8168-11e8-8195-868d5fcec170.png
|
||||
[co-url]: https://www.chatopera.com
|
||||
Copyright 2019 北京华夏春松科技有限公司 <https://www.chatopera.com>. All rights reserved.
|
||||
This software and related documentation are provided under a license agreement containing restrictions on use and disclosure and are protected by intellectual property laws. Except as expressly permitted in your license agreement or allowed by law, you may not use, copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform, publish, or display any part, in any form, or by any means. Reverse engineering, disassembly, or decompilation of this software, unless required by law for interoperability, is prohibited.
|
||||
|
14
cc-switch/.gitignore
vendored
14
cc-switch/.gitignore
vendored
@ -1,14 +0,0 @@
|
||||
*.swp
|
||||
*.swo
|
||||
*.sublime-*
|
||||
*.pyc
|
||||
__pycache__
|
||||
node_modules/
|
||||
sftp-config.json
|
||||
.DS_Store
|
||||
~$*
|
||||
.vscode
|
||||
.idea/
|
||||
.composer.phar
|
||||
app/config/dev.env
|
||||
ax.js
|
@ -1 +0,0 @@
|
||||
# cc-switch
|
@ -1,24 +0,0 @@
|
||||
#! /bin/bash
|
||||
###########################################
|
||||
#
|
||||
###########################################
|
||||
|
||||
# constants
|
||||
baseDir=$(cd `dirname "$0"`;pwd)
|
||||
export ACTIVEMQ_HOST=corsair
|
||||
export REDIS_HOST=corsair
|
||||
|
||||
# functions
|
||||
|
||||
# main
|
||||
[ -z "${BASH_SOURCE[0]}" -o "${BASH_SOURCE[0]}" = "$0" ] || return
|
||||
cd $baseDir/../app
|
||||
|
||||
# for x in {1..100}; do
|
||||
# echo $x
|
||||
# DEBUG=cc* ava --timeout=10hrs
|
||||
# sleep 5
|
||||
# done
|
||||
|
||||
DEBUG=cc* ava --timeout=10hrs $*
|
||||
|
@ -1,14 +0,0 @@
|
||||
FROM node:carbon-alpine
|
||||
|
||||
RUN apk add --no-cache tzdata && \
|
||||
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
|
||||
echo "Asia/Shanghai" > /etc/timezone
|
||||
|
||||
RUN mkdir -p /usr/src/app
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY package.json /usr/src/app/
|
||||
RUN npm install && npm cache clean --force
|
||||
COPY . /usr/src/app
|
||||
|
||||
CMD [ "npm", "start" ]
|
@ -1,7 +0,0 @@
|
||||
|
||||
PBX_CHANNEL_ID=bxzq
|
||||
FREESWITCH_HOST=freeswitch
|
||||
REDIS_HOST=redis
|
||||
MINIO_END_POINT=mini
|
||||
MINIO_ACCESS_KEY=key
|
||||
MINIO_SECRET_KEY=secret
|
@ -1,42 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const dotenv = require('dotenv');
|
||||
|
||||
const PBX_CHANNEL_ID = 'test';
|
||||
|
||||
const FREESWITCH_HOST = 'localhost';
|
||||
const FREESWITCH_PORT = 8021;
|
||||
const FREESWITCH_MAX_CHANNEL = 5;
|
||||
|
||||
const MINIO_END_POINT = 'localhost';
|
||||
const MINIO_ACCESS_KEY = 'key';
|
||||
const MINIO_SECRET_KEY = 'secret';
|
||||
|
||||
const REDIS_HOST = 'localhost';
|
||||
const REDIS_PORT = 6379;
|
||||
|
||||
const config = {
|
||||
PBX_CHANNEL_ID,
|
||||
FREESWITCH_HOST,
|
||||
FREESWITCH_PORT,
|
||||
FREESWITCH_MAX_CHANNEL,
|
||||
REDIS_HOST,
|
||||
REDIS_PORT,
|
||||
MINIO_END_POINT,
|
||||
MINIO_ACCESS_KEY,
|
||||
MINIO_SECRET_KEY,
|
||||
};
|
||||
|
||||
let envFile = path.join(__dirname, 'dev.env');
|
||||
if (fs.existsSync(envFile)) {
|
||||
dotenv.config({ path: envFile });
|
||||
}
|
||||
|
||||
for (let key in config) {
|
||||
let value = process.env[key];
|
||||
if (value) {
|
||||
config[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = exports = config;
|
@ -1,81 +0,0 @@
|
||||
const Redis = require('ioredis');
|
||||
const _ = require('lodash');
|
||||
const config = require('./config');
|
||||
const debug = require('debug')('cc-switch:control');
|
||||
|
||||
const FS_SIP_STATUS = `pbx:${config.PBX_CHANNEL_ID}:sips`;
|
||||
const FS_CHANNE_CC_TO_FS = `pbx:${config.PBX_CHANNEL_ID}:execute`;
|
||||
const FS_DIALPLAN_STATUS = `pbx:${config.PBX_CHANNEL_ID}:status`;
|
||||
const FS_DIALPLAN_TARGET = `pbx:${config.PBX_CHANNEL_ID}:targets`;
|
||||
const FS_EVENT_TO_CC = `pbx:${config.PBX_CHANNEL_ID}:events`;
|
||||
|
||||
const sub = new Redis({
|
||||
host: config.REDIS_HOST,
|
||||
port: config.REDIS_PORT,
|
||||
db: 2,
|
||||
});
|
||||
|
||||
const redis = new Redis({
|
||||
host: config.REDIS_HOST,
|
||||
port: config.REDIS_PORT,
|
||||
db: 2,
|
||||
});
|
||||
|
||||
module.exports = exports = {
|
||||
subExecute(fn) {
|
||||
return new Promise((resolve, reject) => {
|
||||
debug('订阅控制信道');
|
||||
sub.subscribe(FS_CHANNE_CC_TO_FS, (err, count) => {
|
||||
if (err) {
|
||||
debug('订阅失败: %o', err);
|
||||
reject(err);
|
||||
} else {
|
||||
debug('订阅成功: %s', count);
|
||||
sub.on('message', (channel, message) => {
|
||||
if (channel == FS_CHANNE_CC_TO_FS) {
|
||||
message = JSON.parse(message);
|
||||
fn(message);
|
||||
}
|
||||
});
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
getStatus() {
|
||||
return redis.hgetall(FS_DIALPLAN_STATUS).then(rows =>
|
||||
_.map(rows, (v, k) => {
|
||||
let obj = JSON.parse(v);
|
||||
obj.id = k;
|
||||
return obj;
|
||||
}),
|
||||
);
|
||||
},
|
||||
getNextCall(dialplanId) {
|
||||
return redis
|
||||
.rpop(`${FS_DIALPLAN_TARGET}:${dialplanId}`)
|
||||
.then(data => JSON.parse(data));
|
||||
},
|
||||
getSips() {
|
||||
return redis.hgetall(FS_SIP_STATUS).then(sips =>
|
||||
_.map(sips, (v, k) => ({
|
||||
no: k,
|
||||
state: v,
|
||||
})),
|
||||
);
|
||||
},
|
||||
removeSips(nos) {
|
||||
return redis.hdel(FS_SIP_STATUS, ...nos);
|
||||
},
|
||||
setSips(sips) {
|
||||
let args = [];
|
||||
_.forEach(sips, s => {
|
||||
args.push(s.no);
|
||||
args.push(s.state);
|
||||
});
|
||||
return redis.hmset(FS_SIP_STATUS, ...args);
|
||||
},
|
||||
sendEvent(data) {
|
||||
return redis.publish(FS_EVENT_TO_CC, JSON.stringify(data));
|
||||
},
|
||||
};
|
@ -1,109 +0,0 @@
|
||||
const _ = require('lodash');
|
||||
const moment = require('moment');
|
||||
const fs = require('./fs');
|
||||
const control = require('./control');
|
||||
const debug = require('debug')('cc-switch:dialplan');
|
||||
const { access } = require('fs');
|
||||
const minio = require('./minio');
|
||||
|
||||
class Dialplan {
|
||||
constructor(id, concurrency, sips) {
|
||||
this.id = id;
|
||||
this.concurrency = concurrency;
|
||||
this.tasks = [];
|
||||
this.sips = sips;
|
||||
this.state = 'create';
|
||||
}
|
||||
|
||||
start(cb) {
|
||||
debug('开始呼叫计划: %o', this.id);
|
||||
this.time = setInterval(() => this.loop(), 1000);
|
||||
this.start = 'start';
|
||||
this.cb = cb;
|
||||
}
|
||||
|
||||
callTask(to, channel) {
|
||||
debug('呼叫目标号码: %s', to);
|
||||
|
||||
let message = { to, channel, dialplan: this.id, type: 'callout' };
|
||||
let call = fs.call(to);
|
||||
call.sips = this.sips;
|
||||
let removeThisCall = () => _.remove(this.tasks, call);
|
||||
|
||||
call.on('channel_answer', uuid => {
|
||||
debug('用户接听 %s', to);
|
||||
message.uuid = uuid;
|
||||
message.from = call.sip;
|
||||
message.ops = 'answer';
|
||||
message.createtime = moment().valueOf();
|
||||
control.sendEvent(message);
|
||||
});
|
||||
|
||||
call.on('channel_hangup', () => {
|
||||
debug('用户挂机 %s', to);
|
||||
message.ops = 'hangup';
|
||||
message.createtime = moment().valueOf();
|
||||
removeThisCall();
|
||||
|
||||
if (call.state != 'call') {
|
||||
let file = `/usr/recordings/archive/${call.uuid}.wav`;
|
||||
message.record = `${moment().format('YYYY-MM-DD')}/${call.uuid}.wav`;
|
||||
|
||||
access(file, err => {
|
||||
if (err) {
|
||||
debug('录音文件不存在: %s', call.uuid);
|
||||
} else {
|
||||
debug('上传录音: %s', call.uuid);
|
||||
|
||||
setTimeout(() => {
|
||||
minio.fPutObject('chatopera', message.record, file).catch(err => {
|
||||
debug('上传录音失败 %s error: %o', call.uuid, err);
|
||||
});
|
||||
}, 5000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
control.sendEvent(message);
|
||||
});
|
||||
|
||||
call.on('error', () => {
|
||||
debug('呼叫错误 %s', to);
|
||||
message.ops = 'hangup';
|
||||
removeThisCall();
|
||||
control.sendEvent(message);
|
||||
});
|
||||
|
||||
return call;
|
||||
}
|
||||
|
||||
async loop() {
|
||||
// debug('呼叫计划循环: %s', this.id);
|
||||
while (this.tasks.length < this.concurrency) {
|
||||
let info = await control.getNextCall(this.id);
|
||||
|
||||
if (info) {
|
||||
let { to, channel } = info;
|
||||
let call = this.callTask(to, channel);
|
||||
this.tasks.push(call);
|
||||
} else {
|
||||
debug('完成呼叫计划: %s', this.id);
|
||||
this.start = 'finish';
|
||||
clearInterval(this.time);
|
||||
if (this.cb) {
|
||||
this.cb();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async stop() {
|
||||
debug('停止呼叫计划: %s', this.id);
|
||||
clearInterval(this.time);
|
||||
// await Promise.all(this.tasks);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = exports = Dialplan;
|
@ -1,60 +0,0 @@
|
||||
const _ = require('lodash');
|
||||
const debug = require('debug')('cc-switch:engine');
|
||||
|
||||
const config = require('./config');
|
||||
const control = require('./control');
|
||||
const Dialplan = require('./dialplan');
|
||||
const fs = require('./fs');
|
||||
|
||||
class Engine {
|
||||
constructor() {
|
||||
this.dialplans = [];
|
||||
}
|
||||
|
||||
createDialplan(id, concurrency, sips) {
|
||||
debug('创建呼叫计划: %s ,并发: %s', id, concurrency);
|
||||
if (!_.find(this.dialplans, { id })) {
|
||||
let dialplan = new Dialplan(id, concurrency, sips);
|
||||
this.dialplans.push(dialplan);
|
||||
dialplan.start(() => _.remove(this.dialplans, dialplan));
|
||||
}
|
||||
}
|
||||
|
||||
async init() {
|
||||
await fs.init();
|
||||
|
||||
await control.subExecute(message => {
|
||||
debug('接收控制命令: %o', message);
|
||||
let { ops, channel } = message;
|
||||
if (channel == config.PBX_CHANNEL_ID) {
|
||||
if (ops == 'start') {
|
||||
this.createDialplan(
|
||||
message.dialplan,
|
||||
message.concurrency,
|
||||
message.sips,
|
||||
);
|
||||
} else if (ops == 'monitor') {
|
||||
fs.eavesdrop(message.sip, message.uuid);
|
||||
} else {
|
||||
let dialplan = _.find(this.dialplans, { id: message.dialplan });
|
||||
if (dialplan) {
|
||||
dialplan.stop();
|
||||
_.remove(this.dialplans, dialplan);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
debug('获取初始状态');
|
||||
let dialplanTasks = await control.getStatus();
|
||||
|
||||
for (let task of dialplanTasks) {
|
||||
let { id, concurrency, status } = task;
|
||||
if (status == '执行中') {
|
||||
this.createDialplan(id, concurrency);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = exports = Engine;
|
@ -1,406 +0,0 @@
|
||||
const EventEmitter = require('events');
|
||||
const _ = require('lodash');
|
||||
const esl = require('modesl');
|
||||
const debug = require('debug')('cc-switch:fs');
|
||||
const config = require('./config');
|
||||
const control = require('./control');
|
||||
const { access } = require('fs');
|
||||
const minio = require('./minio');
|
||||
const moment = require('moment');
|
||||
|
||||
const { FREESWITCH_HOST, FREESWITCH_PORT, FREESWITCH_MAX_CHANNEL } = config;
|
||||
|
||||
const parseTable = body => {
|
||||
let list = [];
|
||||
let rows = body.split('\n');
|
||||
let first = rows.shift();
|
||||
if (first) {
|
||||
let head = first.split(',');
|
||||
for (let r of rows) {
|
||||
if (r) {
|
||||
let obj = {};
|
||||
let cell = r.split(',');
|
||||
for (let i = 0; i < head.length; i++) {
|
||||
obj[head[i]] = cell[i];
|
||||
}
|
||||
list.push(obj);
|
||||
} else break;
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
};
|
||||
|
||||
const parseHeaders = headers => {
|
||||
let obj = {};
|
||||
for (let h of headers) {
|
||||
obj[h.name] = h.value;
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
let conn;
|
||||
|
||||
const doConnect = reg =>
|
||||
new Promise((resolve, reject) => {
|
||||
conn = new esl.Connection(
|
||||
FREESWITCH_HOST,
|
||||
FREESWITCH_PORT,
|
||||
'ClueCon',
|
||||
() => {
|
||||
reg();
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
|
||||
conn.once('error', err => {
|
||||
debug('connect freeswitch error: %o', err);
|
||||
reject(err);
|
||||
|
||||
setTimeout(() => doConnect(reg), 2000);
|
||||
});
|
||||
});
|
||||
|
||||
const show = cmd =>
|
||||
new Promise((resolve, reject) => {
|
||||
// debug('执行命令: %s', cmd);
|
||||
|
||||
conn.bgapi(cmd, ({ body }) => {
|
||||
resolve(parseTable(body));
|
||||
});
|
||||
});
|
||||
|
||||
const showRegistrations = () => show('show registrations');
|
||||
|
||||
const showChannels = () => show('show channels');
|
||||
|
||||
const showCalls = () => show('show calls');
|
||||
|
||||
const record = uuid =>
|
||||
new Promise((resolve, reject) => {
|
||||
debug('开始录音: %s', uuid);
|
||||
|
||||
conn.bgapi(
|
||||
`uuid_record ${uuid} start /usr/recordings/archive/${uuid}.wav`,
|
||||
({ body }) => {
|
||||
console.log(body);
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
const callOut = phone =>
|
||||
new Promise((resolve, reject) => {
|
||||
debug('拨打电话: %s', phone);
|
||||
|
||||
conn.bgapi(`originate sofia/gateway/goipx/${phone} &park`, ({ body }) => {
|
||||
let match = body.match(/([a-f\d]{8}(-[a-f\d]{4}){3}-[a-f\d]{12}?)/i);
|
||||
if (match) {
|
||||
resolve(match[1]);
|
||||
} else {
|
||||
reject(new Error(`呼叫 ${phone} 失败`));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const callSip = (phone, originate) =>
|
||||
new Promise((resolve, reject) => {
|
||||
debug('拨打SIP: %s', phone);
|
||||
|
||||
('originate user/1000 &park');
|
||||
|
||||
conn.bgapi(
|
||||
`originate {origination_caller_id_number=${originate}}user/${phone} &park`,
|
||||
({ body }) => {
|
||||
let match = body.match(/([a-f\d]{8}(-[a-f\d]{4}){3}-[a-f\d]{12}?)/i);
|
||||
if (match) {
|
||||
resolve(match[1]);
|
||||
} else {
|
||||
reject(new Error(`呼叫SIP ${phone} 失败`));
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
const bridge = (luuid, ruuid) =>
|
||||
new Promise((resolve, reject) => {
|
||||
debug('桥接: %s <--> %s', luuid, ruuid);
|
||||
|
||||
conn.bgapi(`uuid_bridge ${luuid} ${ruuid}`, ({ body }) => {
|
||||
if (/OK/.test(body)) {
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error('桥接失败'));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const eavesdrop = (sip, uuid) =>
|
||||
new Promise((resolve, reject) => {
|
||||
debug('监听: %s <--> %s', sip, uuid);
|
||||
|
||||
conn.bgapi(`originate user/${sip} &eavesdrop(${uuid})`, ({ body }) => {
|
||||
if (/OK/.test(body)) {
|
||||
resolve();
|
||||
} else {
|
||||
reject(new Error('监听失败'));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
class FreeSwitch extends EventEmitter {
|
||||
constructor() {
|
||||
super();
|
||||
this.tasks = [];
|
||||
this.wait = [];
|
||||
this.sips = [];
|
||||
}
|
||||
|
||||
async init() {
|
||||
debug('初始化Freeswich');
|
||||
await doConnect(() => this.regEvent());
|
||||
|
||||
setInterval(async () => {
|
||||
let sips = await showRegistrations();
|
||||
let toDel = _.chain(await control.getSips())
|
||||
.map(s => s.no)
|
||||
.filter(k => !_.find(sips, { reg_user: k }))
|
||||
.value();
|
||||
if (toDel.length > 0) {
|
||||
await control.removeSips(toDel);
|
||||
}
|
||||
|
||||
let channels = await showChannels();
|
||||
let updateSips = _.map(sips, ({ reg_user }) => {
|
||||
return {
|
||||
no: reg_user,
|
||||
state: _.find(channels, { dest: reg_user }) ? '通话' : '空闲',
|
||||
};
|
||||
});
|
||||
if (updateSips.length > 0) {
|
||||
await control.setSips(updateSips);
|
||||
}
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
regEvent() {
|
||||
conn.events('plain CUSTOM sofia::register');
|
||||
|
||||
conn.on('esl::event::CUSTOM::*', ({ subclass, headers }) => {
|
||||
if (subclass == 'sofia::register') {
|
||||
let { username } = parseHeaders(headers);
|
||||
|
||||
debug('SIP %s 已上线', username);
|
||||
control.setSips([{ no: username, state: '空闲' }]);
|
||||
}
|
||||
});
|
||||
|
||||
conn.on('esl::event::CHANNEL_ANSWER::*', async ({ headers }) => {
|
||||
let variable = parseHeaders(headers);
|
||||
let { variable_uuid } = variable;
|
||||
debug('接通电话: %s', variable_uuid);
|
||||
|
||||
let call = _.find(this.tasks, { uuid: variable_uuid });
|
||||
if (call) {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
if (call.state == 'hangup') {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await call.linkSip();
|
||||
call.emit('channel_answer', variable_uuid);
|
||||
return;
|
||||
} catch (e) {
|
||||
debug('link sip error: %o', e);
|
||||
}
|
||||
}
|
||||
|
||||
// debug('link sip error: %o', err);
|
||||
} else if (variable.variable_sip_gateway_name == 'goipx') {
|
||||
let {
|
||||
variable_bridge_channel,
|
||||
variable_sip_to_user: sip_to_user,
|
||||
variable_call_uuid,
|
||||
} = variable;
|
||||
let match = variable_bridge_channel.match(/sofia\/internal\/(\d+)@/);
|
||||
if (match) {
|
||||
let sip_from_user = match[1];
|
||||
let call = new CallOut(
|
||||
variable_uuid,
|
||||
sip_to_user,
|
||||
variable_call_uuid,
|
||||
sip_from_user,
|
||||
);
|
||||
this.tasks.push(call);
|
||||
call.emit('channel_answer', variable_uuid);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
conn.on('esl::event::CHANNEL_HANGUP::*', ({ headers }) => {
|
||||
let event = parseHeaders(headers);
|
||||
|
||||
let { variable_uuid } = event;
|
||||
debug('挂断电话: %s', variable_uuid);
|
||||
|
||||
let call = _.find(this.tasks, { uuid: variable_uuid });
|
||||
if (call) {
|
||||
this.removeCall(call);
|
||||
call.state = 'hangup';
|
||||
call.emit('channel_hangup', variable_uuid);
|
||||
} else if (event.variable_sip_gateway_name == 'goipx') {
|
||||
let {
|
||||
variable_bridge_channel,
|
||||
variable_sip_to_user: sip_to_user,
|
||||
variable_call_uuid,
|
||||
} = event;
|
||||
let match =
|
||||
variable_bridge_channel &&
|
||||
variable_bridge_channel.match(/sofia\/internal\/(\d+)@/);
|
||||
if (match) {
|
||||
let sip_from_user = match[1];
|
||||
let call = new CallOut(
|
||||
variable_uuid,
|
||||
sip_to_user,
|
||||
null,
|
||||
sip_from_user,
|
||||
);
|
||||
|
||||
call.emit('channel_hangup', variable_uuid);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
_.filter(this.tasks, { state: 'call' }).length <=
|
||||
FREESWITCH_MAX_CHANNEL &&
|
||||
this.wait.length > 0
|
||||
) {
|
||||
debug('执行队列');
|
||||
let func = this.wait.shift();
|
||||
func();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
removeCall(call) {
|
||||
_.remove(this.tasks, call);
|
||||
}
|
||||
|
||||
call(phone) {
|
||||
let call = new Call(phone);
|
||||
this.tasks.push(call);
|
||||
|
||||
let doCall = async () => {
|
||||
try {
|
||||
await call.start();
|
||||
} catch (err) {
|
||||
this.removeCall(call);
|
||||
call.emit('error', err);
|
||||
}
|
||||
};
|
||||
|
||||
if (this.tasks.length <= FREESWITCH_MAX_CHANNEL) {
|
||||
doCall();
|
||||
} else {
|
||||
this.wait.push(doCall);
|
||||
}
|
||||
|
||||
return call;
|
||||
}
|
||||
|
||||
eavesdrop(sip, uuid) {
|
||||
return eavesdrop(sip, uuid);
|
||||
}
|
||||
}
|
||||
|
||||
class Call extends EventEmitter {
|
||||
constructor(phone) {
|
||||
super();
|
||||
|
||||
this.sips = [];
|
||||
this.phone = phone;
|
||||
this.try = 0;
|
||||
}
|
||||
|
||||
async start() {
|
||||
this.uuid = await callOut(this.phone);
|
||||
this.state = 'call';
|
||||
}
|
||||
|
||||
async linkSip() {
|
||||
debug('链接SIP电话');
|
||||
|
||||
let sips = _.chain(await control.getSips())
|
||||
.filter({ state: '空闲' })
|
||||
.map(s => s.no)
|
||||
.value();
|
||||
|
||||
this.sip = _.sample(_.intersection(sips, this.sips));
|
||||
if (!this.sip) {
|
||||
throw new Error('无可用SIP');
|
||||
}
|
||||
|
||||
await control.setSips([{ no: this.sip, state: '通话' }]);
|
||||
|
||||
this.sip_uuid = await callSip(this.sip, this.phone);
|
||||
await bridge(this.uuid, this.sip_uuid);
|
||||
await record(this.uuid);
|
||||
this.state = 'answer';
|
||||
}
|
||||
}
|
||||
|
||||
class CallOut extends EventEmitter {
|
||||
constructor(uuid, phone, sip_uuid, sip) {
|
||||
super();
|
||||
|
||||
this.uuid = uuid;
|
||||
this.phone = phone;
|
||||
this.sip_uuid = sip_uuid;
|
||||
this.sip = sip;
|
||||
|
||||
let message = {
|
||||
uuid,
|
||||
from: sip,
|
||||
to: phone,
|
||||
channel: config.PBX_CHANNEL_ID,
|
||||
type: 'callout',
|
||||
};
|
||||
|
||||
this.on('channel_answer', () => {
|
||||
debug('用户接听 %s -> %s', sip, phone);
|
||||
message.ops = 'answer';
|
||||
message.createtime = moment().valueOf();
|
||||
control.sendEvent(message);
|
||||
});
|
||||
|
||||
this.on('channel_hangup', () => {
|
||||
debug('用户挂机 %s -> %s', sip, phone);
|
||||
message.ops = 'hangup';
|
||||
message.createtime = moment().valueOf();
|
||||
|
||||
if (sip_uuid) {
|
||||
let file = `/usr/recordings/archive/${sip_uuid}.wav`;
|
||||
message.record = `${moment().format('YYYY-MM-DD')}/${uuid}.wav`;
|
||||
|
||||
access(file, err => {
|
||||
if (err) {
|
||||
debug('录音文件不存在: %s', uuid);
|
||||
} else {
|
||||
debug('上传录音: %s', uuid);
|
||||
|
||||
setTimeout(() => {
|
||||
minio.fPutObject('chatopera', message.record, file).catch(err => {
|
||||
debug('上传录音失败 %s error: %o', uuid, err);
|
||||
});
|
||||
}, 5000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
control.sendEvent(message);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = exports = new FreeSwitch();
|
@ -1,14 +0,0 @@
|
||||
const debug = require('debug')('cc-switch');
|
||||
const Engine = require('./engine');
|
||||
|
||||
const engine = new Engine();
|
||||
|
||||
engine
|
||||
.init()
|
||||
.then(() => {
|
||||
console.log('cc-switch started');
|
||||
})
|
||||
.catch(err => {
|
||||
debug('cc-switch start error: %o', err);
|
||||
process.exit();
|
||||
});
|
@ -1,12 +0,0 @@
|
||||
const Minio = require('minio');
|
||||
const config = require('./config');
|
||||
|
||||
let client = new Minio.Client({
|
||||
endPoint: config.MINIO_END_POINT,
|
||||
accessKey: config.MINIO_ACCESS_KEY,
|
||||
secretKey: config.MINIO_SECRET_KEY,
|
||||
port: 9000,
|
||||
useSSL: false,
|
||||
});
|
||||
|
||||
module.exports = exports = client;
|
@ -1,26 +0,0 @@
|
||||
{
|
||||
"name": "cc-switch",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node index.js",
|
||||
"dev:start": "nodemon index.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"debug": "^3.1.0",
|
||||
"dotenv": "^6.0.0",
|
||||
"ioredis": "^4.0.0",
|
||||
"lodash": ">=4.17.11",
|
||||
"minio": "^7.0.0",
|
||||
"modesl": "^1.2.0",
|
||||
"moment": "^2.22.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "^0.25.0",
|
||||
"nodemon": "^1.18.3"
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
/**
|
||||
* Redis Test
|
||||
*/
|
||||
const test = require('ava');
|
||||
const debug = require('debug')('cc-switch:test:redis');
|
||||
const Redis = require('ioredis');
|
||||
const config = require('../config');
|
||||
const util = require('util');
|
||||
const moment = require('moment');
|
||||
|
||||
|
||||
const redis = new Redis({
|
||||
host: config.REDIS_HOST,
|
||||
port: config.REDIS_PORT,
|
||||
db: 2,
|
||||
});
|
||||
|
||||
const EVENT_TYPE_CALLOUT = "callout";
|
||||
const EVENT_QUEUE_QUEUE_CC_TO_FS = "cc:to:freeswitch";
|
||||
const CALLOUT_DIALPLAN_STATUS = "callout:dialplan:status";
|
||||
const CALLOUT_DIALPLAN_TARGET = "freeswitch:%s:callout";
|
||||
const CALLOUT_CC_FROM_FS = "pbx:bxzq:events";
|
||||
|
||||
|
||||
|
||||
test.only("Redis Test # 外呼接通", async(t) => {
|
||||
let now = moment();
|
||||
now.add(-3, "minutes");
|
||||
console.log("接通时间:", now);
|
||||
|
||||
let payload = {
|
||||
"uuid": "9a0cbc81-ccae-425e-8d3d-369b872a6481",
|
||||
"to": "13213213213",
|
||||
"from": "1003",
|
||||
"type": "callout",
|
||||
"channel": "bxzq",
|
||||
"dialplan": "4028827365b2acec0165b307afe405de",
|
||||
"createtime": now.valueOf(),
|
||||
"ops": "answer"
|
||||
}
|
||||
|
||||
redis.publish(CALLOUT_CC_FROM_FS, JSON.stringify(payload));
|
||||
t.pass();
|
||||
})
|
||||
|
||||
|
||||
|
@ -1,41 +0,0 @@
|
||||
/**
|
||||
* Redis Test
|
||||
*/
|
||||
const test = require('ava');
|
||||
const debug = require('debug')('cc-switch:test:redis');
|
||||
const Redis = require('ioredis');
|
||||
const config = require('../config');
|
||||
const util = require('util');
|
||||
const moment = require('moment');
|
||||
|
||||
const redis = new Redis({
|
||||
host: config.REDIS_HOST,
|
||||
port: config.REDIS_PORT,
|
||||
db: 2,
|
||||
});
|
||||
|
||||
const EVENT_TYPE_CALLOUT = "callout";
|
||||
const EVENT_QUEUE_QUEUE_CC_TO_FS = "cc:to:freeswitch";
|
||||
const CALLOUT_DIALPLAN_STATUS = "callout:dialplan:status";
|
||||
const CALLOUT_DIALPLAN_TARGET = "freeswitch:%s:callout";
|
||||
const CALLOUT_CC_FROM_FS = "pbx:bxzq:events";
|
||||
|
||||
test.only("Redis Test # 外呼挂断", async(t) => {
|
||||
let now = moment();
|
||||
now.add(-3, "minutes");
|
||||
console.log("挂断时间:", now);
|
||||
let payload = {
|
||||
"uuid": "9a0cbc81-ccae-425e-8d3d-369b872a6481",
|
||||
"to": "13213213213",
|
||||
"from": "1003",
|
||||
"type": "callout",
|
||||
"channel": "bxzq",
|
||||
"dialplan": "4028827365b2acec0165b307afe405de",
|
||||
"createtime": now.valueOf(),
|
||||
"ops": "hangup",
|
||||
"record":"chatopera/376bf70a-9449-46c8-ad3e-03ac41953946.wav"
|
||||
}
|
||||
|
||||
redis.publish(CALLOUT_CC_FROM_FS, JSON.stringify(payload));
|
||||
t.pass();
|
||||
})
|
@ -1,5 +1,6 @@
|
||||
app/target
|
||||
!app/target/contact-center-*.war.original
|
||||
!app/target/*.war.original
|
||||
!app/target/*.war
|
||||
logs/
|
||||
tmp/
|
||||
data/
|
||||
|
@ -12,13 +12,9 @@ LABEL org.label-schema.vcs-ref=$VCS_REF \
|
||||
COPY $PWD/assets/install-corretto-8.sh /opt
|
||||
RUN chmod +x /opt/install-corretto-8.sh && /opt/install-corretto-8.sh
|
||||
|
||||
# install maven
|
||||
COPY $PWD/assets/install-maven.sh /opt
|
||||
RUN chmod +x /opt/install-maven.sh && /opt/install-maven.sh
|
||||
|
||||
# configure timezone
|
||||
# install other lib and configure timezone
|
||||
RUN apt-get update && \
|
||||
apt-get install --no-install-recommends -y tzdata && \
|
||||
apt-get install --no-install-recommends -y tzdata mysql-client-5.7 zip unzip vim-tiny && \
|
||||
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
|
||||
DEBIAN_FRONTEND=noninteractive dpkg-reconfigure --frontend noninteractive tzdata && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
@ -30,22 +26,19 @@ ENV LC_ALL C.UTF-8
|
||||
|
||||
# set ENVs
|
||||
ENV JAVA_HOME=/usr/lib/jvm/java-1.8.0-amazon-corretto
|
||||
ENV MAVEN_HOME=/opt/maven
|
||||
ENV PATH=$PATH:$JAVA_HOME/bin:$MAVEN_HOME/bin
|
||||
ENV PATH=$PATH:$JAVA_HOME/bin
|
||||
|
||||
# create dirs
|
||||
RUN /bin/bash -c "mkdir -p /{data,logs}"
|
||||
|
||||
# build WAR
|
||||
COPY app /app
|
||||
COPY config /config
|
||||
WORKDIR /app
|
||||
RUN mvn clean package && \
|
||||
mkdir -p /opt/chatopera && \
|
||||
mv target/contact-center-3.9.0.war /opt/chatopera && \
|
||||
rm -rf /app && rm -rf /config && \
|
||||
rm -rf /root/.m2
|
||||
RUN mkdir -p /opt/chatopera
|
||||
COPY ./app/target/contact-center-*.war /opt/chatopera/contact-center.war
|
||||
COPY ./assets/setup-mysql-db.sh /opt/chatopera
|
||||
COPY ./assets/utils.sh /opt/chatopera
|
||||
COPY ./assets/docker-entrypoint.sh /opt/chatopera
|
||||
RUN chmod +x /opt/chatopera/*.sh
|
||||
|
||||
WORKDIR /opt/chatopera
|
||||
EXPOSE 8030-8050
|
||||
CMD ["java", "-jar", "contact-center-3.9.0.war"]
|
||||
CMD ["./docker-entrypoint.sh"]
|
@ -1,22 +1,7 @@
|
||||
# 春松客服:智能客服系统
|
||||
|
||||
前三代呼叫中心均是以电话为主要的服务渠道。在2000年,伴随着互联网以及移动通信的发展与普及,将电子邮件、互联网、手机短信等渠道接入呼叫中心,成为第四代呼叫中心的标志。第四代呼叫中心也称为多媒体呼叫中心或联络中心(Contact Center)。它相对传统呼叫中心来说接入渠道丰富,同时引入了多渠道接入与多渠道统一排队等概念。
|
||||
前三代呼叫中心均是以电话为主要的服务渠道。在 2000 年,伴随着互联网以及移动通信的发展与普及,将电子邮件、互联网、手机短信等渠道接入呼叫中心,成为第四代呼叫中心的标志。第四代呼叫中心也称为多媒体呼叫中心或联络中心(Contact Center)。它相对传统呼叫中心来说接入渠道丰富,同时引入了多渠道接入与多渠道统一排队等概念。
|
||||
|
||||
## 文档
|
||||
|
||||
### ukefu
|
||||
原始项目基于[ukefu](https://gitee.com/beimigame/ukefu)。
|
||||
|
||||
```
|
||||
链接: https://pan.baidu.com/s/1wEPZeieZm4qaaFSWUb2Szg
|
||||
密码: tdm2
|
||||
```
|
||||
|
||||
### wiki
|
||||
|
||||
<a href="https://github.com/Samurais/chatopera.io/wiki/13.-ContactCenter%EF%BC%9A%E5%A4%9A%E5%AA%92%E4%BD%93%E5%91%BC%E5%8F%AB%E4%B8%AD%E5%BF%83">ContactCenter:多媒体呼叫中心</a>
|
||||
|
||||
## 媒体
|
||||
|
||||
<a href="http://36kr.com/p/5144999.html" target="_blank">谷歌发布Contact Center AI,智能客服真能不再“智障”了吗?</a>
|
||||
|
||||
https://docs.chatopera.com/products/cskefu/index.html
|
||||
|
@ -6,14 +6,23 @@
|
||||
# constants
|
||||
baseDir=$(cd `dirname "$0"`;pwd)
|
||||
appHome=$baseDir/..
|
||||
registryName=dockerhub.qingcloud.com
|
||||
imagename=chatopera/contact-center
|
||||
PACKAGE_VERSION=1.0.0
|
||||
# functions
|
||||
|
||||
# main
|
||||
[ -z "${BASH_SOURCE[0]}" -o "${BASH_SOURCE[0]}" = "$0" ] || return
|
||||
# build
|
||||
cd $appHome
|
||||
PACKAGE_VERSION=`git rev-parse --short HEAD`
|
||||
|
||||
set -x
|
||||
docker build --build-arg VCS_REF=`git rev-parse --short HEAD` --force-rm=true --tag $imagename:$PACKAGE_VERSION .
|
||||
docker tag $imagename:$PACKAGE_VERSION $imagename:develop
|
||||
$baseDir/package.sh
|
||||
|
||||
if [ ! $? -eq 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
docker build --build-arg VCS_REF=$PACKAGE_VERSION \
|
||||
--no-cache \
|
||||
--force-rm=true --tag $registryName/$imagename:$PACKAGE_VERSION .
|
@ -11,3 +11,7 @@ baseDir=$(cd `dirname "$0"`;pwd)
|
||||
[ -z "${BASH_SOURCE[0]}" -o "${BASH_SOURCE[0]}" = "$0" ] || return
|
||||
cd $baseDir/../app
|
||||
mvn clean package
|
||||
|
||||
if [ ! $? -eq 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
@ -5,12 +5,12 @@
|
||||
|
||||
# constants
|
||||
baseDir=$(cd `dirname "$0"`;pwd)
|
||||
registryName=dockerhub.qingcloud.com
|
||||
imagename=chatopera/contact-center
|
||||
PACKAGE_VERSION=1.0.0
|
||||
PACKAGE_VERSION=w4l
|
||||
|
||||
# functions
|
||||
|
||||
# main
|
||||
[ -z "${BASH_SOURCE[0]}" -o "${BASH_SOURCE[0]}" = "$0" ] || return
|
||||
docker push $imagename:$PACKAGE_VERSION
|
||||
docker push $imagename:develop
|
||||
docker push $registryName/$imagename:$PACKAGE_VERSION
|
@ -5,6 +5,10 @@
|
||||
|
||||
# constants
|
||||
baseDir=$(cd `dirname "$0"`;pwd)
|
||||
registryName=dockerhub.qingcloud.com
|
||||
imagename=chatopera/contact-center
|
||||
PACKAGE_VERSION=w4l
|
||||
|
||||
# functions
|
||||
|
||||
# main
|
||||
@ -35,4 +39,4 @@ docker run -it --rm \
|
||||
-e SPRING_DATA_ELASTICSEARCH_CLUSTER_NODES=elasticsearch:8040 \
|
||||
-e SPRING_DATA_ELASTICSEARCH_LOCAL=false \
|
||||
-e SPRING_DATA_ELASTICSEARCH_REPOSITORIES_ENABLED=true \
|
||||
chatopera/contact-center:develop
|
||||
$registryName/$imagename:$PACKAGE_VERSION
|
||||
|
@ -5,12 +5,10 @@
|
||||
|
||||
# constants
|
||||
baseDir=$(cd `dirname "$0"`;pwd)
|
||||
export ACTIVEMQ_HOST=corsair
|
||||
export REDIS_HOST=corsair
|
||||
|
||||
# functions
|
||||
|
||||
# main
|
||||
[ -z "${BASH_SOURCE[0]}" -o "${BASH_SOURCE[0]}" = "$0" ] || return
|
||||
cd $baseDir/../app
|
||||
DEBUG=cc* npm run dev:start
|
||||
set -x
|
||||
mvn -Dtest=com.chatopera.cc.proto.ProtoTest#testProto test
|
7
contact-center/app/.gitignore
vendored
Normal file
7
contact-center/app/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# ignore plugins source code
|
||||
src/main/java/com/chatopera/cc/plugins/
|
||||
|
||||
# ignore views within plugins
|
||||
!src/main/resources/templates/admin/channel/callout/
|
||||
!src/main/resources/templates/admin/channel/im/
|
||||
src/main/resources/templates/admin/channel/*
|
@ -3,16 +3,15 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.chatopera.cc</groupId>
|
||||
<artifactId>contact-center</artifactId>
|
||||
<version>3.9.0</version>
|
||||
<version>5.0.0</version>
|
||||
<packaging>war</packaging>
|
||||
<name>contact-center</name>
|
||||
<description>Chatopera Contact Center,多媒体呼叫中心,下一代呼叫中心</description>
|
||||
<name>cskefu</name>
|
||||
<description>春松客服企业版:多媒体呼叫中心,下一代呼叫中心</description>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.5.6.RELEASE</version>
|
||||
<relativePath/>
|
||||
<!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
@ -28,10 +27,23 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.activemq</groupId>
|
||||
<artifactId>activemq-pool</artifactId>
|
||||
<version>5.14.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-activemq</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-freemarker</artifactId>
|
||||
@ -44,7 +56,7 @@
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
<artifactId>freemarker</artifactId>
|
||||
<version>2.3.25-incubating</version>
|
||||
<version>2.3.29</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
@ -73,11 +85,15 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
<artifactId>spring-boot-starter-cache</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@ -98,16 +114,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<version>2.2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger-ui</artifactId>
|
||||
<version>2.2.2</version>
|
||||
<version>1.5.13.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jasypt</groupId>
|
||||
@ -157,12 +164,6 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.hazelcast</groupId>
|
||||
<artifactId>hazelcast-all</artifactId>
|
||||
<version>3.10.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.quartz-scheduler</groupId>
|
||||
<artifactId>quartz</artifactId>
|
||||
@ -172,6 +173,19 @@
|
||||
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-xml</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- AOP dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<version>1.9.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<version>1.9.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
@ -183,11 +197,6 @@
|
||||
<artifactId>ip2region</artifactId>
|
||||
<version>1.7.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.lionsoul</groupId>
|
||||
<artifactId>jcseg-core</artifactId>
|
||||
<version>2.2.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.lmax</groupId>
|
||||
<artifactId>disruptor</artifactId>
|
||||
@ -203,6 +212,11 @@
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>3.15</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.47</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-mp</artifactId>
|
||||
@ -329,14 +343,63 @@
|
||||
<artifactId>unirest-java</artifactId>
|
||||
<version>1.4.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.chatopera.compose4j</groupId>
|
||||
<artifactId>compose4j</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.chatopera.bot</groupId>
|
||||
<artifactId>sdk</artifactId>
|
||||
<version>1.0.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>pl.project13.maven</groupId>
|
||||
<artifactId>git-commit-id-plugin</artifactId>
|
||||
<version>2.2.5</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>get-the-git-infos</id>
|
||||
<goals>
|
||||
<goal>revision</goal>
|
||||
</goals>
|
||||
<!-- *NOTE*: The default phase of revision is initialize, but in case you want to change it, you can do so by adding the phase here -->
|
||||
<phase>initialize</phase>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>validate-the-git-infos</id>
|
||||
<goals>
|
||||
<goal>validateRevision</goal>
|
||||
</goals>
|
||||
<!-- *NOTE*: The default phase of validateRevision is verify, but in case you want to change it, you can do so by adding the phase here -->
|
||||
<phase>package</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<excludeProperties>
|
||||
<excludeProperty>git.tags</excludeProperty>
|
||||
<excludeProperty>git.remote.*</excludeProperty>
|
||||
<excludeProperty>git.closest.*</excludeProperty>
|
||||
<excludeProperty>git.total.commit.count</excludeProperty>
|
||||
</excludeProperties>
|
||||
<dotGitDirectory>${project.basedir}/../../.git</dotGitDirectory>
|
||||
<generateGitPropertiesFilename>
|
||||
${project.build.outputDirectory}/git.properties
|
||||
</generateGitPropertiesFilename>
|
||||
<generateGitPropertiesFile>true</generateGitPropertiesFile>
|
||||
<prefix>git</prefix>
|
||||
<verbose>false</verbose>
|
||||
<injectAllReactorProjects>true</injectAllReactorProjects>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
@ -351,11 +414,12 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
@ -370,21 +434,14 @@
|
||||
<resource>
|
||||
<directory>../config/sql/</directory>
|
||||
<includes>
|
||||
<include>cskefu-MySQL-slim.sql</include>
|
||||
<include>cosinee-MySQL-slim.sql</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</webResources>
|
||||
</configuration>
|
||||
<version>2.1.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>8</source>
|
||||
<target>8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
<defaultGoal>compile</defaultGoal>
|
||||
</build>
|
||||
@ -405,7 +462,7 @@
|
||||
<developer>
|
||||
<id>hain</id>
|
||||
<name>Hai Liang Wang</name>
|
||||
<email>hailiang.hl.wang@gmail.com</email>
|
||||
<email>hain@chatopera.com</email>
|
||||
<url>https://github.com/Samurais</url>
|
||||
<organization>Chatopera Inc.</organization>
|
||||
<organizationUrl>https://www.chatopera.com</organizationUrl>
|
||||
|
@ -14,20 +14,21 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app;
|
||||
package com.chatopera.cc;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.config.StartedEventListener;
|
||||
import com.chatopera.cc.util.Constants;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.basic.plugins.PluginRegistry;
|
||||
import com.chatopera.cc.config.AppCtxRefreshEventListener;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.util.SystemEnvHelper;
|
||||
import com.chatopera.cc.util.mobile.MobileNumberUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.Banner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.boot.web.servlet.ErrorPage;
|
||||
@ -35,6 +36,7 @@ import org.springframework.boot.web.servlet.MultipartConfigFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.jms.annotation.EnableJms;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@ -42,12 +44,15 @@ import javax.servlet.MultipartConfigElement;
|
||||
import java.io.IOException;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableJpaRepositories("com.chatopera.cc.app.persistence.repository")
|
||||
@EnableElasticsearchRepositories("com.chatopera.cc.app.persistence.es")
|
||||
@EnableJpaRepositories("com.chatopera.cc.persistence.repository")
|
||||
@EnableElasticsearchRepositories("com.chatopera.cc.persistence.es")
|
||||
@EnableAsync
|
||||
@EnableJms
|
||||
@EnableTransactionManagement
|
||||
public class Application {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Application.class);
|
||||
|
||||
@Value("${web.upload-path}")
|
||||
private String uploaddir;
|
||||
|
||||
@ -61,24 +66,51 @@ public class Application {
|
||||
* 记载模块
|
||||
*/
|
||||
// 外呼模块
|
||||
private final static boolean isCalloutModule = SystemEnvHelper.parseModuleFlag("CSKEFU_MODULE_CALLOUT");
|
||||
private final static boolean isCalloutModule = SystemEnvHelper.parseModuleFlag("cskefu.module.callout");
|
||||
|
||||
// CRM模块
|
||||
private final static boolean isContactsModule = SystemEnvHelper.parseModuleFlag("CSKEFU_MODULE_CONTACTS");
|
||||
private final static boolean isContactsModule = SystemEnvHelper.parseModuleFlag("cskefu.module.contacts");
|
||||
|
||||
// 聊天机器人模块
|
||||
private final static boolean isChatbotModule = SystemEnvHelper.parseModuleFlag("CSKEFU_MODULE_CHATBOT");
|
||||
private final static boolean isChatbotModule = SystemEnvHelper.parseModuleFlag("cskefu.module.chatbot");
|
||||
|
||||
// 访客聊天监控模块
|
||||
private final static boolean isCcaModule = SystemEnvHelper.parseModuleFlag("cskefu.module.cca");
|
||||
|
||||
// 企业聊天模块
|
||||
private final static boolean isEntImModule = SystemEnvHelper.parseModuleFlag("cskefu.module.entim");
|
||||
|
||||
// 渠道:Skype渠道
|
||||
private final static boolean isSkypeModule = SystemEnvHelper.isClassExistByFullName(
|
||||
PluginRegistry.PLUGIN_ENTRY_SKYPE);
|
||||
|
||||
static {
|
||||
// 外呼模块
|
||||
if (isCalloutModule) {
|
||||
MainContext.model.put(Constants.CSKEFU_MODULE_CALLOUT, true);
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_CALLOUT);
|
||||
}
|
||||
// CRM模块
|
||||
if (isContactsModule) {
|
||||
MainContext.model.put(Constants.CSKEFU_MODULE_CONTACTS, true);
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_CONTACTS);
|
||||
}
|
||||
// 聊天机器人模块
|
||||
if (isChatbotModule) {
|
||||
MainContext.model.put(Constants.CSKEFU_MODULE_CHATBOT, true);
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_CHATBOT);
|
||||
}
|
||||
|
||||
// skype模块
|
||||
if (isSkypeModule) {
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_SKYPE);
|
||||
}
|
||||
|
||||
// 会话监控模块 Customer Chats Audit
|
||||
if (isCcaModule) {
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_CCA);
|
||||
|
||||
}
|
||||
// 企业聊天模块
|
||||
if (isEntImModule) {
|
||||
MainContext.enableModule(Constants.CSKEFU_MODULE_ENTIM);
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,10 +119,9 @@ public class Application {
|
||||
*/
|
||||
protected static void init() {
|
||||
try {
|
||||
System.out.println("init mobile number utils ...");
|
||||
MobileNumberUtils.init();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
logger.error("Application Startup Error", e);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
@ -106,7 +137,6 @@ public class Application {
|
||||
|
||||
@Bean
|
||||
public EmbeddedServletContainerCustomizer containerCustomizer() {
|
||||
|
||||
return new EmbeddedServletContainerCustomizer() {
|
||||
@Override
|
||||
public void customize(ConfigurableEmbeddedServletContainer container) {
|
||||
@ -118,11 +148,18 @@ public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Application.init();
|
||||
SpringApplication app = new SpringApplication(Application.class);
|
||||
|
||||
/************************
|
||||
* 该APP中加载多个配置文件
|
||||
* http://roufid.com/load-multiple-configuration-files-different-directories-spring-boot/
|
||||
************************/
|
||||
SpringApplication app = new SpringApplicationBuilder(Application.class)
|
||||
.properties("spring.config.name:application,git")
|
||||
.build();
|
||||
|
||||
app.setBannerMode(Banner.Mode.CONSOLE);
|
||||
app.setAddCommandLineProperties(false);
|
||||
app.addListeners(new StartedEventListener());
|
||||
app.addListeners(new AppCtxRefreshEventListener());
|
||||
MainContext.setApplicationContext(app.run(args));
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app;
|
||||
package com.chatopera.cc;
|
||||
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.support.SpringBootServletInitializer;
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.activemq;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.model.AgentUser;
|
||||
import com.chatopera.cc.model.AgentUserAudit;
|
||||
import com.chatopera.cc.persistence.repository.AgentUserRepository;
|
||||
import com.chatopera.cc.proxy.AgentAuditProxy;
|
||||
import com.chatopera.cc.socketio.client.NettyClients;
|
||||
import com.chatopera.cc.util.SerializeUtil;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jms.annotation.JmsListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 会话监控
|
||||
*/
|
||||
@Component
|
||||
public class AgentAuditSubscription {
|
||||
private final static Logger logger = LoggerFactory.getLogger(AgentAuditSubscription.class);
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@Autowired
|
||||
private AgentAuditProxy agentAuditProxy;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRes;
|
||||
|
||||
|
||||
/**
|
||||
* 接收坐席会话监控消息
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
@JmsListener(destination = Constants.AUDIT_AGENT_MESSAGE, containerFactory = "jmsListenerContainerTopic")
|
||||
public void onMessage(final String msg) {
|
||||
logger.info("[onMessage] payload {}", msg);
|
||||
try {
|
||||
final JsonObject json = new JsonParser().parse(msg).getAsJsonObject();
|
||||
|
||||
if (json.has("orgi") && json.has("data") &&
|
||||
json.has("agentUserId") &&
|
||||
json.has("event") && json.has("agentno")) {
|
||||
|
||||
// 查找关联的会话监控信息
|
||||
final AgentUserAudit agentUserAudit = cache.findOneAgentUserAuditByOrgiAndId(
|
||||
json.get("orgi").getAsString(),
|
||||
json.get("agentUserId").getAsString()).orElseGet(() -> {
|
||||
final AgentUser agentUser = agentUserRes.findOne(json.get("agentUserId").getAsString());
|
||||
if (agentUser != null) {
|
||||
return agentAuditProxy.updateAgentUserAudits(agentUser);
|
||||
} else {
|
||||
logger.warn(
|
||||
"[onMessage] can not find agent user by id {}", json.get("agentUserId").getAsString());
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
if (agentUserAudit != null) {
|
||||
final String agentno = json.get("agentno").getAsString();
|
||||
logger.info(
|
||||
"[onMessage] agentno {}, subscribers size {}, subscribers {}", agentno,
|
||||
agentUserAudit.getSubscribers().size(),
|
||||
StringUtils.join(agentUserAudit.getSubscribers().keySet(), "|"));
|
||||
|
||||
// 发送消息给坐席监控,不需要分布式,因为这条消息已经是从ActiveMQ使用Topic多机广播
|
||||
for (final String subscriber : agentUserAudit.getSubscribers().keySet()) {
|
||||
logger.info("[onMessage] process subscriber {}", subscriber);
|
||||
if (!StringUtils.equals(subscriber, agentno)) {
|
||||
logger.info("[onMessage] publish event to {}", subscriber);
|
||||
NettyClients.getInstance().publishAuditEventMessage(
|
||||
subscriber,
|
||||
json.get("event").getAsString(),
|
||||
SerializeUtil.deserialize(json.get("data").getAsString()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logger.warn(
|
||||
"[onMessage] can not resolve agent user audit object for agent user id {}",
|
||||
json.get("agentUserId").getAsString());
|
||||
}
|
||||
} else {
|
||||
throw new CSKefuException("Invalid payload.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("[onMessage] error", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.activemq;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.socketio.client.NettyClients;
|
||||
import com.chatopera.cc.util.SerializeUtil;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.jms.annotation.JmsListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class AgentSessionSubscription {
|
||||
private final static Logger logger = LoggerFactory.getLogger(AgentSessionSubscription.class);
|
||||
|
||||
/**
|
||||
* 接收坐席会话监控消息
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
@JmsListener(destination = Constants.MQ_TOPIC_WEB_SESSION_SSO, containerFactory = "jmsListenerContainerTopic")
|
||||
public void onMessage(final String msg) {
|
||||
logger.info("[onMessage] payload {}", msg);
|
||||
try {
|
||||
final JsonObject json = new JsonParser().parse(msg).getAsJsonObject();
|
||||
// 把登出消息通知给浏览器
|
||||
NettyClients.getInstance().publishLeaveEventMessage(
|
||||
json.get("agentno").getAsString(),
|
||||
json.get("post").getAsString());
|
||||
} catch (Exception e) {
|
||||
logger.warn("[onMessage] error", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, All rights reserved.
|
||||
* <https://www.chatopera.com>
|
||||
* This software and related documentation are provided under a license agreement containing
|
||||
* restrictions on use and disclosure and are protected by intellectual property laws.
|
||||
* Except as expressly permitted in your license agreement or allowed by law, you may not use,
|
||||
* copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform,
|
||||
* publish, or display any part, in any form, or by any means. Reverse engineering, disassembly,
|
||||
* or decompilation of this software, unless required by law for interoperability, is prohibited.
|
||||
*/
|
||||
package com.chatopera.cc.activemq;
|
||||
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.socketio.client.NettyClients;
|
||||
import com.chatopera.cc.util.SerializeUtil;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.jms.annotation.JmsListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* WebIM Agent
|
||||
*/
|
||||
@Component
|
||||
public class AgentSubscription {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(AgentSubscription.class);
|
||||
|
||||
@Value("${application.node.id}")
|
||||
private String appNodeId;
|
||||
|
||||
@Autowired
|
||||
private BrokerPublisher brokerPublisher;
|
||||
|
||||
/**
|
||||
* Publish Message into ActiveMQ
|
||||
*
|
||||
* @param j
|
||||
*/
|
||||
public void publish(JsonObject j) {
|
||||
j.addProperty("node", appNodeId);
|
||||
brokerPublisher.send(Constants.INSTANT_MESSAGING_MQ_TOPIC_AGENT, j.toString(), true);
|
||||
}
|
||||
|
||||
@JmsListener(destination = Constants.INSTANT_MESSAGING_MQ_TOPIC_AGENT, containerFactory = "jmsListenerContainerTopic")
|
||||
public void onMessage(final String payload) {
|
||||
logger.info("[onMessage] payload {}", payload);
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject j = parser.parse(payload).getAsJsonObject();
|
||||
logger.debug("[onMessage] message body {}", j.toString());
|
||||
try {
|
||||
if (!j.has("id")) {
|
||||
logger.warn("[onMessage] Invalid payload, id is null");
|
||||
return;
|
||||
}
|
||||
|
||||
NettyClients.getInstance().sendAgentEventMessage(
|
||||
j.get("id").getAsString(),
|
||||
j.get("event").getAsString(),
|
||||
SerializeUtil.deserialize(j.get("data").getAsString()));
|
||||
} catch (Exception e) {
|
||||
logger.error("onMessage", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.activemq;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.persistence.repository.BlackListRepository;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jms.annotation.JmsListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 访客黑名单
|
||||
*/
|
||||
@Component
|
||||
public class BlackListEventSubscription {
|
||||
private final static Logger logger = LoggerFactory.getLogger(BlackListEventSubscription.class);
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@Autowired
|
||||
private BlackListRepository blackListRes;
|
||||
|
||||
/**
|
||||
* 拉黑访客到达拉黑时间后,从黑名单中移除
|
||||
*
|
||||
* @param payload
|
||||
*/
|
||||
@JmsListener(destination = Constants.WEBIM_SOCKETIO_ONLINE_USER_BLACKLIST, containerFactory = "jmsListenerContainerQueue")
|
||||
public void onMessage(final String payload) {
|
||||
logger.info("[onMessage] payload {}", payload);
|
||||
|
||||
try {
|
||||
final JSONObject json = JSON.parseObject(payload);
|
||||
final String userId = json.getString("userId");
|
||||
final String orgi = json.getString("orgi");
|
||||
|
||||
if (StringUtils.isNotBlank(userId) && StringUtils.isNotBlank(orgi)) {
|
||||
cache.findOneBlackEntityByUserIdAndOrgi(userId, orgi).ifPresent(blackListRes::delete);
|
||||
} else {
|
||||
logger.warn("[onMessage] error: invalid payload");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("[onMessage] error", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, All rights reserved.
|
||||
* <https://www.chatopera.com>
|
||||
* This software and related documentation are provided under a license agreement containing
|
||||
* restrictions on use and disclosure and are protected by intellectual property laws.
|
||||
* Except as expressly permitted in your license agreement or allowed by law, you may not use,
|
||||
* copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform,
|
||||
* publish, or display any part, in any form, or by any means. Reverse engineering, disassembly,
|
||||
* or decompilation of this software, unless required by law for interoperability, is prohibited.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.activemq;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.apache.activemq.ScheduledMessage;
|
||||
import org.apache.activemq.command.ActiveMQTopic;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jms.core.JmsTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class BrokerPublisher {
|
||||
|
||||
final static private Logger logger = LoggerFactory.getLogger(BrokerPublisher.class);
|
||||
|
||||
@Autowired
|
||||
private JmsTemplate jmsTemplate;
|
||||
|
||||
@PostConstruct
|
||||
public void setup() {
|
||||
logger.info("[ActiveMQ Publisher] setup successfully.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 时延消息
|
||||
*
|
||||
* @param destination
|
||||
* @param payload
|
||||
* @param delay available by delayed seconds
|
||||
*/
|
||||
public void send(final String destination, final String payload, final boolean isTopic, final int delay) {
|
||||
try {
|
||||
if (isTopic) {
|
||||
jmsTemplate.convertAndSend(new ActiveMQTopic(destination), payload, m -> {
|
||||
m.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, 1000 * delay);
|
||||
return m;
|
||||
});
|
||||
} else {
|
||||
// 默认为Queue
|
||||
jmsTemplate.convertAndSend(destination, payload, m -> {
|
||||
m.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, 1000 * delay);
|
||||
return m;
|
||||
});
|
||||
}
|
||||
logger.debug("[send] send succ, dest {}, payload {}", destination, payload);
|
||||
} catch (Exception e) {
|
||||
logger.warn("[send] error happens.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param destination
|
||||
* @param payload
|
||||
* @param isTopic
|
||||
*/
|
||||
public void send(final String destination, final String payload, boolean isTopic) {
|
||||
try {
|
||||
if (isTopic) {
|
||||
jmsTemplate.convertAndSend(new ActiveMQTopic(destination), payload);
|
||||
} else {
|
||||
// 默认为Queue
|
||||
jmsTemplate.convertAndSend(destination, payload);
|
||||
}
|
||||
logger.debug("[send] send succ, dest {}, payload {}", destination, payload);
|
||||
} catch (Exception e) {
|
||||
logger.warn("[send] error happens.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void send(final String destination, final String payload) {
|
||||
send(destination, payload, false);
|
||||
}
|
||||
|
||||
public void send(final String destination, final JSONObject payload) {
|
||||
send(destination, payload.toJSONString());
|
||||
}
|
||||
|
||||
public void send(final String destination, final org.json.JSONObject payload) {
|
||||
send(destination, payload.toString());
|
||||
}
|
||||
|
||||
public void send(final String destination, final Map<String, String> payload) {
|
||||
JSONObject obj = new JSONObject();
|
||||
|
||||
for (Map.Entry<String, String> entry : payload.entrySet()) {
|
||||
obj.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
send(destination, obj.toJSONString());
|
||||
}
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, All rights reserved.
|
||||
* <https://www.chatopera.com>
|
||||
* This software and related documentation are provided under a license agreement containing
|
||||
* restrictions on use and disclosure and are protected by intellectual property laws.
|
||||
* Except as expressly permitted in your license agreement or allowed by law, you may not use,
|
||||
* copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform,
|
||||
* publish, or display any part, in any form, or by any means. Reverse engineering, disassembly,
|
||||
* or decompilation of this software, unless required by law for interoperability, is prohibited.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.activemq;
|
||||
|
||||
import com.chatopera.bot.exception.ChatbotException;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.handler.api.request.RestUtils;
|
||||
import com.chatopera.cc.socketio.message.ChatMessage;
|
||||
import com.chatopera.cc.proxy.ChatbotProxy;
|
||||
import com.chatopera.cc.model.AgentUser;
|
||||
import com.chatopera.cc.model.Chatbot;
|
||||
import com.chatopera.cc.persistence.repository.AgentUserRepository;
|
||||
import com.chatopera.cc.persistence.repository.ChatbotRepository;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.util.SerializeUtil;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.jms.annotation.JmsListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
|
||||
/**
|
||||
* 发送消息给聊天机器人并处理返回结果
|
||||
*/
|
||||
@Component
|
||||
public class ChatbotEventSubscription {
|
||||
private final static Logger logger = LoggerFactory.getLogger(ChatbotEventSubscription.class);
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRes;
|
||||
|
||||
@Autowired
|
||||
private ChatbotRepository chatbotRes;
|
||||
|
||||
@Value("${bot.baseurl}")
|
||||
private static String botBaseUrl;
|
||||
|
||||
@Autowired
|
||||
private ChatbotProxy chatbotProxy;
|
||||
|
||||
/**
|
||||
* 接收发送消息给聊天机器人的请求
|
||||
*
|
||||
* @param payload
|
||||
*/
|
||||
@JmsListener(destination = Constants.INSTANT_MESSAGING_MQ_QUEUE_CHATBOT, containerFactory = "jmsListenerContainerQueue")
|
||||
public void onMessage(final String payload) {
|
||||
ChatMessage message = SerializeUtil.deserialize(payload);
|
||||
try {
|
||||
chat(message);
|
||||
} catch (MalformedURLException e) {
|
||||
logger.error("[onMessage] error", e);
|
||||
} catch (ChatbotException e) {
|
||||
logger.error("[onMessage] error", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void chat(final ChatMessage request) throws MalformedURLException, ChatbotException, JSONException {
|
||||
Chatbot c = chatbotRes
|
||||
.findOne(request.getAiid());
|
||||
|
||||
logger.info(
|
||||
"[chat] chat request baseUrl {}, chatbot {}, fromUserId {}, textMessage {}", botBaseUrl, c.getName(),
|
||||
request.getUserid(), request.getMessage());
|
||||
// Get response from Conversational Engine.
|
||||
com.chatopera.bot.sdk.Chatbot bot = new com.chatopera.bot.sdk.Chatbot(
|
||||
c.getClientId(), c.getSecret(), botBaseUrl);
|
||||
JSONObject result = bot.conversation(request.getUserid(), request.getMessage());
|
||||
|
||||
// parse response
|
||||
if (result != null) {
|
||||
logger.info("[chat] chat response {}", result.toString());
|
||||
if (result.getInt(RestUtils.RESP_KEY_RC) == 0) {
|
||||
// reply
|
||||
JSONObject data = result.getJSONObject("data");
|
||||
ChatMessage resp = new ChatMessage();
|
||||
resp.setCalltype(MainContext.CallType.OUT.toString());
|
||||
resp.setAppid(resp.getAppid());
|
||||
resp.setOrgi(request.getOrgi());
|
||||
resp.setAiid(request.getAiid());
|
||||
resp.setMessage(data.getString("string"));
|
||||
resp.setTouser(request.getUserid());
|
||||
resp.setAgentserviceid(request.getAgentserviceid());
|
||||
resp.setMsgtype(request.getMsgtype());
|
||||
resp.setUserid(request.getUserid());
|
||||
resp.setType(request.getType());
|
||||
resp.setChannel(request.getChannel());
|
||||
if (data.has("params")) {
|
||||
resp.setExpmsg(data.get("params").toString());
|
||||
}
|
||||
resp.setContextid(request.getContextid());
|
||||
resp.setSessionid(request.getSessionid());
|
||||
resp.setUsession(request.getUsession());
|
||||
resp.setUsername(c.getName());
|
||||
resp.setUpdatetime(System.currentTimeMillis());
|
||||
|
||||
// 更新聊天机器人累计值
|
||||
updateAgentUserWithRespData(request.getUserid(), request.getOrgi(), data);
|
||||
// 保存并发送
|
||||
chatbotProxy.saveAndPublish(resp);
|
||||
} else {
|
||||
logger.warn("[chat] can not get expected response {}", result.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据聊天机器人返回数据更新agentUser
|
||||
*
|
||||
* @param userid
|
||||
* @param data
|
||||
*/
|
||||
private void updateAgentUserWithRespData(final String userid, final String orgi, final JSONObject data) throws JSONException {
|
||||
cache.findOneAgentUserByUserIdAndOrgi(userid, orgi).ifPresent(p -> {
|
||||
p.setChatbotround(p.getChatbotround() + 1);
|
||||
if (data.has("logic_is_unexpected") && data.getBoolean("logic_is_unexpected")) {
|
||||
p.setChatbotlogicerror(p.getChatbotlogicerror() + 1);
|
||||
}
|
||||
agentUserRes.save(p);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, All rights reserved.
|
||||
* <https://www.chatopera.com>
|
||||
* This software and related documentation are provided under a license agreement containing
|
||||
* restrictions on use and disclosure and are protected by intellectual property laws.
|
||||
* Except as expressly permitted in your license agreement or allowed by law, you may not use,
|
||||
* copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform,
|
||||
* publish, or display any part, in any form, or by any means. Reverse engineering, disassembly,
|
||||
* or decompilation of this software, unless required by law for interoperability, is prohibited.
|
||||
*/
|
||||
package com.chatopera.cc.activemq;
|
||||
|
||||
import com.chatopera.cc.acd.AutomaticServiceDist;
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.model.AgentStatus;
|
||||
import com.chatopera.cc.persistence.repository.AgentStatusRepository;
|
||||
import com.chatopera.cc.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.jms.annotation.JmsListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 处理SocketIO的离线事件
|
||||
*/
|
||||
@Component
|
||||
public class ConnectionEventSubscription {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ConnectionEventSubscription.class);
|
||||
|
||||
@Autowired
|
||||
private AgentStatusRepository agentStatusRes;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRes;
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@Value("${application.node.id}")
|
||||
private String appNodeId;
|
||||
|
||||
@PostConstruct
|
||||
public void setup() {
|
||||
logger.info("ActiveMQ Subscription is setup successfully.");
|
||||
}
|
||||
|
||||
@JmsListener(destination = Constants.WEBIM_SOCKETIO_AGENT_DISCONNECT, containerFactory = "jmsListenerContainerQueue")
|
||||
public void onMessage(final String payload) {
|
||||
logger.info("[onMessage] payload {}", payload);
|
||||
|
||||
try {
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject j = parser.parse(payload).getAsJsonObject();
|
||||
if (j.has("userId") && j.has("orgi") && j.has("isAdmin")) {
|
||||
final AgentStatus agentStatus = cache.findOneAgentStatusByAgentnoAndOrig(j.get("userId").getAsString(),
|
||||
j.get("orgi").getAsString());
|
||||
if (agentStatus != null && (!agentStatus.isConnected())) {
|
||||
/**
|
||||
* 处理该坐席为离线
|
||||
*/
|
||||
// 重分配坐席
|
||||
if (AutomaticServiceDist.withdrawAgent(agentStatus.getOrgi(), agentStatus.getAgentno())) {
|
||||
logger.info("[onMessage] re-allotAgent for user's visitors successfully.");
|
||||
} else {
|
||||
logger.info("[onMessage] re-allotAgent, error happens.");
|
||||
}
|
||||
|
||||
// 更新数据库
|
||||
agentStatus.setBusy(false);
|
||||
agentStatus.setStatus(MainContext.AgentStatusEnum.OFFLINE.toString());
|
||||
agentStatus.setUpdatetime(new Date());
|
||||
|
||||
// 设置该坐席状态为离线
|
||||
cache.deleteAgentStatusByAgentnoAndOrgi(agentStatus.getAgentno(), agentStatus.getOrgi());
|
||||
agentStatusRes.save(agentStatus);
|
||||
|
||||
// 记录坐席工作日志
|
||||
AutomaticServiceDist.recordAgentStatus(agentStatus.getAgentno(),
|
||||
agentStatus.getUsername(),
|
||||
agentStatus.getAgentno(),
|
||||
j.get("isAdmin").getAsBoolean(),
|
||||
agentStatus.getAgentno(),
|
||||
agentStatus.getStatus(),
|
||||
MainContext.AgentStatusEnum.OFFLINE.toString(),
|
||||
MainContext.AgentWorkType.MEIDIACHAT.toString(),
|
||||
agentStatus.getOrgi(), null);
|
||||
} else if (agentStatus == null) {
|
||||
// 该坐席已经完成离线设置
|
||||
logger.info("[onMessage] agent is already offline, skip any further operations");
|
||||
} else {
|
||||
// 该坐席目前在线,忽略该延迟事件
|
||||
logger.info("[onMessage] agent is online now, ignore this message.");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("onMessage", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, All rights reserved.
|
||||
* <https://www.chatopera.com>
|
||||
* This software and related documentation are provided under a license agreement containing
|
||||
* restrictions on use and disclosure and are protected by intellectual property laws.
|
||||
* Except as expressly permitted in your license agreement or allowed by law, you may not use,
|
||||
* copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform,
|
||||
* publish, or display any part, in any form, or by any means. Reverse engineering, disassembly,
|
||||
* or decompilation of this software, unless required by law for interoperability, is prohibited.
|
||||
*/
|
||||
package com.chatopera.cc.activemq;
|
||||
|
||||
import com.chatopera.cc.socketio.client.NettyClients;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.chatopera.cc.util.SerializeUtil;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.jms.annotation.JmsListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* IM OnlineUser
|
||||
*/
|
||||
@Component
|
||||
public class OnlineUserSubscription {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(OnlineUserSubscription.class);
|
||||
|
||||
@Value("${application.node.id}")
|
||||
private String appNodeId;
|
||||
|
||||
|
||||
@Autowired
|
||||
private BrokerPublisher brokerPublisher;
|
||||
|
||||
@PostConstruct
|
||||
public void setup() {
|
||||
logger.info("ActiveMQ Subscription is setup successfully.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish Message into ActiveMQ
|
||||
*
|
||||
* @param j
|
||||
*/
|
||||
public void publish(final JsonObject j) {
|
||||
j.addProperty("node", appNodeId);
|
||||
brokerPublisher.send(Constants.INSTANT_MESSAGING_MQ_TOPIC_ONLINEUSER, j.toString(), true);
|
||||
|
||||
}
|
||||
|
||||
@JmsListener(destination = Constants.INSTANT_MESSAGING_MQ_TOPIC_ONLINEUSER, containerFactory = "jmsListenerContainerTopic")
|
||||
public void onMessage(final String payload){
|
||||
logger.info("[onMessage] payload {}", payload);
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject j = parser.parse(payload).getAsJsonObject();
|
||||
logger.debug("[instant messaging] message body {}", j.toString());
|
||||
try {
|
||||
NettyClients.getInstance().publishIMEventMessage(j.get("id").getAsString(),
|
||||
j.get("event").getAsString(),
|
||||
SerializeUtil.deserialize(j.get("data").getAsString()));
|
||||
} catch (Exception e) {
|
||||
logger.error("onMessage", e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, All rights reserved.
|
||||
* <https://www.chatopera.com>
|
||||
* This software and related documentation are provided under a license agreement containing
|
||||
* restrictions on use and disclosure and are protected by intellectual property laws.
|
||||
* Except as expressly permitted in your license agreement or allowed by law, you may not use,
|
||||
* copy, reproduce, translate, broadcast, modify, license, transmit, distribute, exhibit, perform,
|
||||
* publish, or display any part, in any form, or by any means. Reverse engineering, disassembly,
|
||||
* or decompilation of this software, unless required by law for interoperability, is prohibited.
|
||||
*/
|
||||
package com.chatopera.cc.activemq;
|
||||
|
||||
import com.chatopera.cc.config.conditions.CalloutBeanCondition;
|
||||
import com.chatopera.cc.persistence.interfaces.CalloutWireEvent;
|
||||
import com.chatopera.cc.schedule.CalloutWireTask;
|
||||
import com.chatopera.cc.basic.Constants;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.jms.annotation.JmsListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* FreeSWITCH
|
||||
*/
|
||||
@Component
|
||||
@Conditional(CalloutBeanCondition.class)
|
||||
public class PbxEventSubscription {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(PbxEventSubscription.class);
|
||||
|
||||
@PostConstruct
|
||||
public void setup() {
|
||||
logger.info("ActiveMQ Subscription is setup successfully.");
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private BrokerPublisher brokerPublisher;
|
||||
|
||||
@Autowired
|
||||
private CalloutWireTask callOutWireTask;
|
||||
|
||||
public void publish(final String dest, final String payload) {
|
||||
brokerPublisher.send(dest, payload);
|
||||
}
|
||||
|
||||
@JmsListener(destination = Constants.INSTANT_MESSAGING_MQ_QUEUE_PBX, containerFactory = "jmsListenerContainerQueue")
|
||||
public void onMessage(final String payload) {
|
||||
logger.info("[onMessage] payload {}", payload);
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject j = parser.parse(payload).getAsJsonObject();
|
||||
// validate message
|
||||
if (!(j.has("type")
|
||||
&& j.has("to")
|
||||
&& j.has("ops")
|
||||
&& j.has("channel")
|
||||
&& j.has("createtime"))) {
|
||||
logger.error(String.format("[callout wire] 接线数据格式不对, %s", payload));
|
||||
} else {
|
||||
try {
|
||||
CalloutWireEvent event = CalloutWireEvent.parse(j);
|
||||
switch (event.getEventType()) {
|
||||
case 1: // 自动外呼接通
|
||||
logger.info("[callout wire] 自动外呼接通 {}", j.toString());
|
||||
callOutWireTask.callOutConnect(event);
|
||||
break;
|
||||
case 2: // 自动外呼挂断
|
||||
logger.info("[callout wire] 自动外呼挂断 {}", j.toString());
|
||||
callOutWireTask.callOutDisconnect(event);
|
||||
break;
|
||||
case 3: // 自动外呼失败
|
||||
logger.info("[callout wire] 自动外呼失败 {}", j.toString());
|
||||
callOutWireTask.callOutFail(event);
|
||||
break;
|
||||
case 4: // 手动外呼接通
|
||||
logger.info("[callout wire] 手动外呼接通 {}", j.toString());
|
||||
callOutWireTask.callOutConnect(event);
|
||||
break;
|
||||
case 5: // 手动外呼挂断
|
||||
logger.info("[callout wire] 手动外呼挂断 {}", j.toString());
|
||||
callOutWireTask.callOutDisconnect(event);
|
||||
break;
|
||||
case 6: // 手动外呼失败
|
||||
logger.info("[callout wire] 手动外呼失败 {}", j.toString());
|
||||
callOutWireTask.callOutFail(event);
|
||||
break;
|
||||
case 7: // 呼入接通
|
||||
logger.info("[callin wire] 呼入接通 {}", j.toString());
|
||||
break;
|
||||
case 8: // 呼入挂断
|
||||
logger.info("[callin wire] 呼入挂断 {}", j.toString());
|
||||
break;
|
||||
case 9: // 呼入失败
|
||||
logger.info("[callin wire] 呼入失败 {}", j.toString());
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("[callout wire] ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.aggregation.filter;
|
||||
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.hazelcast.mapreduce.KeyPredicate;
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.model.UKefuCallOutNames;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class AgentCallOutFilter implements KeyPredicate<String>{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1236581634096258855L;
|
||||
private String orgi ;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public AgentCallOutFilter(String orgi){
|
||||
this.orgi = orgi ;
|
||||
}
|
||||
public boolean evaluate(String key) {
|
||||
UKefuCallOutNames ukefuCallOutNames = (UKefuCallOutNames) CacheHelper.getCallOutCacheBean().getCacheObject(key, orgi);
|
||||
return ukefuCallOutNames !=null && !StringUtils.isBlank(orgi) && orgi.equals(ukefuCallOutNames.getOrgi()) && MainContext.CallOutType.AGENT.toString().equals(ukefuCallOutNames.getCalltype());
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.aggregation.filter;
|
||||
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.model.AgentStatus;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.hazelcast.mapreduce.KeyPredicate;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class AgentStatusBusyOrgiFilter implements KeyPredicate<String>{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1236581634096258855L;
|
||||
private String orgi ;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public AgentStatusBusyOrgiFilter(String orgi){
|
||||
this.orgi = orgi ;
|
||||
}
|
||||
public boolean evaluate(String key) {
|
||||
AgentStatus agent = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(key, orgi);
|
||||
return agent!=null && !StringUtils.isBlank(orgi) && orgi.equals(agent.getOrgi()) && agent.isBusy();
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.aggregation.filter;
|
||||
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.model.AgentStatus;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.hazelcast.mapreduce.KeyPredicate;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class AgentStatusOrgiFilter implements KeyPredicate<String>{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1236581634096258855L;
|
||||
private String orgi ;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public AgentStatusOrgiFilter(String orgi){
|
||||
this.orgi = orgi ;
|
||||
}
|
||||
public boolean evaluate(String key) {
|
||||
AgentStatus agent = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(key, orgi);
|
||||
return agent!=null && !StringUtils.isBlank(orgi) && orgi.equals(agent.getOrgi());
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.aggregation.filter;
|
||||
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.model.AgentUser;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.hazelcast.mapreduce.KeyPredicate;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class AgentUserOrgiFilter implements KeyPredicate<String>{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1236581634096258855L;
|
||||
private String orgi ;
|
||||
private String status ;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public AgentUserOrgiFilter(String orgi , String status){
|
||||
this.orgi = orgi ;
|
||||
this.status = status ;
|
||||
}
|
||||
public boolean evaluate(String key) {
|
||||
AgentUser user = (AgentUser) CacheHelper
|
||||
.getAgentUserCacheBean().getCacheObject(key , orgi);
|
||||
return user!=null && user.getStatus()!=null && !StringUtils.isBlank(orgi) && orgi.equals(user.getOrgi()) && user.getStatus()!=null && user.getStatus().equals(status);
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.aggregation.filter;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.model.UKefuCallOutNames;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.hazelcast.mapreduce.KeyPredicate;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class AiCallOutFilter implements KeyPredicate<String>{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1236581634096258855L;
|
||||
private String orgi ;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public AiCallOutFilter(String orgi){
|
||||
this.orgi = orgi ;
|
||||
}
|
||||
public boolean evaluate(String key) {
|
||||
UKefuCallOutNames ukefuCallOutNames = (UKefuCallOutNames) CacheHelper.getCallOutCacheBean().getCacheObject(key, orgi);
|
||||
return ukefuCallOutNames !=null && !StringUtils.isBlank(orgi) && orgi.equals(ukefuCallOutNames.getOrgi()) && MainContext.CallOutType.AI.toString().equals(ukefuCallOutNames.getCalltype());
|
||||
}
|
||||
}
|
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.aop;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.cache.RedisCommand;
|
||||
import com.chatopera.cc.cache.RedisKey;
|
||||
import com.chatopera.cc.exception.CSKefuCacheException;
|
||||
import com.chatopera.cc.model.AgentUser;
|
||||
import com.chatopera.cc.model.AgentUserAudit;
|
||||
import com.chatopera.cc.proxy.AgentAuditProxy;
|
||||
import com.chatopera.cc.proxy.AgentUserProxy;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.After;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
public class AgentUserAspect {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(AgentUserAspect.class);
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@Autowired
|
||||
private RedisCommand redisCommand;
|
||||
|
||||
@Autowired
|
||||
private AgentAuditProxy agentAuditProxy;
|
||||
|
||||
@Before("execution(* com.chatopera.cc.persistence.repository.AgentUserRepository.save(..))")
|
||||
public void save(final JoinPoint joinPoint) {
|
||||
final AgentUser agentUser = (AgentUser) joinPoint.getArgs()[0];
|
||||
logger.info(
|
||||
"[save] agentUser id {}, agentno {}, userId {}", agentUser.getId(), agentUser.getAgentno(),
|
||||
agentUser.getUserid());
|
||||
|
||||
if (StringUtils.isBlank(agentUser.getId())
|
||||
|| StringUtils.isBlank(agentUser.getUserid())
|
||||
|| StringUtils.isBlank(agentUser.getAgentno())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 从缓存恢复之前的AgentUser
|
||||
final Optional<AgentUser> opt = cache.findOneAgentUserByUserIdAndOrgi(
|
||||
agentUser.getUserid(), agentUser.getOrgi());
|
||||
if (opt.isPresent()) {
|
||||
if (!StringUtils.equals(opt.get().getAgentno(), agentUser.getAgentno())) {
|
||||
// 发生了转接
|
||||
agentAuditProxy.updateAgentUserAudits(agentUser);
|
||||
}
|
||||
} else {
|
||||
// 新建AgentUser
|
||||
agentAuditProxy.updateAgentUserAudits(agentUser);
|
||||
}
|
||||
|
||||
// 同步缓存
|
||||
cache.putAgentUserByOrgi(agentUser, agentUser.getOrgi());
|
||||
}
|
||||
|
||||
@After("execution(* com.chatopera.cc.persistence.repository.AgentUserRepository.delete(..))")
|
||||
public void delete(final JoinPoint joinPoint) {
|
||||
final AgentUser agentUser = (AgentUser) joinPoint.getArgs()[0];
|
||||
logger.info(
|
||||
"[delete] agentUser id {}, agentno {}, userId {}", agentUser.getId(), agentUser.getAgentno(),
|
||||
agentUser.getUserid());
|
||||
cache.deleteAgentUserAuditByOrgiAndId(agentUser.getOrgi(), agentUser.getId());
|
||||
cache.deleteAgentUserByUserIdAndOrgi(agentUser.getUserid(), agentUser.getOrgi());
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新内存中的坐席与其服务的访客的集合
|
||||
*
|
||||
* @param joinPoint
|
||||
* @return
|
||||
* @throws Throwable
|
||||
*/
|
||||
@Around("@annotation(AgentUserAspect.LinkAgentUser)")
|
||||
public Object LinkAgentUser(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
final AgentUser updated = (AgentUser) joinPoint.getArgs()[0];
|
||||
final String orgi = (String) joinPoint.getArgs()[1];
|
||||
Object proceed = joinPoint.proceed(); // after things are done.
|
||||
logger.info(
|
||||
"[linkAgentUser] agentUser: status {}, userId {}, agentno {}, orgi {}", updated.getStatus(),
|
||||
updated.getUserid(), updated.getAgentno(), orgi);
|
||||
if (StringUtils.equals(updated.getStatus(), MainContext.AgentUserStatusEnum.END.toString())) {
|
||||
// 从集合中删除
|
||||
redisCommand.removeSetVal(
|
||||
RedisKey.getInServAgentUsersByAgentnoAndOrgi(updated.getAgentno(), orgi), updated.getUserid());
|
||||
} else if (StringUtils.equals(updated.getStatus(), MainContext.AgentUserStatusEnum.INSERVICE.toString())) {
|
||||
redisCommand.insertSetVal(
|
||||
RedisKey.getInServAgentUsersByAgentnoAndOrgi(updated.getAgentno(), orgi), updated.getUserid());
|
||||
} else if (StringUtils.equals(updated.getStatus(), MainContext.AgentUserStatusEnum.INQUENE.toString())) {
|
||||
logger.info("[linkAgentUser] ignored inque agent user, haven't resolve one agent yet.");
|
||||
} else {
|
||||
logger.warn("[linkAgentUser] unexpected condition.");
|
||||
}
|
||||
return proceed;
|
||||
}
|
||||
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface LinkAgentUser {
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.aop;
|
||||
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.model.BlackEntity;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.After;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
public class BlackEntityAspect {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(BlackEntityAspect.class);
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
@After("execution(* com.chatopera.cc.persistence.repository.BlackListRepository.save(..))")
|
||||
public void save(final JoinPoint joinPoint) {
|
||||
final BlackEntity blackEntity = (BlackEntity) joinPoint.getArgs()[0];
|
||||
logger.info("[save] blackEntity userId {}, orgi {}", blackEntity.getUserid(), blackEntity.getOrgi());
|
||||
cache.putBlackEntityByOrgi(blackEntity, blackEntity.getOrgi());
|
||||
}
|
||||
|
||||
@After("execution(* com.chatopera.cc.persistence.repository.BlackListRepository.delete(..))")
|
||||
public void delete(final JoinPoint joinPoint) {
|
||||
final BlackEntity blackEntity = (BlackEntity) joinPoint.getArgs()[0];
|
||||
logger.info("[delete] blackEntity userId {}, orgi {}", blackEntity.getUserid(), blackEntity.getOrgi());
|
||||
cache.deleteBlackEntityByUserIdAndOrgi(blackEntity.getUserid(), blackEntity.getOrgi());
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package com.chatopera.cc.aop;
|
||||
|
||||
import com.chatopera.cc.basic.MainContext;
|
||||
import com.chatopera.cc.cache.Cache;
|
||||
import com.chatopera.cc.model.OnlineUser;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.After;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Before;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
public class OnlineUserAspect {
|
||||
private final static Logger logger = LoggerFactory.getLogger(OnlineUserAspect.class);
|
||||
|
||||
@Autowired
|
||||
private Cache cache;
|
||||
|
||||
/**
|
||||
* 因为会定期从缓存序列化到数据库
|
||||
*
|
||||
* @param joinPoint
|
||||
*/
|
||||
@Before("execution(* com.chatopera.cc.persistence.repository.OnlineUserRepository.save(..))")
|
||||
public void save(final JoinPoint joinPoint) {
|
||||
final OnlineUser onlineUser = (OnlineUser) joinPoint.getArgs()[0];
|
||||
logger.info(
|
||||
"[save] put onlineUser id {}, status {}, invite status {}", onlineUser.getId(), onlineUser.getStatus(),
|
||||
onlineUser.getInvitestatus());
|
||||
if (StringUtils.isNotBlank(onlineUser.getStatus())) {
|
||||
switch (MainContext.OnlineUserStatusEnum.toValue(onlineUser.getStatus())) {
|
||||
case OFFLINE:
|
||||
cache.deleteOnlineUserByIdAndOrgi(onlineUser.getId(), onlineUser.getOrgi());
|
||||
break;
|
||||
default:
|
||||
cache.putOnlineUserByOrgi(onlineUser, onlineUser.getOrgi());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.aop;
|
||||
|
||||
import com.chatopera.cc.model.ESBean;
|
||||
import com.chatopera.cc.persistence.hibernate.BaseService;
|
||||
import com.chatopera.cc.util.CskefuList;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.hibernate.StaleStateException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
public class SyncDatabaseAspect {
|
||||
private final static Logger logger = LoggerFactory.getLogger(SyncDatabaseAspect.class);
|
||||
|
||||
@Autowired
|
||||
private BaseService<?> dbDataRes;
|
||||
|
||||
/**
|
||||
* 定义拦截规则:拦截org.springframework.data.elasticsearch.repository。
|
||||
*/
|
||||
@Pointcut("execution(* org.springframework.data.elasticsearch.repository.*.save(*))")
|
||||
public void syncSaveEsData() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 定义拦截规则:拦截org.springframework.data.elasticsearch.repository。
|
||||
*/
|
||||
@Pointcut("execution(* org.springframework.data.elasticsearch.repository.*.delete(*))")
|
||||
public void syncDeleteEsData() {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Around("syncSaveEsData()")
|
||||
public void syncSaveEsData(ProceedingJoinPoint pjp) throws Throwable {
|
||||
pjp.proceed();
|
||||
Object[] args = pjp.getArgs();
|
||||
if (args.length == 1) {
|
||||
Object data = args[0];
|
||||
if (data != null) {
|
||||
if (data instanceof CskefuList) {
|
||||
/** 只有一个地方用到,从ES同步数据到MySQL **/
|
||||
} else if (data instanceof List) {
|
||||
// TODO 批量建联系人操作会执行这段代码,此处会报错,但是批量更新可以通过
|
||||
dbDataRes.saveOrUpdateAll((List<Object>) data);
|
||||
} else {
|
||||
try {
|
||||
// 更新时,执行此代码,但是新建时会报错
|
||||
dbDataRes.saveOrUpdate(data);
|
||||
} catch (StaleStateException ex) {
|
||||
// 报错的情况下,执行此代码
|
||||
dbDataRes.save(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Around("syncDeleteEsData()")
|
||||
public void syncDeleteEsData(ProceedingJoinPoint pjp) throws Throwable {
|
||||
pjp.proceed();
|
||||
Object[] args = pjp.getArgs();
|
||||
if (args.length == 1) {
|
||||
Object data = args[0];
|
||||
if (data instanceof List) {
|
||||
dbDataRes.deleteAll((List<Object>) data);
|
||||
} else {
|
||||
if (data instanceof ESBean) {
|
||||
dbDataRes.delete(data);
|
||||
} else {
|
||||
dbDataRes.delete(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,837 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.algorithm;
|
||||
|
||||
import com.chatopera.cc.aggregation.filter.AgentStatusBusyOrgiFilter;
|
||||
import com.chatopera.cc.aggregation.filter.AgentStatusOrgiFilter;
|
||||
import com.chatopera.cc.aggregation.filter.AgentUserOrgiFilter;
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.basic.MainUtils;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.im.client.NettyClients;
|
||||
import com.chatopera.cc.app.im.router.OutMessageRouter;
|
||||
import com.chatopera.cc.app.model.*;
|
||||
import com.chatopera.cc.app.persistence.repository.*;
|
||||
import com.chatopera.cc.util.WebIMReport;
|
||||
import com.corundumstudio.socketio.SocketIONamespace;
|
||||
import com.hazelcast.core.IMap;
|
||||
import com.hazelcast.mapreduce.aggregation.Aggregations;
|
||||
import com.hazelcast.mapreduce.aggregation.Supplier;
|
||||
import com.hazelcast.query.PagingPredicate;
|
||||
import com.hazelcast.query.SqlPredicate;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
/**
|
||||
* Automatic Call Distribution
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class AutomaticServiceDist {
|
||||
private final static Logger logger = LoggerFactory.getLogger(AutomaticServiceDist.class);
|
||||
|
||||
/**
|
||||
* 载入坐席 ACD策略配置
|
||||
*
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public static SessionConfig initSessionConfig(String orgi) {
|
||||
SessionConfig sessionConfig = null;
|
||||
if (MainContext.getContext() != null && (sessionConfig = (SessionConfig) CacheHelper.getSystemCacheBean().getCacheObject(MainContext.SYSTEM_CACHE_SESSION_CONFIG + "_" + orgi, orgi)) == null) {
|
||||
SessionConfigRepository sessionConfigRes = MainContext.getContext().getBean(SessionConfigRepository.class);
|
||||
sessionConfig = sessionConfigRes.findByOrgi(orgi);
|
||||
if (sessionConfig == null) {
|
||||
sessionConfig = new SessionConfig();
|
||||
} else {
|
||||
CacheHelper.getSystemCacheBean().put(MainContext.SYSTEM_CACHE_SESSION_CONFIG + "_" + orgi, sessionConfig, orgi);
|
||||
}
|
||||
}
|
||||
return sessionConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 载入坐席 ACD策略配置
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<SessionConfig> initSessionConfigList() {
|
||||
List<SessionConfig> sessionConfigList = null;
|
||||
if (MainContext.getContext() != null && (sessionConfigList = (List<SessionConfig>) CacheHelper.getSystemCacheBean().getCacheObject(MainContext.SYSTEM_CACHE_SESSION_CONFIG_LIST, MainContext.SYSTEM_ORGI)) == null) {
|
||||
SessionConfigRepository sessionConfigRes = MainContext.getContext().getBean(SessionConfigRepository.class);
|
||||
sessionConfigList = sessionConfigRes.findAll();
|
||||
if (sessionConfigList != null && sessionConfigList.size() > 0) {
|
||||
CacheHelper.getSystemCacheBean().put(MainContext.SYSTEM_CACHE_SESSION_CONFIG_LIST, sessionConfigList, MainContext.SYSTEM_ORGI);
|
||||
}
|
||||
}
|
||||
return sessionConfigList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得 当前服务状态
|
||||
*
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public static AgentReport getAgentReport(String orgi) {
|
||||
/**
|
||||
* 统计当前在线的坐席数量
|
||||
*/
|
||||
AgentReport report = new AgentReport();
|
||||
IMap agentStatusMap = (IMap<String, Object>) CacheHelper.getAgentStatusCacheBean().getCache();
|
||||
AgentStatusOrgiFilter filter = new AgentStatusOrgiFilter(orgi);
|
||||
Long agents = (Long) agentStatusMap.aggregate(Supplier.fromKeyPredicate(filter), Aggregations.count());
|
||||
report.setAgents(agents.intValue());
|
||||
|
||||
Long busyAgent = (Long) agentStatusMap.aggregate(Supplier.fromKeyPredicate(new AgentStatusBusyOrgiFilter(orgi)), Aggregations.count());
|
||||
report.setBusy(busyAgent.intValue());
|
||||
report.setOrgi(orgi);
|
||||
|
||||
/**
|
||||
* 统计当前服务中的用户数量
|
||||
*/
|
||||
IMap agentUserMap = (IMap<String, Object>) CacheHelper.getAgentUserCacheBean().getCache();
|
||||
Long users = (Long) agentUserMap.aggregate(Supplier.fromKeyPredicate(new AgentUserOrgiFilter(orgi, MainContext.AgentUserStatusEnum.INSERVICE.toString())), Aggregations.count());
|
||||
report.setUsers(users.intValue());
|
||||
|
||||
Long queneUsers = (Long) agentUserMap.aggregate(Supplier.fromKeyPredicate(new AgentUserOrgiFilter(orgi, MainContext.AgentUserStatusEnum.INQUENE.toString())), Aggregations.count());
|
||||
report.setInquene(queneUsers.intValue());
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
public static int getQueneIndex(String userid, String orgi, long ordertime) {
|
||||
|
||||
// IList<AgentUser> queneUserList = (IList<AgentUser>) CacheHelper.getQueneUserCacheBean().getCache() ;
|
||||
int queneUsers = 0;
|
||||
// for(AgentUser agentUser : queneUserList){
|
||||
// if(agentUser.getOrgi().equals(orgi) && agentUser.getUserid().equals(userid)){
|
||||
// queneUsers ++ ;
|
||||
// }
|
||||
// }
|
||||
|
||||
return queneUsers;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static int getQueneIndex(String agent, String orgi, String skill) {
|
||||
|
||||
int queneUsers = 0;
|
||||
|
||||
PagingPredicate<String, AgentUser> pagingPredicate = null;
|
||||
if (StringUtils.isNotBlank(skill)) {
|
||||
pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inquene' AND skill = '" + skill + "' AND orgi = '" + orgi + "'"), 100);
|
||||
} else if (StringUtils.isNotBlank(agent)) {
|
||||
pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inquene' AND agent = '" + agent + "' AND orgi = '" + orgi + "'"), 100);
|
||||
} else {
|
||||
pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inquene' AND orgi = '" + orgi + "'"), 100);
|
||||
}
|
||||
queneUsers = ((IMap<String, AgentUser>) CacheHelper.getAgentUserCacheBean().getCache()).values(pagingPredicate).size();
|
||||
return queneUsers;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static int getAgentUsers(String agent, String orgi) {
|
||||
/**
|
||||
* agentno自动是 服务的坐席, agent 是请求的坐席
|
||||
*/
|
||||
PagingPredicate<String, AgentUser> pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inservice' AND agentno = '" + agent + "' AND orgi = '" + orgi + "'"), 100);
|
||||
List<AgentUser> agentUserList = new ArrayList<AgentUser>();
|
||||
agentUserList.addAll(((IMap<String, AgentUser>) CacheHelper.getAgentUserCacheBean().getCache()).values(pagingPredicate));
|
||||
return agentUserList.size();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<AgentStatus> getAgentStatus(String skill, String orgi) {
|
||||
PagingPredicate<String, AgentStatus> pagingPredicate = new PagingPredicate<String, AgentStatus>(new SqlPredicate("orgi = '" + orgi + "'"), 100);
|
||||
|
||||
if (StringUtils.isNotBlank(skill)) {
|
||||
pagingPredicate = new PagingPredicate<String, AgentStatus>(new SqlPredicate("skill = '" + skill + "' AND orgi = '" + orgi + "'"), 100);
|
||||
}
|
||||
List<AgentStatus> agentList = new ArrayList<AgentStatus>();
|
||||
agentList.addAll(((IMap<String, AgentStatus>) CacheHelper.getAgentStatusCacheBean().getCache()).values(pagingPredicate));
|
||||
return agentList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为坐席批量分配用户
|
||||
*
|
||||
* @param agentStatus
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void allotAgent(String agentno, String orgi) {
|
||||
AgentStatus agentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(agentno, orgi);
|
||||
List<AgentUser> agentStatusList = new ArrayList<AgentUser>();
|
||||
PagingPredicate<String, AgentUser> pagingPredicate = null;
|
||||
if (agentStatus != null && StringUtils.isNotBlank(agentStatus.getSkill())) {
|
||||
pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inquene' AND ((agent = null AND skill = null) OR (skill = '" + agentStatus.getSkill() + "' AND agent = null) OR agent = '" + agentno + "') AND orgi = '" + orgi + "'"), 10);
|
||||
} else {
|
||||
pagingPredicate = new PagingPredicate<String, AgentUser>(new SqlPredicate("status = 'inquene' AND ((agent = null AND skill = null) OR agent = '" + agentno + "') AND orgi = '" + orgi + "'"), 10);
|
||||
}
|
||||
agentStatusList.addAll(((IMap<String, AgentUser>) CacheHelper.getAgentUserCacheBean().getCache()).values(pagingPredicate));
|
||||
for (AgentUser agentUser : agentStatusList) {
|
||||
SessionConfig sessionConfig = AutomaticServiceDist.initSessionConfig(orgi);
|
||||
long maxusers = sessionConfig != null ? sessionConfig.getMaxuser() : MainContext.AGENT_STATUS_MAX_USER;
|
||||
if (agentStatus != null && agentStatus.getUsers() < maxusers) { //坐席未达到最大咨询访客数量
|
||||
CacheHelper.getAgentUserCacheBean().delete(agentUser.getUserid(), orgi); //从队列移除,进入正在处理的队列, 避免使用 分布式锁
|
||||
try {
|
||||
AgentService agentService = processAgentService(agentStatus, agentUser, orgi);
|
||||
|
||||
MessageOutContent outMessage = new MessageOutContent();
|
||||
outMessage.setMessage(AutomaticServiceDist.getSuccessMessage(agentService, agentUser.getChannel(), orgi));
|
||||
outMessage.setMessageType(MainContext.MediaTypeEnum.TEXT.toString());
|
||||
outMessage.setCalltype(MainContext.CallTypeEnum.IN.toString());
|
||||
outMessage.setNickName(agentStatus.getUsername());
|
||||
outMessage.setCreatetime(MainUtils.dateFormate.format(new Date()));
|
||||
|
||||
if (StringUtils.isNotBlank(agentUser.getUserid())) {
|
||||
OutMessageRouter router = null;
|
||||
router = (OutMessageRouter) MainContext.getContext().getBean(agentUser.getChannel());
|
||||
if (router != null) {
|
||||
router.handler(agentUser.getUserid(), MainContext.MessageTypeEnum.MESSAGE.toString(), agentUser.getAppid(), outMessage);
|
||||
}
|
||||
}
|
||||
// TODO #111 为坐席分配访客
|
||||
NettyClients.getInstance().publishAgentEventMessage(agentService.getAgentno(), MainContext.MessageTypeEnum.NEW.toString(), agentUser);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
publishMessage(orgi, "agent", "success", agentno);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为坐席批量分配用户
|
||||
*
|
||||
* @param agentStatus
|
||||
* @throws Exception
|
||||
*/
|
||||
public static void serviceFinish(AgentUser agentUser, String orgi) throws Exception {
|
||||
if (agentUser != null) {
|
||||
AgentStatus agentStatus = null;
|
||||
if (MainContext.AgentUserStatusEnum.INSERVICE.toString().equals(agentUser.getStatus()) && agentUser.getAgentno() != null) {
|
||||
agentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(agentUser.getAgentno(), orgi);
|
||||
}
|
||||
CacheHelper.getAgentUserCacheBean().delete(agentUser.getUserid(), orgi);
|
||||
|
||||
AgentUserRepository agentUserRepository = MainContext.getContext().getBean(AgentUserRepository.class);
|
||||
|
||||
AgentUser agentUseDataBean = agentUserRepository.findByIdAndOrgi(agentUser.getId(), agentUser.getOrgi());
|
||||
SessionConfig sessionConfig = AutomaticServiceDist.initSessionConfig(orgi);
|
||||
if (agentUseDataBean != null) {
|
||||
agentUseDataBean.setStatus(MainContext.AgentUserStatusEnum.END.toString());
|
||||
if (agentUser.getServicetime() != null) {
|
||||
agentUseDataBean.setSessiontimes(System.currentTimeMillis() - agentUser.getServicetime().getTime());
|
||||
}
|
||||
|
||||
agentUserRepository.save(agentUseDataBean);
|
||||
|
||||
/**
|
||||
* 更新OnlineUser对象,变更为服务中,不可邀请 , WebIM渠道专用
|
||||
*/
|
||||
if (MainContext.ChannelTypeEnum.WEBIM.toString().equals(agentUser.getChannel())) {
|
||||
OnlineUserRepository onlineUserRes = MainContext.getContext().getBean(OnlineUserRepository.class);
|
||||
List<OnlineUser> onlineUserList = onlineUserRes.findByUseridAndOrgi(agentUser.getUserid(), agentUser.getOrgi());
|
||||
if (onlineUserList.size() > 0) {
|
||||
OnlineUser onlineUser = onlineUserList.get(0);
|
||||
onlineUser.setInvitestatus(MainContext.OnlineUserInviteStatus.DEFAULT.toString());
|
||||
onlineUserRes.save(onlineUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final boolean isPhone = MainContext.ChannelTypeEnum.PHONE.toString().equals(agentUser.getChannel());
|
||||
AgentServiceRepository agentServiceRes = MainContext.getContext().getBean(AgentServiceRepository.class);
|
||||
AgentService service = null;
|
||||
if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) {
|
||||
service = agentServiceRes.findByIdAndOrgi(agentUser.getAgentserviceid(), agentUser.getOrgi());
|
||||
}
|
||||
if (service == null) {//当做留言处理
|
||||
service = processAgentService(agentStatus, agentUser, orgi, true);
|
||||
}
|
||||
if (service != null) {
|
||||
service.setStatus(MainContext.AgentUserStatusEnum.END.toString());
|
||||
service.setEndtime(new Date());
|
||||
if (service.getServicetime() != null) {
|
||||
service.setSessiontimes(System.currentTimeMillis() - service.getServicetime().getTime());
|
||||
}
|
||||
|
||||
AgentUserTaskRepository agentUserTaskRes = MainContext.getContext().getBean(AgentUserTaskRepository.class);
|
||||
List<AgentUserTask> agentUserTaskList = agentUserTaskRes.findByIdAndOrgi(agentUser.getId(), agentUser.getOrgi());
|
||||
if (agentUserTaskList.size() > 0) {
|
||||
AgentUserTask agentUserTask = agentUserTaskList.get(0);
|
||||
service.setAgentreplyinterval(agentUserTask.getAgentreplyinterval());
|
||||
service.setAgentreplytime(agentUserTask.getAgentreplytime());
|
||||
service.setAvgreplyinterval(agentUserTask.getAvgreplyinterval());
|
||||
service.setAvgreplytime(agentUserTask.getAvgreplytime());
|
||||
|
||||
service.setUserasks(agentUserTask.getUserasks());
|
||||
service.setAgentreplys(agentUserTask.getAgentreplys());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 启用了质检任务,开启质检
|
||||
*/
|
||||
if (sessionConfig.isQuality() && service.getUserasks() > 0) { //开启了质检,并且是有效对话
|
||||
service.setQualitystatus(MainContext.QualityStatus.NODIS.toString()); //未分配质检任务
|
||||
} else {
|
||||
service.setQualitystatus(MainContext.QualityStatus.NO.toString()); //未开启质检 或无效对话无需质检
|
||||
}
|
||||
agentServiceRes.save(service);
|
||||
}
|
||||
|
||||
if (isPhone) { // 语音渠道,强制发送
|
||||
NettyClients.getInstance().sendCalloutEventMessage(agentUser.getAgentno(), MainContext.MessageTypeEnum.END.toString(), agentUser);
|
||||
} else {
|
||||
if (agentStatus != null) // WebIM 查看用户状态
|
||||
// TODO #111 结束会话
|
||||
NettyClients.getInstance().publishAgentEventMessage(agentUser.getAgentno(), MainContext.MessageTypeEnum.END.toString(), agentUser);
|
||||
OutMessageRouter router = null;
|
||||
router = (OutMessageRouter) MainContext.getContext().getBean(agentUser.getChannel());
|
||||
if (router != null) {
|
||||
MessageOutContent outMessage = new MessageOutContent();
|
||||
outMessage.setMessage(AutomaticServiceDist.getServiceFinishMessage(agentUser.getChannel(), orgi));
|
||||
outMessage.setMessageType(MainContext.AgentUserStatusEnum.END.toString());
|
||||
outMessage.setCalltype(MainContext.CallTypeEnum.IN.toString());
|
||||
if (agentStatus != null) {
|
||||
outMessage.setNickName(agentStatus.getUsername());
|
||||
} else {
|
||||
outMessage.setNickName(agentUser.getUsername());
|
||||
}
|
||||
outMessage.setCreatetime(MainUtils.dateFormate.format(new Date()));
|
||||
outMessage.setAgentserviceid(agentUser.getAgentserviceid());
|
||||
|
||||
router.handler(agentUser.getUserid(), MainContext.MessageTypeEnum.STATUS.toString(), agentUser.getAppid(), outMessage);
|
||||
}
|
||||
}
|
||||
|
||||
if (agentStatus != null) {
|
||||
updateAgentStatus(agentStatus, agentUser, orgi, false);
|
||||
|
||||
long maxusers = sessionConfig != null ? sessionConfig.getMaxuser() : MainContext.AGENT_STATUS_MAX_USER;
|
||||
if (agentStatus.getUsers() < maxusers) {
|
||||
allotAgent(agentStatus.getAgentno(), orgi);
|
||||
}
|
||||
}
|
||||
publishMessage(orgi, "end", "success", agentUser != null ? agentUser.getId() : null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新坐席当前服务中的用户状态,需要分布式锁
|
||||
*
|
||||
* @param agentStatus
|
||||
* @param agentUser
|
||||
* @param orgi
|
||||
*/
|
||||
public synchronized static void updateAgentStatus(AgentStatus agentStatus, AgentUser agentUser, String orgi, boolean in) {
|
||||
int users = getAgentUsers(agentStatus.getAgentno(), orgi);
|
||||
Lock lock = CacheHelper.getAgentStatusCacheBean().getLock("LOCK", orgi);
|
||||
lock.lock();
|
||||
try {
|
||||
agentStatus.setUsers(users);
|
||||
agentStatus.setUpdatetime(new Date());
|
||||
CacheHelper.getAgentStatusCacheBean().put(agentStatus.getAgentno(), agentStatus, orgi);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public static void publishMessage(String orgi, String worktype, String workresult, String dataid) {
|
||||
/**
|
||||
* 坐席状态改变,通知监测服务
|
||||
*/
|
||||
AgentReport agentReport = AutomaticServiceDist.getAgentReport(orgi);
|
||||
AgentReportRepository agentReportRes = MainContext.getContext().getBean(AgentReportRepository.class);
|
||||
if (agentReportRes != null) {
|
||||
agentReport.setOrgi(orgi);
|
||||
agentReport.setWorktype(worktype);
|
||||
agentReport.setWorkresult(workresult);
|
||||
agentReport.setDataid(dataid);
|
||||
|
||||
agentReportRes.save(agentReport);
|
||||
}
|
||||
MainContext.getContext().getBean("agentNamespace", SocketIONamespace.class).getBroadcastOperations().sendEvent("status", agentReport);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param agent 坐席
|
||||
* @param skill 技能组
|
||||
* @param userid 用户ID
|
||||
* @param status 工作状态
|
||||
* @param worktype 类型 : 语音OR 文本
|
||||
* @param orgi
|
||||
* @param lasttime
|
||||
*/
|
||||
public static void recordAgentStatus(String agent, String username, String extno, String skill, boolean admin, String userid, String status, String current, String worktype, String orgi, Date lasttime) {
|
||||
WorkMonitorRepository workMonitorRes = MainContext.getContext().getBean(WorkMonitorRepository.class);
|
||||
WorkMonitor workMonitor = new WorkMonitor();
|
||||
if (StringUtils.isNotBlank(agent) && StringUtils.isNotBlank(status)) {
|
||||
workMonitor.setAgent(agent);
|
||||
workMonitor.setAgentno(agent);
|
||||
workMonitor.setStatus(status);
|
||||
workMonitor.setAdmin(admin);
|
||||
workMonitor.setUsername(username);
|
||||
workMonitor.setExtno(extno);
|
||||
workMonitor.setWorktype(worktype);
|
||||
if (lasttime != null) {
|
||||
workMonitor.setDuration((int) (System.currentTimeMillis() - lasttime.getTime()) / 1000);
|
||||
}
|
||||
if (status.equals(MainContext.AgentStatusEnum.BUSY.toString())) {
|
||||
workMonitor.setBusy(true);
|
||||
}
|
||||
if (status.equals(MainContext.AgentStatusEnum.READY.toString())) {
|
||||
int count = workMonitorRes.countByAgentAndDatestrAndStatusAndOrgi(agent, MainUtils.simpleDateFormat.format(new Date()), MainContext.AgentStatusEnum.READY.toString(), orgi);
|
||||
if (count == 0) {
|
||||
workMonitor.setFirsttime(true);
|
||||
}
|
||||
}
|
||||
if (current.equals(MainContext.AgentStatusEnum.NOTREADY.toString())) {
|
||||
List<WorkMonitor> workMonitorList = workMonitorRes.findByOrgiAndAgentAndDatestrAndFirsttime(orgi, agent, MainUtils.simpleDateFormat.format(new Date()), true);
|
||||
if (workMonitorList.size() > 0) {
|
||||
WorkMonitor firstWorkMonitor = workMonitorList.get(0);
|
||||
if (firstWorkMonitor.getFirsttimes() == 0) {
|
||||
firstWorkMonitor.setFirsttimes((int) (System.currentTimeMillis() - firstWorkMonitor.getCreatetime().getTime()));
|
||||
workMonitorRes.save(firstWorkMonitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
workMonitor.setCreatetime(new Date());
|
||||
workMonitor.setDatestr(MainUtils.simpleDateFormat.format(new Date()));
|
||||
|
||||
workMonitor.setName(agent);
|
||||
workMonitor.setOrgi(orgi);
|
||||
workMonitor.setSkill(skill);
|
||||
workMonitor.setUserid(userid);
|
||||
|
||||
workMonitorRes.save(workMonitor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 为用户分配坐席
|
||||
*
|
||||
* @param agentUser
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static AgentService allotAgent(AgentUser agentUser, String orgi) {
|
||||
/**
|
||||
* 查询条件,当前在线的 坐席,并且 未达到最大 服务人数的坐席
|
||||
*/
|
||||
|
||||
List<AgentStatus> agentStatusList = new ArrayList<AgentStatus>();
|
||||
PagingPredicate<String, AgentStatus> pagingPredicate = null;
|
||||
/**
|
||||
* 处理ACD 的 技能组请求和 坐席请求
|
||||
*/
|
||||
if (StringUtils.isNotBlank(agentUser.getAgent())) {
|
||||
pagingPredicate = new PagingPredicate<String, AgentStatus>(new SqlPredicate(" busy = false AND agentno = '" + agentUser.getAgent() + "' AND orgi = '" + orgi + "'"), 1);
|
||||
} else if (StringUtils.isNotBlank(agentUser.getSkill())) {
|
||||
pagingPredicate = new PagingPredicate<String, AgentStatus>(new SqlPredicate(" busy = false AND skill = '" + agentUser.getSkill() + "' AND orgi = '" + orgi + "'"), 1);
|
||||
} else {
|
||||
pagingPredicate = new PagingPredicate<String, AgentStatus>(new SqlPredicate(" busy = false AND orgi = '" + orgi + "'"), 1);
|
||||
}
|
||||
|
||||
agentStatusList.addAll(((IMap<String, AgentStatus>) CacheHelper.getAgentStatusCacheBean().getCache()).values(pagingPredicate));
|
||||
AgentStatus agentStatus = null;
|
||||
AgentService agentService = null; //放入缓存的对象
|
||||
if (agentStatusList.size() > 0) {
|
||||
agentStatus = agentStatusList.get(0);
|
||||
if (agentStatus.getUsers() >= initSessionConfig(orgi).getMaxuser()) {
|
||||
agentStatus = null;
|
||||
/**
|
||||
* 判断当前有多少人排队中 , 分三种情况:1、请求技能组的,2、请求坐席的,3,默认请求的
|
||||
*
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
try {
|
||||
agentService = processAgentService(agentStatus, agentUser, orgi);
|
||||
if (agentService.getStatus().equals(MainContext.AgentUserStatusEnum.INQUENE.toString())) {
|
||||
agentService.setQueneindex(getQueneIndex(agentUser.getAgent(), orgi, agentUser.getSkill()));
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
publishMessage(orgi, "user", agentService != null && agentService.getStatus().equals(MainContext.AgentUserStatusEnum.INSERVICE.toString()) ? "inservice" : "inquene", agentUser.getId());
|
||||
return agentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 邀请访客进入当前对话,如果当前操作的 坐席是已就绪状态,则直接加入到当前坐席的 对话列表中,如果未登录,则分配给其他坐席
|
||||
*
|
||||
* @param agentno
|
||||
* @param agentUser
|
||||
* @param orgi
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static AgentService allotAgentForInvite(String agentno, AgentUser agentUser, String orgi) throws Exception {
|
||||
AgentStatus agentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(agentno, orgi);
|
||||
AgentService agentService = null;
|
||||
if (agentStatus != null) {
|
||||
agentService = processAgentService(agentStatus, agentUser, orgi);
|
||||
publishMessage(orgi, "invite", "success", agentno);
|
||||
// TODO #111 为坐席分配邀请的访客
|
||||
NettyClients.getInstance().publishAgentEventMessage(agentService.getAgentno(), MainContext.MessageTypeEnum.NEW.toString(), agentUser);
|
||||
} else {
|
||||
agentService = allotAgent(agentUser, orgi);
|
||||
}
|
||||
return agentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为访客 分配坐席, ACD策略,此处 AgentStatus 是建议 的 坐席, 如果启用了 历史服务坐席 优先策略, 则会默认检查历史坐席是否空闲,如果空闲,则分配,如果不空闲,则 分配当前建议的坐席
|
||||
*
|
||||
* @param agentStatus
|
||||
* @param agentUser
|
||||
* @param orgi
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
private static AgentService processAgentService(AgentStatus agentStatus, AgentUser agentUser, String orgi) throws Exception {
|
||||
return processAgentService(agentStatus, agentUser, orgi, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为访客 分配坐席, ACD策略,此处 AgentStatus 是建议 的 坐席, 如果启用了 历史服务坐席 优先策略, 则会默认检查历史坐席是否空闲,如果空闲,则分配,如果不空闲,则 分配当前建议的坐席
|
||||
*
|
||||
* @param agentUser
|
||||
* @param orgi
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static AgentService processChatbotService(final String botName, final AgentUser agentUser, final String orgi) {
|
||||
AgentService agentService = new AgentService(); //放入缓存的对象
|
||||
AgentServiceRepository agentServiceRes = MainContext.getContext().getBean(AgentServiceRepository.class);
|
||||
Date now = new Date();
|
||||
if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) {
|
||||
agentService = agentServiceRes.findByIdAndOrgi(agentUser.getAgentserviceid(), orgi);
|
||||
agentService.setEndtime(now);
|
||||
if (agentService.getServicetime() != null) {
|
||||
agentService.setSessiontimes(System.currentTimeMillis() - agentService.getServicetime().getTime());
|
||||
}
|
||||
agentService.setStatus(MainContext.AgentUserStatusEnum.END.toString());
|
||||
} else {
|
||||
agentService.setServicetime(now);
|
||||
agentService.setLogindate(now);
|
||||
agentService.setOrgi(orgi);
|
||||
agentService.setOwner(agentUser.getContextid());
|
||||
agentService.setSessionid(agentUser.getSessionid());
|
||||
agentService.setRegion(agentUser.getRegion());
|
||||
agentService.setUsername(agentUser.getUsername());
|
||||
agentService.setChannel(agentUser.getChannel());
|
||||
if (botName != null)
|
||||
agentService.setAgentusername(botName);
|
||||
|
||||
if (StringUtils.isNotBlank(agentUser.getContextid())) {
|
||||
agentService.setContextid(agentUser.getContextid());
|
||||
} else {
|
||||
agentService.setContextid(agentUser.getSessionid());
|
||||
}
|
||||
|
||||
agentService.setUserid(agentUser.getUserid());
|
||||
agentService.setAiid(agentUser.getAgentno());
|
||||
agentService.setAiservice(true);
|
||||
agentService.setStatus(MainContext.AgentUserStatusEnum.INSERVICE.toString());
|
||||
|
||||
agentService.setAppid(agentUser.getAppid());
|
||||
agentService.setLeavemsg(false);
|
||||
}
|
||||
|
||||
agentServiceRes.save(agentService);
|
||||
return agentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* 为访客 分配坐席, ACD策略,此处 AgentStatus 是建议 的 坐席, 如果启用了 历史服务坐席 优先策略, 则会默认检查历史坐席是否空闲,如果空闲,则分配,如果不空闲,则 分配当前建议的坐席
|
||||
*
|
||||
* @param agentStatus
|
||||
* @param agentUser
|
||||
* @param orgi
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
private static AgentService processAgentService(AgentStatus agentStatus, AgentUser agentUser, String orgi, boolean finished) throws Exception {
|
||||
AgentService agentService = new AgentService(); //放入缓存的对象
|
||||
if (StringUtils.isNotBlank(agentUser.getAgentserviceid())) {
|
||||
agentService.setId(agentUser.getAgentserviceid());
|
||||
}
|
||||
agentService.setOrgi(orgi);
|
||||
|
||||
MainUtils.copyProperties(agentUser, agentService); //复制属性
|
||||
|
||||
agentService.setChannel(agentUser.getChannel());
|
||||
|
||||
agentService.setSessionid(agentUser.getSessionid());
|
||||
OnlineUserRepository onlineUserRes = MainContext.getContext().getBean(OnlineUserRepository.class);
|
||||
agentUser.setLogindate(new Date());
|
||||
List<OnlineUser> onlineUserList = onlineUserRes.findByUseridAndOrgi(agentUser.getUserid(), agentUser.getOrgi());
|
||||
OnlineUser onlineUser = null;
|
||||
if (onlineUserList.size() > 0) {
|
||||
onlineUser = onlineUserList.get(0);
|
||||
}
|
||||
|
||||
if (agentStatus != null) {
|
||||
SessionConfig sessionConfig = initSessionConfig(orgi);
|
||||
|
||||
agentService.setAgent(agentStatus.getAgentno());
|
||||
agentService.setSkill(agentUser.getSkill());
|
||||
|
||||
if (sessionConfig.isLastagent()) { //启用了历史坐席优先 , 查找 历史服务坐席
|
||||
List<WebIMReport> webIMaggList = MainUtils.getWebIMDataAgg(onlineUserRes.findByOrgiForDistinctAgent(orgi, agentUser.getUserid()));
|
||||
if (webIMaggList.size() > 0) {
|
||||
for (WebIMReport report : webIMaggList) {
|
||||
if (report.getData().equals(agentStatus.getAgentno())) {
|
||||
break;
|
||||
} else {
|
||||
AgentStatus hisAgentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(report.getData(), orgi);
|
||||
if (hisAgentStatus != null && hisAgentStatus.getUsers() < hisAgentStatus.getMaxusers()) {
|
||||
agentStatus = hisAgentStatus; //变更为 历史服务坐席
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
agentUser.setStatus(MainContext.AgentUserStatusEnum.INSERVICE.toString());
|
||||
agentService.setStatus(MainContext.AgentUserStatusEnum.INSERVICE.toString());
|
||||
|
||||
agentService.setSessiontype(MainContext.AgentUserStatusEnum.INSERVICE.toString());
|
||||
|
||||
agentService.setAgentno(agentStatus.getUserid());
|
||||
agentService.setAgentusername(agentStatus.getUsername()); //agent
|
||||
} else {
|
||||
if (finished == true) {
|
||||
agentUser.setStatus(MainContext.AgentUserStatusEnum.END.toString());
|
||||
agentService.setStatus(MainContext.AgentUserStatusEnum.END.toString());
|
||||
agentService.setSessiontype(MainContext.AgentUserStatusEnum.END.toString());
|
||||
if (agentStatus == null) {
|
||||
agentService.setLeavemsg(true); //是留言
|
||||
agentService.setLeavemsgstatus(MainContext.LeaveMsgStatus.NOTPROCESS.toString()); //未处理的留言
|
||||
}
|
||||
} else {
|
||||
agentUser.setStatus(MainContext.AgentUserStatusEnum.INQUENE.toString());
|
||||
agentService.setStatus(MainContext.AgentUserStatusEnum.INQUENE.toString());
|
||||
|
||||
agentService.setSessiontype(MainContext.AgentUserStatusEnum.INQUENE.toString());
|
||||
}
|
||||
}
|
||||
if (finished || agentStatus != null) {
|
||||
// agentService.setId(null);
|
||||
|
||||
agentService.setAgentuserid(agentUser.getId());
|
||||
|
||||
agentService.setInitiator(MainContext.ChatInitiatorType.USER.toString());
|
||||
|
||||
long waittingtime = 0;
|
||||
if (agentUser.getWaittingtimestart() != null) {
|
||||
waittingtime = System.currentTimeMillis() - agentUser.getWaittingtimestart().getTime();
|
||||
} else if (agentUser.getCreatetime() != null) {
|
||||
waittingtime = System.currentTimeMillis() - agentUser.getCreatetime().getTime();
|
||||
}
|
||||
agentUser.setWaittingtime((int) waittingtime);
|
||||
|
||||
agentUser.setServicetime(new Date());
|
||||
|
||||
agentService.setOwner(agentUser.getOwner());
|
||||
|
||||
agentService.setTimes(0);
|
||||
agentUser.setAgentno(agentService.getAgentno());
|
||||
|
||||
AgentServiceRepository agentServiceRes = MainContext.getContext().getBean(AgentServiceRepository.class);
|
||||
|
||||
if (StringUtils.isNotBlank(agentUser.getName())) {
|
||||
agentService.setName(agentUser.getName());
|
||||
}
|
||||
if (StringUtils.isNotBlank(agentUser.getPhone())) {
|
||||
agentService.setPhone(agentUser.getPhone());
|
||||
}
|
||||
if (StringUtils.isNotBlank(agentUser.getEmail())) {
|
||||
agentService.setEmail(agentUser.getEmail());
|
||||
}
|
||||
if (StringUtils.isNotBlank(agentUser.getResion())) {
|
||||
agentService.setResion(agentUser.getResion());
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(agentUser.getSkill())) {
|
||||
agentService.setAgentskill(agentUser.getSkill());
|
||||
} else if (agentStatus != null) {
|
||||
agentService.setAgentskill(agentStatus.getSkill());
|
||||
}
|
||||
|
||||
agentService.setServicetime(new Date());
|
||||
if (agentUser.getCreatetime() != null) {
|
||||
agentService.setWaittingtime((int) (System.currentTimeMillis() - agentUser.getCreatetime().getTime()));
|
||||
agentUser.setWaittingtime(agentService.getWaittingtime());
|
||||
}
|
||||
if (onlineUser != null) {
|
||||
agentService.setOsname(onlineUser.getOpersystem());
|
||||
agentService.setBrowser(onlineUser.getBrowser());
|
||||
agentService.setDataid(onlineUser.getId()); //记录 onlineuser 的id
|
||||
}
|
||||
agentService.setLogindate(agentUser.getCreatetime());
|
||||
agentServiceRes.save(agentService);
|
||||
agentUser.setAgentserviceid(agentService.getId());
|
||||
agentUser.setLastgetmessage(new Date());
|
||||
agentUser.setLastmessage(new Date());
|
||||
}
|
||||
|
||||
agentService.setDataid(agentUser.getId());
|
||||
/**
|
||||
* 分配成功以后, 将用户 和坐席的对应关系放入到 缓存
|
||||
*/
|
||||
/**
|
||||
* 将 AgentUser 放入到 当前坐席的 服务队列
|
||||
*/
|
||||
AgentUserRepository agentUserRepository = MainContext.getContext().getBean(AgentUserRepository.class);
|
||||
|
||||
/**
|
||||
* 更新OnlineUser对象,变更为服务中,不可邀请
|
||||
*/
|
||||
|
||||
if (onlineUser != null) {
|
||||
onlineUser.setInvitestatus(MainContext.OnlineUserInviteStatus.INSERV.toString());
|
||||
onlineUserRes.save(onlineUser);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
agentUserRepository.save(agentUser);
|
||||
|
||||
CacheHelper.getAgentUserCacheBean().put(agentUser.getUserid(), agentUser, MainContext.SYSTEM_ORGI);
|
||||
|
||||
if (agentStatus != null) {
|
||||
updateAgentStatus(agentStatus, agentUser, orgi, true);
|
||||
}
|
||||
|
||||
return agentService;
|
||||
}
|
||||
|
||||
public static AgentUser deleteAgentUser(AgentUser agentUser, String orgi)
|
||||
throws Exception {
|
||||
if (agentUser != null) {
|
||||
if (!MainContext.AgentUserStatusEnum.END.toString().equals(
|
||||
agentUser.getStatus())) {
|
||||
serviceFinish(agentUser, orgi);
|
||||
}
|
||||
if (StringUtils.isNotBlank(agentUser.getId())) {
|
||||
AgentUserRepository agentUserRes = MainContext.getContext().getBean(AgentUserRepository.class);
|
||||
agentUser = agentUserRes.findByIdAndOrgi(agentUser.getId(), orgi);
|
||||
if (agentUser != null) {
|
||||
agentUserRes.delete(agentUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
return agentUser;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param agentStatus
|
||||
* @return
|
||||
*/
|
||||
public static String getSuccessMessage(AgentService agentService, String channel, String orgi) {
|
||||
String queneTip = "<span id='agentno'>" + agentService.getAgentusername() + "</span>";
|
||||
if (!MainContext.ChannelTypeEnum.WEBIM.toString().equals(channel)) {
|
||||
queneTip = agentService.getAgentusername();
|
||||
}
|
||||
SessionConfig sessionConfig = initSessionConfig(orgi);
|
||||
String successMsg = "坐席分配成功," + queneTip + "为您服务。";
|
||||
if (StringUtils.isNotBlank(sessionConfig.getSuccessmsg())) {
|
||||
successMsg = sessionConfig.getSuccessmsg().replaceAll("\\{agent\\}", queneTip);
|
||||
}
|
||||
return successMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param agentStatus
|
||||
* @return
|
||||
*/
|
||||
public static String getServiceFinishMessage(String channel, String orgi) {
|
||||
SessionConfig sessionConfig = initSessionConfig(orgi);
|
||||
String queneTip = "坐席已断开和您的对话";
|
||||
if (StringUtils.isNotBlank(sessionConfig.getFinessmsg())) {
|
||||
queneTip = sessionConfig.getFinessmsg();
|
||||
}
|
||||
return queneTip;
|
||||
}
|
||||
|
||||
public static String getNoAgentMessage(int queneIndex, String channel, String orgi) {
|
||||
if (queneIndex < 0) {
|
||||
queneIndex = 0;
|
||||
}
|
||||
String queneTip = "<span id='queneindex'>" + queneIndex + "</span>";
|
||||
if (!MainContext.ChannelTypeEnum.WEBIM.toString().equals(channel)) {
|
||||
queneTip = String.valueOf(queneIndex);
|
||||
}
|
||||
SessionConfig sessionConfig = initSessionConfig(orgi);
|
||||
String noAgentTipMsg = "坐席全忙,已进入等待队列,您也可以在其他时间再来咨询。";
|
||||
if (StringUtils.isNotBlank(sessionConfig.getNoagentmsg())) {
|
||||
noAgentTipMsg = sessionConfig.getNoagentmsg().replaceAll("\\{num\\}", queneTip);
|
||||
}
|
||||
return noAgentTipMsg;
|
||||
}
|
||||
|
||||
public static String getQueneMessage(int queneIndex, String channel, String orgi) {
|
||||
|
||||
String queneTip = "<span id='queneindex'>" + queneIndex + "</span>";
|
||||
if (!MainContext.ChannelTypeEnum.WEBIM.toString().equals(channel)) {
|
||||
queneTip = String.valueOf(queneIndex);
|
||||
}
|
||||
SessionConfig sessionConfig = initSessionConfig(orgi);
|
||||
String agentBusyTipMsg = "正在排队,请稍候,在您之前,还有 " + queneTip + " 位等待用户。";
|
||||
if (StringUtils.isNotBlank(sessionConfig.getAgentbusymsg())) {
|
||||
agentBusyTipMsg = sessionConfig.getAgentbusymsg().replaceAll("\\{num\\}", queneTip);
|
||||
}
|
||||
return agentBusyTipMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* 坐席离线
|
||||
*
|
||||
* @param userid
|
||||
* @param status
|
||||
*/
|
||||
public static void deleteAgentStatus(String userid, String orgi, boolean isAdmin) {
|
||||
AgentStatusRepository agentStatusRes = MainContext.getContext().getBean(AgentStatusRepository.class);
|
||||
List<AgentStatus> agentStatusList = agentStatusRes.findByAgentnoAndOrgi(userid, orgi);
|
||||
for (AgentStatus agentStatus : agentStatusList) {
|
||||
AutomaticServiceDist.recordAgentStatus(agentStatus.getAgentno(), agentStatus.getUsername(), agentStatus.getAgentno(), agentStatus.getSkill(), isAdmin, agentStatus.getAgentno(), agentStatus.isBusy() ? MainContext.AgentStatusEnum.BUSY.toString() : MainContext.AgentStatusEnum.NOTREADY.toString(), MainContext.AgentStatusEnum.NOTREADY.toString(), MainContext.AgentWorkType.MEIDIACHAT.toString(), agentStatus.getOrgi(), agentStatus.getUpdatetime());
|
||||
agentStatusRes.delete(agentStatus);
|
||||
}
|
||||
CacheHelper.getAgentStatusCacheBean().delete(userid, orgi);
|
||||
AutomaticServiceDist.publishMessage(orgi, "agent", "leave", userid);
|
||||
}
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.basic.aop;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.basic.MainUtils;
|
||||
import com.chatopera.cc.util.UKeFuList;
|
||||
import com.chatopera.cc.concurrent.multiupdate.MultiUpdateEvent;
|
||||
import com.chatopera.cc.app.persistence.hibernate.BaseService;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.chatopera.cc.app.model.ESBean;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
public class SyncDatabaseExt {
|
||||
|
||||
@Autowired
|
||||
private BaseService<?> dbDataRes ;
|
||||
/**
|
||||
* 定义拦截规则:拦截org.springframework.data.elasticsearch.repository。
|
||||
*/
|
||||
@Pointcut("execution(* org.springframework.data.elasticsearch.repository.*.save(*))")
|
||||
public void syncSaveEsData(){}
|
||||
|
||||
/**
|
||||
* 定义拦截规则:拦截org.springframework.data.elasticsearch.repository。
|
||||
*/
|
||||
@Pointcut("execution(* org.springframework.data.elasticsearch.repository.*.delete(*))")
|
||||
public void syncDeleteEsData(){}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Around("syncSaveEsData()")
|
||||
public Object syncSaveEsData(ProceedingJoinPoint pjp) throws Throwable{
|
||||
Object[] args = pjp.getArgs() ;
|
||||
if(args.length == 1){
|
||||
Object data = args[0] ;
|
||||
if(data!=null){
|
||||
if(data instanceof UKeFuList){
|
||||
/**只有一个地方用到,从DB同步数据到ES**/
|
||||
}else if(data instanceof List){
|
||||
List<Object> dataList = (List<Object>)data ;
|
||||
for(Object dbData : dataList){
|
||||
MainUtils.multiupdate(new MultiUpdateEvent<Object>(dbData , dbDataRes, MainContext.MultiUpdateType.SAVE.toString()));
|
||||
}
|
||||
}else{
|
||||
MainUtils.multiupdate(new MultiUpdateEvent<Object>(data, dbDataRes, MainContext.MultiUpdateType.SAVE.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return pjp.proceed();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Around("syncDeleteEsData()")
|
||||
public Object syncDeleteEsData(ProceedingJoinPoint pjp) throws Throwable{
|
||||
Object[] args = pjp.getArgs() ;
|
||||
if(args.length == 1){
|
||||
Object data = args[0] ;
|
||||
if(data instanceof List){
|
||||
List<Object> dataList = (List<Object>)data ;
|
||||
for(Object dbData : dataList){
|
||||
MainUtils.multiupdate(new MultiUpdateEvent<Object>(dbData , dbDataRes, MainContext.MultiUpdateType.DELETE.toString()));
|
||||
}
|
||||
}else{
|
||||
if(data instanceof ESBean){
|
||||
MainUtils.multiupdate(new MultiUpdateEvent<Object>(data, dbDataRes, MainContext.MultiUpdateType.DELETE.toString()));
|
||||
}else{
|
||||
MainUtils.multiupdate(new MultiUpdateEvent<Object>(data, dbDataRes, MainContext.MultiUpdateType.DELETE.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return pjp.proceed();
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.cache;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import com.hazelcast.com.eclipsesource.json.JsonObject;
|
||||
|
||||
public interface CacheBean {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void put(String key , Object value , String orgi) ;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public void clear(String orgi);
|
||||
|
||||
|
||||
public Object delete(String key , String orgi) ;
|
||||
|
||||
public void update(String key , String orgi , Object object) ;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param key
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public Object getCacheObject(String key, String orgi) ;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param key
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public Object getCacheObject(String key, String orgi,Object defaultValue) ;
|
||||
|
||||
/**
|
||||
* 获取所有缓存对象
|
||||
* @param orgi
|
||||
* @return
|
||||
*/
|
||||
public Collection<?> getAllCacheObject(String orgi) ;
|
||||
|
||||
|
||||
public CacheBean getCacheInstance(String cacheName);
|
||||
|
||||
public Object getCache();
|
||||
|
||||
public JsonObject getStatics();
|
||||
|
||||
public Lock getLock(String lock, String orgi);
|
||||
|
||||
public long getSize();
|
||||
|
||||
public long getAtomicLong(String cacheName) ;
|
||||
|
||||
public void setAtomicLong(String cacheName , long start) ; //初始化 发号器
|
||||
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.cache;
|
||||
|
||||
import com.chatopera.cc.app.cache.hazelcast.HazlcastCacheHelper;
|
||||
|
||||
public class CacheHelper {
|
||||
private static CacheHelper instance = new CacheHelper();
|
||||
|
||||
/**
|
||||
* 获取缓存实例
|
||||
*/
|
||||
public static CacheHelper getInstance(){
|
||||
return instance ;
|
||||
}
|
||||
private static CacheInstance cacheInstance = new HazlcastCacheHelper();
|
||||
|
||||
public static CacheBean getAgentStatusCacheBean() {
|
||||
return cacheInstance!=null ? cacheInstance.getAgentStatusCacheBean() : null;
|
||||
}
|
||||
public static CacheBean getAgentUserCacheBean() {
|
||||
return cacheInstance!=null ? cacheInstance.getAgentUserCacheBean() : null ;
|
||||
}
|
||||
public static CacheBean getOnlineUserCacheBean() {
|
||||
return cacheInstance!=null ? cacheInstance.getOnlineCacheBean() : null;
|
||||
}
|
||||
public static CacheBean getSystemCacheBean() {
|
||||
return cacheInstance!=null ? cacheInstance.getSystemCacheBean() : null ;
|
||||
}
|
||||
|
||||
public static CacheBean getIMRCacheBean() {
|
||||
return cacheInstance!=null ? cacheInstance.getIMRCacheBean() : null ;
|
||||
}
|
||||
public static CacheBean getCallCenterCacheBean() {
|
||||
return cacheInstance!=null ? cacheInstance.getCallCenterCacheBean() : null ;
|
||||
}
|
||||
public static CacheBean getCallCenterAgentCacheBean() {
|
||||
return cacheInstance!=null ? cacheInstance.getCallCenterAgentCacheBean() : null ;
|
||||
}
|
||||
public static CacheBean getApiUserCacheBean() {
|
||||
return cacheInstance!=null ? cacheInstance.getApiUserCacheBean() : null ;
|
||||
}
|
||||
public static CacheBean getJobCacheBean() {
|
||||
return cacheInstance!=null ? cacheInstance.getJobCacheBean(): null ;
|
||||
}
|
||||
public static CacheBean getCallOutCacheBean() {
|
||||
return cacheInstance!=null ? cacheInstance.getCallOutCacheBean(): null ;
|
||||
}
|
||||
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.cache;
|
||||
|
||||
|
||||
public interface CacheInstance {
|
||||
/**
|
||||
* 坐席状态
|
||||
* @return
|
||||
*/
|
||||
public CacheBean getAgentStatusCacheBean() ;
|
||||
|
||||
|
||||
/**
|
||||
* 服务中用户
|
||||
* @return
|
||||
*/
|
||||
public CacheBean getAgentUserCacheBean();
|
||||
|
||||
|
||||
/**
|
||||
* 在线用户
|
||||
* @return
|
||||
*/
|
||||
public CacheBean getOnlineCacheBean();
|
||||
|
||||
/**
|
||||
* 系统缓存
|
||||
* @return
|
||||
*/
|
||||
public CacheBean getSystemCacheBean();
|
||||
|
||||
|
||||
/**
|
||||
* IMR指令
|
||||
* @return
|
||||
*/
|
||||
public CacheBean getIMRCacheBean();
|
||||
|
||||
/**
|
||||
* IMR指令
|
||||
* @return
|
||||
*/
|
||||
public CacheBean getCallCenterCacheBean();
|
||||
|
||||
/**
|
||||
* IMR指令
|
||||
* @return
|
||||
*/
|
||||
public CacheBean getCallCenterAgentCacheBean();
|
||||
|
||||
/**
|
||||
* IMR指令
|
||||
* @return
|
||||
*/
|
||||
public CacheBean getApiUserCacheBean();
|
||||
|
||||
/**
|
||||
* IMR指令
|
||||
* @return
|
||||
*/
|
||||
public CacheBean getJobCacheBean();
|
||||
|
||||
/**
|
||||
* 外呼
|
||||
* @return
|
||||
*/
|
||||
public CacheBean getCallOutCacheBean();
|
||||
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.cache.hazelcast;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.cache.CacheBean;
|
||||
import com.chatopera.cc.app.cache.CacheInstance;
|
||||
import com.chatopera.cc.app.cache.hazelcast.impl.AgentStatusCache;
|
||||
import com.chatopera.cc.app.cache.hazelcast.impl.AgentUserCache;
|
||||
import com.chatopera.cc.app.cache.hazelcast.impl.ApiUserCache;
|
||||
import com.chatopera.cc.app.cache.hazelcast.impl.CallCenterCache;
|
||||
import com.chatopera.cc.app.cache.hazelcast.impl.JobCache;
|
||||
import com.chatopera.cc.app.cache.hazelcast.impl.MultiCache;
|
||||
import com.chatopera.cc.app.cache.hazelcast.impl.OnlineCache;
|
||||
import com.chatopera.cc.app.cache.hazelcast.impl.SystemCache;
|
||||
/**
|
||||
* Hazlcast缓存处理实例类
|
||||
* @author admin
|
||||
*
|
||||
*/
|
||||
public class HazlcastCacheHelper implements CacheInstance {
|
||||
/**
|
||||
* 服务类型枚举
|
||||
* @author admin
|
||||
*
|
||||
*/
|
||||
public enum CacheServiceEnum{
|
||||
HAZLCAST_CLUSTER_AGENT_USER_CACHE, HAZLCAST_CLUSTER_AGENT_STATUS_CACHE, HAZLCAST_CLUSTER_QUENE_USER_CACHE,HAZLCAST_ONLINE_CACHE , HAZLCAST_CULUSTER_SYSTEM , HAZLCAST_IMR_CACHE , API_USER_CACHE , CALLCENTER_CURRENT_CALL ,CALLCENTER_AGENT,JOB_CACHE,HAZLCAST_CALLOUT_CACHE;
|
||||
public String toString(){
|
||||
return super.toString().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheBean getAgentStatusCacheBean() {
|
||||
// TODO Auto-generated method stub
|
||||
return MainContext.getContext().getBean(AgentStatusCache.class).getCacheInstance(CacheServiceEnum.HAZLCAST_CLUSTER_AGENT_STATUS_CACHE.toString()) ;
|
||||
}
|
||||
@Override
|
||||
public CacheBean getAgentUserCacheBean() {
|
||||
// TODO Auto-generated method stub
|
||||
return MainContext.getContext().getBean(AgentUserCache.class).getCacheInstance(CacheServiceEnum.HAZLCAST_CLUSTER_QUENE_USER_CACHE.toString()) ;
|
||||
}
|
||||
@Override
|
||||
public CacheBean getOnlineCacheBean() {
|
||||
return MainContext.getContext().getBean(OnlineCache.class).getCacheInstance(CacheServiceEnum.HAZLCAST_ONLINE_CACHE.toString()) ;
|
||||
}
|
||||
@Override
|
||||
public CacheBean getSystemCacheBean() {
|
||||
return MainContext.getContext().getBean(SystemCache.class).getCacheInstance(CacheServiceEnum.HAZLCAST_CULUSTER_SYSTEM.toString()) ;
|
||||
}
|
||||
@Override
|
||||
public CacheBean getIMRCacheBean() {
|
||||
return MainContext.getContext().getBean(MultiCache.class).getCacheInstance(CacheServiceEnum.HAZLCAST_IMR_CACHE.toString()) ;
|
||||
}
|
||||
@Override
|
||||
public CacheBean getCallCenterCacheBean() {
|
||||
return MainContext.getContext().getBean(CallCenterCache.class).getCacheInstance(CacheServiceEnum.CALLCENTER_CURRENT_CALL.toString()) ;
|
||||
}
|
||||
@Override
|
||||
public CacheBean getCallCenterAgentCacheBean() {
|
||||
return MainContext.getContext().getBean(CallCenterCache.class).getCacheInstance(CacheServiceEnum.CALLCENTER_AGENT.toString()) ;
|
||||
}
|
||||
@Override
|
||||
public CacheBean getApiUserCacheBean() {
|
||||
return MainContext.getContext().getBean(ApiUserCache.class).getCacheInstance(CacheServiceEnum.API_USER_CACHE.toString()) ;
|
||||
}
|
||||
@Override
|
||||
public CacheBean getJobCacheBean() {
|
||||
return MainContext.getContext().getBean(JobCache.class).getCacheInstance(CacheServiceEnum.JOB_CACHE.toString()) ;
|
||||
}
|
||||
@Override
|
||||
public CacheBean getCallOutCacheBean() {
|
||||
// TODO Auto-generated method stub
|
||||
return MainContext.getContext().getBean(JobCache.class).getCacheInstance(CacheServiceEnum.HAZLCAST_CALLOUT_CACHE.toString()) ;
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.cache.hazelcast.impl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.hazelcast.com.eclipsesource.json.JsonObject;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.chatopera.cc.app.cache.CacheBean;
|
||||
|
||||
@Service("agentstatus_cache")
|
||||
public class AgentStatusCache implements CacheBean{
|
||||
|
||||
@Autowired
|
||||
public HazelcastInstance hazelcastInstance;
|
||||
|
||||
private String cacheName ;
|
||||
|
||||
public HazelcastInstance getInstance(){
|
||||
return hazelcastInstance ;
|
||||
}
|
||||
public CacheBean getCacheInstance(String cacheName){
|
||||
this.cacheName = cacheName ;
|
||||
return this ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String key, Object value, String orgi) {
|
||||
getInstance().getMap(getName()).put(key, value) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(String orgi) {
|
||||
getInstance().getMap(getName()).clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object delete(String key, String orgi) {
|
||||
return getInstance().getMap(getName()).remove(key) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(String key, String orgi, Object value) {
|
||||
getInstance().getMap(getName()).put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi) {
|
||||
return getInstance().getMap(getName()).get(key);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return cacheName ;
|
||||
}
|
||||
|
||||
// @Override
|
||||
public void service() throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<?> getAllCacheObject(String orgi) {
|
||||
return getInstance().getMap(getName()).keySet();
|
||||
}
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi, Object defaultValue) {
|
||||
return getCacheObject(key, orgi);
|
||||
}
|
||||
@Override
|
||||
public Object getCache() {
|
||||
return getInstance().getMap(cacheName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getLock(String lock , String orgi) {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getLock(lock);
|
||||
}
|
||||
@Override
|
||||
public long getSize() {
|
||||
return getInstance().getMap(getName()).size();
|
||||
}
|
||||
@Override
|
||||
public long getAtomicLong(String cacheName) {
|
||||
return getInstance().getAtomicLong(getName()).incrementAndGet();
|
||||
}
|
||||
@Override
|
||||
public void setAtomicLong(String cacheName, long start) {
|
||||
getInstance().getAtomicLong(getName()).set(start);
|
||||
}
|
||||
@Override
|
||||
public JsonObject getStatics() {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getMap(getName()).getLocalMapStats().toJson();
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.cache.hazelcast.impl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.hazelcast.com.eclipsesource.json.JsonObject;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.chatopera.cc.app.cache.CacheBean;
|
||||
|
||||
@Service("agentuser_cache")
|
||||
public class AgentUserCache implements CacheBean{
|
||||
|
||||
@Autowired
|
||||
public HazelcastInstance hazelcastInstance;
|
||||
|
||||
private String cacheName ;
|
||||
|
||||
public HazelcastInstance getInstance(){
|
||||
return hazelcastInstance ;
|
||||
}
|
||||
public CacheBean getCacheInstance(String cacheName){
|
||||
this.cacheName = cacheName ;
|
||||
return this ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String key, Object value, String orgi) {
|
||||
getInstance().getMap(getName()).put(key, value) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(String orgi) {
|
||||
getInstance().getMap(getName()).clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object delete(String key, String orgi) {
|
||||
return getInstance().getMap(getName()).remove(key) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(String key, String orgi, Object value) {
|
||||
getInstance().getMap(getName()).put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi) {
|
||||
return getInstance().getMap(getName()).get(key);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return cacheName ;
|
||||
}
|
||||
|
||||
// @Override
|
||||
public void service() throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<?> getAllCacheObject(String orgi) {
|
||||
return getInstance().getMap(getName()).keySet();
|
||||
}
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi, Object defaultValue) {
|
||||
return getCacheObject(key, orgi);
|
||||
}
|
||||
@Override
|
||||
public Object getCache() {
|
||||
return getInstance().getMap(cacheName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getLock(String lock , String orgi) {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getLock(lock);
|
||||
}
|
||||
@Override
|
||||
public long getSize() {
|
||||
return getInstance().getMap(getName()).size();
|
||||
}
|
||||
@Override
|
||||
public long getAtomicLong(String cacheName) {
|
||||
return getInstance().getAtomicLong(getName()).incrementAndGet();
|
||||
}
|
||||
@Override
|
||||
public void setAtomicLong(String cacheName, long start) {
|
||||
getInstance().getAtomicLong(getName()).set(start);
|
||||
}
|
||||
@Override
|
||||
public JsonObject getStatics() {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getMap(getName()).getLocalMapStats().toJson();
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.cache.hazelcast.impl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.hazelcast.com.eclipsesource.json.JsonObject;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.chatopera.cc.app.cache.CacheBean;
|
||||
|
||||
@Service("api_user_cache")
|
||||
public class ApiUserCache implements CacheBean{
|
||||
|
||||
@Autowired
|
||||
public HazelcastInstance hazelcastInstance;
|
||||
|
||||
private String cacheName ;
|
||||
|
||||
public HazelcastInstance getInstance(){
|
||||
return hazelcastInstance ;
|
||||
}
|
||||
public CacheBean getCacheInstance(String cacheName){
|
||||
this.cacheName = cacheName ;
|
||||
return this ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String key, Object value, String orgi) {
|
||||
getInstance().getMap(getName()).put(key, value) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(String orgi) {
|
||||
getInstance().getMap(getName()).clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object delete(String key, String orgi) {
|
||||
return getInstance().getMap(getName()).remove(key) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(String key, String orgi, Object value) {
|
||||
getInstance().getMap(getName()).put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi) {
|
||||
return getInstance().getMap(getName()).get(key);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return cacheName ;
|
||||
}
|
||||
|
||||
// @Override
|
||||
public void service() throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<?> getAllCacheObject(String orgi) {
|
||||
return getInstance().getMap(getName()).keySet();
|
||||
}
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi, Object defaultValue) {
|
||||
return getCacheObject(key, orgi);
|
||||
}
|
||||
@Override
|
||||
public Object getCache() {
|
||||
return getInstance().getMap(cacheName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getLock(String lock , String orgi) {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getLock(lock);
|
||||
}
|
||||
@Override
|
||||
public long getSize() {
|
||||
return getInstance().getMap(getName()).size();
|
||||
}
|
||||
@Override
|
||||
public long getAtomicLong(String cacheName) {
|
||||
return getInstance().getAtomicLong(getName()).incrementAndGet();
|
||||
}
|
||||
@Override
|
||||
public void setAtomicLong(String cacheName, long start) {
|
||||
getInstance().getAtomicLong(getName()).set(start);
|
||||
}
|
||||
@Override
|
||||
public JsonObject getStatics() {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getMap(getName()).getLocalMapStats().toJson();
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.cache.hazelcast.impl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.hazelcast.com.eclipsesource.json.JsonObject;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.chatopera.cc.app.cache.CacheBean;
|
||||
|
||||
@Service("callcenter_current_call")
|
||||
public class CallCenterCache implements CacheBean{
|
||||
|
||||
@Autowired
|
||||
public HazelcastInstance hazelcastInstance;
|
||||
|
||||
private String cacheName ;
|
||||
|
||||
public HazelcastInstance getInstance(){
|
||||
return hazelcastInstance ;
|
||||
}
|
||||
public CacheBean getCacheInstance(String cacheName){
|
||||
this.cacheName = cacheName ;
|
||||
return this ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String key, Object value, String orgi) {
|
||||
getInstance().getMap(getName()).put(key, value) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(String orgi) {
|
||||
getInstance().getMap(getName()).clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object delete(String key, String orgi) {
|
||||
return getInstance().getMap(getName()).remove(key) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(String key, String orgi, Object value) {
|
||||
getInstance().getMap(getName()).put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi) {
|
||||
return getInstance().getMap(getName()).get(key);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return cacheName ;
|
||||
}
|
||||
|
||||
// @Override
|
||||
public void service() throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<?> getAllCacheObject(String orgi) {
|
||||
return getInstance().getMap(getName()).keySet();
|
||||
}
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi, Object defaultValue) {
|
||||
return getCacheObject(key, orgi);
|
||||
}
|
||||
@Override
|
||||
public Object getCache() {
|
||||
return getInstance().getMap(cacheName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getLock(String lock , String orgi) {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getLock(lock);
|
||||
}
|
||||
@Override
|
||||
public long getSize() {
|
||||
return getInstance().getMap(getName()).size();
|
||||
}
|
||||
@Override
|
||||
public long getAtomicLong(String cacheName) {
|
||||
return getInstance().getAtomicLong(getName()).incrementAndGet();
|
||||
}
|
||||
@Override
|
||||
public void setAtomicLong(String cacheName, long start) {
|
||||
getInstance().getAtomicLong(getName()).set(start);
|
||||
}
|
||||
@Override
|
||||
public JsonObject getStatics() {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getMap(getName()).getLocalMapStats().toJson();
|
||||
}
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.cache.hazelcast.impl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.hazelcast.com.eclipsesource.json.JsonObject;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.chatopera.cc.app.cache.CacheBean;
|
||||
|
||||
@Service("job_cache")
|
||||
public class JobCache implements CacheBean{
|
||||
|
||||
@Autowired
|
||||
public HazelcastInstance hazelcastInstance;
|
||||
|
||||
private String cacheName ;
|
||||
|
||||
public HazelcastInstance getInstance(){
|
||||
return hazelcastInstance ;
|
||||
}
|
||||
public CacheBean getCacheInstance(String cacheName){
|
||||
this.cacheName = cacheName ;
|
||||
return this ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String key, Object value, String orgi) {
|
||||
getInstance().getMap(getName()).put(key, value) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(String orgi) {
|
||||
getInstance().getMap(getName()).clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object delete(String key, String orgi) {
|
||||
return getInstance().getMap(getName()).remove(key) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(String key, String orgi, Object value) {
|
||||
getInstance().getMap(getName()).put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi) {
|
||||
return getInstance().getMap(getName()).get(key);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return cacheName ;
|
||||
}
|
||||
|
||||
// @Override
|
||||
public void service() throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<?> getAllCacheObject(String orgi) {
|
||||
return getInstance().getMap(getName()).keySet();
|
||||
}
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi, Object defaultValue) {
|
||||
return getCacheObject(key, orgi);
|
||||
}
|
||||
@Override
|
||||
public Object getCache() {
|
||||
return getInstance().getMap(cacheName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getLock(String lock , String orgi) {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getLock(lock);
|
||||
}
|
||||
@Override
|
||||
public long getSize() {
|
||||
return getInstance().getMap(getName()).size();
|
||||
}
|
||||
@Override
|
||||
public long getAtomicLong(String cacheName) {
|
||||
return getInstance().getAtomicLong(getName()).incrementAndGet();
|
||||
}
|
||||
@Override
|
||||
public void setAtomicLong(String cacheName, long start) {
|
||||
getInstance().getAtomicLong(getName()).set(start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonObject getStatics() {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getMap(getName()).getLocalMapStats().toJson();
|
||||
}
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.cache.hazelcast.impl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import com.chatopera.cc.app.cache.CacheBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.hazelcast.com.eclipsesource.json.JsonObject;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
|
||||
@Service("multi_cache")
|
||||
public class MultiCache implements CacheBean {
|
||||
|
||||
@Autowired
|
||||
public HazelcastInstance hazelcastInstance;
|
||||
|
||||
private String cacheName ;
|
||||
|
||||
public HazelcastInstance getInstance(){
|
||||
return hazelcastInstance ;
|
||||
}
|
||||
public CacheBean getCacheInstance(String cacheName){
|
||||
this.cacheName = cacheName ;
|
||||
return this ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String key, Object value, String orgi) {
|
||||
getInstance().getMultiMap(getName()).put(key, value) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(String orgi) {
|
||||
getInstance().getMultiMap(getName()).clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object delete(String key, String orgi) {
|
||||
return getInstance().getMultiMap(getName()).remove(key) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(String key, String orgi, Object value) {
|
||||
getInstance().getMultiMap(getName()).put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi) {
|
||||
return getInstance().getMultiMap(getName()).get(key);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return cacheName ;
|
||||
}
|
||||
|
||||
// @Override
|
||||
public void service() throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<?> getAllCacheObject(String orgi) {
|
||||
return getInstance().getMultiMap(getName()).keySet();
|
||||
}
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi, Object defaultValue) {
|
||||
return getCacheObject(key, orgi);
|
||||
|
||||
}
|
||||
@Override
|
||||
public Object getCache() {
|
||||
return getInstance().getMultiMap(cacheName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getLock(String lock , String orgi) {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getLock(lock);
|
||||
}
|
||||
@Override
|
||||
public long getSize() {
|
||||
return getInstance().getMultiMap(getName()).size();
|
||||
}
|
||||
@Override
|
||||
public long getAtomicLong(String cacheName) {
|
||||
return getInstance().getAtomicLong(getName()).incrementAndGet();
|
||||
}
|
||||
@Override
|
||||
public void setAtomicLong(String cacheName, long start) {
|
||||
getInstance().getAtomicLong(getName()).set(start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonObject getStatics() {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getMultiMap(getName()).getLocalMultiMapStats().toJson();
|
||||
}
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.cache.hazelcast.impl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.hazelcast.com.eclipsesource.json.JsonObject;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
import com.chatopera.cc.app.cache.CacheBean;
|
||||
|
||||
@Service("online_cache")
|
||||
public class OnlineCache implements CacheBean{
|
||||
|
||||
@Autowired
|
||||
public HazelcastInstance hazelcastInstance;
|
||||
|
||||
private String cacheName ;
|
||||
|
||||
public HazelcastInstance getInstance(){
|
||||
return hazelcastInstance ;
|
||||
}
|
||||
public CacheBean getCacheInstance(String cacheName){
|
||||
this.cacheName = cacheName ;
|
||||
return this ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String key, Object value, String orgi) {
|
||||
getInstance().getMap(getName()).put(key, value) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(String orgi) {
|
||||
getInstance().getMap(getName()).clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object delete(String key, String orgi) {
|
||||
return getInstance().getMap(getName()).remove(key) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(String key, String orgi, Object value) {
|
||||
getInstance().getMap(getName()).put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi) {
|
||||
return getInstance().getMap(getName()).get(key);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return cacheName ;
|
||||
}
|
||||
|
||||
// @Override
|
||||
public void service() throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<?> getAllCacheObject(String orgi) {
|
||||
return getInstance().getMap(getName()).keySet();
|
||||
}
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi, Object defaultValue) {
|
||||
return getCacheObject(key, orgi);
|
||||
}
|
||||
@Override
|
||||
public Object getCache() {
|
||||
return getInstance().getMap(cacheName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getLock(String lock , String orgi) {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getLock(lock);
|
||||
}
|
||||
@Override
|
||||
public long getSize() {
|
||||
return getInstance().getMap(getName()).size();
|
||||
}
|
||||
@Override
|
||||
public long getAtomicLong(String cacheName) {
|
||||
return getInstance().getAtomicLong(getName()).incrementAndGet();
|
||||
}
|
||||
@Override
|
||||
public void setAtomicLong(String cacheName, long start) {
|
||||
getInstance().getAtomicLong(getName()).set(start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonObject getStatics() {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getMap(getName()).getLocalMapStats().toJson();
|
||||
}
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.cache.hazelcast.impl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
|
||||
import com.chatopera.cc.app.cache.CacheBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.hazelcast.com.eclipsesource.json.JsonObject;
|
||||
import com.hazelcast.core.HazelcastInstance;
|
||||
|
||||
@Service("system_cache")
|
||||
public class SystemCache implements CacheBean {
|
||||
|
||||
@Autowired
|
||||
public HazelcastInstance hazelcastInstance;
|
||||
|
||||
private String cacheName ;
|
||||
|
||||
public HazelcastInstance getInstance(){
|
||||
return hazelcastInstance ;
|
||||
}
|
||||
public CacheBean getCacheInstance(String cacheName){
|
||||
this.cacheName = cacheName ;
|
||||
return this ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(String key, Object value, String orgi) {
|
||||
getInstance().getMap(getName()).put(key, value) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(String orgi) {
|
||||
getInstance().getMap(getName()).clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object delete(String key, String orgi) {
|
||||
return getInstance().getMap(getName()).remove(key) ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(String key, String orgi, Object value) {
|
||||
getInstance().getMap(getName()).put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi) {
|
||||
return getInstance().getMap(getName()).get(key);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return cacheName ;
|
||||
}
|
||||
|
||||
// @Override
|
||||
public void service() throws Exception {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<?> getAllCacheObject(String orgi) {
|
||||
return getInstance().getMap(getName()).keySet();
|
||||
}
|
||||
@Override
|
||||
public Object getCacheObject(String key, String orgi, Object defaultValue) {
|
||||
return getCacheObject(key, orgi);
|
||||
}
|
||||
@Override
|
||||
public Object getCache() {
|
||||
return getInstance().getMap(cacheName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lock getLock(String lock , String orgi) {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getLock(lock);
|
||||
}
|
||||
@Override
|
||||
public long getSize() {
|
||||
return getInstance().getMap(getName()).size();
|
||||
}
|
||||
@Override
|
||||
public long getAtomicLong(String cacheName) {
|
||||
return getInstance().getAtomicLong(getName()).incrementAndGet();
|
||||
}
|
||||
@Override
|
||||
public void setAtomicLong(String cacheName, long start) {
|
||||
getInstance().getAtomicLong(getName()).set(start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonObject getStatics() {
|
||||
// TODO Auto-generated method stub
|
||||
return getInstance().getMap(getName()).getLocalMapStats().toJson();
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
@Configuration
|
||||
@EnableSwagger2
|
||||
public class ApiConfigure {
|
||||
|
||||
@Bean
|
||||
public Docket createRestApi() {
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
.groupName("CSKefu")
|
||||
.apiInfo(apiInfo())
|
||||
.select()
|
||||
.apis(RequestHandlerSelectors.basePackage("com.chatopera.cc.app.handler.api.rest"))
|
||||
.paths(PathSelectors.any())
|
||||
.build();
|
||||
}
|
||||
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder()
|
||||
.title("春松客服")
|
||||
.description("春松客服 基于 JAVA 语言开发,是一个全渠道融合的客户支持服务平台,聚合企业内部多个客服渠道,帮助各种行业各种规模的企业建立完整客服体系。通过将邮件、短信、电话语音、WebIM 在线客服、微信、微博、H5 页面、APP 接口等多个渠道来源的客户服务请求与对话汇聚在一个管理平台,用统一的方式来响应和支撑客户服务。")
|
||||
.termsOfServiceUrl("http://docs.chatopera.com/")
|
||||
.contact("春松客服")
|
||||
.version("1.0.0")
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.config;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
|
||||
public class ApiRequestMatchingFilter implements Filter {
|
||||
private RequestMatcher[] ignoredRequests;
|
||||
|
||||
public ApiRequestMatchingFilter(RequestMatcher... matcher) {
|
||||
this.ignoredRequests = matcher;
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
|
||||
HttpServletRequest request = (HttpServletRequest) req;
|
||||
HttpServletResponse response = (HttpServletResponse) resp;
|
||||
|
||||
String method = request.getMethod() ;
|
||||
|
||||
if(!StringUtils.isBlank(method) && method.equalsIgnoreCase("options")){
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
|
||||
response.setHeader("Access-Control-Max-Age", "3600");
|
||||
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,accept,authorization,content-type");
|
||||
response.setHeader("X-Frame-Options", "SAMEORIGIN");
|
||||
response.setStatus(HttpStatus.ACCEPTED.value());
|
||||
}else{
|
||||
boolean matchAnyRoles = false ;
|
||||
for(RequestMatcher anyRequest : ignoredRequests ){
|
||||
if(anyRequest.matches(request)){
|
||||
matchAnyRoles = true ;
|
||||
}
|
||||
}
|
||||
if(matchAnyRoles){
|
||||
String authorization = request.getHeader("authorization") ;
|
||||
if(StringUtils.isBlank(authorization)){
|
||||
authorization = request.getParameter("authorization") ;
|
||||
}
|
||||
if(!StringUtils.isBlank(authorization) && CacheHelper.getApiUserCacheBean().getCacheObject(authorization, MainContext.SYSTEM_ORGI) != null){
|
||||
chain.doFilter(req,resp);
|
||||
}else{
|
||||
response.sendRedirect("/tokens/error");
|
||||
}
|
||||
}else{
|
||||
chain.doFilter(req,resp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig arg0) throws ServletException {
|
||||
|
||||
}
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.config;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.chatopera.cc.concurrent.chatbot.ChatbotDisruptorExceptionHandler;
|
||||
import com.chatopera.cc.concurrent.chatbot.ChatbotEventFactory;
|
||||
import com.chatopera.cc.concurrent.chatbot.ChatbotEventHandler;
|
||||
import com.chatopera.cc.concurrent.multiupdate.MultiUpdateEventFactory;
|
||||
import com.chatopera.cc.concurrent.multiupdate.MultiUpdateEventHandler;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.lmax.disruptor.SleepingWaitStrategy;
|
||||
import com.lmax.disruptor.dsl.Disruptor;
|
||||
import com.lmax.disruptor.dsl.ProducerType;
|
||||
import com.chatopera.cc.concurrent.user.UserDataEvent;
|
||||
import com.chatopera.cc.concurrent.user.UserDataEventFactory;
|
||||
import com.chatopera.cc.concurrent.user.UserEventHandler;
|
||||
|
||||
@Component
|
||||
public class DisruptorConfigure {
|
||||
@SuppressWarnings({ "unchecked", "deprecation" })
|
||||
@Bean(name="disruptor")
|
||||
public Disruptor<UserDataEvent> disruptor() {
|
||||
Executor executor = Executors.newCachedThreadPool();
|
||||
UserDataEventFactory factory = new UserDataEventFactory();
|
||||
Disruptor<UserDataEvent> disruptor = new Disruptor<UserDataEvent>(factory, 1024, executor, ProducerType.SINGLE , new SleepingWaitStrategy());
|
||||
disruptor.setDefaultExceptionHandler(new UKeFuExceptionHandler());
|
||||
disruptor.handleEventsWith(new UserEventHandler());
|
||||
disruptor.start();
|
||||
return disruptor;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "deprecation" })
|
||||
@Bean(name="multiupdate")
|
||||
public Disruptor<UserDataEvent> multiupdate() {
|
||||
Executor executor = Executors.newCachedThreadPool();
|
||||
MultiUpdateEventFactory factory = new MultiUpdateEventFactory();
|
||||
Disruptor<UserDataEvent> disruptor = new Disruptor<UserDataEvent>(factory, 1024, executor, ProducerType.SINGLE , new SleepingWaitStrategy());
|
||||
disruptor.handleEventsWith(new MultiUpdateEventHandler());
|
||||
disruptor.setDefaultExceptionHandler(new UKeFuExceptionHandler());
|
||||
disruptor.start();
|
||||
return disruptor;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "deprecation" })
|
||||
@Bean(name="chatbot")
|
||||
public Disruptor<UserDataEvent> chatbot() {
|
||||
Executor executor = Executors.newCachedThreadPool();
|
||||
ChatbotEventFactory factory = new ChatbotEventFactory();
|
||||
Disruptor<UserDataEvent> disruptor = new Disruptor<UserDataEvent>(factory, 1024, executor, ProducerType.SINGLE , new SleepingWaitStrategy());
|
||||
disruptor.handleEventsWith(new ChatbotEventHandler());
|
||||
disruptor.setDefaultExceptionHandler(new ChatbotDisruptorExceptionHandler());
|
||||
disruptor.start();
|
||||
return disruptor;
|
||||
}
|
||||
}
|
@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.config;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import com.corundumstudio.socketio.AuthorizationListener;
|
||||
import com.corundumstudio.socketio.Configuration;
|
||||
import com.corundumstudio.socketio.HandshakeData;
|
||||
import com.corundumstudio.socketio.SocketIOServer;
|
||||
import com.corundumstudio.socketio.annotation.SpringAnnotationScanner;
|
||||
import com.chatopera.cc.app.basic.MainUtils;
|
||||
import com.chatopera.cc.exception.UCKeFuExceptionListener;
|
||||
|
||||
@org.springframework.context.annotation.Configuration
|
||||
public class IMServerConfiguration
|
||||
{
|
||||
@Value("${uk.im.server.host}")
|
||||
private String host;
|
||||
|
||||
@Value("${uk.im.server.port}")
|
||||
private Integer port;
|
||||
|
||||
@Value("${cs.im.server.ssl.port}")
|
||||
private Integer sslPort;
|
||||
|
||||
@Value("${web.upload-path}")
|
||||
private String path;
|
||||
|
||||
@Value("${uk.im.server.threads}")
|
||||
private String threads;
|
||||
|
||||
private SocketIOServer server ;
|
||||
|
||||
@Bean(name="webimport")
|
||||
public Integer getWebIMPort() {
|
||||
if(sslPort != null){
|
||||
MainContext.setWebIMPort(sslPort);
|
||||
return sslPort;
|
||||
} else {
|
||||
MainContext.setWebIMPort(port);
|
||||
return port;
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SocketIOServer socketIOServer() throws NoSuchAlgorithmException, IOException
|
||||
{
|
||||
Configuration config = new Configuration();
|
||||
// config.setHostname("localhost");
|
||||
config.setPort(port);
|
||||
|
||||
// config.getSocketConfig().setReuseAddress(true);
|
||||
// config.setSocketConfig(new SocketConfig());
|
||||
// config.setOrigin("*");
|
||||
config.setExceptionListener(new UCKeFuExceptionListener());
|
||||
|
||||
File sslFile = new File(path , "ssl/https.properties") ;
|
||||
if(sslFile.exists()){
|
||||
Properties sslProperties = new Properties();
|
||||
FileInputStream in = new FileInputStream(sslFile);
|
||||
sslProperties.load(in);
|
||||
in.close();
|
||||
if(StringUtils.isNotBlank(sslProperties.getProperty("key-store")) && StringUtils.isNotBlank(sslProperties.getProperty("key-store-password"))){
|
||||
config.setKeyStorePassword(MainUtils.decryption(sslProperties.getProperty("key-store-password")));
|
||||
InputStream stream = new FileInputStream(new File(path , "ssl/"+sslProperties.getProperty("key-store")));
|
||||
config.setKeyStore(stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// config.setSSLProtocol("https");
|
||||
int workThreads = StringUtils.isNotBlank(threads) && threads.matches("[\\d]{1,6}") ? Integer.parseInt(threads) : 100 ;
|
||||
config.setWorkerThreads(workThreads);
|
||||
// config.setStoreFactory(new HazelcastStoreFactory());
|
||||
config.setAuthorizationListener(new AuthorizationListener() {
|
||||
public boolean isAuthorized(HandshakeData data) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
config.getSocketConfig().setReuseAddress(true);
|
||||
config.getSocketConfig().setSoLinger(0);
|
||||
config.getSocketConfig().setTcpNoDelay(true);
|
||||
config.getSocketConfig().setTcpKeepAlive(true);
|
||||
|
||||
return server = new SocketIOServer(config);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SpringAnnotationScanner springAnnotationScanner(SocketIOServer socketServer) {
|
||||
return new SpringAnnotationScanner(socketServer);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void destory() {
|
||||
server.stop();
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.config;
|
||||
|
||||
import com.chatopera.cc.app.schedule.CallOutWireTask;
|
||||
import com.chatopera.cc.app.schedule.WebIMAgentDispatcher;
|
||||
import com.chatopera.cc.app.schedule.WebIMOnlineUserDispatcher;
|
||||
import com.chatopera.cc.util.Constants;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||
import org.springframework.data.redis.listener.PatternTopic;
|
||||
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
|
||||
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@Configuration
|
||||
public class RedisConfigure {
|
||||
|
||||
|
||||
@Autowired
|
||||
JedisConnectionFactory jedisConnectionFactory;
|
||||
|
||||
|
||||
@Autowired
|
||||
CallOutWireTask callOutWireTask;
|
||||
|
||||
@Autowired
|
||||
WebIMAgentDispatcher webIMAgentDispatcher;
|
||||
|
||||
@Autowired
|
||||
WebIMOnlineUserDispatcher webIMOnlineUserDispatcher;
|
||||
|
||||
@Bean
|
||||
RedisMessageListenerContainer redisContainer() {
|
||||
final RedisMessageListenerContainer container = new RedisMessageListenerContainer();
|
||||
container.setConnectionFactory(jedisConnectionFactory);
|
||||
container.addMessageListener(pbxMessageListener(), pbxEvents());
|
||||
container.addMessageListener(imAgentDispatchListener(), imAgentEvents());
|
||||
container.addMessageListener(imOnlineUserDispatchListener(), imOnlineUserEvents());
|
||||
container.setTaskExecutor(Executors.newFixedThreadPool(50));
|
||||
return container;
|
||||
}
|
||||
|
||||
@Bean
|
||||
MessageListenerAdapter pbxMessageListener() {
|
||||
return new MessageListenerAdapter(callOutWireTask);
|
||||
}
|
||||
|
||||
@Bean
|
||||
PatternTopic pbxEvents() {
|
||||
return new PatternTopic(Constants.FS_CHANNEL_FS_TO_CC);
|
||||
}
|
||||
|
||||
@Bean
|
||||
MessageListenerAdapter imAgentDispatchListener() {
|
||||
return new MessageListenerAdapter(webIMAgentDispatcher);
|
||||
}
|
||||
|
||||
@Bean
|
||||
PatternTopic imAgentEvents() {
|
||||
return new PatternTopic(Constants.INSTANT_MESSAGING_WEBIM_AGENT_CHANNEL);
|
||||
}
|
||||
|
||||
@Bean
|
||||
MessageListenerAdapter imOnlineUserDispatchListener(){
|
||||
return new MessageListenerAdapter(webIMOnlineUserDispatcher);
|
||||
}
|
||||
|
||||
@Bean
|
||||
PatternTopic imOnlineUserEvents() {
|
||||
return new PatternTopic(Constants.INSTANT_MESSAGING_WEBIM_ONLINE_USER_CHANNEL);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.persistence.repository.GenerationRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.SysDicRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.SystemConfigRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.TablePropertiesRepository;
|
||||
import com.chatopera.cc.app.model.Generation;
|
||||
import com.chatopera.cc.app.model.SysDic;
|
||||
import com.chatopera.cc.app.basic.MainUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.chatopera.cc.app.persistence.repository.BlackListRepository;
|
||||
import com.chatopera.cc.app.model.BlackEntity;
|
||||
import com.chatopera.cc.app.model.SystemConfig;
|
||||
|
||||
@Component
|
||||
public class StartedEventListener implements ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
@Value("${web.upload-path}")
|
||||
private String path;
|
||||
|
||||
private SysDicRepository sysDicRes;
|
||||
private BlackListRepository blackListRes ;
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
if(MainContext.getContext() == null){
|
||||
MainContext.setApplicationContext(event.getApplicationContext());
|
||||
}
|
||||
sysDicRes = event.getApplicationContext().getBean(SysDicRepository.class) ;
|
||||
blackListRes = event.getApplicationContext().getBean(BlackListRepository.class) ;
|
||||
List<SysDic> sysDicList = sysDicRes.findAll() ;
|
||||
|
||||
for(SysDic dic : sysDicList){
|
||||
CacheHelper.getSystemCacheBean().put(dic.getId(), dic, dic.getOrgi());
|
||||
if(dic.getParentid().equals("0")){
|
||||
List<SysDic> sysDicItemList = new ArrayList<SysDic>();
|
||||
for(SysDic item : sysDicList){
|
||||
if(item.getDicid()!=null && item.getDicid().equals(dic.getId())){
|
||||
sysDicItemList.add(item) ;
|
||||
}
|
||||
}
|
||||
CacheHelper.getSystemCacheBean().put(dic.getCode(), sysDicItemList, dic.getOrgi());
|
||||
}
|
||||
}
|
||||
List<BlackEntity> blackList = blackListRes.findByOrgi(MainContext.SYSTEM_ORGI) ;
|
||||
for(BlackEntity black : blackList){
|
||||
if(!StringUtils.isBlank(black.getUserid())) {
|
||||
if(black.getEndtime()==null || black.getEndtime().after(new Date())){
|
||||
CacheHelper.getSystemCacheBean().put(black.getUserid(), black, black.getOrgi());
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 加载系统全局配置
|
||||
*/
|
||||
SystemConfigRepository systemConfigRes = event.getApplicationContext().getBean(SystemConfigRepository.class) ;
|
||||
SystemConfig config = systemConfigRes.findByOrgi(MainContext.SYSTEM_ORGI) ;
|
||||
if(config != null){
|
||||
CacheHelper.getSystemCacheBean().put("systemConfig", config, MainContext.SYSTEM_ORGI);
|
||||
}
|
||||
GenerationRepository generationRes = event.getApplicationContext().getBean(GenerationRepository.class) ;
|
||||
List<Generation> generationList = generationRes.findAll() ;
|
||||
for(Generation generation : generationList){
|
||||
CacheHelper.getSystemCacheBean().setAtomicLong(MainContext.ModelType.WORKORDERS.toString(), generation.getStartinx());
|
||||
}
|
||||
|
||||
MainUtils.initSystemArea();
|
||||
|
||||
MainUtils.initSystemSecField(event.getApplicationContext().getBean(TablePropertiesRepository.class));
|
||||
//MainUtils.initAdv();//初始化广告位
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.chatopera.cc.app.algorithm.AutomaticServiceDist;
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.model.User;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
@Controller
|
||||
public class ApplicationController extends Handler{
|
||||
|
||||
@RequestMapping("/")
|
||||
public ModelAndView admin(HttpServletRequest request) {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("/apps/index"));
|
||||
User user = super.getUser(request) ;
|
||||
view.addObject("agentStatusReport", AutomaticServiceDist.getAgentReport(user.getOrgi())) ;
|
||||
view.addObject("tenant",super.getTenant(request));
|
||||
view.addObject("istenantshare",super.isEnabletneant());
|
||||
if(super.isEnabletneant()) {
|
||||
//多租户启用 非超级管理员 一定要选择租户才能进入界面
|
||||
if(!user.isSuperuser() && StringUtils.isNotBlank(user.getOrgid()) && super.isTenantconsole() && MainContext.SYSTEM_ORGI.equals(user.getOrgi())) {
|
||||
view = request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index"));
|
||||
}
|
||||
if(StringUtils.isBlank(user.getOrgid())) {
|
||||
view = request(super.createRequestPageTempletResponse("redirect:/apps/organization/add.html"));
|
||||
}
|
||||
}
|
||||
view.addObject("agentStatus", CacheHelper.getAgentStatusCacheBean().getCacheObject(user.getId(), user.getOrgi())) ;
|
||||
return view;
|
||||
}
|
||||
}
|
@ -1,317 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.basic.MainUtils;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.model.*;
|
||||
import com.chatopera.cc.app.persistence.repository.OrganRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.RoleAuthRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.UserRoleRepository;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.OnlineUserUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author UK
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@Controller
|
||||
public class LoginController extends Handler {
|
||||
private final static Logger logger = LoggerFactory.getLogger(LoginController.class);
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private UserRoleRepository userRoleRes;
|
||||
|
||||
@Autowired
|
||||
private RoleAuthRepository roleAuthRes;
|
||||
|
||||
@Autowired
|
||||
private OrganRepository organRepository;
|
||||
|
||||
/**
|
||||
* 获取一个用户所拥有的所有部门ID
|
||||
*
|
||||
* @param user
|
||||
*/
|
||||
private void organs(final User user, final String organ) {
|
||||
if (organ == null)
|
||||
return;
|
||||
|
||||
if (user.inMyorgans(organ))
|
||||
return;
|
||||
|
||||
user.getMyorgans().add(organ);
|
||||
List<Organ> y = organRepository.findByOrgiAndParent(user.getOrgi(), organ);
|
||||
for (Organ x : y) {
|
||||
try {
|
||||
organs(user, x.getId());
|
||||
} catch (Exception e) {
|
||||
logger.error("organs", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/login", method = RequestMethod.GET)
|
||||
@Menu(type = "apps", subtype = "user", access = true)
|
||||
public ModelAndView login(HttpServletRequest request, HttpServletResponse response, @RequestHeader(value = "referer", required = false) String referer, @Valid String msg) throws NoSuchAlgorithmException {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("redirect:/"));
|
||||
if (request.getSession(true).getAttribute(MainContext.USER_SESSION_NAME) == null) {
|
||||
view = request(super.createRequestPageTempletResponse("/login"));
|
||||
if (!StringUtils.isBlank(request.getParameter("referer"))) {
|
||||
referer = request.getParameter("referer");
|
||||
}
|
||||
if (!StringUtils.isBlank(referer)) {
|
||||
view.addObject("referer", referer);
|
||||
}
|
||||
Cookie[] cookies = request.getCookies();//这样便可以获取一个cookie数组
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie != null && !StringUtils.isBlank(cookie.getName()) && !StringUtils.isBlank(cookie.getValue())) {
|
||||
if (cookie.getName().equals(MainContext.UKEFU_SYSTEM_COOKIES_FLAG)) {
|
||||
String flagid = MainUtils.decryption(cookie.getValue());
|
||||
if (!StringUtils.isBlank(flagid)) {
|
||||
User user = userRepository.findById(flagid);
|
||||
if (user != null) {
|
||||
view = this.processLogin(request, response, view, user, referer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!StringUtils.isBlank(msg)) {
|
||||
view.addObject("msg", msg);
|
||||
}
|
||||
SystemConfig systemConfig = MainUtils.getSystemConfig();
|
||||
if (systemConfig != null && systemConfig.isEnableregorgi()) {
|
||||
view.addObject("show", true);
|
||||
}
|
||||
if (systemConfig != null) {
|
||||
view.addObject("systemConfig", systemConfig);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/login", method = RequestMethod.POST)
|
||||
@Menu(type = "apps", subtype = "user", access = true)
|
||||
public ModelAndView login(HttpServletRequest request, HttpServletResponse response, @Valid User user, @Valid String referer, @Valid String sla) throws NoSuchAlgorithmException {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("redirect:/"));
|
||||
if (request.getSession(true).getAttribute(MainContext.USER_SESSION_NAME) == null) {
|
||||
if (user != null && user.getUsername() != null) {
|
||||
final User loginUser = userRepository.findByUsernameAndPasswordAndDatastatus(user.getUsername(), MainUtils.md5(user.getPassword()), false);
|
||||
if (loginUser != null && !StringUtils.isBlank(loginUser.getId())) {
|
||||
view = this.processLogin(request, response, view, loginUser, referer);
|
||||
if (!StringUtils.isBlank(sla) && sla.equals("1")) {
|
||||
Cookie flagid = new Cookie(MainContext.UKEFU_SYSTEM_COOKIES_FLAG, MainUtils.encryption(loginUser.getId()));
|
||||
flagid.setMaxAge(7 * 24 * 60 * 60);
|
||||
response.addCookie(flagid);
|
||||
// add authorization code for rest api
|
||||
String auth = MainUtils.getUUID();
|
||||
CacheHelper.getApiUserCacheBean().put(auth, loginUser, MainContext.SYSTEM_ORGI);
|
||||
response.addCookie((new Cookie("authorization", auth)));
|
||||
}
|
||||
} else {
|
||||
view = request(super.createRequestPageTempletResponse("/login"));
|
||||
if (!StringUtils.isBlank(referer)) {
|
||||
view.addObject("referer", referer);
|
||||
}
|
||||
view.addObject("msg", "0");
|
||||
}
|
||||
}
|
||||
}
|
||||
SystemConfig systemConfig = MainUtils.getSystemConfig();
|
||||
if (systemConfig != null && systemConfig.isEnableregorgi()) {
|
||||
view.addObject("show", true);
|
||||
}
|
||||
if (systemConfig != null) {
|
||||
view.addObject("systemConfig", systemConfig);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
private ModelAndView processLogin(HttpServletRequest request, HttpServletResponse response, ModelAndView view, final User loginUser, String referer) {
|
||||
if (loginUser != null) {
|
||||
loginUser.setLogin(true);
|
||||
if (!StringUtils.isBlank(referer)) {
|
||||
view = request(super.createRequestPageTempletResponse("redirect:" + referer));
|
||||
} else {
|
||||
view = request(super.createRequestPageTempletResponse("redirect:/"));
|
||||
}
|
||||
//登录成功 判断是否进入多租户页面
|
||||
SystemConfig systemConfig = MainUtils.getSystemConfig();
|
||||
if (systemConfig != null && systemConfig.isEnabletneant() && systemConfig.isTenantconsole() && !loginUser.isSuperuser()) {
|
||||
view = request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index"));
|
||||
}
|
||||
List<UserRole> userRoleList = userRoleRes.findByOrgiAndUser(loginUser.getOrgi(), loginUser);
|
||||
if (userRoleList != null && userRoleList.size() > 0) {
|
||||
for (UserRole userRole : userRoleList) {
|
||||
loginUser.getRoleList().add(userRole.getRole());
|
||||
}
|
||||
}
|
||||
|
||||
// 获取用户部门以及下级部门
|
||||
organs(loginUser, loginUser.getOrgan()); // 添加部门到myorgans中
|
||||
|
||||
// 获取用户的角色权限,进行授权
|
||||
List<RoleAuth> roleAuthList = roleAuthRes.findAll(new Specification<RoleAuth>() {
|
||||
@Override
|
||||
public Predicate toPredicate(Root<RoleAuth> root, CriteriaQuery<?> query,
|
||||
CriteriaBuilder cb) {
|
||||
List<Predicate> list = new ArrayList<Predicate>();
|
||||
if (loginUser.getRoleList() != null && loginUser.getRoleList().size() > 0) {
|
||||
for (Role role : loginUser.getRoleList()) {
|
||||
list.add(cb.equal(root.get("roleid").as(String.class), role.getId()));
|
||||
}
|
||||
}
|
||||
Predicate[] p = new Predicate[list.size()];
|
||||
cb.and(cb.equal(root.get("orgi").as(String.class), loginUser.getOrgi()));
|
||||
return cb.or(list.toArray(p));
|
||||
}
|
||||
});
|
||||
|
||||
if (roleAuthList != null) {
|
||||
for (RoleAuth roleAuth : roleAuthList) {
|
||||
loginUser.getRoleAuthMap().put(roleAuth.getDicvalue(), true);
|
||||
}
|
||||
}
|
||||
|
||||
loginUser.setLastlogintime(new Date());
|
||||
if (!StringUtils.isBlank(loginUser.getId())) {
|
||||
userRepository.save(loginUser);
|
||||
}
|
||||
|
||||
super.setUser(request, loginUser);
|
||||
//当前用户 企业id为空 调到创建企业页面
|
||||
if (StringUtils.isBlank(loginUser.getOrgid())) {
|
||||
view = request(super.createRequestPageTempletResponse("redirect:/apps/organization/add.html"));
|
||||
}
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@RequestMapping("/logout")
|
||||
public String logout(HttpServletRequest request, HttpServletResponse response) {
|
||||
request.getSession().removeAttribute(MainContext.USER_SESSION_NAME);
|
||||
Cookie[] cookies = request.getCookies();
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie != null && !StringUtils.isBlank(cookie.getName()) && !StringUtils.isBlank(cookie.getValue())) {
|
||||
if (cookie.getName().equals(MainContext.UKEFU_SYSTEM_COOKIES_FLAG)) {
|
||||
cookie.setMaxAge(0);
|
||||
response.addCookie(cookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "redirect:/";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/register")
|
||||
@Menu(type = "apps", subtype = "user", access = true)
|
||||
public ModelAndView register(HttpServletRequest request, HttpServletResponse response, @Valid String msg) {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("redirect:/"));
|
||||
if (request.getSession(true).getAttribute(MainContext.USER_SESSION_NAME) == null) {
|
||||
view = request(super.createRequestPageTempletResponse("/register"));
|
||||
}
|
||||
if (!StringUtils.isBlank(msg)) {
|
||||
view.addObject("msg", msg);
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@RequestMapping("/addAdmin")
|
||||
@Menu(type = "apps", subtype = "user", access = true)
|
||||
public ModelAndView addAdmin(HttpServletRequest request, HttpServletResponse response, @Valid User user) {
|
||||
String msg = "";
|
||||
msg = validUser(user);
|
||||
if (!StringUtils.isBlank(msg)) {
|
||||
return request(super.createRequestPageTempletResponse("redirect:/register.html?msg=" + msg));
|
||||
} else {
|
||||
user.setUname(user.getUsername());
|
||||
user.setUsertype("0");
|
||||
if (!StringUtils.isBlank(user.getPassword())) {
|
||||
user.setPassword(MainUtils.md5(user.getPassword()));
|
||||
}
|
||||
user.setOrgi(super.getOrgiByTenantshare(request));
|
||||
/*if(!StringUtils.isBlank(super.getUser(request).getOrgid())) {
|
||||
user.setOrgid(super.getUser(request).getOrgid());
|
||||
}else {
|
||||
user.setOrgid(MainContext.SYSTEM_ORGI);
|
||||
}*/
|
||||
userRepository.save(user);
|
||||
OnlineUserUtils.clean(super.getOrgi(request));
|
||||
|
||||
}
|
||||
ModelAndView view = this.processLogin(request, response, request(super.createRequestPageTempletResponse("redirect:/")), user, "");
|
||||
//当前用户 企业id为空 调到创建企业页面
|
||||
if (StringUtils.isBlank(user.getOrgid())) {
|
||||
view = request(super.createRequestPageTempletResponse("redirect:/apps/organization/add.html"));
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
private String validUser(User user) {
|
||||
String msg = "";
|
||||
User tempUser = userRepository.findByUsernameAndDatastatus(user.getUsername(), false);
|
||||
if (tempUser != null) {
|
||||
msg = "username_exist";
|
||||
return msg;
|
||||
}
|
||||
tempUser = userRepository.findByEmailAndDatastatus(user.getEmail(), false);
|
||||
if (tempUser != null) {
|
||||
msg = "email_exist";
|
||||
return msg;
|
||||
}
|
||||
tempUser = userRepository.findByMobileAndDatastatus(user.getMobile(), false);
|
||||
if (tempUser != null) {
|
||||
msg = "mobile_exist";
|
||||
return msg;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,181 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.admin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.app.algorithm.AutomaticServiceDist;
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.basic.MainUtils;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.im.client.NettyClients;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.persistence.repository.OnlineUserRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.SysDicRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.UserEventRepository;
|
||||
import com.chatopera.cc.util.OnlineUserUtils;
|
||||
import com.chatopera.cc.app.model.SysDic;
|
||||
import com.chatopera.cc.app.model.User;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.app.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
|
||||
@Controller
|
||||
public class AdminController extends Handler{
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRes;
|
||||
|
||||
@Autowired
|
||||
private OnlineUserRepository onlineUserRes;
|
||||
|
||||
@Autowired
|
||||
private UserEventRepository userEventRes ;
|
||||
|
||||
@Autowired
|
||||
private SysDicRepository sysDicRes ;
|
||||
|
||||
@RequestMapping("/admin")
|
||||
public ModelAndView index(ModelMap map ,HttpServletRequest request) {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("redirect:/"));
|
||||
User user = super.getUser(request) ;
|
||||
view.addObject("agentStatusReport", AutomaticServiceDist.getAgentReport(user.getOrgi())) ;
|
||||
view.addObject("agentStatus", CacheHelper.getAgentStatusCacheBean().getCacheObject(user.getId(), user.getOrgi())) ;
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
private void aggValues(ModelMap map , HttpServletRequest request){
|
||||
map.put("onlineUserCache", CacheHelper.getOnlineUserCacheBean().getSize()) ;
|
||||
map.put("onlineUserClients", OnlineUserUtils.webIMClients.size()) ;
|
||||
map.put("chatClients", NettyClients.getInstance().size()) ;
|
||||
map.put("systemCaches", CacheHelper.getSystemCacheBean().getSize()) ;
|
||||
|
||||
map.put("agentReport", AutomaticServiceDist.getAgentReport(super.getOrgi(request))) ;
|
||||
map.put("webIMReport", MainUtils.getWebIMReport(userEventRes.findByOrgiAndCreatetimeRange(super.getOrgi(request), MainUtils.getStartTime() , MainUtils.getEndTime()))) ;
|
||||
|
||||
map.put("agents",getAgent(request).size()) ;
|
||||
|
||||
map.put("webIMInvite", MainUtils.getWebIMInviteStatus(onlineUserRes.findByOrgiAndStatus(super.getOrgi(request), MainContext.OnlineUserOperatorStatus.ONLINE.toString()))) ;
|
||||
|
||||
map.put("inviteResult", MainUtils.getWebIMInviteResult(onlineUserRes.findByOrgiAndAgentnoAndCreatetimeRange(super.getOrgi(request), super.getUser(request).getId() , MainUtils.getStartTime() , MainUtils.getEndTime()))) ;
|
||||
|
||||
map.put("agentUserCount", onlineUserRes.countByAgentForAgentUser(super.getOrgi(request), MainContext.AgentUserStatusEnum.INSERVICE.toString(),super.getUser(request).getId() , MainUtils.getStartTime() , MainUtils.getEndTime())) ;
|
||||
|
||||
map.put("agentServicesCount", onlineUserRes.countByAgentForAgentUser(super.getOrgi(request), MainContext.AgentUserStatusEnum.END.toString(),super.getUser(request).getId() , MainUtils.getStartTime() , MainUtils.getEndTime())) ;
|
||||
|
||||
map.put("agentServicesAvg", onlineUserRes.countByAgentForAvagTime(super.getOrgi(request), MainContext.AgentUserStatusEnum.END.toString(),super.getUser(request).getId() , MainUtils.getStartTime() , MainUtils.getEndTime())) ;
|
||||
|
||||
map.put("webInviteReport", MainUtils.getWebIMInviteAgg(onlineUserRes.findByOrgiAndCreatetimeRange(super.getOrgi(request) , MainContext.ChannelTypeEnum.WEBIM.toString(), MainUtils.getLast30Day(), MainUtils.getEndTime()))) ;
|
||||
|
||||
map.put("agentConsultReport", MainUtils.getWebIMDataAgg(onlineUserRes.findByOrgiAndCreatetimeRangeForAgent(super.getOrgi(request), MainUtils.getLast30Day(), MainUtils.getEndTime()))) ;
|
||||
|
||||
map.put("clentConsultReport", MainUtils.getWebIMDataAgg(onlineUserRes.findByOrgiAndCreatetimeRangeForClient(super.getOrgi(request), MainUtils.getLast30Day(), MainUtils.getEndTime() , MainContext.ChannelTypeEnum.WEBIM.toString()))) ;
|
||||
|
||||
map.put("browserConsultReport", MainUtils.getWebIMDataAgg(onlineUserRes.findByOrgiAndCreatetimeRangeForBrowser(super.getOrgi(request), MainUtils.getLast30Day(), MainUtils.getEndTime(), MainContext.ChannelTypeEnum.WEBIM.toString()))) ;
|
||||
}
|
||||
private List<User> getAgent(HttpServletRequest request){
|
||||
//获取当前产品or租户坐席数
|
||||
List<User> userList = new ArrayList<>();
|
||||
if(super.isEnabletneant()) {
|
||||
userList = userRes.findByOrgidAndAgentAndDatastatus(super.getOrgid(request), true, false);
|
||||
}else {
|
||||
userList = userRes.findByOrgiAndAgentAndDatastatus(super.getOrgi(request), true, false);
|
||||
}
|
||||
return userList.isEmpty()?new ArrayList<User>():userList;
|
||||
}
|
||||
|
||||
@RequestMapping("/admin/content")
|
||||
@Menu(type = "admin" , subtype = "content")
|
||||
public ModelAndView content(ModelMap map , HttpServletRequest request) {
|
||||
aggValues(map, request);
|
||||
return request(super.createAdminTempletResponse("/admin/content"));
|
||||
/*if(super.getUser(request).isSuperuser()) {
|
||||
aggValues(map, request);
|
||||
return request(super.createAdminTempletResponse("/admin/content"));
|
||||
}else {
|
||||
return request(super.createAdminTempletResponse("/admin/user/index"));
|
||||
}*/
|
||||
}
|
||||
|
||||
@RequestMapping("/admin/auth/infoacq")
|
||||
@Menu(type = "admin" , subtype = "infoacq" , access= false , admin = true)
|
||||
public ModelAndView infoacq(ModelMap map , HttpServletRequest request) {
|
||||
String inacq = (String) request.getSession().getAttribute(MainContext.UKEFU_SYSTEM_INFOACQ) ;
|
||||
if(!StringUtils.isBlank(inacq)){
|
||||
request.getSession().removeAttribute(MainContext.UKEFU_SYSTEM_INFOACQ);
|
||||
}else{
|
||||
request.getSession().setAttribute(MainContext.UKEFU_SYSTEM_INFOACQ , "true");
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/"));
|
||||
}
|
||||
|
||||
@RequestMapping("/admin/auth/event")
|
||||
@Menu(type = "admin" , subtype = "authevent")
|
||||
public ModelAndView authevent(ModelMap map , HttpServletRequest request , @Valid String title , @Valid String url , @Valid String iconstr, @Valid String icontext) {
|
||||
map.addAttribute("title", title) ;
|
||||
map.addAttribute("url", url) ;
|
||||
if(!StringUtils.isBlank(iconstr) && !StringUtils.isBlank(icontext)){
|
||||
map.addAttribute("iconstr", iconstr.replaceAll(icontext, "&#x"+ MainUtils.string2HexString(icontext)+";")) ;
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("/admin/system/auth/exchange"));
|
||||
}
|
||||
|
||||
@RequestMapping("/admin/auth/save")
|
||||
@Menu(type = "admin" , subtype = "authsave")
|
||||
public ModelAndView authsave(ModelMap map , HttpServletRequest request , @Valid String title , @Valid SysDic dic) {
|
||||
SysDic sysDic = sysDicRes.findByCode(MainContext.UKEFU_SYSTEM_AUTH_DIC) ;
|
||||
boolean newdic = false ;
|
||||
if(sysDic!=null && !StringUtils.isBlank(dic.getName())){
|
||||
if(!StringUtils.isBlank(dic.getParentid())){
|
||||
if(dic.getParentid().equals("0")){
|
||||
dic.setParentid(sysDic.getId());
|
||||
newdic = true ;
|
||||
}else{
|
||||
List<SysDic> dicList = sysDicRes.findByDicid(sysDic.getId()) ;
|
||||
for(SysDic temp : dicList){
|
||||
if(temp.getCode().equals(dic.getParentid()) || temp.getName().equals(dic.getParentid())){
|
||||
dic.setParentid(temp.getId());
|
||||
newdic = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(newdic){
|
||||
dic.setCreater(super.getUser(request).getId());
|
||||
dic.setCreatetime(new Date());
|
||||
dic.setCtype("auth");
|
||||
dic.setDicid(sysDic.getId());
|
||||
sysDicRes.save(dic) ;
|
||||
}
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("/public/success"));
|
||||
}
|
||||
|
||||
}
|
@ -1,168 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.admin.callcenter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.exchange.CallCenterInterface;
|
||||
import com.chatopera.cc.app.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.PbxHost;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/callcenter")
|
||||
public class CallCenterController extends Handler {
|
||||
|
||||
@Autowired
|
||||
private PbxHostRepository pbxHostRes ;
|
||||
|
||||
@RequestMapping(value = "/index")
|
||||
@Menu(type = "callcenter" , subtype = "callcenter" , access = false , admin = true)
|
||||
public ModelAndView index(ModelMap map , HttpServletRequest request , @Valid String msg) {
|
||||
List<PbxHost> pbxHostList = pbxHostRes.findByOrgi(super.getOrgi(request)) ;
|
||||
if(MainContext.model.get("callcenter")!=null){
|
||||
CallCenterInterface callCenterImpl = (CallCenterInterface) MainContext.getContext().getBean("callcenter") ;
|
||||
|
||||
for(PbxHost pbxHost : pbxHostList){
|
||||
if(callCenterImpl!=null){
|
||||
pbxHost.setConnected(callCenterImpl.connected(pbxHost.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
map.addAttribute("pbxHostList" , pbxHostList);
|
||||
return request(super.createAdminTempletResponse("/admin/callcenter/index"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/pbxhost")
|
||||
@Menu(type = "callcenter" , subtype = "pbxhost" , access = false , admin = true)
|
||||
public ModelAndView pbxhost(ModelMap map , HttpServletRequest request) {
|
||||
List<PbxHost> pbxHostList = pbxHostRes.findByOrgi(super.getOrgi(request)) ;
|
||||
if(MainContext.model.get("callcenter")!=null){
|
||||
CallCenterInterface callCenterImpl = (CallCenterInterface) MainContext.getContext().getBean("callcenter") ;
|
||||
|
||||
for(PbxHost pbxHost : pbxHostList){
|
||||
if(callCenterImpl!=null){
|
||||
pbxHost.setConnected(callCenterImpl.connected(pbxHost.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
map.addAttribute("pbxHostList" , pbxHostList);
|
||||
return request(super.createRequestPageTempletResponse("/admin/callcenter/pbxhost/index"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/pbxhost/add")
|
||||
@Menu(type = "callcenter" , subtype = "pbxhost" , access = false , admin = true)
|
||||
public ModelAndView pbxhostadd(ModelMap map , HttpServletRequest request) {
|
||||
return request(super.createRequestPageTempletResponse("/admin/callcenter/pbxhost/add"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/pbxhost/save")
|
||||
@Menu(type = "callcenter" , subtype = "pbxhost" , access = false , admin = true)
|
||||
public ModelAndView pbxhostsave(ModelMap map , HttpServletRequest request , @Valid PbxHost pbxHost) {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("redirect:/admin/callcenter/pbxhost.html"));
|
||||
String msg = null ;
|
||||
if(!StringUtils.isBlank(pbxHost.getName())){
|
||||
int count = pbxHostRes.countByHostnameAndOrgi(pbxHost.getHostname(), super.getOrgi(request)) ;
|
||||
if(count == 0){
|
||||
pbxHost.setOrgi(super.getOrgi(request));
|
||||
pbxHost.setCreater(super.getUser(request).getId());
|
||||
pbxHostRes.save(pbxHost) ;
|
||||
if(MainContext.model.get("callcenter")!=null){
|
||||
CallCenterInterface callCenterImpl = (CallCenterInterface) MainContext.getContext().getBean("callcenter") ;
|
||||
if(callCenterImpl!=null){
|
||||
try{
|
||||
callCenterImpl.init(pbxHost);
|
||||
}catch(Exception ex){
|
||||
msg = ex.getMessage() ;
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!StringUtils.isBlank(msg)){
|
||||
view = request(super.createRequestPageTempletResponse("redirect:/admin/callcenter/pbxhost.html?msg="+msg));
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/pbxhost/edit")
|
||||
@Menu(type = "callcenter" , subtype = "pbxhost" , access = false , admin = true)
|
||||
public ModelAndView pbxhostedit(ModelMap map , HttpServletRequest request , @Valid String id) {
|
||||
map.addAttribute("pbxHost" , pbxHostRes.findByIdAndOrgi(id, super.getOrgi(request)));
|
||||
return request(super.createRequestPageTempletResponse("/admin/callcenter/pbxhost/edit"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/pbxhost/update")
|
||||
@Menu(type = "callcenter" , subtype = "pbxhost" , access = false , admin = true)
|
||||
public ModelAndView pbxhostupdate(ModelMap map , HttpServletRequest request , @Valid PbxHost pbxHost) {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("redirect:/admin/callcenter/pbxhost.html"));
|
||||
String msg = null ;
|
||||
if(!StringUtils.isBlank(pbxHost.getId())){
|
||||
PbxHost destHost = pbxHostRes.findByIdAndOrgi(pbxHost.getId(), super.getOrgi(request)) ;
|
||||
destHost.setHostname(pbxHost.getHostname());
|
||||
destHost.setIpaddr(pbxHost.getIpaddr());
|
||||
destHost.setName(pbxHost.getName());
|
||||
destHost.setPort(pbxHost.getPort());
|
||||
if(!StringUtils.isBlank(pbxHost.getPassword())){
|
||||
destHost.setPassword(pbxHost.getPassword());
|
||||
}
|
||||
pbxHostRes.save(destHost) ;
|
||||
if(MainContext.model.get("callcenter")!=null){
|
||||
CallCenterInterface callCenterImpl = (CallCenterInterface) MainContext.getContext().getBean("callcenter") ;
|
||||
if(callCenterImpl!=null){
|
||||
try{
|
||||
callCenterImpl.init(destHost);
|
||||
}catch(Exception ex){
|
||||
msg = ex.getMessage() ;
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!StringUtils.isBlank(msg)){
|
||||
view = request(super.createRequestPageTempletResponse("redirect:/admin/callcenter/pbxhost.html?msg="+msg));
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/pbxhost/delete")
|
||||
@Menu(type = "callcenter" , subtype = "pbxhost" , access = false , admin = true)
|
||||
public ModelAndView mediadelete(ModelMap map , HttpServletRequest request , @Valid String id) {
|
||||
if(!StringUtils.isBlank(id)){
|
||||
pbxHostRes.delete(id);
|
||||
if(MainContext.model.get("callcenter")!=null){
|
||||
CallCenterInterface callCenterImpl = (CallCenterInterface) MainContext.getContext().getBean("callcenter") ;
|
||||
if(callCenterImpl!=null){
|
||||
callCenterImpl.remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/callcenter/pbxhost.html"));
|
||||
}
|
||||
}
|
@ -1,252 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.admin.callcenter;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.ProductRepository;
|
||||
import com.chatopera.cc.app.model.PbxHost;
|
||||
import com.chatopera.cc.app.model.User;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.util.freeswitch.model.CallCenterAgent;
|
||||
import com.chatopera.cc.app.persistence.impl.CallOutQuene;
|
||||
import com.chatopera.cc.app.persistence.repository.ExtentionRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.MediaRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.QueSurveyProcessRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.ServiceAiRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.SipTrunkRepository;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.Extention;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/callcenter")
|
||||
public class CallCenterExtentionController extends Handler{
|
||||
|
||||
@Autowired
|
||||
private PbxHostRepository pbxHostRes ;
|
||||
|
||||
@Autowired
|
||||
private ExtentionRepository extentionRes;
|
||||
|
||||
@Autowired
|
||||
private SipTrunkRepository sipTrunkRes ;
|
||||
|
||||
@Autowired
|
||||
private MediaRepository mediaRes ;
|
||||
|
||||
@Autowired
|
||||
private ServiceAiRepository serviceAiRes ;
|
||||
|
||||
@Autowired
|
||||
private ProductRepository productRes ;
|
||||
|
||||
@Autowired
|
||||
private QueSurveyProcessRepository queSurveyProcessRes ;
|
||||
|
||||
|
||||
@RequestMapping(value = "/extention")
|
||||
@Menu(type = "callcenter" , subtype = "callcenterresource" , access = false , admin = true)
|
||||
public ModelAndView extention(ModelMap map , HttpServletRequest request , @Valid String hostid) {
|
||||
List<PbxHost> pbxHostList = pbxHostRes.findByOrgi(super.getOrgi(request)) ;
|
||||
map.addAttribute("pbxHostList" , pbxHostList);
|
||||
PbxHost pbxHost = null ;
|
||||
if(pbxHostList.size() > 0){
|
||||
map.addAttribute("pbxHost" , pbxHost = getPbxHost(pbxHostList, hostid));
|
||||
map.addAttribute("extentionList" , extentionRes.findByHostidAndOrgi(pbxHost.getId() , super.getOrgi(request)));
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("/admin/callcenter/extention/index"));
|
||||
}
|
||||
|
||||
private PbxHost getPbxHost(List<PbxHost> pbxHostList ,String hostid){
|
||||
PbxHost pbxHost = pbxHostList.get(0) ;
|
||||
if(!StringUtils.isBlank(hostid)){
|
||||
for(PbxHost pbx : pbxHostList){
|
||||
if(pbx.getId().equals(hostid)){
|
||||
pbxHost = pbx; break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pbxHost ;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/extention/add")
|
||||
@Menu(type = "callcenter" , subtype = "extention" , access = false , admin = true)
|
||||
public ModelAndView extentionadd(ModelMap map , HttpServletRequest request , @Valid String hostid) {
|
||||
map.put("pbxHost", pbxHostRes.findByIdAndOrgi(hostid, super.getOrgi(request))) ;
|
||||
|
||||
map.addAttribute("sipTrunkListList" , sipTrunkRes.findByHostidAndOrgi(hostid, super.getOrgi(request)));
|
||||
|
||||
map.put("mediaList" , mediaRes.findByHostidAndOrgi(hostid, super.getOrgi(request)));
|
||||
return request(super.createRequestPageTempletResponse("/admin/callcenter/extention/add"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/extention/save")
|
||||
@Menu(type = "callcenter" , subtype = "extention" , access = false , admin = true)
|
||||
public ModelAndView extentionsave(ModelMap map , HttpServletRequest request , @Valid Extention extention) {
|
||||
if(!StringUtils.isBlank(extention.getExtention()) && !StringUtils.isBlank(extention.getPassword())){
|
||||
String[] extstr = extention.getExtention().split("[,, ]") ;
|
||||
int extnum = 0 ;
|
||||
for(String ext : extstr){
|
||||
if(ext.matches("[\\d]{3,8}")){ //分机号码最少3位数字
|
||||
createNewExtention(ext, super.getUser(request), extention.getHostid(), extention.getPassword(), super.getOrgi(request) , extention) ;
|
||||
}else{
|
||||
String[] ph = ext.split("[~-]") ;
|
||||
if(ph.length == 2 && ph[0].matches("[\\d]{3,8}") && ph[1].matches("[\\d]{3,8}") && ph[0].length() == ph[1].length()){
|
||||
int start = Integer.parseInt(ph[0]) ;
|
||||
int end = Integer.parseInt(ph[1]) ;
|
||||
|
||||
for(int i= start ; i <= end && extnum < 100 ; i++){ //最大一次批量生产的 分机号不超过100个
|
||||
createNewExtention(String.valueOf(i), super.getUser(request), extention.getHostid(), extention.getPassword(), super.getOrgi(request) , extention) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/callcenter/extention.html?hostid="+extention.getHostid()));
|
||||
}
|
||||
|
||||
private Extention createNewExtention(String num , User user , String hostid , String password , String orgi , Extention src){
|
||||
Extention extno = new Extention();
|
||||
extno.setExtention(num);
|
||||
extno.setOrgi(orgi);
|
||||
extno.setCreater(user.getId());
|
||||
extno.setHostid(hostid);
|
||||
extno.setPassword(password);
|
||||
|
||||
extno.setPlaynum(src.isPlaynum());
|
||||
extno.setCallout(src.isCallout());
|
||||
extno.setRecord(src.isRecord());
|
||||
extno.setExtype(src.getExtype());
|
||||
extno.setMediapath(src.getMediapath());
|
||||
|
||||
extno.setSiptrunk(src.getSiptrunk());
|
||||
extno.setEnablewebrtc(src.isEnablewebrtc());
|
||||
int count = extentionRes.countByExtentionAndHostidAndOrgi(extno.getExtention() , hostid, orgi) ;
|
||||
if(count == 0){
|
||||
extentionRes.save(extno) ;
|
||||
}
|
||||
return extno ;
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/extention/edit")
|
||||
@Menu(type = "callcenter" , subtype = "extention" , access = false , admin = true)
|
||||
public ModelAndView extentionedit(ModelMap map , HttpServletRequest request , @Valid String id , @Valid String hostid) {
|
||||
map.addAttribute("extention" , extentionRes.findByIdAndOrgi(id, super.getOrgi(request)));
|
||||
map.put("pbxHost", pbxHostRes.findByIdAndOrgi(hostid, super.getOrgi(request))) ;
|
||||
map.put("mediaList" , mediaRes.findByHostidAndOrgi(hostid, super.getOrgi(request)));
|
||||
map.addAttribute("sipTrunkListList" , sipTrunkRes.findByHostidAndOrgi(hostid, super.getOrgi(request)));
|
||||
|
||||
return request(super.createRequestPageTempletResponse("/admin/callcenter/extention/edit"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/extention/update")
|
||||
@Menu(type = "callcenter" , subtype = "extention" , access = false , admin = true)
|
||||
public ModelAndView extentionupdate(ModelMap map , HttpServletRequest request , @Valid Extention extention) {
|
||||
if(!StringUtils.isBlank(extention.getId())){
|
||||
Extention ext = extentionRes.findByIdAndOrgi(extention.getId(), super.getOrgi(request)) ;
|
||||
if(ext!=null){
|
||||
// ext.setExtention(extention.getExtention());//分机号不能修改
|
||||
if(!StringUtils.isBlank(extention.getPassword())){
|
||||
ext.setPassword(extention.getPassword());
|
||||
}
|
||||
ext.setPlaynum(extention.isPlaynum());
|
||||
ext.setCallout(extention.isCallout());
|
||||
ext.setRecord(extention.isRecord());
|
||||
ext.setExtype(extention.getExtype());
|
||||
ext.setSubtype(extention.getSubtype());
|
||||
ext.setDescription(extention.getDescription());
|
||||
|
||||
ext.setMediapath(extention.getMediapath());
|
||||
|
||||
ext.setSiptrunk(extention.getSiptrunk());
|
||||
ext.setEnablewebrtc(extention.isEnablewebrtc());
|
||||
|
||||
ext.setUpdatetime(new Date());
|
||||
extentionRes.save(ext) ;
|
||||
|
||||
List<CallCenterAgent> callOutAgentList = CallOutQuene.extention(ext.getExtention()) ;
|
||||
for(CallCenterAgent callOutAgent : callOutAgentList) {
|
||||
callOutAgent.setSiptrunk(ext.getSiptrunk());
|
||||
CacheHelper.getCallCenterAgentCacheBean().put(callOutAgent.getUserid(), callOutAgent, callOutAgent.getOrgi());
|
||||
}
|
||||
}
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/callcenter/extention.html?hostid="+extention.getHostid()));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/extention/ivr")
|
||||
@Menu(type = "callcenter" , subtype = "extention" , access = false , admin = true)
|
||||
public ModelAndView ivr(ModelMap map , HttpServletRequest request , @Valid String id , @Valid String hostid) {
|
||||
map.addAttribute("extention" , extentionRes.findByIdAndOrgi(id, super.getOrgi(request)));
|
||||
map.put("pbxHost", pbxHostRes.findByIdAndOrgi(hostid, super.getOrgi(request))) ;
|
||||
map.put("mediaList" , mediaRes.findByHostidAndOrgi(hostid, super.getOrgi(request)));
|
||||
map.addAttribute("sipTrunkListList" , sipTrunkRes.findByHostidAndOrgi(hostid, super.getOrgi(request)));
|
||||
|
||||
map.put("serviceAiList",serviceAiRes.findByOrgi(super.getOrgi(request)) ) ;
|
||||
map.put("queList",queSurveyProcessRes.findByOrgi(super.getOrgi(request)) ) ;
|
||||
map.put("productList",productRes.findByOrgi(super.getOrgi(request)) ) ;
|
||||
|
||||
return request(super.createRequestPageTempletResponse("/admin/callcenter/extention/ivr"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/extention/ivr/update")
|
||||
@Menu(type = "callcenter" , subtype = "extention" , access = false , admin = true)
|
||||
public ModelAndView ivrupdate(ModelMap map , HttpServletRequest request , @Valid Extention extention) {
|
||||
if(!StringUtils.isBlank(extention.getId())){
|
||||
Extention ext = extentionRes.findByIdAndOrgi(extention.getId(), super.getOrgi(request)) ;
|
||||
if(ext!=null){
|
||||
|
||||
ext.setEnableai(extention.getEnableai());
|
||||
ext.setAiid(extention.getAiid());
|
||||
ext.setSceneid(extention.getSceneid());
|
||||
ext.setWelcomemsg(extention.getWelcomemsg()) ;
|
||||
ext.setWaitmsg(extention.getWaitmsg()) ;
|
||||
ext.setTipmessage(extention.getTipmessage());
|
||||
|
||||
ext.setAitype(extention.getAitype());
|
||||
ext.setBustype(extention.getBustype());
|
||||
ext.setProid(extention.getProid());
|
||||
ext.setQueid(extention.getQueid());
|
||||
|
||||
extentionRes.save(ext) ;
|
||||
}
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/callcenter/extention.html?hostid="+extention.getHostid()));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/extention/delete")
|
||||
@Menu(type = "callcenter" , subtype = "extention" , access = false , admin = true)
|
||||
public ModelAndView extentiondelete(ModelMap map , HttpServletRequest request , @Valid String id , @Valid String hostid) {
|
||||
if(!StringUtils.isBlank(id)){
|
||||
extentionRes.delete(id);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/callcenter/extention.html?hostid="+hostid));
|
||||
}
|
||||
}
|
@ -1,128 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.admin.callcenter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.exchange.CallCenterInterface;
|
||||
import com.chatopera.cc.app.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.ServiceAiRepository;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.PbxHost;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.app.persistence.repository.ExtentionRepository;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/callcenter")
|
||||
public class CallCenterResourceController extends Handler {
|
||||
|
||||
@Autowired
|
||||
private PbxHostRepository pbxHostRes ;
|
||||
|
||||
@Autowired
|
||||
private ExtentionRepository extentionRes;
|
||||
|
||||
@Autowired
|
||||
private ServiceAiRepository serviceAiRes ;
|
||||
|
||||
@RequestMapping(value = "/resource")
|
||||
@Menu(type = "callcenter" , subtype = "callcenter" , access = false , admin = true)
|
||||
public ModelAndView index(ModelMap map , HttpServletRequest request , @Valid String hostid) {
|
||||
List<PbxHost> pbxHostList = pbxHostRes.findByOrgi(super.getOrgi(request)) ;
|
||||
map.addAttribute("pbxHostList" , pbxHostList);
|
||||
|
||||
map.put("serviceAiList",serviceAiRes.findByOrgi(super.getOrgi(request)) ) ;
|
||||
|
||||
PbxHost pbxHost = null ;
|
||||
if(pbxHostList.size() > 0){
|
||||
map.addAttribute("pbxHost" , pbxHost = getPbxHost(pbxHostList, hostid));
|
||||
map.addAttribute("extentionList" , extentionRes.findByHostidAndOrgi(pbxHost.getId() , super.getOrgi(request)));
|
||||
}
|
||||
return request(super.createAdminTempletResponse("/admin/callcenter/resource/index"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/resource/config")
|
||||
@Menu(type = "callcenter" , subtype = "callcenter" , access = false , admin = true)
|
||||
public ModelAndView config(ModelMap map , HttpServletRequest request , @Valid String hostid) {
|
||||
List<PbxHost> pbxHostList = pbxHostRes.findByOrgi(super.getOrgi(request)) ;
|
||||
map.addAttribute("pbxHostList" , pbxHostList);
|
||||
PbxHost pbxHost = null ;
|
||||
if(pbxHostList.size() > 0){
|
||||
map.addAttribute("pbxHost" , pbxHost = getPbxHost(pbxHostList, hostid));
|
||||
map.addAttribute("extentionList" , extentionRes.findByHostidAndOrgi(pbxHost.getId() , super.getOrgi(request)));
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("/admin/callcenter/resource/config"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/resource/save")
|
||||
@Menu(type = "callcenter" , subtype = "callcenter" , access = false , admin = true)
|
||||
public ModelAndView save(ModelMap map , HttpServletRequest request , @Valid PbxHost pbxHost) throws Exception {
|
||||
PbxHost tempPbxHost = pbxHostRes.findByIdAndOrgi(pbxHost.getId(), super.getOrgi(request)) ;
|
||||
if(tempPbxHost != null){
|
||||
pbxHost.setCreater(tempPbxHost.getCreater());
|
||||
pbxHost.setCreatetime(tempPbxHost.getCreatetime());
|
||||
if(StringUtils.isBlank(pbxHost.getPassword())){
|
||||
pbxHost.setPassword(tempPbxHost.getPassword());
|
||||
}
|
||||
pbxHost.setOrgi(super.getOrgi(request));
|
||||
pbxHostRes.save(pbxHost) ;
|
||||
|
||||
if(MainContext.model.get("callcenter")!=null){
|
||||
CallCenterInterface callCenterImpl = (CallCenterInterface) MainContext.getContext().getBean("callcenter") ;
|
||||
callCenterImpl.init(pbxHost);
|
||||
}
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/callcenter/resource.html?hostid="+pbxHost.getId()));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/resource/pbxhost")
|
||||
@Menu(type = "callcenter" , subtype = "callcenter" , access = false , admin = true)
|
||||
public ModelAndView resourcepbx(ModelMap map , HttpServletRequest request , @Valid String hostid) {
|
||||
List<PbxHost> pbxHostList = pbxHostRes.findByOrgi(super.getOrgi(request)) ;
|
||||
map.addAttribute("pbxHostList" , pbxHostList);
|
||||
PbxHost pbxHost = null ;
|
||||
if(pbxHostList.size() > 0){
|
||||
map.addAttribute("pbxHost" , pbxHost = getPbxHost(pbxHostList, hostid));
|
||||
map.addAttribute("extentionList" , extentionRes.findByHostidAndOrgi(pbxHost.getId() , super.getOrgi(request)));
|
||||
}
|
||||
return request(super.createAdminTempletResponse("/admin/callcenter/resource/pbxhost"));
|
||||
}
|
||||
|
||||
private PbxHost getPbxHost(List<PbxHost> pbxHostList ,String hostid){
|
||||
PbxHost pbxHost = pbxHostList.get(0) ;
|
||||
if(!StringUtils.isBlank(hostid)){
|
||||
for(PbxHost pbx : pbxHostList){
|
||||
if(pbx.getId().equals(hostid)){
|
||||
pbxHost = pbx; break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return pbxHost ;
|
||||
}
|
||||
|
||||
}
|
@ -1,154 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.admin.callcenter;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.persistence.repository.PbxHostRepository;
|
||||
import com.chatopera.cc.app.model.SipTrunk;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.app.persistence.repository.SipTrunkRepository;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/callcenter")
|
||||
public class CallCenterSipTrunkController extends Handler{
|
||||
|
||||
@Autowired
|
||||
private PbxHostRepository pbxHostRes ;
|
||||
|
||||
|
||||
@Autowired
|
||||
private SipTrunkRepository sipTrunkRes ;
|
||||
|
||||
|
||||
@RequestMapping(value = "/siptrunk")
|
||||
@Menu(type = "callcenter" , subtype = "callcenterresource" , access = false , admin = true)
|
||||
public ModelAndView skill(ModelMap map , HttpServletRequest request , @Valid String hostid) {
|
||||
if(!StringUtils.isBlank(hostid)){
|
||||
map.addAttribute("pbxHost" , pbxHostRes.findByIdAndOrgi(hostid, super.getOrgi(request)));
|
||||
map.addAttribute("sipTrunkListList" , sipTrunkRes.findByHostidAndOrgi(hostid, super.getOrgi(request)));
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("/admin/callcenter/siptrunk/index"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/siptrunk/add")
|
||||
@Menu(type = "callcenter" , subtype = "extention" , access = false , admin = true)
|
||||
public ModelAndView extentionadd(ModelMap map , HttpServletRequest request , @Valid String hostid) {
|
||||
map.put("pbxHost", pbxHostRes.findByIdAndOrgi(hostid, super.getOrgi(request))) ;
|
||||
return request(super.createRequestPageTempletResponse("/admin/callcenter/siptrunk/add"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/siptrunk/save")
|
||||
@Menu(type = "callcenter" , subtype = "extention" , access = false , admin = true)
|
||||
public ModelAndView extentionsave(ModelMap map , HttpServletRequest request , @Valid SipTrunk siptrunk) {
|
||||
if(!StringUtils.isBlank(siptrunk.getName())){
|
||||
int count = sipTrunkRes.countByNameAndOrgi(siptrunk.getName(), super.getOrgi(request)) ;
|
||||
if(count == 0){
|
||||
siptrunk.setOrgi(super.getOrgi(request));
|
||||
siptrunk.setCreater(super.getUser(request).getId());
|
||||
sipTrunkRes.save(siptrunk) ;
|
||||
|
||||
CacheHelper.getSystemCacheBean().put(siptrunk.getId() ,siptrunk , siptrunk.getOrgi()) ;
|
||||
}
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/callcenter/siptrunk.html?hostid="+siptrunk.getHostid()));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/siptrunk/edit")
|
||||
@Menu(type = "callcenter" , subtype = "extention" , access = false , admin = true)
|
||||
public ModelAndView siptrunkedit(ModelMap map , HttpServletRequest request , @Valid String id , @Valid String hostid) {
|
||||
map.addAttribute("siptrunk" , sipTrunkRes.findByIdAndOrgi(id, super.getOrgi(request)));
|
||||
map.put("pbxHost", pbxHostRes.findByIdAndOrgi(hostid, super.getOrgi(request))) ;
|
||||
return request(super.createRequestPageTempletResponse("/admin/callcenter/siptrunk/edit"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/siptrunk/update")
|
||||
@Menu(type = "callcenter" , subtype = "extention" , access = false , admin = true)
|
||||
public ModelAndView pbxhostupdate(ModelMap map , HttpServletRequest request , @Valid SipTrunk siptrunk) {
|
||||
if(!StringUtils.isBlank(siptrunk.getId())){
|
||||
SipTrunk oldSipTrunk = sipTrunkRes.findByIdAndOrgi(siptrunk.getId(), super.getOrgi(request)) ;
|
||||
if(oldSipTrunk!=null){
|
||||
oldSipTrunk.setName(siptrunk.getName());
|
||||
oldSipTrunk.setSipserver(siptrunk.getSipserver());
|
||||
oldSipTrunk.setPort(siptrunk.getPort());
|
||||
oldSipTrunk.setProtocol(siptrunk.getProtocol());
|
||||
oldSipTrunk.setRegister(siptrunk.isRegister());
|
||||
oldSipTrunk.setDefaultsip(siptrunk.isDefaultsip());
|
||||
oldSipTrunk.setTitle(siptrunk.getTitle());
|
||||
|
||||
oldSipTrunk.setEnablecallagent(siptrunk.isEnablecallagent());
|
||||
|
||||
oldSipTrunk.setOutnumber(siptrunk.getOutnumber());
|
||||
oldSipTrunk.setBusyext(siptrunk.getBusyext());
|
||||
oldSipTrunk.setNotready(siptrunk.getNotready());
|
||||
|
||||
oldSipTrunk.setNoname(siptrunk.getNoname());
|
||||
|
||||
oldSipTrunk.setProvince(siptrunk.getProvince());
|
||||
oldSipTrunk.setCity(siptrunk.getCity());
|
||||
oldSipTrunk.setPrefix(siptrunk.getPrefix());
|
||||
|
||||
sipTrunkRes.save(oldSipTrunk);
|
||||
|
||||
CacheHelper.getSystemCacheBean().put(oldSipTrunk.getId() ,oldSipTrunk , oldSipTrunk.getOrgi()) ;
|
||||
}
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/callcenter/siptrunk.html?hostid="+siptrunk.getHostid()));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/siptrunk/code")
|
||||
@Menu(type = "callcenter" , subtype = "extention" , access = false , admin = true)
|
||||
public ModelAndView siptrunkcode(ModelMap map , HttpServletRequest request , @Valid String id , @Valid String hostid) {
|
||||
map.addAttribute("siptrunk" , sipTrunkRes.findByIdAndOrgi(id, super.getOrgi(request)));
|
||||
map.put("pbxHost", pbxHostRes.findByIdAndOrgi(hostid, super.getOrgi(request))) ;
|
||||
return request(super.createRequestPageTempletResponse("/admin/callcenter/siptrunk/code"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/siptrunk/code/update")
|
||||
@Menu(type = "callcenter" , subtype = "extention" , access = false , admin = true)
|
||||
public ModelAndView siptrunkcodeupdate(ModelMap map , HttpServletRequest request , @Valid SipTrunk siptrunk) {
|
||||
if(!StringUtils.isBlank(siptrunk.getId())){
|
||||
SipTrunk oldSipTrunk = sipTrunkRes.findByIdAndOrgi(siptrunk.getId(), super.getOrgi(request)) ;
|
||||
if(!StringUtils.isBlank(siptrunk.getSipcontent())){
|
||||
oldSipTrunk.setSipcontent(siptrunk.getSipcontent());
|
||||
sipTrunkRes.save(oldSipTrunk);
|
||||
|
||||
CacheHelper.getSystemCacheBean().put(oldSipTrunk.getId() ,oldSipTrunk , oldSipTrunk.getOrgi()) ;
|
||||
}
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/callcenter/siptrunk.html?hostid="+siptrunk.getHostid()));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/siptrunk/delete")
|
||||
@Menu(type = "callcenter" , subtype = "extention" , access = false , admin = true)
|
||||
public ModelAndView extentiondelete(ModelMap map , HttpServletRequest request , @Valid String id , @Valid String hostid) {
|
||||
if(!StringUtils.isBlank(id)){
|
||||
sipTrunkRes.delete(id);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/callcenter/siptrunk.html?hostid="+hostid));
|
||||
}
|
||||
}
|
@ -1,346 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.admin.organ;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.persistence.repository.OrganRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.SysDicRepository;
|
||||
import com.chatopera.cc.util.OnlineUserUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.app.persistence.repository.AreaTypeRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.OrganRoleRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.RoleRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.AgentStatus;
|
||||
import com.chatopera.cc.app.model.Organ;
|
||||
import com.chatopera.cc.app.model.OrganRole;
|
||||
import com.chatopera.cc.app.model.SysDic;
|
||||
import com.chatopera.cc.app.model.UKeFuDic;
|
||||
import com.chatopera.cc.app.model.User;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author 程序猿DD
|
||||
* @version 1.0.0
|
||||
* @blog http://blog.didispace.com
|
||||
*
|
||||
*/
|
||||
@Controller
|
||||
@RequestMapping("/admin/organ")
|
||||
public class OrganController extends Handler{
|
||||
|
||||
@Autowired
|
||||
private OrganRepository organRepository;
|
||||
|
||||
@Autowired
|
||||
private RoleRepository roleRepository;
|
||||
|
||||
@Autowired
|
||||
private SysDicRepository sysDicRepository;
|
||||
|
||||
@Autowired
|
||||
private AreaTypeRepository areaRepository;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private OrganRoleRepository organRoleRes ;
|
||||
|
||||
@Autowired
|
||||
private SysDicRepository sysDicRes;
|
||||
|
||||
@RequestMapping("/index")
|
||||
@Menu(type = "admin" , subtype = "organ")
|
||||
public ModelAndView index(ModelMap map , HttpServletRequest request , @Valid String organ, @Valid String msg) {
|
||||
List<Organ> organList = organRepository.findByOrgiAndOrgid(super.getOrgiByTenantshare(request),super.getOrgid(request)) ;
|
||||
map.addAttribute("organList", organList);
|
||||
if(organList.size() > 0){
|
||||
Organ organData = null ;
|
||||
if(!StringUtils.isBlank(organ) && !"null".equals(organ)){
|
||||
for(Organ data : organList){
|
||||
if(data.getId().equals(organ)){
|
||||
map.addAttribute("organData", data);
|
||||
organData = data;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
map.addAttribute("organData", organData = organList.get(0));
|
||||
}
|
||||
if(organData!=null){
|
||||
map.addAttribute("userList", userRepository.findByOrganAndOrgiAndDatastatus(organData.getId() , super.getOrgiByTenantshare(request),false));
|
||||
}
|
||||
}
|
||||
map.addAttribute("areaList", areaRepository.findByOrgi(super.getOrgiByTenantshare(request))) ;
|
||||
map.addAttribute("roleList", roleRepository.findByOrgiAndOrgid(super.getOrgiByTenantshare(request),super.getOrgid(request)));
|
||||
map.put("msg", msg);
|
||||
return request(super.createAdminTempletResponse("/admin/organ/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/add")
|
||||
@Menu(type = "admin" , subtype = "organ")
|
||||
public ModelAndView add(ModelMap map , HttpServletRequest request , @Valid String parent, @Valid String area) {
|
||||
map.addAttribute("areaList", areaRepository.findByOrgi(super.getOrgiByTenantshare(request))) ;
|
||||
if(!StringUtils.isBlank(parent)){
|
||||
map.addAttribute("organ", organRepository.findByIdAndOrgi(parent, super.getOrgiByTenantshare(request))) ;
|
||||
}
|
||||
if(!StringUtils.isBlank(area)){
|
||||
map.addAttribute("area", areaRepository.findByIdAndOrgi(area, super.getOrgiByTenantshare(request))) ;
|
||||
}
|
||||
|
||||
map.addAttribute("organList", organRepository.findByOrgiAndOrgid(super.getOrgiByTenantshare(request),super.getOrgid(request)));
|
||||
|
||||
return request(super.createRequestPageTempletResponse("/admin/organ/add"));
|
||||
}
|
||||
|
||||
@RequestMapping("/save")
|
||||
@Menu(type = "admin" , subtype = "organ")
|
||||
public ModelAndView save(HttpServletRequest request ,@Valid Organ organ) {
|
||||
Organ tempOrgan = organRepository.findByNameAndOrgiAndOrgid(organ.getName(), super.getOrgiByTenantshare(request),super.getOrgid(request)) ;
|
||||
String msg = "admin_organ_save_success" ;
|
||||
String firstId = null;
|
||||
if(tempOrgan != null){
|
||||
msg = "admin_organ_update_name_not";//分类名字重复
|
||||
}else{
|
||||
organ.setOrgi(super.getOrgiByTenantshare(request));
|
||||
|
||||
if(!StringUtils.isBlank(super.getUser(request).getOrgid())) {
|
||||
organ.setOrgid(super.getUser(request).getOrgid());
|
||||
}else {
|
||||
organ.setOrgid(MainContext.SYSTEM_ORGI);
|
||||
}
|
||||
firstId = organ.getId();
|
||||
|
||||
organRepository.save(organ) ;
|
||||
|
||||
OnlineUserUtils.clean(super.getOrgi(request));
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/organ/index.html?msg="+msg+"&organ="+firstId));
|
||||
}
|
||||
|
||||
@RequestMapping("/seluser")
|
||||
@Menu(type = "admin" , subtype = "seluser" , admin = true)
|
||||
public ModelAndView seluser(ModelMap map , HttpServletRequest request , @Valid String organ) {
|
||||
map.addAttribute("userList", userRepository.findByOrgiAndDatastatusAndOrgid(super.getOrgiByTenantshare(request) , false,super.getOrgid(request))) ;
|
||||
Organ organData = organRepository.findByIdAndOrgi(organ, super.getOrgiByTenantshare(request)) ;
|
||||
map.addAttribute("userOrganList", userRepository.findByOrganAndOrgiAndDatastatus(organ, super.getOrgiByTenantshare(request),false)) ;
|
||||
map.addAttribute("organ", organData) ;
|
||||
return request(super.createRequestPageTempletResponse("/admin/organ/seluser"));
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("/saveuser")
|
||||
@Menu(type = "admin" , subtype = "saveuser" , admin = true)
|
||||
public ModelAndView saveuser(HttpServletRequest request ,@Valid String[] users , @Valid String organ) {
|
||||
List<String> userList = new ArrayList<String>();
|
||||
if(users!=null && users.length > 0){
|
||||
for(String user : users){
|
||||
userList.add(user) ;
|
||||
}
|
||||
Organ organData = organRepository.findByIdAndOrgi(organ, super.getOrgiByTenantshare(request)) ;
|
||||
List<User> organUserList = userRepository.findAll(userList) ;
|
||||
for(User user : organUserList){
|
||||
user.setOrgan(organ);
|
||||
/**
|
||||
* 以下更新技能组状态
|
||||
*/
|
||||
AgentStatus agentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject(user.getId(), super.getOrgiByTenantshare(request)) ;
|
||||
if(agentStatus!=null){
|
||||
agentStatus.setSkill(organ);
|
||||
agentStatus.setSkillname(organData.getName());
|
||||
CacheHelper.getAgentStatusCacheBean().delete(user.getId(), user.getOrgi());
|
||||
CacheHelper.getAgentStatusCacheBean().put(user.getId(), agentStatus, super.getOrgiByTenantshare(request));
|
||||
}
|
||||
}
|
||||
userRepository.save(organUserList) ;
|
||||
OnlineUserUtils.clean(super.getOrgi(request));
|
||||
}
|
||||
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/organ/index.html?organ="+organ));
|
||||
}
|
||||
|
||||
@RequestMapping("/user/delete")
|
||||
@Menu(type = "admin" , subtype = "role")
|
||||
public ModelAndView userroledelete(HttpServletRequest request ,@Valid String id , @Valid String organ) {
|
||||
if(id!=null){
|
||||
User user= userRepository.getOne(id) ;
|
||||
user.setOrgan(null);
|
||||
userRepository.save(user) ;
|
||||
OnlineUserUtils.clean(super.getOrgi(request));
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/organ/index.html?organ="+organ));
|
||||
}
|
||||
|
||||
@RequestMapping("/edit")
|
||||
@Menu(type = "admin" , subtype = "organ")
|
||||
public ModelAndView edit(ModelMap map ,HttpServletRequest request , @Valid String id) {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("/admin/organ/edit")) ;
|
||||
map.addAttribute("areaList", areaRepository.findByOrgi(super.getOrgiByTenantshare(request))) ;
|
||||
view.addObject("organData", organRepository.findByIdAndOrgi(id, super.getOrgiByTenantshare(request))) ;
|
||||
|
||||
map.addAttribute("organList", organRepository.findByOrgiAndOrgid(super.getOrgiByTenantshare(request),super.getOrgid(request)));
|
||||
return view;
|
||||
}
|
||||
|
||||
@RequestMapping("/update")
|
||||
@Menu(type = "admin" , subtype = "organ")
|
||||
public ModelAndView update(HttpServletRequest request ,@Valid Organ organ) {
|
||||
Organ org = organRepository.findByNameAndOrgi(organ.getName(), super.getOrgi(request));
|
||||
String msg = "admin_organ_update_success" ;
|
||||
|
||||
if(org != null){
|
||||
if(org.getId().equals(organ.getId())){
|
||||
Organ tempOrgan = organRepository.findByIdAndOrgi(organ.getId(), super.getOrgiByTenantshare(request)) ;
|
||||
|
||||
if(tempOrgan != null){
|
||||
tempOrgan.setName(organ.getName());
|
||||
tempOrgan.setUpdatetime(new Date());
|
||||
tempOrgan.setOrgi(super.getOrgiByTenantshare(request));
|
||||
tempOrgan.setSkill(organ.isSkill());
|
||||
|
||||
tempOrgan.setParent(organ.getParent());
|
||||
|
||||
tempOrgan.setArea(organ.getArea());
|
||||
|
||||
if(!StringUtils.isBlank(super.getUser(request).getOrgid())) {
|
||||
tempOrgan.setOrgid(super.getUser(request).getOrgid());
|
||||
}else {
|
||||
tempOrgan.setOrgid(MainContext.SYSTEM_ORGI);
|
||||
}
|
||||
organRepository.save(tempOrgan) ;
|
||||
OnlineUserUtils.clean(super.getOrgi(request));
|
||||
}else{
|
||||
msg = "admin_organ_update_not_exist";//修改失败
|
||||
}
|
||||
}else{
|
||||
msg = "admin_organ_update_name_not" ;//分类名字重复
|
||||
}
|
||||
}else{
|
||||
Organ tempOrgan = organRepository.findByIdAndOrgi(organ.getId(), super.getOrgiByTenantshare(request)) ;
|
||||
|
||||
if(tempOrgan != null){
|
||||
tempOrgan.setName(organ.getName());
|
||||
tempOrgan.setUpdatetime(new Date());
|
||||
tempOrgan.setOrgi(super.getOrgiByTenantshare(request));
|
||||
tempOrgan.setSkill(organ.isSkill());
|
||||
|
||||
tempOrgan.setParent(organ.getParent());
|
||||
|
||||
tempOrgan.setArea(organ.getArea());
|
||||
|
||||
if(!StringUtils.isBlank(super.getUser(request).getOrgid())) {
|
||||
tempOrgan.setOrgid(super.getUser(request).getOrgid());
|
||||
}else {
|
||||
tempOrgan.setOrgid(MainContext.SYSTEM_ORGI);
|
||||
}
|
||||
organRepository.save(tempOrgan) ;
|
||||
OnlineUserUtils.clean(super.getOrgi(request));
|
||||
}else{
|
||||
msg = "admin_organ_update_not_exist";//修改失败
|
||||
}
|
||||
}
|
||||
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/organ/index.html?msg="+msg+"&organ="+organ.getId()));
|
||||
}
|
||||
|
||||
@RequestMapping("/area")
|
||||
@Menu(type = "admin" , subtype = "area")
|
||||
public ModelAndView area(ModelMap map ,HttpServletRequest request , @Valid String id) {
|
||||
|
||||
SysDic sysDic = sysDicRepository.findByCode(MainContext.UKEFU_SYSTEM_AREA_DIC) ;
|
||||
if(sysDic!=null){
|
||||
map.addAttribute("sysarea", sysDic) ;
|
||||
map.addAttribute("areaList", sysDicRepository.findByDicid(sysDic.getId())) ;
|
||||
}
|
||||
map.addAttribute("cacheList", UKeFuDic.getInstance().getDic(MainContext.UKEFU_SYSTEM_AREA_DIC)) ;
|
||||
|
||||
map.addAttribute("organData", organRepository.findByIdAndOrgi(id, super.getOrgiByTenantshare(request))) ;
|
||||
return request(super.createRequestPageTempletResponse("/admin/organ/area"));
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("/area/update")
|
||||
@Menu(type = "admin" , subtype = "organ")
|
||||
public ModelAndView areaupdate(HttpServletRequest request ,@Valid Organ organ) {
|
||||
Organ tempOrgan = organRepository.findByIdAndOrgi(organ.getId(), super.getOrgiByTenantshare(request)) ;
|
||||
String msg = "admin_organ_update_success" ;
|
||||
if(tempOrgan != null){
|
||||
tempOrgan.setArea(organ.getArea());
|
||||
organRepository.save(tempOrgan) ;
|
||||
OnlineUserUtils.clean(super.getOrgi(request));
|
||||
}else{
|
||||
msg = "admin_organ_update_not_exist";
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/organ/index.html?msg="+msg+"&organ="+organ.getId()));
|
||||
}
|
||||
|
||||
@RequestMapping("/delete")
|
||||
@Menu(type = "admin" , subtype = "organ")
|
||||
public ModelAndView delete(HttpServletRequest request ,@Valid Organ organ) {
|
||||
String msg = "admin_organ_delete" ;
|
||||
if(organ!=null){
|
||||
organRepository.delete(organ);
|
||||
OnlineUserUtils.clean(super.getOrgi(request));
|
||||
}else{
|
||||
msg = "admin_organ_not_exist" ;
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/organ/index.html?msg="+msg));
|
||||
}
|
||||
|
||||
@RequestMapping("/auth/save")
|
||||
@Menu(type = "admin" , subtype = "role")
|
||||
public ModelAndView authsave(HttpServletRequest request ,@Valid String id ,@Valid String menus) {
|
||||
Organ organData = organRepository.findByIdAndOrgi(id, super.getOrgiByTenantshare(request)) ;
|
||||
List<OrganRole> organRoleList = organRoleRes.findByOrgiAndOrgan(super.getOrgiByTenantshare(request), organData) ;
|
||||
organRoleRes.delete(organRoleList);
|
||||
if(!StringUtils.isBlank(menus)){
|
||||
String[] menusarray = menus.split(",") ;
|
||||
for(String menu : menusarray){
|
||||
OrganRole organRole = new OrganRole();
|
||||
SysDic sysDic = UKeFuDic.getInstance().getDicItem(menu) ;
|
||||
if(sysDic!=null && !"0".equals(sysDic.getParentid())) {
|
||||
organRole.setDicid(menu);
|
||||
organRole.setDicvalue(sysDic.getCode());
|
||||
|
||||
organRole.setOrgan(organData);
|
||||
organRole.setCreater(super.getUser(request).getId());
|
||||
organRole.setOrgi(super.getOrgiByTenantshare(request));
|
||||
organRole.setCreatetime(new Date());
|
||||
organRoleRes.save(organRole) ;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/organ/index.html?organ="+organData.getId()));
|
||||
}
|
||||
}
|
@ -1,249 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.admin.role;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.persistence.repository.RoleAuthRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.SysDicRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.UserRoleRepository;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.app.persistence.repository.RoleRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.Role;
|
||||
import com.chatopera.cc.app.model.RoleAuth;
|
||||
import com.chatopera.cc.app.model.SysDic;
|
||||
import com.chatopera.cc.app.model.UKeFuDic;
|
||||
import com.chatopera.cc.app.model.User;
|
||||
import com.chatopera.cc.app.model.UserRole;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/role")
|
||||
public class RoleController extends Handler{
|
||||
|
||||
@Autowired
|
||||
private RoleRepository roleRepository;
|
||||
|
||||
@Autowired
|
||||
private UserRoleRepository userRoleRes;
|
||||
|
||||
@Autowired
|
||||
private RoleAuthRepository roleAuthRes ;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private SysDicRepository sysDicRes;
|
||||
|
||||
@RequestMapping("/index")
|
||||
@Menu(type = "admin" , subtype = "role")
|
||||
public ModelAndView index(ModelMap map , HttpServletRequest request , @Valid String role) {
|
||||
List<Role> roleList = roleRepository.findByOrgiAndOrgid(super.getOrgiByTenantshare(request),super.getOrgid(request));
|
||||
map.addAttribute("roleList", roleList);
|
||||
if(roleList.size() > 0){
|
||||
Role roleData = null ;
|
||||
if(!StringUtils.isBlank(role)){
|
||||
for(Role data : roleList){
|
||||
if(data.getId().equals(role)){
|
||||
roleData = data ;
|
||||
map.addAttribute("roleData", data);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
map.addAttribute("roleData", roleData = roleList.get(0));
|
||||
}
|
||||
if(roleData!=null){
|
||||
map.addAttribute("userRoleList", userRoleRes.findByOrgiAndRole(super.getOrgiByTenantshare(request), roleData, new PageRequest(super.getP(request), super.getPs(request))) );
|
||||
}
|
||||
}
|
||||
return request(super.createAdminTempletResponse("/admin/role/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/add")
|
||||
@Menu(type = "admin" , subtype = "role")
|
||||
public ModelAndView add(ModelMap map , HttpServletRequest request) {
|
||||
return request(super.createRequestPageTempletResponse("/admin/role/add"));
|
||||
}
|
||||
|
||||
@RequestMapping("/save")
|
||||
@Menu(type = "admin" , subtype = "role")
|
||||
public ModelAndView save(HttpServletRequest request ,@Valid Role role) {
|
||||
Role tempRole = roleRepository.findByNameAndOrgiAndOrgid(role.getName(), super.getOrgiByTenantshare(request),super.getOrgid(request)) ;
|
||||
String msg = "admin_role_save_success" ;
|
||||
if(tempRole != null){
|
||||
msg = "admin_role_save_exist";
|
||||
}else{
|
||||
role.setOrgi(super.getOrgiByTenantshare(request));
|
||||
role.setCreater(super.getUser(request).getId());
|
||||
role.setCreatetime(new Date());
|
||||
role.setUpdatetime(new Date());
|
||||
|
||||
if(!StringUtils.isBlank(super.getUser(request).getOrgid())) {
|
||||
role.setOrgid(super.getUser(request).getOrgid());
|
||||
}else {
|
||||
role.setOrgid(MainContext.SYSTEM_ORGI);
|
||||
}
|
||||
|
||||
roleRepository.save(role) ;
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/role/index.html?msg="+msg));
|
||||
}
|
||||
|
||||
@RequestMapping("/seluser")
|
||||
@Menu(type = "admin" , subtype = "seluser" , admin = true)
|
||||
public ModelAndView seluser(ModelMap map , HttpServletRequest request , @Valid String role) {
|
||||
map.addAttribute("userList", userRepository.findByOrgiAndDatastatusAndOrgid(super.getOrgiByTenantshare(request) , false,super.getOrgid(request))) ;
|
||||
Role roleData = roleRepository.findByIdAndOrgi(role, super.getOrgiByTenantshare(request)) ;
|
||||
map.addAttribute("userRoleList", userRoleRes.findByOrgiAndRole(super.getOrgiByTenantshare(request) , roleData)) ;
|
||||
map.addAttribute("role", roleData) ;
|
||||
return request(super.createRequestPageTempletResponse("/admin/role/seluser"));
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("/saveuser")
|
||||
@Menu(type = "admin" , subtype = "saveuser" , admin = true)
|
||||
public ModelAndView saveuser(HttpServletRequest request ,@Valid String[] users , @Valid String role) {
|
||||
Role roleData = roleRepository.findByIdAndOrgi(role, super.getOrgiByTenantshare(request)) ;
|
||||
List<UserRole> userRoleList = userRoleRes.findByOrgiAndRole(super.getOrgiByTenantshare(request) , roleData) ;
|
||||
if(users!=null && users.length > 0){
|
||||
for(String user : users){
|
||||
boolean exist = false ;
|
||||
for(UserRole userRole : userRoleList){
|
||||
if(user.equals(userRole.getUser().getId())){
|
||||
exist = true ; continue ;
|
||||
}
|
||||
}
|
||||
if(exist == false) {
|
||||
UserRole userRole = new UserRole() ;
|
||||
userRole.setUser(new User(user));
|
||||
userRole.setRole(new Role(role));
|
||||
userRole.setOrgi(super.getOrgiByTenantshare(request));
|
||||
userRole.setCreater(super.getUser(request).getId());
|
||||
userRoleRes.save(userRole) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/role/index.html?role="+role));
|
||||
}
|
||||
|
||||
@RequestMapping("/user/delete")
|
||||
@Menu(type = "admin" , subtype = "role")
|
||||
public ModelAndView userroledelete(HttpServletRequest request ,@Valid String id , @Valid String role) {
|
||||
if(role!=null){
|
||||
userRoleRes.delete(id);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/role/index.html?role="+role));
|
||||
}
|
||||
|
||||
@RequestMapping("/edit")
|
||||
@Menu(type = "admin" , subtype = "role")
|
||||
public ModelAndView edit(ModelMap map , HttpServletRequest request ,@Valid String id) {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("/admin/role/edit")) ;
|
||||
view.addObject("roleData", roleRepository.findByIdAndOrgi(id, super.getOrgiByTenantshare(request))) ;
|
||||
return view;
|
||||
}
|
||||
|
||||
@RequestMapping("/update")
|
||||
@Menu(type = "admin" , subtype = "role")
|
||||
public ModelAndView update(HttpServletRequest request ,@Valid Role role) {
|
||||
Role tempRole = roleRepository.findByIdAndOrgi(role.getId(), super.getOrgiByTenantshare(request)) ;
|
||||
String msg = "admin_role_update_success" ;
|
||||
if(tempRole != null){
|
||||
tempRole.setName(role.getName());
|
||||
tempRole.setUpdatetime(new Date());
|
||||
|
||||
if(!StringUtils.isBlank(super.getUser(request).getOrgid())) {
|
||||
tempRole.setOrgid(super.getUser(request).getOrgid());
|
||||
}else {
|
||||
tempRole.setOrgid(MainContext.SYSTEM_ORGI);
|
||||
}
|
||||
|
||||
roleRepository.save(tempRole) ;
|
||||
}else{
|
||||
msg = "admin_role_update_not_exist";
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/role/index.html?msg="+msg));
|
||||
}
|
||||
|
||||
@RequestMapping("/delete")
|
||||
@Menu(type = "admin" , subtype = "role")
|
||||
public ModelAndView delete(HttpServletRequest request ,@Valid Role role) {
|
||||
String msg = "admin_role_delete" ;
|
||||
if(role!=null){
|
||||
userRoleRes.delete(userRoleRes.findByOrgiAndRole(super.getOrgiByTenantshare(request), role));
|
||||
roleRepository.delete(role);
|
||||
}else{
|
||||
msg = "admin_role_not_exist" ;
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/role/index.html?msg="+msg));
|
||||
}
|
||||
|
||||
@RequestMapping("/auth")
|
||||
@Menu(type = "admin" , subtype = "role")
|
||||
public ModelAndView auth(ModelMap map , HttpServletRequest request , @Valid String id) {
|
||||
SysDic sysDic = sysDicRes.findByCode(MainContext.UKEFU_SYSTEM_AUTH_DIC) ;
|
||||
if(sysDic!=null){
|
||||
map.addAttribute("resourceList", sysDicRes.findByDicid(sysDic.getId())) ;
|
||||
}
|
||||
map.addAttribute("sysDic", sysDic) ;
|
||||
Role role = roleRepository.findByIdAndOrgi(id, super.getOrgiByTenantshare(request)) ;
|
||||
map.addAttribute("role", role) ;
|
||||
map.addAttribute("roleAuthList", roleAuthRes.findByRoleidAndOrgi(role.getId(), super.getOrgiByTenantshare(request))) ;
|
||||
return request(super.createRequestPageTempletResponse("/admin/role/auth"));
|
||||
}
|
||||
|
||||
@RequestMapping("/auth/save")
|
||||
@Menu(type = "admin" , subtype = "role")
|
||||
public ModelAndView authsave(HttpServletRequest request ,@Valid String id ,@Valid String menus) {
|
||||
List<RoleAuth> roleAuthList = roleAuthRes.findByRoleidAndOrgi(id, super.getOrgiByTenantshare(request)) ;
|
||||
roleAuthRes.delete(roleAuthList);
|
||||
if(!StringUtils.isBlank(menus)){
|
||||
String[] menuarray = menus.split(",") ;
|
||||
for(String menu : menuarray){
|
||||
RoleAuth roleAuth = new RoleAuth();
|
||||
|
||||
roleAuth.setRoleid(id);
|
||||
roleAuth.setDicid(menu);
|
||||
SysDic sysDic = UKeFuDic.getInstance().getDicItem(menu) ;
|
||||
if(sysDic!=null && !"0".equals(sysDic.getParentid())) {
|
||||
roleAuth.setCreater(super.getUser(request).getId());
|
||||
roleAuth.setOrgi(super.getOrgiByTenantshare(request));
|
||||
roleAuth.setCreatetime(new Date());
|
||||
roleAuth.setName(sysDic.getName());
|
||||
roleAuth.setDicvalue(sysDic.getCode());
|
||||
roleAuthRes.save(roleAuth) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/role/index.html?role="+id));
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.admin.system;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.hazelcast.com.eclipsesource.json.JsonObject;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/monitor")
|
||||
public class HazelcastMonitorController extends Handler{
|
||||
|
||||
@RequestMapping("/hazelcast")
|
||||
@Menu(type = "admin" , subtype = "metadata" , admin = true)
|
||||
public ModelAndView index(ModelMap map , HttpServletRequest request , HttpServletResponse response) throws SQLException {
|
||||
Map<String , Object> jsonObjectMap = new HashMap< String , Object>();
|
||||
|
||||
jsonObjectMap.put("agentUser" , convert(CacheHelper.getAgentUserCacheBean().getStatics())) ;
|
||||
jsonObjectMap.put("agentStatus" , convert(CacheHelper.getAgentStatusCacheBean().getStatics())) ;
|
||||
|
||||
jsonObjectMap.put("apiUser" , convert(CacheHelper.getApiUserCacheBean().getStatics())) ;
|
||||
jsonObjectMap.put("imrCache" , convert(CacheHelper.getIMRCacheBean().getStatics())) ;
|
||||
jsonObjectMap.put("onlineUser" , convert(CacheHelper.getOnlineUserCacheBean().getStatics())) ;
|
||||
jsonObjectMap.put("systemCache" , convert(CacheHelper.getSystemCacheBean().getStatics())) ;
|
||||
|
||||
map.addAttribute("systemStatics", new Gson().toJson(jsonObjectMap)) ;
|
||||
|
||||
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setContentType("application/json; charset=utf-8");
|
||||
return request(super.createRequestPageTempletResponse("/admin/system/monitor/hazelcast"));
|
||||
}
|
||||
/**
|
||||
* 转换统计数据
|
||||
* @param json
|
||||
* @return
|
||||
*/
|
||||
private Map<String , Object> convert(JsonObject json){
|
||||
Map<String , Object> values = new HashMap<String , Object>();
|
||||
for(String key : json.names()){
|
||||
values.put(key, json.get(key)) ;
|
||||
}
|
||||
return values;
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.admin.system;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.persistence.repository.LogRepository;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/log")
|
||||
public class LogController extends Handler{
|
||||
|
||||
|
||||
@Autowired
|
||||
private LogRepository logRes;
|
||||
|
||||
@RequestMapping("/index")
|
||||
@Menu(type = "admin" , subtype = "syslog")
|
||||
public ModelAndView index(ModelMap map , HttpServletRequest request) {
|
||||
map.addAttribute("logList", logRes.findByOrgi(MainContext.SYSTEM_ORGI , new PageRequest(super.getP(request), super.getPs(request) , Direction.DESC , "createdate")));
|
||||
return request(super.createAdminTempletResponse("/admin/system/log/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/levels")
|
||||
@Menu(type = "admin" , subtype = "levels")
|
||||
public ModelAndView levels(ModelMap map , HttpServletRequest request , @Valid String levels) {
|
||||
map.addAttribute("logList", logRes.findByOrgiAndLevels(MainContext.SYSTEM_ORGI , levels , new PageRequest(super.getP(request), super.getPs(request) , Direction.DESC , "createdate")));
|
||||
map.addAttribute("levels" , levels) ;
|
||||
return request(super.createAdminTempletResponse("/admin/system/log/levels"));
|
||||
}
|
||||
|
||||
@RequestMapping("/detail")
|
||||
@Menu(type = "admin" , subtype = "detail")
|
||||
public ModelAndView detail(ModelMap map , HttpServletRequest request , @Valid String id) {
|
||||
map.addAttribute("log", logRes.findOne(id));
|
||||
return request(super.createRequestPageTempletResponse("/admin/system/log/detail"));
|
||||
}
|
||||
}
|
@ -1,240 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.admin.system;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.persistence.repository.SysDicRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.SysDic;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/admin/sysdic")
|
||||
public class SysDicController extends Handler{
|
||||
|
||||
|
||||
@Autowired
|
||||
private SysDicRepository sysDicRes;
|
||||
|
||||
@RequestMapping("/index")
|
||||
@Menu(type = "admin" , subtype = "sysdic")
|
||||
public ModelAndView index(ModelMap map , HttpServletRequest request) {
|
||||
map.addAttribute("sysDicList", sysDicRes.findByParentid( "0" , new PageRequest(super.getP(request), super.getPs(request) , Direction.DESC , "createtime")));
|
||||
return request(super.createAdminTempletResponse("/admin/system/sysdic/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/add")
|
||||
@Menu(type = "admin" , subtype = "sysdic")
|
||||
public ModelAndView add(ModelMap map , HttpServletRequest request) {
|
||||
return request(super.createRequestPageTempletResponse("/admin/system/sysdic/add"));
|
||||
}
|
||||
|
||||
@RequestMapping("/save")
|
||||
@Menu(type = "admin" , subtype = "sysdic")
|
||||
public ModelAndView save(HttpServletRequest request ,@Valid SysDic dic) {
|
||||
List<SysDic> sysDicList = sysDicRes.findByCodeOrName(dic.getCode() , dic.getName()) ;
|
||||
String msg = null ;
|
||||
if(sysDicList.size() == 0){
|
||||
dic.setParentid("0");
|
||||
dic.setHaschild(true);
|
||||
dic.setCreater(super.getUser(request).getId());
|
||||
dic.setCreatetime(new Date());
|
||||
sysDicRes.save(dic) ;
|
||||
reloadSysDicItem(dic , request);
|
||||
}else{
|
||||
msg = "exist" ;
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/sysdic/index.html"+(msg!=null ? "?msg="+msg : "")));
|
||||
}
|
||||
|
||||
@RequestMapping("/edit")
|
||||
@Menu(type = "admin" , subtype = "sysdic")
|
||||
public ModelAndView edit(ModelMap map , HttpServletRequest request , @Valid String id , @Valid String p) {
|
||||
map.addAttribute("sysDic", sysDicRes.findById(id)) ;
|
||||
map.addAttribute("p", p) ;
|
||||
return request(super.createRequestPageTempletResponse("/admin/system/sysdic/edit"));
|
||||
}
|
||||
|
||||
@RequestMapping("/update")
|
||||
@Menu(type = "admin" , subtype = "sysdic")
|
||||
public ModelAndView update(HttpServletRequest request ,@Valid SysDic dic, @Valid String p) {
|
||||
List<SysDic> sysDicList = sysDicRes.findByCodeOrName(dic.getCode() , dic.getName()) ;
|
||||
if(sysDicList.size() == 0 || (sysDicList.size() ==1 && sysDicList.get(0).getId().equals(dic.getId()))){
|
||||
SysDic sysDic = sysDicRes.findById(dic.getId()) ;
|
||||
sysDic.setName(dic.getName());
|
||||
sysDic.setCode(dic.getCode());
|
||||
sysDic.setCtype(dic.getCtype());
|
||||
sysDic.setIconskin(dic.getIconskin());
|
||||
sysDic.setIconstr(dic.getIconstr());
|
||||
sysDic.setDescription(dic.getDescription());
|
||||
sysDicRes.save(sysDic) ;
|
||||
|
||||
reloadSysDicItem(sysDic, request);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/sysdic/index.html?p="+p));
|
||||
}
|
||||
|
||||
@RequestMapping("/delete")
|
||||
@Menu(type = "admin" , subtype = "sysdic")
|
||||
public ModelAndView delete(ModelMap map , HttpServletRequest request , @Valid String id, @Valid String p) {
|
||||
SysDic sysDic = sysDicRes.findById(id);
|
||||
sysDicRes.delete(sysDicRes.findByDicid(id) );
|
||||
sysDicRes.delete(sysDic);
|
||||
|
||||
reloadSysDicItem(sysDic, request);
|
||||
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/sysdic/index.html?p="+p));
|
||||
}
|
||||
|
||||
@RequestMapping("/dicitem")
|
||||
@Menu(type = "admin" , subtype = "sysdic")
|
||||
public ModelAndView dicitem(ModelMap map , HttpServletRequest request , @Valid String id) {
|
||||
map.addAttribute("sysDic", sysDicRes.findById(id)) ;
|
||||
map.addAttribute("sysDicList", sysDicRes.findByParentid( id , new PageRequest(super.getP(request), super.getPs(request) , Direction.DESC , "createtime")));
|
||||
return request(super.createAdminTempletResponse("/admin/system/sysdic/dicitem"));
|
||||
}
|
||||
|
||||
@RequestMapping("/dicitem/add")
|
||||
@Menu(type = "admin" , subtype = "sysdic")
|
||||
public ModelAndView dicitemadd(ModelMap map , HttpServletRequest request , @Valid String id , @Valid String p) {
|
||||
map.addAttribute("sysDic", sysDicRes.findById(id)) ;
|
||||
map.addAttribute("p", p) ;
|
||||
return request(super.createRequestPageTempletResponse("/admin/system/sysdic/dicitemadd"));
|
||||
}
|
||||
|
||||
@RequestMapping("/dicitem/save")
|
||||
@Menu(type = "admin" , subtype = "sysdic")
|
||||
public ModelAndView dicitemsave(HttpServletRequest request ,@Valid SysDic dic , @Valid String p) {
|
||||
List<SysDic> sysDicList = sysDicRes.findByDicidAndName(dic.getDicid() , dic.getName()) ;
|
||||
String msg = null ;
|
||||
if(sysDicList.size() == 0){
|
||||
dic.setHaschild(true);
|
||||
dic.setOrgi(super.getOrgi(request));
|
||||
dic.setCreater(super.getUser(request).getId());
|
||||
dic.setCreatetime(new Date());
|
||||
sysDicRes.save(dic) ;
|
||||
reloadSysDicItem(dic, request);
|
||||
}else{
|
||||
msg = "exist" ;
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/sysdic/dicitem.html?id="+dic.getParentid()+(msg!=null ? "&p="+p+"&msg="+msg : "")));
|
||||
}
|
||||
|
||||
private void reloadSysDicItem(SysDic dic , HttpServletRequest request ){
|
||||
CacheHelper.getSystemCacheBean().put(dic.getId(), dic,super.getOrgi(request));
|
||||
if(dic.getDicid()!=null){
|
||||
SysDic root = (SysDic) CacheHelper.getSystemCacheBean().getCacheObject(dic.getDicid(), super.getOrgi(request)) ;
|
||||
List<SysDic> sysDicList = sysDicRes.findByDicid(dic.getDicid()) ;
|
||||
CacheHelper.getSystemCacheBean().put(root.getCode(), sysDicList,super.getOrgi(request));
|
||||
}else if(dic.getParentid().equals("0")){
|
||||
List<SysDic> sysDicList = sysDicRes.findByDicid(dic.getId()) ;
|
||||
CacheHelper.getSystemCacheBean().put(dic.getCode(), sysDicList,super.getOrgi(request));
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping("/dicitem/batadd")
|
||||
@Menu(type = "admin" , subtype = "sysdic")
|
||||
public ModelAndView dicitembatadd(ModelMap map , HttpServletRequest request , @Valid String id , @Valid String p) {
|
||||
map.addAttribute("sysDic", sysDicRes.findById(id)) ;
|
||||
map.addAttribute("p", p) ;
|
||||
return request(super.createRequestPageTempletResponse("/admin/system/sysdic/batadd"));
|
||||
}
|
||||
|
||||
@RequestMapping("/dicitem/batsave")
|
||||
@Menu(type = "admin" , subtype = "sysdic")
|
||||
public ModelAndView dicitembatsave(HttpServletRequest request ,@Valid SysDic sysDic , @Valid String content , @Valid String p) {
|
||||
String[] dicitems = content.split("[\n\r\n]") ;
|
||||
int count = 0 ;
|
||||
for(String dicitem : dicitems){
|
||||
String[] dicValues = dicitem.split("[\t, ;]{1,}") ;
|
||||
if(dicValues.length == 2 && dicValues[0].length()>0 && dicValues[1].length() >0){
|
||||
SysDic dic = new SysDic() ;
|
||||
dic.setOrgi(super.getOrgi(request));
|
||||
|
||||
dic.setName(dicValues[0]);
|
||||
dic.setCode(dicValues[1]);
|
||||
dic.setCreater(super.getUser(request).getId());
|
||||
dic.setParentid(sysDic.getParentid());
|
||||
dic.setDicid(sysDic.getDicid());
|
||||
dic.setSortindex(++count);
|
||||
dic.setCreatetime(new Date());
|
||||
dic.setUpdatetime(new Date());
|
||||
if(sysDicRes.findByDicidAndName(dic.getDicid(), dic.getName()).size() == 0){
|
||||
sysDicRes.save(dic) ;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
reloadSysDicItem(sysDicRes.getOne(sysDic.getParentid()), request);
|
||||
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/sysdic/dicitem.html?id="+sysDic.getParentid()+"&p="+p));
|
||||
}
|
||||
|
||||
@RequestMapping("/dicitem/edit")
|
||||
@Menu(type = "admin" , subtype = "sysdic")
|
||||
public ModelAndView dicitemedit(ModelMap map , HttpServletRequest request , @Valid String id , @Valid String p) {
|
||||
map.addAttribute("sysDic", sysDicRes.findById(id)) ;
|
||||
map.addAttribute("p", p) ;
|
||||
return request(super.createRequestPageTempletResponse("/admin/system/sysdic/dicitemedit"));
|
||||
}
|
||||
|
||||
@RequestMapping("/dicitem/update")
|
||||
@Menu(type = "admin" , subtype = "sysdic")
|
||||
public ModelAndView dicitemupdate(HttpServletRequest request ,@Valid SysDic dic, @Valid String p) {
|
||||
List<SysDic> sysDicList = sysDicRes.findByDicidAndName(dic.getDicid() , dic.getName()) ;
|
||||
if(sysDicList.size() == 0 || (sysDicList.size() ==1 && sysDicList.get(0).getId().equals(dic.getId()))){
|
||||
SysDic sysDic = sysDicRes.findById(dic.getId()) ;
|
||||
sysDic.setName(dic.getName());
|
||||
sysDic.setCode(dic.getCode());
|
||||
sysDic.setCtype(dic.getCtype());
|
||||
sysDic.setOrgi(super.getOrgi(request));
|
||||
sysDic.setIconskin(dic.getIconskin());
|
||||
sysDic.setIconstr(dic.getIconstr());
|
||||
sysDic.setDiscode(dic.isDiscode());
|
||||
sysDic.setDescription(dic.getDescription());
|
||||
sysDicRes.save(sysDic) ;
|
||||
|
||||
reloadSysDicItem(sysDic, request);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/sysdic/dicitem.html?id="+dic.getParentid()+"&p="+p));
|
||||
}
|
||||
|
||||
@RequestMapping("/dicitem/delete")
|
||||
@Menu(type = "admin" , subtype = "sysdic")
|
||||
public ModelAndView dicitemdelete(ModelMap map , HttpServletRequest request , @Valid String id, @Valid String p) {
|
||||
sysDicRes.delete(sysDicRes.findByDicid(id));
|
||||
SysDic dic = sysDicRes.getOne(id) ;
|
||||
sysDicRes.delete(dic);
|
||||
reloadSysDicItem(dic, request);
|
||||
return request(super.createRequestPageTempletResponse("redirect:/admin/sysdic/dicitem.html?id="+dic.getParentid()+"&p="+p));
|
||||
}
|
||||
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.api;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainUtils;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.persistence.repository.UserRoleRepository;
|
||||
import com.chatopera.cc.app.model.User;
|
||||
import com.chatopera.cc.app.model.UserRole;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/tokens")
|
||||
@Api(value = "登录服务", description = "账号密码登录")
|
||||
public class ApiLoginController extends Handler{
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private UserRoleRepository userRoleRes ;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@RequestMapping(method = RequestMethod.POST)
|
||||
@Menu(type = "apps" , subtype = "token" , access = true)
|
||||
@ApiOperation("登录服务,传入登录账号和密码")
|
||||
public ResponseEntity login(HttpServletRequest request , HttpServletResponse response , @Valid String username, @Valid String password) {
|
||||
User loginUser = userRepository.findByUsernameAndPassword(username , MainUtils.md5(password)) ;
|
||||
ResponseEntity entity = null ;
|
||||
if(loginUser!=null && !StringUtils.isBlank(loginUser.getId())){
|
||||
loginUser.setLogin(true);
|
||||
List<UserRole> userRoleList = userRoleRes.findByOrgiAndUser(loginUser.getOrgi(), loginUser);
|
||||
if(userRoleList!=null && userRoleList.size()>0){
|
||||
for(UserRole userRole : userRoleList){
|
||||
loginUser.getRoleList().add(userRole.getRole()) ;
|
||||
}
|
||||
}
|
||||
loginUser.setLastlogintime(new Date());
|
||||
if(!StringUtils.isBlank(loginUser.getId())){
|
||||
userRepository.save(loginUser) ;
|
||||
}
|
||||
String auth = MainUtils.getUUID();
|
||||
CacheHelper.getApiUserCacheBean().put(auth, loginUser, MainContext.SYSTEM_ORGI);
|
||||
entity = new ResponseEntity<>(auth, HttpStatus.OK) ;
|
||||
response.addCookie(new Cookie("authorization",auth));
|
||||
}else{
|
||||
entity = new ResponseEntity<>(HttpStatus.UNAUTHORIZED) ;
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
@Menu(type = "apps" , subtype = "token" , access = true)
|
||||
public ResponseEntity error(HttpServletRequest request) {
|
||||
User data = super.getUser(request);
|
||||
return new ResponseEntity<>(data , data!=null ? HttpStatus.OK : HttpStatus.UNAUTHORIZED);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@RequestMapping(method = RequestMethod.DELETE)
|
||||
public ResponseEntity logout(HttpServletRequest request , @RequestHeader(value="authorization") String authorization) {
|
||||
CacheHelper.getApiUserCacheBean().delete(authorization, MainContext.SYSTEM_ORGI);
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.api.rest;
|
||||
|
||||
import com.chatopera.cc.util.RestResult;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.persistence.repository.AgentUserRepository;
|
||||
import com.chatopera.cc.util.RestResultType;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/agentuser")
|
||||
@Api(value = "ACD服务", description = "获取当前对话中的访客")
|
||||
public class ApiAgentUserController extends Handler{
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRepository ;
|
||||
|
||||
/**
|
||||
* 获取当前对话中的访客
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping( method = RequestMethod.GET)
|
||||
@Menu(type = "apps" , subtype = "agentuser" , access = true)
|
||||
@ApiOperation("获取当前正在对话的访客信息,包含多种渠道来源的访客")
|
||||
public ResponseEntity<RestResult> list(HttpServletRequest request , @Valid String q) {
|
||||
return new ResponseEntity<>(new RestResult(RestResultType.OK , agentUserRepository.findByAgentnoAndOrgi(super.getUser(request).getId() , super.getOrgi(request) , new Sort(Direction.ASC,"status"))), HttpStatus.OK);
|
||||
}
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.api.rest;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.util.RestResult;
|
||||
import com.chatopera.cc.util.RestResultType;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.Contacts;
|
||||
import com.chatopera.cc.app.model.User;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/contacts")
|
||||
@Api(value = "联系人服务", description = "联系人管理功能")
|
||||
public class ApiContactsController extends Handler {
|
||||
|
||||
@Autowired
|
||||
private ContactsRepository contactsRepository;
|
||||
|
||||
/**
|
||||
* 返回用户列表,支持分页,分页参数为 p=1&ps=50,默认分页尺寸为 20条每页
|
||||
* @param request
|
||||
* @param username 搜索用户名,精确搜索
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping( method = RequestMethod.GET)
|
||||
@Menu(type = "apps" , subtype = "contacts" , access = true)
|
||||
@ApiOperation("返回联系人列表,支持分页,分页参数为 p=1&ps=50,默认分页尺寸为 20条每页")
|
||||
public ResponseEntity<RestResult> list(HttpServletRequest request , @Valid String creater , @Valid String q) {
|
||||
Page<Contacts> contactsList = null ;
|
||||
if(!StringUtils.isBlank(creater)){
|
||||
User user = super.getUser(request) ;
|
||||
contactsList = contactsRepository.findByCreaterAndSharesAndOrgi(user.getId(), user.getId(),super.getOrgi(request), false, q, new PageRequest(super.getP(request), super.getPs(request))) ;
|
||||
}else{
|
||||
contactsList = contactsRepository.findByOrgi(super.getOrgi(request), false , q , new PageRequest(super.getP(request), super.getPs(request))) ;
|
||||
}
|
||||
return new ResponseEntity<>(new RestResult(RestResultType.OK, contactsList), HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增或修改用户用户 ,在修改用户信息的时候,如果用户 密码未改变,请设置为 NULL
|
||||
* @param request
|
||||
* @param user
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.PUT)
|
||||
@Menu(type = "apps" , subtype = "contacts" , access = true)
|
||||
@ApiOperation("新增或修改联系人,联系人部分字段是字典选项,请从字典接口获取数据")
|
||||
public ResponseEntity<RestResult> put(HttpServletRequest request , @Valid Contacts contacts) {
|
||||
if(contacts != null && !StringUtils.isBlank(contacts.getName())){
|
||||
|
||||
contacts.setOrgi(super.getOrgi(request));
|
||||
contacts.setCreater(super.getUser(request).getId());
|
||||
contacts.setUsername(super.getUser(request).getUsername());
|
||||
|
||||
contacts.setOrgan(super.getUser(request).getOrgan());
|
||||
contacts.setCreatetime(new Date());
|
||||
contacts.setUpdatetime(new Date());
|
||||
|
||||
contactsRepository.save(contacts) ;
|
||||
}
|
||||
return new ResponseEntity<>(new RestResult(RestResultType.OK), HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除用户,只提供 按照用户ID删除 , 并且,不能删除系统管理员
|
||||
* @param request
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.DELETE)
|
||||
@Menu(type = "apps" , subtype = "contacts" , access = true)
|
||||
@ApiOperation("删除联系人,联系人删除是逻辑删除,将 datastatus字段标记为 true,即已删除")
|
||||
public ResponseEntity<RestResult> delete(HttpServletRequest request , @Valid String id) {
|
||||
RestResult result = new RestResult(RestResultType.OK) ;
|
||||
if(!StringUtils.isBlank(id)){
|
||||
Contacts contacts = contactsRepository.findOne(id) ;
|
||||
if(contacts!=null){ //系统管理员, 不允许 使用 接口删除
|
||||
contacts.setDatastatus(true);
|
||||
contactsRepository.save(contacts) ;
|
||||
}
|
||||
}
|
||||
return new ResponseEntity<>(result, HttpStatus.OK);
|
||||
}
|
||||
}
|
@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.api.rest;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.app.algorithm.AutomaticServiceDist;
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.persistence.repository.AgentStatusRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.OrganRepository;
|
||||
import com.chatopera.cc.util.RestResult;
|
||||
import com.chatopera.cc.app.model.AgentStatus;
|
||||
import com.chatopera.cc.app.model.User;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.chatopera.cc.app.persistence.repository.AgentUserRepository;
|
||||
import com.chatopera.cc.util.RestResultType;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.Organ;
|
||||
import com.chatopera.cc.app.model.SessionConfig;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/servicequene")
|
||||
@Api(value = "ACD服务", description = "获取队列统计信息")
|
||||
public class ApiServiceQueneController extends Handler{
|
||||
|
||||
@Autowired
|
||||
private AgentStatusRepository agentStatusRepository ;
|
||||
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRepository ;
|
||||
|
||||
@Autowired
|
||||
private OrganRepository organRes ;
|
||||
/**
|
||||
* 返回当前队列信息
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping( method = RequestMethod.GET)
|
||||
@Menu(type = "apps" , subtype = "user" , access = true)
|
||||
@ApiOperation("获取队列统计信息,包含当前队列服务中的访客数,排队人数,坐席数")
|
||||
public ResponseEntity<RestResult> list(HttpServletRequest request) {
|
||||
return new ResponseEntity<>(new RestResult(RestResultType.OK , AutomaticServiceDist.getAgentReport(super.getOrgi(request))), HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前队列信息
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping( method = RequestMethod.PUT)
|
||||
@Menu(type = "apps" , subtype = "user" , access = true)
|
||||
@ApiOperation("坐席状态操作,就绪、未就绪、忙")
|
||||
public ResponseEntity<RestResult> agentStatus(HttpServletRequest request , @Valid String status) {
|
||||
User user = super.getUser(request) ;
|
||||
AgentStatus agentStatus = null ;
|
||||
if(!StringUtils.isBlank(status) && status.equals(MainContext.AgentStatusEnum.READY.toString())) {
|
||||
List<AgentStatus> agentStatusList = agentStatusRepository.findByAgentnoAndOrgi(user.getId() , super.getOrgi(request));
|
||||
if(agentStatusList.size() > 0){
|
||||
agentStatus = agentStatusList.get(0) ;
|
||||
}else{
|
||||
agentStatus = new AgentStatus() ;
|
||||
agentStatus.setUserid(user.getId());
|
||||
agentStatus.setUsername(user.getUname());
|
||||
agentStatus.setAgentno(user.getId());
|
||||
agentStatus.setLogindate(new Date());
|
||||
|
||||
if(!StringUtils.isBlank(user.getOrgan())){
|
||||
Organ organ = organRes.findByIdAndOrgi(user.getOrgan(), super.getOrgiByTenantshare(request)) ;
|
||||
if(organ!=null && organ.isSkill()){
|
||||
agentStatus.setSkill(organ.getId());
|
||||
agentStatus.setSkillname(organ.getName());
|
||||
}
|
||||
}
|
||||
|
||||
SessionConfig sessionConfig = AutomaticServiceDist.initSessionConfig(super.getOrgi(request)) ;
|
||||
|
||||
agentStatus.setUsers(agentUserRepository.countByAgentnoAndStatusAndOrgi(user.getId(), MainContext.AgentUserStatusEnum.INSERVICE.toString(), super.getOrgi(request)));
|
||||
|
||||
agentStatus.setUpdatetime(new Date());
|
||||
|
||||
agentStatus.setOrgi(super.getOrgi(request));
|
||||
agentStatus.setMaxusers(sessionConfig.getMaxuser());
|
||||
agentStatusRepository.save(agentStatus) ;
|
||||
|
||||
}
|
||||
if(agentStatus!=null){
|
||||
/**
|
||||
* 更新当前用户状态
|
||||
*/
|
||||
agentStatus.setUsers(AutomaticServiceDist.getAgentUsers(agentStatus.getAgentno(), super.getOrgi(request)));
|
||||
agentStatus.setStatus(MainContext.AgentStatusEnum.READY.toString());
|
||||
CacheHelper.getAgentStatusCacheBean().put(agentStatus.getAgentno(), agentStatus, super.getOrgi(request));
|
||||
AutomaticServiceDist.recordAgentStatus(agentStatus.getAgentno(),agentStatus.getUsername(),agentStatus.getAgentno(), agentStatus.getSkill(),"0".equals(super.getUser(request).getUsertype()), agentStatus.getAgentno(), MainContext.AgentStatusEnum.OFFLINE.toString(), MainContext.AgentStatusEnum.READY.toString(), MainContext.AgentWorkType.MEIDIACHAT.toString() , agentStatus.getOrgi() , null);
|
||||
|
||||
AutomaticServiceDist.allotAgent(agentStatus.getAgentno(), super.getOrgi(request));
|
||||
}
|
||||
}else if(!StringUtils.isBlank(status)) {
|
||||
if(status.equals(MainContext.AgentStatusEnum.NOTREADY.toString())) {
|
||||
List<AgentStatus> agentStatusList = agentStatusRepository.findByAgentnoAndOrgi(user.getId() , super.getOrgi(request));
|
||||
for(AgentStatus temp : agentStatusList){
|
||||
AutomaticServiceDist.recordAgentStatus(temp.getAgentno(),temp.getUsername(),temp.getAgentno(), temp.getSkill(),"0".equals(super.getUser(request).getUsertype()), temp.getAgentno(), temp.isBusy() ? MainContext.AgentStatusEnum.BUSY.toString(): MainContext.AgentStatusEnum.READY.toString(), MainContext.AgentStatusEnum.NOTREADY.toString(), MainContext.AgentWorkType.MEIDIACHAT.toString() , temp.getOrgi() , temp.getUpdatetime());
|
||||
agentStatusRepository.delete(temp);
|
||||
}
|
||||
CacheHelper.getAgentStatusCacheBean().delete(super.getUser(request).getId(),super.getOrgi(request));
|
||||
}else if(!StringUtils.isBlank(status) && status.equals(MainContext.AgentStatusEnum.BUSY.toString())) {
|
||||
List<AgentStatus> agentStatusList = agentStatusRepository.findByAgentnoAndOrgi(user.getId() , super.getOrgi(request));
|
||||
if(agentStatusList.size() > 0){
|
||||
agentStatus = agentStatusList.get(0) ;
|
||||
agentStatus.setBusy(true);
|
||||
AutomaticServiceDist.recordAgentStatus(agentStatus.getAgentno(),agentStatus.getUsername(), agentStatus.getAgentno(),agentStatus.getSkill(), "0".equals(super.getUser(request).getUsertype()),agentStatus.getAgentno(), MainContext.AgentStatusEnum.READY.toString(), MainContext.AgentStatusEnum.BUSY.toString(), MainContext.AgentWorkType.MEIDIACHAT.toString() , agentStatus.getOrgi() , agentStatus.getUpdatetime());
|
||||
agentStatus.setUpdatetime(new Date());
|
||||
|
||||
agentStatusRepository.save(agentStatus);
|
||||
CacheHelper.getAgentStatusCacheBean().put(agentStatus.getAgentno(), agentStatus, super.getOrgi(request));
|
||||
}
|
||||
}else if(!StringUtils.isBlank(status) && status.equals(MainContext.AgentStatusEnum.NOTBUSY.toString())) {
|
||||
List<AgentStatus> agentStatusList = agentStatusRepository.findByAgentnoAndOrgi(user.getId() , super.getOrgi(request));
|
||||
if(agentStatusList.size() > 0){
|
||||
agentStatus = agentStatusList.get(0) ;
|
||||
agentStatus.setBusy(false);
|
||||
AutomaticServiceDist.recordAgentStatus(agentStatus.getAgentno(),agentStatus.getUsername(), agentStatus.getAgentno(),agentStatus.getSkill(), "0".equals(super.getUser(request).getUsertype()),agentStatus.getAgentno(), MainContext.AgentStatusEnum.BUSY.toString(), MainContext.AgentStatusEnum.READY.toString(), MainContext.AgentWorkType.MEIDIACHAT.toString() , agentStatus.getOrgi() , agentStatus.getUpdatetime());
|
||||
|
||||
agentStatus.setUpdatetime(new Date());
|
||||
agentStatusRepository.save(agentStatus);
|
||||
CacheHelper.getAgentStatusCacheBean().put(agentStatus.getAgentno(), agentStatus,super.getOrgi(request));
|
||||
}
|
||||
AutomaticServiceDist.allotAgent(agentStatus.getAgentno(), super.getOrgi(request));
|
||||
}
|
||||
AutomaticServiceDist.publishMessage(super.getOrgi(request) , "agent" , "api" , super.getUser(request).getId());
|
||||
}
|
||||
return new ResponseEntity<>(new RestResult(RestResultType.OK , agentStatus), HttpStatus.OK);
|
||||
}
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.api.rest;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.util.RestResult;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.RestResultType;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.UKeFuDic;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/sysdic")
|
||||
@Api(value = "数据字典" , description = "数据字典功能")
|
||||
public class ApiSysDicController extends Handler{
|
||||
|
||||
/**
|
||||
* 返回所有部门
|
||||
* @param request
|
||||
* @param username 搜索用户名,精确搜索
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping( method = RequestMethod.GET)
|
||||
@Menu(type = "apps" , subtype = "sysdic" , access = true)
|
||||
@ApiOperation("获取在线客服")
|
||||
public ResponseEntity<RestResult> list(HttpServletRequest request , @Valid String code) {
|
||||
return new ResponseEntity<>(new RestResult(RestResultType.OK, UKeFuDic.getInstance().getDic(code)), HttpStatus.OK);
|
||||
}
|
||||
}
|
@ -1,273 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.apps;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.basic.MainUtils;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.algorithm.AutomaticServiceDist;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.util.OnlineUserUtils;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.app.persistence.repository.InviteRecordRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.OnlineUserRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.OrgiSkillRelRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.UserEventRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.app.model.AgentStatus;
|
||||
import com.chatopera.cc.app.model.Contacts;
|
||||
import com.chatopera.cc.app.model.InviteRecord;
|
||||
import com.chatopera.cc.app.model.OnlineUser;
|
||||
import com.chatopera.cc.app.model.OrgiSkillRel;
|
||||
import com.chatopera.cc.app.model.User;
|
||||
|
||||
@Controller
|
||||
public class AppsController extends Handler {
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRes;
|
||||
|
||||
@Autowired
|
||||
private OnlineUserRepository onlineUserRes;
|
||||
|
||||
@Autowired
|
||||
private UserEventRepository userEventRes ;
|
||||
|
||||
@Autowired
|
||||
private InviteRecordRepository inviteRecordRes ;
|
||||
|
||||
@Autowired
|
||||
private ContactsRepository contactsRes ;
|
||||
|
||||
@Autowired
|
||||
private OrgiSkillRelRepository orgiSkillRelService;
|
||||
|
||||
@RequestMapping({"/apps/content"})
|
||||
@Menu(type="apps", subtype="content")
|
||||
public ModelAndView content(ModelMap map , HttpServletRequest request,@Valid String msg){
|
||||
|
||||
Page<OnlineUser> onlineUserList = this.onlineUserRes.findByOrgiAndStatus(super.getOrgi(request), MainContext.OnlineUserOperatorStatus.ONLINE.toString(), new PageRequest(super.getP(request), super.getPs(request), Sort.Direction.DESC, new String[] { "createtime" })) ;
|
||||
List<String> ids = new ArrayList<String>();
|
||||
for(OnlineUser onlineUser : onlineUserList.getContent()){
|
||||
onlineUser.setBetweentime((int) (System.currentTimeMillis() - onlineUser.getLogintime().getTime()));
|
||||
if(!StringUtils.isBlank(onlineUser.getContactsid())){
|
||||
ids.add(onlineUser.getContactsid()) ;
|
||||
}
|
||||
}
|
||||
if(ids.size() > 0){
|
||||
Iterable<Contacts> contactsList = contactsRes.findAll(ids) ;
|
||||
for(OnlineUser onlineUser : onlineUserList.getContent()){
|
||||
if(!StringUtils.isBlank(onlineUser.getContactsid())){
|
||||
for(Contacts contacts : contactsList){
|
||||
if(onlineUser.getContactsid().equals(contacts.getId())){
|
||||
onlineUser.setContacts(contacts);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
map.put("onlineUserList", onlineUserList);
|
||||
map.put("msg", msg);
|
||||
aggValues(map, request);
|
||||
|
||||
return request(super.createAppsTempletResponse("/apps/desktop/index"));
|
||||
}
|
||||
|
||||
private void aggValues(ModelMap map , HttpServletRequest request){
|
||||
map.put("agentReport", AutomaticServiceDist.getAgentReport(super.getOrgi(request))) ;
|
||||
map.put("webIMReport", MainUtils.getWebIMReport(userEventRes.findByOrgiAndCreatetimeRange(super.getOrgi(request), MainUtils.getStartTime() , MainUtils.getEndTime()))) ;
|
||||
|
||||
map.put("agents",getUsers(request).size()) ;
|
||||
|
||||
map.put("webIMInvite", MainUtils.getWebIMInviteStatus(onlineUserRes.findByOrgiAndStatus(super.getOrgi(request), MainContext.OnlineUserOperatorStatus.ONLINE.toString()))) ;
|
||||
|
||||
map.put("inviteResult", MainUtils.getWebIMInviteResult(onlineUserRes.findByOrgiAndAgentnoAndCreatetimeRange(super.getOrgi(request), super.getUser(request).getId() , MainUtils.getStartTime() , MainUtils.getEndTime()))) ;
|
||||
|
||||
map.put("agentUserCount", onlineUserRes.countByAgentForAgentUser(super.getOrgi(request), MainContext.AgentUserStatusEnum.INSERVICE.toString(),super.getUser(request).getId() , MainUtils.getStartTime() , MainUtils.getEndTime())) ;
|
||||
|
||||
map.put("agentServicesCount", onlineUserRes.countByAgentForAgentUser(super.getOrgi(request), MainContext.AgentUserStatusEnum.END.toString(),super.getUser(request).getId() , MainUtils.getStartTime() , MainUtils.getEndTime())) ;
|
||||
|
||||
map.put("agentServicesAvg", onlineUserRes.countByAgentForAvagTime(super.getOrgi(request), MainContext.AgentUserStatusEnum.END.toString(),super.getUser(request).getId() , MainUtils.getStartTime() , MainUtils.getEndTime())) ;
|
||||
|
||||
}
|
||||
@RequestMapping({"/apps/onlineuser"})
|
||||
@Menu(type="apps", subtype="onlineuser")
|
||||
public ModelAndView onlineuser(ModelMap map , HttpServletRequest request){
|
||||
Page<OnlineUser> onlineUserList = this.onlineUserRes.findByOrgiAndStatus(super.getOrgi(request), MainContext.OnlineUserOperatorStatus.ONLINE.toString(), new PageRequest(super.getP(request), super.getPs(request), Sort.Direction.DESC, new String[] { "createtime" })) ;
|
||||
List<String> ids = new ArrayList<String>();
|
||||
for(OnlineUser onlineUser : onlineUserList.getContent()){
|
||||
onlineUser.setBetweentime((int) (System.currentTimeMillis() - onlineUser.getLogintime().getTime()));
|
||||
if(!StringUtils.isBlank(onlineUser.getContactsid())){
|
||||
ids.add(onlineUser.getContactsid()) ;
|
||||
}
|
||||
}
|
||||
if(ids.size() > 0){
|
||||
Iterable<Contacts> contactsList = contactsRes.findAll(ids) ;
|
||||
for(OnlineUser onlineUser : onlineUserList.getContent()){
|
||||
if(!StringUtils.isBlank(onlineUser.getContactsid())){
|
||||
for(Contacts contacts : contactsList){
|
||||
if(onlineUser.getContactsid().equals(contacts.getId())){
|
||||
onlineUser.setContacts(contacts);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
map.put("onlineUserList", onlineUserList);
|
||||
aggValues(map, request);
|
||||
|
||||
return request(super.createAppsTempletResponse("/apps/desktop/onlineuser"));
|
||||
}
|
||||
|
||||
@RequestMapping({"/apps/invite"})
|
||||
@Menu(type="apps", subtype="invite")
|
||||
public ModelAndView invite(ModelMap map , HttpServletRequest request , @Valid String id) throws Exception{
|
||||
OnlineUser onlineUser = onlineUserRes.findOne(id) ;
|
||||
if(onlineUser!=null){
|
||||
onlineUser.setInvitestatus(MainContext.OnlineUserInviteStatus.INVITE.toString());
|
||||
onlineUser.setInvitetimes(onlineUser.getInvitetimes()+1);
|
||||
onlineUserRes.save(onlineUser) ;
|
||||
OnlineUserUtils.sendWebIMClients(onlineUser.getUserid() , "invite");
|
||||
InviteRecord record = new InviteRecord() ;
|
||||
record.setAgentno(super.getUser(request).getId());
|
||||
record.setUserid(onlineUser.getUserid());
|
||||
record.setAppid(onlineUser.getAppid());
|
||||
record.setOrgi(super.getOrgi(request));
|
||||
inviteRecordRes.save(record) ;
|
||||
}
|
||||
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/content.html"));
|
||||
}
|
||||
|
||||
@RequestMapping({"/apps/profile"})
|
||||
@Menu(type="apps", subtype="content")
|
||||
public ModelAndView profile(ModelMap map , HttpServletRequest request,@Valid String index){
|
||||
map.addAttribute("userData",super.getUser(request)) ;
|
||||
map.addAttribute("index",index) ;
|
||||
return request(super.createRequestPageTempletResponse("/apps/desktop/profile"));
|
||||
}
|
||||
|
||||
@RequestMapping({"/apps/profile/save"})
|
||||
@Menu(type="apps", subtype="content")
|
||||
public ModelAndView profile(ModelMap map , HttpServletRequest request , @Valid User user, @Valid String index){
|
||||
User tempUser = userRes.getOne(user.getId()) ;
|
||||
if(tempUser != null){
|
||||
String msg = validUserUpdate(user,tempUser);
|
||||
if(!StringUtils.isBlank(msg)){
|
||||
if(StringUtils.isBlank(index)) {
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/content.html?msg="+msg));
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index.html?msg="+msg));
|
||||
}
|
||||
tempUser.setUname(user.getUname());
|
||||
tempUser.setEmail(user.getEmail());
|
||||
tempUser.setMobile(user.getMobile());
|
||||
//切换成非坐席 判断是否坐席 以及 是否有对话
|
||||
if(!user.isAgent()) {
|
||||
AgentStatus agentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject((super.getUser(request)).getId(), super.getOrgi(request));
|
||||
if(!(agentStatus==null && AutomaticServiceDist.getAgentUsers(super.getUser(request).getId(), super.getOrgi(request))==0)) {
|
||||
if(StringUtils.isBlank(index)) {
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/content.html?msg=t1"));
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index.html?msg=t1"));
|
||||
}
|
||||
}
|
||||
tempUser.setAgent(user.isAgent());
|
||||
tempUser.setOrgi(super.getOrgiByTenantshare(request));
|
||||
if(!StringUtils.isBlank(user.getPassword())){
|
||||
tempUser.setPassword(MainUtils.md5(user.getPassword()));
|
||||
}
|
||||
if(tempUser.getCreatetime() == null){
|
||||
tempUser.setCreatetime(new Date());
|
||||
}
|
||||
tempUser.setUpdatetime(new Date());
|
||||
userRes.save(tempUser) ;
|
||||
User sessionUser = super.getUser(request) ;
|
||||
tempUser.setRoleList(sessionUser.getRoleList()) ;
|
||||
tempUser.setRoleAuthMap(sessionUser.getRoleAuthMap());
|
||||
tempUser.setMyorgans(sessionUser.getMyorgans());
|
||||
User u = tempUser;
|
||||
u.setOrgi(super.getOrgi(request));
|
||||
super.setUser(request, u);
|
||||
}
|
||||
if(StringUtils.isBlank(index)) {
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/content.html"));
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index.html"));
|
||||
}
|
||||
|
||||
private String validUserUpdate(User user,User oldUser) {
|
||||
String msg = "";
|
||||
User tempUser = userRes.findByUsernameAndDatastatus(user.getUsername(),false) ;
|
||||
if(tempUser!=null&&!user.getUsername().equals(oldUser.getUsername())) {
|
||||
msg = "username_exist";
|
||||
return msg;
|
||||
}
|
||||
tempUser = userRes.findByEmailAndDatastatus(user.getEmail(),false) ;
|
||||
if(tempUser!=null&&!user.getEmail().equals(oldUser.getEmail())) {
|
||||
msg = "email_exist";
|
||||
return msg;
|
||||
}
|
||||
tempUser = userRes.findByMobileAndDatastatus(user.getMobile(),false) ;
|
||||
if(tempUser!=null&&!user.getMobile().equals(oldUser.getMobile())) {
|
||||
msg = "mobile_exist";
|
||||
return msg;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
/**
|
||||
* 获取当前产品下人员信息
|
||||
* @param request
|
||||
* @param q
|
||||
* @return
|
||||
*/
|
||||
private List<User> getUsers(HttpServletRequest request){
|
||||
List<User> userList = null;
|
||||
if(super.isTenantshare()) {
|
||||
List<String> organIdList = new ArrayList<>();
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelService.findByOrgi(super.getOrgi(request)) ;
|
||||
if(!orgiSkillRelList.isEmpty()) {
|
||||
for(OrgiSkillRel rel:orgiSkillRelList) {
|
||||
organIdList.add(rel.getSkillid());
|
||||
}
|
||||
}
|
||||
userList=userRes.findByOrganInAndAgentAndDatastatus(organIdList,true,false);
|
||||
}else {
|
||||
userList=userRes.findByOrgiAndAgentAndDatastatus(super.getOrgi(request), true,false) ;
|
||||
}
|
||||
return userList;
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,126 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.app.handler.apps.callcenter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.util.es.SearchTools;
|
||||
import com.chatopera.cc.util.es.UKDataBean;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.util.CallCenterUtils;
|
||||
import com.chatopera.cc.app.model.User;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.freeswitch.model.CallCenterAgent;
|
||||
import com.chatopera.cc.app.persistence.impl.CallOutQuene;
|
||||
import com.chatopera.cc.app.persistence.repository.ExtentionRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.SipTrunkRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.SipTrunk;
|
||||
|
||||
import freemarker.template.TemplateException;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/callcenter")
|
||||
public class SipTrunkController extends Handler{
|
||||
|
||||
@Autowired
|
||||
private ExtentionRepository extentionRes;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private SipTrunkRepository sipTrunkRes ;
|
||||
|
||||
@RequestMapping(value = "/siptrunk")
|
||||
@Menu(type = "callcenter" , subtype = "extention" , access = true)
|
||||
public ModelAndView detail(ModelMap map , HttpServletRequest request , HttpServletResponse response ,@Valid String extno) throws IOException, TemplateException {
|
||||
SipTrunk sipTrunk = CallCenterUtils.siptrunk(extno, sipTrunkRes, extentionRes) ;
|
||||
map.addAttribute("siptrunk" , sipTrunk);
|
||||
response.setContentType("Content-type: text/plain; charset=utf-8");
|
||||
return request(super.createRequestPageTempletResponse("/apps/business/callcenter/extention/siptrunk"));
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/agent")
|
||||
@Menu(type = "callcenter" , subtype = "agent" , access = true)
|
||||
public ModelAndView agent(ModelMap map , HttpServletRequest request , HttpServletResponse response ,@Valid String ani ,@Valid String dest,@Valid String sip) throws IOException, TemplateException {
|
||||
SipTrunk sipTrunk = CallCenterUtils.siptrunk(sip, sipTrunkRes) ;
|
||||
map.addAttribute("siptrunk" , sipTrunk);
|
||||
String agent = null ;
|
||||
response.setContentType("Content-type: text/plain; charset=utf-8");
|
||||
if(sipTrunk!=null) {
|
||||
PageImpl<UKDataBean> dataBeanList = SearchTools.namesearch(sipTrunk.getOrgi(), ani) ;
|
||||
if(dataBeanList!=null && dataBeanList.getContent().size() > 0) {
|
||||
UKDataBean dataBean = dataBeanList.getContent().get(0) ;
|
||||
if(dataBean.getValues().get(MainContext.UKEFU_SYSTEM_DIS_AGENT)!=null) {
|
||||
String disagent = (String) dataBean.getValues().get(MainContext.UKEFU_SYSTEM_DIS_AGENT) ;
|
||||
/**
|
||||
* 找到了 坐席
|
||||
*/
|
||||
CallCenterAgent callCenterAgent = (CallCenterAgent) CacheHelper.getCallCenterAgentCacheBean().getCacheObject(disagent, sipTrunk.getOrgi()) ;
|
||||
if(callCenterAgent!=null) {
|
||||
/**
|
||||
* 坐席在线
|
||||
*/
|
||||
agent = callCenterAgent.getExtno() ;
|
||||
}else if(sipTrunk.isEnablecallagent()){//坐席不在线
|
||||
User user = userRepository.findById(disagent) ;
|
||||
if(!StringUtils.isBlank(user.getMobile())) {
|
||||
agent = user.getMobile() ;
|
||||
}
|
||||
}
|
||||
}else {
|
||||
/**
|
||||
* 名单未分配 , 转给网关进来的任何一个坐席 , 从当前登录系统的 坐席中选取一个
|
||||
*/
|
||||
List<CallCenterAgent> agentList = CallOutQuene.service(sipTrunk.getId()) ;
|
||||
if(agentList.size() > 0) {
|
||||
CallCenterAgent callCenterAgent = agentList.get(0) ;
|
||||
agent = callCenterAgent.getExtno() ;
|
||||
}else if(!StringUtils.isBlank(sipTrunk.getNotready())){
|
||||
agent = sipTrunk.getNotready() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(StringUtils.isBlank(agent) && !StringUtils.isBlank(sipTrunk.getNoname())){
|
||||
/**
|
||||
* 未找到名单,从 SIPTrunk里选取一个 转移号码
|
||||
*/
|
||||
agent = sipTrunk.getNoname() ;
|
||||
}
|
||||
}
|
||||
map.addAttribute("agent" , agent);
|
||||
|
||||
return request(super.createRequestPageTempletResponse("/apps/business/callcenter/extention/agent"));
|
||||
}
|
||||
}
|
@ -1,433 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.app.handler.apps.contacts;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.PinYinTools;
|
||||
import com.chatopera.cc.app.basic.MainUtils;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.concurrent.dsdata.DSData;
|
||||
import com.chatopera.cc.concurrent.dsdata.DSDataEvent;
|
||||
import com.chatopera.cc.concurrent.dsdata.ExcelImportProecess;
|
||||
import com.chatopera.cc.concurrent.dsdata.export.ExcelExporterProcess;
|
||||
import com.chatopera.cc.concurrent.dsdata.process.ContactsProcess;
|
||||
import com.chatopera.cc.app.model.Contacts;
|
||||
import com.chatopera.cc.app.model.MetadataTable;
|
||||
import com.chatopera.cc.app.model.PropertiesEvent;
|
||||
import com.chatopera.cc.app.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.PropertiesEventRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.ReporterRepository;
|
||||
import com.chatopera.cc.util.PropertiesEventUtils;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/contacts")
|
||||
public class ContactsController extends Handler {
|
||||
private final static Logger logger = LoggerFactory.getLogger(ContactsController.class);
|
||||
|
||||
@Autowired
|
||||
private ContactsRepository contactsRes;
|
||||
|
||||
@Autowired
|
||||
private PropertiesEventRepository propertiesEventRes;
|
||||
|
||||
@Autowired
|
||||
private ReporterRepository reporterRes;
|
||||
|
||||
@Autowired
|
||||
private MetadataRepository metadataRes;
|
||||
|
||||
@Value("${web.upload-path}")
|
||||
private String path;
|
||||
|
||||
@RequestMapping("/index")
|
||||
@Menu(type = "customer", subtype = "index")
|
||||
public ModelAndView index(ModelMap map, HttpServletRequest request, @Valid String q, @Valid String ckind) throws CSKefuException {
|
||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||
|
||||
if(!super.esOrganFilter(request, boolQueryBuilder)){
|
||||
return request(super.createAppsTempletResponse("/apps/business/contacts/index"));
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(q)) {
|
||||
map.put("q", q);
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(ckind)) {
|
||||
boolQueryBuilder.must(termQuery("ckind", ckind));
|
||||
map.put("ckind", ckind);
|
||||
}
|
||||
|
||||
map.addAttribute("contactsList", contactsRes.findByCreaterAndSharesAndOrgi(super.getUser(request).getId(), super.getUser(request).getId(), super.getOrgi(request), null, null, false, boolQueryBuilder, q, new PageRequest(super.getP(request), super.getPs(request))));
|
||||
|
||||
return request(super.createAppsTempletResponse("/apps/business/contacts/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/today")
|
||||
@Menu(type = "customer", subtype = "today")
|
||||
public ModelAndView today(ModelMap map, HttpServletRequest request, @Valid String q, @Valid String ckind) throws CSKefuException {
|
||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||
if(!super.esOrganFilter(request, boolQueryBuilder)){
|
||||
return request(super.createAppsTempletResponse("/apps/business/contacts/index"));
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(q)) {
|
||||
map.put("q", q);
|
||||
}
|
||||
if (!StringUtils.isBlank(ckind)) {
|
||||
boolQueryBuilder.must(termQuery("ckind", ckind));
|
||||
map.put("ckind", ckind);
|
||||
}
|
||||
map.addAttribute("contactsList", contactsRes.findByCreaterAndSharesAndOrgi(super.getUser(request).getId(), super.getUser(request).getId(), super.getOrgi(request), MainUtils.getStartTime(), null, false, boolQueryBuilder, q, new PageRequest(super.getP(request), super.getPs(request))));
|
||||
|
||||
return request(super.createAppsTempletResponse("/apps/business/contacts/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/week")
|
||||
@Menu(type = "customer", subtype = "week")
|
||||
public ModelAndView week(ModelMap map, HttpServletRequest request, @Valid String q, @Valid String ckind) throws CSKefuException {
|
||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||
if(!super.esOrganFilter(request, boolQueryBuilder)){
|
||||
return request(super.createAppsTempletResponse("/apps/business/contacts/index"));
|
||||
}
|
||||
|
||||
if (!StringUtils.isBlank(q)) {
|
||||
map.put("q", q);
|
||||
}
|
||||
if (!StringUtils.isBlank(ckind)) {
|
||||
boolQueryBuilder.must(termQuery("ckind", ckind));
|
||||
map.put("ckind", ckind);
|
||||
}
|
||||
map.addAttribute("contactsList", contactsRes.findByCreaterAndSharesAndOrgi(super.getUser(request).getId(), super.getUser(request).getId(), super.getOrgi(request), MainUtils.getWeekStartTime(), null, false, boolQueryBuilder, q, new PageRequest(super.getP(request), super.getPs(request))));
|
||||
|
||||
return request(super.createAppsTempletResponse("/apps/business/contacts/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/creater")
|
||||
@Menu(type = "customer", subtype = "creater")
|
||||
public ModelAndView creater(ModelMap map, HttpServletRequest request, @Valid String q, @Valid String ckind) throws CSKefuException {
|
||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||
if(!super.esOrganFilter(request, boolQueryBuilder)){
|
||||
return request(super.createAppsTempletResponse("/apps/business/contacts/index"));
|
||||
}
|
||||
|
||||
boolQueryBuilder.must(termQuery("creater", super.getUser(request).getId()));
|
||||
|
||||
if (!StringUtils.isBlank(ckind)) {
|
||||
boolQueryBuilder.must(termQuery("ckind", ckind));
|
||||
map.put("ckind", ckind);
|
||||
}
|
||||
if (!StringUtils.isBlank(q)) {
|
||||
map.put("q", q);
|
||||
}
|
||||
|
||||
map.addAttribute("contactsList", contactsRes.findByCreaterAndSharesAndOrgi(super.getUser(request).getId(), super.getUser(request).getId(), super.getOrgi(request), null, null, false, boolQueryBuilder, q, new PageRequest(super.getP(request), super.getPs(request))));
|
||||
return request(super.createAppsTempletResponse("/apps/business/contacts/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/delete")
|
||||
@Menu(type = "contacts", subtype = "contacts")
|
||||
public ModelAndView delete(HttpServletRequest request, @Valid Contacts contacts, @Valid String p) {
|
||||
if (contacts != null) {
|
||||
contacts = contactsRes.findOne(contacts.getId());
|
||||
contacts.setDatastatus(true); //客户和联系人都是 逻辑删除
|
||||
contactsRes.save(contacts);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/contacts/index.html?p=" + p + "&ckind=" + contacts.getCkind()));
|
||||
}
|
||||
|
||||
@RequestMapping("/add")
|
||||
@Menu(type = "contacts", subtype = "add")
|
||||
public ModelAndView add(ModelMap map, HttpServletRequest request, @Valid String ckind) {
|
||||
map.addAttribute("ckind", ckind);
|
||||
return request(super.createRequestPageTempletResponse("/apps/business/contacts/add"));
|
||||
}
|
||||
|
||||
@RequestMapping("/save")
|
||||
@Menu(type = "contacts", subtype = "save")
|
||||
public ModelAndView save(HttpServletRequest request, @Valid Contacts contacts) {
|
||||
contacts.setCreater(super.getUser(request).getId());
|
||||
contacts.setOrgi(super.getOrgi(request));
|
||||
contacts.setOrgan(super.getUser(request).getOrgan());
|
||||
contacts.setPinyin(PinYinTools.getInstance().getFirstPinYin(contacts.getName()));
|
||||
if (StringUtils.isBlank(contacts.getCusbirthday())) {
|
||||
contacts.setCusbirthday(null);
|
||||
}
|
||||
contactsRes.save(contacts);
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/contacts/index.html?ckind=" + contacts.getCkind()));
|
||||
}
|
||||
|
||||
@RequestMapping("/edit")
|
||||
@Menu(type = "contacts", subtype = "contacts")
|
||||
public ModelAndView edit(ModelMap map, HttpServletRequest request, @Valid String id) {
|
||||
map.addAttribute("contacts", contactsRes.findOne(id));
|
||||
return request(super.createRequestPageTempletResponse("/apps/business/contacts/edit"));
|
||||
}
|
||||
|
||||
@RequestMapping("/detail")
|
||||
@Menu(type = "customer" , subtype = "index")
|
||||
public ModelAndView detail(ModelMap map , HttpServletRequest request , @Valid String id) {
|
||||
map.addAttribute("contacts", contactsRes.findOne(id)) ;
|
||||
return request(super.createAppsTempletResponse("/apps/business/contacts/detail"));
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("/update")
|
||||
@Menu(type = "contacts", subtype = "contacts")
|
||||
public ModelAndView update(HttpServletRequest request, @Valid Contacts contacts) {
|
||||
Contacts data = contactsRes.findOne(contacts.getId());
|
||||
if (data != null) {
|
||||
List<PropertiesEvent> events = PropertiesEventUtils.processPropertiesModify(request, contacts, data, "id", "orgi", "creater", "createtime", "updatetime"); //记录 数据变更 历史
|
||||
if (events.size() > 0) {
|
||||
String modifyid = MainUtils.getUUID();
|
||||
Date modifytime = new Date();
|
||||
for (PropertiesEvent event : events) {
|
||||
event.setDataid(contacts.getId());
|
||||
event.setCreater(super.getUser(request).getId());
|
||||
event.setOrgi(super.getOrgi(request));
|
||||
event.setModifyid(modifyid);
|
||||
event.setCreatetime(modifytime);
|
||||
propertiesEventRes.save(event);
|
||||
}
|
||||
}
|
||||
|
||||
contacts.setCreater(data.getCreater());
|
||||
contacts.setCreatetime(data.getCreatetime());
|
||||
contacts.setOrgi(super.getOrgi(request));
|
||||
contacts.setOrgan(super.getUser(request).getOrgan());
|
||||
contacts.setPinyin(PinYinTools.getInstance().getFirstPinYin(contacts.getName()));
|
||||
if (StringUtils.isBlank(contacts.getCusbirthday())) {
|
||||
contacts.setCusbirthday(null);
|
||||
}
|
||||
contactsRes.save(contacts);
|
||||
}
|
||||
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/contacts/index.html?ckind=" + contacts.getCkind()));
|
||||
}
|
||||
|
||||
@RequestMapping("/imp")
|
||||
@Menu(type = "contacts", subtype = "contacts")
|
||||
public ModelAndView imp(ModelMap map, HttpServletRequest request, @Valid String ckind) {
|
||||
map.addAttribute("ckind", ckind);
|
||||
return request(super.createRequestPageTempletResponse("/apps/business/contacts/imp"));
|
||||
}
|
||||
|
||||
@RequestMapping("/impsave")
|
||||
@Menu(type = "contacts", subtype = "contacts")
|
||||
public ModelAndView impsave(ModelMap map, HttpServletRequest request, @RequestParam(value = "cusfile", required = false) MultipartFile cusfile, @Valid String ckind) throws IOException {
|
||||
DSDataEvent event = new DSDataEvent();
|
||||
String fileName = "contacts/" + MainUtils.getUUID() + cusfile.getOriginalFilename().substring(cusfile.getOriginalFilename().lastIndexOf("."));
|
||||
File excelFile = new File(path, fileName);
|
||||
if (!excelFile.getParentFile().exists()) {
|
||||
excelFile.getParentFile().mkdirs();
|
||||
}
|
||||
MetadataTable table = metadataRes.findByTablename("uk_contacts");
|
||||
if (table != null) {
|
||||
FileUtils.writeByteArrayToFile(new File(path, fileName), cusfile.getBytes());
|
||||
event.setDSData(new DSData(table, excelFile, cusfile.getContentType(), super.getUser(request)));
|
||||
event.getDSData().setClazz(Contacts.class);
|
||||
event.getDSData().setProcess(new ContactsProcess(contactsRes));
|
||||
event.setOrgi(super.getOrgi(request));
|
||||
/*if(!StringUtils.isBlank(ckind)){
|
||||
exchange.getValues().put("ckind", ckind) ;
|
||||
}*/
|
||||
event.getValues().put("creater", super.getUser(request).getId());
|
||||
reporterRes.save(event.getDSData().getReport());
|
||||
new ExcelImportProecess(event).process(); //启动导入任务
|
||||
}
|
||||
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/contacts/index.html"));
|
||||
}
|
||||
|
||||
@RequestMapping("/expids")
|
||||
@Menu(type = "contacts", subtype = "contacts")
|
||||
public void expids(ModelMap map, HttpServletRequest request, HttpServletResponse response, @Valid String[] ids) throws IOException {
|
||||
if (ids != null && ids.length > 0) {
|
||||
Iterable<Contacts> contactsList = contactsRes.findAll(Arrays.asList(ids));
|
||||
MetadataTable table = metadataRes.findByTablename("uk_contacts");
|
||||
List<Map<String, Object>> values = new ArrayList<Map<String, Object>>();
|
||||
for (Contacts contacts : contactsList) {
|
||||
values.add(MainUtils.transBean2Map(contacts));
|
||||
}
|
||||
|
||||
response.setHeader("content-disposition", "attachment;filename=CSKefu-Contacts-" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".xls");
|
||||
|
||||
ExcelExporterProcess excelProcess = new ExcelExporterProcess(values, table, response.getOutputStream());
|
||||
excelProcess.process();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@RequestMapping("/expall")
|
||||
@Menu(type = "contacts", subtype = "contacts")
|
||||
public void expall(ModelMap map, HttpServletRequest request, HttpServletResponse response) throws IOException, CSKefuException {
|
||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||
if(!super.esOrganFilter(request, boolQueryBuilder)){
|
||||
return;
|
||||
}
|
||||
boolQueryBuilder.must(termQuery("datastatus", false)); //只导出 数据删除状态 为 未删除的 数据
|
||||
Iterable<Contacts> contactsList = contactsRes.findByCreaterAndSharesAndOrgi(super.getUser(request).getId(), super.getUser(request).getId(), super.getOrgi(request), null, null, false, boolQueryBuilder, null, new PageRequest(super.getP(request), super.getPs(request)));
|
||||
|
||||
MetadataTable table = metadataRes.findByTablename("uk_contacts");
|
||||
List<Map<String, Object>> values = new ArrayList<Map<String, Object>>();
|
||||
for (Contacts contacts : contactsList) {
|
||||
values.add(MainUtils.transBean2Map(contacts));
|
||||
}
|
||||
|
||||
response.setHeader("content-disposition", "attachment;filename=CSKefu-Contacts-" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".xls");
|
||||
|
||||
ExcelExporterProcess excelProcess = new ExcelExporterProcess(values, table, response.getOutputStream());
|
||||
excelProcess.process();
|
||||
return;
|
||||
}
|
||||
|
||||
@RequestMapping("/expsearch")
|
||||
@Menu(type = "contacts", subtype = "contacts")
|
||||
public void expall(ModelMap map, HttpServletRequest request, HttpServletResponse response, @Valid String q, @Valid String ekind) throws IOException {
|
||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||
if (!StringUtils.isBlank(q)) {
|
||||
map.put("q", q);
|
||||
}
|
||||
if (!StringUtils.isBlank(ekind)) {
|
||||
boolQueryBuilder.must(termQuery("ekind", ekind));
|
||||
map.put("ekind", ekind);
|
||||
}
|
||||
|
||||
Iterable<Contacts> contactsList = contactsRes.findByCreaterAndSharesAndOrgi(super.getUser(request).getId(), super.getUser(request).getId(), super.getOrgi(request), null, null, false, boolQueryBuilder, q, new PageRequest(super.getP(request), super.getPs(request)));
|
||||
MetadataTable table = metadataRes.findByTablename("uk_contacts");
|
||||
List<Map<String, Object>> values = new ArrayList<Map<String, Object>>();
|
||||
for (Contacts contacts : contactsList) {
|
||||
values.add(MainUtils.transBean2Map(contacts));
|
||||
}
|
||||
|
||||
response.setHeader("content-disposition", "attachment;filename=CSKefu-Contacts-" + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + ".xls");
|
||||
|
||||
ExcelExporterProcess excelProcess = new ExcelExporterProcess(values, table, response.getOutputStream());
|
||||
excelProcess.process();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("/embed/index")
|
||||
@Menu(type = "customer", subtype = "embed")
|
||||
public ModelAndView embed(ModelMap map, HttpServletRequest request, @Valid String q, @Valid String ckind) throws CSKefuException {
|
||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||
if(!super.esOrganFilter(request, boolQueryBuilder)){
|
||||
return request(super.createAppsTempletResponse("/apps/business/contacts/embed/index"));
|
||||
}
|
||||
if (!StringUtils.isBlank(q)) {
|
||||
map.put("q", q);
|
||||
}
|
||||
if (!StringUtils.isBlank(ckind)) {
|
||||
boolQueryBuilder.must(termQuery("ckind", ckind));
|
||||
map.put("ckind", ckind);
|
||||
}
|
||||
map.addAttribute("contactsList", contactsRes.findByCreaterAndSharesAndOrgi(super.getUser(request).getId(), super.getUser(request).getId(), super.getOrgi(request), null, null, false, boolQueryBuilder, q, new PageRequest(super.getP(request), super.getPs(request))));
|
||||
|
||||
return request(super.createRequestPageTempletResponse("/apps/business/contacts/embed/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/embed/add")
|
||||
@Menu(type = "contacts", subtype = "embedadd")
|
||||
public ModelAndView embedadd(ModelMap map, HttpServletRequest request) {
|
||||
return request(super.createRequestPageTempletResponse("/apps/business/contacts/embed/add"));
|
||||
}
|
||||
|
||||
@RequestMapping("/embed/save")
|
||||
@Menu(type = "contacts", subtype = "embedsave")
|
||||
public ModelAndView embedsave(HttpServletRequest request, @Valid Contacts contacts) {
|
||||
contacts.setCreater(super.getUser(request).getId());
|
||||
contacts.setOrgi(super.getOrgi(request));
|
||||
contacts.setOrgan(super.getUser(request).getOrgan());
|
||||
contacts.setPinyin(PinYinTools.getInstance().getFirstPinYin(contacts.getName()));
|
||||
if (StringUtils.isBlank(contacts.getCusbirthday())) {
|
||||
contacts.setCusbirthday(null);
|
||||
}
|
||||
contactsRes.save(contacts);
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/contacts/embed/index.html"));
|
||||
}
|
||||
|
||||
@RequestMapping("/embed/edit")
|
||||
@Menu(type = "contacts", subtype = "embededit")
|
||||
public ModelAndView embededit(ModelMap map, HttpServletRequest request, @Valid String id) {
|
||||
map.addAttribute("contacts", contactsRes.findOne(id));
|
||||
return request(super.createRequestPageTempletResponse("/apps/business/contacts/embed/edit"));
|
||||
}
|
||||
|
||||
@RequestMapping("/embed/update")
|
||||
@Menu(type = "contacts", subtype = "embedupdate")
|
||||
public ModelAndView embedupdate(HttpServletRequest request, @Valid Contacts contacts) {
|
||||
Contacts data = contactsRes.findOne(contacts.getId());
|
||||
if (data != null) {
|
||||
List<PropertiesEvent> events = PropertiesEventUtils.processPropertiesModify(request, contacts, data, "id", "orgi", "creater", "createtime", "updatetime"); //记录 数据变更 历史
|
||||
if (events.size() > 0) {
|
||||
String modifyid = MainUtils.getUUID();
|
||||
Date modifytime = new Date();
|
||||
for (PropertiesEvent event : events) {
|
||||
event.setDataid(contacts.getId());
|
||||
event.setCreater(super.getUser(request).getId());
|
||||
event.setOrgi(super.getOrgi(request));
|
||||
event.setModifyid(modifyid);
|
||||
event.setCreatetime(modifytime);
|
||||
propertiesEventRes.save(event);
|
||||
}
|
||||
}
|
||||
|
||||
contacts.setCreater(data.getCreater());
|
||||
contacts.setCreatetime(data.getCreatetime());
|
||||
contacts.setOrgi(super.getOrgi(request));
|
||||
contacts.setOrgan(super.getUser(request).getOrgan());
|
||||
contacts.setPinyin(PinYinTools.getInstance().getFirstPinYin(contacts.getName()));
|
||||
if (StringUtils.isBlank(contacts.getCusbirthday())) {
|
||||
contacts.setCusbirthday(null);
|
||||
}
|
||||
contactsRes.save(contacts);
|
||||
}
|
||||
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/contacts/embed/index.html"));
|
||||
}
|
||||
}
|
@ -1,407 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.app.handler.apps.customer;
|
||||
|
||||
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.basic.MainUtils;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.PinYinTools;
|
||||
import com.chatopera.cc.exception.CSKefuException;
|
||||
import com.chatopera.cc.concurrent.dsdata.DSData;
|
||||
import com.chatopera.cc.concurrent.dsdata.ExcelImportProecess;
|
||||
import com.chatopera.cc.concurrent.dsdata.export.ExcelExporterProcess;
|
||||
import com.chatopera.cc.concurrent.dsdata.process.EntCustomerProcess;
|
||||
import com.chatopera.cc.app.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.app.persistence.es.EntCustomerRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.PropertiesEventRepository;
|
||||
import com.chatopera.cc.util.PropertiesEventUtils;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.concurrent.dsdata.DSDataEvent;
|
||||
import com.chatopera.cc.app.persistence.repository.MetadataRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.ReporterRepository;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.CustomerGroupForm;
|
||||
import com.chatopera.cc.app.model.EntCustomer;
|
||||
import com.chatopera.cc.app.model.MetadataTable;
|
||||
import com.chatopera.cc.app.model.PropertiesEvent;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/customer")
|
||||
public class CustomerController extends Handler{
|
||||
|
||||
@Autowired
|
||||
private EntCustomerRepository entCustomerRes;
|
||||
|
||||
@Autowired
|
||||
private ContactsRepository contactsRes ;
|
||||
|
||||
@Autowired
|
||||
private ReporterRepository reporterRes ;
|
||||
|
||||
@Autowired
|
||||
private MetadataRepository metadataRes ;
|
||||
|
||||
@Autowired
|
||||
private PropertiesEventRepository propertiesEventRes ;
|
||||
|
||||
@Value("${web.upload-path}")
|
||||
private String path;
|
||||
|
||||
@RequestMapping("/index")
|
||||
@Menu(type = "customer" , subtype = "index")
|
||||
public ModelAndView index(ModelMap map , HttpServletRequest request , @Valid String q , @Valid String ekind) throws CSKefuException {
|
||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||
|
||||
if(!super.esOrganFilter(request, boolQueryBuilder)){
|
||||
return request(super.createAppsTempletResponse("/apps/business/customer/index"));
|
||||
}
|
||||
|
||||
if(!StringUtils.isBlank(q)){
|
||||
map.put("q", q) ;
|
||||
}
|
||||
if(!StringUtils.isBlank(ekind)){
|
||||
boolQueryBuilder.must(termQuery("ekind" , ekind)) ;
|
||||
map.put("ekind", ekind) ;
|
||||
}
|
||||
map.addAttribute("entCustomerList", entCustomerRes.findByCreaterAndSharesAndOrgi(super.getUser(request).getId(), super.getUser(request).getId(),super.getOrgi(request), null , null , false, boolQueryBuilder , q , new PageRequest(super.getP(request) , super.getPs(request)))) ;
|
||||
|
||||
return request(super.createAppsTempletResponse("/apps/business/customer/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/today")
|
||||
@Menu(type = "customer" , subtype = "today")
|
||||
public ModelAndView today(ModelMap map , HttpServletRequest request , @Valid String q , @Valid String ekind) throws CSKefuException {
|
||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||
|
||||
if(!super.esOrganFilter(request, boolQueryBuilder)){
|
||||
return request(super.createAppsTempletResponse("/apps/business/customer/index"));
|
||||
}
|
||||
|
||||
if(!StringUtils.isBlank(q)){
|
||||
map.put("q", q) ;
|
||||
}
|
||||
|
||||
if(!StringUtils.isBlank(ekind)){
|
||||
boolQueryBuilder.must(termQuery("ekind" , ekind)) ;
|
||||
map.put("ekind", ekind) ;
|
||||
}
|
||||
map.addAttribute("entCustomerList", entCustomerRes.findByCreaterAndSharesAndOrgi(super.getUser(request).getId(), super.getUser(request).getId(),super.getOrgi(request), MainUtils.getStartTime() , null , false, boolQueryBuilder ,q , new PageRequest(super.getP(request) , super.getPs(request)))) ;
|
||||
|
||||
return request(super.createAppsTempletResponse("/apps/business/customer/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/week")
|
||||
@Menu(type = "customer" , subtype = "week")
|
||||
public ModelAndView week(ModelMap map , HttpServletRequest request , @Valid String q , @Valid String ekind) throws CSKefuException {
|
||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||
if(!super.esOrganFilter(request, boolQueryBuilder)){
|
||||
return request(super.createAppsTempletResponse("/apps/business/customer/index"));
|
||||
}
|
||||
|
||||
if(!StringUtils.isBlank(q)){
|
||||
map.put("q", q) ;
|
||||
}
|
||||
if(!StringUtils.isBlank(ekind)){
|
||||
boolQueryBuilder.must(termQuery("ekind" , ekind)) ;
|
||||
map.put("ekind", ekind) ;
|
||||
}
|
||||
map.addAttribute("entCustomerList", entCustomerRes.findByCreaterAndSharesAndOrgi(super.getUser(request).getId(), super.getUser(request).getId(),super.getOrgi(request), MainUtils.getWeekStartTime() , null , false, boolQueryBuilder ,q , new PageRequest(super.getP(request) , super.getPs(request)))) ;
|
||||
|
||||
return request(super.createAppsTempletResponse("/apps/business/customer/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/enterprise")
|
||||
@Menu(type = "customer" , subtype = "enterprise")
|
||||
public ModelAndView enterprise(ModelMap map , HttpServletRequest request , @Valid String q , @Valid String ekind) throws CSKefuException {
|
||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||
if(!super.esOrganFilter(request, boolQueryBuilder)){
|
||||
return request(super.createAppsTempletResponse("/apps/business/customer/index"));
|
||||
}
|
||||
|
||||
boolQueryBuilder.must(termQuery("etype" , MainContext.CustomerTypeEnum.ENTERPRISE.toString())) ;
|
||||
if(!StringUtils.isBlank(ekind)){
|
||||
boolQueryBuilder.must(termQuery("ekind" , ekind)) ;
|
||||
map.put("ekind", ekind) ;
|
||||
}
|
||||
if(!StringUtils.isBlank(q)){
|
||||
map.put("q", q) ;
|
||||
}
|
||||
map.addAttribute("entCustomerList", entCustomerRes.findByCreaterAndSharesAndOrgi(super.getUser(request).getId(), super.getUser(request).getId(),super.getOrgi(request), null , null , false, boolQueryBuilder ,q , new PageRequest(super.getP(request) , super.getPs(request)))) ;
|
||||
return request(super.createAppsTempletResponse("/apps/business/customer/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/personal")
|
||||
@Menu(type = "customer" , subtype = "personal")
|
||||
public ModelAndView personal(ModelMap map , HttpServletRequest request , @Valid String q , @Valid String ekind) throws CSKefuException {
|
||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||
if(!super.esOrganFilter(request, boolQueryBuilder)){
|
||||
return request(super.createAppsTempletResponse("/apps/business/customer/index"));
|
||||
}
|
||||
|
||||
boolQueryBuilder.must(termQuery("etype" , MainContext.CustomerTypeEnum.PERSONAL.toString())) ;
|
||||
|
||||
if(!StringUtils.isBlank(ekind)){
|
||||
boolQueryBuilder.must(termQuery("ekind" , ekind)) ;
|
||||
map.put("ekind", ekind) ;
|
||||
}
|
||||
|
||||
if(!StringUtils.isBlank(q)){
|
||||
map.put("q", q) ;
|
||||
}
|
||||
map.addAttribute("entCustomerList", entCustomerRes.findByCreaterAndSharesAndOrgi(super.getUser(request).getId(), super.getUser(request).getId(),super.getOrgi(request), null , null , false, boolQueryBuilder ,q , new PageRequest(super.getP(request) , super.getPs(request)))) ;
|
||||
return request(super.createAppsTempletResponse("/apps/business/customer/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/creater")
|
||||
@Menu(type = "customer" , subtype = "creater")
|
||||
public ModelAndView creater(ModelMap map , HttpServletRequest request , @Valid String q , @Valid String ekind) throws CSKefuException {
|
||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||
if(!super.esOrganFilter(request, boolQueryBuilder)){
|
||||
return request(super.createAppsTempletResponse("/apps/business/customer/index"));
|
||||
}
|
||||
|
||||
boolQueryBuilder.must(termQuery("creater" , super.getUser(request).getId())) ;
|
||||
|
||||
if(!StringUtils.isBlank(ekind)){
|
||||
boolQueryBuilder.must(termQuery("ekind" , ekind)) ;
|
||||
map.put("ekind", ekind) ;
|
||||
}
|
||||
if(!StringUtils.isBlank(q)){
|
||||
map.put("q", q) ;
|
||||
}
|
||||
|
||||
map.addAttribute("entCustomerList", entCustomerRes.findByCreaterAndSharesAndOrgi(super.getUser(request).getId(), super.getUser(request).getId(), super.getOrgi(request),null , null , false, boolQueryBuilder ,q , new PageRequest(super.getP(request) , super.getPs(request)))) ;
|
||||
return request(super.createAppsTempletResponse("/apps/business/customer/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/add")
|
||||
@Menu(type = "customer" , subtype = "customer")
|
||||
public ModelAndView add(ModelMap map , HttpServletRequest request,@Valid String ekind) {
|
||||
map.addAttribute("ekind", ekind);
|
||||
return request(super.createRequestPageTempletResponse("/apps/business/customer/add"));
|
||||
}
|
||||
|
||||
@RequestMapping( "/save")
|
||||
@Menu(type = "customer" , subtype = "customer")
|
||||
public ModelAndView save(HttpServletRequest request , @Valid CustomerGroupForm customerGroupForm) {
|
||||
customerGroupForm.getEntcustomer().setCreater(super.getUser(request).getId());
|
||||
customerGroupForm.getEntcustomer().setOrgi(super.getOrgi(request));
|
||||
customerGroupForm.getEntcustomer().setOrgan(super.getUser(request).getOrgan());
|
||||
// customerGroupForm.getEntcustomer().setEtype(MainContext.CustomerTypeEnum.ENTERPRISE.toString());
|
||||
customerGroupForm.getEntcustomer().setPinyin(PinYinTools.getInstance().getFirstPinYin(customerGroupForm.getEntcustomer().getName()));
|
||||
entCustomerRes.save(customerGroupForm.getEntcustomer());
|
||||
if(customerGroupForm.getContacts()!=null && !StringUtils.isBlank(customerGroupForm.getContacts().getName())){
|
||||
customerGroupForm.getContacts().setEntcusid(customerGroupForm.getEntcustomer().getId());
|
||||
customerGroupForm.getContacts().setCreater(super.getUser(request).getId());
|
||||
customerGroupForm.getContacts().setOrgi(super.getOrgi(request));
|
||||
customerGroupForm.getContacts().setOrgan(super.getUser(request).getOrgan());
|
||||
customerGroupForm.getContacts().setPinyin(PinYinTools.getInstance().getFirstPinYin(customerGroupForm.getContacts().getName()));
|
||||
if(StringUtils.isBlank(customerGroupForm.getContacts().getCusbirthday())) {
|
||||
customerGroupForm.getContacts().setCusbirthday(null);
|
||||
}
|
||||
contactsRes.save(customerGroupForm.getContacts()) ;
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/customer/index.html?ekind="+customerGroupForm.getEntcustomer().getEkind()));
|
||||
}
|
||||
|
||||
@RequestMapping("/delete")
|
||||
@Menu(type = "customer" , subtype = "customer")
|
||||
public ModelAndView delete(HttpServletRequest request ,@Valid EntCustomer entCustomer ,@Valid String p) {
|
||||
if(entCustomer!=null){
|
||||
entCustomer = entCustomerRes.findOne(entCustomer.getId()) ;
|
||||
entCustomer.setDatastatus(true); //客户和联系人都是 逻辑删除
|
||||
entCustomerRes.save(entCustomer) ;
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/customer/index.html?p="+p+"&ekind="+entCustomer.getEkind()));
|
||||
}
|
||||
|
||||
@RequestMapping("/edit")
|
||||
@Menu(type = "customer" , subtype = "customer")
|
||||
public ModelAndView edit(ModelMap map , HttpServletRequest request , @Valid String id) {
|
||||
map.addAttribute("entCustomer", entCustomerRes.findOne(id)) ;
|
||||
return request(super.createRequestPageTempletResponse("/apps/business/customer/edit"));
|
||||
}
|
||||
|
||||
@RequestMapping( "/update")
|
||||
@Menu(type = "customer" , subtype = "customer")
|
||||
public ModelAndView update(HttpServletRequest request , @Valid CustomerGroupForm customerGroupForm) {
|
||||
EntCustomer customer = entCustomerRes.findOne(customerGroupForm.getEntcustomer().getId()) ;
|
||||
|
||||
List<PropertiesEvent> events = PropertiesEventUtils.processPropertiesModify(request, customerGroupForm.getEntcustomer() , customer , "id" , "orgi" , "creater" ,"createtime" , "updatetime") ; //记录 数据变更 历史
|
||||
if(events.size()>0){
|
||||
String modifyid = MainUtils.getUUID() ;
|
||||
Date modifytime = new Date();
|
||||
for(PropertiesEvent event : events){
|
||||
event.setDataid(customerGroupForm.getEntcustomer().getId());
|
||||
event.setCreater(super.getUser(request).getId());
|
||||
event.setOrgi(super.getOrgi(request));
|
||||
event.setModifyid(modifyid);
|
||||
event.setCreatetime(modifytime);
|
||||
propertiesEventRes.save(event) ;
|
||||
}
|
||||
}
|
||||
|
||||
customerGroupForm.getEntcustomer().setCreater(customer.getCreater());
|
||||
customerGroupForm.getEntcustomer().setCreatetime(customer.getCreatetime());
|
||||
customerGroupForm.getEntcustomer().setOrgi(super.getOrgi(request));
|
||||
customerGroupForm.getEntcustomer().setOrgan(super.getUser(request).getOrgan());
|
||||
customerGroupForm.getEntcustomer().setPinyin(PinYinTools.getInstance().getFirstPinYin(customerGroupForm.getEntcustomer().getName()));
|
||||
entCustomerRes.save(customerGroupForm.getEntcustomer());
|
||||
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/customer/index.html?ekind="+customerGroupForm.getEntcustomer().getEkind()));
|
||||
}
|
||||
|
||||
@RequestMapping("/imp")
|
||||
@Menu(type = "customer" , subtype = "customer")
|
||||
public ModelAndView imp(ModelMap map , HttpServletRequest request,@Valid String ekind) {
|
||||
map.addAttribute("ekind",ekind);
|
||||
return request(super.createRequestPageTempletResponse("/apps/business/customer/imp"));
|
||||
}
|
||||
|
||||
@RequestMapping("/impsave")
|
||||
@Menu(type = "customer" , subtype = "customer")
|
||||
public ModelAndView impsave(ModelMap map , HttpServletRequest request , @RequestParam(value = "cusfile", required = false) MultipartFile cusfile,@Valid String ekind) throws IOException {
|
||||
DSDataEvent event = new DSDataEvent();
|
||||
String fileName = "customer/"+ MainUtils.getUUID()+cusfile.getOriginalFilename().substring(cusfile.getOriginalFilename().lastIndexOf(".")) ;
|
||||
File excelFile = new File(path , fileName) ;
|
||||
if(!excelFile.getParentFile().exists()){
|
||||
excelFile.getParentFile().mkdirs() ;
|
||||
}
|
||||
MetadataTable table = metadataRes.findByTablename("uk_entcustomer") ;
|
||||
if(table!=null){
|
||||
FileUtils.writeByteArrayToFile(new File(path , fileName), cusfile.getBytes());
|
||||
event.setDSData(new DSData(table,excelFile , cusfile.getContentType(), super.getUser(request)));
|
||||
event.getDSData().setClazz(EntCustomer.class);
|
||||
event.getDSData().setProcess(new EntCustomerProcess(entCustomerRes));
|
||||
event.setOrgi(super.getOrgi(request));
|
||||
/*if(!StringUtils.isBlank(ekind)){
|
||||
exchange.getValues().put("ekind", ekind) ;
|
||||
}*/
|
||||
event.getValues().put("creater", super.getUser(request).getId()) ;
|
||||
reporterRes.save(event.getDSData().getReport()) ;
|
||||
new ExcelImportProecess(event).process() ; //启动导入任务
|
||||
}
|
||||
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/customer/index.html"));
|
||||
}
|
||||
|
||||
@RequestMapping("/expids")
|
||||
@Menu(type = "customer" , subtype = "customer")
|
||||
public void expids(ModelMap map , HttpServletRequest request , HttpServletResponse response , @Valid String[] ids) throws IOException {
|
||||
if(ids!=null && ids.length > 0){
|
||||
Iterable<EntCustomer> entCustomerList = entCustomerRes.findAll(Arrays.asList(ids)) ;
|
||||
MetadataTable table = metadataRes.findByTablename("uk_entcustomer") ;
|
||||
List<Map<String,Object>> values = new ArrayList<Map<String,Object>>();
|
||||
for(EntCustomer customer : entCustomerList){
|
||||
values.add(MainUtils.transBean2Map(customer)) ;
|
||||
}
|
||||
|
||||
response.setHeader("content-disposition", "attachment;filename=UCKeFu-EntCustomer-"+new SimpleDateFormat("yyyy-MM-dd").format(new Date())+".xls");
|
||||
|
||||
ExcelExporterProcess excelProcess = new ExcelExporterProcess( values, table, response.getOutputStream()) ;
|
||||
excelProcess.process();
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
@RequestMapping("/expall")
|
||||
@Menu(type = "customer" , subtype = "customer")
|
||||
public void expall(ModelMap map , HttpServletRequest request , HttpServletResponse response) throws IOException, CSKefuException {
|
||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||
if(!super.esOrganFilter(request, boolQueryBuilder)){
|
||||
// #TODO 提示没有部门
|
||||
return;
|
||||
}
|
||||
|
||||
boolQueryBuilder.must(termQuery("datastatus" , false)) ; //只导出 数据删除状态 为 未删除的 数据
|
||||
Iterable<EntCustomer> entCustomerList = entCustomerRes.findByCreaterAndSharesAndOrgi(super.getUser(request).getId(), super.getUser(request).getId(),super.getOrgi(request), null , null , false, boolQueryBuilder , null , new PageRequest(super.getP(request) , super.getPs(request)));
|
||||
|
||||
MetadataTable table = metadataRes.findByTablename("uk_entcustomer") ;
|
||||
List<Map<String,Object>> values = new ArrayList<Map<String,Object>>();
|
||||
for(EntCustomer customer : entCustomerList){
|
||||
values.add(MainUtils.transBean2Map(customer)) ;
|
||||
}
|
||||
|
||||
response.setHeader("content-disposition", "attachment;filename=UCKeFu-EntCustomer-"+new SimpleDateFormat("yyyy-MM-dd").format(new Date())+".xls");
|
||||
|
||||
ExcelExporterProcess excelProcess = new ExcelExporterProcess( values, table, response.getOutputStream()) ;
|
||||
excelProcess.process();
|
||||
return ;
|
||||
}
|
||||
|
||||
@RequestMapping("/expsearch")
|
||||
@Menu(type = "customer" , subtype = "customer")
|
||||
public void expall(ModelMap map , HttpServletRequest request , HttpServletResponse response , @Valid String q , @Valid String ekind) throws IOException, CSKefuException {
|
||||
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
|
||||
if(!super.esOrganFilter(request, boolQueryBuilder)){
|
||||
// #TODO 提示没有部门
|
||||
return;
|
||||
}
|
||||
|
||||
if(!StringUtils.isBlank(q)){
|
||||
map.put("q", q) ;
|
||||
}
|
||||
if(!StringUtils.isBlank(ekind)){
|
||||
boolQueryBuilder.must(termQuery("ekind" , ekind)) ;
|
||||
map.put("ekind", ekind) ;
|
||||
}
|
||||
|
||||
Iterable<EntCustomer> entCustomerList = entCustomerRes.findByCreaterAndSharesAndOrgi(super.getUser(request).getId(), super.getUser(request).getId(),super.getOrgi(request), null , null , false, boolQueryBuilder ,q , new PageRequest(super.getP(request) , super.getPs(request)));
|
||||
MetadataTable table = metadataRes.findByTablename("uk_entcustomer") ;
|
||||
List<Map<String,Object>> values = new ArrayList<Map<String,Object>>();
|
||||
for(EntCustomer customer : entCustomerList){
|
||||
values.add(MainUtils.transBean2Map(customer)) ;
|
||||
}
|
||||
|
||||
response.setHeader("content-disposition", "attachment;filename=UCKeFu-EntCustomer-"+new SimpleDateFormat("yyyy-MM-dd").format(new Date())+".xls");
|
||||
|
||||
ExcelExporterProcess excelProcess = new ExcelExporterProcess( values, table, response.getOutputStream()) ;
|
||||
excelProcess.process();
|
||||
|
||||
return ;
|
||||
}
|
||||
}
|
@ -1,231 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.app.handler.apps.entim;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainUtils;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.im.client.NettyClients;
|
||||
import com.chatopera.cc.app.persistence.repository.IMGroupRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.IMGroupUserRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.OrganRepository;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.IMGroupUser;
|
||||
import com.chatopera.cc.app.model.RecentUser;
|
||||
import com.chatopera.cc.app.model.User;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.app.persistence.repository.ChatMessageRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.RecentUserRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.app.model.IMGroup;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/ent/im")
|
||||
public class EntIMController extends Handler {
|
||||
|
||||
@Autowired
|
||||
private OrganRepository organRes ;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRes ;
|
||||
|
||||
@Autowired
|
||||
private IMGroupRepository imGroupRes ;
|
||||
|
||||
@Autowired
|
||||
private IMGroupUserRepository imGroupUserRes ;
|
||||
|
||||
@Autowired
|
||||
private ChatMessageRepository chatMessageRes;
|
||||
|
||||
@Autowired
|
||||
private RecentUserRepository recentUserRes ;
|
||||
|
||||
@RequestMapping("/index")
|
||||
@Menu(type = "im" , subtype = "entim" , access = false)
|
||||
public ModelAndView index(HttpServletRequest request , HttpServletResponse response) {
|
||||
ModelAndView view = request(super.createEntIMTempletResponse("/apps/entim/index")) ;
|
||||
view.addObject("organList", organRes.findByOrgi(super.getOrgi(request))) ;
|
||||
view.addObject("userList", userRes.findByOrgiAndDatastatus(super.getOrgi(request) , false)) ;
|
||||
|
||||
view.addObject("groupList", imGroupRes.findByCreaterAndOrgi(super.getUser(request).getId(), super.getOrgi(request)));
|
||||
|
||||
view.addObject("joinGroupList", imGroupUserRes.findByUserAndOrgi(super.getUser(request), super.getOrgi(request))) ;
|
||||
|
||||
view.addObject("recentUserList", recentUserRes.findByCreaterAndOrgi(super.getUser(request).getId(), super.getOrgi(request))) ;
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@RequestMapping("/skin")
|
||||
@Menu(type = "im" , subtype = "entim" , access = false)
|
||||
public ModelAndView skin(HttpServletRequest request , HttpServletResponse response) {
|
||||
ModelAndView view = request(super.createEntIMTempletResponse("/apps/entim/skin")) ;
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@RequestMapping("/point")
|
||||
@Menu(type = "im" , subtype = "entim" , access = false)
|
||||
public ModelAndView point(HttpServletRequest request , HttpServletResponse response) {
|
||||
ModelAndView view = request(super.createEntIMTempletResponse("/apps/entim/point")) ;
|
||||
view.addObject("recentUserList", recentUserRes.findByCreaterAndOrgi(super.getUser(request).getId(), super.getOrgi(request))) ;
|
||||
return view;
|
||||
}
|
||||
|
||||
@RequestMapping("/chat")
|
||||
@Menu(type = "im" , subtype = "entim" , access = false)
|
||||
public ModelAndView chat(HttpServletRequest request , HttpServletResponse response , @Valid String userid) {
|
||||
ModelAndView view = request(super.createEntIMTempletResponse("/apps/entim/chat")) ;
|
||||
view.addObject("entimuser", userRes.findByIdAndOrgi(userid, super.getOrgi(request))) ;
|
||||
view.addObject("contextid", MainUtils.genNewID(super.getUser(request).getId(), userid)) ;
|
||||
view.addObject("online", NettyClients.getInstance().getEntIMClientsNum(userid) > 0) ;
|
||||
view.addObject("chatMessageList", chatMessageRes.findByContextidAndUseridAndOrgi(userid , super.getUser(request).getId(), super.getOrgi(request), new PageRequest(0, 20, Sort.Direction.DESC, "createtime"))) ;
|
||||
|
||||
RecentUser recentUser = recentUserRes.findByCreaterAndUserAndOrgi(super.getUser(request).getId() , new User(userid), super.getOrgi(request)) ;
|
||||
/**
|
||||
* 我的最近联系人
|
||||
*/
|
||||
if(recentUser == null){
|
||||
recentUser = new RecentUser();
|
||||
recentUser.setOrgi(super.getOrgi(request));
|
||||
recentUser.setCreater(super.getUser(request).getId());
|
||||
recentUser.setUser(new User(userid));
|
||||
}else{
|
||||
recentUser.setNewmsg(0);
|
||||
}
|
||||
recentUserRes.save(recentUser) ;
|
||||
/**
|
||||
* 对方的最近联系人
|
||||
*/
|
||||
recentUser = recentUserRes.findByCreaterAndUserAndOrgi(userid , super.getUser(request), super.getOrgi(request)) ;
|
||||
if(recentUser == null){
|
||||
recentUser = new RecentUser();
|
||||
recentUser.setOrgi(super.getOrgi(request));
|
||||
recentUser.setCreater(userid);
|
||||
recentUser.setUser(super.getUser(request));
|
||||
recentUserRes.save(recentUser) ;
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
@RequestMapping("/group")
|
||||
@Menu(type = "im" , subtype = "entim" , access = false)
|
||||
public ModelAndView group(HttpServletRequest request , HttpServletResponse response , @Valid String id) {
|
||||
ModelAndView view = request(super.createEntIMTempletResponse("/apps/entim/group/index")) ;
|
||||
IMGroup imGroup = imGroupRes.findById(id);
|
||||
view.addObject("imGroup", imGroup) ;
|
||||
view.addObject("imGroupUserList", imGroupUserRes.findByImgroupAndOrgi(imGroup, super.getOrgi(request))) ;
|
||||
view.addObject("contextid", id) ;
|
||||
view.addObject("chatMessageList", chatMessageRes.findByContextidAndOrgi(id, super.getOrgi(request), new PageRequest(0, 20, Sort.Direction.DESC, "createtime"))) ;
|
||||
return view;
|
||||
}
|
||||
|
||||
@RequestMapping("/group/user")
|
||||
@Menu(type = "im" , subtype = "entim" , access = false)
|
||||
public ModelAndView user(HttpServletRequest request , HttpServletResponse response , @Valid String id) {
|
||||
ModelAndView view = request(super.createEntIMTempletResponse("/apps/entim/group/user")) ;
|
||||
IMGroup imGroup = imGroupRes.findById(id);
|
||||
view.addObject("imGroup", imGroup) ;
|
||||
view.addObject("organList", organRes.findByOrgi(super.getOrgi(request))) ;
|
||||
view.addObject("userList", userRes.findByOrgiAndDatastatus(super.getOrgi(request) , false)) ;
|
||||
|
||||
view.addObject("imGroupUserList", imGroupUserRes.findByImgroupAndOrgi(imGroup, super.getOrgi(request))) ;
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@RequestMapping("/group/seluser")
|
||||
@Menu(type = "im" , subtype = "entim" , access = false)
|
||||
public void seluser(HttpServletRequest request , HttpServletResponse response , @Valid String id , @Valid String user) {
|
||||
IMGroup imGroup = new IMGroup();
|
||||
imGroup.setId(id);
|
||||
User curUser = new User();
|
||||
curUser.setId(user);
|
||||
IMGroupUser imGroupUser = imGroupUserRes.findByImgroupAndUserAndOrgi(imGroup, curUser, super.getOrgi(request)) ;
|
||||
if(imGroupUser == null){
|
||||
imGroupUser = new IMGroupUser() ;
|
||||
imGroupUser.setImgroup(imGroup);
|
||||
imGroupUser.setUser(curUser);
|
||||
imGroupUser.setOrgi(super.getUser(request).getOrgi());
|
||||
imGroupUser.setCreater(super.getUser(request).getId());
|
||||
imGroupUserRes.save(imGroupUser) ;
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping("/group/rmuser")
|
||||
@Menu(type = "im" , subtype = "entim" , access = false)
|
||||
public void rmluser(HttpServletRequest request , HttpServletResponse response , @Valid String id , @Valid String user) {
|
||||
IMGroup imGroup = new IMGroup();
|
||||
imGroup.setId(id);
|
||||
User curUser = new User();
|
||||
curUser.setId(user);
|
||||
IMGroupUser imGroupUser = imGroupUserRes.findByImgroupAndUserAndOrgi(imGroup, curUser, super.getOrgi(request)) ;
|
||||
if(imGroupUser != null){
|
||||
imGroupUserRes.delete(imGroupUser);
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping("/group/tipmsg")
|
||||
@Menu(type = "im" , subtype = "entim" , access = false)
|
||||
public ModelAndView tipmsg(HttpServletRequest request , HttpServletResponse response , @Valid String id , @Valid String tipmsg) {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("/apps/entim/group/tipmsg")) ;
|
||||
IMGroup imGroup = imGroupRes.findById(id) ;
|
||||
if(imGroup != null){
|
||||
imGroup.setTipmessage(tipmsg);
|
||||
imGroupRes.save(imGroup) ;
|
||||
}
|
||||
view.addObject("imGroup", imGroup) ;
|
||||
return view ;
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("/group/save")
|
||||
@Menu(type = "im" , subtype = "entim" , access = false)
|
||||
public ModelAndView groupsave(HttpServletRequest request , HttpServletResponse response , @Valid IMGroup group) {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("/apps/entim/group/grouplist")) ;
|
||||
if(!StringUtils.isBlank(group.getName()) && imGroupRes.countByNameAndOrgi(group.getName() , super.getOrgi(request)) == 0){
|
||||
group.setOrgi(super.getUser(request).getOrgi());
|
||||
group.setCreater(super.getUser(request).getId());
|
||||
imGroupRes.save(group) ;
|
||||
|
||||
IMGroupUser imGroupUser = new IMGroupUser() ;
|
||||
imGroupUser.setOrgi(super.getUser(request).getOrgi());
|
||||
imGroupUser.setUser(super.getUser(request));
|
||||
imGroupUser.setImgroup(group);
|
||||
imGroupUser.setAdmin(true);
|
||||
imGroupUser.setCreater(super.getUser(request).getId());
|
||||
imGroupUserRes.save(imGroupUser) ;
|
||||
}
|
||||
view.addObject("groupList", imGroupRes.findByCreaterAndOrgi(super.getUser(request).getId(), super.getOrgi(request))) ;
|
||||
|
||||
view.addObject("joinGroupList", imGroupUserRes.findByUserAndOrgi(super.getUser(request), super.getOrgi(request))) ;
|
||||
|
||||
return view;
|
||||
}
|
||||
}
|
@ -1,829 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.app.handler.apps.internet;
|
||||
|
||||
import com.chatopera.cc.app.algorithm.AutomaticServiceDist;
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.basic.MainUtils;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.im.util.RichMediaUtils;
|
||||
import com.chatopera.cc.app.model.*;
|
||||
import com.chatopera.cc.app.persistence.blob.JpaBlobHelper;
|
||||
import com.chatopera.cc.app.persistence.es.ContactsRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.*;
|
||||
import com.chatopera.cc.util.*;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort.Direction;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/im")
|
||||
@EnableAsync
|
||||
public class IMController extends Handler {
|
||||
private final static Logger logger = LoggerFactory.getLogger(IMController.class);
|
||||
|
||||
|
||||
@Value("${uk.im.server.host}")
|
||||
private String host;
|
||||
|
||||
@Value("${uk.im.server.port}")
|
||||
private Integer port;
|
||||
|
||||
@Value("${cs.im.server.ssl.port}")
|
||||
private Integer sslPort;
|
||||
|
||||
@Value("${web.upload-path}")
|
||||
private String path;
|
||||
|
||||
@Autowired
|
||||
private StreamingFileRepository streamingFileRepository;
|
||||
|
||||
@Autowired
|
||||
private JpaBlobHelper jpaBlobHelper;
|
||||
|
||||
@Autowired
|
||||
private ConsultInviteRepository inviteRepository;
|
||||
|
||||
@Autowired
|
||||
private ChatMessageRepository chatMessageRes;
|
||||
|
||||
@Autowired
|
||||
private AgentServiceSatisRepository agentServiceSatisRes;
|
||||
|
||||
@Autowired
|
||||
private InviteRecordRepository inviteRecordRes;
|
||||
|
||||
@Autowired
|
||||
private LeaveMsgRepository leaveMsgRes;
|
||||
|
||||
|
||||
@Autowired
|
||||
private AttachmentRepository attachementRes;
|
||||
|
||||
@Autowired
|
||||
private ContactsRepository contactsRes;
|
||||
|
||||
@Autowired
|
||||
private AgentUserContactsRepository agentUserContactsRes;
|
||||
|
||||
@Autowired
|
||||
private SNSAccountRepository snsAccountRepository;
|
||||
|
||||
@RequestMapping("/{id}")
|
||||
@Menu(type = "im", subtype = "point", access = true)
|
||||
public ModelAndView point(HttpServletRequest request, HttpServletResponse response,
|
||||
@PathVariable String id,
|
||||
@Valid String orgi,
|
||||
@Valid String userid,
|
||||
@Valid String title,
|
||||
@Valid String aiid) {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("/apps/im/point"));
|
||||
String sessionid = request.getSession().getId();
|
||||
if (StringUtils.isNotBlank(id)) {
|
||||
view.addObject("hostname", request.getServerName());
|
||||
|
||||
SystemConfig systemConfig = MainUtils.getSystemConfig();
|
||||
if (systemConfig != null && systemConfig.isEnablessl()) {
|
||||
view.addObject("schema", "https");
|
||||
if (request.getServerPort() == 80) {
|
||||
view.addObject("port", 443);
|
||||
} else {
|
||||
view.addObject("port", request.getServerPort());
|
||||
}
|
||||
} else {
|
||||
view.addObject("schema", request.getScheme());
|
||||
view.addObject("port", request.getServerPort());
|
||||
}
|
||||
view.addObject("appid", id);
|
||||
|
||||
|
||||
view.addObject("client", MainUtils.getUUID());
|
||||
view.addObject("sessionid", sessionid);
|
||||
|
||||
view.addObject("ip", MainUtils.md5(request.getRemoteAddr()));
|
||||
|
||||
view.addObject("mobile", CheckMobile.check(request.getHeader("User-Agent")));
|
||||
|
||||
CousultInvite invite = OnlineUserUtils.cousult(id, orgi, inviteRepository);
|
||||
if (invite != null) {
|
||||
orgi = invite.getOrgi();
|
||||
view.addObject("inviteData", invite);
|
||||
view.addObject("orgi", invite.getOrgi());
|
||||
view.addObject("appid", id);
|
||||
|
||||
if (StringUtils.isNotBlank(aiid)) {
|
||||
view.addObject("aiid", aiid);
|
||||
} else if (StringUtils.isNotBlank(invite.getAiid())) {
|
||||
view.addObject("aiid", invite.getAiid());
|
||||
}
|
||||
//记录用户行为日志
|
||||
UserHistory userHistory = new UserHistory();
|
||||
String url = request.getHeader("referer");
|
||||
if (StringUtils.isNotBlank(url)) {
|
||||
if (url.length() > 255) {
|
||||
userHistory.setUrl(url.substring(0, 255));
|
||||
} else {
|
||||
userHistory.setUrl(url);
|
||||
}
|
||||
userHistory.setReferer(userHistory.getUrl());
|
||||
}
|
||||
userHistory.setParam(MainUtils.getParameter(request));
|
||||
if (userHistory != null) {
|
||||
userHistory.setMaintype("im");
|
||||
userHistory.setSubtype("point");
|
||||
userHistory.setName("online");
|
||||
userHistory.setAdmin(false);
|
||||
userHistory.setAccessnum(true);
|
||||
}
|
||||
User imUser = super.getIMUser(request, userid, null);
|
||||
if (imUser != null) {
|
||||
userHistory.setCreater(imUser.getId());
|
||||
userHistory.setUsername(imUser.getUsername());
|
||||
userHistory.setOrgi(orgi);
|
||||
}
|
||||
if (StringUtils.isNotBlank(title)) {
|
||||
if (title.length() > 255) {
|
||||
userHistory.setTitle(title.substring(0, 255));
|
||||
} else {
|
||||
userHistory.setTitle(title);
|
||||
}
|
||||
}
|
||||
userHistory.setOrgi(invite.getOrgi());
|
||||
userHistory.setAppid(id);
|
||||
userHistory.setSessionid(sessionid);
|
||||
|
||||
String ip = MainUtils.getIpAddr(request);
|
||||
userHistory.setHostname(ip);
|
||||
userHistory.setIp(ip);
|
||||
IP ipdata = IPTools.getInstance().findGeography(ip);
|
||||
userHistory.setCountry(ipdata.getCountry());
|
||||
userHistory.setProvince(ipdata.getProvince());
|
||||
userHistory.setCity(ipdata.getCity());
|
||||
userHistory.setIsp(ipdata.getIsp());
|
||||
|
||||
BrowserClient client = MainUtils.parseClient(request);
|
||||
userHistory.setOstype(client.getOs());
|
||||
userHistory.setBrowser(client.getBrowser());
|
||||
userHistory.setMobile(CheckMobile.check(request.getHeader("User-Agent")) ? "1" : "0");
|
||||
|
||||
if (invite.isSkill()) {
|
||||
/***
|
||||
* 查询 技能组 , 缓存?
|
||||
*/
|
||||
view.addObject("skillList", OnlineUserUtils.organ(orgi, ipdata, invite, true));
|
||||
/**
|
||||
* 查询坐席 , 缓存?
|
||||
*/
|
||||
view.addObject("agentList", OnlineUserUtils.agents(orgi, true));
|
||||
}
|
||||
view.addObject("traceid", userHistory.getId());
|
||||
if (invite.isRecordhis()) {
|
||||
MainUtils.published(userHistory);
|
||||
}
|
||||
|
||||
view.addObject("pointAd", MainUtils.getPointAdv(MainContext.AdPosEnum.POINT.toString(), orgi));
|
||||
view.addObject("inviteAd", MainUtils.getPointAdv(MainContext.AdPosEnum.INVITE.toString(), orgi));
|
||||
}
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@RequestMapping("/{id}/userlist")
|
||||
@Menu(type = "im", subtype = "inlist", access = true)
|
||||
public void inlist(HttpServletRequest request, HttpServletResponse response, @PathVariable String id, @Valid String userid) throws IOException {
|
||||
response.setHeader("Content-Type", "text/html;charset=utf-8");
|
||||
if (StringUtils.isNotBlank(userid)) {
|
||||
BlackEntity black = (BlackEntity) CacheHelper.getSystemCacheBean().getCacheObject(userid, MainContext.SYSTEM_ORGI);
|
||||
if ((black != null && (black.getEndtime() == null || black.getEndtime().after(new Date())))) {
|
||||
response.getWriter().write("in");
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 延时获取用户端浏览器的跟踪ID
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
* @param orgi
|
||||
* @param appid
|
||||
* @param userid
|
||||
* @param sign
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping("/online")
|
||||
@Menu(type = "im", subtype = "online", access = true)
|
||||
public SseEmitter callable(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@Valid Contacts contacts,
|
||||
final @Valid String orgi,
|
||||
final @Valid String sessionid,
|
||||
@Valid String appid,
|
||||
final @Valid String userid,
|
||||
@Valid String sign,
|
||||
final @Valid String client,
|
||||
final @Valid String title,
|
||||
final @Valid String traceid) {
|
||||
BlackEntity black = (BlackEntity) CacheHelper.getSystemCacheBean().getCacheObject(userid, orgi);
|
||||
SseEmitter retSseEmitter = null;
|
||||
if ((black == null || (black.getEndtime() != null && black.getEndtime().before(new Date())))) {
|
||||
final SseEmitter emitter = new SseEmitter(30000L);
|
||||
if (CacheHelper.getSystemCacheBean().getCacheObject(userid, orgi) == null) {
|
||||
if (StringUtils.isNotBlank(userid)) {
|
||||
emitter.onCompletion(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
OnlineUserUtils.webIMClients.removeClient(userid, client, false); //执行了 邀请/再次邀请后终端的
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
emitter.onTimeout(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (emitter != null) {
|
||||
emitter.complete();
|
||||
}
|
||||
OnlineUserUtils.webIMClients.removeClient(userid, client, true); //正常的超时断开
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
CousultInvite invite = OnlineUserUtils.cousult(appid, orgi, inviteRepository);
|
||||
if (invite != null && invite.isTraceuser()) {
|
||||
contacts = processContacts(orgi, contacts, appid, userid);
|
||||
}
|
||||
if (StringUtils.isNotBlank(sign)) {
|
||||
OnlineUserUtils.online(super.getIMUser(request, sign, contacts != null ? contacts.getName() : null),
|
||||
orgi,
|
||||
sessionid,
|
||||
MainContext.OnlineUserTypeStatus.WEBIM.toString(),
|
||||
request,
|
||||
MainContext.ChannelTypeEnum.WEBIM.toString(),
|
||||
appid,
|
||||
contacts,
|
||||
invite);
|
||||
|
||||
}
|
||||
OnlineUserUtils.webIMClients.putClient(userid, new WebIMClient(userid, client, emitter));
|
||||
}
|
||||
}
|
||||
retSseEmitter = emitter;
|
||||
}
|
||||
return retSseEmitter;
|
||||
}
|
||||
|
||||
@RequestMapping("/index")
|
||||
@Menu(type = "im", subtype = "index", access = true)
|
||||
public ModelAndView index(ModelMap map, HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
@Valid String orgi,
|
||||
@Valid String aiid,
|
||||
@Valid String traceid,
|
||||
@Valid String exchange,
|
||||
@Valid String title,
|
||||
@Valid String url,
|
||||
@Valid String mobile,
|
||||
@Valid String phone,
|
||||
@Valid String ai,
|
||||
@Valid String client,
|
||||
@Valid String type,
|
||||
@Valid String appid,
|
||||
@Valid String userid,
|
||||
@Valid String sessionid,
|
||||
@Valid String skill,
|
||||
@Valid String agent,
|
||||
@Valid Contacts contacts,
|
||||
@Valid String product,
|
||||
@Valid String description,
|
||||
@Valid String imgurl,
|
||||
@Valid String pid,
|
||||
@Valid String purl) throws Exception {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("/apps/im/index"));
|
||||
BlackEntity black = (BlackEntity) CacheHelper.getSystemCacheBean().getCacheObject(userid, MainContext.SYSTEM_ORGI);
|
||||
if (StringUtils.isNotBlank(appid) && (black == null || (black.getEndtime() != null && black.getEndtime().before(new Date())))) {
|
||||
CousultInvite invite = OnlineUserUtils.cousult(appid, orgi, inviteRepository);
|
||||
String userID = null;
|
||||
if (StringUtils.isNotBlank(userid)) {
|
||||
userID = MainUtils.genIDByKey(userid);
|
||||
} else {
|
||||
userID = MainUtils.genIDByKey(sessionid);
|
||||
}
|
||||
String nickname = "Guest_" + userID;
|
||||
boolean consult = true; //是否已收集用户信息
|
||||
SessionConfig sessionConfig = AutomaticServiceDist.initSessionConfig(orgi);
|
||||
|
||||
map.addAttribute("sessionConfig", sessionConfig);
|
||||
map.addAttribute("hostname", request.getServerName());
|
||||
|
||||
if (sslPort != null) {
|
||||
map.addAttribute("port", sslPort);
|
||||
} else {
|
||||
map.addAttribute("port", port);
|
||||
}
|
||||
|
||||
map.addAttribute("appid", appid);
|
||||
map.addAttribute("userid", userid);
|
||||
map.addAttribute("schema", request.getScheme());
|
||||
map.addAttribute("sessionid", sessionid);
|
||||
|
||||
view.addObject("product", product);
|
||||
view.addObject("description", description);
|
||||
view.addObject("imgurl", imgurl);
|
||||
view.addObject("pid", pid);
|
||||
view.addObject("purl", purl);
|
||||
|
||||
map.addAttribute("ip", MainUtils.md5(request.getRemoteAddr()));
|
||||
|
||||
if (StringUtils.isNotBlank(traceid)) {
|
||||
map.addAttribute("traceid", traceid);
|
||||
}
|
||||
if (StringUtils.isNotBlank(exchange)) {
|
||||
map.addAttribute("exchange", exchange);
|
||||
}
|
||||
if (StringUtils.isNotBlank(title)) {
|
||||
map.addAttribute("title", title);
|
||||
}
|
||||
if (StringUtils.isNotBlank(traceid)) {
|
||||
map.addAttribute("url", url);
|
||||
}
|
||||
|
||||
map.addAttribute("ukefport", request.getServerPort());
|
||||
/**
|
||||
* 先检查 invite不为空
|
||||
*/
|
||||
if (invite != null) {
|
||||
map.addAttribute("orgi", invite.getOrgi());
|
||||
map.addAttribute("inviteData", invite);
|
||||
|
||||
if (StringUtils.isNotBlank(aiid)) {
|
||||
map.addAttribute("aiid", aiid);
|
||||
} else if (StringUtils.isNotBlank(invite.getAiid())) {
|
||||
map.addAttribute("aiid", invite.getAiid());
|
||||
}
|
||||
|
||||
AgentReport report = AutomaticServiceDist.getAgentReport(invite.getOrgi());
|
||||
|
||||
if (report.getAgents() == 0 || (sessionConfig.isHourcheck() && !MainUtils.isInWorkingHours(sessionConfig.getWorkinghours()) && invite.isLeavemessage())) {
|
||||
view = request(super.createRequestPageTempletResponse("/apps/im/leavemsg"));
|
||||
} else if (invite.isConsult_info()) { //启用了信息收集 , 从Request获取 , 或从 Cookies 里去
|
||||
//验证 OnlineUser 信息
|
||||
if (contacts != null && StringUtils.isNotBlank(contacts.getName())) { //contacts用于传递信息,并不和 联系人表发生 关联,contacts信息传递给 Socket.IO,然后赋值给 AgentUser,最终赋值给 AgentService永久存储
|
||||
consult = true;
|
||||
//存入 Cookies
|
||||
if (invite.isConsult_info_cookies()) {
|
||||
Cookie name = new Cookie("name", MainUtils.encryption(URLEncoder.encode(contacts.getName(), "UTF-8")));
|
||||
response.addCookie(name);
|
||||
name.setMaxAge(3600);
|
||||
if (StringUtils.isNotBlank(contacts.getPhone())) {
|
||||
Cookie phonecookie = new Cookie("phone", MainUtils.encryption(URLEncoder.encode(contacts.getPhone(), "UTF-8")));
|
||||
phonecookie.setMaxAge(3600);
|
||||
response.addCookie(phonecookie);
|
||||
}
|
||||
if (StringUtils.isNotBlank(contacts.getEmail())) {
|
||||
Cookie email = new Cookie("email", MainUtils.encryption(URLEncoder.encode(contacts.getEmail(), "UTF-8")));
|
||||
email.setMaxAge(3600);
|
||||
response.addCookie(email);
|
||||
}
|
||||
if (StringUtils.isNotBlank(contacts.getMemo())) {
|
||||
Cookie memo = new Cookie("memo", MainUtils.encryption(URLEncoder.encode(contacts.getName(), "UTF-8")));
|
||||
memo.setMaxAge(3600);
|
||||
response.addCookie(memo);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//从 Cookies里尝试读取
|
||||
if (invite.isConsult_info_cookies()) {
|
||||
Cookie[] cookies = request.getCookies();//这样便可以获取一个cookie数组
|
||||
contacts = new Contacts();
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie != null && StringUtils.isNotBlank(cookie.getName()) && StringUtils.isNotBlank(cookie.getValue())) {
|
||||
if (cookie.getName().equals("name")) {
|
||||
contacts.setName(URLDecoder.decode(MainUtils.decryption(cookie.getValue()), "UTF-8"));
|
||||
}
|
||||
if (cookie.getName().equals("phone")) {
|
||||
contacts.setPhone(URLDecoder.decode(MainUtils.decryption(cookie.getValue()), "UTF-8"));
|
||||
}
|
||||
if (cookie.getName().equals("email")) {
|
||||
contacts.setEmail(URLDecoder.decode(MainUtils.decryption(cookie.getValue()), "UTF-8"));
|
||||
}
|
||||
if (cookie.getName().equals("memo")) {
|
||||
contacts.setMemo(URLDecoder.decode(MainUtils.decryption(cookie.getValue()), "UTF-8"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (StringUtils.isBlank(contacts.getName())) {
|
||||
consult = false;
|
||||
view = request(super.createRequestPageTempletResponse("/apps/im/collecting"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
contacts = processContacts(invite.getOrgi(), contacts, appid, userid);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(client)) {
|
||||
map.addAttribute("client", client);
|
||||
}
|
||||
if (StringUtils.isNotBlank(skill)) {
|
||||
map.addAttribute("skill", skill);
|
||||
}
|
||||
if (StringUtils.isNotBlank(agent)) {
|
||||
map.addAttribute("agent", agent);
|
||||
}
|
||||
|
||||
map.addAttribute("contacts", contacts);
|
||||
|
||||
if (StringUtils.isNotBlank(type)) {
|
||||
map.addAttribute("type", type);
|
||||
}
|
||||
IP ipdata = IPTools.getInstance().findGeography(MainUtils.getIpAddr(request));
|
||||
map.addAttribute("skillList", OnlineUserUtils.organ(invite.getOrgi(), ipdata, invite, true));
|
||||
|
||||
if (invite != null && consult) {
|
||||
if (contacts != null && StringUtils.isNotBlank(contacts.getName())) {
|
||||
nickname = contacts.getName();
|
||||
}
|
||||
map.addAttribute("username", nickname);
|
||||
if (MainContext.model.get("chatbot") != null &&
|
||||
StringUtils.isNotBlank(invite.getAiid()) &&
|
||||
invite.isAi() &&
|
||||
((StringUtils.equals(ai, "true")) || (invite.isAifirst() && ai == null))) { //启用 AI , 并且 AI优先 接待
|
||||
HashMap<String, String> chatbotConfig = new HashMap<String, String>();
|
||||
chatbotConfig.put("botname", invite.getAiname());
|
||||
chatbotConfig.put("botid", invite.getAiid());
|
||||
chatbotConfig.put("botwelcome", invite.getAimsg());
|
||||
chatbotConfig.put("botfirst", Boolean.toString(invite.isAifirst()));
|
||||
chatbotConfig.put("isai", Boolean.toString(invite.isAi()));
|
||||
if (chatbotConfig != null) {
|
||||
map.addAttribute("chatbotConfig", chatbotConfig);
|
||||
}
|
||||
view = request(super.createRequestPageTempletResponse("/apps/im/chatbot/index"));
|
||||
if (CheckMobile.check(request.getHeader("User-Agent")) || StringUtils.isNotBlank(mobile)) {
|
||||
view = request(super.createRequestPageTempletResponse("/apps/im/chatbot/mobile")); //智能机器人 移动端
|
||||
}
|
||||
} else {
|
||||
if (CheckMobile.check(request.getHeader("User-Agent")) || StringUtils.isNotBlank(mobile)) {
|
||||
view = request(super.createRequestPageTempletResponse("/apps/im/mobile")); //WebIM移动端。再次点选技能组?
|
||||
}
|
||||
}
|
||||
map.addAttribute("chatMessageList", chatMessageRes.findByUsessionAndOrgi(userid, orgi, new PageRequest(0, 20, Direction.DESC, "updatetime")));
|
||||
}
|
||||
view.addObject("commentList", UKeFuDic.getInstance().getDic(MainContext.UKEFU_SYSTEM_COMMENT_DIC));
|
||||
view.addObject("commentItemList", UKeFuDic.getInstance().getDic(MainContext.UKEFU_SYSTEM_COMMENT_ITEM_DIC));
|
||||
view.addObject("welcomeAd", MainUtils.getPointAdv(MainContext.AdPosEnum.WELCOME.toString(), orgi));
|
||||
view.addObject("imageAd", MainUtils.getPointAdv(MainContext.AdPosEnum.IMAGE.toString(), orgi));
|
||||
// OnlineUserUtils.sendWebIMClients(userid , "accept");
|
||||
|
||||
if (invite.isTraceuser()) {
|
||||
Page<InviteRecord> inviteRecordList = inviteRecordRes.findByUseridAndOrgi(userid, orgi, new PageRequest(0, 1, Direction.DESC, "createtime"));
|
||||
if (inviteRecordList.getContent() != null && inviteRecordList.getContent().size() > 0) {
|
||||
InviteRecord record = inviteRecordList.getContent().get(0);
|
||||
record.setUpdatetime(new Date());
|
||||
record.setTraceid(traceid);
|
||||
record.setTitle(title);
|
||||
record.setUrl(url);
|
||||
record.setResponsetime((int) (System.currentTimeMillis() - record.getCreatetime().getTime()));
|
||||
record.setResult(MainContext.OnlineUserInviteStatus.ACCEPT.toString());
|
||||
inviteRecordRes.save(record);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
private Contacts processContacts(String orgi, Contacts contacts, String appid, String userid) {
|
||||
if (contacts != null) {
|
||||
if (contacts != null &&
|
||||
(StringUtils.isNotBlank(contacts.getName()) ||
|
||||
StringUtils.isNotBlank(contacts.getPhone()) ||
|
||||
StringUtils.isNotBlank(contacts.getEmail()))) {
|
||||
StringBuffer query = new StringBuffer();
|
||||
query.append(contacts.getName());
|
||||
if (StringUtils.isNotBlank(contacts.getPhone())) {
|
||||
query.append(" OR ").append(contacts.getPhone());
|
||||
}
|
||||
if (StringUtils.isNotBlank(contacts.getEmail())) {
|
||||
query.append(" OR ").append(contacts.getEmail());
|
||||
}
|
||||
Page<Contacts> contactsList = contactsRes.findByOrgi(orgi, false, query.toString(), new PageRequest(0, 1));
|
||||
if (contactsList.getContent().size() > 0) {
|
||||
contacts = contactsList.getContent().get(0);
|
||||
} else {
|
||||
// contactsRes.save(contacts) ; //需要增加签名验证,避免随便产生垃圾信息,也可以自行修改?
|
||||
contacts.setId(null);
|
||||
}
|
||||
} else {
|
||||
contacts.setId(null);
|
||||
}
|
||||
if (contacts != null && StringUtils.isNotBlank(contacts.getId())) {
|
||||
List<AgentUserContacts> agentUserContactsList = agentUserContactsRes.findByUseridAndOrgi(userid, orgi);
|
||||
if (agentUserContactsList.size() == 0) {
|
||||
AgentUserContacts agentUserContacts = new AgentUserContacts();
|
||||
agentUserContacts.setAppid(appid);
|
||||
agentUserContacts.setChannel(MainContext.ChannelTypeEnum.WEBIM.toString());
|
||||
agentUserContacts.setContactsid(contacts.getId());
|
||||
agentUserContacts.setUserid(userid);
|
||||
agentUserContacts.setOrgi(orgi);
|
||||
agentUserContacts.setCreatetime(new Date());
|
||||
agentUserContactsRes.save(agentUserContacts);
|
||||
}
|
||||
} else if (StringUtils.isNotBlank(userid)) {
|
||||
List<AgentUserContacts> agentUserContactsList = agentUserContactsRes.findByUseridAndOrgi(userid, orgi);
|
||||
if (agentUserContactsList.size() > 0) {
|
||||
AgentUserContacts agentUserContacts = agentUserContactsList.get(0);
|
||||
contacts = contactsRes.findOne(agentUserContacts.getContactsid());
|
||||
}
|
||||
}
|
||||
}
|
||||
return contacts;
|
||||
}
|
||||
|
||||
@RequestMapping("/text/{appid}")
|
||||
@Menu(type = "im", subtype = "index", access = true)
|
||||
public ModelAndView text(HttpServletRequest request, HttpServletResponse response, @PathVariable String appid, @Valid String traceid, @Valid String aiid, @Valid String exchange, @Valid String title, @Valid String url, @Valid String skill, @Valid String id, @Valid String userid, @Valid String agent, @Valid String name, @Valid String email, @Valid String phone, @Valid String ai, @Valid String orgi, @Valid String product, @Valid String description, @Valid String imgurl, @Valid String pid, @Valid String purl) throws Exception {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("/apps/im/text"));
|
||||
|
||||
view.addObject("hostname", request.getServerName());
|
||||
view.addObject("port", request.getServerPort());
|
||||
view.addObject("schema", request.getScheme());
|
||||
view.addObject("appid", appid);
|
||||
|
||||
|
||||
view.addObject("ip", MainUtils.md5(request.getRemoteAddr()));
|
||||
|
||||
if (StringUtils.isNotBlank(skill)) {
|
||||
view.addObject("skill", skill);
|
||||
}
|
||||
if (StringUtils.isNotBlank(agent)) {
|
||||
view.addObject("agent", agent);
|
||||
}
|
||||
|
||||
view.addObject("client", MainUtils.getUUID());
|
||||
view.addObject("sessionid", request.getSession().getId());
|
||||
|
||||
view.addObject("id", id);
|
||||
if (StringUtils.isNotBlank(ai)) {
|
||||
view.addObject("ai", ai);
|
||||
}
|
||||
if (StringUtils.isNotBlank(exchange)) {
|
||||
view.addObject("exchange", exchange);
|
||||
}
|
||||
|
||||
view.addObject("name", name);
|
||||
view.addObject("email", email);
|
||||
view.addObject("phone", phone);
|
||||
view.addObject("userid", userid);
|
||||
|
||||
view.addObject("product", product);
|
||||
view.addObject("description", description);
|
||||
view.addObject("imgurl", imgurl);
|
||||
view.addObject("pid", pid);
|
||||
view.addObject("purl", purl);
|
||||
|
||||
|
||||
if (StringUtils.isNotBlank(traceid)) {
|
||||
view.addObject("traceid", traceid);
|
||||
}
|
||||
if (StringUtils.isNotBlank(title)) {
|
||||
view.addObject("title", title);
|
||||
}
|
||||
if (StringUtils.isNotBlank(traceid)) {
|
||||
view.addObject("url", url);
|
||||
}
|
||||
CousultInvite invite = OnlineUserUtils.cousult(appid, orgi, inviteRepository);
|
||||
if (invite != null) {
|
||||
view.addObject("inviteData", invite);
|
||||
view.addObject("orgi", invite.getOrgi());
|
||||
view.addObject("appid", appid);
|
||||
|
||||
if (StringUtils.isNotBlank(aiid)) {
|
||||
view.addObject("aiid", aiid);
|
||||
} else if (StringUtils.isNotBlank(invite.getAiid())) {
|
||||
view.addObject("aiid", invite.getAiid());
|
||||
}
|
||||
}
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping("/leavemsg/save")
|
||||
@Menu(type = "admin", subtype = "user")
|
||||
public ModelAndView leavemsgsave(HttpServletRequest request, @Valid String appid, @Valid LeaveMsg msg) {
|
||||
if (StringUtils.isNotBlank(appid)) {
|
||||
SNSAccount snsAccount = snsAccountRepository.findBySnsid(appid);
|
||||
String orgi = snsAccount.getOrgi();
|
||||
CousultInvite invite = inviteRepository.findBySnsaccountidAndOrgi(appid, orgi);
|
||||
;
|
||||
List<LeaveMsg> msgList = leaveMsgRes.findByOrgiAndUserid(invite.getOrgi(), msg.getUserid());
|
||||
// if(msg!=null && msgList.size() == 0){
|
||||
if (msg != null) {
|
||||
msg.setOrgi(invite.getOrgi());
|
||||
leaveMsgRes.save(msg);
|
||||
}
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("/apps/im/leavemsgsave"));
|
||||
}
|
||||
|
||||
@RequestMapping("/refuse")
|
||||
@Menu(type = "im", subtype = "refuse", access = true)
|
||||
public void refuse(HttpServletRequest request, HttpServletResponse response, @Valid String orgi, @Valid String appid, @Valid String userid, @Valid String sessionid, @Valid String client) throws Exception {
|
||||
OnlineUserUtils.refuseInvite(userid, orgi);
|
||||
// OnlineUserUtils.sendWebIMClients(userid , "refuse");
|
||||
Page<InviteRecord> inviteRecordList = inviteRecordRes.findByUseridAndOrgi(userid, orgi, new PageRequest(0, 1, Direction.DESC, "createtime"));
|
||||
if (inviteRecordList.getContent() != null && inviteRecordList.getContent().size() > 0) {
|
||||
InviteRecord record = inviteRecordList.getContent().get(0);
|
||||
record.setUpdatetime(new Date());
|
||||
record.setResponsetime((int) (System.currentTimeMillis() - record.getCreatetime().getTime()));
|
||||
record.setResult(MainContext.OnlineUserInviteStatus.REFUSE.toString());
|
||||
inviteRecordRes.save(record);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@RequestMapping("/satis")
|
||||
@Menu(type = "im", subtype = "satis", access = true)
|
||||
public void satis(HttpServletRequest request, HttpServletResponse response, @Valid AgentServiceSatis satis) throws Exception {
|
||||
if (satis != null && StringUtils.isNotBlank(satis.getId())) {
|
||||
int count = agentServiceSatisRes.countById(satis.getId());
|
||||
if (count == 1) {
|
||||
if (StringUtils.isNotBlank(satis.getSatiscomment()) && satis.getSatiscomment().length() > 255) {
|
||||
satis.setSatiscomment(satis.getSatiscomment().substring(0, 255));
|
||||
}
|
||||
satis.setSatisfaction(true);
|
||||
satis.setSatistime(new Date());
|
||||
agentServiceSatisRes.save(satis);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@RequestMapping("/image/upload")
|
||||
@Menu(type = "im", subtype = "image", access = true)
|
||||
public ModelAndView upload(ModelMap map, HttpServletRequest request,
|
||||
@RequestParam(value = "imgFile", required = false) MultipartFile multipart,
|
||||
@Valid String channel,
|
||||
@Valid String userid,
|
||||
@Valid String username,
|
||||
@Valid String appid,
|
||||
@Valid String orgi,
|
||||
@Valid String paste) throws IOException {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("/apps/im/upload"));
|
||||
UploadStatus upload = null;
|
||||
String fileName = null;
|
||||
if (multipart != null
|
||||
&& multipart.getOriginalFilename().lastIndexOf(".") > 0
|
||||
&& StringUtils.isNotBlank(userid)) {
|
||||
File uploadDir = new File(path, "upload");
|
||||
if (!uploadDir.exists()) {
|
||||
uploadDir.mkdirs();
|
||||
}
|
||||
|
||||
String fileid = MainUtils.getUUID();
|
||||
StreamingFile sf = new StreamingFile();
|
||||
sf.setId(fileid);
|
||||
sf.setName(multipart.getOriginalFilename());
|
||||
sf.setMime(multipart.getContentType());
|
||||
if (multipart.getContentType() != null
|
||||
&& multipart.getContentType().indexOf(Constants.ATTACHMENT_TYPE_IMAGE) >= 0) {
|
||||
// 检查文件格式
|
||||
String invalid = StreamingFileUtils.getInstance().validate(Constants.ATTACHMENT_TYPE_IMAGE, multipart.getOriginalFilename());
|
||||
if (invalid == null) {
|
||||
fileName = "upload/" + fileid + "_original";
|
||||
File imageFile = new File(path, fileName);
|
||||
FileCopyUtils.copy(multipart.getBytes(), imageFile);
|
||||
String thumbnailsFileName = "upload/" + fileid;
|
||||
File thumbnail = new File(path, thumbnailsFileName);
|
||||
MainUtils.processImage(thumbnail, imageFile);
|
||||
|
||||
// 存储数据库
|
||||
sf.setData(jpaBlobHelper.createBlob(multipart.getInputStream(), multipart.getSize()));
|
||||
sf.setThumbnail(jpaBlobHelper.createBlobWithFile(thumbnail));
|
||||
streamingFileRepository.save(sf);
|
||||
String fileUrl = "/res/image.html?id=" + fileid;
|
||||
upload = new UploadStatus("0", fileUrl);
|
||||
|
||||
if (paste == null) {
|
||||
if (StringUtils.isNotBlank(channel)) {
|
||||
RichMediaUtils.uploadImageWithChannel(fileUrl, fileid, (int) multipart.getSize(), multipart.getName(), channel, userid, username, appid, orgi);
|
||||
} else {
|
||||
RichMediaUtils.uploadImage(fileUrl, fileid, (int) multipart.getSize(), multipart.getName(), userid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
upload = new UploadStatus(invalid);
|
||||
}
|
||||
} else {
|
||||
String invalid = StreamingFileUtils.getInstance().validate(Constants.ATTACHMENT_TYPE_FILE, multipart.getOriginalFilename());
|
||||
if (invalid == null) {
|
||||
// 存储数据库
|
||||
sf.setData(jpaBlobHelper.createBlob(multipart.getInputStream(), multipart.getSize()));
|
||||
streamingFileRepository.save(sf);
|
||||
|
||||
// 存储到本地硬盘
|
||||
String id = processAttachmentFile(multipart, fileid, request);
|
||||
upload = new UploadStatus("0", "/res/file.html?id=" + id);
|
||||
String file = "/res/file.html?id=" + id;
|
||||
|
||||
File tempFile = new File(multipart.getOriginalFilename());
|
||||
if (StringUtils.isNotBlank(channel)) {
|
||||
RichMediaUtils.uploadFileWithChannel(file, (int) multipart.getSize(), tempFile.getName(), channel, userid, username, appid, orgi, id);
|
||||
} else {
|
||||
RichMediaUtils.uploadFile(file, (int) multipart.getSize(), tempFile.getName(), userid, id);
|
||||
}
|
||||
} else {
|
||||
upload = new UploadStatus(invalid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
upload = new UploadStatus("请选择文件");
|
||||
}
|
||||
map.addAttribute("upload", upload);
|
||||
return view;
|
||||
}
|
||||
|
||||
private String processAttachmentFile(final MultipartFile file, final String fileid, HttpServletRequest request) throws IOException {
|
||||
String id = null;
|
||||
if (file.getSize() > 0) { //文件尺寸 限制 ?在 启动 配置中 设置 的最大值,其他地方不做限制
|
||||
AttachmentFile attachmentFile = new AttachmentFile();
|
||||
attachmentFile.setCreater(super.getUser(request).getId());
|
||||
attachmentFile.setOrgi(super.getOrgi(request));
|
||||
attachmentFile.setOrgan(super.getUser(request).getOrgan());
|
||||
attachmentFile.setModel(MainContext.ModelType.WEBIM.toString());
|
||||
attachmentFile.setFilelength((int) file.getSize());
|
||||
if (file.getContentType() != null && file.getContentType().length() > 255) {
|
||||
attachmentFile.setFiletype(file.getContentType().substring(0, 255));
|
||||
} else {
|
||||
attachmentFile.setFiletype(file.getContentType());
|
||||
}
|
||||
File uploadFile = new File(file.getOriginalFilename());
|
||||
if (uploadFile.getName() != null && uploadFile.getName().length() > 255) {
|
||||
attachmentFile.setTitle(uploadFile.getName().substring(0, 255));
|
||||
} else {
|
||||
attachmentFile.setTitle(uploadFile.getName());
|
||||
}
|
||||
if (StringUtils.isNotBlank(attachmentFile.getFiletype()) && attachmentFile.getFiletype().indexOf("image") >= 0) {
|
||||
attachmentFile.setImage(true);
|
||||
}
|
||||
attachmentFile.setFileid(fileid);
|
||||
attachementRes.save(attachmentFile);
|
||||
FileUtils.writeByteArrayToFile(new File(path, "upload/" + fileid), file.getBytes());
|
||||
id = attachmentFile.getId();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
}
|
@ -1,129 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.chatopera.cc.app.handler.apps.quality;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.app.algorithm.AutomaticServiceDist;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.app.persistence.repository.SessionConfigRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.TagRepository;
|
||||
import com.chatopera.cc.app.model.Quality;
|
||||
import com.chatopera.cc.app.model.QualityRequest;
|
||||
import com.chatopera.cc.app.model.Tag;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.persistence.repository.QualityRepository;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.SessionConfig;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/quality")
|
||||
public class AgentQualityController extends Handler{
|
||||
|
||||
|
||||
@Autowired
|
||||
private QualityRepository qualityRes ;
|
||||
|
||||
@Autowired
|
||||
private SessionConfigRepository sessionConfigRes ;
|
||||
|
||||
@Autowired
|
||||
private TagRepository tagRes ;
|
||||
|
||||
|
||||
@RequestMapping(value = "/index")
|
||||
@Menu(type = "agent" , subtype = "quality" , access = false)
|
||||
public ModelAndView index(ModelMap map , HttpServletRequest request ) {
|
||||
map.addAttribute("sessionConfig", AutomaticServiceDist.initSessionConfig(super.getOrgi(request))) ;
|
||||
map.addAttribute("qualityList", qualityRes.findByQualitytypeAndOrgi(MainContext.QualityType.CHAT.toString(), super.getOrgi(request))) ;
|
||||
map.addAttribute("tagList", tagRes.findByOrgiAndTagtype(super.getOrgi(request), MainContext.TagTypeEnum.QUALITY.toString())) ;
|
||||
return request(super.createAppsTempletResponse("/apps/quality/index"));
|
||||
}
|
||||
|
||||
|
||||
@RequestMapping(value = "/save")
|
||||
@Menu(type = "agent" , subtype = "quality" , access = false)
|
||||
public ModelAndView save(ModelMap map , HttpServletRequest request ,@Valid QualityRequest qualityArray) {
|
||||
if(qualityArray!=null && qualityArray.getTitle()!=null) {
|
||||
List<Quality> qualityList = qualityRes.findByQualitytypeAndOrgi(MainContext.QualityType.CHAT.toString(), super.getOrgi(request)) ;
|
||||
qualityRes.delete(qualityList);
|
||||
List<Quality> tempList = new ArrayList<Quality>();
|
||||
for(int i=0 ; i<qualityArray.getTitle().length ; i++) {
|
||||
Quality temp = new Quality();
|
||||
temp.setName(qualityArray.getTitle()[i]);
|
||||
if(qualityArray.getDescription().length == qualityArray.getTitle().length) {
|
||||
temp.setDescription(qualityArray.getDescription()[i]);
|
||||
}
|
||||
if(qualityArray.getScore().length == qualityArray.getTitle().length) {
|
||||
temp.setScore(qualityArray.getScore()[i]);
|
||||
}
|
||||
temp.setOrgi(super.getOrgi(request));
|
||||
temp.setQualitytype(MainContext.QualityType.CHAT.toString());
|
||||
tempList.add(temp) ;
|
||||
}
|
||||
if(tempList.size() > 0) {
|
||||
qualityRes.save(tempList) ;
|
||||
}
|
||||
SessionConfig config = AutomaticServiceDist.initSessionConfig(super.getOrgi(request)) ;
|
||||
if(config!=null) {
|
||||
if("points".equals(request.getParameter("qualityscore"))) {
|
||||
config.setQualityscore("points");
|
||||
}else {
|
||||
config.setQualityscore("score");
|
||||
}
|
||||
|
||||
sessionConfigRes.save(config) ;
|
||||
|
||||
CacheHelper.getSystemCacheBean().put(MainContext.SYSTEM_CACHE_SESSION_CONFIG+"_"+super.getOrgi(request),config, super.getOrgi(request)) ;
|
||||
|
||||
CacheHelper.getSystemCacheBean().delete(MainContext.SYSTEM_CACHE_SESSION_CONFIG_LIST , MainContext.SYSTEM_ORGI) ;
|
||||
}
|
||||
if(qualityArray!=null && qualityArray.getTag()!=null && qualityArray.getTag().length > 0) {
|
||||
List<Tag> tagList = tagRes.findByOrgiAndTagtype(super.getOrgi(request), MainContext.TagTypeEnum.QUALITY.toString()) ;
|
||||
if(tagList.size() > 0) {
|
||||
tagRes.delete(tagList);
|
||||
}
|
||||
List<Tag> tagTempList = new ArrayList<Tag>() ;
|
||||
for(String tag : qualityArray.getTag()) {
|
||||
Tag temp = new Tag();
|
||||
temp.setOrgi(super.getOrgi(request));
|
||||
temp.setCreater(super.getUser(request).getId());
|
||||
temp.setTag(tag);
|
||||
temp.setCreater(super.getOrgi(request));
|
||||
temp.setTagtype(MainContext.TagTypeEnum.QUALITY.toString());
|
||||
tagTempList.add(temp) ;
|
||||
}
|
||||
if(tagTempList.size() > 0) {
|
||||
tagRes.save(tagTempList) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/quality/index.html"));
|
||||
}
|
||||
}
|
@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.apps.service;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.util.bi.ReportData;
|
||||
import com.chatopera.cc.app.persistence.repository.DataSourceService;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.basic.MainUtils;
|
||||
import com.chatopera.cc.util.bi.UKExcelUtil;
|
||||
import com.chatopera.cc.util.bi.model.Level;
|
||||
import com.chatopera.cc.app.persistence.repository.CubeService;
|
||||
import com.chatopera.cc.util.OnlineUserUtils;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.SysDic;
|
||||
import com.chatopera.cc.app.model.UKeFuDic;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/service")
|
||||
public class StatsController extends Handler{
|
||||
|
||||
@Value("${web.upload-path}")
|
||||
private String path;
|
||||
|
||||
@Autowired
|
||||
private DataSourceService dataSource ;
|
||||
|
||||
@RequestMapping("/stats/coment")
|
||||
@Menu(type = "service" , subtype = "statcoment" , admin= true)
|
||||
public ModelAndView statcoment(ModelMap map , HttpServletRequest request , @Valid String agent , @Valid String skill , @Valid String begin ,@Valid String end) throws Exception {
|
||||
Map<String,Object> mapR = MainUtils.getRequestParam(request);
|
||||
mapR.put("orgi",super.getOrgi(request));
|
||||
ReportData reportData = new CubeService("coment.xml", path, dataSource ,mapR ).execute("SELECT [comment].[满意度].members on columns , NonEmptyCrossJoin([time].[日期].members , NonEmptyCrossJoin([skill].[技能组].members,[agent].[坐席].members)) on rows FROM [满意度]") ;
|
||||
|
||||
List<SysDic> dicList = UKeFuDic.getInstance().getDic(MainContext.UKEFU_SYSTEM_COMMENT_DIC) ;
|
||||
for(Level title : reportData.getCol().getChilderen()){
|
||||
for(SysDic dic : dicList){
|
||||
if(dic.getCode().equals(title.getName())){
|
||||
title.setName(dic.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
map.addAttribute("reportData", reportData);
|
||||
if(!StringUtils.isBlank(agent)){
|
||||
map.addAttribute("agent", agent);
|
||||
}
|
||||
if(!StringUtils.isBlank(skill)){
|
||||
map.addAttribute("skill", skill);
|
||||
}
|
||||
if(!StringUtils.isBlank(begin)){
|
||||
map.addAttribute("begin", begin);
|
||||
}
|
||||
if(!StringUtils.isBlank(end)){
|
||||
map.addAttribute("end", end);
|
||||
}
|
||||
map.addAttribute("orgi",super.getOrgi(request));
|
||||
/***
|
||||
* 查询 技能组 , 缓存?
|
||||
*/
|
||||
map.addAttribute("skillList", OnlineUserUtils.organ(super.getOrgi(request),true)) ;
|
||||
/**
|
||||
* 查询坐席 , 缓存?
|
||||
*/
|
||||
map.addAttribute("agentList", OnlineUserUtils.agents(super.getOrgi(request),true)) ;
|
||||
|
||||
return request(super.createAppsTempletResponse("/apps/service/stats/coment"));
|
||||
}
|
||||
|
||||
@RequestMapping("/stats/coment/exp")
|
||||
@Menu(type = "service" , subtype = "statcoment" , admin= true)
|
||||
public void statcomentexp(ModelMap map , HttpServletRequest request , HttpServletResponse response , @Valid String agent , @Valid String skill , @Valid String begin ,@Valid String end) throws Exception {
|
||||
Map<String,Object> mapR = MainUtils.getRequestParam(request);
|
||||
mapR.put("orgi",super.getOrgi(request));
|
||||
ReportData reportData = new CubeService("coment.xml", path, dataSource , mapR).execute("SELECT [comment].[满意度].members on columns , NonEmptyCrossJoin([time].[日期].members , NonEmptyCrossJoin([skill].[技能组].members,[agent].[坐席].members)) on rows FROM [满意度]") ;
|
||||
|
||||
List<SysDic> dicList = UKeFuDic.getInstance().getDic(MainContext.UKEFU_SYSTEM_COMMENT_DIC) ;
|
||||
for(Level title : reportData.getCol().getChilderen()){
|
||||
for(SysDic dic : dicList){
|
||||
if(dic.getCode().equals(title.getName())){
|
||||
title.setName(dic.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.setHeader("content-disposition", "attachment;filename=UCKeFu-Report-"+new SimpleDateFormat("yyyy-MM-dd").format(new Date())+".xls");
|
||||
new UKExcelUtil(reportData , response.getOutputStream() , "满意度统计").createFile() ;
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
@RequestMapping("/stats/agent")
|
||||
@Menu(type = "service" , subtype = "statagent" , admin= true)
|
||||
public ModelAndView statagent(ModelMap map , HttpServletRequest request , @Valid String agent , @Valid String skill , @Valid String begin ,@Valid String end) throws Exception {
|
||||
Map<String,Object> mapR = MainUtils.getRequestParam(request);
|
||||
mapR.put("orgi",super.getOrgi(request));
|
||||
ReportData reportData = new CubeService("consult.xml", path, dataSource , mapR).execute("SELECT {[Measures].[咨询数量],[Measures].[平均等待时长(秒)],[Measures].[平均咨询时长(秒)]} on columns , NonEmptyCrossJoin([time].[日期].members , NonEmptyCrossJoin([skill].[技能组].members,[agent].[坐席].members)) on rows FROM [咨询]") ;
|
||||
map.addAttribute("reportData", reportData);
|
||||
|
||||
if(!StringUtils.isBlank(agent)){
|
||||
map.addAttribute("agent", agent);
|
||||
}
|
||||
if(!StringUtils.isBlank(skill)){
|
||||
map.addAttribute("skill", skill);
|
||||
}
|
||||
if(!StringUtils.isBlank(begin)){
|
||||
map.addAttribute("begin", begin);
|
||||
}
|
||||
if(!StringUtils.isBlank(end)){
|
||||
map.addAttribute("end", end);
|
||||
}
|
||||
/***
|
||||
* 查询 技能组 , 缓存?
|
||||
*/
|
||||
map.addAttribute("skillList", OnlineUserUtils.organ(super.getOrgi(request),true)) ;
|
||||
/**
|
||||
* 查询坐席 , 缓存?
|
||||
*/
|
||||
map.addAttribute("agentList", OnlineUserUtils.agents(super.getOrgi(request),true)) ;
|
||||
|
||||
return request(super.createAppsTempletResponse("/apps/service/stats/consult"));
|
||||
}
|
||||
|
||||
@RequestMapping("/stats/agent/exp")
|
||||
@Menu(type = "service" , subtype = "statagent" , admin= true)
|
||||
public void statagentexp(ModelMap map , HttpServletRequest request , HttpServletResponse response ,@Valid String agent , @Valid String skill , @Valid String begin ,@Valid String end) throws Exception {
|
||||
Map<String,Object> mapR = MainUtils.getRequestParam(request);
|
||||
mapR.put("orgi",super.getOrgi(request));
|
||||
ReportData reportData = new CubeService("consult.xml", path, dataSource , mapR).execute("SELECT {[Measures].[咨询数量],[Measures].[平均等待时长(秒)],[Measures].[平均咨询时长(秒)]} on columns , NonEmptyCrossJoin([time].[日期].members , NonEmptyCrossJoin([skill].[技能组].members,[agent].[坐席].members)) on rows FROM [咨询]") ;
|
||||
response.setHeader("content-disposition", "attachment;filename=UCKeFu-Report-"+new SimpleDateFormat("yyyy-MM-dd").format(new Date())+".xls");
|
||||
new UKExcelUtil(reportData , response.getOutputStream() , "客服坐席统计").createFile() ;
|
||||
|
||||
return ;
|
||||
}
|
||||
}
|
@ -1,305 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.apps.tenant;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.algorithm.AutomaticServiceDist;
|
||||
import com.chatopera.cc.app.cache.CacheHelper;
|
||||
import com.chatopera.cc.util.OnlineUserUtils;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.app.persistence.repository.AgentUserRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.OrganRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.OrganizationRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.OrgiSkillRelRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.TenantRepository;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.AgentStatus;
|
||||
import com.chatopera.cc.app.model.AgentUser;
|
||||
import com.chatopera.cc.app.model.Organ;
|
||||
import com.chatopera.cc.app.model.OrgiSkillRel;
|
||||
import com.chatopera.cc.app.model.Tenant;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/apps/tenant")
|
||||
public class TenantController extends Handler{
|
||||
|
||||
@Autowired
|
||||
private TenantRepository tenantRes;
|
||||
|
||||
@Autowired
|
||||
private OrgiSkillRelRepository orgiSkillRelRes;
|
||||
|
||||
@Autowired
|
||||
private OrganRepository organRes;
|
||||
|
||||
@Autowired
|
||||
private OrganizationRepository organizationRes;
|
||||
|
||||
@Autowired
|
||||
private AgentUserRepository agentUserRepository;
|
||||
|
||||
@Value("${web.upload-path}")
|
||||
private String path;
|
||||
@RequestMapping("/index")
|
||||
@Menu(type = "apps" , subtype = "tenant")
|
||||
public ModelAndView index(ModelMap map , HttpServletRequest request,@Valid String msg,@Valid String currentorgi,@Valid String currentname) throws FileNotFoundException, IOException {
|
||||
if(super.isEnabletneant()) {
|
||||
if("0".equals(super.getUser(request).getUsertype())) {
|
||||
map.addAttribute("tenantList", tenantRes.findByOrgid(super.getOrgid(request)));
|
||||
}else {
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelRes.findBySkillid((super.getUser(request)).getOrgan());
|
||||
List<Tenant> tenantList = null;
|
||||
if(!orgiSkillRelList.isEmpty()) {
|
||||
tenantList = new ArrayList<Tenant>();
|
||||
for(OrgiSkillRel orgiSkillRel:orgiSkillRelList) {
|
||||
Tenant t = tenantRes.findById(orgiSkillRel.getOrgi());
|
||||
if(t!=null) {
|
||||
tenantList.add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
map.addAttribute("tenantList", tenantList);
|
||||
}
|
||||
}else{
|
||||
map.addAttribute("tenantList", tenantRes.findById(super.getOrgi(request)));
|
||||
}
|
||||
map.addAttribute("organization", organizationRes.findById(super.getUser(request).getOrgid()));
|
||||
map.addAttribute("msg",msg);
|
||||
map.addAttribute("currentorgi",currentorgi);
|
||||
if(currentname!=null) {
|
||||
map.addAttribute("currentname",URLDecoder.decode(currentname,"UTF-8"));
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("/apps/tenant/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/add")
|
||||
@Menu(type = "apps" , subtype = "tenant")
|
||||
public ModelAndView add(ModelMap map , HttpServletRequest request) {
|
||||
if(super.isTenantshare()) {
|
||||
map.addAttribute("isShowSkillList",true);
|
||||
List<Organ> organList = organRes.findByOrgiAndOrgid(super.getOrgiByTenantshare(request),super.getOrgid(request));
|
||||
map.addAttribute("skillList",organList);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("/apps/tenant/add"));
|
||||
}
|
||||
|
||||
@RequestMapping("/save")
|
||||
@Menu(type = "apps" , subtype = "tenant")
|
||||
public ModelAndView save(HttpServletRequest request ,@Valid Tenant tenant, @RequestParam(value = "tenantpic", required = false) MultipartFile tenantpic,@Valid String skills) throws NoSuchAlgorithmException, IOException {
|
||||
Tenant tenanttemp = tenantRes.findByOrgidAndTenantname(super.getOrgid(request),tenant.getTenantname());
|
||||
if(tenanttemp!=null) {
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index.html?msg=tenantexist"));
|
||||
}
|
||||
tenantRes.save(tenant) ;
|
||||
if(tenantpic!=null && tenantpic.getOriginalFilename().lastIndexOf(".") > 0){
|
||||
File logoDir = new File(path , "tenantpic");
|
||||
if(!logoDir.exists()){
|
||||
logoDir.mkdirs() ;
|
||||
}
|
||||
String fileName = "tenantpic/"+tenant.getId()+tenantpic.getOriginalFilename().substring(tenantpic.getOriginalFilename().lastIndexOf(".")) ;
|
||||
FileCopyUtils.copy(tenantpic.getBytes(), new File(path , fileName));
|
||||
tenant.setTenantlogo(fileName);
|
||||
}
|
||||
String tenantid = tenant.getId();
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelRes.findByOrgi(tenantid) ;
|
||||
orgiSkillRelRes.delete(orgiSkillRelList);
|
||||
if(!StringUtils.isBlank(skills)){
|
||||
String[] skillsarray = skills.split(",") ;
|
||||
for(String skill : skillsarray){
|
||||
OrgiSkillRel rel = new OrgiSkillRel();
|
||||
rel.setOrgi(tenant.getId());
|
||||
rel.setSkillid(skill);
|
||||
rel.setCreater(super.getUser(request).getId());
|
||||
rel.setCreatetime(new Date());
|
||||
orgiSkillRelRes.save(rel) ;
|
||||
}
|
||||
}
|
||||
if(!StringUtils.isBlank(super.getUser(request).getOrgid())) {
|
||||
tenant.setOrgid(super.getUser(request).getOrgid());
|
||||
}else {
|
||||
tenant.setOrgid(MainContext.SYSTEM_ORGI);
|
||||
}
|
||||
tenantRes.save(tenant) ;
|
||||
OnlineUserUtils.clean(tenantid);
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/edit")
|
||||
@Menu(type = "apps" , subtype = "tenant")
|
||||
public ModelAndView edit(ModelMap map , HttpServletRequest request , @Valid String id) {
|
||||
if(super.isTenantshare()) {
|
||||
map.addAttribute("isShowSkillList",true);
|
||||
List<Organ> organList = organRes.findByOrgiAndOrgid(super.getOrgiByTenantshare(request),super.getOrgid(request));
|
||||
map.addAttribute("skillList",organList);
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelRes.findByOrgi(id) ;
|
||||
map.addAttribute("orgiSkillRelList",orgiSkillRelList);
|
||||
}
|
||||
map.addAttribute("tenant", tenantRes.findById(id)) ;
|
||||
return request(super.createRequestPageTempletResponse("/apps/tenant/edit"));
|
||||
}
|
||||
|
||||
@RequestMapping("/update")
|
||||
@Menu(type = "apps" , subtype = "tenant" , admin = true)
|
||||
public ModelAndView update(HttpServletRequest request ,@Valid Tenant tenant, @RequestParam(value = "tenantpic", required = false) MultipartFile tenantpic,@Valid String skills) throws NoSuchAlgorithmException, IOException {
|
||||
Tenant temp = tenantRes.findById(tenant.getId()) ;
|
||||
Tenant tenanttemp = tenantRes.findByOrgidAndTenantname(super.getOrgid(request),tenant.getTenantname());
|
||||
if(temp!=null&&tenanttemp!=null&&!temp.getId().equals(tenanttemp.getId())) {
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index.html?msg=tenantexist"));
|
||||
}
|
||||
if(tenant!=null) {
|
||||
tenant.setCreatetime(temp.getCreatetime());
|
||||
if(tenantpic!=null && tenantpic.getOriginalFilename().lastIndexOf(".") > 0){
|
||||
File logoDir = new File(path , "tenantpic");
|
||||
if(!logoDir.exists()){
|
||||
logoDir.mkdirs() ;
|
||||
}
|
||||
String fileName = "tenantpic/"+tenant.getId()+tenantpic.getOriginalFilename().substring(tenantpic.getOriginalFilename().lastIndexOf(".")) ;
|
||||
FileCopyUtils.copy(tenantpic.getBytes(), new File(path , fileName));
|
||||
tenant.setTenantlogo(fileName);
|
||||
}else {
|
||||
tenant.setTenantlogo(temp.getTenantlogo());
|
||||
}
|
||||
if(!StringUtils.isBlank(super.getUser(request).getOrgid())) {
|
||||
tenant.setOrgid(super.getUser(request).getOrgid());
|
||||
}else {
|
||||
tenant.setOrgid(MainContext.SYSTEM_ORGI);
|
||||
}
|
||||
tenantRes.save(tenant) ;
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelRes.findByOrgi(tenant.getId()) ;
|
||||
orgiSkillRelRes.delete(orgiSkillRelList);
|
||||
if(!StringUtils.isBlank(skills)){
|
||||
String[] skillsarray = skills.split(",") ;
|
||||
for(String skill : skillsarray){
|
||||
OrgiSkillRel rel = new OrgiSkillRel();
|
||||
rel.setOrgi(tenant.getId());
|
||||
rel.setSkillid(skill);
|
||||
rel.setCreater(super.getUser(request).getId());
|
||||
rel.setCreatetime(new Date());
|
||||
orgiSkillRelRes.save(rel) ;
|
||||
}
|
||||
}
|
||||
OnlineUserUtils.clean(tenant.getId());
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/delete")
|
||||
@Menu(type = "apps" , subtype = "tenant")
|
||||
public ModelAndView delete(HttpServletRequest request ,@Valid Tenant tenant) {
|
||||
Tenant temp = tenantRes.findById(tenant.getId()) ;
|
||||
if(tenant!=null) {
|
||||
tenantRes.delete(temp);
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index"));
|
||||
}
|
||||
|
||||
@RequestMapping("/canswitch")
|
||||
@Menu(type = "apps" , subtype = "tenant")
|
||||
public ModelAndView canswitch(HttpServletRequest request ,@Valid Tenant tenant) throws UnsupportedEncodingException {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("redirect:/"));
|
||||
AgentStatus agentStatus = (AgentStatus) CacheHelper.getAgentStatusCacheBean().getCacheObject((super.getUser(request)).getId(), super.getOrgi(request));
|
||||
if(agentStatus==null && AutomaticServiceDist.getAgentUsers(super.getUser(request).getId(), super.getOrgi(request))==0) {
|
||||
Tenant temp = tenantRes.findById(tenant.getId()) ;
|
||||
if(temp!=null) {
|
||||
super.getUser(request).setOrgi(temp.getId());
|
||||
}
|
||||
return view;
|
||||
}
|
||||
if(agentStatus!=null) {
|
||||
if(tenant.getId().equals(agentStatus.getOrgi())){
|
||||
Tenant temp = tenantRes.findById(tenant.getId()) ;
|
||||
if(temp!=null) {
|
||||
super.getUser(request).setOrgi(temp.getId());
|
||||
}
|
||||
return view;
|
||||
}else {
|
||||
Tenant temp = tenantRes.findById(agentStatus.getOrgi()) ;
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index.html?msg=t0"+"¤torgi="+agentStatus.getOrgi()+"¤tname="+URLEncoder.encode(temp!=null?temp.getTenantname():"","UTF-8")));
|
||||
}
|
||||
}
|
||||
AgentUser agentUser = agentUserRepository.findOneByAgentnoAndStatusAndOrgi(super.getUser(request).getId(), MainContext.AgentUserStatusEnum.INSERVICE.toString(), super.getOrgi(request));
|
||||
if(agentUser!=null) {
|
||||
if(tenant.getId().equals(agentUser.getOrgi())){
|
||||
Tenant temp = tenantRes.findById(tenant.getId()) ;
|
||||
if(temp!=null) {
|
||||
super.getUser(request).setOrgi(temp.getId());
|
||||
}
|
||||
return view;
|
||||
}else {
|
||||
Tenant temp = tenantRes.findById(agentUser.getOrgi()) ;
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index.html?msg=t0"+"¤torgi="+agentUser.getOrgi()+"¤tname="+URLEncoder.encode(temp!=null?temp.getTenantname():"","UTF-8")));
|
||||
}
|
||||
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index.html?msg=t0"));
|
||||
}
|
||||
|
||||
/*@RequestMapping("/switch")
|
||||
@Menu(type = "apps" , subtype = "tenant")
|
||||
public ModelAndView switchTenant(HttpServletRequest request ,@Valid Tenant tenant) {
|
||||
ModelAndView view = request(super.createRequestPageTempletResponse("redirect:/"));
|
||||
AgentStatus agentStatus = (AgentStatus)CacheHelper.getAgentStatusCacheBean().getCacheObject((super.getUser(request)).getId(), super.getOrgi(request));
|
||||
if(agentStatus==null && AutomaticServiceDist.getAgentUsers(super.getUser(request).getId(), super.getOrgi(request))==0) {
|
||||
Tenant temp = tenantRes.findById(tenant.getId()) ;
|
||||
if(temp!=null) {
|
||||
super.getUser(request).setOrgi(temp.getId());
|
||||
}
|
||||
return view;
|
||||
}
|
||||
if(agentStatus!=null && tenant.getId().equals(agentStatus.getOrgi())) {
|
||||
Tenant temp = tenantRes.findById(tenant.getId()) ;
|
||||
if(temp!=null) {
|
||||
super.getUser(request).setOrgi(temp.getId());
|
||||
}
|
||||
return view;
|
||||
}
|
||||
AgentUser agentUser = agentUserRepository.findOneByAgentnoAndStatusAndOrgi(super.getUser(request).getId(), MainContext.AgentUserStatusEnum.INSERVICE.toString(), super.getOrgi(request));
|
||||
if(agentUser!=null&&tenant.getId().equals(agentUser.getOrgi())) {
|
||||
Tenant temp = tenantRes.findById(tenant.getId()) ;
|
||||
if(temp!=null) {
|
||||
super.getUser(request).setOrgi(temp.getId());
|
||||
}
|
||||
return view;
|
||||
}
|
||||
return request(super.createRequestPageTempletResponse("redirect:/apps/tenant/index.html?msg=t0"));
|
||||
}*/
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.apps.test;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.chatopera.cc.app.basic.MainContext;
|
||||
import com.chatopera.cc.app.basic.MainUtils;
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.util.OnlineUserUtils;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
@Controller
|
||||
public class TestController extends Handler {
|
||||
|
||||
|
||||
@RequestMapping({"/test/demo"})
|
||||
@Menu(type="apps", subtype="test" , access=false , admin = true)
|
||||
public ModelAndView content(ModelMap map , HttpServletRequest request){
|
||||
for(int i=0 ; i<500; i++){
|
||||
String user = MainUtils.getUUID();
|
||||
try {
|
||||
OnlineUserUtils.newRequestMessage(user, "ukewo", "user", "system", "localhost" , "win10", "test" , MainContext.ChannelTypeEnum.WEBIM.toString() , null , null , "admin" , "标题" , "https://www.chatopera.com" , "12434" , MainContext.ChatInitiatorType.USER.toString()) ;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return request(super.createAppsTempletResponse("/public/success"));
|
||||
}
|
||||
}
|
@ -1,144 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.handler.resource;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import com.chatopera.cc.util.Menu;
|
||||
import com.chatopera.cc.app.persistence.repository.OrganRepository;
|
||||
import com.chatopera.cc.app.persistence.repository.OrgiSkillRelRepository;
|
||||
import com.chatopera.cc.app.model.OrgiSkillRel;
|
||||
import com.chatopera.cc.app.model.User;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import com.chatopera.cc.app.persistence.repository.UserRepository;
|
||||
import com.chatopera.cc.app.handler.Handler;
|
||||
import com.chatopera.cc.app.model.Organ;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/res")
|
||||
public class UsersResourceController extends Handler {
|
||||
@Autowired
|
||||
private UserRepository userRes ;
|
||||
|
||||
@Autowired
|
||||
private OrgiSkillRelRepository orgiSkillRelService;
|
||||
|
||||
@Autowired
|
||||
private OrganRepository organRes ;
|
||||
|
||||
@RequestMapping("/users")
|
||||
@Menu(type = "res" , subtype = "users")
|
||||
public ModelAndView add(ModelMap map , HttpServletRequest request , @Valid String q , @Valid String id) {
|
||||
if(q==null){
|
||||
q = "" ;
|
||||
}
|
||||
map.addAttribute("usersList",getUsers(request, q)) ;
|
||||
return request(super.createRequestPageTempletResponse("/public/users"));
|
||||
}
|
||||
|
||||
@RequestMapping("/bpm/users")
|
||||
@Menu(type = "res" , subtype = "users")
|
||||
public ModelAndView bpmusers(ModelMap map , HttpServletRequest request , @Valid String q , @Valid String id) {
|
||||
if(q==null){
|
||||
q = "" ;
|
||||
}
|
||||
map.addAttribute("usersList", getUsers(request, q)) ;
|
||||
return request(super.createRequestPageTempletResponse("/public/bpmusers"));
|
||||
}
|
||||
|
||||
@RequestMapping("/bpm/organ")
|
||||
@Menu(type = "res" , subtype = "users")
|
||||
public ModelAndView organ(ModelMap map , HttpServletRequest request , @Valid String q , @Valid String ids) {
|
||||
map.addAttribute("organList", getOrgans(request)) ;
|
||||
map.addAttribute("usersList", getUsers(request)) ;
|
||||
map.addAttribute("ids", ids) ;
|
||||
return request(super.createRequestPageTempletResponse("/public/organ"));
|
||||
}
|
||||
private List<User> getUsers(HttpServletRequest request){
|
||||
List<User> list = null;
|
||||
if(super.isTenantshare()) {
|
||||
List<String> organIdList = new ArrayList<>();
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelService.findByOrgi(super.getOrgi(request)) ;
|
||||
if(!orgiSkillRelList.isEmpty()) {
|
||||
for(OrgiSkillRel rel:orgiSkillRelList) {
|
||||
organIdList.add(rel.getSkillid());
|
||||
}
|
||||
}
|
||||
list = userRes.findByOrganInAndDatastatus(organIdList,false);
|
||||
}else {
|
||||
list = userRes.findByOrgiAndDatastatus(super.getOrgi(request),false) ;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
/**
|
||||
* 获取当前产品下人员信息
|
||||
* @param request
|
||||
* @param q
|
||||
* @return
|
||||
*/
|
||||
private Page<User> getUsers(HttpServletRequest request,String q){
|
||||
if(q==null){
|
||||
q = "" ;
|
||||
}
|
||||
Page<User> list = null;
|
||||
if(super.isTenantshare()) {
|
||||
List<String> organIdList = new ArrayList<>();
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelService.findByOrgi(super.getOrgi(request)) ;
|
||||
if(!orgiSkillRelList.isEmpty()) {
|
||||
for(OrgiSkillRel rel:orgiSkillRelList) {
|
||||
organIdList.add(rel.getSkillid());
|
||||
}
|
||||
}
|
||||
list = userRes.findByOrganInAndDatastatusAndUsernameLike(organIdList,false, "%"+q+"%", new PageRequest(0, 10) );
|
||||
}else {
|
||||
list = userRes.findByDatastatusAndOrgiAndOrgidAndUsernameLike(false,super.getOrgi(request),super.getOrgid(request), "%"+q+"%" , new PageRequest(0, 10)) ;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
/**
|
||||
* 获取当前产品下 技能组 组织信息
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
private List<Organ> getOrgans(HttpServletRequest request){
|
||||
List<Organ> list = null;
|
||||
if(super.isTenantshare()) {
|
||||
List<String> organIdList = new ArrayList<>();
|
||||
List<OrgiSkillRel> orgiSkillRelList = orgiSkillRelService.findByOrgi(super.getOrgi(request)) ;
|
||||
if(!orgiSkillRelList.isEmpty()) {
|
||||
for(OrgiSkillRel rel:orgiSkillRelList) {
|
||||
organIdList.add(rel.getSkillid());
|
||||
}
|
||||
}
|
||||
list = organRes.findByIdInAndSkill(organIdList,true);
|
||||
}else {
|
||||
list = organRes.findByOrgiAndSkillAndOrgid(super.getOrgi(request),true,super.getOrgid(request)) ;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统
|
||||
* Modifications copyright (C) 2018 Chatopera Inc, <https://www.chatopera.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.chatopera.cc.app.im.client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.corundumstudio.socketio.SocketIOClient;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.chatopera.cc.app.basic.MainUtils;
|
||||
|
||||
public class NettyAgentClient implements NettyClient{
|
||||
|
||||
private ArrayListMultimap<String, SocketIOClient> agentClientsMap = ArrayListMultimap.create();
|
||||
|
||||
public List<SocketIOClient> getClients(String key){
|
||||
return agentClientsMap.get(key) ;
|
||||
}
|
||||
|
||||
public void putClient(String key , SocketIOClient client){
|
||||
agentClientsMap.put(key, client) ;
|
||||
}
|
||||
|
||||
public void removeClient(String key , String id){
|
||||
List<SocketIOClient> keyClients = this.getClients(key) ;
|
||||
for(SocketIOClient client : keyClients){
|
||||
if(MainUtils.getContextID(client.getSessionId().toString()).equals(id)){
|
||||
keyClients.remove(client) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if(keyClients.size() == 0){
|
||||
agentClientsMap.removeAll(key) ;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user