修复随机号码前先按权重随机工单,并修复降权号码筛选与清理

This commit is contained in:
root
2026-07-04 22:09:39 +08:00
parent 9b57b0c400
commit 6b72cd7b67
37 changed files with 2201 additions and 473 deletions
@@ -0,0 +1,21 @@
-- 号码管理:清理无效降权池权限节点
INSERT INTO `fa_auth_rule` (`type`, `pid`, `name`, `title`, `icon`, `condition`, `remark`, `ismenu`, `createtime`, `updatetime`, `weigh`, `status`)
SELECT 'file', m.id, 'split.number/cleanupdeferred', '清理降权池', 'fa fa-circle-o', '', '清除无落地页访问基线的无效 ratio_deferred 标记', 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 0, 'normal'
FROM `fa_auth_rule` m
WHERE m.name = 'split.number' AND m.ismenu = 1
AND NOT EXISTS (SELECT 1 FROM `fa_auth_rule` WHERE `name` = 'split.number/cleanupdeferred' LIMIT 1)
LIMIT 1;
-- 可选:一次性修复历史脏数据(与后台「清理降权池」逻辑一致)
-- UPDATE `fa_split_number`
-- SET `ratio_deferred` = 0, `ratio_deferred_at` = NULL,
-- `no_inbound_click_streak` = IF(`visit_count` <= 0, 0, `no_inbound_click_streak`)
-- WHERE `ratio_deferred` = 1
-- AND (`visit_count` <= 0 OR `visit_count` <= `last_sync_visit_count`);
INSERT INTO `fa_auth_rule` (`type`, `pid`, `name`, `title`, `icon`, `condition`, `remark`, `ismenu`, `createtime`, `updatetime`, `weigh`, `status`)
SELECT 'file', m.id, 'split.number/cleanupdeferredpreview', '清理降权池预览', 'fa fa-circle-o', '', '', 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 0, 'normal'
FROM `fa_auth_rule` m
WHERE m.name = 'split.number' AND m.ismenu = 1
AND NOT EXISTS (SELECT 1 FROM `fa_auth_rule` WHERE `name` = 'split.number/cleanupdeferredpreview' LIMIT 1)
LIMIT 1;
+17 -3
View File
@@ -18,6 +18,7 @@ use think\console\Output;
* 用法:
* php think split:sync-tickets
* php think split:sync-tickets --ticket=12
* php think split:sync-tickets --ticket=12 --mode=auto
*/
class SplitSyncTickets extends Command
{
@@ -25,21 +26,24 @@ class SplitSyncTickets extends Command
{
$this->setName('split:sync-tickets')
->addOption('ticket', 't', Option::VALUE_OPTIONAL, '指定工单 ID(强制同步,忽略周期)', '')
->addOption('mode', 'm', Option::VALUE_OPTIONAL, '同步方式: auto=定时自动, manual=手动触发', 'manual')
->setDescription('同步分流工单云控数据');
}
protected function execute(Input $input, Output $output): void
{
set_time_limit(0);
$syncMode = $this->resolveSyncMode($input);
SplitTicketSyncLogger::log('cli', 'command start', [
'ticketOption' => trim((string) $input->getOption('ticket')),
'syncMode' => $syncMode,
'appDebug' => SplitTicketSyncLogger::isEnabled(),
]);
$service = new SplitTicketSyncService();
$ticketId = trim((string) $input->getOption('ticket'));
if ($ticketId !== '' && ctype_digit($ticketId)) {
$result = $service->syncOne((int) $ticketId, true);
$result = $service->syncOne((int) $ticketId, true, false, $syncMode);
if (!empty($result['skipped'])) {
$output->writeln('<comment>跳过: ' . ($result['message'] ?? '') . '</comment>');
return;
@@ -61,8 +65,8 @@ class SplitSyncTickets extends Command
try {
$count = $service->syncDueTickets();
$output->writeln('<info>本次处理工单数: ' . $count . '</info>');
$output->writeln('<comment>汇总日志已写入 runtime/log/split_sync.log</comment>');
$output->writeln('<info>本次投递工单数: ' . $count . '</info>');
$output->writeln('<comment>同步在后台 CLI 进程中执行,汇总日志 runtime/log/split_sync.log</comment>');
} finally {
$cronLock->release();
}
@@ -71,4 +75,14 @@ class SplitSyncTickets extends Command
$output->writeln('<comment>详细调试日志已写入 runtime/log/split_sync.log</comment>');
}
}
/**
* 解析 CLI 同步方式,供 sync_success_mode 落库
*/
private function resolveSyncMode(Input $input): string
{
$mode = strtolower(trim((string) $input->getOption('mode')));
return in_array($mode, ['auto', 'manual'], true) ? $mode : 'manual';
}
}
@@ -65,6 +65,7 @@ class Number extends Backend
$this->assignconfig('statusList', $this->model->getStatusList());
$this->assignconfig('manualManageList', $this->model->getManualManageList());
$this->assignconfig('platformStatusList', $this->model->getPlatformStatusList());
$this->assignconfig('ratioDeferredList', $this->model->getRatioDeferredList());
$this->assignconfig('splitLinkFilterList', $this->buildNumberSplitLinkFilterList());
$this->assignconfig('splitLinkSelectList', $this->buildSplitLinkSelectConfig());
@@ -525,6 +526,47 @@ class Number extends Backend
$this->success(sprintf(__('Batch operate success'), $count));
}
/**
* 预览待清理的无效降权号码数量
*/
public function cleanupdeferredpreview(): void
{
if (false === $this->request->isAjax()) {
$this->error(__('Invalid parameters'));
}
$service = new \app\common\service\SplitNumberRatioDeferredService();
$adminIds = $this->dataLimit ? $this->getDataLimitAdminIds() : null;
$count = $service->countInvalidDeferred(is_array($adminIds) ? $adminIds : null);
$this->success('', null, ['count' => $count]);
}
/**
* 清理无效降权号码池(无落地页访问基线却标记 ratio_deferred=1 的记录)
*/
public function cleanupdeferred(): void
{
if (false === $this->request->isPost()) {
$this->error(__('Invalid parameters'));
}
$service = new \app\common\service\SplitNumberRatioDeferredService();
$adminIds = $this->dataLimit ? $this->getDataLimitAdminIds() : null;
try {
$count = $service->cleanupInvalidDeferred(is_array($adminIds) ? $adminIds : null);
} catch (\Throwable $e) {
$this->error($e->getMessage());
}
if ($count <= 0) {
$this->success(__('Ratio deferred cleanup none'));
}
$this->success(sprintf(__('Ratio deferred cleanup success'), $count));
}
/**
* 排除不可由表单提交的字段
*
@@ -51,4 +51,16 @@ return [
'Invalid manual manage' => '手动管理选项无效',
'Batch update success' => '批量更新成功',
'Unit count' => '个',
'Ratio_deferred' => '选号降权',
'Ratio deferred badge' => '降权中',
'Ratio deferred no' => '正常选号',
'Ratio deferred yes' => '降权中',
'Ratio deferred filter' => '仅显示降权中号码',
'Ratio deferred tooltip'=> '连续 %s 次访问无进线增长,已触线下号比率,选号已后置,等待同步裁决',
'Ratio deferred edit notice' => '该号码处于下号比率触线降权状态,同步后将根据进线情况恢复或关闭',
'No inbound click streak' => '无进线连续点击',
'Ratio deferred cleanup btn' => '清理降权池',
'Ratio deferred cleanup confirm' => '将清除 %d 条无效降权记录(无落地页访问或访问未超过同步基线)。确定继续?',
'Ratio deferred cleanup success' => '已清理 %d 条无效降权记录',
'Ratio deferred cleanup none' => '当前没有需要清理的无效降权记录',
];
+19
View File
@@ -42,6 +42,7 @@ class Number extends Model
'status_text',
'manual_manage_text',
'platform_status_text',
'ratio_deferred_text',
];
/**
@@ -81,6 +82,17 @@ class Number extends Model
];
}
/**
* @return array<string, string>
*/
public function getRatioDeferredList(): array
{
return [
'0' => __('Ratio deferred no'),
'1' => __('Ratio deferred yes'),
];
}
/**
* @return array<string, string>
*/
@@ -158,6 +170,13 @@ class Number extends Model
return $list[$key] ?? $key;
}
public function getRatioDeferredTextAttr($value, $data): string
{
$key = (string) ((int) ($data['ratio_deferred'] ?? 0));
$list = $this->getRatioDeferredList();
return $list[$key] ?? $key;
}
/**
* 根据链接码生成完整分流 URL
*/
@@ -123,6 +123,13 @@
<div class="form-group">
{if isset($row)}
<label for="c-number" class="control-label">{:__('Number')}<span class="text-danger">*</span></label>
{if isset($row.ratio_deferred) && $row.ratio_deferred==1 && isset($row.status) && $row.status=='normal'}
<div class="alert alert-warning split-ratio-deferred-notice" style="margin-bottom:10px;padding:8px 12px;font-size:12px;">
<i class="fa fa-level-down"></i>
{:__('Ratio deferred edit notice')}
{:__('No inbound click streak')}{$row.no_inbound_click_streak|default=0}
</div>
{/if}
<input id="c-number" data-rule="required" class="form-control" name="row[number]" type="text" value="{$row.number|default=''|htmlentities}" maxlength="50">
{else}
<label for="c-numbers" class="control-label">{:__('Numbers')}<span class="text-danger">*</span></label>
@@ -18,6 +18,8 @@
<a href="javascript:;" class="btn btn-success btn-edit btn-disabled disabled {:$auth->check('split.number/edit')?'':'hide'}" title="{:__('Edit')}"><i class="fa fa-pencil"></i> {:__('Edit')}</a>
<a href="javascript:;" class="btn btn-danger btn-del btn-disabled disabled {:$auth->check('split.number/del')?'':'hide'}" title="{:__('Delete')}"><i class="fa fa-trash"></i> {:__('Delete')}</a>
<a href="javascript:;" class="btn btn-warning btn-batch-update-status btn-disabled disabled {:$auth->check('split.number/batchupdate')?'':'hide'}" title="{:__('Batch update btn')}"><i class="fa fa-edit"></i> {:__('Batch update btn')}</a>
<a href="javascript:;" class="btn btn-default btn-filter-ratio-deferred" title="{:__('Ratio deferred filter')}"><i class="fa fa-level-down text-warning"></i> {:__('Ratio deferred badge')}</a>
<a href="javascript:;" class="btn btn-warning btn-cleanup-ratio-deferred {:$auth->check('split.number/cleanupdeferred')?'':'hide'}" title="{:__('Ratio deferred cleanup btn')}"><i class="fa fa-eraser"></i> {:__('Ratio deferred cleanup btn')}</a>
<a href="javascript:;" class="btn btn-info btn-batch-operate {:$auth->check('split.number/batchoperate')?'':'hide'}" title="{:__('Batch operate btn')}"><i class="fa fa-list-alt"></i> {:__('Batch operate btn')}</a>
</div>
<table id="table" class="table table-striped table-bordered table-hover table-nowrap"