This commit is contained in:
lilong@dgg.net
2021-03-11 11:17:01 +08:00
parent b22d3622ea
commit aea70bf25a
622 changed files with 0 additions and 52005 deletions

View File

@@ -1,15 +0,0 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2

View File

@@ -1,46 +0,0 @@
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:2dcQ94B9y3FBI+rRqaM5V0SVt7YrDXgOvQcUeSSlt2g=
APP_DEBUG=true
APP_URL=http://127.0.0.1
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=wh_com
DB_USERNAME=wh_com
DB_PASSWORD=wh_com
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

5
.gitattributes vendored
View File

@@ -1,5 +0,0 @@
* text=auto
*.css linguist-vendored
*.scss linguist-vendored
*.js linguist-vendored
CHANGELOG.md export-ignore

View File

@@ -1,13 +0,0 @@
php:
preset: laravel
disabled:
- unused_use
finder:
not-name:
- index.php
- server.php
js:
finder:
not-name:
- webpack.mix.js
css: true

View File

@@ -1,3 +0,0 @@
## 此版本是单商户

View File

@@ -1,127 +0,0 @@
<?php
namespace App\Console\Commands;
use App\Models\Agent;
use App\Models\Call;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
class callcenterListen extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'callcenter:listen';
/**
* The console command description.
*
* @var string
*/
protected $description = 'callcenter listen';
protected $fs_dir = '/usr/local/freeswitch';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$fs = new \Freeswitchesl();
$service = config('freeswitch.esl');
if (!$fs->connect($service['host'], $service['port'], $service['password'])){
Log::info("群呼监听ESL未连接");
return 0;
}
$fs->events('json', 'CUSTOM callcenter::info');
while (true){
$received_parameters = $fs->recvEvent();
if (!empty($received_parameters)) {
$action = $fs->getHeader($received_parameters,"CC-Action");
$uuid = $fs->getHeader($received_parameters,"CC-Member-Session-UUID");
switch ($action){
//坐席状态
case 'agent-status-change':
$agent_name = $fs->getHeader($received_parameters,"CC-Agent");
$status = $fs->getHeader($received_parameters,"CC-Agent-Status");
$id = (int)Str::after($agent_name,'agent');
Agent::where('id',$id)->update(['status'=>urldecode($status)]);
break;
//坐席呼叫状态
case 'agent-state-change':
$agent_name = $fs->getHeader($received_parameters,"CC-Agent");
$state = $fs->getHeader($received_parameters,"CC-Agent-State");
$id = (int)Str::after($agent_name,'agent');
Agent::where('id',$id)->update(['state'=>urldecode($state)]);
break;
//呼叫进入队列
case 'member-queue-start':
$datetime = urldecode($fs->getHeader($received_parameters,"variable_cc_queue_joined_epoch"));
Call::where('uuid',$uuid)->update(['datetime_entry_queue'=>date('Y-m-d H:i:s',$datetime),'status'=>3]);
break;
// 坐席应答
case 'bridge-agent-start':
$datetime = $fs->getHeader($received_parameters,"CC-Agent-Answered-Time");
$agent_name = $fs->getHeader($received_parameters,"CC-Agent");
$id = (int)Str::after($agent_name,'agent');
//录音
$filepath = $this->fs_dir . '/recordings/' . date('Y') . '/' . date('m') . '/' . date('d') . '/';
$callcenter_file = $filepath . 'callcenter_' . md5($uuid . time() . uniqid()) . '.wav';
$fs->bgapi("uuid_setvar {$uuid} callcenter_record_file {$callcenter_file}");
$fs->bgapi("uuid_record " . $uuid . " start " . $callcenter_file . " 1800");
Call::where('uuid',$uuid)->update(['datetime_agent_answered'=>date('Y-m-d H:i:s',$datetime),'status'=>4,'agent_id'=>$id]);
break;
//坐席结束
case 'bridge-agent-end':
$datetime = $fs->getHeader($received_parameters,"CC-Bridge-Terminated-Time");
$agent_name = $fs->getHeader($received_parameters,"CC-Agent");
$id = (int)Str::after($agent_name,'agent');
Call::where('uuid',$uuid)->update(['datetime_end'=>date('Y-m-d H:i:s',$datetime),'status'=>4,'agent_id'=>$id]);
break;
//桥接结束,通话结束
case 'member-queue-end':
$cause = $fs->getHeader($received_parameters,"CC-Cause");
$answered_time = $fs->getHeader($received_parameters,"CC-Agent-Answered-Time");
$leaving_time = $fs->getHeader($received_parameters,"CC-Member-Leaving-Time");
$joined_time = $fs->getHeader($received_parameters,"CC-Member-Joined-Time");
//If we get a hangup from the caller before talking to an agent
if ($cause == 'Cancel') {
$billsec = 0;
}else{
if ($leaving_time && $answered_time){
$billsec = $leaving_time - $answered_time > 0 ? $leaving_time - $answered_time : 0;
}else{
$billsec = 0;
}
}
if ($billsec > 0) {
$record_file = $fs->getHeader($received_parameters,"variable_callcenter_record_file");
$data['record_file'] = $record_file ? str_replace('/usr/local/freeswitch',config('app.url'),$record_file) : null;
}
$data['cause'] = $cause;
$data['billsec'] = $billsec;
Call::where('uuid',$uuid)->update($data);
unset($data);
break;
default:
}
}
}
$fs->disconnect();
}
}

View File

@@ -1,195 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use App\Models\Task;
use App\Models\Call;
class callcenterRun extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'callcenter:run';
/**
* The console command description.
*
* @var string
*/
protected $description = 'start swoole server';
public $server;
public $client;
public $machineId = 3;
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->client = new client();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$redis_key = config('freeswitch.redis_key.callcenter_task');
//服务启动或重启时检测是否有已启动的任务
$res = Task::where(['status'=>2])->select(['id'])->get();
if ($res->isNotEmpty()) {
foreach ($res as $key => $task) {
Redis::rPush($redis_key,$task->id);
}
}
//启动服务
while (true) {
$task_id = Redis::lPop($redis_key);
if ($task_id == null) {
sleep(10);
continue;
}
$process = new \Swoole\Process(function () use ($task_id) {
$fs = new \Freeswitchesl();
$service = config('freeswitch.esl');
if ($fs->connect($service['host'], $service['port'], $service['password']) ){
//redis自增ID的key,用于生成uuid
$callKey = config('freeswitch.redis_key.callcenter_call');
while (true){
$task = Task::with(['queue.agents','gateway'])
->where('status',2)
->where('id',$task_id)
->first();
//检测是否有启动的任务
if ($task == null ){
break;
}
//检测执行日期
$now_date = strtotime(date('Y-m-d'));
if ( $now_date < strtotime($task->date_start) || $now_date > strtotime($task->date_end) ) {
//延迟10秒
sleep(10);
continue;
}
//检测执行时间
$now_time = strtotime(date('H:i:s'));
if ( $now_time < strtotime($task->time_start) || $now_time > strtotime($task->time_end) ) {
//延迟10秒
sleep(10);
Log::info("任务ID".$task->id."运行时间不满足");
continue;
}
//检测网关信息
if ($task->gateway==null){
Log::info("任务ID".$task->id." 的网关不存在,任务停止");
$task->update(['status'=>1]);
break;
}
/*$gw_info = $fs->api("sofia status gateway gw".$task->gateway->id);
if (trim($gw_info)=='Invalid Gateway!'){
Log::info("任务ID ".$task->name."的网关 ".$task->gateway->name."的网关配置不存在");
continue;
}
$gw_status = 0;
foreach (explode("\n",$gw_info) as $str){
if (str_contains($str,"REGED")){
$gw_status = 1;
}
}
if ($gw_status==0){
Log::info("任务ID ".$task->name."的网关 ".$task->gateway->name."未注册成功");
continue;
}*/
//检测队列
if ($task->queue==null){
Log::info("任务ID".$task->id." 的队列不存在,任务停止");
$task->update(['status'=>1]);
break;
}
//检测队列是否有坐席
if ($task->queue->agents->isEmpty()){
Log::info("任务ID".$task->id." 的队列无坐席存在,任务停止");
$task->update(['status'=>1]);
break;
}
//并发数调节
$channel = 0;
$members = $fs->api("callcenter_config queue count members queue".$task->queue->id);
$members = (int)$members;
if ($task->max_channel > $members){
$channel = $task->max_channel - $members;
}
//如果通道数还是0则不需要呼叫
if ($channel == 0) {
Log::info("任务ID".$task->name." 的并发不需要呼叫,成员数:".$members);
sleep(10);
continue;
}
//否则进行呼叫
Log::info("任务:".$task->name." 将呼叫 ".$channel." 个号码");
$calls = Call::where('task_id',$task->id)->where('status',1)->orderBy('id','asc')->take($channel)->get();
if ($calls->isEmpty()){
Log::info("任务:".$task->name."已完成");
$task->update(['status'=>3]);
break;
}
foreach ($calls as $call){
$uuid = md5(\Snowflake::nextId($this->machineId).$call->phone.Redis::incr($callKey));
//更新为正在呼叫
$call->update(['status'=>2,'uuid'=>$uuid,'datetime_originate_phone'=>date('Y-m-d H:i:s')]);
Log::info("更新号码: ".$call->phone." 状态为2");
$phone = $task->gateway->prefix ? $task->gateway->prefix.$call->phone : $call->phone;
$varStr = "{origination_uuid=".$uuid."}";
$varStr .= "{ignore_early_media=true}";
$varStr .= "{effective_caller_id_number=".$call->phone."}";
$varStr .= "{effective_caller_id_name=".$call->phone."}";
if ($task->gateway->outbound_caller_id){
$varStr .= "{origination_caller_id_number=".$task->gateway->outbound_caller_id."}";
$varStr .= "{origination_caller_id_name=".$task->gateway->outbound_caller_id."}";
}
$varStr .= "{cc_export_vars=effective_caller_id_number,effective_caller_id_name}";
$dail_string = "originate ".$varStr."sofia/gateway/gw".$task->gateway->id."/".$phone." &callcenter(queue".$task->queue->id.")";
Log::info("呼叫:".$dail_string);
$fs->bgapi($dail_string);
sleep(2);
}
sleep(6);
}
$fs->disconnect();
}
});
$process->start();
}
}
}

View File

@@ -1,93 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Arr;
class eslCustom extends Command
{
/**
* 监听CUSTOM事件
* @var string
*/
protected $signature = 'esl:custom {event*}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'esl listen custom events';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$fs = new \Freeswitchesl();
$service = config('freeswitch.esl');
if (!$fs->connect($service['host'], $service['port'], $service['password'])){
Log::error("asr监听ESL未连接");
return false;
}
//====================== 接收事件参数验证 ====================
$eventarr = [
'sofia::register',
'sofia::unregister',
];
$argument = $this->argument('event');
foreach ($argument as $name){
if (!in_array($name,$eventarr)){
$this->error('custom event '.$name.' not allowed');
return false;
}
}
$event = implode(" ",$argument);
//====================== 接收事件参数验证 ====================
$fs->events('plain', 'CUSTOM '.$event);
while (true) {
$received_parameters = $fs->recvEvent();
if (!empty($received_parameters)) {
$info = $fs->serialize($received_parameters, "json");
$info = json_decode($info,true);
$eventname = Arr::get($info,"Event-Subclass"); //子事件名称
$eventname = urldecode($eventname);
$username = Arr::get($info,"username"); //分机号
switch ($eventname){
//注册
case 'sofia::register':
DB::table('sip')->where('username',$username)->update(['status'=>1]);
break;
//注销
case 'sofia::unregister':
DB::table('sip')->where('username',$username)->update(['status'=>0]);
break;
default:
break;
}
}
}
$fs->disconnect();
}
}

View File

@@ -1,272 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Arr;
class eslListen extends Command
{
/**
* 允许事件:'CHANNEL_ANSWER',
'RECORD_START',
'RECORD_STOP',
'CHANNEL_HANGUP_COMPLETE',
* 多个事件以空格隔开CHANNEL_ANSWER RECORD_START RECORD_STOP CHANNEL_HANGUP_COMPLETE
* 如果指定uuid则表示只监听指定的uuid的事件
* The name and signature of the console command.
* @var string
*/
protected $signature = 'esl:listen {event*} {--aleg_uuid=} {--bleg_uuid=}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'esl listen events';
protected $fs_dir = '/usr/local/freeswitch';
protected $recording_dir = 'recordings';
public $url = null;
public $hash_table = 'esl_listen';
public $cdr_table = 'cdr';
public $asr_table = 'asr';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
if ($this->url == null){
$this->url = config('app.url');
}
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$fs = new \Freeswitchesl();
$service = config('freeswitch.esl');
if (!$fs->connect($service['host'], $service['port'], $service['password'])){
Log::error("asr监听ESL未连接");
return false;
}
//====================== 接收事件参数验证 ====================
$eventarr = [
'CHANNEL_CALLSTATE',
'CHANNEL_ANSWER',
'RECORD_START',
'RECORD_STOP',
'CHANNEL_HANGUP_COMPLETE',
];
$argument = $this->argument('event');
foreach ($argument as $name){
if (!in_array($name,$eventarr)){
$this->error('event '.$name.' not allowed');
return false;
}
}
$event = implode(" ",$argument);
//====================== 接收事件参数验证 ====================
//====================== 是否监听指定的uuid的事件 ===============
$aleg_uuid = $this->option('aleg_uuid');
$bleg_uuid = $this->option('bleg_uuid');
if ($aleg_uuid){
$fs->filteruuid($aleg_uuid);
}
if ($bleg_uuid){
$fs->filteruuid($bleg_uuid);
}
//====================== 是否监听指定的uuid的事件 ===============
$fs->events('plain', $event);
while (true) {
//录音目录
$filepath = $this->fs_dir . '/' .$this->recording_dir. '/' . date('Y') . '/' . date('m') . '/' . date('d') . '/';
$received_parameters = $fs->recvEvent();
if (!empty($received_parameters)) {
$this->setTable();
$info = $fs->serialize($received_parameters, "json");
$info = json_decode($info,true);
$eventname = Arr::get($info,"Event-Name"); //事件名称
$uuid = Arr::get($info,"Unique-ID"); //UUID
$CallerCallerIDNumber = Arr::get($info,"Caller-Caller-ID-Number"); //主叫
$CallerCalleeIDNumber = Arr::get($info,"Caller-Destination-Number"); //被叫
switch ($eventname){
//呼叫状态
case 'CHANNEL_CALLSTATE':
//是分机号才记录
if (preg_match('/\d{4,5}/',$CallerCallerIDNumber)){
$state = Arr::get($info,'Channel-Call-State');
$uniqueid = Arr::get($info,'Caller-Unique-ID');
Redis::setex($CallerCallerIDNumber.'_uuid',1200, $uniqueid);
DB::table('sip')->where('username',$CallerCallerIDNumber)->update(['state'=>$state]);
}
break;
//通道应答
case 'CHANNEL_ANSWER':
Redis::hset($this->hash_table,$uuid,json_encode([
'pid' => $uuid,
'unique_id' => $uuid,
'record_file' => null,
'full_record_file' => null,
'start_time' => date('Y-m-d H:i:s'),
'end_time' => null,
]));
$otherUuid = Arr::get($info,"Other-Leg-Unique-ID");
if ($otherUuid) { //被叫应答后
//开启全程录音
$fullfile = $filepath . 'full_' . md5($otherUuid . $uuid) . '.wav';
$fs->bgapi("uuid_record {$uuid} start {$fullfile} 7200"); //录音
//记录A分段录音数据
$halffile_a = $filepath . 'half_' . md5($otherUuid . time() . uniqid()) . '.wav';
$fs->bgapi("uuid_record " . $otherUuid . " start " . $halffile_a . " 18");
$a_data = Redis::hget($this->hash_table,$otherUuid);
if ($a_data){
$a_data = json_decode(Redis::hget($this->hash_table,$otherUuid),true);
$a_data = array_merge($a_data,[
'record_file' => $halffile_a,
'full_record_file' => str_replace($this->fs_dir,$this->url,$fullfile),
]);
Redis::hset($this->hash_table,$otherUuid,json_encode($a_data));
}
unset($a_data);
unset($halffile_a);
//记录B分段录音数据
$halffile_b = $filepath . 'half_' . md5($uuid . time() . uniqid()) . '.wav';
$fs->bgapi("uuid_record " . $uuid . " start " . $halffile_b . " 18");
$b_data = Redis::hget($this->hash_table,$uuid);
if ($b_data){
$b_data = json_decode(Redis::hget($this->hash_table,$uuid),true);
$b_data = array_merge($b_data,[
'pid' => $otherUuid,
'record_file' => $halffile_b,
'full_record_file' => str_replace($this->fs_dir,$this->url,$fullfile),
]);
Redis::hset($this->hash_table,$uuid,json_encode($b_data));
}
unset($a_data);
unset($halffile_b);
//更新B接听时间
DB::table($this->cdr_table)->where('uuid',$otherUuid)->update([
'bleg_answer_at' => date('Y-m-d H:i:s'),
'record_file' => str_replace($this->fs_dir,$this->url,$fullfile),
'updated_at' => date('Y-m-d H:i:s'),
]);
unset($fullfile);
}else{
//更新A接听时间
DB::table($this->cdr_table)->where('uuid',$uuid)->update([
'aleg_answer_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
}
unset($otherUuid);
break;
//开始说话
case 'RECORD_START':
$data = Redis::hget($this->hash_table,$uuid);
if ($data){
$data = json_decode($data,true);
$data = array_merge($data,[
'start_time' => date('Y-m-d H:i:s'),
]);
Redis::hset($this->hash_table,$uuid,json_encode($data));
}
unset($data);
break;
//结束说话
case 'RECORD_STOP':
$data = Redis::hget($this->hash_table,$uuid);
if ($data){
$data = json_decode($data,true);
$data['is_prologue'] += 1;
if (isset($data['record_file'])&&file_exists($data['record_file'])){
DB::table($this->asr_table)->insert([
'uuid' => $data['pid'],
'leg_uuid' => $data['unique_id'],
'start_at' => $data['start_time'],
'end_at' => date('Y-m-d H:i:s'),
'billsec' => strtotime(date('Y-m-d H:i:s'))-strtotime($data['start_time']),
'record_file' => str_replace($this->fs_dir, $this->url, $data['record_file']),
'created_at' => date('Y-m-d H:i:s'),
]);
}
//结束说话 后接着开启分段录音
$halffile = $filepath . 'half_' . md5($uuid . time() . uniqid()) . '.wav';
$fs->bgapi("uuid_record " . $uuid . " start " . $halffile . " 18");
$data = array_merge($data,[
'record_file' => $halffile,
'start_time' => date('Y-m-d H:i:s'),
'end_time' => null,
]);
Redis::hset($this->hash_table,$uuid,json_encode($data));
unset($halffile);
}
unset($data);
break;
//挂断
case 'CHANNEL_HANGUP_COMPLETE':
$data = Redis::hget($this->hash_table,$uuid);
if ($data){
$data = json_decode($data,true);
Redis::hdel($this->hash_table, $data['pid']);
$cdr = DB::table($this->cdr_table)
>where('uuid',$data['pid'])
->whereNull('aleg_end_at')
->first();
if ($cdr != null){
$hanguptime = Arr::get($info,'variable_end_stamp',null);
$hanguptime = $hanguptime != null ? urldecode($hanguptime) : null;
if ($uuid == $data['pid']){ // A的挂断事件
$callsec = $cdr->bleg_answer_at != null ? strtotime($hanguptime)-strtotime($cdr->bleg_answer_at) : 0;
}else{ // B的挂断事件
$callsec = Arr::get($info,'variable_billsec',0);
}
//更新通话时长
DB::table($this->cdr_table)->where('uuid',$data['pid'])->update([
'aleg_end_at' => $hanguptime,
'billsec' => $callsec,
]);
unset($callsec);
unset($hanguptime);
}
unset($cdr);
}
unset($data);
break;
default:
break;
}
}
}
$fs->disconnect();
}
public function setTable(){
if ($this->cdr_table == null){
$this->cdr_table = 'cdr_'.date('Ym');
}
if ($this->asr_table == null){
$this->asr_table = 'asr_'.date('Ym');
}
}
}

View File

@@ -1,100 +0,0 @@
<?php
namespace App\Console\Commands;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
class submeter extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'auto:submeter';
/**
* The console command description.
*
* @var string
*/
protected $description = '自动按月分表';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
//表名
$tables = ['asr','cdr'];
foreach ($tables as $table){
$new_table = $table.'_'.date('Ym',strtotime('+1 month'));
try{
if (!Schema::hasTable($new_table)) {
DB::update("create table {$new_table} like {$table}");
}
}catch (\Exception $exception){
Log::info('创建分表'.$new_table.'异常:'.$exception->getMessage());
}
}
//需要合建视图的表
$view_tables = [];
foreach ($view_tables as $table){
$this->createView($table);
}
}
/**
* 创建视图
* @param $table
*/
public function createView($table)
{
try{
//先删除视图
try{
DB::statement("drop view {$table}_view");
}catch (\Exception $exception){
Log::info('删除视图'.$table.'_view异常'.$exception->getMessage());
}
//查询所有表
$res = DB::select("show tables like '".$table."_%'");
$tables = array_map(function($item) use($table){
$name = collect(json_decode(json_encode($item), true))->first();
if (preg_match('/'.$table.'_2\d{5}/',$name)){
return $name;
}
},$res);
if (!empty($tables)){
$sql = "CREATE VIEW {$table}_view AS ";
foreach ($tables as $k => $tab){
$sql .= " (select * from ".$tab.") ";
if (count($tables) > 1 && $k < count($tables)-1){
$sql .= "union all";
}
}
DB::statement($sql);
}
}catch (\Exception $exception){
Log::info('创建视图'.$table.'异常:'.$exception->getMessage());
}
}
}

View File

@@ -1,239 +0,0 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
class swoole extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'swoole:cdr';
/**
* The console command description.
*
* @var string
*/
protected $description = '监听打电话';
protected $fs_dir = '/usr/local/freeswitch';
public $url = null;
public $machineId = 3;
public $asr_status_key = 'asr_status_key'; //控制是否开启分段录音asr识别的redis key
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
$this->url = config('app.url');
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
while (true){
$data = Redis::lPop(config('freeswitch.fs_dial_key'));
if ($data == null){
sleep(2);
continue;
}
$data = json_decode($data,true);
$process = new \Swoole\Process(function () use ($data) {
$fs = new \Freeswitchesl();
$service = config('freeswitch.esl');
if (!$fs->connect($service['host'], $service['port'], $service['password'])){
Log::error("asr监听ESL未连接");
return false;
}
//监听的事件
$eventarr = [
'CHANNEL_CALLSTATE',
'CHANNEL_ANSWER',
//'RECORD_START',
//'RECORD_STOP',
'CHANNEL_HANGUP_COMPLETE',
];
if (isset($data['aleg_uuid'])){
$fs->filteruuid($data['aleg_uuid']);
}
if (isset($data['bleg_uuid'])){
$fs->filteruuid($data['bleg_uuid']);
}
if (isset($data['dial_str'])){
$fs->bgapi(base64_decode($data['dial_str']));
}
$answer_time = 0;
//录音目录
$filepath = $this->fs_dir . '/recordings/' . date('Y') . '/' . date('m') . '/' . date('d') . '/';
$fullfile = $filepath . 'full_' . md5($data['aleg_uuid'] . $data['bleg_uuid']) . '.wav';
$leg = [
$data['aleg_uuid'] => [
'uuid' => $data['aleg_uuid'],
'leg_uuid' => $data['aleg_uuid'],
'record_file' => null,
'full_record_file' => $fullfile,
'start_at' => null,
'end_at' => null,
],
$data['bleg_uuid'] => [
'uuid' => $data['aleg_uuid'],
'leg_uuid' => $data['bleg_uuid'],
'record_file' => null,
'full_record_file' => $fullfile,
'start_at' => null,
'end_at' => null,
],
];
$fs->events('plain', implode(" ",$eventarr));
while (true) {
$received_parameters = $fs->recvEvent();
if (!empty($received_parameters)) {
$serialize = $fs->serialize($received_parameters,'json');
$json = json_decode($serialize,true);
$eventname = Arr::get($json,'Event-Name',null); //事件名称
$uuid = Arr::get($json,'Unique-ID',null);//当前信道leg的uuid
$otherUuid = Arr::get($json,'Other-Leg-Unique-ID',null);
$CallerCallerIDNumber = Arr::get($json,"Caller-Caller-ID-Number"); //主叫
$CallerCalleeIDNumber = Arr::get($json,"Caller-Destination-Number"); //被叫
switch ($eventname) {
//呼叫状态
case 'CHANNEL_CALLSTATE':
//是分机号才记录
if (preg_match('/\d{4,5}/',$CallerCallerIDNumber)){
$state = Arr::get($json,'Channel-Call-State');
$uniqueid = Arr::get($json,'Caller-Unique-ID');
Redis::setex($CallerCallerIDNumber.'_uuid',1200, $uniqueid);
DB::table('sip')->where('username',$CallerCallerIDNumber)->update(['state'=>$state]);
}
break;
case 'CHANNEL_ANSWER':
if ($otherUuid) { //被叫应答后
$answer_time = time();
//开启全程录音
$fs->bgapi("uuid_record {$uuid} start {$fullfile} 7200"); //录音
if (Redis::get($this->asr_status_key)==1) {
//记录A分段录音数据
$halffile_a = $filepath . 'half_' . md5($otherUuid . time() . uniqid()) . '.wav';
$fs->bgapi("uuid_record " . $otherUuid . " start " . $halffile_a . " 18");
$leg[$otherUuid] = array_merge($leg[$otherUuid],[
'record_file' => $halffile_a,
'start_at' => date('Y-m-d H:i:s'),
]);
//记录B分段录音数据
$halffile_b = $filepath . 'half_' . md5($uuid . time() . uniqid()) . '.wav';
$fs->bgapi("uuid_record " . $uuid . " start " . $halffile_b . " 18");
$leg[$uuid] = array_merge($leg[$uuid],[
'record_file' => $halffile_b,
'start_at' => date('Y-m-d H:i:s'),
]);
unset($halffile_a);
unset($halffile_b);
}
}
break;
case 'RECORD_START':
$leg[$uuid] = array_merge($leg[$uuid],[
'start_time' => date('Y-m-d H:i:s'),
'end_at' => null,
]);
break;
case 'RECORD_STOP':
if (Redis::get($this->asr_status_key)==1) {
$res = $leg[$uuid];
if (isset($res['record_file'])&&file_exists($res['record_file'])){
DB::table('asr')->insert([
'uuid' => $res['uuid'],
'leg_uuid' => $res['leg_uuid'],
'start_at' => $res['start_at'],
'end_at' => date('Y-m-d H:i:s'),
'billsec' => strtotime(date('Y-m-d H:i:s'))-strtotime($res['start_at']),
'record_file' => str_replace($this->fs_dir, $this->url, $res['record_file']),
'created_at' => date('Y-m-d H:i:s'),
]);
}
//结束说话 后接着开启分段录音
$halffile = $filepath . 'half_' . md5($uuid . time() . uniqid()) . '.wav';
$fs->bgapi("uuid_record " . $uuid . " start " . $halffile . " 18");
$leg[$uuid] = array_merge($leg[$uuid],[
'record_file' => $halffile,
'start_at' => date('Y-m-d H:i:s'),
'end_at' => null,
]);
unset($res);
unset($halffile);
}
break;
case 'CHANNEL_HANGUP_COMPLETE':
$otherType = Arr::get($json,'Other-Type',null);
//A的挂机事件到来时线束进程
if (empty($otherType) || $otherType == 'originatee') {
$src = Arr::get($json,'Caller-Caller-ID-Number',null);
$dst = Arr::get($json,'Caller-Callee-ID-Number',null);
$customer_caller = Arr::get($json,'variable_customer_caller',null);
$dst = !empty($customer_caller)?$customer_caller:$dst;
$start = Arr::get($json,'variable_start_stamp',null);
$user_data = Arr::get($json,'variable_user_data',null);
$record_file = str_replace($this->fs_dir,$this->url,$fullfile);
$billsec = $answer_time!=0?time()-$answer_time:0;
try{
$user_data = decrypt($user_data);
}catch (\Exception $exception){
$user_data = null;
}
try {
$model = DB::table('sip')
->join('users','sip.id','=','users.sip_id')
->where('sip.username',$src)
->select(['users.id','users.department_id'])
->first();
if ($model == null) break 2;
$cdr = [
'user_id' => $model->id,
'uuid' => $uuid,
'aleg_uuid' => $uuid,
'bleg_uuid' => $uuid,
'direction' => 1,
'src' => $src,
'dst' => $dst,
'duration' => 0,
'billsec' => $billsec,
'aleg_start_at' => urldecode($start),
'record_file' => $record_file,
'user_data' => $user_data,
'created_at' => date('Y-m-d H:i:s'),
];
DB::table('cdr')->insert($cdr);
}catch (\Exception $exception){
Log::error('写入通话记录异常:'.$exception->getMessage(),$cdr);
}
break 2;
}
default:
# code...
break;
}
}
}
$fs->disconnect();
});
$process->start();
}
}
}

View File

@@ -1,42 +0,0 @@
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
//
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')
// ->hourly();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}

View File

@@ -1,55 +0,0 @@
<?php
namespace App\Exceptions;
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that are not reported.
*
* @var array
*/
protected $dontReport = [
//
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array
*/
protected $dontFlash = [
'password',
'password_confirmation',
];
/**
* Report or log an exception.
*
* @param \Exception $exception
* @return void
*
* @throws \Exception
*/
public function report(Exception $exception)
{
parent::report($exception);
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $exception
* @return \Symfony\Component\HttpFoundation\Response
*
* @throws \Exception
*/
public function render($request, Exception $exception)
{
return parent::render($request, $exception);
}
}

View File

@@ -1,22 +0,0 @@
<?php
namespace App\Exports;
use Maatwebsite\Excel\Concerns\FromArray;
use Maatwebsite\Excel\Concerns\WithHeadings;
class ProjectExport implements FromArray,WithHeadings
{
public function array(): array
{
return [
];
}
public function headings(): array
{
return [
'公司名称','姓名','联系电话'
];
}
}

View File

@@ -1,112 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Models\Action;
use App\Models\Condition;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class ActionController extends Controller
{
/**
* 列表
* @param Request $request
* @param $condition_id
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\JsonResponse|\Illuminate\View\View
*/
public function index(Request $request,$condition_id)
{
if ($request->ajax()){
$res = Action::where('condition_id',$condition_id)->orderBy('sort')->orderBy('id')->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items(),
];
return response()->json($data);
}
$condition = Condition::findOrFail($condition_id);
return view('admin.dialplan.action.index',compact('condition'));
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create($condition_id)
{
$condition = Condition::findOrFail($condition_id);
return view('admin.dialplan.action.create',compact('condition'));
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request,$condition_id)
{
$condition = Condition::findOrFail($condition_id);
$data = $request->all(['display_name','application','data','sort']);
$data['condition_id'] = $condition->id;
if (Action::create($data)){
return redirect(route('admin.action',['condition_id'=>$condition->id]))->with(['success'=>'添加成功']);
}
return back()->withErrors(['error'=>'添加失败']);
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($condition_id,$id)
{
$condition = Condition::findOrFail($condition_id);
$model = Action::findOrFail($id);
return view('admin.dialplan.action.edit',compact('condition','model'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $condition_id, $id)
{
$condition = Condition::findOrFail($condition_id);
$model = Action::findOrFail($id);
$data = $request->all(['display_name','application','data','sort']);
if ($model->update($data)){
return redirect(route('admin.action',['condition_id'=>$condition->id]))->with(['success'=>'更新成功']);
}
return back()->withErrors(['error'=>'更新失败']);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request)
{
$ids = $request->get('ids');
if (empty($ids)){
return response()->json(['code'=>1,'msg'=>'请选择删除项']);
}
if (Action::destroy($ids)){
return response()->json(['code'=>0,'msg'=>'删除成功']);
}
return response()->json(['code'=>1,'msg'=>'删除失败']);
}
}

View File

@@ -1,145 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\Admin\Agent\AgentRequest;
use App\Models\Agent;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Response;
class AgentController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
if ($request->ajax()){
$data = $request->all(['display_name','originate_number']);
$res = Agent::when($data['display_name'],function($q) use($data){
return $q->where('display_name','like','%'.$data['display_name'].'%');
})->when($data['originate_number'],function($q) use($data){
return $q->where('originate_number','like','%'.$data['originate_number'].'%');
})->orderByDesc('id')->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items(),
];
return response()->json($data);
}
return view('admin.agent.index');
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
return view('admin.agent.create');
}
/**
* @param AgentRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function store(AgentRequest $request)
{
$data = $request->all();
try{
Agent::create($data);
return Response::json(['code'=>0,'msg'=>'添加成功']);
}catch (\Exception $exception){
Log::error('添加坐席异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'添加失败']);
}
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
$model = Agent::findOrFail($id);
return view('admin.agent.edit',compact('model'));
}
/**
* @param AgentRequest $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function update(AgentRequest $request, $id)
{
$model = Agent::findOrFail($id);
$data = $request->except(['_method','_token']);
try{
$model->update($data);
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
Log::error('更新坐席异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request)
{
$ids = $request->get('ids');
if (empty($ids)){
return response()->json(['code'=>1,'msg'=>'请选择删除项']);
}
if (Agent::destroy($ids)){
return response()->json(['code'=>0,'msg'=>'删除成功']);
}
return response()->json(['code'=>1,'msg'=>'删除失败']);
}
/**
* 签入签出
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function check(Request $request){
$data = $request->all(['ids','status']);
if (empty($data['ids']) || !is_array($data['ids'])) {
return response()->json(['code'=>1,'msg'=>'请选择操作项']);
}
if (!in_array($data['status'], [0,1])) {
return response()->json(['code'=>1,'msg'=>'状态参数错误']);
}
$status = $data['status']==1?'Available':'Logged Out';
$freeswitch = new \Freeswitchesl();
$service = config('freeswitch.esl');
try{
if ($freeswitch->connect($service['host'], $service['port'], $service['password'])) {
foreach ($data['ids'] as $id) {
$freeswitch->api("callcenter_config agent set status agent".$id." '".$status."'");
}
$freeswitch->disconnect();
return response()->json(['code'=>0,'msg'=>'更新成功']);
}else{
return response()->json(['code'=>1,'msg'=>'更新成功']);
}
}catch(\Exception $e){
return response()->json(['code'=>1,'msg'=>'系统错误','data'=>$e->getMessage()]);
}
}
}

View File

@@ -1,281 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Project\ProjectRequest;
use App\Imports\ProjectImport;
use App\Models\Project;
use App\Models\ProjectDesign;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\View;
use Maatwebsite\Excel\Facades\Excel;
class AssignmentController extends Controller
{
/**
* 待分配列表
* @return \Illuminate\Contracts\View\View
*/
public function index()
{
$users = User::where('id','!=',config('freeswitch.user_root_id'))->get();
return View::make('admin.assignment.index',compact('users'));
}
public function data(Request $request)
{
$user = Auth::user();
$data = $request->all([
'name',
'phone',
'company_name',
]);
$res = Project::query()
//姓名
->when($data['name'], function ($query) use ($data) {
return $query->where('name', $data['name']);
})
//联系电话
->when($data['phone'], function ($query) use ($data) {
return $query->where('phone', $data['phone']);
})
//公司名称
->when($data['company_name'], function ($query) use ($data) {
return $query->where('company_name', '%' . $data['company_name'] . '%');
})
->where('owner_user_id','>=',0)
->orderBy('owner_user_id','asc')
->orderBy('id','desc')
->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items()
];
return Response::json($data);
}
/**
* 导入项目
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function import(Request $request)
{
//上传文件最大大小,单位M
$maxSize = 10;
//支持的上传类型
$allowed_extensions = ["xls", "xlsx"];
$file = $request->file('file');
//检查文件是否上传完成
if ($file->isValid()){
//检测类型
$ext = $file->getClientOriginalExtension();
if (!in_array(strtolower($ext),$allowed_extensions)){
return Response::json(['code'=>1,'msg'=>"请上传".implode(",",$allowed_extensions)."格式的图片"]);
}
//检测大小
if ($file->getSize() > $maxSize*1024*1024){
return Response::json(['code'=>1,'msg'=>"大小限制".$maxSize."M"]);
}
}else{
Log::info('导入项目是文件上传不完整:'.$file->getErrorMessage());
return Response::json(['code'=>1,'msg'=>'文件上传不完整']);
}
$newFile = date('Y-m-d')."_".time()."_".uniqid().".".$file->getClientOriginalExtension();
try{
$res = Storage::disk('uploads')->put($newFile,file_get_contents($file->getRealPath()));
}catch (\Exception $exception){
Log::info('上传文件失败:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'文件上传失败']);
}
$xlsFile = public_path('uploads').'/'.$newFile;
try{
Excel::import(new ProjectImport(), $xlsFile);
return Response::json(['code'=>0,'msg'=>'导入成功']);
}catch (\Exception $exception){
Log::info('导入失败:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'导入失败']);
}
}
/**
* 分配
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function to(Request $request)
{
$ids = $request->get('ids',[]);
$user_id = $request->get('user_id');
DB::beginTransaction();
try{
DB::table('project')->whereIn('id',$ids)->update([
'owner_user_id' => $user_id
]);
DB::commit();
return Response::json(['code'=>0,'msg'=>'分配成功']);
}catch (\Exception $exception){
DB::rollBack();
Log::error('分配异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'分配失败']);
}
}
/**
* 删除
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function destroy(Request $request)
{
$ids = $request->get('ids',[]);
DB::beginTransaction();
try{
DB::table('project')->whereIn('id',$ids)->delete();
DB::commit();
return Response::json(['code'=>0,'msg'=>'删除成功']);
}catch (\Exception $exception){
DB::rollBack();
Log::error('删除项目异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'删除失败']);
}
}
/**
* 添加项目
* @return \Illuminate\Contracts\View\View
*/
public function create()
{
$designs = ProjectDesign::where('visiable',1)
->orderBy('sort','asc')
->get();
return View::make('admin.assignment.create',compact('designs'));
}
/**
* 添加项目
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(ProjectRequest $request)
{
$user = Auth::user();
$data = $request->all(['company_name','name','phone']);
$dataInfo = [];
$fields = ProjectDesign::where('visiable',1)->get();
foreach ($fields as $d){
$items = [
'project_design_id' => $d->id,
'data' => $request->get($d->field_key),
];
if ($d->field_type=='checkbox'){
if (!empty($items['data'])){
$items['data'] = implode(',',$items['data']);
}else{
$items['data'] = null;
}
}
array_push($dataInfo,$items);
}
DB::beginTransaction();
try{
$project_id = DB::table('project')->insertGetId([
'company_name' => $data['company_name'],
'name' => $data['name'],
'phone' => $data['phone'],
'created_user_id' => $user->id,
'owner_user_id' => 0,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
foreach ($dataInfo as $d){
DB::table('project_design_value')->insert([
'project_id' => $project_id,
'project_design_id' => $d['project_design_id'],
'data' => $d['data'],
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
]);
}
DB::commit();
return Response::json(['code'=>0,'msg'=>'添加成功']);
}catch (\Exception $exception){
DB::rollBack();
Log::info('添加项目异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'添加失败']);
}
}
/**
* 更新项目
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function edit($id)
{
$model = Project::with('designs')->findOrFail($id);
return View::make('admin.assignment.edit',compact('model'));
}
/**
* 更新项目
* @param ProjectRequest $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function update(ProjectRequest $request,$id)
{
$data = $request->all(['company_name','name','phone']);
$dataInfo = [];
$model = Project::with('designs')->findOrFail($id);
foreach ($model->designs as $d){
$items = [
'id' => $d->pivot->id,
'data' => $request->get($d->field_key),
];
if ($d->field_type=='checkbox'){
if (!empty($items['data'])){
$items['data'] = implode(',',$items['data']);
}else{
$items['data'] = null;
}
}
array_push($dataInfo,$items);
}
DB::beginTransaction();
try{
DB::table('project')->where('id',$id)->update([
'company_name' => $data['company_name'],
'name' => $data['name'],
'phone' => $data['phone'],
'updated_user_id' => $request->user()->id,
'updated_at' => Carbon::now(),
]);
foreach ($dataInfo as $d){
DB::table('project_design_value')->where('id',$d['id'])->update(['data'=>$d['data']]);
}
DB::commit();
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
DB::rollBack();
Log::error('更新项目异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
}

View File

@@ -1,92 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Models\Audio;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
class AudioController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
if ($request->ajax()) {
$res = Audio::orderBy('id','desc')->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items(),
];
return response()->json($data);
}
return view('admin.audio.index');
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$text = $request->get('text');
if ($text==null){
return response()->json(['code'=>1,'msg'=>'请输入待合成文本']);
}
try{
$model = new Audio();
$res = $model->tts($text);
if ($res['code']==0) {
Audio::create([
'url' => $res['data']['url'],
'path' => $res['data']['path'],
'text' => $text,
'user_id' => auth()->user()->id,
]);
return response()->json(['code'=>0,'msg'=>'合成成功','data'=>['url'=>$res['data']['url']]]);
}
return response()->json($res);
}catch (\Exception $exception){
Log::error('合成语音异常:'.$exception->getMessage());
return response()->json(['code'=>1,'msg'=>'合成失败']);
}
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request)
{
$ids = $request->get('ids');
$audio = Audio::where('id',$ids[0])->first();
if ($ids == null){
return response()->json(['code'=>1,'msg'=>'请选择删除项']);
}
try{
if (file_exists($audio->path)){
unlink($audio->path);
}
$audio->delete();
return response()->json(['code'=>0,'msg'=>'删除成功']);
}catch (\Exception $exception){
return response()->json(['code'=>1,'msg'=>'删除失败']);
}
}
}

View File

@@ -1,202 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Models\Cdr;
use App\Models\Sip;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
class CdrController extends Controller
{
public function index()
{
return view('admin.cdr.index');
}
public function data(Request $request)
{
$query = Cdr::query();
$search = $request->all(['src','dst','start_at_start','start_at_end']);
if ($search['src']){
$query = $query->where('src',$search['src']);
}
if ($search['dst']){
$query = $query->where('dst',$search['dst']);
}
if ($search['start_at_start'] && !$search['start_at_end']){
$query = $query->where('aleg_start_at','>=',$search['start_at_start']);
}else if (!$search['start_at_start'] && $search['start_at_end']){
$query = $query->where('aleg_start_at','<=',$search['start_at_end']);
}else if ($search['start_at_start'] && $search['start_at_end']){
$query = $query->whereBetween('aleg_start_at',[$search['start_at_start'],$search['start_at_end']]);
}
$user = $request->user();
$res = $query->where(function ($query) use($user) {
if ($user->hasPermissionTo('data.cdr.list_all')) {
# code...
}elseif ($user->hasPermissionTo('data.cdr.list_department')) {
$user_ids = User::where('department_id',$user->department_id)->pluck('id')->toArray();
return $query->whereIn('user_id',$user_ids);
}else{
return $query->where('user_id',$user->id);
}
})->orderByDesc('id')->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items(),
];
return response()->json($data);
}
/**
* 播放录音
* @param $uuid
* @return array
*/
public function play($uuid)
{
$cdr = Cdr::where('uuid',$uuid)->first();
if ($cdr==null){
return ['code'=>'1','msg'=>'通话记录不存在'];
}
if (empty($cdr->record_file)){
return ['code'=>'1','msg'=>'未找到录音文件'];
}
return ['code'=>0,'msg'=>'请求成功','data'=>$cdr->record_file];
}
/**
* 下载录音
* @param $uuid
* @return \Illuminate\Http\RedirectResponse|\Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function download($uuid)
{
$cdr = Cdr::where('uuid',$uuid)->first();
if ($cdr==null){
return back()->withErrors(['error'=>'通话记录不存在']);
}
if (!file_exists($cdr->record_file)){
return back()->withErrors(['error'=>'未找到录音文件']);
}
return response()->download($cdr->record_file,$uuid.".wav");
}
/**
* 人员统计
* @param Request $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Http\JsonResponse
*/
public function count(Request $request)
{
$users = User::where('id','!=',config('freeswitch.user_root_id'))->get();
if ($request->ajax()){
$res = $request->all(['user_id','start_stamp_start','start_stamp_end']);
$data = $users->keyBy('id')->all();
foreach ($data as &$d){
$d['todayCalls'] = 0;
$d['todaySuccessCalls'] = 0;
$d['todayRateCalls'] = '0.00%';
$d['todayThirtyCalls'] = 0;
$d['todaySixtyCalls'] = 0;
$d['weekCalls'] = 0;
$d['weekSuccessCalls'] = 0;
$d['weekRateCalls'] = '0.00%';
$d['weekThirtyCalls'] = 0;
$d['weekSixtyCalls'] = 0;
$d['monthCalls'] = 0;
$d['monthSuccessCalls'] = 0;
$d['monthRateCalls'] = '0.00%';
$d['monthThirtyCalls'] = 0;
$d['monthSixtyCalls'] = 0;
}
Cdr::when($res['user_id'],function ($q) use($res){
return $q->where('user_id',$res['user_id']);
})
->when($res['start_stamp_start'] && !$res['start_stamp_end'],function ($q) use($res){
return $q->where('aleg_start_at','>=',$res['start_stamp_start']);
})
->when(!$res['start_stamp_start'] && $res['start_stamp_end'],function ($q) use($res){
return $q->where('aleg_start_at','<=',$res['start_stamp_end']);
})
->when($res['start_stamp_start'] && $res['start_stamp_end'],function ($q) use($res){
return $q->whereBetween('aleg_start_at',[$res['start_stamp_start'],$res['start_stamp_end']]);
})
->where('user_id','!=',config('freeswitch.user_root_id'))
->orderBy('id','asc')
->chunk(1000,function ($cdrs) use(&$data){
foreach ($cdrs as $cdr){
foreach ($data as $d){
if ($cdr->user_id==$d['id']){
$time = strtotime($cdr->aleg_start_at);
//当天
if ($time>=Carbon::today()->timestamp && $time<=Carbon::tomorrow()->timestamp){
$d['todayCalls'] += 1;
}
if ($time>=Carbon::today()->timestamp && $time<=Carbon::tomorrow()->timestamp && $cdr->billsec>0){
$d['todaySuccessCalls'] += 1;
}
if ($time>=Carbon::today()->timestamp && $time<=Carbon::tomorrow()->timestamp && $cdr->billsec>30){
$d['todayThirtyCalls'] += 1;
}
if ($time>=Carbon::today()->timestamp && $time<=Carbon::tomorrow()->timestamp && $cdr->billsec>60){
$d['todaySixtyCalls'] += 1;
}
//本周
if ($time>=Carbon::now()->startOfWeek()->timestamp && $time<=Carbon::now()->endOfWeek()->timestamp){
$d['weekCalls'] += 1;
}
if ($time>=Carbon::now()->endOfWeek()->timestamp && $time<=Carbon::now()->endOfWeek()->timestamp && $cdr->billsec>0){
$d['weekSuccessCalls'] += 1;
}
if ($time>=Carbon::now()->endOfWeek()->timestamp && $time<=Carbon::now()->endOfWeek()->timestamp && $cdr->billsec>30){
$d['weekThirtyCalls'] += 1;
}
if ($time>=Carbon::now()->endOfWeek()->timestamp && $time<=Carbon::now()->endOfWeek()->timestamp && $cdr->billsec>60){
$d['weekSixtyCalls'] += 1;
}
//本月
if ($time>=Carbon::now()->startOfMonth()->timestamp && $time<=Carbon::now()->endOfMonth()->timestamp){
$d['monthCalls'] += 1;
}
if ($time>=Carbon::now()->startOfMonth()->timestamp && $time<=Carbon::now()->endOfMonth()->timestamp && $cdr->billsec>0){
$d['monthSuccessCalls'] += 1;
}
if ($time>=Carbon::now()->startOfMonth()->timestamp && $time<=Carbon::now()->endOfMonth()->timestamp && $cdr->billsec>30){
$d['monthThirtyCalls'] += 1;
}
if ($time>=Carbon::now()->startOfMonth()->timestamp && $time<=Carbon::now()->endOfMonth()->timestamp && $cdr->billsec>60){
$d['monthSixtyCalls'] += 1;
}
break;
}
}
}
});
foreach ($data as &$d){
$d['todayRateCalls'] = $d['todayCalls']>0?100*round($d['todaySuccessCalls']/$d['todayCalls'],4).'%':'0.00%';
$d['weekRateCalls'] = $d['weekCalls']>0?100*round($d['weekSuccessCalls']/$d['weekCalls'],4).'%':'0.00%';
$d['monthRateCalls'] = $d['monthCalls']>0?100*round($d['monthSuccessCalls']/$d['monthCalls'],4).'%':'0.00%';
}
return Response::json([
'code' => 0,
'msg' => '正在请求中...',
'count' => count($data),
'data' => $data,
]);
}
return View::make('admin.cdr.count',compact('users'));
}
}

View File

@@ -1,123 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\Admin\Dialplan\ConditionRequest;
use App\Models\Condition;
use App\Models\Extension;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class ConditionController extends Controller
{
/**
* 列表
* @param Request $request
* @param $extension_id
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\JsonResponse|\Illuminate\View\View
*/
public function index(Request $request,$extension_id)
{
if ($request->ajax()){
$res = Condition::where('extension_id',$extension_id)->orderBy('sort')->orderBy('id')->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items(),
];
return response()->json($data);
}
$extension = Extension::findOrFail($extension_id);
return view('admin.dialplan.condition.index',compact('extension'));
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create($extension_id)
{
$extension = Extension::findOrFail($extension_id);
return view('admin.dialplan.condition.create',compact('extension'));
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(ConditionRequest $request,$extension_id)
{
$extension = Extension::findOrFail($extension_id);
$data = $request->all(['display_name','field','expression','break','sort']);
$data['extension_id'] = $extension->id;
if (Condition::create($data)){
return redirect(route('admin.condition',['extension_id'=>$extension->id]))->with(['success'=>'添加成功']);
}
return back()->withErrors(['error'=>'添加失败']);
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($extension_id,$id)
{
$extension = Extension::findOrFail($extension_id);
$model = Condition::findOrFail($id);
return view('admin.dialplan.condition.edit',compact('extension','model'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $extension_id, $id)
{
$extension = Extension::findOrFail($extension_id);
$model = Condition::findOrFail($id);
$data = $request->all(['display_name','field','expression','break','sort']);
if ($model->update($data)){
return redirect(route('admin.condition',['extension_id'=>$extension->id]))->with(['success'=>'更新成功']);
}
return back()->withErrors(['error'=>'更新失败']);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request)
{
$ids = $request->get('ids');
if (empty($ids)){
return response()->json(['code'=>1,'msg'=>'请选择删除项']);
}
if (Condition::destroy($ids)){
return response()->json(['code'=>0,'msg'=>'删除成功']);
}
return response()->json(['code'=>1,'msg'=>'删除失败']);
}
}

View File

@@ -1,103 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Department;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
class DepartmentController extends Controller
{
public function index(Request $request)
{
if ($request->ajax()){
$res = Department::orderBy('id')->get();
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->count(),
'data' => $res
];
return response()->json($data);
}
return View::make('admin.department.index');
}
/**
* 添加部门
* @return \Illuminate\Contracts\View\View
*/
public function create()
{
$departments = Department::with('childs')->where('parent_id',0)->get();
return View::make('admin.department.create',compact('departments'));
}
public function store(Request $request)
{
$data = $request->all(['name','parent_id']);
try{
Department::create($data);
return Response::json(['code'=>0,'msg'=>'添加成功']);
}catch (\Exception $exception){
Log::error('添加部门异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'添加失败']);
}
}
/**
* 更新
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function edit($id)
{
$model = Department::findOrFail($id);
$departments = Department::with('childs')->where('parent_id',0)->get();
return View::make('admin.department.edit',compact('departments','model'));
}
public function update(Request $request,$id)
{
$data = $request->all(['name','parent_id']);
$model = Department::findOrFail($id);
try{
$model->update($data);
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
Log::error('添加部门异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
/**
* 删除
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function destroy(Request $request)
{
$ids = $request->get('ids');
if (empty($ids)){
return Response::json(['code'=>1,'msg'=>'请选择删除项']);
}
$model = Department::with('childs')->find($ids[0]);
if (!$model) {
return Response::json(['code' => 1, 'msg' => '部门不存在']);
}
if ($model->childs->isNotEmpty()) {
return Response::json(['code' => 1, 'msg' => '存在子部门禁止删除']);
}
try {
$model->delete();
return Response::json(['code' => 0, 'msg' => '删除成功']);
} catch (\Exception $exception) {
Log::error('删除部门异常:'.$exception->getMessage());
return Response::json(['code' => 1, 'msg' => '删除失败']);
}
}
}

View File

@@ -1,151 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\Admin\Dialplan\ExtensionRequest;
use App\Models\Extension;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\DB;
class ExtensionController extends Controller
{
/**
* 列表
* @param Request $request
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\JsonResponse|\Illuminate\View\View
*/
public function index(Request $request)
{
if ($request->ajax()){
$query = Extension::query();
$res = $query->orderBy('sort')->orderBy('id')->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items(),
];
return response()->json($data);
}
return view('admin.dialplan.extension.index');
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
return view('admin.dialplan.extension.create');
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(ExtensionRequest $request)
{
$data = $request->all(['display_name','name','sort','continue','context']);
if (Extension::create($data)){
return redirect(route('admin.extension'))->with(['success'=>'添加成功']);
}
return back()->withErrors(['error'=>'添加失败']);
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
$extension = Extension::with('conditions')->findOrFail($id);
return view('admin.dialplan.extension.show',compact('extension'));
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
$model = Extension::findOrFail($id);
return view('admin.dialplan.extension.edit',compact('model'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(ExtensionRequest $request, $id)
{
$model = Extension::findOrFail($id);
$data = $request->all(['display_name','name','sort','continue','context']);
if ($model->update($data)){
return redirect(route('admin.extension'))->with(['success'=>'更新成功']);
}
return back()->withErrors(['error'=>'更新失败']);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request)
{
$ids = $request->get('ids');
if (empty($ids)){
return response()->json(['code'=>1,'msg'=>'请选择删除项']);
}
if (Extension::destroy($ids)){
return response()->json(['code'=>0,'msg'=>'删除成功']);
}
return response()->json(['code'=>1,'msg'=>'删除失败']);
}
public function updateXml()
{
set_time_limit(0);
$extension = DB::table('extension')->orderBy('sort')->get()->groupBy('context')->toArray();
$condition = DB::table('condition')->orderBy('sort')->get()->groupBy('extension_id')->toArray();
$action = DB::table('action')->orderBy('sort')->get()->groupBy('condition_id')->toArray();
if (empty($extension)){
return response()->json(['code'=>1,'msg'=>'无数据需要更新']);
}
foreach ($condition as $key1 => $value1) {
foreach ($value1 as $key2 => $value2) {
$value2->action = isset($action[$value2->id]) ? $action[$value2->id] : [];
}
}
foreach ($extension as $key1 => $value1) {
foreach ($value1 as $key2 => $value2) {
$value2->condition = isset($condition[$value2->id]) ? $condition[$value2->id] : [];
}
}
$data = $extension;
try{
$client = new Client();
$res = $client->post(config('freeswitch.swoole_http_url.dialplan'),['form_params'=>['data'=>json_encode($data)]]);
return response()->json(json_decode($res->getBody(),true));
}catch (\Exception $exception){
return response()->json(['code'=>1,'msg'=>'更新失败','data'=>$exception->getMessage()]);
}
}
}

View File

@@ -1,132 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\Admin\Gateway\GatewayRequest;
use App\Models\Gateway;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Response;
class GatewayController extends Controller
{
/**
* 列表
* @param Request $request
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\JsonResponse|\Illuminate\View\View
*/
public function index(Request $request)
{
if ($request->ajax()){
$res = Gateway::orderByDesc('id')->paginate($request->get('limit', 30));
foreach ($res->items() as $d){
$d->status = $d->getStatus($d->id);
}
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items(),
];
return response()->json($data);
}
return view('admin.gateway.index');
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
return view('admin.gateway.create');
}
/**
* @param GatewayRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function store(GatewayRequest $request)
{
$data = $request->except(['_method','_token']);
try{
Gateway::create($data);
return Response::json(['code'=>0,'msg'=>'添加成功']);
}catch (\Exception $exception){
Log::error('添加网关异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'添加失败']);
}
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
$model = Gateway::findOrFail($id);
return view('admin.gateway.edit',compact('model'));
}
/**
* @param GatewayRequest $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function update(GatewayRequest $request, $id)
{
$model = Gateway::findOrFail($id);
$data = $request->except(['_method','_token']);
try{
$model->update($data);
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
Log::error('更新网关异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
/**
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function destroy(Request $request)
{
$ids = $request->get('ids');
if (empty($ids)){
return response()->json(['code'=>1,'msg'=>'请选择删除项']);
}
if (Gateway::destroy($ids)){
return response()->json(['code'=>0,'msg'=>'删除成功']);
}
return response()->json(['code'=>1,'msg'=>'删除失败']);
}
/**
* 更新配置
* @return \Illuminate\Http\JsonResponse
*/
public function updateXml()
{
set_time_limit(0);
$gateway = Gateway::get()->toArray();
if (empty($gateway)){
return response()->json(['code'=>1,'msg'=>'无数据需要更新']);
}
try{
$client = new Client();
$res = $client->post(config('freeswitch.swoole_http_url.gateway'),['form_params'=>['data'=>json_encode($gateway)]]);
return response()->json(json_decode($res->getBody(),true));
}catch (\Exception $exception){
return response()->json(['code'=>1,'msg'=>'更新失败','data'=>$exception->getMessage()]);
}
}
}

View File

@@ -1,225 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Models\Gateway;
use App\Models\GatewayOutbound;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;
use Faker\Provider\Uuid;
class GatewayOutboundController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
if ($request->ajax()){
$data = $request->all(['gateway_id','number']);
$res = GatewayOutbound::with('gateway')
->when($data['gateway_id'],function($q) use($data){
return $q->where('gateway_id',$data['gateway_id']);
})
->when($data['number'],function($q) use($data){
return $q->where('number',$data['number']);
})
->orderByDesc('id')->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items(),
];
return Response::json($data);
}
$gateways = Gateway::get();
return view('admin.gateway_outbound.index',compact('gateways'));
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
$gateways = Gateway::get();
return View::make('admin.gateway_outbound.create',compact('gateways'));
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$data = $request->all(['gateway_id','number','status']);
try{
GatewayOutbound::create($data);
return Response::json(['code'=>0,'msg'=>'添加成功']);
}catch (\Exception $exception){
Log::error('添加网关号码异常:'.$exception->getMessage(),$data);
return Response::json(['code'=>1,'msg'=>'添加失败']);
}
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
$model = GatewayOutbound::findOrFail($id);
$gateways = Gateway::get();
return View::make('admin.gateway_outbound.edit',compact('model','gateways'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$model = GatewayOutbound::where('id',$id)->first();
if ($model == null){
return Response::json(['code'=>1,'msg'=>'词库不存在']);
}
$data = $request->all(['gateway_id','number','status']);
try{
$model->update($data);
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
Log::error('更新网关号码异常:'.$exception->getMessage(),$data);
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request)
{
$ids = $request->get('ids');
if (empty($ids)){
return response()->json(['code'=>1,'msg'=>'请选择删除项']);
}
if (GatewayOutbound::destroy($ids)){
return response()->json(['code'=>0,'msg'=>'删除成功']);
}
return response()->json(['code'=>1,'msg'=>'删除失败']);
}
public function importForm()
{
$gateways = Gateway::get();
return View::make('admin.gateway_outbound.import',compact('gateways'));
}
public function import(Request $request)
{
set_time_limit(0);
$gateway_id = $request->get('gateway_id');
$gateway = Gateway::find($gateway_id);
if ($gateway==null){
return response()->json(['code'=>1,'msg'=>'网关不存在']);
}
$file = $request->file('file');
if ($file->isValid()){
$allowed_extensions = ['csv'];
//上传文件最大大小,单位M 500Kb大约4万条数据
$maxSize = 1;
//检测类型
$ext = $file->getClientOriginalExtension();
if (!in_array(strtolower($ext),$allowed_extensions)){
return response()->json(['code'=>1,'msg'=>"请上传".implode(",",$allowed_extensions)."格式"]);
}
//检测大小
if ($file->getClientSize() > $maxSize*1024*1024){
return response()->json(['code'=>1,'msg'=>"大小限制".$maxSize."M"]);
}
//上传到七牛云
$newFile = Uuid::uuid().".".$file->getClientOriginalExtension();
try{
Storage::disk('uploadfile')->put($newFile,file_get_contents($file->getRealPath()));
$url = public_path('uploadfile').'/'.$newFile;
}catch (\Exception $exception){
return response()->json(['code'=>1,'msg'=>'文件上传失败','data'=>$exception->getMessage()]);
}
//文件内容读取
$data = [];
try{
$fp = fopen($url,"r");
while(!feof($fp))
{
$line = fgetcsv($fp);
if ($line){
foreach ($line as $phone){
array_push($data,$phone);
}
}
}
fclose($fp);
//去重,去空
$data = array_filter(array_unique($data));
}catch (\Exception $exception){
return response()->json(['code'=>1,'msg'=>'读取文件内容错误','data'=>$exception->getMessage()]);
}
//写入数据库
if (!empty($data)){
DB::beginTransaction();
try{
foreach ($data as $d){
DB::table('gateway_outbound')->insert([
'gateway_id' => $gateway->id,
'number' => $d,
'status' => 1,
'created_at'=> Carbon::now(),
'updated_at'=> Carbon::now(),
]);
}
DB::commit();
return response()->json(['code'=>0,'msg'=>'导入完成']);
}catch (\Exception $exception){
DB::rollBack();
return response()->json(['code'=>1,'msg'=>'导入失败','data'=>$exception->getMessage()]);
}
}
return response()->json(['code'=>1,'msg'=>'导入数据为空']);
}
return response()->json(['code'=>1,'msg'=>'上传失败','data'=>$file->getErrorMessage()]);
}
}

View File

@@ -1,72 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Cdr;
use App\Models\Department;
use App\Models\Project;
use App\Models\User;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
class IndexController extends Controller
{
//后台布局
public function layout()
{
return View::make('admin.layout');
}
public function index()
{
//部门数量
$departmentCount = Department::count();
//用户数量
$userCount = User::where('id','!=',config('freeswitch.user_root_id'))->count();
//总客户数
$projectCount = Project::count();
//公海客户数
$wasteCount = Project::onlyTrashed()->count();
return View::make('admin.index.index',compact('departmentCount','userCount','projectCount','wasteCount'));
}
public function chart()
{
$data = [
'months' => [],
'calls' => [],
'success' => [],
];
for ($m=1;$m<=12;$m++){
$data['year_month'][$m] = [
'start' => mktime(0,0,0,$m,1,date('Y')),
'end' => mktime(0,0,0,$m+1,1,date('Y')),
];
$data['months'][] = $m.'月';
$data['calls'][$m] = 0;
$data['success'][$m] = 0;
}
Cdr::whereYear('aleg_start_at', date('Y'))
->orderBy('id')
->chunk(1000, function ($result) use(&$data){
foreach ($result as $item) {
foreach ($data['year_month'] as $key=>$time){
if (strtotime($item->aleg_start_at)>=$time['start'] && strtotime($item->aleg_start_at)<$time['end']){
$data['calls'][$key] += 1;
if ($item->billsec>0){
$data['success'][$key] += 1;
}
}
}
}
});
return Response::json(['code'=>0,'msg'=>'请求成功','data'=>$data]);
}
public function onlinecall()
{
return View::make('admin.index.onlinecall');
}
}

View File

@@ -1,164 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Menu\StoreRequest;
use App\Http\Requests\Admin\Menu\UpdateRequest;
use App\Models\Menu;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
use App\Models\Permission;
class MenuController extends Controller
{
/**
* 菜单列表
* @param Request $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Http\JsonResponse
*/
public function index(Request $request)
{
if ($request->ajax()){
$res = Menu::orderBy('sort','asc')->orderBy('id','asc')->paginate($request->get('limit', 30));
foreach ($res->items() as $re){
if ($re->type==1){
$re->url = $re->url ? $re->url : route($re->route,[],false);
}
}
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items()
];
return Response::json($data);
}
return View::make('admin.menu.index');
}
/**
* 添加菜单
* @return \Illuminate\Contracts\View\View
*/
public function create()
{
$menus = Menu::with('childs')->where('parent_id', 0)->get();
$permissions = Permission::with('childs')->where('parent_id', 0)->get();
return View::make('admin.menu.create', compact('menus','permissions','menus'));
}
/**
* 添加菜单
* @param StoreRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function store(StoreRequest $request)
{
$data = $request->all([
'name',
'parent_id',
'route',
'url',
'icon',
'sort',
'type',
'permission_id',
]);
if ($data['type']==1){
if ($data['route'] && $data['url']){
return Response::json(['code'=>1,'msg'=>'路由与链接只可启用一个']);
}
if (!$data['route'] && !$data['url']){
return Response::json(['code'=>1,'msg'=>'路由与链接至少启用一个']);
}
}
try {
Menu::create($data);
return Response::json(['code'=>0,'msg'=>'添加成功']);
} catch (\Exception $exception) {
Log::error('添加菜单异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'添加失败']);
}
}
/**
* 更新菜单
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function edit($id)
{
$menu = Menu::findOrFail($id);
$menus = Menu::with('childs')->where('parent_id', 0)->get();
$permissions = Permission::with('childs')->where('parent_id', 0)->get();
return View::make('admin.menu.edit', compact('menu', 'menus','permissions'));
}
/**
* 更新菜单
* @param UpdateRequest $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function update(UpdateRequest $request, $id)
{
$model = Menu::findOrFail($id);
$data = $request->all([
'name',
'parent_id',
'route',
'url',
'icon',
'sort',
'type',
'permission_id',
]);
if ($data['type']==1){
if ($data['route'] && $data['url']){
return Response::json(['code'=>1,'msg'=>'路由与链接只可启用一个']);
}
if (!$data['route'] && !$data['url']){
return Response::json(['code'=>1,'msg'=>'路由与链接至少启用一个']);
}
}
try {
$model->update($data);
return Response::json(['code'=>0,'msg'=>'更新成功']);
} catch (\Exception $exception) {
Log::error('更新菜单异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
/**
* 删除菜单
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function destroy(Request $request)
{
$ids = $request->get('ids');
if (!is_array($ids) || empty($ids)) {
return Response::json(['code' => 1, 'msg' => '请选择删除项']);
}
$model = Menu::with('childs')->find($ids[0]);
if (!$model) {
return Response::json(['code' => 1, 'msg' => '菜单不存在']);
}
//如果有子权限,则禁止删除
if ($model->childs->isNotEmpty()) {
return Response::json(['code' => 1, 'msg' => '存在子菜单禁止删除']);
}
try {
$model->delete();
return Response::json(['code' => 0, 'msg' => '删除成功']);
} catch (\Exception $exception) {
Log::error('删除菜单异常:'.$exception->getMessage());
return Response::json(['code' => 1, 'msg' => '删除失败']);
}
}
}

View File

@@ -1,49 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Sip;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
class MonitorController extends Controller
{
/**
* 监听主页
* @param Request $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Http\JsonResponse
*/
public function index(Request $request)
{
$data = Sip::query()->get();
if ($request->ajax()){
$list = [];
$total = $ring = $active = $down = 0;
foreach ($data as $d){
$list[$d->id]['state'] = $d->state;
$list[$d->id]['state_name'] = $d->state_name;
$total++;
if ($d->state == 'RINGING' || $d->state == 'EARLY' || $d->state == 'RING_WAIT'){
$ring++;
}elseif ($d->state == 'ACTIVE'){
$active++;
}elseif ($d->state == 'DOWN' || $d->state == 'HANGUP'){
$down++;
}
}
return Response::json([
'code' => 0,
'msg' => '请求成功',
'data' => [
'count' => ['total' => $total, 'ring' => $ring, 'active' => $active, 'down' => $down],
'list' => $list,
]
]);
}
return View::make('admin.monitor.index',compact('data'));
}
}

View File

@@ -1,83 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Node;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
class NodeController extends Controller
{
public function index(Request $request)
{
if ($request->ajax()){
$res = Node::orderBy('sort')
->orderBy('type','asc')
->orderBy('id')
->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items(),
];
return response()->json($data);
}
$data = Node::orderBy('sort','asc')->select(['id','name','sort'])->get();
return View::make('admin.node.index',compact('data'));
}
public function create()
{
return View::make('admin.node.create');
}
public function store(Request $request)
{
$data = $request->all(['name','sort','type']);
try{
Node::create($data);
return Response::json(['code'=>0,'msg'=>'添加成功']);
}catch (\Exception $exception){
Log::error('添加节点异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'添加失败']);
}
}
public function edit($id)
{
$model = Node::findOrFail($id);
return View::make('admin.node.edit',compact('model'));
}
public function update(Request $request,$id)
{
$data = $request->all(['name','sort','type']);
$model = Node::findOrFail($id);
try{
$model->update($data);
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
Log::error('更新节点异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
public function destroy(Request $request)
{
$ids = $request->get('ids');
if (empty($ids)){
return Response::json(['code'=>1,'msg'=>'请选择删除项']);
}
if (Node::destroy($ids)){
return Response::json(['code'=>0,'msg'=>'删除成功']);
}
return Response::json(['code'=>1,'msg'=>'删除失败']);
}
}

View File

@@ -1,258 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Project\ProjectRequest;
use App\Models\Node;
use App\Models\Order;
use App\Models\OrderFollow;
use App\Models\Project;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
class OrderController extends Controller
{
/**
* 项目列表
* @return \Illuminate\Contracts\View\View
*/
public function index()
{
$nodes = Node::where('type',2)->orderBy('sort','asc')->get();
$merchants = User::where('id','!=',config('freeswitch.user_root_id'))->get();
return View::make('admin.order.index',compact('nodes','merchants'));
}
public function data(Request $request)
{
$user = Auth::user();
$data = $request->all([
'name',
'phone',
'follow_user_id',
'created_user_id',
'node_id',
'follow_at_start',
'follow_at_end',
'next_follow_at_start',
'next_follow_at_end',
'created_at_start',
'created_at_end',
]);
$res = Order::with(['node','followUser','createUser','acceptUser'])
->where(function ($query) use($user){
if ($user->hasPermissionTo('crm.order.list_all')) {
//return $query->where('backend_owner_user_id','>',0);
}elseif ($user->hasPermissionTo('crm.order.list_department')) {
$user_ids = User::where('department_id',$user->department_id)->pluck('id')->toArray();
return $query->whereIn('accept_user_id',$user_ids);
}else{
return $query->where('accept_user_id',$user->id);
}
})
//姓名
->when($data['name'],function ($query) use($data){
return $query->where('name',$data['name']);
})
//联系电话
->when($data['phone'],function ($query) use($data){
return $query->where('phone',$data['phone']);
})
//节点
->when($data['node_id'],function ($query) use($data){
return $query->where('node_id',$data['node_id']);
})
//跟进时间
->when($data['follow_at_start']&&!$data['follow_at_end'],function ($query) use($data){
return $query->where('follow_at','>=',$data['follow_at_start']);
})
->when(!$data['follow_at_start']&&$data['follow_at_end'],function ($query) use($data){
return $query->where('follow_at','<=',$data['follow_at_end']);
})
->when($data['follow_at_start']&&$data['follow_at_end'],function ($query) use($data){
return $query->whereBetween('follow_at',[$data['follow_at_start'],$data['follow_at_end']]);
})
//下次跟进时间
->when($data['next_follow_at_start']&&!$data['next_follow_at_end'],function ($query) use($data){
return $query->where('next_follow_at','>=',$data['next_follow_at_start']);
})
->when(!$data['next_follow_at_start']&&$data['next_follow_at_end'],function ($query) use($data){
return $query->where('next_follow_at','<=',$data['next_follow_at_end']);
})
->when($data['next_follow_at_start']&&$data['next_follow_at_end'],function ($query) use($data){
return $query->whereBetween('next_follow_at',[$data['next_follow_at_start'],$data['next_follow_at_end']]);
})
//创建时间
->when($data['created_at_start']&&!$data['created_at_end'],function ($query) use($data){
return $query->where('created_at','>=',$data['created_at_start']);
})
->when(!$data['created_at_start']&&$data['created_at_end'],function ($query) use($data){
return $query->where('created_at','<=',$data['created_at_end']);
})
->when($data['created_at_start']&&$data['created_at_end'],function ($query) use($data){
return $query->whereBetween('created_at',[$data['created_at_start'],$data['created_at_end']]);
})
//成单人
->when($data['created_user_id'],function ($query) use($data){
return $query->where('created_user_id',$data['created_user_id']);
})
//跟进人
->when($data['follow_user_id'],function ($query) use($data){
return $query->where('follow_user_id',$data['follow_user_id']);
})
->orderBy('accept_user_id','asc')
->orderBy('follow_at','desc')
->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items()
];
return Response::json($data);
}
/**
* 删除
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function destroy(Request $request)
{
$ids = $request->get('ids',[]);
$id = $ids[0];
DB::beginTransaction();
try{
DB::table('order')->where('id',$id)->update([
'deleted_at' => Carbon::now(),
]);
DB::commit();
return Response::json(['code'=>0,'msg'=>'删除成功']);
}catch (\Exception $exception){
DB::rollBack();
Log::error('删除项目异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'删除失败']);
}
}
/**
* 项目详情
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function show($id)
{
$order = Order::where('id',$id)->first();
$model = Project::with('designs')->findOrFail($order->project_id);
return View::make('admin.order.show',compact('model','order'));
}
/**
* 分单
* @param Request $request
* @param $id
* @return \Illuminate\Contracts\View\View|\Illuminate\Http\JsonResponse
*/
public function send(Request $request,$id)
{
$model = Order::where('id',$id)->first();
$users = User::where('id','!=',config('freeswitch.user_root_id'))->get();
if ($request->ajax()){
$accept_user_id = $request->input('accept_user_id');
try {
Order::where('id',$id)->update([
'accept_user_id' => $accept_user_id,
'accept_time' => date('Y-m-d H:i:s'),
'accept_result' => 1,
'handle_user_id' => Auth::id(),
'handle_time' => date('Y-m-d H:i:s'),
]);
return Response::json(['code'=>0,'msg'=>'分单成功']);
}catch (\Exception $exception){
return Response::json(['code'=>1,'msg'=>'分单失败']);
}
}
return View::make('admin.order.send',compact('users','model'));
}
/**
* 跟进
* @param Request $request
* @param $id
* @return \Illuminate\Contracts\View\View|\Illuminate\Http\JsonResponse
*/
public function follow(Request $request, $id)
{
$order = Order::with('node')->where('id',$id)->first();
$nodes = Node::where('type',2)->orderBy('sort','asc')->orderBy('id','asc')->pluck('name','id')->toArray();
if ($request->ajax()){
if (!$order->accept_user_id){
return Response::json(['code'=>1,'msg'=>'未接单禁止跟进']);
}
$data = $request->all(['node_id','next_follow_at','remark']);
DB::beginTransaction();
try {
DB::table('order_follow')->insert([
'order_id' => $id,
'old_node_id' => $order->node->id??0,
'old_node_name' => $order->node->name??0,
'new_node_id' => $data['node_id'],
'new_node_name' => $nodes[$data['node_id']],
'user_id' => Auth::id(),
'user_name' => Auth::user()->nickname,
'next_follow_time' => $data['next_follow_at'],
'remark' => $data['remark'],
'created_at' => date('Y-m-d H:i:s'),
]);
DB::table('order')->where('id',$id)->update([
'node_id' => $data['node_id'],
'follow_at' => date('Y-m-d H:i:s'),
'follow_user_id' => Auth::id(),
'next_follow_at' => $data['next_follow_at'],
'remark' => $data['remark'],
]);
DB::commit();
return Response::json(['code'=>0,'msg'=>'跟进成功']);
}catch (\Exception $exception){
DB::rollBack();
return Response::json(['code'=>1,'msg'=>'跟进失败']);
}
}
return View::make('admin.order.follow',compact('order','nodes'));
}
/**
* 跟进列表
* @param Request $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function followList(Request $request, $id)
{
$res = OrderFollow::query()
->orderBy('created_at','desc')
->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items()
];
return Response::json($data);
}
}

View File

@@ -1,122 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\Admin\Permission\StoreRequest;
use App\Http\Requests\Admin\Permission\UpdateRequest;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
use App\Models\Permission;
class PermissionController extends Controller
{
/**
* 权限列表
* @param Request $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Http\JsonResponse
*/
public function index(Request $request)
{
if ($request->ajax()){
$res = Permission::orderBy('sort','asc')->orderBy('id','desc')->get();
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->count(),
'data' => $res
];
return Response::json($data);
}
return View::make('admin.permission.index');
}
/**
* 添加权限
* @return \Illuminate\Contracts\View\View
*/
public function create()
{
$permissions = Permission::with('childs')->where('parent_id', 0)->get();
return View::make('admin.permission.create', compact('permissions'));
}
/**
* 添加权限
* @param StoreRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function store(StoreRequest $request)
{
$data = $request->all(['name','display_name','sort','parent_id']);
try {
Permission::create($data);
return Response::json(['code'=>0,'msg'=>'添加成功']);
} catch (\Exception $exception) {
Log::error('添加权限异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'添加失败']);
}
}
/**
* 更新权限
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function edit($id)
{
$permission = Permission::findOrFail($id);
$permissions = Permission::with('childs')->where('parent_id', 0)->get();
return View::make('admin.permission.edit', compact('permission', 'permissions'));
}
/**
* 更新权限
* @param UpdateRequest $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function update(UpdateRequest $request, $id)
{
$permission = Permission::findOrFail($id);
$data = $request->all(['name','display_name','sort','parent_id']);
try {
$permission->update($data);
return Response::json(['code'=>0,'msg'=>'更新成功']);
} catch (\Exception $exception) {
Log::error('更新权限异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
/**
* 删除权限
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function destroy(Request $request)
{
$ids = $request->get('ids');
if (!is_array($ids) || empty($ids)) {
return Response::json(['code' => 1, 'msg' => '请选择删除项']);
}
$permission = Permission::with('childs')->find($ids[0]);
if (!$permission) {
return Response::json(['code' => 1, 'msg' => '权限不存在']);
}
//如果有子权限,则禁止删除
if ($permission->childs->isNotEmpty()) {
return Response::json(['code' => 1, 'msg' => '存在子权限禁止删除']);
}
try {
$permission->delete();
return Response::json(['code' => 0, 'msg' => '删除成功']);
} catch (\Exception $exception) {
Log::error('删除权限异常:'.$exception->getMessage());
return Response::json(['code' => 1, 'msg' => '删除失败']);
}
}
}

View File

@@ -1,516 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Exports\ProjectExport;
use App\Http\Requests\Admin\Project\ProjectRequest;
use App\Imports\ProjectImport;
use App\Models\Node;
use App\Models\Project;
use App\Models\ProjectDesign;
use App\Models\ProjectNode;
use App\Models\ProjectRemark;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Support\Facades\Storage;
class ProjectController extends Controller
{
/**
* 项目列表
* @return \Illuminate\Contracts\View\View
*/
public function index()
{
$nodes = Node::where('type',1)->orderBy('sort','asc')->get();
$merchants = User::where('id','!=',config('freeswitch.user_root_id'))->get();
return View::make('admin.project.index',compact('nodes','merchants'));
}
public function data(Request $request)
{
$user = Auth::user();
$data = $request->all([
'name',
'phone',
'follow_user_id',
'created_user_id',
'node_id',
'follow_at_start',
'follow_at_end',
'next_follow_at_start',
'next_follow_at_end',
'created_at_start',
'created_at_end',
]);
$res = Project::with(['node','followUser'])
->where(function ($query) use($user){
if ($user->hasPermissionTo('crm.project.list_all')) {
return $query->where('owner_user_id','>',0);
}elseif ($user->hasPermissionTo('crm.project.list_department')) {
$user_ids = User::where('department_id',$user->department_id)->pluck('id')->toArray();
return $query->whereIn('owner_user_id',$user_ids);
}else{
return $query->where('owner_user_id',$user->id);
}
})
//姓名
->when($data['name'],function ($query) use($data){
return $query->where('name',$data['name']);
})
//联系电话
->when($data['phone'],function ($query) use($data){
return $query->where('phone',$data['phone']);
})
//节点
->when($data['node_id'],function ($query) use($data){
return $query->where('node_id',$data['node_id']);
})
//跟进时间
->when($data['follow_at_start']&&!$data['follow_at_end'],function ($query) use($data){
return $query->where('follow_at','>=',$data['follow_at_start']);
})
->when(!$data['follow_at_start']&&$data['follow_at_end'],function ($query) use($data){
return $query->where('follow_at','<=',$data['follow_at_end']);
})
->when($data['follow_at_start']&&$data['follow_at_end'],function ($query) use($data){
return $query->whereBetween('follow_at',[$data['follow_at_start'],$data['follow_at_end']]);
})
//下次跟进时间
->when($data['next_follow_at_start']&&!$data['next_follow_at_end'],function ($query) use($data){
return $query->where('next_follow_at','>=',$data['next_follow_at_start']);
})
->when(!$data['next_follow_at_start']&&$data['next_follow_at_end'],function ($query) use($data){
return $query->where('next_follow_at','<=',$data['next_follow_at_end']);
})
->when($data['next_follow_at_start']&&$data['next_follow_at_end'],function ($query) use($data){
return $query->whereBetween('next_follow_at',[$data['next_follow_at_start'],$data['next_follow_at_end']]);
})
//创建时间
->when($data['created_at_start']&&!$data['created_at_end'],function ($query) use($data){
return $query->where('created_at','>=',$data['created_at_start']);
})
->when(!$data['created_at_start']&&$data['created_at_end'],function ($query) use($data){
return $query->where('created_at','<=',$data['created_at_end']);
})
->when($data['created_at_start']&&$data['created_at_end'],function ($query) use($data){
return $query->whereBetween('created_at',[$data['created_at_start'],$data['created_at_end']]);
})
->orderBy('is_end','asc')
->orderBy('follow_at','desc')
->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items()
];
return Response::json($data);
}
/**
* 添加项目
* @return \Illuminate\Contracts\View\View
*/
public function create()
{
$designs = ProjectDesign::where('visiable',1)
->orderBy('sort','asc')
->get();
return View::make('admin.project.create',compact('designs'));
}
/**
* 添加项目
* @param Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(ProjectRequest $request)
{
$user = Auth::user();
$data = $request->all(['company_name','name','phone']);
$dataInfo = [];
$fields = ProjectDesign::where('visiable',1)->get();
foreach ($fields as $d){
$items = [
'project_design_id' => $d->id,
'data' => $request->get($d->field_key),
];
if ($d->field_type=='checkbox'){
if (!empty($items['data'])){
$items['data'] = implode(',',$items['data']);
}else{
$items['data'] = null;
}
}
array_push($dataInfo,$items);
}
DB::beginTransaction();
try{
$project_id = DB::table('project')->insertGetId([
'company_name' => $data['company_name'],
'name' => $data['name'],
'phone' => $data['phone'],
'created_user_id' => $user->id,
'owner_user_id' => $user->id,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
foreach ($dataInfo as $d){
DB::table('project_design_value')->insert([
'project_id' => $project_id,
'project_design_id' => $d['project_design_id'],
'data' => $d['data'],
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
]);
}
DB::commit();
return Response::json(['code'=>0,'msg'=>'添加成功']);
}catch (\Exception $exception){
DB::rollBack();
Log::info('添加项目异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'添加失败']);
}
}
/**
* 更新项目
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function edit($id)
{
$model = Project::with('designs')->findOrFail($id);
return View::make('admin.project.edit',compact('model'));
}
/**
* 更新项目
* @param ProjectRequest $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function update(ProjectRequest $request,$id)
{
$data = $request->all(['company_name','name','phone']);
$dataInfo = [];
$model = Project::with('designs')->findOrFail($id);
foreach ($model->designs as $d){
$items = [
'id' => $d->pivot->id,
'data' => $request->get($d->field_key),
];
if ($d->field_type=='checkbox'){
if (!empty($items['data'])){
$items['data'] = implode(',',$items['data']);
}else{
$items['data'] = null;
}
}
array_push($dataInfo,$items);
}
DB::beginTransaction();
try{
DB::table('project')->where('id',$id)->update([
'company_name' => $data['company_name'],
'name' => $data['name'],
'phone' => $data['phone'],
'updated_user_id' => $request->user()->id,
'updated_at' => Carbon::now(),
]);
foreach ($dataInfo as $d){
DB::table('project_design_value')->where('id',$d['id'])->update(['data'=>$d['data']]);
}
DB::commit();
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
DB::rollBack();
Log::error('更新项目异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
/**
* 删除项目
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function destroy(Request $request)
{
$ids = $request->get('ids',[]);
$id = $ids[0];
DB::beginTransaction();
try{
DB::table('project')->where('id',$id)->update([
'owner_user_id' => -1,
'deleted_user_id' => Auth::guard()->user()->id,
'deleted_at' => Carbon::now(),
]);
DB::commit();
return Response::json(['code'=>0,'msg'=>'删除成功']);
}catch (\Exception $exception){
DB::rollBack();
Log::error('删除项目异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'删除失败']);
}
}
/**
* 项目详情
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function show($id)
{
$model = Project::with('designs')->findOrFail($id);
return View::make('admin.project.show',compact('model'));
}
/**
* 更新节点
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function node($id)
{
$model = Project::findOrFail($id);
$nodes = Node::orderBy('sort','asc')->get();
return View::make('admin.project.node',compact('model','nodes'));
}
/**
* 更新节点
* @param ProjectRequest $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function nodeStore(ProjectRequest $request,$id)
{
$model = Project::findOrFail($id);
$data = $request->all(['node_id','content']);
$old = $model->node_id;
$user = Auth::user();
DB::beginTransaction();
try{
DB::table('project_node')->insert([
'project_id' => $id,
'old' => $old,
'new' => $data['node_id'],
'content' => $data['content'],
'user_id' => $user->id,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
]);
DB::table('project')->where('id',$id)->update([
'node_id' => $data['node_id'],
'updated_user_id' => $user->id,
'updated_at' => Carbon::now()
]);
DB::commit();
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
DB::rollBack();
Log::info('更新节点异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
/**
* 项目的节点变更记录
* @param Request $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function nodeList(Request $request,$id)
{
$res = ProjectNode::with(['oldNode','newNode','user'])
->where('project_id',$id)
->orderByDesc('id')
->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items()
];
return Response::json($data);
}
/**
* 更新备注
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function remark($id)
{
$model = Project::findOrFail($id);
return View::make('admin.project.remark',compact('model'));
}
/**
* 更新备注
* @param ProjectRequest $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function remarkStore(ProjectRequest $request,$id)
{
$model = Project::findOrFail($id);
$data = $request->all(['next_follow_at','content']);
$user = Auth::user();
DB::beginTransaction();
try{
DB::table('project_remark')->insert([
'project_id' => $id,
'content' => $data['content'],
'next_follow_at' => $data['next_follow_at'],
'user_id' => $user->id,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
]);
DB::table('project')->where('id',$id)->update([
'next_follow_at' => $data['next_follow_at'],
'follow_at' => Carbon::now(),
'follow_user_id' => $user->id,
'updated_user_id' => $user->id,
'updated_at' => Carbon::now()
]);
DB::commit();
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
DB::rollBack();
Log::error('更新备注异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
/**
* 备注记录
* @param Request $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function remarkList(Request $request,$id)
{
$res = ProjectRemark::with(['user'])
->where('project_id',$id)
->orderByDesc('id')
->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items()
];
return Response::json($data);
}
/**
* 下载模板
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
*/
public function downloadTemplate()
{
return Excel::download(new ProjectExport(),'project.xlsx');
}
/**
* 导入项目
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function import(Request $request)
{
//上传文件最大大小,单位M
$maxSize = 10;
//支持的上传类型
$allowed_extensions = ["xls", "xlsx"];
$file = $request->file('file');
//检查文件是否上传完成
if ($file->isValid()){
//检测类型
$ext = $file->getClientOriginalExtension();
if (!in_array(strtolower($ext),$allowed_extensions)){
return Response::json(['code'=>1,'msg'=>"请上传".implode(",",$allowed_extensions)."格式的图片"]);
}
//检测大小
if ($file->getSize() > $maxSize*1024*1024){
return Response::json(['code'=>1,'msg'=>"大小限制".$maxSize."M"]);
}
}else{
Log::info('导入项目是文件上传不完整:'.$file->getErrorMessage());
return Response::json(['code'=>1,'msg'=>'文件上传不完整']);
}
$newFile = date('Y-m-d')."_".time()."_".uniqid().".".$file->getClientOriginalExtension();
try{
$res = Storage::disk('uploads')->put($newFile,file_get_contents($file->getRealPath()));
}catch (\Exception $exception){
Log::info('上传文件失败:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'文件上传失败']);
}
$xlsFile = public_path('uploads').'/'.$newFile;
try{
Excel::import(new ProjectImport(), $xlsFile);
return Response::json(['code'=>0,'msg'=>'导入成功']);
}catch (\Exception $exception){
Log::info('导入失败:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'导入失败']);
}
}
/**
* 确认成单
* @param Request $request
* @param $id
* @return \Illuminate\Contracts\View\View|\Illuminate\Http\JsonResponse
*/
public function order(Request $request,$id)
{
$model = Project::where('id',$id)->first();
$data = [
'backend_owner_user_id' => $request->input('backend_owner_user_id'),
'is_end' => 1,
];
DB::beginTransaction();
try {
DB::table('project')->where('id',$id)->update([
'is_end' => 1,
'end_time' => date('Y-m-d H:i:s'),
]);
DB::table('order')->insert([
'project_id' => $id,
'company_name' => $model->company_name,
'name' => $model->name,
'phone' => $model->phone,
'created_user_id' => $model->owner_user_id,
'created_at' => date('Y-m-d H:i:s'),
]);
DB::commit();
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
Log::error('确认成单异常:'.$exception->getMessage());
DB::rollBack();
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
}

View File

@@ -1,138 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\Admin\Project\ProjectDesignRequest;
use App\Models\ProjectDesign;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
class ProjectDesignController extends Controller
{
/**
* 项目表单设计列表
* @param Request $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Http\JsonResponse
*/
public function index(Request $request)
{
if ($request->ajax()){
$res = ProjectDesign::orderBy('sort','asc')->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items()
];
return Response::json($data);
}
return View::make('admin.project_design.index');
}
/**
* 添加字段
* @return \Illuminate\Contracts\View\View
*/
public function create()
{
return View::make('admin.project_design.create');
}
/**
* 添加字段
* @param ProjectDesignRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function store(ProjectDesignRequest $request)
{
$data = $request->all(['field_label','field_key','field_type','field_option','field_value','field_tips','sort','visiable']);
//验证field_key是否重复
$hasExisit = ProjectDesign::where('field_key',$data['field_key'])->count();
if (in_array($data['field_key'],['company_name','name','phone']) || $hasExisit){
return Response::json(['code'=>1,'msg'=>'字段Key已存在']);
}
try{
if ($data['visiable']==null){
$data['visiable'] = 2;
}
ProjectDesign::create($data);
return Response::json(['code'=>0,'msg'=>'添加成功']);
}catch (\Exception $exception){
Log::error('添加表单设计异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'添加失败']);
}
}
/**
* 更新表单设计
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function edit($id)
{
$model = ProjectDesign::findOrFail($id);
return View::make('admin.project_design.edit',compact('model'));
}
/**
* 更新表单设计
* @param ProjectDesignRequest $request
* @param $id
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
*/
public function update(ProjectDesignRequest $request,$id)
{
$model = ProjectDesign::findOrFail($id);
$data = $request->all(['field_label','field_key','field_type','field_option','field_value','field_tips','sort','visiable','required']);
//验证field_key是否重复
$hasExisit = ProjectDesign::where('field_key',$data['field_key'])->where('id','!=',$id)->count();
if (in_array($data['field_key'],['company_name','name','phone']) || $hasExisit){
return Response::json(['code'=>1,'msg'=>'字段Key已存在']);
}
if ($data['visiable']==null){
$data['visiable'] = 2;
}
if ($data['required']==null){
$data['required'] = 2;
}
try{
$model->update($data);
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
Log::error('更新表单设计异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
/**
* 删除
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function destroy(Request $request)
{
$ids = $request->get('ids');
$id = $ids[0];
//删除
DB::beginTransaction();
try{
DB::table('project_design')->where('id',$id)->delete();
DB::table('project_design_value')->where('project_design_id',$id)->delete();
DB::commit();
return Response::json(['code'=>0,'msg'=>'删除成功']);
}catch (\Exception $exception){
DB::rollBack();
Log::error('删除表单字段异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'删除失败']);
}
}
}

View File

@@ -1,170 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\Admin\Queue\QueueRequest;
use App\Models\Agent;
use App\Models\Queue;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use GuzzleHttp\Client;
class QueueController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
if ($request->ajax()){
$display_name = $request->get('display_name');
$res = Queue::withCount(['agents'])->when($display_name,function($q) use($display_name){
return $q->where('display_name','like','%'.$display_name.'%');
})->orderByDesc('id')->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items(),
];
return response()->json($data);
}
return view('admin.queue.index');
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
return view('admin.queue.create');
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(QueueRequest $request)
{
$data = $request->all();
if (Queue::create($data)){
return redirect(route('admin.queue'))->with(['success'=>'添加成功,请更新配置']);
}
return back()->withErrors(['error'=>'添加失败']);
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
$model = Queue::findOrFail($id);
return view('admin.queue.edit',compact('model'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(QueueRequest $request, $id)
{
$model = Queue::findOrFail($id);
$data = $request->except(['_method','_token']);
if ($model->update($data)){
return redirect(route('admin.queue'))->with(['success'=>'更新成功,请更新配置']);
}
return back()->withErrors(['error'=>'更新失败']);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request)
{
$ids = $request->get('ids');
if (empty($ids)){
return response()->json(['code'=>1,'msg'=>'请选择删除项']);
}
if (Queue::destroy($ids)){
return response()->json(['code'=>0,'msg'=>'删除成功,请更新配置']);
}
return response()->json(['code'=>1,'msg'=>'删除失败']);
}
/**
* 更新配置
* @return \Illuminate\Http\JsonResponse|\Psr\Http\Message\StreamInterface
*/
public function updateXml()
{
$queues = Queue::with('agents')->get();
if ($queues->isEmpty()){
return response()->json(['code'=>1,'msg'=>'无数据需要更新']);
}
$agents = Agent::get()->toArray();
try{
$client = new Client();
$res = $client->post(config('freeswitch.swoole_http_url.callcenter'),[
'form_params'=>[
'data'=>json_encode(['queues'=>$queues->toArray(),'agents'=>$agents]),
],
'timeout'=>30
]);
return response()->json(json_decode($res->getBody(),true));
}catch (\Exception $exception){
return response()->json(['code'=>1,'msg'=>'更新失败','data'=>$exception->getMessage()]);
}
}
/**
* 分配坐席
* @param $id
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function agent($id)
{
$queue = Queue::with('agents')->findOrFail($id);
$agents = Agent::orderByDesc('id')->get();
return view('admin.queue.agent',compact('queue','agents'));
}
public function assignAgent(Request $request,$id)
{
$queue = Queue::with('agents')->findOrFail($id);
$names = $request->get('agents',[]);
if ($queue->agents()->sync($names)){
return redirect(route('admin.queue'))->with(['success'=>'更新成功']);
}
return back()->withErrors(['error'=>'更新失败']);
}
}

View File

@@ -1,68 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Models\User;
use App\Models\Node;
use App\Models\Project;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
class RemindController extends Controller
{
/**
* 跟进提醒列表
* @return \Illuminate\Contracts\View\View
*/
public function index()
{
return View::make('admin.remind.index');
}
public function data(Request $request)
{
// 1 今日待跟进, 2 超期待跟进
$type = $request->get('type',1);
$model = Project::query()
->where('owner_user_id',$request->user()->id)
->whereNotNull('next_follow_at');
if ($type==1){
$model = $model->whereBetween('next_follow_at',[Carbon::today(),Carbon::tomorrow()]);
}elseif ($type==2){
$model = $model->where('next_follow_at','<',Carbon::now());
}
$res = $model->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items()
];
return Response::json($data);
}
/**
* 各节点分布
* @return \Illuminate\Http\JsonResponse
*/
public function count()
{
$data = [];
$nodes = Node::with('projects')->orderBy('sort','asc')->get();
foreach ($nodes as $node){
$data[$node->name] = $node->projects->count();
}
return Response::json([
'code' => 0,
'msg' => '请求成功',
'data' => $data,
]);
}
}

View File

@@ -1,157 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\Admin\Role\StoreRequest;
use App\Http\Requests\Admin\Role\UpdateRequest;
use App\Models\Permission;
use App\Models\Role;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
class RoleController extends Controller
{
/**
* 角色列表
* @param Request $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Http\JsonResponse
*/
public function index(Request $request)
{
if ($request->ajax()){
$res = Role::where('id','!=',config('freeswitch.role_root_id'))->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items()
];
return Response::json($data);
}
return View::make('admin.role.index');
}
/**
* 添加角色
* @return \Illuminate\Contracts\View\View
*/
public function create()
{
return View::make('admin.role.create');
}
/**
* 添加角色
* @param StoreRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function store(StoreRequest $request)
{
$data = $request->only(['name','display_name']);
try{
Role::create($data);
return Response::json(['code'=>0,'msg'=>'添加成功']);
}catch (\Exception $exception){
Log::error('添加角色异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'添加失败']);
}
}
/**
* 更新角色
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function edit($id)
{
$role = Role::findOrFail($id);
return View::make('admin.role.edit',compact('role'));
}
/**
* 更新角色
* @param UpdateRequest $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function update(UpdateRequest $request, $id)
{
$role = Role::findOrFail($id);
$data = $request->only(['name','display_name']);
try{
$role->update($data);
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
Log::error('更新角色异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
/**
* 删除角色
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function destroy(Request $request)
{
$ids = $request->get('ids');
if (!is_array($ids) || empty($ids)){
return Response::json(['code'=>1,'msg'=>'请选择删除项']);
}
try{
Role::destroy($ids);
return Response::json(['code'=>0,'msg'=>'删除成功']);
}catch (\Exception $exception){
Log::error('删除角色异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'删除失败']);
}
}
/**
* 分配权限
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function permission($id)
{
$role = Role::findOrFail($id);
$permissions = Permission::with('childs')->where('guard_name',$role->guard_name)->where('parent_id',0)->get();
foreach ($permissions as $p1){
$p1->own = $role->hasPermissionTo($p1->id) ? 'checked' : false ;
if ($p1->childs->isNotEmpty()){
foreach ($p1->childs as $p2){
$p2->own = $role->hasPermissionTo($p2->id) ? 'checked' : false ;
if ($p2->childs->isNotEmpty()){
foreach ($p2->childs as $p3){
$p3->own = $role->hasPermissionTo($p3->id) ? 'checked' : false ;
}
}
}
}
}
return View::make('admin.role.permission',compact('role','permissions'));
}
/**
* 存储权限
* @param Request $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function assignPermission(Request $request,$id)
{
$role = Role::findOrFail($id);
$permissions = $request->get('permissions',[]);
try{
$role->syncPermissions($permissions);
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
Log::error('更新角色权限异常:'.$exception->getMessage());
return Response::json(['code'=>0,'msg'=>'更新失败']);
}
}
}

View File

@@ -1,243 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\Sip\SipListRequest;
use App\Http\Requests\Sip\SipRequest;
use App\Models\Sip;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Response;
use GuzzleHttp\Client;
use App\Models\Gateway;
class SipController extends Controller
{
/**
* 分机列表
* @param Request $request
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\JsonResponse|\Illuminate\View\View
*/
public function index(Request $request)
{
if ($request->ajax()){
$query = Sip::query();
$username = $request->get('username');
if ($username){
$query = $query->where('username',$username);
}
$res = $query->orderByDesc('id')->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items(),
];
return response()->json($data);
}
return view('admin.sip.index');
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
$gateways = Gateway::select(['id','name'])->get();
return view('admin.sip.create',compact('gateways'));
}
/**
* @param SipRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function store(SipRequest $request)
{
$data = $request->all([
'gateway_id',
'username',
'password',
'effective_caller_id_name',
'effective_caller_id_number',
'outbound_caller_id_name',
'outbound_caller_id_number',
]);
if ($data['effective_caller_id_name']==null){
$data['effective_caller_id_name'] = $data['username'];
}
if ($data['effective_caller_id_number']==null){
$data['effective_caller_id_number'] = $data['username'];
}
try{
Sip::create($data);
return Response::json(['code'=>0,'msg'=>'添加成功']);
}catch (\Exception $exception){
Log::error('添加分机异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'添加失败']);
}
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
$model = Sip::findOrFail($id);
$gateways = Gateway::select(['id','name'])->get();
return view('admin.sip.edit',compact('model','gateways'));
}
/**
* @param SipRequest $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function update(SipRequest $request, $id)
{
$model = Sip::findOrFail($id);
$data = $request->all([
'gateway_id',
'username',
'password',
'effective_caller_id_name',
'effective_caller_id_number',
'outbound_caller_id_name',
'outbound_caller_id_number',
]);
if ($data['effective_caller_id_name']==null){
$data['effective_caller_id_name'] = $data['username'];
}
if ($data['effective_caller_id_number']==null){
$data['effective_caller_id_number'] = $data['username'];
}
try{
$model->update($data);
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
Log::error('更新分机异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request)
{
$ids = $request->get('ids');
if (empty($ids)){
return response()->json(['code'=>1,'msg'=>'请选择删除项']);
}
if (Sip::destroy($ids)){
return response()->json(['code'=>0,'msg'=>'删除成功']);
}
return response()->json(['code'=>1,'msg'=>'删除失败']);
}
public function createList()
{
$gateways = Gateway::select(['id','name'])->get();
return view('admin.sip.create_list',compact('gateways'));
}
public function storeList(SipListRequest $request)
{
$data = $request->all(['sip_start','sip_end','password','gateway_id']);
if ($data['sip_start'] <= $data['sip_end']){
//开启事务
DB::beginTransaction();
try{
for ($i=$data['sip_start'];$i<=$data['sip_end'];$i++){
DB::table('sip')->insert([
'gateway_id' => $data['gateway_id'],
'username' => $i,
'password' => $data['password'],
'effective_caller_id_name' => $i,
'effective_caller_id_number' => $i,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
]);
}
DB::commit();
return Response::json(['code'=>0,'msg'=>'添加成功']);
}catch (\Exception $exception) {
DB::rollback();
Log::error('批量添加分机异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'添加失败']);
}
}
return Response::json(['code'=>1,'msg'=>'开始分机号必须小于等于结束分机号']);
}
/**
* 更新配置
* @return \Illuminate\Http\JsonResponse
*/
public function updateXml(){
$sips = DB::table('sip')->get()->toArray();
if (empty($sips)){
return response()->json(['code'=>1,'msg'=>'无数据需要更新']);
}
try{
$client = new Client();
$res = $client->post(config('freeswitch.swoole_http_url.directory'),['form_params'=>['data'=>json_encode($sips)],'timeout'=>30]);
return response()->json(json_decode($res->getBody(),true));
}catch (\Exception $exception){
return response()->json(['code'=>1,'msg'=>'更新失败','data'=>$exception->getMessage()]);
}
}
/**
* 切换网关
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function updateGatewayForm(){
$gateways = Gateway::get();
return view('admin.sip.update_gateway',compact('gateways'));
}
public function updateGateway(Request $request){
$data = $request->all(['gateway_id','content']);
if (preg_match('/(\d{4,5})-(\d{4,5})/', $data['content'],$arr)) { //区间
if ((int)$arr[1] <= (int)$arr[2]) {
try{
Sip::where('username','>=',$arr[1])->where('username','<=',$arr[2])->update(['gateway_id'=>$data['gateway_id']]);
return response()->json(['code'=>0,'msg'=>'更新成功']);
}catch(\Exception $e){
return response()->json(['code'=>1,'msg'=>'更新失败','data'=>$e->getMessage()]);
}
}else{
return response()->json(['code'=>1,'msg'=>'参数不合法']);
}
}elseif(strpos($data['content'], ",")!==false){ //多个
$arr = explode(",",$data['content']);
try{
Sip::whereIn('username',$arr)->update(['gateway_id'=>$data['gateway_id']]);
return response()->json(['code'=>0,'msg'=>'更新成功']);
}catch(\Exception $e){
return response()->json(['code'=>1,'msg'=>'更新失败','data'=>$e->getMessage()]);
}
}else{ //单个
try{
Sip::where('username',$data['content'])->update(['gateway_id'=>$data['gateway_id']]);
return response()->json(['code'=>0,'msg'=>'更新成功']);
}catch(\Exception $e){
return response()->json(['code'=>1,'msg'=>'更新失败','data'=>$e->getMessage()]);
}
}
}
}

View File

@@ -1,269 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\Admin\Task\TaskRequest;
use App\Models\Agent;
use App\Models\Call;
use App\Models\Gateway;
use App\Models\Queue;
use App\Models\Task;
use Carbon\Carbon;
use Faker\Provider\Uuid;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use DB;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Storage;
use Log;
use Illuminate\Support\Facades\Redis;
class TaskController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
if ($request->ajax()){
$res = Task::orderByDesc('id')->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items(),
];
return response()->json($data);
}
return view('admin.task.index');
}
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
$queues = Queue::orderByDesc('id')->get();
$gateways = Gateway::orderByDesc('id')->get();
return view('admin.task.create',compact('queues','gateways'));
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(TaskRequest $request)
{
$data = $request->except(['_method','_token']);
if (Task::create($data)){
return redirect(route('admin.task'))->with(['success'=>'添加成功']);
}
return back()->withErrors(['error'=>'添加失败']);
}
/**
* Display the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function show(Request $request, $id)
{
$task = Task::withCount(['calls','hasCalls','missCalls','successCalls','failCalls'])->findOrFail($id);
$percent = $task->calls_count>0?100*round(($task->has_calls_count)/($task->calls_count),4).'%':'0.00%';
if ($request->isMethod('post')){
$tiers = DB::table('queue_agent')->where('queue_id',$task->queue_id)->pluck('agent_id');
$agents = Agent::whereIn('id',$tiers)->get();
return response()->json(['code'=>0, 'msg'=>'请求成功', 'data'=>$agents]);
}
return view('admin.task.show',compact('task','percent'));
}
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
$model = Task::findOrFail($id);
$queues = Queue::orderByDesc('id')->get();
$gateways = Gateway::orderByDesc('id')->get();
return view('admin.task.edit',compact('model', 'queues', 'gateways'));
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(TaskRequest $request, $id)
{
$data = $request->except(['_method','_token']);
$model = Task::findOrFail($id);
if ($model->update($data)){
return redirect(route('admin.task'))->with(['success'=>'更新成功']);
}
return back()->withErrors(['error'=>'更新失败']);
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy(Request $request)
{
$ids = $request->get('ids');
if (empty($ids)){
return response()->json(['code'=>1,'msg'=>'请选择删除项']);
}
if (Task::destroy($ids)){
return response()->json(['code'=>0,'msg'=>'删除成功']);
}
return response()->json(['code'=>1,'msg'=>'删除失败']);
}
public function setStatus(Request $request)
{
$ids = $request->get('ids',[]);
if (count($ids)!=1){
return response()->json(['code'=>1,'msg'=>'请选择一条记录']);
}
$task = Task::withCount('calls')->find($ids[0]);
if ($task==null){
return response()->json(['code'=>1,'msg'=>'任务不存在']);
}
if ($task->status==3){
return response()->json(['code'=>1,'msg'=>'任务已完成,禁止操作']);
}
$status = $request->get('status',1);
if ($status==2&&$task->calls_count==0){
return response()->json(['code'=>1,'msg'=>'任务未导入号码,禁止操作']);
}
if ($status==1&&$task->status!=2){
return response()->json(['code'=>1,'msg'=>'任务未启动,禁止操作']);
}
if ($task->update(['status'=>$status])){
$key = config('freeswitch.redis_key.callcenter_task');
Redis::rPush($key,$task->id);
return response()->json(['code'=>0,'msg'=>'更新成功']);
}
return response()->json(['code'=>1,'msg'=>'更新失败']);
}
public function importCall(Request $request, $id)
{
set_time_limit(0);
$task = Task::find($id);
if ($task==null){
return response()->json(['code'=>1,'msg'=>'任务不存在']);
}
$file = $request->file('file');
if ($file->isValid()){
$allowed_extensions = ['csv'];
//上传文件最大大小,单位M 500Kb大约4万条数据
$maxSize = 1;
//检测类型
$ext = $file->getClientOriginalExtension();
if (!in_array(strtolower($ext),$allowed_extensions)){
return response()->json(['code'=>1,'msg'=>"请上传".implode(",",$allowed_extensions)."格式"]);
}
//检测大小
if ($file->getClientSize() > $maxSize*1024*1024){
return response()->json(['code'=>1,'msg'=>"图片大小限制".$maxSize."M"]);
}
//上传到七牛云
$newFile = Uuid::uuid().".".$file->getClientOriginalExtension();
try{
$disk = Storage::disk('uploads');
$disk->put($newFile,file_get_contents($file->getRealPath()));
$url = public_path('uploads').'/'.$newFile;
}catch (\Exception $exception){
return response()->json(['code'=>1,'msg'=>'文件上传失败','data'=>$exception->getMessage()]);
}
//文件内容读取
$data = [];
try{
$fp = fopen($url,"r");
while(!feof($fp))
{
$line = fgetcsv($fp);
if ($line){
foreach ($line as $phone){
array_push($data,$phone);
}
}
}
fclose($fp);
//去重,去空
$data = array_filter(array_unique($data));
}catch (\Exception $exception){
return response()->json(['code'=>1,'msg'=>'读取文件内容错误','data'=>$exception->getMessage()]);
}
//写入数据库
if (!empty($data)){
DB::beginTransaction();
try{
foreach ($data as $d){
DB::table('call')->insert([
'task_id' => $task->id,
'phone' => $d,
'created_at'=> Carbon::now(),
'updated_at'=> Carbon::now(),
]);
}
DB::commit();
return response()->json(['code'=>0,'msg'=>'导入完成']);
}catch (\Exception $exception){
DB::rollBack();
return response()->json(['code'=>1,'msg'=>'导入失败','data'=>$exception->getMessage()]);
}
}
return response()->json(['code'=>1,'msg'=>'导入数据为空']);
}
return response()->json(['code'=>1,'msg'=>'上传失败','data'=>$file->getErrorMessage()]);
}
/**
* 呼叫详情
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function calls(Request $request)
{
$data = $request->all(['task_id','phone']);
$res = Call::with('agent')
->when($data['phone'],function ($q) use($data){
return $q->where('phone','like','%'.$data['phone'].'%');
})->where('task_id',$data['task_id'])
->orderBy('id','asc')
->paginate($request->get('limit', 30));
foreach ($res->items() as $item){
$item->status_name = Arr::get(config('freeswitch.callcenter_call_status'),$item->status,'-');
}
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items(),
];
return response()->json($data);
}
}

View File

@@ -1,337 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\User\ChangePasswordRequest;
use App\Http\Requests\Admin\User\ResetPasswordRequest;
use App\Http\Requests\Admin\User\StoreRequest;
use App\Http\Requests\Admin\User\UpdateRequest;
use App\Models\Department;
use App\Models\Menu;
use App\Models\Permission;
use App\Models\Role;
use App\Models\Sip;
use App\Models\User;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
class UserController extends Controller
{
use AuthenticatesUsers;
public $redirectTo = '/admin';
/**
* 用户登录表单
* @return \Illuminate\Contracts\View\View
*/
public function showLoginForm()
{
return View::make('admin.user.login');
}
/**
* 验证登录字段
* @param Request $request
* @throws \Illuminate\Validation\ValidationException
*/
protected function validateLogin(Request $request)
{
$this->validate($request, [
'captcha' => 'required|captcha',
$this->username() => 'required|string',
'password' => 'required|string',
]);
}
/**
* 退出后的动作
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
protected function loggedOut()
{
Session::forget('menus');
return Redirect::route('admin.user.login');
}
/**
* Get the guard to be used during authentication.
*
* @return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return Auth::guard();
}
protected function authenticated(Request $request, $user)
{
$user->update([
'last_login_at' => date('Y-m-d H:i:s'),
'last_login_ip' => $request->ip(),
]);
$menus = $user->menus();
Session::put('menus',$menus);
}
/**
* 用于登录的字段
* @return string
*/
public function username()
{
return 'phone';
}
/**
* 更改密码
* @return \Illuminate\Contracts\View\View
*/
public function changeMyPasswordForm()
{
return View::make('admin.user.changeMyPassword');
}
/**
* 修改自己的密码
* @param ChangePasswordRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function changeMyPassword(ChangePasswordRequest $request)
{
$data = $request->all(['old_password','new_password']);
//验证原密码
if (!Hash::check($data['old_password'],$request->user()->getAuthPassword())){
return Response::json(['code'=>1,'msg'=>'原密码不正确']);
}
try{
$request->user()->fill(['password' => $data['new_password']])->save();
return Response::json(['code'=>0,'msg'=>'密码修改成功']);
}catch (\Exception $exception){
Log::error('修改密码异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'修改失败']);
}
}
/**
* 用户列表主页
* @param Request $request
* @return \Illuminate\Contracts\View\View|\Illuminate\Http\JsonResponse
*/
public function index(Request $request)
{
if ($request->ajax()){
$res = User::with(['department','sip'])
->where('id','!=',config('freeswitch.user_root_id'))
->orderByDesc('id')
->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items()
];
return Response::json($data);
}
return View::make('admin.user.index');
}
/**
* 添加用户
* @return \Illuminate\Contracts\View\View
*/
public function create()
{
$departments = Department::with('childs')->where('parent_id',0)->get();
$user_sip = User::whereNotNull('sip_id')->pluck('sip_id')->toArray();
$sips = Sip::get();
return View::make('admin.user.create',compact('departments','user_sip','sips'));
}
/**
* 添加用户
* @param StoreRequest $request
* @return \Illuminate\Http\JsonResponse
*/
public function store(StoreRequest $request)
{
$data = $request->all(['phone','nickname','password','department_id','sip_id']);
try{
User::create($data);
return Response::json(['code'=>0,'msg'=>'添加成功']);
}catch (\Exception $exception){
Log::error('添加用户异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'添加失败']);
}
}
/**
* 更新用户
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function edit($id)
{
$user = User::findOrFail($id);
$departments = Department::with('childs')->where('parent_id',0)->get();
$user_sip = User::whereNotNull('sip_id')->pluck('sip_id')->toArray();
$sips = Sip::get();
return View::make('admin.user.edit',compact('user','departments','user_sip','sips'));
}
/**
* 更新用户
* @param UpdateRequest $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function update(UpdateRequest $request, $id)
{
$user = User::findOrFail($id);
$data = $request->all(['phone','nickname','department_id','sip_id']);
try{
$user->update($data);
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
Log::error('更新用户信息异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
/**
* 重置用户密码表单
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function resetPasswordForm($id)
{
$user = User::findOrFail($id);
return View::make('admin.user.resetPassword',compact('user'));
}
/**
* 重置用户密码
* @param ResetPasswordRequest $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function resetPassword(ResetPasswordRequest $request,$id)
{
$user = User::findOrFail($id);
$data = $request->all(['new_password']);
try{
$user->update(['password'=>$data['new_password']]);
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
Log::error('重置用户密码异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
/**
* 删除用户
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function destroy(Request $request)
{
$ids = $request->input('ids');
if (!is_array($ids) || empty($ids)){
return Response::json(['code'=>1,'msg'=>'请选择删除项']);
}
try{
User::destroy($ids);
return Response::json(['code'=>0,'msg'=>'删除成功']);
}catch (\Exception $exception){
Log::error('删除用户异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'删除失败']);
}
}
/**
* 分配角色
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function role($id)
{
$user = User::findOrFail($id);
$roles = Role::where('id','!=',config('freeswitch.role_root_id'))->get();
foreach ($roles as $role){
$role->own = $user->hasRole($role) ? true : false;
}
return View::make('admin.user.role',compact('roles','user'));
}
/**
* 分配角色
* @param Request $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function assignRole(Request $request,$id)
{
$user = User::findOrFail($id);
$roles = $request->get('roles',[]);
try{
$user->syncRoles($roles);
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
Log::error('为用户分配角色异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
/**
* 分配直接权限
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function permission($id)
{
$user = User::findOrFail($id);
$permissions = Permission::with('childs')->where('parent_id',0)->get();
foreach ($permissions as $p1){
$p1->own = $user->hasDirectPermission($p1->id) ? 'checked' : '' ;
if ($p1->childs->isNotEmpty()){
foreach ($p1->childs as $p2){
$p2->own = $user->hasDirectPermission($p2->id) ? 'checked' : '' ;
if ($p2->childs->isNotEmpty()){
foreach ($p2->childs as $p3){
$p3->own = $user->hasDirectPermission($p3->id) ? 'checked' : '' ;
}
}
}
}
}
return View::make('admin.user.permission',compact('user','permissions'));
}
/**
* 分配直接权限
* @param Request $request
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public function assignPermission(Request $request,$id)
{
$user = User::findOrFail($id);
$permissions = $request->get('permissions',[]);
try{
$user->syncPermissions($permissions);
return Response::json(['code'=>0,'msg'=>'更新成功']);
}catch (\Exception $exception){
Log::error('为用户分配权限异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'更新失败']);
}
}
}

View File

@@ -1,99 +0,0 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Models\User;
use App\Models\Project;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Str;
class WasteController extends Controller
{
/**
* 公海库列表
* @return \Illuminate\Contracts\View\View
*/
public function index()
{
return View::make('admin.waste.index');
}
public function data(Request $request)
{
$data = $request->all(['company_name','name','phone']);
$res = Project::onlyTrashed()
->where('owner_user_id',-1)
//公司名称
->when($data['company_name'],function ($query) use($data){
return $query->where('company_name',$data['company_name']);
})
//姓名
->when($data['name'],function ($query) use($data){
return $query->where('name',$data['name']);
})
//联系电话
->when($data['phone'],function ($query) use($data){
return $query->where('phone',$data['phone']);
})
->orderBy('deleted_at','desc')
->paginate($request->get('limit', 30));
$data = [
'code' => 0,
'msg' => '正在请求中...',
'count' => $res->total(),
'data' => $res->items()
];
return Response::json($data);
}
/**
* 拾回
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function retrieve(Request $request)
{
$id = $request->get('id');
$project = Project::onlyTrashed()
->where('id',$id)
->first();
if (!$project){
return Response::json(['code'=>1,'msg'=>'拾回异常:项目不存在']);
}
DB::beginTransaction();
try{
DB::table('project')->where('id',$id)->update([
'deleted_user_id' => null,
'deleted_at' => null,
'owner_user_id' => $request->user()->id,
]);
DB::commit();
return Response::json(['code'=>0,'msg'=>'拾回成功']);
}catch (\Exception $exception){
DB::rollBack();
Log::info('拾回异常:'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'拾回失败']);
}
}
/**
* 项目详情
* @param $id
* @return \Illuminate\Contracts\View\View
*/
public function show($id)
{
$model = Project::onlyTrashed()->with('designs')->findOrFail($id);
return View::make('admin.waste.show',compact('model'));
}
}

View File

@@ -1,303 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\Audio;
use App\Models\Cdr;
use App\Models\Gateway;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
use App\Models\Sip;
use Illuminate\Support\Facades\Redis;
class ApiController extends Controller
{
//文件上传
public function upload(Request $request)
{
//上传文件最大大小,单位M
$maxSize = 10;
//支持的上传图片类型
$allowed_extensions = ["png", "jpg", "gif"];
//返回信息json
$data = ['code'=>1, 'msg'=>'上传失败', 'data'=>''];
$file = $request->file('file');
//检查文件是否上传完成
if ($file->isValid()){
//检测图片类型
$ext = $file->getClientOriginalExtension();
if (!in_array(strtolower($ext),$allowed_extensions)){
$data['msg'] = "请上传".implode(",",$allowed_extensions)."格式的图片";
return response()->json($data);
}
//检测图片大小
if ($file->getSize() > $maxSize*1024*1024){
$data['msg'] = "图片大小限制".$maxSize."M";
return response()->json($data);
}
}else{
$data['msg'] = $file->getErrorMessage();
return response()->json($data);
}
$newFile = date('Y-m-d')."_".time()."_".uniqid().".".$file->getClientOriginalExtension();
$disk = Storage::disk('uploads');
$res = $disk->put($newFile,file_get_contents($file->getRealPath()));
if($res){
$data = [
'code' => 0,
'msg' => '上传成功',
'data' => $newFile,
'url' => '/uploads/'.$newFile,
];
}else{
$data['data'] = $file->getErrorMessage();
}
return response()->json($data);
}
/**
* 拨打接口
* @param Request $request
* @return \Illuminate\Http\JsonResponse
* @throws \Exception
*/
public function dial(Request $request)
{
$data = $request->all(['exten','phone','user_data']);
if ($data['exten'] == null || $data['phone'] == null) {
return Response::json(['code'=>1,'msg'=>'号码不能为空']);
}
//验证手机号码
if (!preg_match('/\d{4,12}/', $data['phone'])) {
return Response::json(['code'=>1,'msg'=>'客户电话号码格式不正确']);
}
//检测10秒重复请求
if(Redis::get($data['exten'].'_check')!=null){
return Response::json(['code'=>1,'msg'=>'重复请求,请稍后再试']);
}else{
Redis::setex($data['exten'].'_check',10,'exist');
}
//验证分机信息
$sip = Sip::where('username',$data['exten'])->first();
if ($sip == null) {
return Response::json(['code'=>1,'msg'=>' 外呼号不存在']);
}
//验证分机是否登录
if ($sip->status == 0){
return Response::json(['code'=>1,'msg'=>'当前外呼号未登录']);
}
//呼叫字符串
$aleg_uuid = md5(\Snowflake::nextId(1).$data['exten'].$data['phone'].Redis::incr('fs_id'));
$bleg_uuid = md5(\Snowflake::nextId(2).$data['phone'].$data['exten'].Redis::incr('fs_id'));
$dialStr = "originate {origination_uuid=".$aleg_uuid."}";
$dialStr .= "{origination_caller_id_number=".$sip->username."}";
$dialStr .= "{origination_caller_id_name=".$sip->username."}";
//验证内部呼叫还是外部呼叫
$res = Sip::where('username',$data['phone'])->first();
if ($res == null) { //外部呼叫
//查询分机的网关信息
$gateway = Gateway::with('outbound')->where('id',$sip->gateway_id)->first();
if ($gateway == null) {
return Response::json(['code'=>1,'msg'=>'外呼号无可用的网关']);
}
//获取网关出局号码
$outbound = null;
if ($gateway->outbound_caller_id) {
$outbound = $gateway->outbound_caller_id;
}else{
$gw_key = 'gw'.$gateway->id.'_outbound';
if (Redis::lLen($gw_key) == 0) {
foreach ($gateway->outbound as $d) {
Redis::rPush($gw_key,$d->number);
}
}
$outbound = Redis::lPop($gw_key);
}
if ($outbound) {
$dialStr .= "{effective_caller_id_number=".$outbound."}";
$dialStr .= "{effective_caller_id_name=".$outbound."}";
}
$dialStr .= "{customer_caller=".$data['phone']."}user/".$sip->username." gw".$gateway->id."_";
//网关后缀SS
if ($gateway->prefix){
$dialStr .=$gateway->prefix;
}
$dialStr .= $data['phone']."_".$bleg_uuid;
}else{ //内部呼叫
$dialStr .="user/".$sip->username." ".$data["phone"]."_".$bleg_uuid;
}
$dialStr .=" XML default";
try{
$fs = new \Freeswitchesl();
$service = config('freeswitch.esl');
$fs->connect($service['host'],$service['port'],$service['password']);
$fs->bgapi($dialStr);
$fs->disconnect();
//写入初始记录
$user = User::where('sip_id',$sip->id)->first();
Cdr::create([
'user_id' => $user->id??0,
'uuid' => $aleg_uuid,
'aleg_uuid' => $aleg_uuid,
'bleg_uuid' => $bleg_uuid,
'src' => $data['exten'],
'dst' => $data['phone'],
'user_data' => $data['user_data'],
'aleg_start_at' => date('Y-m-d H:i:s'),
]);
//20分钟过期
Redis::setex($data['exten'].'_uuid',1200, $aleg_uuid);
return Response::json(['code'=>0,'msg'=>'呼叫成功','data'=>['uuid'=>$aleg_uuid,'time'=>date('Y-m-d H:i:s')]]);
}catch (\Exception $exception){
Log::info("呼叫错误:".$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'呼叫失败']);
}
}
/**
* 挂断
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function hangup(Request $request)
{
$exten = $request->get('exten');
$uuid = Redis::get($exten.'_uuid');
if($uuid == null){
return Response::json(['code'=>0,'msg'=>'已挂断']);
}
$sip = Sip::where('username',$exten)->first();
if ($sip == null) {
return Response::json(['code'=>1,'msg'=>' 外呼号不存在']);
}
$fs = new \Freeswitchesl();
$service = config('freeswitch.esl');
try{
if ($fs->connect($service['host'],$service['port'],$service['password'])) {
$fs->bgapi("uuid_kill",$uuid);
$fs->disconnect();
Redis::del($exten.'_uuid');
return Response::json(['code'=>0,'msg'=>'已挂断']);
}
}catch (\Exception $exception){
Log::info('ESL连接异常'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'连接异常']);
}
return Response::json(['code'=>0,'msg'=>'已挂断']);
}
/**
* 语音消息接口
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function voice(Request $request)
{
$data = $request->all(['phone','text','gateway_id']);
//验证参数
if (!preg_match('/^1[34578][0-9]{9}$/',$data['phone'])){
return Response::json(['code'=>1,'msg'=>'号码格式不正确']);
}
//验证网关信息
$gw = Gateway::find($data['gateway_id']);
if ($gw == null){
return Response::json(['code'=>1,'msg'=>'网关不存在']);
}
//合成语音
$res = (new Audio())->tts($data['text']);
if ($res['code']!=0){
return Response::json(['code'=>1,'msg'=>'语音合成失败']);
}
//呼叫
try{
$fs = new \Freeswitchesl();
$service = config('freeswitch.esl');
$fs->connect($service['host'],$service['port'],$service['password']);
$dialStr = "originate {ignore_early_media=true}";
if ($gw->outbound_caller_id){
$dialStr .= "{effective_caller_id_number=".$gw->outbound_caller_id."}";
$dialStr .= "{effective_caller_id_name=".$gw->outbound_caller_id."}";
}
$dialStr .= "sofia/gateway/gw".$gw->id."/";
if ($gw->prefix){
$dialStr .= $gw->prefix.$data['phone'];
}
$dialStr .= " &playback(".$res['path'].")";
$fs->bgapi($dialStr);
$fs->disconnect();
return Response::json(['code'=>0,'msg'=>'呼叫成功']);
}catch (\Exception $exception){
Log::info('ESL连接异常'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'呼叫异常']);
}
}
/**
* fromExten 监听分机
* toExten 被监听分机
* type 监听模式
* type: 1 客户听不到监听者说话
* type: 2 只能听
* type: 3 三方正常通话
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function chanspy(Request $request)
{
$data = $request->all(['fromExten','toExten','type']);
//验证被监听
$uuid = Redis::get($data['toExten'].'_uuid');
$toSip = Sip::where('username',$data['toExten'])->first();
if ($uuid == null || $toSip->state != 'ACTIVE'){
return Response::json(['code'=>1,'msg'=>'被监听分机未在通话中']);
}
//验证监听,是否登录
$fromSip = Sip::where('username',$data['fromExten'])->first();
if ($fromSip->status == 0){
return Response::json(['code'=>1,'msg'=>'监听分机未注册']);
}
$fs = new \Freeswitchesl();
$service = config('freeswitch.esl');
try{
$fs->connect($service['host'],$service['port'],$service['password']);
$dailStr = "originate ";
$dailStr .= "{origination_caller_id_number=".$data['fromExten']."}";
$dailStr .= "{origination_caller_id_name=".$data['fromExten']."}";
$dailStr .= "user/".$data['fromExten'];
if ($data['type']==3){
$dailStr .= " &three_way(".$uuid.")";
}elseif ($data['type']==2){
$dailStr .= " &{eavesdrop_whisper_aleg=false}{eavesdrop_whisper_bleg=false}eavesdrop(".$uuid.")";
}elseif ($data['type']==1){
$dailStr .= " &{eavesdrop_whisper_aleg=true}{eavesdrop_whisper_bleg=false}eavesdrop(".$uuid.")";
}else{
return Response::json(['code'=>1,'msg'=>'监听模式错误']);
}
$fs->bgapi($dailStr);
return Response::json(['code'=>0,'msg'=>'监听成功']);
}catch (\Exception $exception){
Log::info('监听ESL连接异常'.$exception->getMessage());
return Response::json(['code'=>1,'msg'=>'连接异常']);
}
}
}

View File

@@ -1,13 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}

View File

@@ -1,85 +0,0 @@
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array
*/
protected $middleware = [
\App\Http\Middleware\TrustProxies::class,
\App\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
];
/**
* The priority-sorted list of middleware.
*
* This forces non-global middleware to always be in the given order.
*
* @var array
*/
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];
}

View File

@@ -1,22 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Support\Facades\URL;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*
* @param \Illuminate\Http\Request $request
* @return string|null
*/
protected function redirectTo($request)
{
if (! $request->expectsJson()) {
return URL::route('admin.user.login');
}
}
}

View File

@@ -1,17 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode as Middleware;
class CheckForMaintenanceMode extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array
*/
protected $except = [
//
];
}

View File

@@ -1,17 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array
*/
protected $except = [
//
];
}

View File

@@ -1,27 +0,0 @@
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
* @return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
return $next($request);
}
}

View File

@@ -1,18 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
class TrimStrings extends Middleware
{
/**
* The names of the attributes that should not be trimmed.
*
* @var array
*/
protected $except = [
'password',
'password_confirmation',
];
}

View File

@@ -1,23 +0,0 @@
<?php
namespace App\Http\Middleware;
use Fideloper\Proxy\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array|string
*/
protected $proxies;
/**
* The headers that should be used to detect proxies.
*
* @var int
*/
protected $headers = Request::HEADER_X_FORWARDED_ALL;
}

View File

@@ -1,24 +0,0 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* Indicates whether the XSRF-TOKEN cookie should be set on the response.
*
* @var bool
*/
protected $addHttpCookie = true;
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array
*/
protected $except = [
//
];
}

View File

@@ -1,49 +0,0 @@
<?php
namespace App\Http\Requests\Admin\Agent;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class AgentRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'display_name' => 'required',
'originate_type' => 'required',
'originate_number' => 'required',
];
}
public function attributes()
{
return [
'display_name' => '坐席名称',
'originate_type' => '呼叫类型',
'originate_number' => '呼叫号码',
];
}
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(['code'=>1,'msg'=>$validator->errors()->first()]));
}
}

View File

@@ -1,51 +0,0 @@
<?php
namespace App\Http\Requests\Admin\Gateway;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class GatewayRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required',
'realm' => 'required',
'username' => 'required',
'password' => 'required',
];
}
public function attributes()
{
return [
'name' => '网关名称',
'realm' => '地址',
'username' => '帐号',
'password' => '密码',
];
}
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(['code'=>1,'msg'=>$validator->errors()->first()]));
}
}

View File

@@ -1,39 +0,0 @@
<?php
namespace App\Http\Requests\Admin\Menu;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class StoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required',
'parent_id' => 'required',
'sort' => 'required|numeric',
'type' => 'required|in:1,2',
];
}
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(['code'=>1,'msg'=>$validator->errors()->first()]));
}
}

View File

@@ -1,40 +0,0 @@
<?php
namespace App\Http\Requests\Admin\Menu;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class UpdateRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required',
'parent_id' => 'required',
'sort' => 'required|numeric',
'type' => 'required|in:1,2',
];
}
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(['code'=>1,'msg'=>$validator->errors()->first()]));
}
}

View File

@@ -1,39 +0,0 @@
<?php
namespace App\Http\Requests\Admin\Permission;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class StoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name'=>'required|unique:permissions,name,'.$this->id.',id|max:200',
'display_name' => 'required',
'sort' => 'required|numeric',
];
}
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(['code'=>1,'msg'=>$validator->errors()->first()]));
}
}

View File

@@ -1,39 +0,0 @@
<?php
namespace App\Http\Requests\Admin\Permission;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class UpdateRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name'=>'required|unique:permissions,name,'.$this->id.',id|max:200',
'display_name' => 'required',
'sort' => 'required|numeric',
];
}
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(['code'=>1,'msg'=>$validator->errors()->first()]));
}
}

View File

@@ -1,40 +0,0 @@
<?php
namespace App\Http\Requests\Admin\Project;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class ProjectDesignRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'field_label' => 'required',
'field_key' => 'required',
'field_type' => 'required',
'sort' => 'required',
];
}
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(['code'=>1,'msg'=>$validator->errors()->first()]));
}
}

View File

@@ -1,30 +0,0 @@
<?php
namespace App\Http\Requests\Admin\Project;
use Illuminate\Foundation\Http\FormRequest;
class ProjectRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
}

View File

@@ -1,42 +0,0 @@
<?php
namespace App\Http\Requests\Admin\Queue;
use Illuminate\Foundation\Http\FormRequest;
class QueueRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'display_name' => 'required',
'strategy' => 'required',
'max_wait_time' => 'required|numeric|min:0',
];
}
public function attributes()
{
return [
'display_name' => '队列名称',
'strategy' => '振铃策略',
'max_wait_time' => '超时时间',
];
}
}

View File

@@ -1,38 +0,0 @@
<?php
namespace App\Http\Requests\Admin\Role;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class StoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required|unique:roles|max:200',
'display_name' => 'required'
];
}
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(['code'=>1,'msg'=>$validator->errors()->first()]));
}
}

View File

@@ -1,38 +0,0 @@
<?php
namespace App\Http\Requests\Admin\Role;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class UpdateRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name'=>'required|unique:roles,name,'.$this->id.',id|max:200',
'display_name' => 'required'
];
}
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(['code'=>1,'msg'=>$validator->errors()->first()]));
}
}

View File

@@ -1,50 +0,0 @@
<?php
namespace App\Http\Requests\Sip;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class SipListRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'sip_start' => 'required|numeric|min:1000',
'sip_end' => 'required|numeric',
'password' => 'required',
'gateway_id' => 'required'
];
}
public function attributes()
{
return [
'sip_start' => '开始分机',
'sip_end' => '结束分机',
'gateway_id' => '网关'
];
}
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(['code'=>1,'msg'=>$validator->errors()->first()]));
}
}

View File

@@ -1,48 +0,0 @@
<?php
namespace App\Http\Requests\Sip;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class SipRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'username' => 'required|numeric|min:1000|max:9999|unique:sip,username,'.$this->id.',id',
'password' => 'required',
'gateway_id' => 'required'
];
}
public function attributes()
{
return [
'username' => '分机号',
'gateway_id' => '网关'
];
}
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(['code'=>1,'msg'=>$validator->errors()->first()]));
}
}

View File

@@ -1,52 +0,0 @@
<?php
namespace App\Http\Requests\Admin\Task;
use Illuminate\Foundation\Http\FormRequest;
class TaskRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'name' => 'required',
'date_start' => 'required|date_format:Y-m-d|before_or_equal:date_end',
'date_end' => 'required|date_format:Y-m-d|after_or_equal:date_start',
'time_start' => 'required|date_format:H\:i\:s|before:time_end',
'time_end' => 'required|date_format:H\:i\:s|after:time_start',
'gateway_id' => 'required|exists:gateway,id',
'queue_id' => 'required|exists:queue,id',
'max_channel' => 'required|numeric|min:0',
];
}
public function attributes()
{
return [
'name' => '名称',
'date_start' => '开始日期',
'date_end' => '结束日期',
'time_start' => '开始时间',
'time_end' => '结束时间',
'gateway_id' => '网关',
'queue_id' => '队列',
'max_channel' => '最大并发',
];
}
}

View File

@@ -1,39 +0,0 @@
<?php
namespace App\Http\Requests\Admin\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class ChangePasswordRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'old_password' => 'required|string|min:6|max:14',
'new_password' => 'required|string|min:6|max:14|confirmed'
];
}
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(['code'=>1,'msg'=>$validator->errors()->first()]));
}
}

View File

@@ -1,37 +0,0 @@
<?php
namespace App\Http\Requests\Admin\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class ResetPasswordRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'new_password' => 'required|string|min:6|max:14|confirmed'
];
}
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(['code'=>1,'msg'=>$validator->errors()->first()]));
}
}

View File

@@ -1,46 +0,0 @@
<?php
namespace App\Http\Requests\Admin\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class StoreRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'phone' => 'required|numeric|regex:/^1[3456789][0-9]{9}$/|unique:users',
'nickname' => 'required|min:2|max:14|unique:users',
'password' => 'required|confirmed|min:6|max:14'
];
}
public function attributes()
{
return [
'nickname' => '昵称',
];
}
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(['code'=>1,'msg'=>$validator->errors()->first()]));
}
}

View File

@@ -1,45 +0,0 @@
<?php
namespace App\Http\Requests\Admin\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class UpdateRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'phone' => 'required|numeric|regex:/^1[34578][0-9]{9}$/|unique:users,phone,'.$this->id.',id',
'nickname' => 'required|min:2|max:14',
];
}
public function attributes()
{
return [
'nickname' => '昵称',
];
}
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json(['code'=>1,'msg'=>$validator->errors()->first()]));
}
}

View File

@@ -1,46 +0,0 @@
<?php
namespace App\Http\Requests\Admin\Dialplan;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class ActionRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'display_name' => 'required',
'application' => 'required',
'sort' => 'required|numeric|min:0|max:99',
];
}
public function attributes()
{
return [
'display_name' => '名称',
'application' => '应用',
'sort' => '序号',
];
}
}

View File

@@ -1,49 +0,0 @@
<?php
namespace App\Http\Requests\Admin\Dialplan;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class ConditionRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'display_name' => 'required',
'field' => 'required|string',
'expression' => 'required',
'break' => 'required|in:on-false,on-true,always,never',
'sort' => 'required|numeric|min:0|max:99',
];
}
public function attributes()
{
return [
'display_name' => '名称',
'field' => '字段',
'expression' => '正则',
'sort' => '序号',
];
}
}

View File

@@ -1,48 +0,0 @@
<?php
namespace App\Http\Requests\Admin\Dialplan;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
class ExtensionRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'display_name' => 'required',
'name' => 'required|string|unique:extension,name,'.$this->id.',id',
'sort' => 'required|numeric|min:0|max:99',
'continue' => 'required|string|in:true,false',
'context' => 'required|string|in:default,public'
];
}
public function attributes()
{
return [
'display_name' => '名称',
'name' => '标识符',
'sort' => '序号',
];
}
}

View File

@@ -1,21 +0,0 @@
<?php
namespace App\Imports;
use App\Models\Project;
use Illuminate\Support\Facades\Auth;
use Maatwebsite\Excel\Concerns\ToModel;
class ProjectImport implements ToModel
{
public function model(array $row)
{
return new Project([
'company_name' => $row[0],
'name' => $row[1],
'phone' => $row[2],
'created_user_id' => Auth::user()->id,
'owner_user_id' => 0,
]);
}
}

View File

@@ -1,19 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
class Action extends Model
{
protected $table = 'action';
protected $fillable = ['display_name','application','data','sort','condition_id'];
protected $appends = ['application_name'];
public function getApplicationNameAttribute()
{
return Arr::get(config('freeswitch.application'),$this->application)."".$this->application."";
}
}

View File

@@ -1,45 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
class Agent extends Model
{
protected $table = 'agent';
protected $fillable = [
'display_name',
'originate_type',
'originate_number',
'status',
'state',
'max_no_answer',
'wrap_up_time',
'reject_delay_time',
'busy_delay_time',
'no_answer_delay_time',
];
protected $appends = ['originate_type_name','status_name','state_name'];
public function getOriginateTypeNameAttribute()
{
return $this->attributes['originate_type_name'] = Arr::get([
'user' => '分机',
'group' => '分机组',
'gateway' => '网关',
],$this->originate_type,'-');
}
public function getStatusNameAttribute()
{
return $this->attributes['status_name'] = Arr::get(config('freeswitch.agent_status'),$this->status,'-');
}
public function getStateNameAttribute()
{
return $this->attributes['state_name'] = Arr::get(config('freeswitch.agent_state'),$this->state,'-');
}
}

View File

@@ -1,108 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Redis;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class Audio extends Model
{
protected $table = 'audio';
protected $fillable = ['text','url','path','user_id'];
public function getAccessToken(){
$key = 'baidu_token';
$token = Redis::get($key);
if ($token == null) {
$client = new Client();
try{
$response = $client->get(config('freeswitch.baidu.url.token'),[
'query' => [
'grant_type' => 'client_credentials',
'client_id' => config('freeswitch.baidu.appKey'),
'client_secret' => config('freeswitch.baidu.appSecret'),
]
]);
$result = json_decode($response->getBody(),true);
$token = $result['access_token'];
Redis::setex($key,$result['expires_in']-100,$token);
}catch(\Exception $exception){
$token = null;
}
}
return $token;
}
public function tts($text){
$token = $this->getAccessToken();
if ($token==null) {
return ['code'=>1,'msg'=>'获取accessToken失败'];
}
$client = new Client();
try{
$response = $client->post(config('freeswitch.baidu.url.tts'),[
'body' => http_build_query([
'tex' => urlencode($text),
'tok' => $token,
'cuid' => 'freeswitch',
'ctp' => 1,
'lan' => 'zh',
'spd' => 5, //语速0-15默认为5中语速
'pit' => 5, //音调0-15默认为5中音调
'vol' => 5, //音量0-15默认为5中音量
'aue' => 6, //3为mp3格式(默认) 4为pcm-16k5为pcm-8k6为wav内容同pcm-16k; 注意aue=4或者6是语音识别要求的格式
'per' => 0, //度小宇=1度小美=0度逍遥=3度丫丫=4 ,度博文=106度小童=110度小萌=111度米朵=103度小娇=5
])
]);
if (in_array('audio/wav',$response->getHeader('Content-Type'))){
$file_url = Str::random().'.wav';
$file_path = public_path('uploads').'/'.$file_url;
Storage::disk('uploads')->put($file_url,$response->getBody());
return ['code'=>0,'msg'=>'合成成功','data'=>['url'=>'/uploads/'.$file_url,'path'=>$file_path]];
}
return ['code'=>1,'msg'=>'合成失败','data'=>$response->getHeader('Content-Type')];
}catch(\Exception $exception){
return ['code'=>1,'msg'=>'合成异常','data'=>$exception->getMessage()];
}
}
public function asr($file){
$token = $this->getAccessToken();
if ($token==null) {
return ['code'=>1,'msg'=>'获取accessToken失败'];
}
if (!file_exists($file)) {
return ['code'=>1,'msg'=>'文件不存在'];
}
$client = new Client();
try{
$response = $client->post(config('freeswitch.baidu.url.asr'),[
'body' => base64_encode(file_get_contents($file)),
'json' => http_build_query([
'format' => 'wav',
'rate' => 16000,
'channel' => 1,
'cuid' => 'freeswitch',
'token' => $token,
'dev_pid' => 1537 //语速0-15默认为5中语速
])
]);
$result = json_decode($response->getBody(),true);
if (!$result['err_no']) {
return ['code'=>0,'msg'=>'识别成功','data'=>$result['result'][0]];
}
return ['code'=>1,'msg'=>'识别失败'];
}catch(\Exception $exception){
return ['code'=>1,'msg'=>'识别异常'];
}
}
}

View File

@@ -1,18 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Call extends Model
{
protected $table = 'call';
protected $guarded = ['id'];
public function agent()
{
return $this->hasOne('App\Models\Agent','id','agent_id')->withDefault(['display_name'=>'-']);
}
}

View File

@@ -1,11 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Cdr extends Model
{
protected $table = 'cdr';
protected $guarded = ['id'];
}

View File

@@ -1,18 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Condition extends Model
{
protected $table = 'condition';
protected $fillable = ['display_name','field','expression','break','extension_id','sort'];
protected $with = 'actions';
public function actions()
{
return $this->hasMany('App\Models\Action','condition_id','id')->orderBy('sort')->orderBy('id');
}
}

View File

@@ -1,27 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Department extends Model
{
protected $table = 'department';
protected $fillable = [
'name',
'parent_id',
];
//子部门
public function child()
{
return $this->hasMany('App\Models\Department','parent_id','id');
}
//所有子递归
public function childs()
{
return $this->child()->with('childs');
}
}

View File

@@ -1,23 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
class Extension extends Model
{
protected $table = 'extension';
protected $fillable = ['display_name','name','sort','continue','context'];
protected $appends = ['context_name'];
public function getContextNameAttribute()
{
return Arr::get(['default'=>'呼出','public'=>'呼入'],$this->context);
}
public function conditions()
{
return $this->hasMany('App\Models\Condition','extension_id','id')->orderBy('sort')->orderBy('id');
}
}

View File

@@ -1,46 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Log;
class Gateway extends Model
{
protected $table = 'gateway';
protected $fillable = ['name','realm','username','password','prefix','outbound_caller_id','rate','type'];
/**
* 查询网关状态
* @param $id
* @return string
*/
public function getStatus($id)
{
$fs = new \Freeswitchesl();
$service = config('freeswitch.esl');
try{
$fs->connect($service['host'], $service['port'], $service['password']);
$result = $fs->api("sofia status gateway gw".$id);
$data = trim($result);
if ($data=="Invalid Gateway!"){
return $data;
}
foreach (explode("\n",$data) as $item){
$itemArr = explode("\t",$item);
if (trim($itemArr[0])=="State"){
return $itemArr[1];
}
}
$fs->disconnect();
}catch (\Exception $exception){
Log::info('查询网关状态ESL连接异常'.$exception->getMessage());
return '连接失败';
}
}
//出局号码
public function outbound(){
return $this->hasMany('App\Models\GatewayOutbound','gateway_id','id');
}
}

View File

@@ -1,25 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class GatewayOutbound extends Model
{
protected $table = 'gateway_outbound';
protected $fillable = [
'gateway_id',
'status',
'number',
];
/**
* 所属网关
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function gateway()
{
return $this->hasOne('App\Models\Gateway','id','gateway_id')->withDefault([]);
}
}

View File

@@ -1,33 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Menu extends Model
{
protected $table = 'menu';
protected $fillable = [
'name',
'parent_id',
'route',
'url',
'icon',
'sort',
'type',
'permission_id',
];
//子权限
public function child()
{
return $this->hasMany('App\Models\Menu','parent_id','id');
}
//所有子权限递归
public function childs()
{
return $this->child()->with('childs');
}
}

View File

@@ -1,31 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
class Node extends Model
{
protected $table = 'node';
protected $fillable = [
'name',
'sort',
'type',
];
protected $appends = ['type_name'];
public function getTypeNameAttribute()
{
return $this->attributes['type_name'] = Arr::get([1=>'前台',2=>'后台'],$this->type,'-');
}
/**
* 节点所有的项目
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function projects()
{
return $this->hasMany('App\Models\Project','node_id','id');
}
}

View File

@@ -1,66 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Order extends Model
{
use SoftDeletes;
protected $table = 'order';
protected $fillable = [
'company_name',
'name',
'phone',
'project_id',
'node_id',
'created_user_id',
'handle_user_id',
'handle_time',
'accept_user_id',
'accept_time',
'accept_result',
'follow_at',
'follow_user_id',
'next_follow_at',
'remark',
];
/**
* 当前节点
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function node()
{
return $this->hasOne('App\Models\Node','id','node_id')->withDefault(['name'=>'-']);
}
/**
* 成单人
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function createUser()
{
return $this->hasOne('App\Models\User','id','created_user_id')->withDefault(['nickname'=>'-']);
}
/**
* 接单人
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function acceptUser()
{
return $this->hasOne('App\Models\User','id','accept_user_id')->withDefault(['nickname'=>'-']);
}
/**
* 跟进人
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function followUser()
{
return $this->hasOne('App\Models\User','id','follow_user_id')->withDefault(['nickname'=>'-']);
}
}

View File

@@ -1,11 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class OrderFollow extends Model
{
protected $table = 'order_follow';
protected $guarded = ['id'];
}

View File

@@ -1,19 +0,0 @@
<?php
namespace App\Models;
class Permission extends \Spatie\Permission\Models\Permission
{
//子权限
public function child()
{
return $this->hasMany('App\Models\Permission','parent_id','id');
}
//所有子权限递归
public function childs()
{
return $this->child()->with('childs');
}
}

View File

@@ -1,57 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Project extends Model
{
use SoftDeletes;
protected $table = 'project';
protected $fillable = [
'company_name',
'name',
'phone',
'node_id',
'follow_at',
'follow_user_id',
'next_follow_at',
'created_user_id',
'updated_user_id',
'deleted_user_id',
'owner_user_id',
'is_end',
];
/**
* 表单字段
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function designs()
{
return $this->belongsToMany('App\Models\ProjectDesign','project_design_value','project_id','project_design_id')
->where('visiable',1)
->orderBy('sort','asc')
->withPivot(['id','data']);
}
/**
* 当前节点
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function node()
{
return $this->hasOne('App\Models\Node','id','node_id')->withDefault(['name'=>'-']);
}
/**
* 跟进人
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function followUser()
{
return $this->hasOne('App\Models\User','id','follow_user_id')->withDefault(['nickname'=>'-']);
}
}

View File

@@ -1,29 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
class ProjectDesign extends Model
{
protected $table = 'project_design';
protected $fillable = [
'field_label',
'field_key',
'field_type',
'field_option',
'field_value',
'field_tips',
'sort',
'visiable',
'required',
];
protected $appends = ['field_type_name'];
public function getFieldTypeNameAttribute($value)
{
return Arr::get(config('freeswitch.field_type'),$this->field_type,'-');
}
}

View File

@@ -1,26 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ProjectNode extends Model
{
protected $table = 'project_node';
public function oldNode()
{
return $this->hasOne('App\Models\Node','id','old')->withDefault(['name'=>'-']);
}
public function newNode()
{
return $this->hasOne('App\Models\Node','id','new')->withDefault(['name'=>'-']);
}
public function user()
{
return $this->hasOne('App\Models\User','id','user_id')->withDefault(['nickname'=>'-']);
}
}

View File

@@ -1,15 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ProjectRemark extends Model
{
protected $table = 'project_remark';
public function user()
{
return $this->hasOne('App\Models\User','id','user_id')->withDefault(['nickname'=>'-']);
}
}

View File

@@ -1,30 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
class Queue extends Model
{
protected $table = 'queue';
protected $fillable = [
'display_name',
'strategy',
'max_wait_time',
];
protected $appends = ['strategy_name'];
public function agents()
{
return $this->belongsToMany('App\Models\Agent','queue_agent');
}
public function getStrategyNameAttribute()
{
return $this->attributes['strategy_name'] = Arr::get(config('freeswitch.strategy'),$this->strategy);
}
}

View File

@@ -1,7 +0,0 @@
<?php
namespace App\Models;
class Role extends \Spatie\Permission\Models\Role
{
}

View File

@@ -1,47 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
class Sip extends Model
{
protected $table = 'sip';
protected $fillable = [
'username',
'password',
'effective_caller_id_name',
'effective_caller_id_number',
'outbound_caller_id_name',
'outbound_caller_id_number',
'gateway_id',
'state',
'status'
];
protected $appends = ['status_name','state_name'];
public function getStateNameAttribute()
{
return $this->attributes['state_name'] = Arr::get(config('freeswitch.channel_callstate'),$this->state,'DOWN');
}
public function getStatusNameAttribute()
{
return $this->attributes['status'] = Arr::get([0=>'未注册',1=>'已注册'],$this->status,'-');;
}
/**
* 所属网关
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function gateway()
{
return $this->hasOne('App\Models\Gateway','id','gateway_id')->withDefault(['name'=>'未分配']);
}
}

View File

@@ -1,84 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
{
protected $table = 'task';
protected $fillable = [
'name',
'date_start',
'date_end',
'time_start',
'time_end',
'gateway_id',
'queue_id',
'max_channel',
'status',
];
protected $appends = ['gateway_name','queue_name','date','time'];
public function gateway()
{
return $this->hasOne('App\Models\Gateway','id','gateway_id');
}
public function queue()
{
return $this->hasOne('App\Models\Queue','id','queue_id');
}
public function getGatewayNameAttribute()
{
return $this->attributes['gateway_name'] = $this->gateway->name;
}
public function getQueueNameAttribute()
{
return $this->attributes['queue_name'] = $this->queue->display_name;
}
public function getDateAttribute()
{
return $this->attributes['date'] = $this->date_start . ' / '. $this->date_end;
}
public function getTimeAttribute()
{
return $this->attributes['time'] = $this->time_start . ' - '. $this->time_end;
}
//总呼叫数
public function calls()
{
return $this->hasMany('App\Models\Call','task_id','id');
}
//已呼叫数 status !=1
public function hasCalls()
{
return $this->hasMany('App\Models\Call','task_id','id')->where('status','!=',1);
}
//漏接数 status=3
public function missCalls()
{
return $this->hasMany('App\Models\Call','task_id','id')->where('status',3);
}
//呼叫成功数 status=4
public function successCalls()
{
return $this->hasMany('App\Models\Call','task_id','id')->where('status',4);
}
//呼叫失败数 status=2
public function failCalls()
{
return $this->hasMany('App\Models\Call','task_id','id')->where('status',2);
}
}

View File

@@ -1,94 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Hash;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use Notifiable,HasRoles;
protected $table = 'users';
protected $guard_name = 'web';
protected $fillable = [
'phone',
'nickname',
'password',
'remember_token',
'api_token',
'department_id',
'sip_id',
'last_login_at',
'last_login_ip',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'last_login_at' => 'datetime',
];
public function setPasswordAttribute($value)
{
$this->attributes['password'] = Hash::make($value);
}
public function department()
{
return $this->hasOne('App\Models\Department','id','department_id')->withDefault(['name'=>'-']);
}
public function sip()
{
return $this->hasOne('App\Models\Sip','id','sip_id')->withDefault(['username'=>'-']);
}
public function menus()
{
$menus = [];
$data = Menu::with('childs')->where('parent_id', 0)->orderBy('sort','asc')->get();
foreach ($data as $k1 => $v1){
if ($v1->permission_id==null || ($v1->permission_id!=null&&$this->hasPermissionTo($v1->permission_id))){
$menus[$k1] = [
'name' => $v1->name,
'route' => $v1->route,
'url' => $v1->url,
'icon' => $v1->icon,
'type' => $v1->type,
'childs' => [],
];
if ($v1->childs->isNotEmpty()){
foreach ($v1->childs as $k2 => $v2){
if ($v2->permission_id==null || ($v2->permission_id!=null&&$this->hasPermissionTo($v2->permission_id))){
$menus[$k1]['childs'][$k2] = [
'name' => $v2->name,
'route' => $v2->route,
'url' => $v2->url,
'icon' => $v2->icon,
'type' => $v2->type,
];
}
}
}
}
}
return $menus;
}
}

View File

@@ -1,36 +0,0 @@
<?php
namespace App\Providers;
use App\Models\Sip;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Schema::defaultStringLength(191);
//前台用户的分机
view()->composer('admin.base',function ($view){
$sip = Sip::where('id',Auth::user()->sip_id)->first();
$view->with('exten',$sip->username??null);
});
}
}

View File

@@ -1,30 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
// 'App\Model' => 'App\Policies\ModelPolicy',
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
//
}
}

View File

@@ -1,21 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\ServiceProvider;
class BroadcastServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Broadcast::routes();
require base_path('routes/channels.php');
}
}

View File

@@ -1,34 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
{
parent::boot();
//
}
}

View File

@@ -1,87 +0,0 @@
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
/**
* This namespace is applied to your controller routes.
*
* In addition, it is set as the URL generator's root namespace.
*
* @var string
*/
protected $namespace = 'App\Http\Controllers';
/**
* The path to the "home" route for your application.
*
* @var string
*/
public const HOME = '/home';
/**
* Define your route model bindings, pattern filters, etc.
*
* @return void
*/
public function boot()
{
//
parent::boot();
}
/**
* Define the routes for the application.
*
* @return void
*/
public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
$this->mapAdminRoutes();
}
/**
* Define the "web" routes for the application.
*
* These routes all receive session state, CSRF protection, etc.
*
* @return void
*/
protected function mapWebRoutes()
{
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/web.php'));
}
/**
* Define the "api" routes for the application.
*
* These routes are typically stateless.
*
* @return void
*/
protected function mapApiRoutes()
{
Route::prefix('api')
->middleware('api')
->namespace($this->namespace)
->group(base_path('routes/api.php'));
}
protected function mapAdminRoutes()
{
Route::middleware('web')
->namespace($this->namespace)
->group(base_path('routes/admin.php'));
}
}

Some files were not shown because too many files have changed in this diff Show More