diff --git a/app/Console/Commands/SwooleCallcenterRun.php b/app/Console/Commands/SwooleCallcenterRun.php
new file mode 100644
index 00000000..91dfe544
--- /dev/null
+++ b/app/Console/Commands/SwooleCallcenterRun.php
@@ -0,0 +1,156 @@
+where(['status'=>2])->select(['id'])->get();
+ if ($res->isNotEmpty()) {
+ foreach ($res as $key => $task) {
+ Redis::rPush($redis_key,$task->id);
+ }
+ }
+ \Swoole\Coroutine\run(function () use ($redis_key) {
+ //启动服务
+ while (true) {
+ $task_id = Redis::lPop($redis_key);
+ if ($task_id == null) {
+ sleep(10);
+ continue;
+ }
+ \Swoole\Coroutine::create(function () use ($task_id){
+ while (true){
+ $task = Task::with(['queue.sips','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);
+ Log::info("任务ID:".$task->id."运行日期不满足");
+ 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;
+ }
+
+ //检测队列
+ if ($task->queue==null){
+ Log::info("任务ID:".$task->id." 的队列不存在,任务停止");
+ $task->update(['status'=>1]);
+ break;
+ }
+ //检测队列是否有坐席
+ if ($task->queue->sips->isEmpty()){
+ Log::info("任务ID:".$task->id." 的队列无坐席存在,任务停止");
+ $task->update(['status'=>1]);
+ break;
+ }
+ //并发数调节
+ $channel = 0;
+ $members = 0;
+ foreach ($task->queue->sips as $sip){
+ if ($sip->status==1 && $sip->state=='down'){
+ $members++;
+ }
+ }
+ if ($members === 0){
+ Log::info("任务ID:".$task->name." 无空闲坐席,sleep:1秒");
+ sleep(1);
+ continue;
+ }else{
+ if ($task->max_channel==0){
+ $channel = $members;
+ }else{
+ $channel = $task->max_channel > $members ? $members : $task->max_channel;
+ }
+ }
+
+ //如果通道数还是0,则不需要呼叫
+ if ($channel == 0) {
+ Log::info("任务ID:".$task->name." 的并发不需要呼叫");
+ sleep(10);
+ continue;
+ }
+
+ //进行呼叫
+ $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){
+ go(function () use ($call,$task){
+ (new Callcenter($call,$task))->run();
+ });
+ sleep(2);
+ }
+ sleep(6);
+ }
+ });
+ }
+ });
+ }
+}
diff --git a/app/Console/Commands/SwooleHttp.php b/app/Console/Commands/SwooleHttp.php
index c87d81f7..964bc29c 100644
--- a/app/Console/Commands/SwooleHttp.php
+++ b/app/Console/Commands/SwooleHttp.php
@@ -50,6 +50,7 @@ class SwooleHttp extends Command
'directory' => '/usr/local/freeswitch/conf/directory/default/',
//拨号计划下面默认分为default(呼出)和public(呼入)
'dialplan' => '/usr/local/freeswitch/conf/dialplan/',
+ 'callcenter' => '/usr/local/freeswitch/conf/autoload_configs/callcenter.conf.xml'
];
$http->on('request', function ($request, $response) use ($conf) {
if($request->server['request_method'] == 'POST'){
@@ -137,7 +138,60 @@ class SwooleHttp extends Command
exec($command."\""."reloadxml"."\"");
$return = ['code'=>0,'msg'=>'拨号计划更新成功'];
break;
+ case '/callcenter':
+ $xml = "\n";
+ $xml .= "\t\n";
+ $xml .= "\t\t\n";
+ $xml .= "\t\t\n";
+ $xml .= "\t\t\n";
+ $xml .= "\t\t\n";
+ $xml .= "\t\t\n";
+ $xml .= "\t\n";
+ //---------------------------------- 写入队列信息 ------------------------------------
+ $xml .= "\t\n";
+ foreach ($data['queues'] as $queue){
+ $xml .= "\t\t\n";
+ $xml .= "\t\t\t\n";
+ $xml .= "\t\t\t\n";
+ //$xml .= "\t\t\t\n";
+ $xml .= "\t\t\t\n";
+ $xml .= "\t\t\t\n";
+ $xml .= "\t\t\t\n";
+ $xml .= "\t\t\t\n";
+ $xml .= "\t\t\t\n";
+ $xml .= "\t\t\t\n";
+ $xml .= "\t\t\t\n";
+ $xml .= "\t\t\t\n";
+ $xml .= "\t\t\t\n";
+ $xml .= "\t\t\t\n";
+ $xml .= "\t\t\n";
+ }
+ $xml .= "\t\n";
+ //---------------------------------- 写入坐席信息 ------------------------------------
+ $xml .= "\t\n";
+ foreach ($data['agents'] as $agent){
+ $contact = "[leg_timeout=10]user/".$agent['username'];
+ $xml .= "\t\t\n";
+ }
+ $xml .= "\t\n";
+
+ //---------------------------------- 写入队列-坐席信息 ------------------------------------
+ $xml .= "\t\n";
+ foreach ($data['queues'] as $queue){
+ if (isset($queue['agents'])&&!empty($queue['agents'])) {
+ foreach ($queue['agents'] as $agent){
+ $xml .= "\t\t\n";
+ }
+ }
+ }
+ $xml .= "\t\n";
+ $xml .= "\n";
+ //生成配置文件
+ file_put_contents($conf['callcenter'],$xml);
+ exec($command."\""."reload mod_callcenter"."\"");
+ $return = ['code'=>0,'msg'=>'分机更新成功'];
+ break;
case '/favicon.ico':
$response->status(404);
$response->end();
diff --git a/app/Http/Controllers/Callcenter/QueueController.php b/app/Http/Controllers/Callcenter/QueueController.php
index ab1cc662..c4aad17b 100644
--- a/app/Http/Controllers/Callcenter/QueueController.php
+++ b/app/Http/Controllers/Callcenter/QueueController.php
@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Callcenter;
use App\Http\Controllers\Controller;
+use App\Models\Sip;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
@@ -42,6 +43,7 @@ class QueueController extends Controller
'name' => $data['name'],
'strategy' => $data['strategy'],
'max_wait_time' => $data['max_wait_time'],
+ 'created_at' => date('Y-m-d H:i:s'),
]);
foreach ($data['sips'] as $sipId){
DB::table('queue_sip')->insert([
@@ -108,11 +110,16 @@ class QueueController extends Controller
public function updateXml()
{
$queues = Queue::with('sips')->get()->toArray();
+ $sipIds = DB::table('queue_sip')->pluck('sip_id')->toArray();
+ $agents = Sip::query()->whereIn('id',$sipIds)->get()->toArray();
try{
$client = new Client();
$client->post(config('freeswitch.swoole_http_url.callcenter'),
[
- 'json' => $queues,
+ 'json' => [
+ 'queues' => $queues,
+ 'agents' => $agents,
+ ],
'timeout' => 30
]
);
diff --git a/app/Http/Controllers/Callcenter/Task.php b/app/Http/Controllers/Callcenter/Task.php
deleted file mode 100644
index 987adf9c..00000000
--- a/app/Http/Controllers/Callcenter/Task.php
+++ /dev/null
@@ -1,11 +0,0 @@
-ajax()){
+ $res = Task::query()->withCount('calls')->orderByDesc('id')->paginate($request->get('limit', 30));
+ return $this->success('ok',$res->items(),$res->total());
+ }
+ return View::make('callcenter.task.index');
+ }
+
+ public function create()
+ {
+ $queues = Queue::query()->orderByDesc('id')->get();
+ $gateways = Gateway::query()->orderByDesc('id')->get();
+ return View::make('callcenter.task.create',compact('queues','gateways'));
+ }
+
+ public function store(Request $request)
+ {
+ $data = $request->all([
+ 'name',
+ 'date_start',
+ 'date_end',
+ 'time_start',
+ 'time_end',
+ 'gateway_id',
+ 'queue_id',
+ 'max_channel',
+ ]);
+ try {
+ Task::create($data);
+ return $this->success();
+ }catch (\Exception $exception){
+ Log::error('添加任务异常:'.$exception->getMessage());
+ return $this->error();
+ }
+ }
+
+ public function edit($id)
+ {
+ $model = Task::query()->findOrFail($id);
+ $queues = Queue::query()->orderByDesc('id')->get();
+ $gateways = Gateway::query()->orderByDesc('id')->get();
+ return View::make('callcenter.task.edit',compact('model', 'queues', 'gateways'));
+ }
+
+ public function update(Request $request,$id)
+ {
+ $data = $request->all([
+ 'name',
+ 'date_start',
+ 'date_end',
+ 'time_start',
+ 'time_end',
+ 'gateway_id',
+ 'queue_id',
+ 'max_channel',
+ ]);
+ $model = Task::query()->findOrFail($id);
+ try {
+ $model->update($data);
+ return $this->success();
+ }catch (\Exception $exception){
+ Log::error('更新任务异常:'.$exception->getMessage());
+ return $this->error();
+ }
+ }
+
+ public function destroy(Request $request)
+ {
+ $ids = $request->get('ids');
+ if (empty($ids)){
+ return $this->error('请选择删除项');
+ }
+ DB::beginTransaction();
+ try {
+ Task::destroy($ids);
+
+ DB::commit();
+ return $this->success();
+ }catch (\Exception $exception){
+ DB::rollBack();
+ Log::error('删除群呼任务异常:'.$exception->getMessage());
+ return $this->error();
+ }
+ }
+
+ public function show(Request $request,$id)
+ {
+ $task = Task::query()->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');
+ return response()->json(['code'=>0, 'msg'=>'请求成功']);
+ }
+ return view('callcenter.task.show',compact('task','percent'));
+ }
+
+ public function setStatus(Request $request)
+ {
+ $ids = $request->get('ids',[]);
+ if (count($ids)!=1){
+ return $this->error('请选择一条记录');
+ }
+ $task = Task::query()->withCount('calls')->find($ids[0]);
+ if ($task==null){
+ return $this->error('任务不存在');
+ }
+ if ($task->status==3){
+ return $this->error('任务已完成,禁止操作');
+ }
+ $status = $request->get('status',1);
+
+ if ($status==2&&$task->calls_count==0){
+ return $this->error('任务未导入号码,禁止操作');
+ }
+ if ($status==1&&$task->status!=2){
+ return $this->error('任务未启动,禁止操作');
+ }
+ try {
+ $task->update(['status'=>$status]);
+ $key = config('freeswitch.redis_key.callcenter_task');
+ Redis::rPush($key,$task->id);
+ return $this->success();
+ }catch (\Exception $exception){
+ Log::error('设置任务状态异常:'.$exception->getMessage());
+ return $this->error();
+ }
+ }
+
+ public function importCall(Request $request, $id)
+ {
+ $model = Task::query()->findOrFail($id);
+ if ($request->ajax()){
+ $file = $request->input('file');
+ if ($file == null){
+ return $this->error('请先上传文件');
+ }
+ $xlsFile = public_path().$file;
+ try{
+ Excel::import(new CallImport($id), $xlsFile);
+ return $this->success('导入成功');
+ }catch (\Exception $exception){
+ Log::error('导入失败:'.$exception->getMessage());
+ return $this->error('导入失败');
+ }
+ }
+ return View::make('callcenter.task.import',compact('model'));
+ }
+
+ public function calls(Request $request)
+ {
+ $data = $request->all(['task_id','phone']);
+ $res = Call::query()
+ ->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,'-');
+ }
+ return $this->success('ok',$res->items(),$res->total());
+ }
+
+}
diff --git a/app/Imports/CallImport.php b/app/Imports/CallImport.php
new file mode 100644
index 00000000..f07dc578
--- /dev/null
+++ b/app/Imports/CallImport.php
@@ -0,0 +1,30 @@
+task_id = $task_id;
+ }
+
+ public function model(array $row)
+ {
+ if (!isset($row[0]) || !preg_match('/\d{7,11}/',$row[0]) ) {
+ return null;
+ }
+ return new Call([
+ 'task_id' => $this->task_id,
+ 'phone' => $row[0],
+ ]);
+ }
+}
diff --git a/app/Models/Call.php b/app/Models/Call.php
new file mode 100644
index 00000000..a01e2c57
--- /dev/null
+++ b/app/Models/Call.php
@@ -0,0 +1,22 @@
+hasOne('App\Models\Sip','id','sip_id');
+ }
+
+ public function user()
+ {
+ return $this->hasOne('App\Models\User','id','user_id');
+ }
+
+}
diff --git a/app/Models/Task.php b/app/Models/Task.php
index 58531793..0629f09f 100644
--- a/app/Models/Task.php
+++ b/app/Models/Task.php
@@ -8,4 +8,67 @@ class Task extends Model
{
protected $table = 'task';
protected $guarded = ['id'];
+
+ 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->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);
+ }
+
}
diff --git a/app/Service/Callcenter.php b/app/Service/Callcenter.php
new file mode 100644
index 00000000..4a9b945a
--- /dev/null
+++ b/app/Service/Callcenter.php
@@ -0,0 +1,123 @@
+call = $call;
+ $this->fs = new SwooleFreeswitch();
+ if (!$this->fs->connect()) {
+ return false;
+ }
+
+ }
+
+ public function run()
+ {
+ $record_url = config('freeswitch.record_url');
+ $fs_dir = '/usr/local/freeswitch';
+
+ $uuid = uuid_generate();
+ //更新为正在呼叫
+ $this->call->update([
+ 'status' => 2,
+ 'uuid' => $uuid,
+ 'datetime_originate_phone' => date('Y-m-d H:i:s')
+ ]);
+ Log::info("更新号码: " . $this->call->phone . " 状态为:2");
+
+ $phone = $this->task->gateway->prefix ? $this->task->gateway->prefix . $this->call->phone : $this->call->phone;
+ $varStr = "{origination_uuid=" . $uuid . "}";
+ $varStr .= "{ignore_early_media=true}";
+ $varStr .= "{effective_caller_id_number=" . $this->call->phone . "}";
+ $varStr .= "{effective_caller_id_name=" . $this->call->phone . "}";
+ if ($this->task->gateway->outbound_caller_id) {
+ $varStr .= "{origination_caller_id_number=" . $this->task->gateway->outbound_caller_id . "}";
+ $varStr .= "{origination_caller_id_name=" . $this->task->gateway->outbound_caller_id . "}";
+ }
+ $varStr .= "{cc_export_vars=effective_caller_id_number,effective_caller_id_name}";
+ $dail_string = "originate " . $varStr . "sofia/gateway/gw" . $this->task->gateway->id . "/" . $phone . " &callcenter(queue" . $this->task->queue->id . ")";
+ Log::info("呼叫:" . $dail_string);
+
+ $this->fs->bgapi($dail_string);
+ $this->fs->events("CUSTOM callcenter::info");
+ $this->fs->filteruuid($this->call->uuid);
+
+ while (true) {
+ $received_parameters = $this->fs->recvEvent();
+ if (!empty($received_parameters)) {
+ $json = $this->fs->serialize($received_parameters);
+ $action = Arr::get($json, "CC-Action");
+ $uuid = Arr::get($json, "CC-Member-Session-UUID");
+ switch ($action) {
+ //呼叫进入队列
+ case 'member-queue-start':
+ $this->call->update([
+ 'datetime_entry_queue' => date('Y-m-d H:i:s'),
+ 'status' => 3
+ ]);
+ break;
+ // 坐席应答
+ case 'bridge-agent-start':
+ $agent_name = Arr::get($json, "CC-Agent");
+ $id = (int)Str::after($agent_name, 'agent');
+ $filepath = $fs_dir . '/recordings/' . date('Y/m/d/');
+ $file = $filepath . 'callcenter_' . $uuid . '.wav';
+ $this->fs->bgapi("uuid_record " . $uuid . " start " . $file . " 1800");
+ $this->call->update([
+ 'datetime_agent_answered' => date('Y-m-d H:i:s'),
+ 'status' => 4,
+ 'agent_id' => $id,
+ 'record_file' => str_replace($fs_dir, $record_url, $file),
+ ]);
+ break;
+ //坐席结束
+ case 'bridge-agent-end':
+ $this->call->update([
+ 'datetime_end' => date('Y-m-d H:i:s'),
+ 'status' => 4
+ ]);
+ break;
+ //桥接结束,通话结束
+ case 'member-queue-end':
+ $cause = Arr::get($json, "CC-Cause");
+ $answered_time = Arr::get($json, "CC-Agent-Answered-Time");
+ $leaving_time = Arr::get($json, "CC-Member-Leaving-Time");
+ 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;
+ }
+ }
+ $this->call->update([
+ 'billsec' => $billsec,
+ ]);
+ break;
+ default:
+ }
+ }
+ }
+ $this->fs->disconnect();
+ }
+
+}
diff --git a/config/freeswitch.php b/config/freeswitch.php
index 2aa42d8a..ab5e9c52 100644
--- a/config/freeswitch.php
+++ b/config/freeswitch.php
@@ -31,6 +31,8 @@ return [
'directory' => 'http://127.0.0.1:9501/directory',
//生成拨号计划
'dialplan' => 'http://127.0.0.1:9501/dialplan',
+ //生成群呼
+ 'callcenter' => 'http://127.0.0.1:9501/callcenter',
],
'esl' => [
@@ -42,6 +44,7 @@ return [
'redis_key' => [
'dial' => 'dial_uuid_queue',
'api' => 'api_exec_queue',
+ 'callcenter_task' => 'callcenter_task_queue',
],
'record_url' => env('APP_URL','http://localhost'),
'host' => env('FS_HOST','127.0.0.1'),
@@ -85,4 +88,12 @@ return [
4 => '微信',
5 => '其它',
],
+
+ //群呼状态
+ 'callcenter_call_status' => [
+ 1 => '待呼叫',
+ 2 => '呼叫失败',
+ 3 => '漏接',
+ 4 => '成功',
+ ],
];
diff --git a/database/migrations/2021_04_02_154147_callcenter_task_call.php b/database/migrations/2021_04_02_154147_callcenter_task_call.php
index 164b99e9..28660646 100644
--- a/database/migrations/2021_04_02_154147_callcenter_task_call.php
+++ b/database/migrations/2021_04_02_154147_callcenter_task_call.php
@@ -18,6 +18,9 @@ class CallcenterTaskCall extends Migration
$table->unsignedBigInteger('task_id')->comment('任务ID');
$table->string('phone')->comment('待呼叫号码');
$table->tinyInteger('status')->default(1)->comment('1-待呼叫,2-呼叫中,3-队列等待,4-已通话');
+ $table->string('uuid')->nullable()->comment('UUID');
+ $table->string('aleg_uuid')->nullable()->comment('客户通话UUID');
+ $table->string('bleg_uuid')->nullable()->comment('坐席通话UUID');
$table->string('uuid')->nullable()->comment('客户通话UUID');
$table->timestamp('datetime_originate_phone')->nullable()->comment('呼叫时间');
$table->timestamp('datetime_entry_queue')->nullable()->comment('进入队列时间');
diff --git a/database/seeds/MenuTableSeeder.php b/database/seeds/MenuTableSeeder.php
index 88787bd0..324149e6 100644
--- a/database/seeds/MenuTableSeeder.php
+++ b/database/seeds/MenuTableSeeder.php
@@ -116,6 +116,14 @@ class MenuTableSeeder extends Seeder
'type' => 1,
'permission_name' => 'callcenter.queue',
],
+ [
+ 'name' => '任务管理',
+ 'route' => 'callcenter.task',
+ 'url' => null,
+ 'icon' => 'layui-icon-template-1',
+ 'type' => 1,
+ 'permission_name' => 'callcenter.task',
+ ],
]
],
[
diff --git a/database/seeds/UserTableSeeder.php b/database/seeds/UserTableSeeder.php
index 4ba4e2ea..13cac881 100644
--- a/database/seeds/UserTableSeeder.php
+++ b/database/seeds/UserTableSeeder.php
@@ -137,6 +137,18 @@ class UserTableSeeder extends Seeder
['name' => 'callcenter.queue.updateXml', 'display_name' => '更新配置'],
]
],
+ [
+ 'name' => 'callcenter.task',
+ 'display_name' => '任务管理',
+ 'child' => [
+ ['name' => 'callcenter.task.create', 'display_name' => '添加'],
+ ['name' => 'callcenter.task.show', 'display_name' => '详情'],
+ ['name' => 'callcenter.task.edit', 'display_name' => '编辑'],
+ ['name' => 'callcenter.task.destroy', 'display_name' => '删除'],
+ ['name' => 'callcenter.task.importCall', 'display_name' => '导入号码'],
+ ['name' => 'callcenter.task.setStatus', 'display_name' => '设置状态'],
+ ]
+ ],
],
],
[
diff --git a/public/template/calls.xlsx b/public/template/calls.xlsx
new file mode 100644
index 00000000..9ed6a893
Binary files /dev/null and b/public/template/calls.xlsx differ
diff --git a/public/template/outgoing.csv b/public/template/outgoing.csv
deleted file mode 100644
index 76cfebf0..00000000
--- a/public/template/outgoing.csv
+++ /dev/null
@@ -1,7 +0,0 @@
-18908221080
-13512293513
-13512293514
-13512293515
-13512293516
-13512293517
-13512293517
\ No newline at end of file
diff --git a/resources/views/callcenter/task/_form.blade.php b/resources/views/callcenter/task/_form.blade.php
new file mode 100644
index 00000000..b97c0e30
--- /dev/null
+++ b/resources/views/callcenter/task/_form.blade.php
@@ -0,0 +1,65 @@
+{{csrf_field()}}
+
+
+
+
+
+
+
diff --git a/resources/views/callcenter/task/_js.blade.php b/resources/views/callcenter/task/_js.blade.php
new file mode 100644
index 00000000..93bdd5fe
--- /dev/null
+++ b/resources/views/callcenter/task/_js.blade.php
@@ -0,0 +1,14 @@
+
\ No newline at end of file
diff --git a/resources/views/callcenter/task/create.blade.php b/resources/views/callcenter/task/create.blade.php
new file mode 100644
index 00000000..ab20fce7
--- /dev/null
+++ b/resources/views/callcenter/task/create.blade.php
@@ -0,0 +1,15 @@
+@extends('base')
+
+@section('content')
+
+@endsection
+
+@section('script')
+ @include('callcenter.task._js')
+@endsection
diff --git a/resources/views/callcenter/task/edit.blade.php b/resources/views/callcenter/task/edit.blade.php
new file mode 100644
index 00000000..b5a40536
--- /dev/null
+++ b/resources/views/callcenter/task/edit.blade.php
@@ -0,0 +1,16 @@
+@extends('base')
+
+@section('content')
+
+@endsection
+
+@section('script')
+ @include('callcenter.task._js')
+@endsection
diff --git a/resources/views/callcenter/task/import.blade.php b/resources/views/callcenter/task/import.blade.php
new file mode 100644
index 00000000..15ce4e25
--- /dev/null
+++ b/resources/views/callcenter/task/import.blade.php
@@ -0,0 +1,63 @@
+@extends('base')
+
+@section('content')
+
+@endsection
+
+@section('script')
+
+@endsection
diff --git a/resources/views/callcenter/task/index.blade.php b/resources/views/callcenter/task/index.blade.php
new file mode 100644
index 00000000..97aeefd3
--- /dev/null
+++ b/resources/views/callcenter/task/index.blade.php
@@ -0,0 +1,150 @@
+@extends('base')
+
+@section('content')
+
+@endsection
+
+@section('script')
+
+@endsection
diff --git a/resources/views/callcenter/task/show.blade.php b/resources/views/callcenter/task/show.blade.php
new file mode 100644
index 00000000..58b5acc0
--- /dev/null
+++ b/resources/views/callcenter/task/show.blade.php
@@ -0,0 +1,206 @@
+@extends('base')
+
+@section('content')
+
+
+
+
+
+
+
+
+
+
+
+
+
+ | 状态 | 数量 | 占比 |
+
+
+ | 成功 | {{$task->success_calls_count}} | {{$task->has_calls_count>0?100*round($task->success_calls_count/$task->has_calls_count,4).'%':'0.00%'}} |
+ | 失败 | {{$task->fail_calls_count}} | {{$task->has_calls_count>0?100*round($task->fail_calls_count/$task->has_calls_count,4).'%':'0.00%'}} |
+ | 漏接 | {{$task->miss_calls_count}} | {{$task->has_calls_count>0?100*round($task->miss_calls_count/$task->has_calls_count,4).'%':'0.00%'}} |
+
+
+
+
+
+
+
+
+
+
+
+@endsection
+
+@section('script')
+
+@endsection
diff --git a/routes/web.php b/routes/web.php
index 756e1763..3af7c952 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -211,6 +211,27 @@ Route::group(['prefix'=>'callcenter','namespace'=>'Callcenter','middleware'=>['a
Route::post('queue/updateXml','QueueController@updateXml')->name('callcenter.queue.updateXml')->middleware('permission:callcenter.queue.updateXml');
});
+ //任务管理
+ Route::group([],function (){
+ Route::get('task','TaskController@index')->name('callcenter.task')->middleware('permission:callcenter.task');
+ //添加
+ Route::get('task/create','TaskController@create')->name('callcenter.task.create')->middleware('permission:callcenter.task.create');
+ Route::post('task/store','TaskController@store')->name('callcenter.task.store')->middleware('permission:callcenter.task.create');
+ //编辑
+ Route::get('task/{id}/edit','TaskController@edit')->name('callcenter.task.edit')->middleware('permission:callcenter.task.edit');
+ Route::put('task/{id}/update','TaskController@update')->name('callcenter.task.update')->middleware('permission:callcenter.task.edit');
+ //删除
+ Route::delete('task/destroy','TaskController@destroy')->name('callcenter.task.destroy')->middleware('permission:callcenter.task.destroy');
+ //详情
+ Route::get('task/{id}/show','TaskController@show')->name('callcenter.task.show')->middleware('permission:callcenter.task.show');
+ //设置状态
+ Route::post('task/setStatus','TaskController@setStatus')->name('callcenter.task.setStatus')->middleware('permission:callcenter.task.setStatus');
+ //导入号码
+ Route::match(['get','post'],'task/{id}/importCall','TaskController@importCall')->name('callcenter.task.importCall')->middleware('permission:callcenter.task.importCall');
+ //呼叫记录
+ Route::get('task/calls','TaskController@calls')->name('callcenter.task.calls');
+ });
+
});