修正 Proxied、 SSL/TLS 设为 Flexible、开启 Always Use HTTPS

This commit is contained in:
root
2026-06-10 06:44:57 +08:00
parent a68b83fcbd
commit 5dea4c8b28
31 changed files with 950 additions and 160 deletions
@@ -15,6 +15,7 @@ CREATE TABLE `fa_split_number` (
`inbound_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '进线人数',
`manual_manage` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '手动管理:0=否,1=是',
`status` enum('normal','hidden') NOT NULL DEFAULT 'normal' COMMENT '状态:normal=正常,hidden=停用',
`weigh` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '排序权重(越大越靠前)',
`createtime` bigint(16) DEFAULT NULL COMMENT '创建时间',
`updatetime` bigint(16) DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
@@ -22,6 +23,7 @@ CREATE TABLE `fa_split_number` (
KEY `admin_id` (`admin_id`),
KEY `split_link_id` (`split_link_id`),
KEY `status` (`status`),
KEY `weigh` (`weigh`),
KEY `number` (`number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='分流号码表';
@@ -68,3 +70,10 @@ 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/batchupdate' LIMIT 1)
LIMIT 1;
INSERT INTO `fa_auth_rule` (`type`, `pid`, `name`, `title`, `icon`, `condition`, `remark`, `ismenu`, `createtime`, `updatetime`, `weigh`, `status`)
SELECT 'file', m.id, 'split.number/multi', '批量更新', '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/multi' LIMIT 1)
LIMIT 1;
@@ -4,6 +4,7 @@ declare(strict_types=1);
namespace app\admin\command;
use app\common\service\SplitTicketSyncLogger;
use app\common\service\SplitTicketSyncService;
use think\console\Command;
use think\console\Input;
@@ -29,6 +30,10 @@ class SplitSyncTickets extends Command
protected function execute(Input $input, Output $output): void
{
set_time_limit(0);
SplitTicketSyncLogger::log('cli', 'command start', [
'ticketOption' => trim((string) $input->getOption('ticket')),
'appDebug' => SplitTicketSyncLogger::isEnabled(),
]);
$service = new SplitTicketSyncService();
$ticketId = trim((string) $input->getOption('ticket'));
@@ -48,5 +53,8 @@ class SplitSyncTickets extends Command
$count = $service->syncDueTickets();
$output->writeln('<info>本次处理工单数: ' . $count . '</info>');
if (SplitTicketSyncLogger::isEnabled()) {
$output->writeln('<comment>调试日志已写入 runtime/log/split_sync.log</comment>');
}
}
}
+2 -7
View File
@@ -84,13 +84,8 @@ class Link extends Backend
$cfg = is_array($this->view->config ?? null) ? $this->view->config : [];
$version = (string) \think\Config::get('site.version');
$scriptUrl = (string) url('split.link/script', ['v' => $version], false, true);
if (strpos($scriptUrl, '?') === false) {
$scriptUrl .= '?v=' . $version;
}
if (strpos($scriptUrl, '://') === false) {
$scriptUrl = $this->request->domain() . $scriptUrl;
}
// 使用站内相对路径,避免生产环境 domain() 与反向代理/HTTPS 不一致导致 JS 跨域丢 Cookie
$scriptUrl = (string) url('split.link/script', ['v' => $version], '', false);
$cfg['jsname'] = $scriptUrl;
$this->view->assign('config', $cfg);
$this->view->config = $cfg;
+58 -7
View File
@@ -33,6 +33,9 @@ class Number extends Backend
protected $modelSceneValidate = true;
/** @var string */
protected $multiFields = 'status,manual_manage';
/** @var string[] */
protected $noNeedRight = ['script'];
@@ -76,13 +79,8 @@ class Number extends Backend
$cfg = is_array($this->view->config ?? null) ? $this->view->config : [];
$version = (string) \think\Config::get('site.version');
$scriptUrl = (string) url('split.number/script', ['v' => $version], false, true);
if (strpos($scriptUrl, '?') === false) {
$scriptUrl .= '?v=' . $version;
}
if (strpos($scriptUrl, '://') === false) {
$scriptUrl = $this->request->domain() . $scriptUrl;
}
// 使用站内相对路径,避免生产环境 domain() 与反向代理/HTTPS 不一致导致 JS 跨域丢 Cookie
$scriptUrl = (string) url('split.number/script', ['v' => $version], '', false);
$cfg['jsname'] = $scriptUrl;
$this->view->assign('config', $cfg);
$this->view->config = $cfg;
@@ -127,6 +125,59 @@ class Number extends Backend
return (string) $this->view->fetch($file);
}
/**
* 列表状态开关:手动关闭时标记 manual_manage=1,防止同步自动恢复开启
*
* @param string $ids
*/
public function multi($ids = '')
{
if (!$this->request->isPost()) {
$this->error(__('Invalid parameters'));
}
$ids = $ids ?: $this->request->post('ids', '');
if ($ids === '') {
$this->error(__('Parameter %s can not be empty', 'ids'));
}
$params = $this->request->post('params', '');
parse_str((string) $params, $values);
if (!isset($values['status'])) {
parent::multi($ids);
return;
}
if ((string) $values['status'] === 'hidden') {
$values['manual_manage'] = 1;
} elseif ((string) $values['status'] === 'normal') {
$values['manual_manage'] = 0;
}
$adminIds = $this->getDataLimitAdminIds();
if (is_array($adminIds)) {
$this->model->where($this->dataLimitField, 'in', $adminIds);
}
$count = 0;
Db::startTrans();
try {
$list = $this->model->where($this->model->getPk(), 'in', $ids)->select();
foreach ($list as $item) {
$count += $item->allowField(true)->isUpdate(true)->save($values);
}
Db::commit();
} catch (ValidateException $e) {
Db::rollback();
$this->error($e->getMessage());
} catch (PDOException|Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
if ($count > 0) {
$this->success();
}
$this->error(__('No rows were updated'));
}
/**
* @return string|Json
* @throws DbException
+52 -11
View File
@@ -8,6 +8,7 @@ use app\admin\model\split\Link as LinkModel;
use app\admin\model\split\Ticket as TicketModel;
use app\common\controller\Backend;
use app\common\service\SplitTicketRuleService;
use app\common\service\SplitTicketSyncLogger;
use app\common\service\SplitTicketSyncService;
use think\Db;
use think\Lang;
@@ -57,6 +58,12 @@ class Ticket extends Backend
$this->assignconfig('ticketTypeList', $this->model->getTicketTypeList());
$this->assignconfig('numberTypeList', $this->model->getNumberTypeList());
$this->assignconfig('statusList', $this->model->getStatusList());
$this->assignconfig([
'syncConfirmMsg' => __('Sync confirm'),
'syncBackgroundStartedMsg' => __('Sync background started'),
'syncInProgressMsg' => __('Sync in progress'),
'syncTicketStartedMsg' => __('Sync ticket started'),
]);
$this->setupPatchFrontend();
}
@@ -103,13 +110,8 @@ class Ticket extends Backend
$cfg = is_array($this->view->config ?? null) ? $this->view->config : [];
$version = (string) \think\Config::get('site.version');
$scriptUrl = (string) url('split.ticket/script', ['v' => $version], false, true);
if (strpos($scriptUrl, '?') === false) {
$scriptUrl .= '?v=' . $version;
}
if (strpos($scriptUrl, '://') === false) {
$scriptUrl = $this->request->domain() . $scriptUrl;
}
// 使用站内相对路径,避免生产环境 domain() 与反向代理/HTTPS 不一致导致 JS 跨域丢 Cookie
$scriptUrl = (string) url('split.ticket/script', ['v' => $version], '', false);
$cfg['jsname'] = $scriptUrl;
$this->view->assign('config', $cfg);
$this->view->config = $cfg;
@@ -228,6 +230,11 @@ class Ticket extends Backend
$this->error(__('No Results were found'));
}
SplitTicketSyncLogger::log('web', 'manual sync request', [
'ids' => $ids,
'appDebug' => SplitTicketSyncLogger::isEnabled(),
]);
$service = new SplitTicketSyncService();
$ok = 0;
$fail = 0;
@@ -276,15 +283,42 @@ class Ticket extends Backend
if (isset($values['status'])) {
$pk = $this->model->getPk();
$rows = $this->model->where($pk, 'in', $ids)->select();
parent::multi($ids);
$adminIds = $this->getDataLimitAdminIds();
$query = $this->model->where($pk, 'in', $ids);
if (is_array($adminIds)) {
$query->where($this->dataLimitField, 'in', $adminIds);
}
$rows = $query->select();
if (!$rows || count($rows) === 0) {
$this->error(__('No Results were found'));
}
$count = 0;
Db::startTrans();
try {
foreach ($rows as $item) {
$count += $item->allowField(true)->isUpdate(true)->save($values);
}
Db::commit();
} catch (ValidateException $e) {
Db::rollback();
$this->error($e->getMessage());
} catch (PDOException|Exception $e) {
Db::rollback();
$this->error($e->getMessage());
}
foreach ($rows as $row) {
$fresh = $this->model->get($row['id']);
if ($fresh) {
$ruleService->syncNumbersWithTicketStatus($fresh);
}
}
return;
if ($count > 0) {
$this->success();
}
$this->error(__('No rows were updated'));
}
parent::multi($ids);
@@ -330,7 +364,7 @@ class Ticket extends Backend
if ($result === false) {
$this->error(__('No rows were inserted'));
}
$this->success();
$this->success('', null, ['id' => (int) $this->model->id]);
}
/**
@@ -363,6 +397,7 @@ class Ticket extends Backend
if (($params['number_type'] ?? '') !== 'custom') {
$params['number_type_custom'] = '';
}
$oldStatus = (string) ($row['status'] ?? 'hidden');
$result = false;
Db::startTrans();
try {
@@ -383,6 +418,12 @@ class Ticket extends Backend
if ($result === false) {
$this->error(__('No rows were updated'));
}
if (isset($params['status']) && (string) $params['status'] !== $oldStatus) {
$fresh = $this->model->get($row['id']);
if ($fresh) {
(new SplitTicketRuleService())->syncNumbersWithTicketStatus($fresh);
}
}
$this->success();
}
+1 -1
View File
@@ -25,7 +25,7 @@ return [
'Domain input tips line1' => '请输入根域名,比如:nihao.com,不要填写 www,且不支持二级子域名。',
'Domain input tips line2' => '不支持中国域名注册商注册的域名,比如阿里云、腾讯云等注册商;也不支持中国域名后缀,包括 cn、com.cn、net.cn、org.cn 等。',
'Domain guide title' => '接入指引',
'Domain guide content' => '提交后,请在详情中查看 Cloudflare 实际分配的 NS,并到域名注册商处修改。',
'Domain guide content' => '提交后,请在详情中查看 Cloudflare 实际分配的 NS,并到域名注册商处修改。NS 生效后点击「检测」完成接入。',
'Domain submitted, please check NS in detail page and update at registrar' => '域名已提交,请在详情中查看 Cloudflare 分配的 NS,并到注册商处修改',
'Domain cannot be edited after creation' => '域名创建后不可编辑',
'Domain already exists' => '该域名已存在',
@@ -26,11 +26,16 @@ return [
'Sync_status' => '同步状态',
'Sync_status_btn' => '同步状态',
'Sync running' => '正在同步,请稍候…',
'Sync confirm' => '确定同步所选工单吗?任务将在后台执行,完成后自动提示结果。',
'Sync background started' => '同步任务已在后台执行,请稍候…',
'Sync in progress' => '同步中',
'Sync ticket started' => '正在同步工单',
'Sync done' => '同步完成',
'Sync status success' => '同步成功',
'Sync status error' => '同步异常',
'Sync status pending' => '待同步',
'Sync display success' => '同步成功 / 在线人数 %s',
'Sync display success' => '同步成功 / 在线 %s',
'Sync display pending' => '待同步',
'Sync display error' => '同步异常',
'Createtime' => '创建时间',
'Section basic' => '基础信息',
+15
View File
@@ -15,6 +15,21 @@ class Number extends Model
{
protected $name = 'split_number';
protected static function init(): void
{
self::beforeInsert(function (self $row): void {
if ((int) ($row['weigh'] ?? 0) > 0) {
return;
}
$linkId = (int) ($row['split_link_id'] ?? 0);
if ($linkId <= 0) {
return;
}
$maxWeigh = (int) self::where('split_link_id', $linkId)->max('weigh');
$row->setAttr('weigh', $maxWeigh + 1);
});
}
protected $autoWriteTimestamp = 'integer';
protected $createTime = 'createtime';
+3
View File
@@ -163,6 +163,9 @@ class Ticket extends Model
if ($status === 'success') {
return sprintf((string) __('Sync display success'), $online);
}
if ($status === 'pending') {
return (string) __('Sync display pending');
}
return (string) __('Sync display error');
}
@@ -1,3 +1,29 @@
<style>
.split-ticket-sync-pending {
display: inline-flex;
align-items: center;
gap: 6px;
font-weight: 600;
color: #31708f;
white-space: nowrap;
}
.split-ticket-sync-pending .fa-spinner {
color: #5bc0de;
}
.split-ticket-sync-pending .split-ticket-sync-label::after {
content: '';
display: inline-block;
width: 1.2em;
text-align: left;
animation: split-ticket-sync-dots 1.4s steps(4, end) infinite;
}
@keyframes split-ticket-sync-dots {
0%, 20% { content: ''; }
40% { content: '.'; }
60% { content: '..'; }
80%, 100% { content: '...'; }
}
</style>
<div class="panel panel-default panel-intro">
<div class="panel-heading">
{:build_heading(null,FALSE)}