初始版本

This commit is contained in:
root
2026-06-14 21:12:22 +08:00
commit 6a81742dc7
806 changed files with 179174 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
<?php
namespace app\admin\validate;
use think\Validate;
class Admin extends Validate
{
/**
* 验证规则
*/
protected $rule = [
'username' => 'require|regex:\w{3,30}|unique:admin',
'nickname' => 'require',
'password' => 'require|regex:\S{32}',
'email' => 'require|email|unique:admin,email',
'mobile' => 'regex:1[3-9]\d{9}|unique:admin,mobile',
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 字段描述
*/
protected $field = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => ['username', 'email', 'nickname', 'password', 'mobile'],
'edit' => ['username', 'email', 'nickname', 'password', 'mobile'],
];
public function __construct(array $rules = [], $message = [], $field = [])
{
$this->field = [
'username' => __('Username'),
'nickname' => __('Nickname'),
'password' => __('Password'),
'email' => __('Email'),
'mobile' => __('Mobile'),
];
$this->message = array_merge($this->message, [
'username.regex' => __('Please input correct username'),
'password.regex' => __('Please input correct password')
]);
parent::__construct($rules, $message, $field);
}
}
+52
View File
@@ -0,0 +1,52 @@
<?php
namespace app\admin\validate;
use think\Validate;
class AuthRule extends Validate
{
/**
* 正则
*/
protected $regex = ['format' => '[a-z0-9_\/]+'];
/**
* 验证规则
*/
protected $rule = [
'name' => 'require|unique:AuthRule',
'title' => 'require',
];
/**
* 提示消息
*/
protected $message = [
'name.format' => 'URL规则只能是小写字母、数字、下划线和/组成'
];
/**
* 字段描述
*/
protected $field = [
];
/**
* 验证场景
*/
protected $scene = [
];
public function __construct(array $rules = [], $message = [], $field = [])
{
$this->field = [
'name' => __('Name'),
'title' => __('Title'),
];
$this->message['name.format'] = __('Name only supports letters, numbers, underscore and slash');
parent::__construct($rules, $message, $field);
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace app\admin\validate;
use think\Validate;
class Category extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}
+39
View File
@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace app\admin\validate;
use app\admin\model\Domain as DomainModel;
use think\Validate;
/**
* 域名验证器
*/
class Domain extends Validate
{
protected $rule = [
'domain' => 'require|checkDomain',
];
protected $message = [
'domain.require' => '请输入根域名',
];
protected $scene = [
'add' => ['domain'],
];
/**
* @param string $value
* @return bool|string
*/
protected function checkDomain($value)
{
$domain = DomainModel::normalizeDomain((string)$value);
if (!DomainModel::isValidRootDomain($domain)) {
return '请输入合法根域名,不要填写 www 或二级子域名,且不支持中国域名后缀';
}
return true;
}
}
+50
View File
@@ -0,0 +1,50 @@
<?php
namespace app\admin\validate;
use think\Validate;
class User extends Validate
{
/**
* 验证规则
*/
protected $rule = [
'username' => 'require|regex:\w{3,30}|unique:user',
'nickname' => 'require|unique:user',
'password' => 'regex:\S{6,30}',
'email' => 'require|email|unique:user',
'mobile' => 'unique:user'
];
/**
* 字段描述
*/
protected $field = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => ['username', 'nickname', 'password', 'email', 'mobile'],
];
public function __construct(array $rules = [], $message = [], $field = [])
{
$this->field = [
'username' => __('Username'),
'nickname' => __('Nickname'),
'password' => __('Password'),
'email' => __('Email'),
'mobile' => __('Mobile')
];
parent::__construct($rules, $message, $field);
}
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace app\admin\validate;
use think\Validate;
class UserGroup extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace app\admin\validate;
use think\Validate;
class UserRule extends Validate
{
/**
* 验证规则
*/
protected $rule = [
];
/**
* 提示消息
*/
protected $message = [
];
/**
* 验证场景
*/
protected $scene = [
'add' => [],
'edit' => [],
];
}
+67
View File
@@ -0,0 +1,67 @@
<?php
declare(strict_types=1);
namespace app\admin\validate\split;
use app\common\library\CountryIso;
use app\common\service\SplitLinkCodeService;
use think\Validate;
/**
* 分流链接验证器
*/
class Link extends Validate
{
protected $rule = [
'countries' => 'require|checkCountries',
'link_code' => 'require|checkLinkCode',
'description' => 'require|max:255',
'ip_protect' => 'in:0,1',
'random_shuffle' => 'in:0,1',
'status' => 'in:normal,hidden',
];
protected $message = [
'countries.require' => '请至少选择一个投放国家',
'link_code.require' => '请填写分流链接',
'description.require' => '请填写链接描述',
'description.max' => '链接描述不能超过255个字符',
];
protected $scene = [
'add' => ['countries', 'link_code', 'description', 'ip_protect', 'random_shuffle', 'status'],
'edit' => ['countries', 'description', 'ip_protect', 'random_shuffle', 'status'],
];
/**
* @param mixed $value
* @return bool|string
*/
protected function checkCountries($value)
{
$codes = is_array($value) ? $value : explode(',', (string)$value);
if (CountryIso::normalizeCodes($codes) === []) {
return '请至少选择一个有效的投放国家';
}
return true;
}
/**
* 校验分流链接格式与唯一性(仅新增)
*
* @param mixed $value
* @return bool|string
*/
protected function checkLinkCode($value)
{
$code = SplitLinkCodeService::normalize((string) $value);
if (!SplitLinkCodeService::isValidFormat($code)) {
return '分流链接须为9位小写字母(a-z)';
}
if (!SplitLinkCodeService::isAvailable($code)) {
return '该分流链接已被使用,请更换';
}
return true;
}
}
+109
View File
@@ -0,0 +1,109 @@
<?php
declare(strict_types=1);
namespace app\admin\validate\split;
use app\admin\model\split\Link;
use app\admin\model\split\Number as NumberModel;
use think\Validate;
/**
* 分流号码验证器(部署源文件,由 deploy_split_number.php 复制到 application
*/
class Number extends Validate
{
protected $rule = [
'number_type' => 'require|checkNumberType',
'number_type_custom' => 'max:50|checkNumberTypeCustom',
'split_link_id' => 'require|integer|gt:0|checkSplitLink',
'ticket_name' => 'require|max:100',
'numbers' => 'require|checkNumbers',
'number' => 'require|max:50',
'status' => 'require|checkStatus',
];
protected $message = [
'number_type.require' => '请选择号码类型',
'split_link_id.require' => '请选择分流链接',
'ticket_name.require' => '请填写工单名称',
'ticket_name.max' => '工单名称不能超过100个字符',
'numbers.require' => '请填写号码',
'number.require' => '请填写号码',
'number.max' => '号码不能超过50个字符',
'status.require' => '请选择状态',
];
protected $scene = [
'add' => ['number_type', 'number_type_custom', 'split_link_id', 'ticket_name', 'numbers', 'status'],
'edit' => ['number_type', 'number_type_custom', 'split_link_id', 'ticket_name', 'number', 'status'],
];
/**
* @param mixed $value
* @return bool|string
*/
protected function checkNumberType($value)
{
$key = (string) $value;
$list = (new NumberModel())->getNumberTypeList();
return isset($list[$key]) ? true : '号码类型无效';
}
/**
* @param mixed $value
* @param mixed $rule
* @param array $data
* @return bool|string
*/
protected function checkNumberTypeCustom($value, $rule, array $data = [])
{
if (($data['number_type'] ?? '') !== 'custom') {
return true;
}
if (trim((string) $value) === '') {
return '请填写自定义号码类型';
}
return true;
}
/**
* @param mixed $value
* @param mixed $rule
* @param array $data
* @return bool|string
*/
protected function checkSplitLink($value, $rule, array $data = [])
{
$linkId = (int) $value;
$link = Link::get($linkId);
if (!$link) {
return '所选分流链接不存在';
}
if (($link['status'] ?? '') !== 'normal') {
return '所选分流链接已停用';
}
return true;
}
/**
* @param mixed $value
* @return bool|string
*/
protected function checkNumbers($value)
{
$list = NumberModel::parseNumbersText((string) $value);
return $list !== [] ? true : '请至少填写一个有效号码(每行一个)';
}
/**
* @param mixed $value
* @return bool|string
*/
protected function checkStatus($value)
{
$key = (string) $value;
$list = (new NumberModel())->getStatusList();
return isset($list[$key]) ? true : '状态无效';
}
}
+154
View File
@@ -0,0 +1,154 @@
<?php
declare(strict_types=1);
namespace app\admin\validate\split;
use app\admin\model\split\Link;
use app\admin\model\split\Ticket as TicketModel;
use think\Validate;
/**
* 分流工单验证器(部署源文件,由 deploy_split_ticket.php 复制到 application
*/
class Ticket extends Validate
{
protected $rule = [
'ticket_type' => 'require|checkTicketType',
'ticket_name' => 'require|max:100',
'ticket_url' => 'require|max:1000',
'ticket_total' => 'require|integer|egt:0',
'split_link_id' => 'require|integer|gt:0|checkSplitLink',
'number_type' => 'require|checkNumberType',
'number_type_custom' => 'max:50|checkNumberTypeCustom',
'start_time' => 'require|checkStartTime',
'end_time' => 'require|checkEndTime',
'order_limit' => 'require|integer|egt:0',
'assign_ratio' => 'require|integer|egt:0',
'account' => 'max:50',
'password' => 'max:50',
];
protected $message = [
'ticket_type.require' => '请选择工单类型',
'ticket_name.require' => '请填写工单名称',
'ticket_name.max' => '工单名称不能超过100个字符',
'ticket_url.require' => '请填写工单链接',
'ticket_url.max' => '工单链接不能超过1000个字符',
'ticket_total.require' => '请填写工单总量',
'ticket_total.integer' => '工单总量必须为整数',
'ticket_total.egt' => '工单总量不能小于0',
'split_link_id.require' => '请选择分流链接',
'number_type.require' => '请选择号码类型',
'start_time.require' => '请选择开始时间',
'end_time.require' => '请选择到期时间',
'order_limit.require' => '请填写单号上限',
'order_limit.egt' => '单号上限不能小于0',
'assign_ratio.require' => '请填写下号比率',
'assign_ratio.egt' => '下号比率不能小于0',
];
protected $scene = [
'add' => [
'ticket_type', 'ticket_name', 'ticket_url', 'ticket_total', 'split_link_id',
'number_type', 'number_type_custom', 'start_time', 'end_time',
'order_limit', 'assign_ratio', 'account', 'password',
],
'edit' => [
'ticket_type', 'ticket_name', 'ticket_url', 'ticket_total', 'split_link_id',
'number_type', 'number_type_custom', 'start_time', 'end_time',
'order_limit', 'assign_ratio', 'account', 'password',
],
];
/**
* @param mixed $value
* @return bool|string
*/
protected function checkTicketType($value)
{
$key = (string) $value;
$list = (new TicketModel())->getTicketTypeList();
return isset($list[$key]) ? true : '工单类型无效';
}
/**
* @param mixed $value
* @return bool|string
*/
protected function checkNumberType($value)
{
$key = (string) $value;
$list = (new TicketModel())->getNumberTypeList();
return isset($list[$key]) ? true : '号码类型无效';
}
/**
* @param mixed $value
* @param mixed $rule
* @param array $data
* @return bool|string
*/
protected function checkNumberTypeCustom($value, $rule, array $data = [])
{
if (($data['number_type'] ?? '') !== 'custom') {
return true;
}
if (trim((string) $value) === '') {
return '请填写自定义号码类型';
}
return true;
}
/**
* @param mixed $value
* @param mixed $rule
* @param array $data
* @return bool|string
*/
protected function checkSplitLink($value, $rule, array $data = [])
{
$linkId = (int) $value;
$link = Link::get($linkId);
if (!$link) {
return '所选分流链接不存在';
}
if (($link['status'] ?? '') !== 'normal') {
return '所选分流链接已停用';
}
return true;
}
/**
* @param mixed $value
* @return bool|string
*/
protected function checkStartTime($value)
{
$ts = is_numeric($value) ? (int) $value : strtotime((string) $value);
return ($ts !== false && $ts > 0) ? true : '开始时间格式无效';
}
/**
* @param mixed $value
* @param mixed $rule
* @param array $data
* @return bool|string
*/
protected function checkEndTime($value, $rule, array $data = [])
{
$endTs = is_numeric($value) ? (int) $value : strtotime((string) $value);
if ($endTs === false || $endTs <= 0) {
return '到期时间格式无效';
}
$startRaw = $data['start_time'] ?? '';
$startTs = is_numeric($startRaw) ? (int) $startRaw : strtotime((string) $startRaw);
if ($startTs === false || $startTs <= 0) {
return true;
}
if ($endTs <= $startTs) {
return '到期时间必须晚于开始时间';
}
return true;
}
}