Files
BlackFruit-UI/plugins/addon/example/logic/IdcsmartTicketLogic.php
yiqiu cbd6250967
All checks were successful
continuous-integration/drone/push Build is passing
修改插件
2025-11-21 00:01:45 +08:00

399 lines
16 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace addon\idcsmart_ticket\logic;
use addon\idcsmart_ticket\model\IdcsmartTicketInternalModel;
use addon\idcsmart_ticket\model\IdcsmartTicketModel;
use addon\idcsmart_ticket\IdcsmartTicket;
use addon\idcsmart_ticket\model\IdcsmartTicketReplyModel;
use addon\idcsmart_ticket\model\IdcsmartTicketStatusModel;
use addon\idcsmart_ticket\model\IdcsmartTicketTypeModel;
use addon\idcsmart_ticket\model\IdcsmartTicketUpstreamModel;
use app\admin\model\PluginModel;
class IdcsmartTicketLogic
{
# 默认配置
public static function getDefaultConfig($name = '')
{
$fileConfig = include dirname(__DIR__) . '/config/config.php';
$dbConfig = (new IdcsmartTicket())->getConfig();
$config = array_merge($fileConfig?:[],$dbConfig?:[]);
return isset($config[$name])?$config[$name]:$config;
}
# 工单号生成
public function ticketNum($prefix='YHGD')
{
$IdcsmartTicketModel = new IdcsmartTicketModel();
$ticketNum = rand_str(7,'NUMBER');
for ($i=0;$i<10;$i++){ # 至多10次比较
$exist = $IdcsmartTicketModel->where('ticket_num',$ticketNum)->find();
if (empty($exist)){
break;
}
$ticketNum = rand_str(7,'NUMBER');
}
return [$ticketNum,$ticketNum];
}
public function setConfig($param)
{
$PluginModel = new PluginModel();
$plugin = $PluginModel->where('name','IdcsmartTicket')->find();
$config = json_decode($plugin['config'],true);
$config['refresh_time'] = $param['refresh_time']??($config['refresh_time']??3);
$config['ticket_notice_open'] = $param['ticket_notice_open']??($config['ticket_notice_open']??1);
if (isset($param['ticket_notice_description']) && !empty($param['ticket_notice_description'])){
$config['ticket_notice_description'] = htmlspecialchars($param['ticket_notice_description']);
}else{
$config['ticket_notice_description'] = $config['ticket_notice_description']??"";
}
if (isset($param['ticket_type_id']) && !empty($param['ticket_type_id'])){
$IdcsmartTicketTypeModel = new IdcsmartTicketTypeModel();
$ticketType = $IdcsmartTicketTypeModel->where('id',$param['ticket_type_id'])->find();
if (empty($ticketType)){
return ['status'=>400,'msg'=>lang_plugins('ticket_type_is_not_exist')];
}
$config['ticket_type_id'] = $param['ticket_type_id'];
}
$config['downstream_delivery'] = intval($param['downstream_delivery']??0);
$config['ticket_close_switch'] = $param['ticket_close_switch']??($config['ticket_close_switch']??0);
$config['ticket_close_hour'] = $param['ticket_close_hour']??($config['ticket_close_hour']??0);
$plugin->save([
'config' => json_encode($config)
]);
return [
'status' => 200,
'msg' => lang_plugins('success_message')
];
}
/**
* 时间 2022-5-25
* @title curl下载解压包到指定路径
* @desc curl下载解压包到指定路径
* @author theworld
* @version v1
* @param string url - 下载链接地址
* @param string file_name - 目标路径
* @return mixed
*/
public static function curl_download($url, $file_name)
{
$ch = curl_init($url);
//设置抓取的url
$dir = $file_name;
$fp = fopen($dir, "wb");
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$res=curl_exec($ch);
curl_close($ch);
fclose($fp);
return $res;
}
public static function idcsmartApiCurlUploadFile($api_id,$file_path,$file_name)
{
$login = idcsmart_api_login($api_id);
if ($login['status']!=200){
return $login;
}
if($login['data']['supplier']['type']!='default'){
return ['status'=>400,'msg'=>lang_plugins('ticket_supplier_not_support_delivery')];
}
// 下载对象存储的文件
$fileUrl = getOssUrl([
'file_path' => $file_path,
'file_name' => $file_name
])['url'];
if (strpos($file_name,'^')!==false){
$file_name = explode('^',$file_name)[1];
}
$file = UPLOAD_DEFAULT.$file_name;
self::curl_download($fileUrl, $file);
if (!file_exists($file)){
return ['status'=>400,'msg'=>lang_plugins('source_file_not_exist')];
}
$url = $login['data']['url'] . '/console/v1/upload';
$header = [
'Authorization: Bearer '.$login['data']['jwt']
];
$file = realpath($file);
$data = ['file' => new \CURLFile($file)];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
$ssl = substr($url, 0, 8) == 'https://' ? true : false;
//if ($ssl) {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
//}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
if(!empty($header)){
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
}
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($file==UPLOAD_DEFAULT.$file_name){
unlink($file);
}
if ($http_code!=200){
return ['status'=>400, 'msg'=>lang_plugins('ticket_network_desertion')];
}
$response = json_decode($response,true);
return $response;
}
/**
* 时间 2024-06-18
* @title 判断后台当前工单是否可操作
* @desc 判断后台当前工单是否可操作,涉及:
* @author wyh
* @version v1
* @param int ticketId - 工单ID required
* @return boolean
*/
public static function checkUpstreamTicket($ticketId)
{
// 考虑到目前逻辑是一个工单最多对应一个产品,所以这里直接拉取
$IdcsmartTicketUpstreamModel = new IdcsmartTicketUpstreamModel();
$ticketUpstream = $IdcsmartTicketUpstreamModel->where('ticket_id',$ticketId)->find();
// 1、没有对应的上游工单可操作
if (empty($ticketUpstream)){
return true;
}
// 2、对于多级传递来说中间层不可操作(有上游,也有下游)
$IdcsmartTicketModel = new IdcsmartTicketModel();
$ticket = $IdcsmartTicketModel->find($ticketId);
if ($ticket['downstream_ticket_id']>0){
// 若本地已关闭传递,且下游已开启传递或者已关闭;则可操作
if ($ticketUpstream['delivery_status']==0/* && $ticket['downstream_delivery_status']==1*/){
return true;
}
return false;
}
// 3、已关闭传递可操作
if ($ticketUpstream['delivery_status']==0){
return true;
}
return false;
}
/**
* 时间 2024-06-18
* @title 判断前台当前工单是否可操作
* @desc 判断前台当前工单是否可操作,涉及:
* @author wyh
* @version v1
* @param int ticketId - 工单ID required
* @return boolean
*/
public static function checkDownstreamTicket($ticketId)
{
$IdcsmartTicketModel = new IdcsmartTicketModel();
$ticket = $IdcsmartTicketModel->find($ticketId);
if ($ticket['is_downstream']==1 && $ticket['downstream_delivery_status']==1){
return false;
}
return true;
}
// 后台判断是否可以向下游推送
public static function checkPushTicketToDownstream(IdcsmartTicketModel $ticket)
{
if ($ticket['is_downstream'] && $ticket['downstream_delivery_status']==1){
return true;
}
return false;
}
// 下游验证签名
public static function validateSign($params){
$sign = $params['signature'];
// 用这几个参数生成签名
$data = [
'id'=>(int)$params['id'], // 数据类型必须和生成签名时的类型一致
'token'=>$params['token'],
'rand_str'=>$params['rand_str'],
];
ksort($data, SORT_STRING);
$str = json_encode($data);
$signature = md5($str);
return strtoupper($signature) === $sign;
}
// 推送通用curl请求
public static function commonCurl($url, $data = [], $timeout = 30, $request = 'POST', $header = [])
{
$result = curl($url,$data,$timeout,$request,$header);
if($result['http_code'] != 200){
return ['status'=>400, 'msg'=>lang('network_desertion'), 'content'=>$result['content']];
}
$result = json_decode($result['content'], true);
if ($result['status']==401){
$result['status']=400;
$result['msg'] = lang('network_desertion');
}
return $result;
}
// 推送工单状态至下游
public static function pushTicketStatus(IdcsmartTicketModel $ticket,IdcsmartTicketStatusModel $ticketStatus,$param)
{
if (self::checkPushTicketToDownstream($ticket)){
// 非默认状态
if (!in_array($param['status'],[1,2,3,4,5])){
// 完结状态推送至下游,下游为已回复
if ($ticketStatus['status']==1){
$param['status'] = 3;
}else{
// 未完结状态推送至下游,下游为处理中
$param['status'] = 5;
}
}
$data = [
'status' => $param['status']
];
$sign = create_sign(['id'=>$ticket['downstream_ticket_id']],$ticket['downstream_token']);
$data = array_merge($data,$sign);
$res = IdcsmartTicketLogic::commonCurl(rtrim($ticket['downstream_url'],'/')."/console/v1/api/ticket/{$ticket['downstream_ticket_id']}/status", $data, 30, 'PUT');
if ($res['status']==200){
active_log(lang_plugins('ticket_log_admin_update_downstream_ticket_status_success',
['{admin}'=>'admin#'.request()->admin_id.'#' .request()->admin_name.'#','{ticket}'=>'ticket#'.$ticket['ticket_num'],'{status}'=>$ticketStatus['name'],'{url}'=>$ticket['downstream_url']]),
'addon_idcsmart_ticket', $ticket['id']);
}else{
active_log(lang_plugins('ticket_log_admin_update_downstream_ticket_status_fail',
['{admin}'=>'admin#'.request()->admin_id.'#' .request()->admin_name.'#','{ticket}'=>'ticket#'.$ticket['ticket_num'],'{status}'=>$ticketStatus['name'],'{url}'=>$ticket['downstream_url'],'{reason}'=>$res['msg']]),
'addon_idcsmart_ticket', $ticket['id']);
}
}
return true;
}
// 推送工单回复内容更改至下游
public static function pushTicketReply(IdcsmartTicketModel $ticket,IdcsmartTicketReplyModel $ticketReply,$param)
{
if (self::checkPushTicketToDownstream($ticket)){
$data = [
'ticket_reply_id' => $ticketReply['downstream_ticket_reply_id'],
'content' => $param['content']??""
];
$sign = create_sign(['id'=>$ticket['downstream_ticket_id']],$ticket['downstream_token']);
$data = array_merge($data,$sign);
$res = IdcsmartTicketLogic::commonCurl(rtrim($ticket['downstream_url'],'/')."/console/v1/api/ticket/{$ticket['downstream_ticket_id']}/reply", $data, 30, 'PUT');
if ($res['status']==200){
active_log(lang_plugins('ticket_log_admin_update_downstream_ticket_reply_success',
['{admin}'=>'admin#'.request()->admin_id.'#' .request()->admin_name.'#','{ticket}'=>'ticket#'.$ticket['ticket_num'],'{ticket_reply_id}'=>$ticketReply['id'],'{url}'=>$ticket['downstream_url']]),
'addon_idcsmart_ticket', $ticket['id']);
}else{
active_log(lang_plugins('ticket_log_admin_update_downstream_ticket_reply_fail',
['{admin}'=>'admin#'.request()->admin_id.'#' .request()->admin_name.'#','{ticket}'=>'ticket#'.$ticket['ticket_num'],'{ticket_reply_id}'=>$ticketReply['id'],'{url}'=>$ticket['downstream_url'],'{reason}'=>$res['msg']]),
'addon_idcsmart_ticket', $ticket['id']);
}
}
return true;
}
// 推送工单回复删除至下游
public static function pushTicketReplyDelete(IdcsmartTicketModel $ticket,IdcsmartTicketReplyModel $ticketReply,$param)
{
if (self::checkPushTicketToDownstream($ticket)){
$data = [
'ticket_reply_id' => $ticketReply['downstream_ticket_reply_id'],
];
$sign = create_sign(['id'=>$ticket['downstream_ticket_id']],$ticket['downstream_token']);
$data = array_merge($data,$sign);
$res = IdcsmartTicketLogic::commonCurl(rtrim($ticket['downstream_url'],'/')."/console/v1/api/ticket/{$ticket['downstream_ticket_id']}/reply", $data, 30, 'DELETE');
if ($res['status']==200){
active_log(lang_plugins('ticket_log_admin_update_downstream_ticket_reply_delete_success',
['{admin}'=>'admin#'.request()->admin_id.'#' .request()->admin_name.'#','{ticket}'=>'ticket#'.$ticket['ticket_num'],'{ticket_reply_id}'=>$ticketReply['id'],'{url}'=>$ticket['downstream_url']]),
'addon_idcsmart_ticket', $ticket['id']);
}else{
active_log(lang_plugins('ticket_log_admin_update_downstream_ticket_reply_delete_fail',
['{admin}'=>'admin#'.request()->admin_id.'#' .request()->admin_name.'#','{ticket}'=>'ticket#'.$ticket['ticket_num'],'{ticket_reply_id}'=>$ticketReply['id'],'{url}'=>$ticket['downstream_url'],'{reason}'=>$res['msg']]),
'addon_idcsmart_ticket', $ticket['id']);
}
}
return true;
}
// 推送工单回复至下游
public static function pushTicketReplyCreate(IdcsmartTicketModel $ticket,IdcsmartTicketReplyModel $ticketReply,$param)
{
if (self::checkPushTicketToDownstream($ticket)){
$data = [
'content' => htmlspecialchars_decode($ticketReply['content']),
'upstream_ticket_reply_id' => $ticketReply['id'],
'attachment' => [],
];
$sign = create_sign(['id'=>$ticket['downstream_ticket_id']],$ticket['downstream_token']);
$data = array_merge($data,$sign);
$res = IdcsmartTicketLogic::commonCurl(rtrim($ticket['downstream_url'],'/')."/console/v1/api/ticket/{$ticket['downstream_ticket_id']}/reply", $data, 30, 'POST');
if ($res['status']==200){
$ticketReply->save([
'is_downstream' => 1,
'downstream_ticket_reply_id' => $res['data']['ticket_reply_id'],
'update_time' => time()
]);
active_log(lang_plugins('ticket_log_admin_update_downstream_ticket_reply_create_success',
['{admin}'=>'admin#'.request()->admin_id.'#' .request()->admin_name.'#','{ticket}'=>'ticket#'.$ticket['ticket_num'],'{ticket_reply_id}'=>$ticketReply['id'],'{url}'=>$ticket['downstream_url']]),
'addon_idcsmart_ticket', $ticket['id']);
}else{
active_log(lang_plugins('ticket_log_admin_update_downstream_ticket_reply_create_fail',
['{admin}'=>'admin#'.request()->admin_id.'#' .request()->admin_name.'#','{ticket}'=>'ticket#'.$ticket['ticket_num'],'{ticket_reply_id}'=>$ticketReply['id'],'{url}'=>$ticket['downstream_url'],'{reason}'=>$res['msg']]),
'addon_idcsmart_ticket', $ticket['id']);
}
}
return true;
}
}