mirror of
https://github.com/chatopera/cosin.git
synced 2025-06-16 18:30:03 +08:00
https://gitee.com/cskefu/cskefu/issues/I836RO add webim channel creation as billing resource
Signed-off-by: Hai Liang Wang <hai@chatopera.com>
This commit is contained in:
parent
3cb64fa664
commit
2e4a71c175
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd.
|
||||
* <https://www.chatopera.com>, Licensed under the Chunsong Public
|
||||
* License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html
|
||||
* 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.cskefu.cc.aspect;
|
||||
|
||||
import com.cskefu.cc.basic.MainContext;
|
||||
import com.cskefu.cc.exception.BillingQuotaException;
|
||||
import com.cskefu.cc.exception.BillingResourceException;
|
||||
import com.cskefu.cc.model.Channel;
|
||||
import com.cskefu.cc.model.User;
|
||||
import com.cskefu.cc.proxy.LicenseProxy;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
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 ChannelAspect {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(ChannelAspect.class);
|
||||
|
||||
@Autowired
|
||||
private LicenseProxy licenseProxy;
|
||||
|
||||
@Before("execution(* com.cskefu.cc.persistence.repository.ChannelRepository.save(..))")
|
||||
public void beforeSave(final JoinPoint joinPoint) throws BillingResourceException, BillingQuotaException {
|
||||
final Channel channel = (Channel) joinPoint.getArgs()[0];
|
||||
logger.info("[beforeSave] before channel id {}, type {}", channel.getId(), channel.getType());
|
||||
if (StringUtils.isBlank(channel.getId())) {
|
||||
// create new Channel
|
||||
if (StringUtils.equals(channel.getType(), MainContext.ChannelType.WEBIM.toString())) {
|
||||
// create new WEBIM channel
|
||||
licenseProxy.writeDownResourceUsageInStore(MainContext.BillingResource.CHANNELWEBIM, 1);
|
||||
}
|
||||
} else {
|
||||
// update existed Channel
|
||||
}
|
||||
}
|
||||
}
|
@ -1,15 +1,15 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd.
|
||||
* <https://www.chatopera.com>, Licensed under the Chunsong Public
|
||||
* Copyright (C) 2023 Beijing Huaxia Chunsong Technology Co., Ltd.
|
||||
* <https://www.chatopera.com>, Licensed under the Chunsong Public
|
||||
* License, Version 1.0 (the "License"), https://docs.cskefu.com/licenses/v1.html
|
||||
* 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 (C) 2018- Jun. 2023 Chatopera Inc, <https://www.chatopera.com>, Licensed under the Apache License, Version 2.0,
|
||||
* Copyright (C) 2018- Jun. 2023 Chatopera Inc, <https://www.chatopera.com>, Licensed under the Apache License, Version 2.0,
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统, Licensed under the Apache License, Version 2.0,
|
||||
* Copyright (C) 2017 优客服-多渠道客服系统, Licensed under the Apache License, Version 2.0,
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
package com.cskefu.cc.controller.admin.channel;
|
||||
@ -18,6 +18,7 @@ import com.cskefu.cc.basic.MainContext;
|
||||
import com.cskefu.cc.basic.MainUtils;
|
||||
import com.cskefu.cc.cache.Cache;
|
||||
import com.cskefu.cc.controller.Handler;
|
||||
import com.cskefu.cc.exception.BillingQuotaException;
|
||||
import com.cskefu.cc.model.*;
|
||||
import com.cskefu.cc.persistence.repository.ConsultInviteRepository;
|
||||
import com.cskefu.cc.persistence.repository.OrganRepository;
|
||||
@ -27,6 +28,8 @@ import com.cskefu.cc.proxy.OrganProxy;
|
||||
import com.cskefu.cc.util.Base62;
|
||||
import com.cskefu.cc.util.Menu;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -37,6 +40,8 @@ import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@ -48,6 +53,7 @@ import java.util.Map;
|
||||
@Controller
|
||||
@RequestMapping("/admin/im")
|
||||
public class ChannelController extends Handler {
|
||||
private final static Logger logger = LoggerFactory.getLogger(ChannelController.class);
|
||||
|
||||
@Autowired
|
||||
private ChannelRepository snsAccountRes;
|
||||
@ -93,40 +99,59 @@ public class ChannelController extends Handler {
|
||||
return request(super.createView("/admin/channel/im/add"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新的网站渠道
|
||||
*
|
||||
* @param request
|
||||
* @param channel
|
||||
* @return
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
@RequestMapping("/save")
|
||||
@Menu(type = "admin", subtype = "weixin")
|
||||
@Menu(type = "admin", subtype = "im")
|
||||
public ModelAndView save(HttpServletRequest request,
|
||||
@Valid Channel channel) throws NoSuchAlgorithmException {
|
||||
Organ currentOrgan = super.getOrgan(request);
|
||||
String status = "new_webim_fail";
|
||||
if (StringUtils.isNotBlank(channel.getBaseURL())) {
|
||||
channel.setSnsid(Base62.encode(channel.getBaseURL()).toLowerCase());
|
||||
int count = snsAccountRes.countBySnsid(channel.getSnsid());
|
||||
if (count == 0) {
|
||||
status = "new_webim_success";
|
||||
channel.setType(MainContext.ChannelType.WEBIM.toString());
|
||||
channel.setCreatetime(new Date());
|
||||
User curr = super.getUser(request);
|
||||
channel.setCreater(curr.getId());
|
||||
channel.setOrgan(currentOrgan.getId());
|
||||
try {
|
||||
channel.setSnsid(Base62.encode(channel.getBaseURL()).toLowerCase());
|
||||
int count = snsAccountRes.countBySnsid(channel.getSnsid());
|
||||
if (count == 0) {
|
||||
status = "new_webim_success";
|
||||
channel.setType(MainContext.ChannelType.WEBIM.toString());
|
||||
channel.setCreatetime(new Date());
|
||||
User curr = super.getUser(request);
|
||||
channel.setCreater(curr.getId());
|
||||
channel.setOrgan(currentOrgan.getId());
|
||||
|
||||
snsAccountRes.save(channel);
|
||||
snsAccountRes.save(channel);
|
||||
|
||||
/**
|
||||
* 同时创建CousultInvite 记录
|
||||
*/
|
||||
CousultInvite coultInvite = invite.findBySnsaccountid(channel.getSnsid());
|
||||
if (coultInvite == null) {
|
||||
coultInvite = new CousultInvite();
|
||||
coultInvite.setSnsaccountid(channel.getSnsid());
|
||||
coultInvite.setCreate_time(new Date());
|
||||
coultInvite.setName(channel.getName());
|
||||
coultInvite.setOwner(channel.getCreater());
|
||||
coultInvite.setSkill(false); // 不启动技能组
|
||||
coultInvite.setConsult_skill_fixed(false); // 不绑定唯一技能组
|
||||
coultInvite.setAi(false);
|
||||
coultInvite.setAifirst(false);
|
||||
invite.save(coultInvite);
|
||||
/**
|
||||
* 同时创建CousultInvite 记录
|
||||
*/
|
||||
CousultInvite coultInvite = invite.findBySnsaccountid(channel.getSnsid());
|
||||
if (coultInvite == null) {
|
||||
coultInvite = new CousultInvite();
|
||||
coultInvite.setSnsaccountid(channel.getSnsid());
|
||||
coultInvite.setCreate_time(new Date());
|
||||
coultInvite.setName(channel.getName());
|
||||
coultInvite.setOwner(channel.getCreater());
|
||||
coultInvite.setSkill(false); // 不启动技能组
|
||||
coultInvite.setConsult_skill_fixed(false); // 不绑定唯一技能组
|
||||
coultInvite.setAi(false);
|
||||
coultInvite.setAifirst(false);
|
||||
invite.save(coultInvite);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (e instanceof UndeclaredThrowableException) {
|
||||
logger.error("[save] BillingQuotaException", e);
|
||||
if (StringUtils.startsWith(e.getCause().getMessage(), BillingQuotaException.SUFFIX)) {
|
||||
status = e.getCause().getMessage();
|
||||
}
|
||||
} else {
|
||||
logger.error("[save] err", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,80 +11,136 @@
|
||||
* Licensed under the Apache License, Version 2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
function processUserAddOrUpdateResult(responsecode, cb){
|
||||
/**
|
||||
* 处理系统用户的创建的返回值
|
||||
* @param responsecode
|
||||
* @param cb
|
||||
*/
|
||||
function processUserAddOrUpdateResult(responsecode, cb) {
|
||||
switch (responsecode) {
|
||||
case 'username_exist':
|
||||
layer.msg('用户名存在,请重新填写',{icon: 2, time: 3000});
|
||||
layer.msg('用户名存在,请重新填写', {icon: 2, time: 3000});
|
||||
// 清空用户名
|
||||
$('input[name="username"]').val("");
|
||||
break;
|
||||
case 'email_exist':
|
||||
layer.msg('邮件存在,请重新填写',{icon: 2, time: 3000});
|
||||
layer.msg('邮件存在,请重新填写', {icon: 2, time: 3000});
|
||||
// 清空邮件
|
||||
$('input[name="email"]').val("");
|
||||
break;
|
||||
case 'mobile_exist':
|
||||
layer.msg('手机存在,请重新填写',{icon: 2, time: 3000});
|
||||
layer.msg('手机存在,请重新填写', {icon: 2, time: 3000});
|
||||
// 清空手机号
|
||||
$('input[name="mobile"]').val("");
|
||||
break;
|
||||
case 'sip_account_exist':
|
||||
layer.msg('SIP地址已经存在,请重新填写',{icon: 2, time: 3000});
|
||||
layer.msg('SIP地址已经存在,请重新填写', {icon: 2, time: 3000});
|
||||
// 清空SIP
|
||||
$('input[name="sipaccount"]').val("");
|
||||
break;
|
||||
case 'extension_binded':
|
||||
layer.msg('分机号已经被其他用户绑定',{icon: 2, time: 3000});
|
||||
layer.msg('分机号已经被其他用户绑定', {icon: 2, time: 3000});
|
||||
$('input[name="extensionid"]').val("");
|
||||
break;
|
||||
case 'extension_not_exist':
|
||||
layer.msg('绑定分机不存在',{icon: 2, time: 3000});
|
||||
layer.msg('绑定分机不存在', {icon: 2, time: 3000});
|
||||
$('input[name="extensionid"]').val("");
|
||||
break;
|
||||
case 'pbxhost_not_exist':
|
||||
layer.msg('指定的呼叫中心语音平台不存在',{icon: 2, time: 3000});
|
||||
layer.msg('指定的呼叫中心语音平台不存在', {icon: 2, time: 3000});
|
||||
$('input[name="pbxhostid"]').val("");
|
||||
break;
|
||||
case 't1':
|
||||
layer.msg('当前用户坐席就绪或对话未结束,不能切换为非坐席',{icon: 2, time: 3000});
|
||||
layer.msg('当前用户坐席就绪或对话未结束,不能切换为非坐席', {icon: 2, time: 3000});
|
||||
break;
|
||||
case 'new_user_success':
|
||||
layer.msg('新用户创建成功',{icon: 1, time: 1000});
|
||||
layer.msg('新用户创建成功', {icon: 1, time: 1000});
|
||||
cb();
|
||||
break;
|
||||
case 'edit_user_success':
|
||||
layer.msg('用户编辑成功',{icon: 1, time: 1000});
|
||||
layer.msg('用户编辑成功', {icon: 1, time: 1000});
|
||||
cb();
|
||||
break;
|
||||
default:
|
||||
handleGeneralCodeInQueryPathOrApiResp(responsecode, cb);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理在 RedirectURL, API 中返回的 code 信息: status, msg, etc.
|
||||
* code 为约定的返回值,通过下面的函数进行展示
|
||||
* @param code
|
||||
* @param cb
|
||||
*/
|
||||
function handleGeneralCodeInQueryPathOrApiResp(code, cb) {
|
||||
switch (code) {
|
||||
case 'billingquotaexception.no_license_found':
|
||||
layer.msg('【使用授权证书】证书不存在,联系系统超级管理员导入。',{icon: 2, time: 5000});
|
||||
layer.msg('【使用授权证书】证书不存在,联系系统超级管理员导入。', {icon: 2, time: 5000});
|
||||
if (cb && (typeof (x) === 'function')) {
|
||||
cb()
|
||||
}
|
||||
break;
|
||||
case 'billingquotaexception.response_unexpected':
|
||||
layer.msg('【使用授权证书】证书商店返回异常,稍后再试。',{icon: 2, time: 5000});
|
||||
layer.msg('【使用授权证书】证书商店返回异常,稍后再试。', {icon: 2, time: 5000});
|
||||
if (cb && (typeof (x) === 'function')) {
|
||||
cb()
|
||||
}
|
||||
break;
|
||||
case 'billingquotaexception.invalid_request_body':
|
||||
layer.msg('【使用授权证书】请求证书商店参数不合法,请获取最新软件代码。',{icon: 2, time: 5000});
|
||||
layer.msg('【使用授权证书】请求证书商店参数不合法,请获取最新软件代码。', {icon: 2, time: 5000});
|
||||
if (cb && (typeof (x) === 'function')) {
|
||||
cb()
|
||||
}
|
||||
break;
|
||||
case 'billingquotaexception.license_invalid':
|
||||
layer.msg('【使用授权证书】证书商店中不存在该证书,请联系系统超级管理员导入。',{icon: 2, time: 5000});
|
||||
layer.msg('【使用授权证书】证书商店中不存在该证书,请联系系统超级管理员导入。', {icon: 2, time: 5000});
|
||||
if (cb && (typeof (x) === 'function')) {
|
||||
cb()
|
||||
}
|
||||
break;
|
||||
case 'billingquotaexception.product_invalid':
|
||||
layer.msg('【使用授权证书】产品或产品款式不存在,请联系系统超级管理员导入新证书。',{icon: 2, time: 5000});
|
||||
layer.msg('【使用授权证书】产品或产品款式不存在,请联系系统超级管理员导入新证书。', {icon: 2, time: 5000});
|
||||
if (cb && (typeof (x) === 'function')) {
|
||||
cb()
|
||||
}
|
||||
break;
|
||||
case 'billingquotaexception.license_expired_or_exhausted':
|
||||
layer.msg('【使用授权证书】证书过期或耗尽,请升级证书或绑定新证书。',{icon: 2, time: 5000});
|
||||
layer.msg('【使用授权证书】证书过期或耗尽,请升级证书或绑定新证书。', {icon: 2, time: 5000});
|
||||
if (cb && (typeof (x) === 'function')) {
|
||||
cb()
|
||||
}
|
||||
break;
|
||||
case 'billingquotaexception.license_disabled_serverinst':
|
||||
layer.msg('【使用授权证书】证书商店禁用了本服务实例。',{icon: 2, time: 5000});
|
||||
layer.msg('【使用授权证书】证书商店禁用了本服务实例。', {icon: 2, time: 5000});
|
||||
if (cb && (typeof (x) === 'function')) {
|
||||
cb()
|
||||
}
|
||||
break;
|
||||
case 'billingquotaexception.license_unsupport_refund':
|
||||
layer.msg('【使用授权证书】目前使用的证书不支持回退配额。',{icon: 2, time: 5000});
|
||||
layer.msg('【使用授权证书】目前使用的证书不支持回退配额。', {icon: 2, time: 5000});
|
||||
if (cb && (typeof (x) === 'function')) {
|
||||
cb()
|
||||
}
|
||||
break;
|
||||
case 'billingquotaexception.license_quota_inadequate':
|
||||
layer.msg('【使用授权证书】本次操作需要使用的配额资源超过证书中剩余配额,请联系系统超级管理员升级证书。',{icon: 2, time: 5000});
|
||||
layer.msg('【使用授权证书】本次操作需要使用的配额资源超过证书中剩余配额,请联系系统超级管理员升级证书。', {
|
||||
icon: 2,
|
||||
time: 5000
|
||||
});
|
||||
if (cb && (typeof (x) === 'function')) {
|
||||
cb()
|
||||
}
|
||||
break;
|
||||
case 'billingquotaexception.internal_error':
|
||||
layer.msg('【使用授权证书】系统错误,稍后再试。',{icon: 2, time: 5000});
|
||||
layer.msg('【使用授权证书】系统错误,稍后再试。', {icon: 2, time: 5000});
|
||||
if (cb && (typeof (x) === 'function')) {
|
||||
cb()
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.log("[handleGeneralCodeInQueryPathOrApiResp] none code matched", code);
|
||||
if (cb && (typeof (x) === 'function')) {
|
||||
cb("no_code_matched");
|
||||
}
|
||||
}
|
||||
}
|
@ -63,13 +63,13 @@ block content
|
||||
|
||||
layui.use('layer', function () {
|
||||
var layer = layui.layer;
|
||||
console.log(window.location.href)
|
||||
var status = '#{status}';
|
||||
if (status == 'new_webim_success')
|
||||
layer.msg('网站添加成功', {icon: 1, time: 1000})
|
||||
else if (status == 'new_webim_fail')
|
||||
layer.msg('网站添加失败', {icon: 2, time: 3000})
|
||||
|
||||
else
|
||||
handleGeneralCodeInQueryPathOrApiResp(status);
|
||||
});
|
||||
layui.use(['laypage', 'layer'], function () {
|
||||
var laypage = layui.laypage
|
||||
|
@ -33,6 +33,7 @@ html(xmlns='http://www.w3.org/1999/xhtml', xmlns:th='http://www.thymeleaf.org',
|
||||
script(src='/js/echarts.common.min.js')
|
||||
script(language='javascript', src='/js/theme/wonderland.js')
|
||||
script(src='/layui.js')
|
||||
script(src="/js/CSKeFu_Admin.v1.js")
|
||||
script(src='/js/cskefu.js')
|
||||
if userExpTelemetry == 'on'
|
||||
script(src='https://www.googletagmanager.com/gtag/js?id=G-SBBX10RKTC' async)
|
||||
|
@ -38,8 +38,6 @@ html(xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xm
|
||||
script(src="/js/moment-timezone.js")
|
||||
script(src="/js/moment-timezone-with-data.js")
|
||||
script(src="/layui.js")
|
||||
//- #894 和原生Map行为不一致
|
||||
//- <script src="/js/utils.js"></script>
|
||||
script(src="/js/cskefu.js")
|
||||
script(src="/im/js/socket.io.js")
|
||||
script(src="/js/CSKeFu_IM.v1.js")
|
||||
|
Loading…
x
Reference in New Issue
Block a user