计划任务及获客场景逻辑框架
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
namespace app\plan\controller;
|
||||
|
||||
use think\Controller;
|
||||
use think\Request;
|
||||
use think\facade\Request;
|
||||
use app\plan\model\PlanScene;
|
||||
|
||||
/**
|
||||
|
||||
247
Server/application/plan/controller/Tag.php
Normal file
247
Server/application/plan/controller/Tag.php
Normal file
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
namespace app\plan\controller;
|
||||
|
||||
use think\Controller;
|
||||
use think\Request;
|
||||
use app\plan\model\Tag as TagModel;
|
||||
use think\facade\Log;
|
||||
|
||||
/**
|
||||
* 标签控制器
|
||||
*/
|
||||
class Tag extends Controller
|
||||
{
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
protected function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取标签列表
|
||||
*
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$type = Request::param('type', '');
|
||||
$status = Request::param('status', 1, 'intval');
|
||||
|
||||
// 查询标签列表
|
||||
$tags = TagModel::getTagsByType($type, $status);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '获取成功',
|
||||
'data' => $tags
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建标签
|
||||
*
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$data = Request::post();
|
||||
|
||||
// 数据验证
|
||||
if (empty($data['name']) || empty($data['type'])) {
|
||||
return json([
|
||||
'code' => 400,
|
||||
'msg' => '缺少必要参数'
|
||||
]);
|
||||
}
|
||||
|
||||
try {
|
||||
// 创建或获取标签
|
||||
$tagId = TagModel::getOrCreate($data['name'], $data['type']);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '创建成功',
|
||||
'data' => $tagId
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('创建标签异常', [
|
||||
'data' => $data,
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return json([
|
||||
'code' => 500,
|
||||
'msg' => '创建失败:' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量创建标签
|
||||
*
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function batchCreate()
|
||||
{
|
||||
$data = Request::post();
|
||||
|
||||
// 数据验证
|
||||
if (empty($data['names']) || empty($data['type'])) {
|
||||
return json([
|
||||
'code' => 400,
|
||||
'msg' => '缺少必要参数'
|
||||
]);
|
||||
}
|
||||
|
||||
// 检查名称数组
|
||||
if (!is_array($data['names'])) {
|
||||
return json([
|
||||
'code' => 400,
|
||||
'msg' => '标签名称必须是数组'
|
||||
]);
|
||||
}
|
||||
|
||||
try {
|
||||
$result = [];
|
||||
|
||||
// 批量处理标签
|
||||
foreach ($data['names'] as $name) {
|
||||
$name = trim($name);
|
||||
if (empty($name)) continue;
|
||||
|
||||
$tagId = TagModel::getOrCreate($name, $data['type']);
|
||||
$result[] = [
|
||||
'id' => $tagId,
|
||||
'name' => $name,
|
||||
'type' => $data['type']
|
||||
];
|
||||
}
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '创建成功',
|
||||
'data' => $result
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('批量创建标签异常', [
|
||||
'data' => $data,
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return json([
|
||||
'code' => 500,
|
||||
'msg' => '创建失败:' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新标签
|
||||
*
|
||||
* @param int $id
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function update($id)
|
||||
{
|
||||
$data = Request::put();
|
||||
|
||||
// 检查标签是否存在
|
||||
$tag = TagModel::get($id);
|
||||
if (!$tag) {
|
||||
return json([
|
||||
'code' => 404,
|
||||
'msg' => '标签不存在'
|
||||
]);
|
||||
}
|
||||
|
||||
// 准备更新数据
|
||||
$updateData = [];
|
||||
|
||||
// 只允许更新特定字段
|
||||
$allowedFields = ['name', 'status'];
|
||||
foreach ($allowedFields as $field) {
|
||||
if (isset($data[$field])) {
|
||||
$updateData[$field] = $data[$field];
|
||||
}
|
||||
}
|
||||
|
||||
// 更新标签
|
||||
$tag->save($updateData);
|
||||
|
||||
// 如果更新了标签名称,且该标签有使用次数,则增加计数
|
||||
if (isset($updateData['name']) && $updateData['name'] != $tag->name && $tag->count > 0) {
|
||||
$tag->updateCount(1);
|
||||
}
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '更新成功'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除标签
|
||||
*
|
||||
* @param int $id
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
// 检查标签是否存在
|
||||
$tag = TagModel::get($id);
|
||||
if (!$tag) {
|
||||
return json([
|
||||
'code' => 404,
|
||||
'msg' => '标签不存在'
|
||||
]);
|
||||
}
|
||||
|
||||
// 更新状态为删除
|
||||
$tag->save([
|
||||
'status' => 0
|
||||
]);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '删除成功'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取标签名称
|
||||
*
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function getNames()
|
||||
{
|
||||
$ids = Request::param('ids');
|
||||
|
||||
// 验证参数
|
||||
if (empty($ids)) {
|
||||
return json([
|
||||
'code' => 400,
|
||||
'msg' => '缺少标签ID参数'
|
||||
]);
|
||||
}
|
||||
|
||||
// 处理参数
|
||||
if (is_string($ids)) {
|
||||
$ids = explode(',', $ids);
|
||||
}
|
||||
|
||||
// 获取标签名称
|
||||
$names = TagModel::getTagNames($ids);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '获取成功',
|
||||
'data' => $names
|
||||
]);
|
||||
}
|
||||
}
|
||||
370
Server/application/plan/controller/Task.php
Normal file
370
Server/application/plan/controller/Task.php
Normal file
@@ -0,0 +1,370 @@
|
||||
<?php
|
||||
namespace app\plan\controller;
|
||||
|
||||
use think\Controller;
|
||||
use think\Request;
|
||||
use app\plan\model\PlanTask;
|
||||
use app\plan\model\PlanExecution;
|
||||
use app\plan\service\TaskRunner;
|
||||
use think\facade\Log;
|
||||
|
||||
/**
|
||||
* 计划任务控制器
|
||||
*/
|
||||
class Task extends Controller
|
||||
{
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
protected function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务列表
|
||||
*
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$page = Request::param('page', 1, 'intval');
|
||||
$limit = Request::param('limit', 10, 'intval');
|
||||
$keyword = Request::param('keyword', '');
|
||||
$status = Request::param('status', '', 'trim');
|
||||
|
||||
// 构建查询条件
|
||||
$where = [];
|
||||
if (!empty($keyword)) {
|
||||
$where[] = ['name', 'like', "%{$keyword}%"];
|
||||
}
|
||||
|
||||
if ($status !== '') {
|
||||
$where[] = ['status', '=', intval($status)];
|
||||
}
|
||||
|
||||
// 查询列表
|
||||
$result = PlanTask::getTaskList($where, 'id desc', $page, $limit);
|
||||
|
||||
// 查询场景和设备信息
|
||||
foreach ($result['list'] as &$task) {
|
||||
$task['scene'] = $task->scene ? $task->scene->toArray() : null;
|
||||
$task['device'] = $task->device ? $task->device->toArray() : null;
|
||||
}
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '获取成功',
|
||||
'data' => $result
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务详情
|
||||
*
|
||||
* @param int $id
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function read($id)
|
||||
{
|
||||
$task = PlanTask::get($id, ['scene', 'device']);
|
||||
if (!$task) {
|
||||
return json([
|
||||
'code' => 404,
|
||||
'msg' => '任务不存在'
|
||||
]);
|
||||
}
|
||||
|
||||
// 获取执行记录
|
||||
$executions = PlanExecution::where('plan_id', $id)
|
||||
->order('createTime DESC')
|
||||
->select();
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'task' => $task,
|
||||
'executions' => $executions
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建任务
|
||||
*
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$data = Request::post();
|
||||
|
||||
// 数据验证
|
||||
$validate = validate('app\plan\validate\Task');
|
||||
if (!$validate->check($data)) {
|
||||
return json([
|
||||
'code' => 400,
|
||||
'msg' => $validate->getError()
|
||||
]);
|
||||
}
|
||||
|
||||
// 添加任务
|
||||
$task = new PlanTask;
|
||||
$task->save([
|
||||
'name' => $data['name'],
|
||||
'device_id' => $data['device_id'] ?? null,
|
||||
'scene_id' => $data['scene_id'] ?? null,
|
||||
'scene_config' => $data['scene_config'] ?? [],
|
||||
'status' => $data['status'] ?? 0,
|
||||
'current_step' => 0,
|
||||
'priority' => $data['priority'] ?? 5,
|
||||
'created_by' => $data['created_by'] ?? 0
|
||||
]);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '创建成功',
|
||||
'data' => $task->id
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新任务
|
||||
*
|
||||
* @param int $id
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function update($id)
|
||||
{
|
||||
$data = Request::put();
|
||||
|
||||
// 检查任务是否存在
|
||||
$task = PlanTask::get($id);
|
||||
if (!$task) {
|
||||
return json([
|
||||
'code' => 404,
|
||||
'msg' => '任务不存在'
|
||||
]);
|
||||
}
|
||||
|
||||
// 准备更新数据
|
||||
$updateData = [];
|
||||
|
||||
// 只允许更新特定字段
|
||||
$allowedFields = ['name', 'device_id', 'scene_id', 'scene_config', 'status', 'priority'];
|
||||
foreach ($allowedFields as $field) {
|
||||
if (isset($data[$field])) {
|
||||
$updateData[$field] = $data[$field];
|
||||
}
|
||||
}
|
||||
|
||||
// 更新任务
|
||||
$task->save($updateData);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '更新成功'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除任务
|
||||
*
|
||||
* @param int $id
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
// 检查任务是否存在
|
||||
$task = PlanTask::get($id);
|
||||
if (!$task) {
|
||||
return json([
|
||||
'code' => 404,
|
||||
'msg' => '任务不存在'
|
||||
]);
|
||||
}
|
||||
|
||||
// 软删除任务
|
||||
$task->delete();
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '删除成功'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动任务
|
||||
*
|
||||
* @param int $id
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function start($id)
|
||||
{
|
||||
// 检查任务是否存在
|
||||
$task = PlanTask::get($id);
|
||||
if (!$task) {
|
||||
return json([
|
||||
'code' => 404,
|
||||
'msg' => '任务不存在'
|
||||
]);
|
||||
}
|
||||
|
||||
// 更新状态为启用
|
||||
$task->save([
|
||||
'status' => 1,
|
||||
'current_step' => 0
|
||||
]);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '任务已启动'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止任务
|
||||
*
|
||||
* @param int $id
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function stop($id)
|
||||
{
|
||||
// 检查任务是否存在
|
||||
$task = PlanTask::get($id);
|
||||
if (!$task) {
|
||||
return json([
|
||||
'code' => 404,
|
||||
'msg' => '任务不存在'
|
||||
]);
|
||||
}
|
||||
|
||||
// 更新状态为停用
|
||||
$task->save([
|
||||
'status' => 0
|
||||
]);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '任务已停止'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行定时任务(供外部调用)
|
||||
*
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function cron()
|
||||
{
|
||||
// 获取密钥
|
||||
$key = Request::param('key', '');
|
||||
|
||||
// 验证密钥(实际生产环境应当使用更安全的验证方式)
|
||||
if ($key !== config('task.cron_key')) {
|
||||
return json([
|
||||
'code' => 403,
|
||||
'msg' => '访问密钥无效'
|
||||
]);
|
||||
}
|
||||
|
||||
try {
|
||||
// 获取待执行的任务
|
||||
$tasks = PlanTask::getPendingTasks(5);
|
||||
if ($tasks->isEmpty()) {
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '没有需要执行的任务',
|
||||
'data' => []
|
||||
]);
|
||||
}
|
||||
|
||||
$results = [];
|
||||
|
||||
// 逐一执行任务
|
||||
foreach ($tasks as $task) {
|
||||
$runner = new TaskRunner($task);
|
||||
$result = $runner->run();
|
||||
|
||||
$results[] = [
|
||||
'task_id' => $task->id,
|
||||
'name' => $task->name,
|
||||
'result' => $result
|
||||
];
|
||||
|
||||
// 记录执行信息
|
||||
Log::info('任务执行', [
|
||||
'task_id' => $task->id,
|
||||
'name' => $task->name,
|
||||
'result' => $result
|
||||
]);
|
||||
}
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '任务执行完成',
|
||||
'data' => $results
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('任务执行异常', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return json([
|
||||
'code' => 500,
|
||||
'msg' => '任务执行异常:' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动执行任务
|
||||
*
|
||||
* @param int $id
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function execute($id)
|
||||
{
|
||||
// 检查任务是否存在
|
||||
$task = PlanTask::get($id);
|
||||
if (!$task) {
|
||||
return json([
|
||||
'code' => 404,
|
||||
'msg' => '任务不存在'
|
||||
]);
|
||||
}
|
||||
|
||||
try {
|
||||
// 执行任务
|
||||
$runner = new TaskRunner($task);
|
||||
$result = $runner->run();
|
||||
|
||||
// 记录执行信息
|
||||
Log::info('手动执行任务', [
|
||||
'task_id' => $task->id,
|
||||
'name' => $task->name,
|
||||
'result' => $result
|
||||
]);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '任务执行完成',
|
||||
'data' => $result
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('手动执行任务异常', [
|
||||
'task_id' => $task->id,
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return json([
|
||||
'code' => 500,
|
||||
'msg' => '任务执行异常:' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
380
Server/application/plan/controller/Traffic.php
Normal file
380
Server/application/plan/controller/Traffic.php
Normal file
@@ -0,0 +1,380 @@
|
||||
<?php
|
||||
namespace app\plan\controller;
|
||||
|
||||
use think\Controller;
|
||||
use think\Request;
|
||||
use app\plan\model\TrafficPool;
|
||||
use app\plan\model\TrafficSource;
|
||||
use app\plan\service\SceneHandler;
|
||||
use think\facade\Log;
|
||||
|
||||
/**
|
||||
* 流量控制器
|
||||
*/
|
||||
class Traffic extends Controller
|
||||
{
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
protected function initialize()
|
||||
{
|
||||
parent::initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流量池列表
|
||||
*
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$page = Request::param('page', 1, 'intval');
|
||||
$limit = Request::param('limit', 10, 'intval');
|
||||
$keyword = Request::param('keyword', '');
|
||||
$status = Request::param('status', '', 'trim');
|
||||
$gender = Request::param('gender', '', 'trim');
|
||||
|
||||
// 构建查询条件
|
||||
$where = [];
|
||||
if (!empty($keyword)) {
|
||||
$where[] = ['mobile|tags', 'like', "%{$keyword}%"];
|
||||
}
|
||||
|
||||
if ($status !== '') {
|
||||
$where[] = ['status', '=', intval($status)];
|
||||
}
|
||||
|
||||
if ($gender !== '') {
|
||||
$where[] = ['gender', '=', intval($gender)];
|
||||
}
|
||||
|
||||
// 查询流量池列表
|
||||
$result = TrafficPool::getAvailableTraffic($where, 'id desc', $page, $limit);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '获取成功',
|
||||
'data' => $result
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流量详情
|
||||
*
|
||||
* @param int $id
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function read($id)
|
||||
{
|
||||
$traffic = TrafficPool::get($id);
|
||||
if (!$traffic) {
|
||||
return json([
|
||||
'code' => 404,
|
||||
'msg' => '流量记录不存在'
|
||||
]);
|
||||
}
|
||||
|
||||
// 获取流量来源
|
||||
$sources = TrafficSource::getSourcesByTrafficId($id);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '获取成功',
|
||||
'data' => [
|
||||
'traffic' => $traffic,
|
||||
'sources' => $sources
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建或更新流量
|
||||
*
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function save()
|
||||
{
|
||||
$data = Request::post();
|
||||
|
||||
// 数据验证
|
||||
$validate = validate('app\plan\validate\Traffic');
|
||||
if (!$validate->check($data)) {
|
||||
return json([
|
||||
'code' => 400,
|
||||
'msg' => $validate->getError()
|
||||
]);
|
||||
}
|
||||
|
||||
try {
|
||||
// 添加或更新流量
|
||||
$result = TrafficPool::addOrUpdateTraffic(
|
||||
$data['mobile'],
|
||||
$data['gender'] ?? 0,
|
||||
$data['age'] ?? 0,
|
||||
$data['tags'] ?? '',
|
||||
$data['province'] ?? '',
|
||||
$data['city'] ?? '',
|
||||
$data['source_channel'] ?? '',
|
||||
$data['source_detail'] ?? []
|
||||
);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '保存成功',
|
||||
'data' => $result
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('保存流量记录异常', [
|
||||
'data' => $data,
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return json([
|
||||
'code' => 500,
|
||||
'msg' => '保存失败:' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新流量记录
|
||||
*
|
||||
* @param int $id
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function update($id)
|
||||
{
|
||||
$data = Request::put();
|
||||
|
||||
// 检查流量记录是否存在
|
||||
$traffic = TrafficPool::get($id);
|
||||
if (!$traffic) {
|
||||
return json([
|
||||
'code' => 404,
|
||||
'msg' => '流量记录不存在'
|
||||
]);
|
||||
}
|
||||
|
||||
// 准备更新数据
|
||||
$updateData = [];
|
||||
|
||||
// 只允许更新特定字段
|
||||
$allowedFields = ['gender', 'age', 'tags', 'province', 'city', 'status'];
|
||||
foreach ($allowedFields as $field) {
|
||||
if (isset($data[$field])) {
|
||||
$updateData[$field] = $data[$field];
|
||||
}
|
||||
}
|
||||
|
||||
// 更新流量记录
|
||||
$traffic->save($updateData);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '更新成功'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除流量记录
|
||||
*
|
||||
* @param int $id
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function delete($id)
|
||||
{
|
||||
// 检查流量记录是否存在
|
||||
$traffic = TrafficPool::get($id);
|
||||
if (!$traffic) {
|
||||
return json([
|
||||
'code' => 404,
|
||||
'msg' => '流量记录不存在'
|
||||
]);
|
||||
}
|
||||
|
||||
// 更新状态为无效
|
||||
$traffic->save([
|
||||
'status' => 0
|
||||
]);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '删除成功'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流量来源统计
|
||||
*
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function sourceStats()
|
||||
{
|
||||
$channel = Request::param('channel', '');
|
||||
$planId = Request::param('plan_id', 0, 'intval');
|
||||
$sceneId = Request::param('scene_id', 0, 'intval');
|
||||
$startDate = Request::param('start_date', '', 'trim');
|
||||
$endDate = Request::param('end_date', '', 'trim');
|
||||
|
||||
// 获取统计数据
|
||||
$stats = TrafficSource::getSourceStats($channel, $planId, $sceneId, $startDate, $endDate);
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '获取成功',
|
||||
'data' => $stats
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理外部流量
|
||||
*
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function handleExternalTraffic()
|
||||
{
|
||||
$data = Request::post();
|
||||
|
||||
// 验证必要参数
|
||||
if (empty($data['scene_id']) || empty($data['mobile'])) {
|
||||
return json([
|
||||
'code' => 400,
|
||||
'msg' => '缺少必要参数'
|
||||
]);
|
||||
}
|
||||
|
||||
try {
|
||||
// 获取场景处理器
|
||||
$handler = SceneHandler::getHandler($data['scene_id']);
|
||||
|
||||
// 根据场景类型处理流量
|
||||
switch ($data['scene_type'] ?? '') {
|
||||
case 'poster':
|
||||
$result = $handler->handlePosterScan($data['mobile'], $data);
|
||||
break;
|
||||
|
||||
case 'order':
|
||||
$result = $handler->handleOrderImport($data['orders'] ?? []);
|
||||
break;
|
||||
|
||||
default:
|
||||
$result = $handler->handleChannelTraffic($data['mobile'], $data['channel'] ?? '', $data);
|
||||
}
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '处理成功',
|
||||
'data' => $result
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('处理外部流量异常', [
|
||||
'data' => $data,
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return json([
|
||||
'code' => 500,
|
||||
'msg' => '处理失败:' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量导入流量
|
||||
*
|
||||
* @return \think\response\Json
|
||||
*/
|
||||
public function importTraffic()
|
||||
{
|
||||
// 检查是否上传了文件
|
||||
$file = Request::file('file');
|
||||
if (!$file) {
|
||||
return json([
|
||||
'code' => 400,
|
||||
'msg' => '未上传文件'
|
||||
]);
|
||||
}
|
||||
|
||||
// 检查文件类型,只允许csv或xlsx
|
||||
$fileExt = strtolower($file->getOriginalExtension());
|
||||
if (!in_array($fileExt, ['csv', 'xlsx'])) {
|
||||
return json([
|
||||
'code' => 400,
|
||||
'msg' => '仅支持CSV或XLSX格式文件'
|
||||
]);
|
||||
}
|
||||
|
||||
try {
|
||||
// 处理上传文件
|
||||
$saveName = \think\facade\Filesystem::disk('upload')->putFile('traffic', $file);
|
||||
$filePath = app()->getRuntimePath() . 'storage/upload/' . $saveName;
|
||||
|
||||
// 读取文件内容并导入
|
||||
$results = [];
|
||||
$success = 0;
|
||||
$fail = 0;
|
||||
|
||||
// 这里简化处理,实际应当使用专业的Excel/CSV解析库
|
||||
if ($fileExt == 'csv') {
|
||||
$handle = fopen($filePath, 'r');
|
||||
|
||||
// 跳过标题行
|
||||
fgetcsv($handle);
|
||||
|
||||
while (($data = fgetcsv($handle)) !== false) {
|
||||
if (count($data) < 1) continue;
|
||||
|
||||
$mobile = trim($data[0]);
|
||||
// 验证手机号
|
||||
if (!preg_match('/^1[3-9]\d{9}$/', $mobile)) {
|
||||
$fail++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 添加或更新流量
|
||||
TrafficPool::addOrUpdateTraffic(
|
||||
$mobile,
|
||||
isset($data[1]) ? intval($data[1]) : 0, // 性别
|
||||
isset($data[2]) ? intval($data[2]) : 0, // 年龄
|
||||
isset($data[3]) ? $data[3] : '', // 标签
|
||||
isset($data[4]) ? $data[4] : '', // 省份
|
||||
isset($data[5]) ? $data[5] : '', // 城市
|
||||
'import', // 来源渠道
|
||||
['detail' => '批量导入'] // 来源详情
|
||||
);
|
||||
|
||||
$success++;
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
} else {
|
||||
// 处理xlsx文件,实际应当使用专业的Excel解析库
|
||||
// 此处代码省略,依赖于具体的Excel解析库
|
||||
}
|
||||
|
||||
return json([
|
||||
'code' => 200,
|
||||
'msg' => '导入完成',
|
||||
'data' => [
|
||||
'success' => $success,
|
||||
'fail' => $fail
|
||||
]
|
||||
]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Log::error('批量导入流量异常', [
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString()
|
||||
]);
|
||||
|
||||
return json([
|
||||
'code' => 500,
|
||||
'msg' => '导入失败:' . $e->getMessage()
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user