From 76692e00213f9ce73804f23c81ea21374977ed61 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 8 Jul 2026 01:07:08 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8F=B7=E7=A0=81=E6=95=B0?= =?UTF-8?q?=E9=87=8F=E5=88=97=E7=9A=84=E6=95=B0=E6=8D=AE=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/command/Install/split_ticket.sql | 1 + .../split_ticket_active_number_count.sql | 21 +++ application/admin/controller/split/Number.php | 54 +++++++ application/admin/controller/split/Ticket.php | 1 + .../SplitTicketActiveNumberCountService.php | 151 ++++++++++++++++++ .../common/service/SplitTicketRuleService.php | 4 + .../admin/command/Install/split_ticket.sql | 1 + .../split_ticket_active_number_count.sql | 21 +++ .../admin/command/SplitSyncTickets.php | 16 +- .../admin/controller/split/Number.php | 54 +++++++ .../admin/controller/split/Ticket.php | 1 + .../SplitTicketActiveNumberCountService.php | 151 ++++++++++++++++++ .../common/service/SplitTicketRuleService.php | 4 + .../SplitTicketSyncDispatchService.php | 16 +- .../public/assets/js/backend/split/ticket.js | 15 +- public/assets/js/backend/split/ticket.js | 15 +- 16 files changed, 497 insertions(+), 29 deletions(-) create mode 100644 application/admin/command/Install/split_ticket_active_number_count.sql create mode 100644 application/common/service/SplitTicketActiveNumberCountService.php create mode 100644 patches/application/admin/command/Install/split_ticket_active_number_count.sql create mode 100644 patches/application/common/service/SplitTicketActiveNumberCountService.php diff --git a/application/admin/command/Install/split_ticket.sql b/application/admin/command/Install/split_ticket.sql index e0677c6..b0926b7 100755 --- a/application/admin/command/Install/split_ticket.sql +++ b/application/admin/command/Install/split_ticket.sql @@ -27,6 +27,7 @@ CREATE TABLE `fa_split_ticket` ( `number_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '号码数量含离线封号(同步)', `number_offline_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '离线号码数(同步)', `number_banned_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '封号号码数(同步)', + `active_number_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '本地开启号码数(status=normal)', `online_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '在线人数(同步)', `sync_status` enum('success','error','pending') NOT NULL DEFAULT 'pending' COMMENT '同步状态', `sync_time` bigint(16) DEFAULT NULL COMMENT '最近同步时间', diff --git a/application/admin/command/Install/split_ticket_active_number_count.sql b/application/admin/command/Install/split_ticket_active_number_count.sql new file mode 100644 index 0000000..2d2e320 --- /dev/null +++ b/application/admin/command/Install/split_ticket_active_number_count.sql @@ -0,0 +1,21 @@ +-- 工单表:本地开启号码数(status=normal),列表直接读字段,避免子查询 +SET NAMES utf8mb4; + +ALTER TABLE `fa_split_ticket` + ADD COLUMN `active_number_count` int(10) unsigned NOT NULL DEFAULT 0 + COMMENT '本地开启号码数(status=normal)' AFTER `number_banned_count`; + +-- 历史数据回填 +UPDATE `fa_split_ticket` t +SET t.`active_number_count` = ( + SELECT COUNT(*) + FROM `fa_split_number` n + WHERE n.`admin_id` = t.`admin_id` + AND n.`split_link_id` = t.`split_link_id` + AND n.`ticket_name` = t.`ticket_name` + AND n.`status` = 'normal' +); + +-- 加速按工单统计 status=normal 数量 +ALTER TABLE `fa_split_number` + ADD KEY `idx_ticket_active` (`admin_id`, `split_link_id`, `ticket_name`(50), `status`); diff --git a/application/admin/controller/split/Number.php b/application/admin/controller/split/Number.php index 07fc38d..cb78cc6 100755 --- a/application/admin/controller/split/Number.php +++ b/application/admin/controller/split/Number.php @@ -7,6 +7,7 @@ namespace app\admin\controller\split; use app\admin\model\split\Link as LinkModel; use app\admin\model\split\Number as NumberModel; use app\common\controller\Backend; +use app\common\service\SplitTicketActiveNumberCountService; use think\Db; use think\Exception; use think\exception\DbException; @@ -225,6 +226,7 @@ class Number extends Backend $this->error($e->getMessage()); } if ($count > 0) { + (new SplitTicketActiveNumberCountService())->refreshForNumberIds(explode(',', (string) $ids)); $this->success(); } $this->error(__('No rows were updated')); @@ -331,6 +333,12 @@ class Number extends Backend $this->error($e->getMessage()); } + (new SplitTicketActiveNumberCountService())->refreshForTicketKeys( + (int) ($baseRow['admin_id'] ?? $adminId), + $splitLinkId, + (string) ($baseRow['ticket_name'] ?? '') + ); + $msg = __('Inserted %d number(s)', $inserted); if ($skipped > 0) { $msg .= ',' . __('Skipped %d duplicate(s)', $skipped); @@ -378,6 +386,7 @@ class Number extends Backend } $result = false; + $before = $row->getData(); Db::startTrans(); try { if ($this->modelValidate) { @@ -397,9 +406,50 @@ class Number extends Backend if ($result === false) { $this->error(__('No rows were updated')); } + (new SplitTicketActiveNumberCountService())->refreshAfterNumberEdit($before, $row->getData()); $this->success(); } + /** + * 删除号码后回写工单本地开启号码数 + * + * @param string|null $ids + */ + public function del($ids = null) + { + if (false === $this->request->isPost()) { + $this->error(__('Invalid parameters')); + } + $ids = $ids ?: $this->request->post('ids'); + if (empty($ids)) { + $this->error(__('Parameter %s can not be empty', 'ids')); + } + $pk = $this->model->getPk(); + $adminIds = $this->getDataLimitAdminIds(); + if (is_array($adminIds)) { + $this->model->where($this->dataLimitField, 'in', $adminIds); + } + $list = $this->model->where($pk, 'in', $ids)->select(); + + $count = 0; + $countService = new SplitTicketActiveNumberCountService(); + Db::startTrans(); + try { + foreach ($list as $item) { + $count += $item->delete(); + } + Db::commit(); + } catch (PDOException|Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + if ($count) { + $countService->refreshFromNumberRows($list); + $this->success(); + } + $this->error(__('No rows were deleted')); + } + /** * 批量更新号码状态与手动管理 */ @@ -444,6 +494,7 @@ class Number extends Backend if ($count === false || $count === 0) { $this->error(__('No rows were updated')); } + (new SplitTicketActiveNumberCountService())->refreshForNumberIds($ids); $this->success(__('Batch update success')); } @@ -496,6 +547,8 @@ class Number extends Backend } $count = 0; + $countService = new SplitTicketActiveNumberCountService(); + $keyRows = (clone $query)->field('admin_id,split_link_id,ticket_name')->select(); Db::startTrans(); try { if ($action === 'delete') { @@ -523,6 +576,7 @@ class Number extends Backend $this->error(__('No matching numbers found')); } + $countService->refreshFromNumberRows($keyRows); $this->success(sprintf(__('Batch operate success'), $count)); } diff --git a/application/admin/controller/split/Ticket.php b/application/admin/controller/split/Ticket.php index 7317e41..2babeff 100755 --- a/application/admin/controller/split/Ticket.php +++ b/application/admin/controller/split/Ticket.php @@ -268,6 +268,7 @@ class Ticket extends Backend $params['inbound_count'], $params['speed_per_hour'], $params['number_count'], + $params['active_number_count'], $params['number_offline_count'], $params['number_banned_count'], $params['online_count'], diff --git a/application/common/service/SplitTicketActiveNumberCountService.php b/application/common/service/SplitTicketActiveNumberCountService.php new file mode 100644 index 0000000..7890a7a --- /dev/null +++ b/application/common/service/SplitTicketActiveNumberCountService.php @@ -0,0 +1,151 @@ +where('split_link_id', $linkId) + ->where('ticket_name', $ticketName) + ->where('status', 'normal') + ->count(); + + Ticket::where('admin_id', $adminId) + ->where('split_link_id', $linkId) + ->where('ticket_name', $ticketName) + ->update([ + 'active_number_count' => $count, + 'updatetime' => time(), + ]); + } + + /** + * 按工单模型回写 + */ + public function refreshForTicket(Ticket $ticket): void + { + $this->refreshForTicketKeys( + (int) $ticket['admin_id'], + (int) $ticket['split_link_id'], + (string) $ticket['ticket_name'] + ); + } + + /** + * 批量号码 ID:去重后刷新涉及工单 + * + * @param array $ids + */ + public function refreshForNumberIds(array $ids): void + { + $ids = array_values(array_filter(array_map('intval', $ids))); + if ($ids === []) { + return; + } + + $rows = Number::where('id', 'in', $ids) + ->field('admin_id,split_link_id,ticket_name') + ->select(); + + $this->refreshFromNumberRows($rows); + } + + /** + * 编辑单条号码:关联键变更时刷新旧工单与新工单 + * + * @param array $before + * @param array $after + */ + public function refreshAfterNumberEdit(array $before, array $after): void + { + $keys = []; + $beforeKey = $this->buildTicketKeyFromRow($before); + if ($beforeKey !== null) { + $keys[] = $beforeKey; + } + $afterKey = $this->buildTicketKeyFromRow($after); + if ($afterKey !== null) { + $keys[] = $afterKey; + } + $this->refreshForTicketKeyList($keys); + } + + /** + * 批量工单关联键去重后刷新 + * + * @param array $keys + */ + public function refreshForTicketKeyList(array $keys): void + { + $seen = []; + foreach ($keys as $key) { + if (!is_array($key) || count($key) < 3) { + continue; + } + $adminId = (int) $key[0]; + $linkId = (int) $key[1]; + $ticketName = trim((string) $key[2]); + if ($adminId <= 0 || $linkId <= 0 || $ticketName === '') { + continue; + } + $hash = $adminId . ':' . $linkId . ':' . $ticketName; + if (isset($seen[$hash])) { + continue; + } + $seen[$hash] = true; + $this->refreshForTicketKeys($adminId, $linkId, $ticketName); + } + } + + /** + * @param iterable|Number> $rows + */ + public function refreshFromNumberRows(iterable $rows): void + { + $keys = []; + foreach ($rows as $row) { + $data = $row instanceof Number ? $row->getData() : (array) $row; + $key = $this->buildTicketKeyFromRow($data); + if ($key !== null) { + $keys[] = $key; + } + } + $this->refreshForTicketKeyList($keys); + } + + /** + * @param array $row + * @return array{0:int,1:int,2:string}|null + */ + private function buildTicketKeyFromRow(array $row): ?array + { + $adminId = (int) ($row['admin_id'] ?? 0); + $linkId = (int) ($row['split_link_id'] ?? 0); + $ticketName = trim((string) ($row['ticket_name'] ?? '')); + if ($adminId <= 0 || $linkId <= 0 || $ticketName === '') { + return null; + } + + return [$adminId, $linkId, $ticketName]; + } +} diff --git a/application/common/service/SplitTicketRuleService.php b/application/common/service/SplitTicketRuleService.php index 4e8c44f..660a839 100755 --- a/application/common/service/SplitTicketRuleService.php +++ b/application/common/service/SplitTicketRuleService.php @@ -76,6 +76,8 @@ class SplitTicketRuleService 'status' => 'hidden', 'updatetime' => time(), ]); + + (new SplitTicketActiveNumberCountService())->refreshForTicket($ticket); } /** @@ -185,6 +187,8 @@ class SplitTicketRuleService Number::where('id', (int) $number['id'])->update($update); } + + (new SplitTicketActiveNumberCountService())->refreshForTicket($ticket); } /** diff --git a/patches/application/admin/command/Install/split_ticket.sql b/patches/application/admin/command/Install/split_ticket.sql index e0677c6..b0926b7 100755 --- a/patches/application/admin/command/Install/split_ticket.sql +++ b/patches/application/admin/command/Install/split_ticket.sql @@ -27,6 +27,7 @@ CREATE TABLE `fa_split_ticket` ( `number_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '号码数量含离线封号(同步)', `number_offline_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '离线号码数(同步)', `number_banned_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '封号号码数(同步)', + `active_number_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '本地开启号码数(status=normal)', `online_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '在线人数(同步)', `sync_status` enum('success','error','pending') NOT NULL DEFAULT 'pending' COMMENT '同步状态', `sync_time` bigint(16) DEFAULT NULL COMMENT '最近同步时间', diff --git a/patches/application/admin/command/Install/split_ticket_active_number_count.sql b/patches/application/admin/command/Install/split_ticket_active_number_count.sql new file mode 100644 index 0000000..2d2e320 --- /dev/null +++ b/patches/application/admin/command/Install/split_ticket_active_number_count.sql @@ -0,0 +1,21 @@ +-- 工单表:本地开启号码数(status=normal),列表直接读字段,避免子查询 +SET NAMES utf8mb4; + +ALTER TABLE `fa_split_ticket` + ADD COLUMN `active_number_count` int(10) unsigned NOT NULL DEFAULT 0 + COMMENT '本地开启号码数(status=normal)' AFTER `number_banned_count`; + +-- 历史数据回填 +UPDATE `fa_split_ticket` t +SET t.`active_number_count` = ( + SELECT COUNT(*) + FROM `fa_split_number` n + WHERE n.`admin_id` = t.`admin_id` + AND n.`split_link_id` = t.`split_link_id` + AND n.`ticket_name` = t.`ticket_name` + AND n.`status` = 'normal' +); + +-- 加速按工单统计 status=normal 数量 +ALTER TABLE `fa_split_number` + ADD KEY `idx_ticket_active` (`admin_id`, `split_link_id`, `ticket_name`(50), `status`); diff --git a/patches/application/admin/command/SplitSyncTickets.php b/patches/application/admin/command/SplitSyncTickets.php index 6cdebeb..63ea1fe 100755 --- a/patches/application/admin/command/SplitSyncTickets.php +++ b/patches/application/admin/command/SplitSyncTickets.php @@ -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('跳过: ' . ($result['message'] ?? '') . ''); return; @@ -71,4 +75,14 @@ class SplitSyncTickets extends Command $output->writeln('详细调试日志已写入 runtime/log/split_sync.log'); } } + + /** + * 解析 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'; + } } diff --git a/patches/application/admin/controller/split/Number.php b/patches/application/admin/controller/split/Number.php index 07fc38d..cb78cc6 100755 --- a/patches/application/admin/controller/split/Number.php +++ b/patches/application/admin/controller/split/Number.php @@ -7,6 +7,7 @@ namespace app\admin\controller\split; use app\admin\model\split\Link as LinkModel; use app\admin\model\split\Number as NumberModel; use app\common\controller\Backend; +use app\common\service\SplitTicketActiveNumberCountService; use think\Db; use think\Exception; use think\exception\DbException; @@ -225,6 +226,7 @@ class Number extends Backend $this->error($e->getMessage()); } if ($count > 0) { + (new SplitTicketActiveNumberCountService())->refreshForNumberIds(explode(',', (string) $ids)); $this->success(); } $this->error(__('No rows were updated')); @@ -331,6 +333,12 @@ class Number extends Backend $this->error($e->getMessage()); } + (new SplitTicketActiveNumberCountService())->refreshForTicketKeys( + (int) ($baseRow['admin_id'] ?? $adminId), + $splitLinkId, + (string) ($baseRow['ticket_name'] ?? '') + ); + $msg = __('Inserted %d number(s)', $inserted); if ($skipped > 0) { $msg .= ',' . __('Skipped %d duplicate(s)', $skipped); @@ -378,6 +386,7 @@ class Number extends Backend } $result = false; + $before = $row->getData(); Db::startTrans(); try { if ($this->modelValidate) { @@ -397,9 +406,50 @@ class Number extends Backend if ($result === false) { $this->error(__('No rows were updated')); } + (new SplitTicketActiveNumberCountService())->refreshAfterNumberEdit($before, $row->getData()); $this->success(); } + /** + * 删除号码后回写工单本地开启号码数 + * + * @param string|null $ids + */ + public function del($ids = null) + { + if (false === $this->request->isPost()) { + $this->error(__('Invalid parameters')); + } + $ids = $ids ?: $this->request->post('ids'); + if (empty($ids)) { + $this->error(__('Parameter %s can not be empty', 'ids')); + } + $pk = $this->model->getPk(); + $adminIds = $this->getDataLimitAdminIds(); + if (is_array($adminIds)) { + $this->model->where($this->dataLimitField, 'in', $adminIds); + } + $list = $this->model->where($pk, 'in', $ids)->select(); + + $count = 0; + $countService = new SplitTicketActiveNumberCountService(); + Db::startTrans(); + try { + foreach ($list as $item) { + $count += $item->delete(); + } + Db::commit(); + } catch (PDOException|Exception $e) { + Db::rollback(); + $this->error($e->getMessage()); + } + if ($count) { + $countService->refreshFromNumberRows($list); + $this->success(); + } + $this->error(__('No rows were deleted')); + } + /** * 批量更新号码状态与手动管理 */ @@ -444,6 +494,7 @@ class Number extends Backend if ($count === false || $count === 0) { $this->error(__('No rows were updated')); } + (new SplitTicketActiveNumberCountService())->refreshForNumberIds($ids); $this->success(__('Batch update success')); } @@ -496,6 +547,8 @@ class Number extends Backend } $count = 0; + $countService = new SplitTicketActiveNumberCountService(); + $keyRows = (clone $query)->field('admin_id,split_link_id,ticket_name')->select(); Db::startTrans(); try { if ($action === 'delete') { @@ -523,6 +576,7 @@ class Number extends Backend $this->error(__('No matching numbers found')); } + $countService->refreshFromNumberRows($keyRows); $this->success(sprintf(__('Batch operate success'), $count)); } diff --git a/patches/application/admin/controller/split/Ticket.php b/patches/application/admin/controller/split/Ticket.php index 7317e41..2babeff 100755 --- a/patches/application/admin/controller/split/Ticket.php +++ b/patches/application/admin/controller/split/Ticket.php @@ -268,6 +268,7 @@ class Ticket extends Backend $params['inbound_count'], $params['speed_per_hour'], $params['number_count'], + $params['active_number_count'], $params['number_offline_count'], $params['number_banned_count'], $params['online_count'], diff --git a/patches/application/common/service/SplitTicketActiveNumberCountService.php b/patches/application/common/service/SplitTicketActiveNumberCountService.php new file mode 100644 index 0000000..7890a7a --- /dev/null +++ b/patches/application/common/service/SplitTicketActiveNumberCountService.php @@ -0,0 +1,151 @@ +where('split_link_id', $linkId) + ->where('ticket_name', $ticketName) + ->where('status', 'normal') + ->count(); + + Ticket::where('admin_id', $adminId) + ->where('split_link_id', $linkId) + ->where('ticket_name', $ticketName) + ->update([ + 'active_number_count' => $count, + 'updatetime' => time(), + ]); + } + + /** + * 按工单模型回写 + */ + public function refreshForTicket(Ticket $ticket): void + { + $this->refreshForTicketKeys( + (int) $ticket['admin_id'], + (int) $ticket['split_link_id'], + (string) $ticket['ticket_name'] + ); + } + + /** + * 批量号码 ID:去重后刷新涉及工单 + * + * @param array $ids + */ + public function refreshForNumberIds(array $ids): void + { + $ids = array_values(array_filter(array_map('intval', $ids))); + if ($ids === []) { + return; + } + + $rows = Number::where('id', 'in', $ids) + ->field('admin_id,split_link_id,ticket_name') + ->select(); + + $this->refreshFromNumberRows($rows); + } + + /** + * 编辑单条号码:关联键变更时刷新旧工单与新工单 + * + * @param array $before + * @param array $after + */ + public function refreshAfterNumberEdit(array $before, array $after): void + { + $keys = []; + $beforeKey = $this->buildTicketKeyFromRow($before); + if ($beforeKey !== null) { + $keys[] = $beforeKey; + } + $afterKey = $this->buildTicketKeyFromRow($after); + if ($afterKey !== null) { + $keys[] = $afterKey; + } + $this->refreshForTicketKeyList($keys); + } + + /** + * 批量工单关联键去重后刷新 + * + * @param array $keys + */ + public function refreshForTicketKeyList(array $keys): void + { + $seen = []; + foreach ($keys as $key) { + if (!is_array($key) || count($key) < 3) { + continue; + } + $adminId = (int) $key[0]; + $linkId = (int) $key[1]; + $ticketName = trim((string) $key[2]); + if ($adminId <= 0 || $linkId <= 0 || $ticketName === '') { + continue; + } + $hash = $adminId . ':' . $linkId . ':' . $ticketName; + if (isset($seen[$hash])) { + continue; + } + $seen[$hash] = true; + $this->refreshForTicketKeys($adminId, $linkId, $ticketName); + } + } + + /** + * @param iterable|Number> $rows + */ + public function refreshFromNumberRows(iterable $rows): void + { + $keys = []; + foreach ($rows as $row) { + $data = $row instanceof Number ? $row->getData() : (array) $row; + $key = $this->buildTicketKeyFromRow($data); + if ($key !== null) { + $keys[] = $key; + } + } + $this->refreshForTicketKeyList($keys); + } + + /** + * @param array $row + * @return array{0:int,1:int,2:string}|null + */ + private function buildTicketKeyFromRow(array $row): ?array + { + $adminId = (int) ($row['admin_id'] ?? 0); + $linkId = (int) ($row['split_link_id'] ?? 0); + $ticketName = trim((string) ($row['ticket_name'] ?? '')); + if ($adminId <= 0 || $linkId <= 0 || $ticketName === '') { + return null; + } + + return [$adminId, $linkId, $ticketName]; + } +} diff --git a/patches/application/common/service/SplitTicketRuleService.php b/patches/application/common/service/SplitTicketRuleService.php index 4e8c44f..660a839 100755 --- a/patches/application/common/service/SplitTicketRuleService.php +++ b/patches/application/common/service/SplitTicketRuleService.php @@ -76,6 +76,8 @@ class SplitTicketRuleService 'status' => 'hidden', 'updatetime' => time(), ]); + + (new SplitTicketActiveNumberCountService())->refreshForTicket($ticket); } /** @@ -185,6 +187,8 @@ class SplitTicketRuleService Number::where('id', (int) $number['id'])->update($update); } + + (new SplitTicketActiveNumberCountService())->refreshForTicket($ticket); } /** diff --git a/patches/application/common/service/SplitTicketSyncDispatchService.php b/patches/application/common/service/SplitTicketSyncDispatchService.php index 4957d14..161d3ca 100755 --- a/patches/application/common/service/SplitTicketSyncDispatchService.php +++ b/patches/application/common/service/SplitTicketSyncDispatchService.php @@ -378,11 +378,13 @@ class SplitTicketSyncDispatchService $logDir = $this->resolveLogDir(); $logFile = $logDir . 'cli_' . $ticketId . '_' . date('YmdHis') . '.log'; + $syncMode = $this->normalizeSyncModeForCli($source); $inner = sprintf( - '%s %s split:sync-tickets --ticket=%d >> %s 2>&1', + '%s %s split:sync-tickets --ticket=%d --mode=%s >> %s 2>&1', escapeshellarg($php), escapeshellarg($think), $ticketId, + $syncMode, escapeshellarg($logFile) ); @@ -408,11 +410,13 @@ class SplitTicketSyncDispatchService continue; } $logFile = $logDir . 'cli_' . $ticketId . '_' . date('YmdHis') . '.log'; + $syncMode = $this->normalizeSyncModeForCli($source); $parts[] = sprintf( - '%s %s split:sync-tickets --ticket=%d >> %s 2>&1', + '%s %s split:sync-tickets --ticket=%d --mode=%s >> %s 2>&1', escapeshellarg($php), escapeshellarg($think), $ticketId, + $syncMode, escapeshellarg($logFile) ); } @@ -557,4 +561,12 @@ class SplitTicketSyncDispatchService { return function_exists('shell_exec') && !in_array('shell_exec', $this->disabledFunctions(), true); } + + /** + * 投递 CLI 时携带 --mode,供 sync_success_mode 区分自动/手动 + */ + private function normalizeSyncModeForCli(string $source): string + { + return in_array($source, ['auto', 'manual'], true) ? $source : 'manual'; + } } diff --git a/patches/public/assets/js/backend/split/ticket.js b/patches/public/assets/js/backend/split/ticket.js index 07f1ab5..3c8dc62 100755 --- a/patches/public/assets/js/backend/split/ticket.js +++ b/patches/public/assets/js/backend/split/ticket.js @@ -88,10 +88,9 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin formatter: Controller.api.formatter.speedPerHour }, { - field: 'number_count', + field: 'active_number_count', title: __('Number_count'), - operate: false, - formatter: Controller.api.formatter.numberCount + operate: false }, { field: 'sync_display_text', @@ -486,16 +485,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin } return num.toFixed(2); }, - numberCount: function (value, row) { - var total = parseInt(value, 10) || 0; - var offline = parseInt(row.number_offline_count, 10) || 0; - var banned = parseInt(row.number_banned_count, 10) || 0; - var tip = __('Number_count_detail').replace('%s', offline).replace('%s', banned); - if (offline > 0 || banned > 0) { - return '' + total + ''; - } - return String(total); - }, syncDisplay: function (value, row) { var rowId = parseInt(row.id, 10); if (Controller.api.syncingTicketIds.indexOf(rowId) !== -1) { diff --git a/public/assets/js/backend/split/ticket.js b/public/assets/js/backend/split/ticket.js index 07f1ab5..3c8dc62 100755 --- a/public/assets/js/backend/split/ticket.js +++ b/public/assets/js/backend/split/ticket.js @@ -88,10 +88,9 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin formatter: Controller.api.formatter.speedPerHour }, { - field: 'number_count', + field: 'active_number_count', title: __('Number_count'), - operate: false, - formatter: Controller.api.formatter.numberCount + operate: false }, { field: 'sync_display_text', @@ -486,16 +485,6 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin } return num.toFixed(2); }, - numberCount: function (value, row) { - var total = parseInt(value, 10) || 0; - var offline = parseInt(row.number_offline_count, 10) || 0; - var banned = parseInt(row.number_banned_count, 10) || 0; - var tip = __('Number_count_detail').replace('%s', offline).replace('%s', banned); - if (offline > 0 || banned > 0) { - return '' + total + ''; - } - return String(total); - }, syncDisplay: function (value, row) { var rowId = parseInt(row.id, 10); if (Controller.api.syncingTicketIds.indexOf(rowId) !== -1) {