修改自动推广的相关任务
This commit is contained in:
@@ -1362,84 +1362,48 @@ class EmailClient extends Base
|
|||||||
// ==================== Promotion Tasks ====================
|
// ==================== Promotion Tasks ====================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a promotion sending task
|
* 基于任务工厂创建单个推广任务(手动触发)
|
||||||
* Params:
|
*
|
||||||
* - journal_id, template_id, style_id, scene, task_name
|
* 参数:
|
||||||
* - expert_ids (comma separated) OR field + major_id (auto-query from DB)
|
* - promotion_factory_id (必填)工厂ID,任务的模板/领域/国家/发送参数均从工厂读取
|
||||||
* - smtp_ids (comma separated, optional: restrict to specific SMTP accounts)
|
* - send_date (可选,默认明天)Y-m-d
|
||||||
* - min_interval, max_interval (seconds between emails)
|
* - task_name (可选,默认 "Manual-{journal_title}-F{factory_id}-{send_date}")
|
||||||
* - max_bounce_rate (%), no_repeat_days
|
* - no_repeat_days (可选,默认 30)覆盖默认不重复天数
|
||||||
* - send_start_hour, send_end_hour (UTC, default 8-22)
|
* - min_interval/max_interval/max_bounce_rate/send_start_hour/send_end_hour 可选覆盖
|
||||||
* - send_date (Y-m-d,计划发送日期;有则「今日准备明日发」由定时任务处理,无则创建后需手动 startTask)
|
|
||||||
*/
|
*/
|
||||||
public function createTask()
|
public function createTask()
|
||||||
{
|
{
|
||||||
$journalId = intval($this->request->param('journal_id', 0));
|
$factoryId = intval($this->request->param('promotion_factory_id', 0));
|
||||||
$templateId = intval($this->request->param('template_id', 0));
|
$sendDate = trim($this->request->param('send_date', date('Y-m-d', strtotime('+1 day'))));
|
||||||
$styleId = intval($this->request->param('style_id', 0));
|
$taskName = trim($this->request->param('task_name', ''));
|
||||||
$scene = trim($this->request->param('scene', ''));
|
$noRepeatDays = intval($this->request->param('no_repeat_days', 30));
|
||||||
$taskName = trim($this->request->param('task_name', ''));
|
$minInterval = intval($this->request->param('min_interval', 30));
|
||||||
$expertIds = trim($this->request->param('expert_ids', ''));
|
$maxInterval = intval($this->request->param('max_interval', 60));
|
||||||
$field = trim($this->request->param('field', ''));
|
|
||||||
$fetchIds = trim($this->request->param('fetch_ids', ''));
|
|
||||||
$smtpIds = trim($this->request->param('smtp_ids', ''));
|
|
||||||
$minInterval = intval($this->request->param('min_interval', 30));
|
|
||||||
$maxInterval = intval($this->request->param('max_interval', 60));
|
|
||||||
$maxBounceRate = intval($this->request->param('max_bounce_rate', 5));
|
$maxBounceRate = intval($this->request->param('max_bounce_rate', 5));
|
||||||
$noRepeatDays = intval($this->request->param('no_repeat_days', 7));
|
$sendStartHour = intval($this->request->param('send_start_hour', 8));
|
||||||
$sendStartHour = intval($this->request->param('send_start_hour', 8));
|
$sendEndHour = intval($this->request->param('send_end_hour', 22));
|
||||||
$sendEndHour = intval($this->request->param('send_end_hour', 22));
|
|
||||||
$sendDate = trim($this->request->param('send_date', date("Y-m-d",strtotime('+1 day'))));
|
|
||||||
$targetPartitions = trim($this->request->param('target_partitions', ''));
|
|
||||||
$targetCountryIds = trim($this->request->param('target_country_ids', ''));
|
|
||||||
$type = intval($this->request->param('type', 0));
|
|
||||||
$expertType = intval($this->request->param('expert_type', 5));
|
|
||||||
|
|
||||||
if (!$journalId) {
|
if (!$factoryId) {
|
||||||
return jsonError('journal_id is required');
|
return jsonError('promotion_factory_id is required');
|
||||||
}
|
}
|
||||||
$journal_info = $this->journal_obj->where("journal_id",$journalId)->find();
|
|
||||||
$templateId = ($templateId == 0) ? intval($journal_info['default_template_id']) : $templateId;
|
$factory = Db::name('promotion_factory')
|
||||||
$styleId = ($styleId == 0) ? intval(isset($journal_info['default_style_id']) ? $journal_info['default_style_id'] : 0) : $styleId;
|
->where('promotion_factory_id', $factoryId)
|
||||||
if($templateId==0){
|
|
||||||
return jsonError("template is not set!");
|
|
||||||
}
|
|
||||||
$tpl = Db::name('mail_template')
|
|
||||||
->where('template_id', $templateId)
|
|
||||||
->where('journal_id', $journalId)
|
|
||||||
->where('state', 0)
|
|
||||||
->find();
|
->find();
|
||||||
if (!$tpl) {
|
if (!$factory) {
|
||||||
return jsonError('Template not found for this journal');
|
return jsonError('Factory not found');
|
||||||
|
}
|
||||||
|
if (intval($factory['state']) !== 0) {
|
||||||
|
return jsonError('Factory is disabled');
|
||||||
|
}
|
||||||
|
if (intval($factory['expert_type']) !== 5) {
|
||||||
|
return jsonError('Only expert_type=5 is supported currently');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($scene)) {
|
$journalId = intval($factory['journal_id']);
|
||||||
$scene = $tpl['scene'];
|
$journal = Db::name('journal')->where('journal_id', $journalId)->find();
|
||||||
}
|
if (!$journal) {
|
||||||
|
return jsonError('Journal not found');
|
||||||
$experts = [];
|
|
||||||
if (!empty($expertIds)) {
|
|
||||||
$ids = array_map('intval', explode(',', $expertIds));
|
|
||||||
$experts = Db::name('expert')
|
|
||||||
->where('expert_id', 'in', $ids)
|
|
||||||
->where('state', 0)
|
|
||||||
->select();
|
|
||||||
} else {
|
|
||||||
// 领域来源优先级:前端传 field > 前端传 fetch_ids > journal_promotion_field
|
|
||||||
$fields = [];
|
|
||||||
if ($field !== '') {
|
|
||||||
$fields = [$field];
|
|
||||||
} elseif ($fetchIds !== '') {
|
|
||||||
$fields = $this->resolveFieldsByFetchIds($fetchIds);
|
|
||||||
} else {
|
|
||||||
$fields = $this->resolveFieldsByJournal($journalId);
|
|
||||||
}
|
|
||||||
|
|
||||||
$experts = $this->findEligibleExperts($fields, $noRepeatDays, 100, $targetPartitions, $targetCountryIds);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($experts)) {
|
|
||||||
return jsonError('No eligible experts found (all may have been promoted recently)');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$sendDateVal = null;
|
$sendDateVal = null;
|
||||||
@@ -1450,16 +1414,78 @@ class EmailClient extends Base
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$now = time();
|
if ($sendDateVal) {
|
||||||
|
$existTask = Db::name('promotion_task')
|
||||||
|
->where('factory_id', $factoryId)
|
||||||
|
->where('send_date', $sendDateVal)
|
||||||
|
->where('state', 'in', [0, 1, 5])
|
||||||
|
->find();
|
||||||
|
if ($existTask) {
|
||||||
|
return jsonError('Factory already has an active task for send_date=' . $sendDateVal . ' (task_id=' . $existTask['task_id'] . ')');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$templateId = intval($factory['template_id']) > 0
|
||||||
|
? intval($factory['template_id'])
|
||||||
|
: intval($journal['default_template_id']);
|
||||||
|
$styleId = intval($factory['style_id']) > 0
|
||||||
|
? intval($factory['style_id'])
|
||||||
|
: intval(isset($journal['default_style_id']) ? $journal['default_style_id'] : 0);
|
||||||
|
|
||||||
|
if ($templateId <= 0) {
|
||||||
|
return jsonError('template_id is not set on factory or journal');
|
||||||
|
}
|
||||||
|
|
||||||
|
$tpl = Db::name('mail_template')
|
||||||
|
->where('template_id', $templateId)
|
||||||
|
->where('journal_id', $journalId)
|
||||||
|
->where('state', 0)
|
||||||
|
->find();
|
||||||
|
if (!$tpl) {
|
||||||
|
return jsonError('Template not found for this journal');
|
||||||
|
}
|
||||||
|
$scene = $tpl['scene'] ?? 'promotion';
|
||||||
|
|
||||||
|
$smtpIds = trim((string)$factory['email_ids']);
|
||||||
|
if ($smtpIds === '') {
|
||||||
|
$smtpCount = Db::name('journal_email')
|
||||||
|
->where('journal_id', $journalId)
|
||||||
|
->where('state', 0)
|
||||||
|
->count();
|
||||||
|
if ($smtpCount == 0) {
|
||||||
|
return jsonError('No active SMTP account for this journal');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$fields = $this->resolveFieldsByFetchIds($factory['fetch_ids']);
|
||||||
|
if (empty($fields)) {
|
||||||
|
return jsonError('No valid fields resolved from factory.fetch_ids');
|
||||||
|
}
|
||||||
|
|
||||||
|
$targetPartitions = trim((string)$factory['target_partitions']);
|
||||||
|
$targetCountryIds = trim((string)$factory['target_country_ids']);
|
||||||
|
$dailyLimit = max(1, intval($factory['send_count']));
|
||||||
|
|
||||||
|
$experts = $this->findEligibleExperts($fields, $noRepeatDays, $dailyLimit, $targetPartitions, $targetCountryIds);
|
||||||
|
|
||||||
|
if (empty($experts)) {
|
||||||
|
return jsonError('No eligible experts found (all may have been promoted recently)');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($taskName === '') {
|
||||||
|
$taskName = 'Manual-' . ($journal['title'] ?? $journalId) . '-F' . $factoryId . '-' . ($sendDateVal ?: date('Y-m-d H:i'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$now = time();
|
||||||
$taskId = Db::name('promotion_task')->insertGetId([
|
$taskId = Db::name('promotion_task')->insertGetId([
|
||||||
'journal_id' => $journalId,
|
'journal_id' => $journalId,
|
||||||
'factory_id' => 0,
|
'factory_id' => $factoryId,
|
||||||
'template_id' => $templateId,
|
'template_id' => $templateId,
|
||||||
'style_id' => $styleId,
|
'style_id' => $styleId,
|
||||||
'scene' => $scene,
|
'scene' => $scene,
|
||||||
'type' => $type,
|
'type' => intval($factory['type']),
|
||||||
'expert_type' => $expertType,
|
'expert_type' => intval($factory['expert_type']),
|
||||||
'task_name' => $taskName ?: ('Task ' . date('Y-m-d H:i')),
|
'task_name' => $taskName,
|
||||||
'total_count' => count($experts),
|
'total_count' => count($experts),
|
||||||
'sent_count' => 0,
|
'sent_count' => 0,
|
||||||
'fail_count' => 0,
|
'fail_count' => 0,
|
||||||
@@ -1501,6 +1527,7 @@ class EmailClient extends Base
|
|||||||
}
|
}
|
||||||
return jsonSuccess([
|
return jsonSuccess([
|
||||||
'task_id' => $taskId,
|
'task_id' => $taskId,
|
||||||
|
'factory_id' => $factoryId,
|
||||||
'total_count' => count($experts),
|
'total_count' => count($experts),
|
||||||
'state' => 0,
|
'state' => 0,
|
||||||
'send_date' => $sendDateVal,
|
'send_date' => $sendDateVal,
|
||||||
@@ -1583,32 +1610,7 @@ class EmailClient extends Base
|
|||||||
|
|
||||||
// ==================== Journal Promotion Field Mapping ====================
|
// ==================== Journal Promotion Field Mapping ====================
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取某期刊已选的推广领域
|
|
||||||
* 参数: journal_id
|
|
||||||
*/
|
|
||||||
public function getJournalPromotionFields()
|
|
||||||
{
|
|
||||||
$journalId = intval($this->request->param('journal_id', 0));
|
|
||||||
if (!$journalId) {
|
|
||||||
return jsonError('journal_id is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
$list = Db::name('journal_promotion_field')
|
|
||||||
->alias('jpf')
|
|
||||||
->join('t_expert_fetch ef', 'ef.expert_fetch_id = jpf.expert_fetch_id', 'left')
|
|
||||||
->where('jpf.journal_id', $journalId)
|
|
||||||
->where('jpf.state', 0)
|
|
||||||
->field('jpf.jpf_id, jpf.expert_fetch_id, ef.field, ef.source, ef.state as fetch_state, jpf.ctime')
|
|
||||||
->order('jpf.jpf_id asc')
|
|
||||||
->select();
|
|
||||||
|
|
||||||
foreach ($list as &$item) {
|
|
||||||
$item['ctime_text'] = $item['ctime'] ? date('Y-m-d H:i:s', $item['ctime']) : '';
|
|
||||||
}
|
|
||||||
|
|
||||||
return jsonSuccess($list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置/更新期刊的推广领域(全量覆盖)
|
* 设置/更新期刊的推广领域(全量覆盖)
|
||||||
@@ -1872,6 +1874,8 @@ class EmailClient extends Base
|
|||||||
public function getTaskList()
|
public function getTaskList()
|
||||||
{
|
{
|
||||||
$journalId = intval($this->request->param('journal_id', 0));
|
$journalId = intval($this->request->param('journal_id', 0));
|
||||||
|
$factoryId = $this->request->param('factory_id', '');
|
||||||
|
$type = $this->request->param('type', '');
|
||||||
$state = $this->request->param('state', '-1');
|
$state = $this->request->param('state', '-1');
|
||||||
$page = max(1, intval($this->request->param('page', 1)));
|
$page = max(1, intval($this->request->param('page', 1)));
|
||||||
$perPage = max(1, min(intval($this->request->param('per_page', 20)), 100));
|
$perPage = max(1, min(intval($this->request->param('per_page', 20)), 100));
|
||||||
@@ -1880,6 +1884,12 @@ class EmailClient extends Base
|
|||||||
if ($journalId) {
|
if ($journalId) {
|
||||||
$where['journal_id'] = $journalId;
|
$where['journal_id'] = $journalId;
|
||||||
}
|
}
|
||||||
|
if ($factoryId !== '' && $factoryId !== '-1') {
|
||||||
|
$where['factory_id'] = intval($factoryId);
|
||||||
|
}
|
||||||
|
if ($type !== '' && $type !== '-1') {
|
||||||
|
$where['type'] = intval($type);
|
||||||
|
}
|
||||||
if ($state !== '-1' && $state !== '') {
|
if ($state !== '-1' && $state !== '') {
|
||||||
$where['state'] = intval($state);
|
$where['state'] = intval($state);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,6 +133,19 @@ class PromotionFactory extends Base
|
|||||||
return jsonSuccess(['promotion_factory_id' => $id]);
|
return jsonSuccess(['promotion_factory_id' => $id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function changePromotionAct(){
|
||||||
|
$data = $this->request->post();
|
||||||
|
$rule = new Validate([
|
||||||
|
"promotion_factory_id"=>"require",
|
||||||
|
"start_promotion"=>"require"
|
||||||
|
]);
|
||||||
|
if(!$rule->check($data)){
|
||||||
|
return jsonError($rule->getError());
|
||||||
|
}
|
||||||
|
Db::name("promotion_factory")->where("promotion_factory_id",$data['promotion_factory_id'])->update(['start_promotion'=>$data['start_promotion']]);
|
||||||
|
return jsonSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
public function getCountForPromotionEmailIds(){
|
public function getCountForPromotionEmailIds(){
|
||||||
$data = $this->request->post();
|
$data = $this->request->post();
|
||||||
$rule = new Validate([
|
$rule = new Validate([
|
||||||
|
|||||||
Reference in New Issue
Block a user