first commit

This commit is contained in:
CN-JS-HuiBai
2026-04-07 16:54:24 +08:00
commit 2c6a38c80d
399 changed files with 42205 additions and 0 deletions

2
Xboard/database/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.sqlite
*.sqlite-journal

View File

@@ -0,0 +1,28 @@
<?php
/** @var \Illuminate\Database\Eloquent\Factory $factory */
use App\User;
use Faker\Generator as Faker;
use Illuminate\Support\Str;
/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| This directory should contain each of the model factory definitions for
| your application. Factories provide a convenient way to generate new
| model instances for testing / seeding your application's database.
|
*/
$factory->define(User::class, function (Faker $faker) {
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
});

View File

@@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateFailedJobsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if (!Schema::hasTable('failed_jobs')) {
Schema::create('failed_jobs', function (Blueprint $table) {
$table->bigIncrements('id');
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
});
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('failed_jobs');
}
}

View File

@@ -0,0 +1,34 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
if (!Schema::hasTable('personal_access_tokens')) {
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->id();
$table->morphs('tokenable');
$table->string('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamp('expires_at')->nullable();
$table->timestamps();
});
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('personal_access_tokens');
}
};

View File

@@ -0,0 +1,496 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
// Commission Log
if (!Schema::hasTable('v2_commission_log')) {
Schema::create('v2_commission_log', function (Blueprint $table) {
$table->integer('id', true);
$table->integer('invite_user_id');
$table->integer('user_id');
$table->char('trade_no', 36);
$table->integer('order_amount');
$table->integer('get_amount');
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Invite Code
if (!Schema::hasTable('v2_invite_code')) {
Schema::create('v2_invite_code', function (Blueprint $table) {
$table->integer('id', true);
$table->integer('user_id');
$table->char('code', 32);
$table->boolean('status')->default(false);
$table->integer('pv')->default(0);
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Knowledge
if (!Schema::hasTable('v2_knowledge')) {
Schema::create('v2_knowledge', function (Blueprint $table) {
$table->integer('id', true);
$table->char('language', 5)->comment('語言');
$table->string('category')->comment('分類名');
$table->string('title')->comment('標題');
$table->text('body')->comment('內容');
$table->integer('sort')->nullable()->comment('排序');
$table->boolean('show')->default(false)->comment('顯示');
$table->integer('created_at')->comment('創建時間');
$table->integer('updated_at')->comment('更新時間');
});
}
// Plan
if (!Schema::hasTable('v2_plan')) {
Schema::create('v2_plan', function (Blueprint $table) {
$table->integer('id', true);
$table->integer('group_id');
$table->integer('transfer_enable');
$table->string('name');
$table->integer('speed_limit')->nullable();
$table->boolean('show')->default(false);
$table->integer('sort')->nullable();
$table->boolean('renew')->default(true);
$table->text('content')->nullable();
$table->integer('month_price')->nullable();
$table->integer('quarter_price')->nullable();
$table->integer('half_year_price')->nullable();
$table->integer('year_price')->nullable();
$table->integer('two_year_price')->nullable();
$table->integer('three_year_price')->nullable();
$table->integer('onetime_price')->nullable();
$table->integer('reset_price')->nullable();
$table->integer('reset_traffic_method')->nullable()->comment('重置流量方式:null跟随系统设置、0每月1号、1按月重置、2不重置、3每年1月1日、4按年重置');
$table->integer('capacity_limit')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Server Group
if (!Schema::hasTable('v2_server_group')) {
Schema::create('v2_server_group', function (Blueprint $table) {
$table->integer('id', true);
$table->string('name');
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Server Route
if (!Schema::hasTable('v2_server_route')) {
Schema::create('v2_server_route', function (Blueprint $table) {
$table->integer('id', true);
$table->string('remarks');
$table->text('match');
$table->string('action', 11);
$table->string('action_value')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
}
// stat server
if (!Schema::hasTable('v2_stat_server')) {
Schema::create('v2_stat_server', function (Blueprint $table) {
$table->integer('id', true);
$table->integer('server_id')->index('server_id')->comment('节点id');
$table->char('server_type', 11)->comment('节点类型');
$table->bigInteger('u');
$table->bigInteger('d');
$table->char('record_type', 1)->comment('d day m month');
$table->integer('record_at')->index('record_at')->comment('记录时间');
$table->integer('created_at');
$table->integer('updated_at');
$table->unique(['server_id', 'server_type', 'record_at'], 'server_id_server_type_record_at');
});
}
// User
if (!Schema::hasTable('v2_user')) {
Schema::create('v2_user', function (Blueprint $table) {
$table->integer('id', true);
$table->integer('invite_user_id')->nullable();
$table->bigInteger('telegram_id')->nullable();
$table->string('email', 64)->unique('email');
$table->string('password', 64);
$table->char('password_algo', 10)->nullable();
$table->char('password_salt', 10)->nullable();
$table->integer('balance')->default(0);
$table->integer('discount')->nullable();
$table->tinyInteger('commission_type')->default(0)->comment('0: system 1: period 2: onetime');
$table->integer('commission_rate')->nullable();
$table->integer('commission_balance')->default(0);
$table->integer('t')->default(0);
$table->bigInteger('u')->default(0);
$table->bigInteger('d')->default(0);
$table->bigInteger('transfer_enable')->default(0);
$table->boolean('banned')->default(false);
$table->boolean('is_admin')->default(false);
$table->integer('last_login_at')->nullable();
$table->boolean('is_staff')->default(false);
$table->integer('last_login_ip')->nullable();
$table->string('uuid', 36);
$table->integer('group_id')->nullable();
$table->integer('plan_id')->nullable();
$table->integer('speed_limit')->nullable();
$table->tinyInteger('remind_expire')->nullable()->default(1);
$table->tinyInteger('remind_traffic')->nullable()->default(1);
$table->char('token', 32);
$table->bigInteger('expired_at')->nullable()->default(0);
$table->text('remarks')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Mail Log
if (!Schema::hasTable('v2_mail_log')) {
Schema::create('v2_mail_log', function (Blueprint $table) {
$table->integer('id', true);
$table->string('email', 64);
$table->string('subject');
$table->string('template_name');
$table->text('error')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Log
if (!Schema::hasTable('v2_log')) {
Schema::create('v2_log', function (Blueprint $table) {
$table->integer('id', true);
$table->text('title');
$table->string('level', 11)->nullable();
$table->string('host')->nullable();
$table->string('uri');
$table->string('method', 11);
$table->text('data')->nullable();
$table->string('ip', 128)->nullable();
$table->text('context')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Stat
if (!Schema::hasTable('v2_stat')) {
Schema::create('v2_stat', function (Blueprint $table) {
$table->integer('id', true);
$table->integer('record_at');
$table->char('record_type', 1);
$table->integer('order_count')->comment('订单数量');
$table->integer('order_total')->comment('订单合计');
$table->integer('commission_count');
$table->integer('commission_total')->comment('佣金合计');
$table->integer('paid_count');
$table->integer('paid_total');
$table->integer('register_count');
$table->integer('invite_count');
$table->string('transfer_used_total', 32);
$table->integer('created_at');
$table->integer('updated_at');
if (config('database.default') !== 'sqlite') {
$table->unique(['record_at']);
}
});
}
// stat user
if (!Schema::hasTable('v2_stat_user')) {
Schema::create('v2_stat_user', function (Blueprint $table) {
$table->integer('id', true);
$table->integer('user_id');
$table->decimal('server_rate', 10);
$table->bigInteger('u');
$table->bigInteger('d');
$table->char('record_type', 2);
$table->integer('record_at');
$table->integer('created_at');
$table->integer('updated_at');
// 如果是不是sqlite才添加多个索引
if (config('database.default') !== 'sqlite') {
$table->index(['user_id', 'server_rate', 'record_at']);
$table->unique(['server_rate', 'user_id', 'record_at'], 'server_rate_user_id_record_at');
}
});
}
// ticket message
if (!Schema::hasTable('v2_ticket_message')) {
Schema::create('v2_ticket_message', function (Blueprint $table) {
$table->integer('id', true);
$table->integer('user_id');
$table->integer('ticket_id');
$table->text('message');
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Order
if (!Schema::hasTable('v2_order')) {
Schema::create('v2_order', function (Blueprint $table) {
$table->integer('id', true);
$table->integer('invite_user_id')->nullable();
$table->integer('user_id');
$table->integer('plan_id');
$table->integer('coupon_id')->nullable();
$table->integer('payment_id')->nullable();
$table->integer('type')->comment('1新购2续费3升级');
$table->string('period');
$table->string('trade_no', 36)->unique('trade_no');
$table->string('callback_no')->nullable();
$table->integer('total_amount');
$table->integer('handling_amount')->nullable();
$table->integer('discount_amount')->nullable();
$table->integer('surplus_amount')->nullable()->comment('剩余价值');
$table->integer('refund_amount')->nullable()->comment('退款金额');
$table->integer('balance_amount')->nullable()->comment('使用余额');
$table->text('surplus_order_ids')->nullable()->comment('折抵订单');
$table->integer('status')->default(0)->comment('0待支付1开通中2已取消3已完成4已折抵');
$table->integer('commission_status')->default(false)->comment('0待确认1发放中2有效3无效');
$table->integer('commission_balance')->default(0);
$table->integer('actual_commission_balance')->nullable()->comment('实际支付佣金');
$table->integer('paid_at')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Payment
if (!Schema::hasTable('v2_payment')) {
Schema::create('v2_payment', function (Blueprint $table) {
$table->integer('id', true);
$table->char('uuid', 32);
$table->string('payment', 16);
$table->string('name');
$table->string('icon')->nullable();
$table->text('config');
$table->string('notify_domain', 128)->nullable();
$table->integer('handling_fee_fixed')->nullable();
$table->decimal('handling_fee_percent', 5)->nullable();
$table->boolean('enable')->default(false);
$table->integer('sort')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Coupon
if (!Schema::hasTable('v2_coupon')) {
Schema::create('v2_coupon', function (Blueprint $table) {
$table->integer('id', true);
$table->string('code');
$table->string('name');
$table->integer('type');
$table->integer('value');
$table->boolean('show')->default(false);
$table->integer('limit_use')->nullable();
$table->integer('limit_use_with_user')->nullable();
$table->string('limit_plan_ids')->nullable();
$table->string('limit_period')->nullable();
$table->integer('started_at');
$table->integer('ended_at');
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Notice
if (!Schema::hasTable('v2_notice')) {
Schema::create('v2_notice', function (Blueprint $table) {
$table->integer('id', true);
$table->string('title');
$table->text('content');
$table->boolean('show')->default(false);
$table->string('img_url')->nullable();
$table->string('tags')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Ticket
if (!Schema::hasTable('v2_ticket')) {
Schema::create('v2_ticket', function (Blueprint $table) {
$table->integer('id', true);
$table->integer('user_id');
$table->string('subject');
$table->integer('level');
$table->integer('status')->default(0)->comment('0:已开启 1:已关闭');
$table->integer('reply_status')->default(1)->comment('0:待回复 1:已回复');
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Server Hysteria
if (!Schema::hasTable('v2_server_hysteria')) {
Schema::create('v2_server_hysteria', function (Blueprint $table) {
$table->integer('id', true);
$table->string('group_id');
$table->string('route_id')->nullable();
$table->string('name');
$table->integer('parent_id')->nullable();
$table->string('host');
$table->string('port', 11);
$table->integer('server_port');
$table->string('tags')->nullable();
$table->string('rate', 11);
$table->boolean('show')->default(false);
$table->integer('sort')->nullable();
$table->integer('up_mbps');
$table->integer('down_mbps');
$table->string('server_name', 64)->nullable();
$table->boolean('insecure')->default(false);
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Server Shadowsocks
if (!Schema::hasTable('v2_server_shadowsocks')) {
autoIncrement:
Schema::create('v2_server_shadowsocks', function (Blueprint $table) {
$table->integer('id', true);
$table->string('group_id');
$table->string('route_id')->nullable();
$table->integer('parent_id')->nullable();
$table->string('tags')->nullable();
$table->string('name');
$table->string('rate', 11);
$table->string('host');
$table->string('port', 11);
$table->integer('server_port');
$table->string('cipher');
$table->char('obfs', 11)->nullable();
$table->string('obfs_settings')->nullable();
$table->tinyInteger('show')->default(0);
$table->integer('sort')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Server Trojan
if (!Schema::hasTable('v2_server_trojan')) {
Schema::create('v2_server_trojan', function (Blueprint $table) {
$table->integer('id', true)->comment('节点ID');
$table->string('group_id')->comment('节点组');
$table->string('route_id')->nullable();
$table->integer('parent_id')->nullable()->comment('父节点');
$table->string('tags')->nullable()->comment('节点标签');
$table->string('name')->comment('节点名称');
$table->string('rate', 11)->comment('倍率');
$table->string('host')->comment('主机名');
$table->string('port', 11)->comment('连接端口');
$table->integer('server_port')->comment('服务端口');
$table->boolean('allow_insecure')->default(false)->comment('是否允许不安全');
$table->string('server_name')->nullable();
$table->boolean('show')->default(false)->comment('是否显示');
$table->integer('sort')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Server Vless
if (!Schema::hasTable('v2_server_vless')) {
Schema::create('v2_server_vless', function (Blueprint $table) {
$table->integer('id', true);
$table->text('group_id');
$table->text('route_id')->nullable();
$table->string('name');
$table->integer('parent_id')->nullable();
$table->string('host');
$table->integer('port');
$table->integer('server_port');
$table->integer('tls');
$table->text('tls_settings')->nullable();
$table->string('flow', 64)->nullable();
$table->string('network', 11);
$table->text('network_settings')->nullable();
$table->text('tags')->nullable();
$table->string('rate', 11);
$table->boolean('show')->default(false);
$table->integer('sort')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
}
// Server Vmess
if (!Schema::hasTable('v2_server_vmess')) {
Schema::create('v2_server_vmess', function (Blueprint $table) {
$table->integer('id', true);
$table->string('group_id');
$table->string('route_id')->nullable();
$table->string('name');
$table->integer('parent_id')->nullable();
$table->string('host');
$table->string('port', 11);
$table->integer('server_port');
$table->tinyInteger('tls')->default(0);
$table->string('tags')->nullable();
$table->string('rate', 11);
$table->string('network', 11);
$table->text('rules')->nullable();
$table->text('networkSettings')->nullable();
$table->text('tlsSettings')->nullable();
$table->text('ruleSettings')->nullable();
$table->text('dnsSettings')->nullable();
$table->boolean('show')->default(false);
$table->integer('sort')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('v2_commission_log');
Schema::dropIfExists('v2_plan');
Schema::dropIfExists('v2_user');
Schema::dropIfExists('v2_mail_log');
Schema::dropIfExists('v2_log');
Schema::dropIfExists('v2_stat');
Schema::dropIfExists('v2_order');
Schema::dropIfExists('v2_coupon');
Schema::dropIfExists('v2_notice');
Schema::dropIfExists('v2_ticket');
Schema::dropIfExists('v2_settings');
Schema::dropIfExists('v2_ticket_message');
Schema::dropIfExists('v2_invite_code');
Schema::dropIfExists('v2_knowledge');
Schema::dropIfExists('v2_server_group');
Schema::dropIfExists('v2_server_route');
Schema::dropIfExists('v2_stat_server');
Schema::dropIfExists('v2_stat_user');
Schema::dropIfExists('v2_server_hysteria');
Schema::dropIfExists('v2_server_shadowsocks');
Schema::dropIfExists('v2_server_trojan');
Schema::dropIfExists('v2_server_vless');
Schema::dropIfExists('v2_server_vmess');
}
};

View File

@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateV2SettingsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('v2_settings', function (Blueprint $table) {
$table->id();
$table->string('group')->comment('设置分组')->nullable();
$table->string('type')->comment('设置类型')->nullable();
$table->string('name')->comment('设置名称')->unique();
$table->string('value')->comment('设置值')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('v2_settings');
}
}

View File

@@ -0,0 +1,56 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddColumnExcludesToServerTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('v2_server_hysteria', function (Blueprint $table) {
$table->text("excludes")->nullable()->after('tags');
});
Schema::table('v2_server_shadowsocks', function (Blueprint $table) {
$table->text("excludes")->nullable()->after('tags');
});
Schema::table('v2_server_trojan', function (Blueprint $table) {
$table->text("excludes")->nullable()->after('tags');
});
Schema::table('v2_server_vless', function (Blueprint $table) {
$table->text("excludes")->nullable()->after('tags');
});
Schema::table('v2_server_vmess', function (Blueprint $table) {
$table->text("excludes")->nullable()->after('tags');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('v2_server_hysteria', function (Blueprint $table) {
$table->dropColumn('excludes');
});
Schema::table('v2_server_shadowsocks', function (Blueprint $table) {
$table->dropColumn('excludes');
});
Schema::table('v2_server_trojan', function (Blueprint $table) {
$table->dropColumn('excludes');
});
Schema::table('v2_server_vless', function (Blueprint $table) {
$table->dropColumn('excludes');
});
Schema::table('v2_server_vmess', function (Blueprint $table) {
$table->dropColumn('excludes');
});
}
}

View File

@@ -0,0 +1,56 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddColumnIpsToServerTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('v2_server_hysteria', function (Blueprint $table) {
$table->string("ips")->nullable()->after('excludes');
});
Schema::table('v2_server_shadowsocks', function (Blueprint $table) {
$table->string("ips")->nullable()->after('excludes');
});
Schema::table('v2_server_trojan', function (Blueprint $table) {
$table->string("ips")->nullable()->after('excludes');
});
Schema::table('v2_server_vless', function (Blueprint $table) {
$table->string("ips")->nullable()->after('excludes');
});
Schema::table('v2_server_vmess', function (Blueprint $table) {
$table->string("ips")->nullable()->after('excludes');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('v2_server_hysteria', function (Blueprint $table) {
$table->dropColumn('ips');
});
Schema::table('v2_server_shadowsocks', function (Blueprint $table) {
$table->dropColumn('ips');
});
Schema::table('v2_server_trojan', function (Blueprint $table) {
$table->dropColumn('ips');
});
Schema::table('v2_server_vless', function (Blueprint $table) {
$table->dropColumn('ips');
});
Schema::table('v2_server_vmess', function (Blueprint $table) {
$table->dropColumn('ips');
});
}
}

View File

@@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddColumnAlpnToServerHysteriaTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('v2_server_hysteria', function (Blueprint $table) {
$table->tinyInteger('alpn',false,true)->default(0)->comment('ALPN,0:hysteria、1:http/1.1、2:h2、3:h3');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('v2_server_hysteria', function (Blueprint $table) {
$table->dropColumn('alpn');
});
}
}

View File

@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddColumnNetworkAndNetworkSettingsToV2ServerTrojan extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('v2_server_trojan', function (Blueprint $table) {
$table->string('network', 11)->default('tcp')->after('server_name')->comment('传输协议');
$table->text('networkSettings')->nullable()->after('network')->comment('传输协议配置');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('v2_server_trojan', function (Blueprint $table) {
$table->dropColumn(["network","networkSettings"]);
});
}
}

View File

@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddColumnVersionAndIsObfsToServerHysteriaTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('v2_server_hysteria', function (Blueprint $table) {
$table->tinyInteger('version',false,true)->default(1)->comment('hysteria版本,Version:1\2');
$table->boolean('is_obfs')->default(true)->comment('是否开启obfs');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('v2_server_hysteria', function (Blueprint $table) {
$table->dropColumn('version','is_obfs');
});
}
}

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('v2_settings', function (Blueprint $table) {
$table->text('value')->comment('设置值')->nullable()->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v2_settings', function (Blueprint $table) {
$table->string('value')->comment('设置值')->nullable()->change();
});
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('v2_user', function (Blueprint $table) {
$table->index(['u','d','expired_at','group_id','banned','transfer_enable']);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v2_user', function (Blueprint $table) {
$table->dropIndex(['u','d','expired_at','group_id','banned','transfer_enable']);
});
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('v2_payment', function (Blueprint $table) {
$table->text('icon')->nullable()->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v2_payment', function (Blueprint $table) {
$table->string('icon')->nullable()->change();
});
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('v2_order', function (Blueprint $table) {
$table->integer('commission_status')->nullable()->default(null)->comment('0待确认1发放中2有效3无效')->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v2_order', function (Blueprint $table) {
$table->integer('commission_status')->default(false)->comment('0待确认1发放中2有效3无效')->change();
});
}
};

View File

@@ -0,0 +1,129 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
// Step 1: Add new columns first
Schema::table('v2_plan', function (Blueprint $table) {
$table->json('prices')->nullable()->after('name')
->comment('Store different duration prices and reset traffic price');
$table->boolean('sell')->default(false)->after('prices')->comment('is sell');
});
// Step 2: Migrate data to new format
DB::table('v2_plan')->orderBy('id')->chunk(100, function ($plans) {
foreach ($plans as $plan) {
$prices = array_filter([
'monthly' => $plan->month_price !== null ? $plan->month_price / 100 : null,
'quarterly' => $plan->quarter_price !== null ? $plan->quarter_price / 100 : null,
'half_yearly' => $plan->half_year_price !== null ? $plan->half_year_price / 100 : null,
'yearly' => $plan->year_price !== null ? $plan->year_price / 100 : null,
'two_yearly' => $plan->two_year_price !== null ? $plan->two_year_price / 100 : null,
'three_yearly' => $plan->three_year_price !== null ? $plan->three_year_price / 100 : null,
'onetime' => $plan->onetime_price !== null ? $plan->onetime_price / 100 : null,
'reset_traffic' => $plan->reset_price !== null ? $plan->reset_price / 100 : null
], function ($price) {
return $price !== null;
});
DB::table('v2_plan')
->where('id', $plan->id)
->update([
'prices' => json_encode($prices),
'sell' => $plan->show
]);
}
});
// Step 3: Optimize existing columns
Schema::table('v2_plan', function (Blueprint $table) {
// Modify existing columns to be more efficient
$table->unsignedInteger('group_id')->nullable()->change();
$table->unsignedBigInteger('transfer_enable')->nullable()
->comment('Transfer limit in bytes')->change();
$table->unsignedInteger('speed_limit')->nullable()
->comment('Speed limit in Mbps, 0 for unlimited')->change();
$table->integer('reset_traffic_method')->nullable()->default(0)
->comment('重置流量方式:null跟随系统设置、0每月1号、1按月重置、2不重置、3每年1月1日、4按年重置')->change();
$table->unsignedInteger('capacity_limit')->nullable()->default(0)
->comment('0 for unlimited')->change();
});
// Step 4: Drop old columns
Schema::table('v2_plan', function (Blueprint $table) {
$table->dropColumn([
'month_price',
'quarter_price',
'half_year_price',
'year_price',
'two_year_price',
'three_year_price',
'onetime_price',
'reset_price',
]);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// Step 1: Add back old columns
Schema::table('v2_plan', function (Blueprint $table) {
$table->integer('month_price')->nullable();
$table->integer('quarter_price')->nullable();
$table->integer('half_year_price')->nullable();
$table->integer('year_price')->nullable();
$table->integer('two_year_price')->nullable();
$table->integer('three_year_price')->nullable();
$table->integer('onetime_price')->nullable();
$table->integer('reset_price')->nullable();
});
// Step 2: Restore data from new format to old format
DB::table('v2_plan')->orderBy('id')->chunk(100, function ($plans) {
foreach ($plans as $plan) {
$prices = json_decode($plan->prices, true) ?? [];
DB::table('v2_plan')
->where('id', $plan->id)
->update([
'month_price' => $prices['monthly'] * 100 ?? null,
'quarter_price' => $prices['quarterly'] * 100 ?? null,
'half_year_price' => $prices['half_yearly'] * 100 ?? null,
'year_price' => $prices['yearly'] * 100 ?? null,
'two_year_price' => $prices['two_yearly'] * 100 ?? null,
'three_year_price' => $prices['three_yearly'] * 100 ?? null,
'onetime_price' => $prices['onetime'] * 100 ?? null,
'reset_price' => $prices['reset_traffic'] * 100 ?? null,
]);
}
});
// Step 3: Drop new columns
Schema::table('v2_plan', function (Blueprint $table) {
$table->dropColumn([
'prices',
'sell'
]);
});
// Step 4: Restore column types to original
Schema::table('v2_plan', function (Blueprint $table) {
$table->integer('group_id')->change();
$table->integer('transfer_enable')->change();
$table->integer('speed_limit')->nullable()->change();
$table->integer('reset_traffic_method')->nullable()->change();
$table->integer('capacity_limit')->nullable()->change();
});
}
};

View File

@@ -0,0 +1,523 @@
<?php
use App\Utils\Helper;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('v2_server', function (Blueprint $table) {
$table->id('id');
$table->string('type')->comment('Server Type');
$table->string('code')->nullable()->comment('Server Spectific Key');
$table->unsignedInteger('parent_id')->nullable()->comment('Parent Server ID');
$table->json('group_ids')->nullable()->comment('Group ID');
$table->json('route_ids')->nullable()->comment('Route ID');
$table->string('name')->comment('Server Name');
$table->decimal('rate', 8, 2)->comment('Traffic Rate');
$table->json('tags')->nullable()->comment('Server Tags');
$table->string('host')->comment('Server Host');
$table->string('port')->comment('Client Port');
$table->integer('server_port')->comment('Server Port');
$table->json('protocol_settings')->nullable();
$table->boolean('show')->default(false)->comment('Show in List');
$table->integer('sort')->nullable()->unsigned()->index();
$table->timestamps();
$table->unique(['type', 'code']);
});
// Migrate Trojan servers
$trojanServers = DB::table('v2_server_trojan')->get();
foreach ($trojanServers as $server) {
DB::table('v2_server')->insert([
'type' => 'trojan',
'code' => (string) $server->id,
'parent_id' => $server->parent_id,
'group_ids' => $server->group_id ?: "[]",
'route_ids' => $server->route_id ?: "[]",
'name' => $server->name,
'rate' => $server->rate,
'tags' => $server->tags ?: "[]",
'host' => $server->host,
'port' => $server->port,
'server_port' => $server->server_port,
'protocol_settings' => json_encode([
'allow_insecure' => $server->allow_insecure,
'server_name' => $server->server_name,
'network' => $server->network,
'network_settings' => $server->networkSettings
]),
'show' => $server->show,
'sort' => $server->sort,
'created_at' => date('Y-m-d H:i:s', $server->created_at),
'updated_at' => date('Y-m-d H:i:s', $server->updated_at)
]);
}
// Migrate VMess servers
$vmessServers = DB::table('v2_server_vmess')->get();
foreach ($vmessServers as $server) {
DB::table('v2_server')->insert([
'type' => 'vmess',
'code' => (string) $server->id,
'parent_id' => $server->parent_id,
'group_ids' => $server->group_id ?: "[]",
'route_ids' => $server->route_id ?: "[]",
'name' => $server->name,
'rate' => $server->rate,
'tags' => $server->tags ?: "[]",
'host' => $server->host,
'port' => $server->port,
'server_port' => $server->server_port,
'protocol_settings' => json_encode([
'tls' => $server->tls,
'network' => $server->network,
'rules' => json_decode($server->rules),
'network_settings' => json_decode($server->networkSettings),
'tls_settings' => json_decode($server->tlsSettings),
]),
'show' => $server->show,
'sort' => $server->sort,
'created_at' => date('Y-m-d H:i:s', $server->created_at),
'updated_at' => date('Y-m-d H:i:s', $server->updated_at)
]);
}
// Migrate VLESS servers
$vlessServers = DB::table('v2_server_vless')->get();
foreach ($vlessServers as $server) {
$tlsSettings = optional(json_decode($server->tls_settings));
DB::table('v2_server')->insert([
'type' => 'vless',
'code' => (string) $server->id,
'parent_id' => $server->parent_id,
'group_ids' => $server->group_id ?: "[]",
'route_ids' => $server->route_id ?: "[]",
'name' => $server->name,
'rate' => $server->rate,
'tags' => $server->tags ?: "[]",
'host' => $server->host,
'port' => $server->port,
'server_port' => $server->server_port,
'protocol_settings' => json_encode([
'tls' => $server->tls,
'tls_settings' => $tlsSettings,
'flow' => $server->flow,
'network' => $server->network,
'network_settings' => json_decode($server->network_settings),
'reality_settings' => ($tlsSettings && $tlsSettings->public_key && $tlsSettings->short_id && $tlsSettings->server_name) ? [
'public_key' => $tlsSettings->public_key,
'short_id' => $tlsSettings->short_id,
'server_name' => $tlsSettings->server_name,
'server_port' => $tlsSettings->server_port,
'private_key' => $tlsSettings->private_key,
] : null
]),
'show' => $server->show,
'sort' => $server->sort,
'created_at' => date('Y-m-d H:i:s', $server->created_at),
'updated_at' => date('Y-m-d H:i:s', $server->updated_at)
]);
}
// Migrate Shadowsocks servers
$ssServers = DB::table('v2_server_shadowsocks')->get();
foreach ($ssServers as $server) {
DB::table('v2_server')->insert([
'type' => 'shadowsocks',
'code' => (string) $server->id,
'parent_id' => $server->parent_id,
'group_ids' => $server->group_id ?: "[]",
'route_ids' => $server->route_id ?: "[]",
'name' => $server->name,
'rate' => $server->rate,
'tags' => $server->tags ?: "[]",
'host' => $server->host,
'port' => $server->port,
'server_port' => $server->server_port,
'protocol_settings' => json_encode([
'cipher' => $server->cipher,
'obfs' => $server->obfs,
'obfs_settings' => json_decode($server->obfs_settings)
]),
'show' => (bool) $server->show,
'sort' => $server->sort,
'created_at' => date('Y-m-d H:i:s', $server->created_at),
'updated_at' => date('Y-m-d H:i:s', $server->updated_at)
]);
}
// Migrate Hysteria servers
$hysteriaServers = DB::table(table: 'v2_server_hysteria')->get();
foreach ($hysteriaServers as $server) {
DB::table('v2_server')->insert([
'type' => 'hysteria',
'code' => (string) $server->id,
'parent_id' => $server->parent_id,
'group_ids' => $server->group_id ?: "[]",
'route_ids' => $server->route_id ?: "[]",
'name' => $server->name,
'rate' => $server->rate,
'tags' => $server->tags ?: "[]",
'host' => $server->host,
'port' => $server->port,
'server_port' => $server->server_port,
'protocol_settings' => json_encode([
'version' => $server->version,
'bandwidth' => [
'up' => $server->up_mbps,
'down' => $server->down_mbps,
],
'obfs' => [
'open' => $server->is_obfs,
'type' => 'salamander',
'password' => Helper::getServerKey($server->created_at, 16),
],
'tls' => [
'server_name' => $server->server_name,
'allow_insecure' => $server->insecure
]
]),
'show' => $server->show,
'sort' => $server->sort,
'created_at' => date('Y-m-d H:i:s', $server->created_at),
'updated_at' => date('Y-m-d H:i:s', $server->updated_at)
]);
}
// Update parent_id for all servers
$this->updateParentIds();
// Drop old tables
Schema::dropIfExists('v2_server_trojan');
Schema::dropIfExists('v2_server_vmess');
Schema::dropIfExists('v2_server_vless');
Schema::dropIfExists('v2_server_shadowsocks');
Schema::dropIfExists('v2_server_hysteria');
}
/**
* Update parent_id references for all servers
*/
private function updateParentIds(): void
{
// Get all servers that have a parent_id
$servers = DB::table('v2_server')
->whereNotNull('parent_id')
->get();
// Update each server's parent_id to reference the new table's id
foreach ($servers as $server) {
$parentId = DB::table('v2_server')
->where('type', $server->type)
->where('code', $server->parent_id)
->value('id');
if ($parentId) {
DB::table('v2_server')
->where('id', $server->id)
->update(['parent_id' => $parentId]);
}
}
}
/**
* Restore parent_id references when rolling back
*/
private function restoreParentIds(string $type, string $table): void
{
// Get all servers of the specified type that have a parent_id
$servers = DB::table($table)
->whereNotNull('parent_id')
->get();
// Update each server's parent_id to reference back to the original id
foreach ($servers as $server) {
$originalParentId = DB::table('v2_server')
->where('type', $type)
->where('id', $server->parent_id)
->value('code');
if ($originalParentId) {
DB::table($table)
->where('id', $server->id)
->update(['parent_id' => $originalParentId]);
}
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// Recreate old tables
Schema::create('v2_server_trojan', function (Blueprint $table) {
$table->integer('id', true)->comment('节点ID');
$table->string('group_id')->comment('节点组');
$table->string('route_id')->nullable();
$table->string('ips')->nullable();
$table->string('excludes')->nullable();
$table->integer('parent_id')->nullable()->comment('父节点');
$table->string('tags')->nullable()->comment('节点标签');
$table->string('name')->comment('节点名称');
$table->string('rate', 11)->comment('倍率');
$table->string('host')->comment('主机名');
$table->string('port', 11)->comment('连接端口');
$table->integer('server_port')->comment('服务端口');
$table->boolean('allow_insecure')->default(false)->comment('是否允许不安全');
$table->string('server_name')->nullable();
$table->string('network')->nullable();
$table->text('networkSettings')->nullable();
$table->boolean('show')->default(false)->comment('是否显示');
$table->integer('sort')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
Schema::create('v2_server_vmess', function (Blueprint $table) {
$table->integer('id', true);
$table->string('group_id');
$table->string('route_id')->nullable();
$table->string('ips')->nullable();
$table->string('excludes')->nullable();
$table->string('name');
$table->integer('parent_id')->nullable();
$table->string('host');
$table->string('port', 11);
$table->integer('server_port');
$table->tinyInteger('tls')->default(0);
$table->string('tags')->nullable();
$table->string('rate', 11);
$table->string('network', 11);
$table->text('rules')->nullable();
$table->text('networkSettings')->nullable();
$table->text('tlsSettings')->nullable();
$table->boolean('show')->default(false);
$table->integer('sort')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
Schema::create('v2_server_vless', function (Blueprint $table) {
$table->integer('id', true);
$table->text('group_id');
$table->text('route_id')->nullable();
$table->string('ips')->nullable();
$table->string('excludes')->nullable();
$table->string('name');
$table->integer('parent_id')->nullable();
$table->string('host');
$table->integer('port');
$table->integer('server_port');
$table->boolean('tls');
$table->text('tls_settings')->nullable();
$table->string('flow', 64)->nullable();
$table->string('network', 11);
$table->text('network_settings')->nullable();
$table->text('tags')->nullable();
$table->string('rate', 11);
$table->boolean('show')->default(false);
$table->integer('sort')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
Schema::create('v2_server_shadowsocks', function (Blueprint $table) {
$table->integer('id', true);
$table->string('group_id');
$table->string('route_id')->nullable();
$table->string('ips')->nullable();
$table->string('excludes')->nullable();
$table->integer('parent_id')->nullable();
$table->string('tags')->nullable();
$table->string('name');
$table->string('rate', 11);
$table->string('host');
$table->string('port', 11);
$table->integer('server_port');
$table->string('cipher');
$table->char('obfs', 11)->nullable();
$table->string('obfs_settings')->nullable();
$table->tinyInteger('show')->default(0);
$table->integer('sort')->nullable();
$table->integer('created_at');
$table->integer('updated_at');
});
Schema::create('v2_server_hysteria', function (Blueprint $table) {
$table->integer('id', true);
$table->string('group_id');
$table->string('route_id')->nullable();
$table->string('ips')->nullable();
$table->string('excludes')->nullable();
$table->string('name');
$table->integer('parent_id')->nullable();
$table->string('host');
$table->string('port', 11);
$table->integer('server_port');
$table->string('tags')->nullable();
$table->string('rate', 11);
$table->boolean('show')->default(false);
$table->integer('sort')->nullable();
$table->tinyInteger('version', false, true)->default(1)->comment('hysteria版本,Version:1\2');
$table->boolean('is_obfs')->default(true)->comment('是否开启obfs');
$table->string('alpn')->nullable();
$table->integer('up_mbps');
$table->integer('down_mbps');
$table->string('server_name', 64)->nullable();
$table->boolean('insecure')->default(false);
$table->integer('created_at');
$table->integer('updated_at');
});
// Migrate data back to old tables
$servers = DB::table('v2_server')->get();
foreach ($servers as $server) {
$settings = json_decode($server->protocol_settings, true);
$timestamp = strtotime($server->created_at);
$updated = strtotime($server->updated_at);
switch ($server->type) {
case 'trojan':
DB::table('v2_server_trojan')->insert([
'id' => (int) $server->code,
'group_id' => $server->group_ids,
'route_id' => $server->route_ids,
'parent_id' => $server->parent_id,
'tags' => $server->tags,
'name' => $server->name,
'rate' => (string) $server->rate,
'host' => $server->host,
'port' => $server->port,
'server_port' => $server->server_port,
'allow_insecure' => $settings['allow_insecure'],
'server_name' => $settings['server_name'],
'network' => $settings['network'] ?? null,
'networkSettings' => $settings['network_settings'] ?? null,
'show' => $server->show,
'sort' => $server->sort,
'created_at' => $timestamp,
'updated_at' => $updated
]);
break;
case 'vmess':
DB::table('v2_server_vmess')->insert([
'id' => (int) $server->code,
'group_id' => $server->group_ids,
'route_id' => $server->route_ids,
'name' => $server->name,
'parent_id' => $server->parent_id,
'host' => $server->host,
'port' => $server->port,
'server_port' => $server->server_port,
'tls' => $settings['tls'],
'tags' => $server->tags,
'rate' => (string) $server->rate,
'network' => $settings['network'],
'rules' => json_encode($settings['rules']),
'networkSettings' => json_encode($settings['network_settings']),
'tlsSettings' => json_encode($settings['tls_settings']),
'show' => $server->show,
'sort' => $server->sort,
'created_at' => $timestamp,
'updated_at' => $updated
]);
break;
case 'vless':
// 处理 reality settings
$tlsSettings = $settings['tls_settings'] ?? new \stdClass();
if (isset($settings['reality_settings'])) {
$tlsSettings = array_merge((array) $tlsSettings, [
'public_key' => $settings['reality_settings']['public_key'],
'short_id' => $settings['reality_settings']['short_id'],
'server_name' => explode(':', $settings['reality_settings']['dest'])[0],
'server_port' => explode(':', $settings['reality_settings']['dest'])[1] ?? null,
'private_key' => $settings['reality_settings']['private_key']
]);
}
DB::table('v2_server_vless')->insert([
'id' => (int) $server->code,
'group_id' => $server->group_ids,
'route_id' => $server->route_ids,
'name' => $server->name,
'parent_id' => $server->parent_id,
'host' => $server->host,
'port' => $server->port,
'server_port' => $server->server_port,
'tls' => $settings['tls'],
'tls_settings' => json_encode($tlsSettings),
'flow' => $settings['flow'],
'network' => $settings['network'],
'network_settings' => json_encode($settings['network_settings']),
'tags' => $server->tags,
'rate' => (string) $server->rate,
'show' => $server->show,
'sort' => $server->sort,
'created_at' => $timestamp,
'updated_at' => $updated
]);
break;
case 'shadowsocks':
DB::table('v2_server_shadowsocks')->insert([
'id' => (int) $server->code,
'group_id' => $server->group_ids,
'route_id' => $server->route_ids,
'parent_id' => $server->parent_id,
'tags' => $server->tags,
'name' => $server->name,
'rate' => (string) $server->rate,
'host' => $server->host,
'port' => $server->port,
'server_port' => $server->server_port,
'cipher' => $settings['cipher'],
'obfs' => $settings['obfs'],
'obfs_settings' => json_encode($settings['obfs_settings']),
'show' => (int) $server->show,
'sort' => $server->sort,
'created_at' => $timestamp,
'updated_at' => $updated
]);
break;
case 'hysteria':
DB::table('v2_server_hysteria')->insert([
'id' => (int) $server->code,
'group_id' => $server->group_ids,
'route_id' => $server->route_ids,
'name' => $server->name,
'parent_id' => $server->parent_id,
'host' => $server->host,
'port' => $server->port,
'server_port' => $server->server_port,
'tags' => $server->tags,
'rate' => (string) $server->rate,
'show' => $server->show,
'sort' => $server->sort,
'up_mbps' => $settings['bandwidth']['up'],
'down_mbps' => $settings['bandwidth']['down'],
'server_name' => $settings['tls']['server_name'],
'insecure' => $settings['tls']['allow_insecure'],
'created_at' => $timestamp,
'updated_at' => $updated
]);
break;
}
}
// Restore parent_id references for each server type
$this->restoreParentIds('trojan', 'v2_server_trojan');
$this->restoreParentIds('vmess', 'v2_server_vmess');
$this->restoreParentIds('vless', 'v2_server_vless');
$this->restoreParentIds('shadowsocks', 'v2_server_shadowsocks');
$this->restoreParentIds('hysteria', 'v2_server_hysteria');
// Drop new table
Schema::dropIfExists('v2_server');
}
};

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void
{
Schema::table('v2_plan', function (Blueprint $table) {
$table->unsignedInteger('device_limit')->nullable()->after('speed_limit');
});
Schema::table('v2_user', function (Blueprint $table) {
$table->integer('device_limit')->nullable()->after('expired_at');
$table->integer('online_count')->nullable()->after('device_limit');
$table->timestamp('last_online_at')->nullable()->after('online_count');
});
}
public function down(): void
{
Schema::table('v2_user', function (Blueprint $table) {
$table->dropColumn('device_limit');
$table->dropColumn('online_count');
$table->dropColumn('last_online_at');
});
Schema::table('v2_plan', function (Blueprint $table) {
$table->dropColumn('device_limit');
});
}
};

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('v2_notice', function (Blueprint $table) {
$table->integer('sort')->nullable()->after('id')->index();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v2_notice', function (Blueprint $table) {
$table->dropColumn('sort');
});
}
};

View File

@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
DB::table('v2_order')->where('commission_status', null)->update([
'commission_status' => 0
]);
Schema::table('v2_order', function (Blueprint $table) {
$table->integer('commission_status')->default(value: 0)->comment('0待确认1发放中2有效3无效')->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v2_order', function (Blueprint $table) {
$table->integer('commission_status')->nullable()->comment('0待确认1发放中2有效3无效')->change();
});
}
};

View File

@@ -0,0 +1,56 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
return new class extends Migration {
/**
* 旧的价格字段到新周期的映射关系
*/
private const PERIOD_MAPPING = [
'month_price' => 'monthly',
'quarter_price' => 'quarterly',
'half_year_price' => 'half_yearly',
'year_price' => 'yearly',
'two_year_price' => 'two_yearly',
'three_year_price' => 'three_yearly',
'onetime_price' => 'onetime',
'reset_price' => 'reset_traffic'
];
/**
* Run the migrations.
*/
public function up(): void
{
// 批量更新订单的周期字段
foreach (self::PERIOD_MAPPING as $oldPeriod => $newPeriod) {
DB::table('v2_order')
->where('period', $oldPeriod)
->update(['period' => $newPeriod]);
}
// 检查是否还有未转换的记录
$unconvertedCount = DB::table('v2_order')
->whereNotIn('period', array_values(self::PERIOD_MAPPING))
->count();
if ($unconvertedCount > 0) {
Log::warning("Found {$unconvertedCount} orders with unconverted period values");
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// 回滚操作 - 将新的周期值转换回旧的价格字段名
foreach (self::PERIOD_MAPPING as $oldPeriod => $newPeriod) {
DB::table('v2_order')
->where('period', $newPeriod)
->update(['period' => $oldPeriod]);
}
}
};

View File

@@ -0,0 +1,93 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('v2_user', function (Blueprint $table) {
$table->index('t');
$table->index('online_count');
$table->index('created_at');
});
Schema::table('v2_order', function (Blueprint $table) {
$table->index('created_at');
$table->index('status');
$table->index('total_amount');
$table->index('commission_status');
$table->index('invite_user_id');
$table->index('commission_balance');
});
Schema::table('v2_stat_server', function (Blueprint $table) {
$table->index('server_id');
$table->index('record_at');
$table->index('u');
$table->index('d');
});
Schema::table('v2_stat_user', function (Blueprint $table) {
$table->index('u');
$table->index('d');
});
Schema::table('v2_commission_log', function (Blueprint $table) {
$table->index('created_at');
$table->index('get_amount');
});
Schema::table('v2_ticket', function (Blueprint $table) {
$table->index('status');
$table->index('created_at');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v2_user', function (Blueprint $table) {
$table->dropIndex(['t']);
$table->dropIndex(['online_count']);
$table->dropIndex(['created_at']);
});
Schema::table('v2_order', function (Blueprint $table) {
$table->dropIndex(['created_at']);
$table->dropIndex(['status']);
$table->dropIndex(['total_amount']);
$table->dropIndex(['commission_status']);
$table->dropIndex(['invite_user_id']);
$table->dropIndex(['commission_balance']);
});
Schema::table('v2_stat_server', function (Blueprint $table) {
$table->dropIndex(['server_id']);
$table->dropIndex(['record_at']);
$table->dropIndex(['u']);
$table->dropIndex(['d']);
});
Schema::table('v2_stat_user', function (Blueprint $table) {
$table->dropIndex(['u']);
$table->dropIndex(['d']);
});
Schema::table('v2_commission_log', function (Blueprint $table) {
$table->dropIndex(['created_at']);
$table->dropIndex(['get_amount']);
});
Schema::table('v2_ticket', function (Blueprint $table) {
$table->dropIndex(['status']);
$table->dropIndex(['created_at']);
});
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('v2_order', function (Blueprint $table) {
$table->index('updated_at');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v2_order', function (Blueprint $table) {
$table->dropIndex(['updated_at']);
});
}
};

View File

@@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('v2_plugins', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('code')->unique();
$table->string('version', 50);
$table->boolean('is_enabled')->default(false);
$table->json('config')->nullable();
$table->timestamp('installed_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('v2_plugins');
}
};

View File

@@ -0,0 +1,37 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
class OptimizeV2SettingsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('v2_settings', function (Blueprint $table) {
// 将 value 字段改为 MEDIUMTEXT支持最大16MB内容
$table->mediumText('value')->nullable()->change();
// 添加优化索引
$table->index('name', 'idx_setting_name');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('v2_settings', function (Blueprint $table) {
$table->string('value')->nullable()->change();
$table->dropIndex('idx_setting_name');
});
}
}

View File

@@ -0,0 +1,43 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateTrafficResetLogsTable extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('v2_traffic_reset_logs', function (Blueprint $table) {
$table->id();
$table->bigInteger('user_id')->comment('用户ID');
$table->string('reset_type', 50)->comment('重置类型');
$table->timestamp('reset_time')->comment('重置时间');
$table->bigInteger('old_upload')->default(0)->comment('重置前上传流量');
$table->bigInteger('old_download')->default(0)->comment('重置前下载流量');
$table->bigInteger('old_total')->default(0)->comment('重置前总流量');
$table->bigInteger('new_upload')->default(0)->comment('重置后上传流量');
$table->bigInteger('new_download')->default(0)->comment('重置后下载流量');
$table->bigInteger('new_total')->default(0)->comment('重置后总流量');
$table->string('trigger_source', 50)->comment('触发来源');
$table->json('metadata')->nullable()->comment('额外元数据');
$table->timestamps();
// 添加索引
$table->index('user_id', 'idx_user_id');
$table->index('reset_time', 'idx_reset_time');
$table->index(['user_id', 'reset_time'], 'idx_user_reset_time');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('v2_traffic_reset_logs');
}
}

View File

@@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Artisan;
class AddTrafficResetFieldsToUsers extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
ini_set('memory_limit', '-1');
if (!Schema::hasColumn('v2_user', 'next_reset_at')) {
Schema::table('v2_user', function (Blueprint $table) {
$table->integer('next_reset_at')->nullable()->after('expired_at')->comment('下次流量重置时间');
$table->integer('last_reset_at')->nullable()->after('next_reset_at')->comment('上次流量重置时间');
$table->integer('reset_count')->default(0)->after('last_reset_at')->comment('流量重置次数');
$table->index('next_reset_at', 'idx_next_reset_at');
});
}
// Set initial reset time for existing users
Artisan::call('reset:traffic', ['--fix-null' => true]);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v2_user', function (Blueprint $table) {
$table->dropIndex('idx_next_reset_at');
$table->dropColumn(['next_reset_at', 'last_reset_at', 'reset_count']);
});
}
}

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('v2_plan', function (Blueprint $table) {
$table->json('tags')->nullable()->after('content');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v2_plan', function (Blueprint $table) {
$table->dropColumn('tags');
});
}
};

View File

@@ -0,0 +1,98 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
// 礼品卡模板表
Schema::create('v2_gift_card_template', function (Blueprint $table) {
$table->id();
$table->string('name')->comment('礼品卡名称');
$table->text('description')->nullable()->comment('礼品卡描述');
$table->tinyInteger('type')->comment('卡片类型1余额 2有效期 3流量 4重置包 5套餐 6组合 7盲盒 8任务 9等级 10节日');
$table->tinyInteger('status')->default(1)->comment('状态0禁用 1启用');
$table->json('conditions')->nullable()->comment('使用条件配置');
$table->json('rewards')->comment('奖励配置');
$table->json('limits')->nullable()->comment('限制条件');
$table->json('special_config')->nullable()->comment('特殊配置(节日时间、等级倍率等)');
$table->string('icon')->nullable()->comment('卡片图标');
$table->string('background_image')->nullable()->comment('背景图片URL');
$table->string('theme_color', 7)->default('#1890ff')->comment('主题色');
$table->integer('sort')->default(0)->comment('排序');
$table->integer('admin_id')->comment('创建管理员ID');
$table->integer('created_at');
$table->integer('updated_at');
$table->index(['type', 'status'], 'idx_gift_template_type_status');
$table->index('created_at', 'idx_gift_template_created_at');
});
// 礼品卡兑换码表
Schema::create('v2_gift_card_code', function (Blueprint $table) {
$table->id();
$table->integer('template_id')->comment('模板ID');
$table->string('code', 32)->unique()->comment('兑换码');
$table->string('batch_id', 32)->nullable()->comment('批次ID');
$table->tinyInteger('status')->default(0)->comment('状态0未使用 1已使用 2已过期 3已禁用');
$table->integer('user_id')->nullable()->comment('使用用户ID');
$table->integer('used_at')->nullable()->comment('使用时间');
$table->integer('expires_at')->nullable()->comment('过期时间');
$table->json('actual_rewards')->nullable()->comment('实际获得的奖励(用于盲盒等)');
$table->integer('usage_count')->default(0)->comment('使用次数(分享卡)');
$table->integer('max_usage')->default(1)->comment('最大使用次数');
$table->json('metadata')->nullable()->comment('额外数据');
$table->integer('created_at');
$table->integer('updated_at');
$table->index('template_id', 'idx_gift_code_template_id');
$table->index('status', 'idx_gift_code_status');
$table->index('user_id', 'idx_gift_code_user_id');
$table->index('batch_id', 'idx_gift_code_batch_id');
$table->index('expires_at', 'idx_gift_code_expires_at');
$table->index(['code', 'status', 'expires_at'], 'idx_gift_code_lookup');
});
// 礼品卡使用记录表
Schema::create('v2_gift_card_usage', function (Blueprint $table) {
$table->id();
$table->integer('code_id')->comment('兑换码ID');
$table->integer('template_id')->comment('模板ID');
$table->integer('user_id')->comment('使用用户ID');
$table->integer('invite_user_id')->nullable()->comment('邀请人ID');
$table->json('rewards_given')->comment('实际发放的奖励');
$table->json('invite_rewards')->nullable()->comment('邀请人获得的奖励');
$table->integer('user_level_at_use')->nullable()->comment('使用时用户等级');
$table->integer('plan_id_at_use')->nullable()->comment('使用时用户套餐ID');
$table->decimal('multiplier_applied', 3, 2)->default(1.00)->comment('应用的倍率');
$table->string('ip_address', 45)->nullable()->comment('使用IP地址');
$table->text('user_agent')->nullable()->comment('用户代理');
$table->text('notes')->nullable()->comment('备注');
$table->integer('created_at');
$table->index('code_id', 'idx_gift_usage_code_id');
$table->index('template_id', 'idx_gift_usage_template_id');
$table->index('user_id', 'idx_gift_usage_user_id');
$table->index('invite_user_id', 'idx_gift_usage_invite_user_id');
$table->index('created_at', 'idx_gift_usage_created_at');
$table->index(['user_id', 'created_at'], 'idx_gift_usage_user_usage');
$table->index(['template_id', 'created_at'], 'idx_gift_usage_template_stats');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('v2_gift_card_usage');
Schema::dropIfExists('v2_gift_card_code');
Schema::dropIfExists('v2_gift_card_template');
}
};

View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('v2_server', function (Blueprint $table) {
$table->boolean('rate_time_enable')->default(false)->comment('是否启用动态倍率')->after('rate');
$table->json('rate_time_ranges')->nullable()->comment('动态倍率规则')->after('rate_time_enable');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v2_server', function (Blueprint $table) {
$table->dropColumn('rate_time_enable');
$table->dropColumn('rate_time_ranges');
});
}
};

View File

@@ -0,0 +1,24 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('v2_plugins', function (Blueprint $table) {
$table->string('type', 20)->default('feature')->after('code')->comment('插件类型feature功能性payment支付型');
$table->index(['type', 'is_enabled']);
});
}
public function down(): void
{
Schema::table('v2_plugins', function (Blueprint $table) {
$table->dropIndex(['type', 'is_enabled']);
$table->dropColumn('type');
});
}
};

View File

@@ -0,0 +1,91 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
return new class extends Migration
{
public function up(): void
{
Schema::create('v2_subscribe_templates', function (Blueprint $table) {
$table->id();
$table->string('name')->unique()->comment('Template key, e.g. singbox, clash');
$table->mediumText('content')->nullable()->comment('Template content');
$table->timestamps();
});
$this->seedDefaults();
}
public function down(): void
{
Schema::dropIfExists('v2_subscribe_templates');
}
private function seedDefaults(): void
{
// Fallback order matches original protocol class behavior
$protocols = [
'singbox' => [
'resources/rules/custom.sing-box.json',
'resources/rules/default.sing-box.json',
],
'clash' => [
'resources/rules/custom.clash.yaml',
'resources/rules/default.clash.yaml',
],
'clashmeta' => [
'resources/rules/custom.clashmeta.yaml',
'resources/rules/custom.clash.yaml',
'resources/rules/default.clash.yaml',
],
'stash' => [
'resources/rules/custom.stash.yaml',
'resources/rules/custom.clash.yaml',
'resources/rules/default.clash.yaml',
],
'surge' => [
'resources/rules/custom.surge.conf',
'resources/rules/default.surge.conf',
],
'surfboard' => [
'resources/rules/custom.surfboard.conf',
'resources/rules/default.surfboard.conf',
],
];
foreach ($protocols as $name => $fileFallbacks) {
$existing = DB::table('v2_settings')
->where('name', "subscribe_template_{$name}")
->value('value');
if ($existing !== null && $existing !== '') {
$content = $existing;
} else {
$content = '';
foreach ($fileFallbacks as $file) {
$path = base_path($file);
if (File::exists($path)) {
$content = File::get($path);
break;
}
}
}
DB::table('v2_subscribe_templates')->insert([
'name' => $name,
'content' => $content,
'created_at' => now(),
'updated_at' => now(),
]);
}
// Clean up old entries from v2_settings
DB::table('v2_settings')
->where('name', 'like', 'subscribe_template_%')
->delete();
}
};

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('v2_admin_audit_log', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('admin_id')->index();
$table->string('action', 64)->index()->comment('Action identifier e.g. user.update');
$table->string('method', 10);
$table->string('uri', 512);
$table->text('request_data')->nullable();
$table->string('ip', 128)->nullable();
$table->unsignedInteger('created_at');
$table->unsignedInteger('updated_at');
});
}
public function down(): void
{
Schema::dropIfExists('v2_admin_audit_log');
}
};

View File

@@ -0,0 +1,22 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::table('v2_stat_user', function (Blueprint $table) {
$table->index(['record_at', 'user_id'], 'idx_stat_user_record_user');
});
}
public function down(): void
{
Schema::table('v2_stat_user', function (Blueprint $table) {
$table->dropIndex('idx_stat_user_record_user');
});
}
};

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('v2_server', function (Blueprint $table) {
$table->json('custom_outbounds')->nullable()->after('protocol_settings');
$table->json('custom_routes')->nullable()->after('custom_outbounds');
$table->json('cert_config')->nullable()->after('custom_routes');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v2_server', function (Blueprint $table) {
$table->dropColumn(['custom_outbounds', 'custom_routes', 'cert_config']);
});
}
};

View File

@@ -0,0 +1,46 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('v2_server', function (Blueprint $table) {
if (!Schema::hasColumn('v2_server', 'transfer_enable')) {
$table->bigInteger('transfer_enable')
->default(null)
->nullable()
->after('rate')
->comment('Traffic limit , 0 or null=no limit');
}
if (!Schema::hasColumn('v2_server', 'u')) {
$table->bigInteger('u')
->default(0)
->after('transfer_enable')
->comment('upload traffic');
}
if (!Schema::hasColumn('v2_server', 'd')) {
$table->bigInteger('d')
->default(0)
->after('u')
->comment('donwload traffic');
}
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('v2_server', function (Blueprint $table) {
$table->dropColumn(['transfer_enable', 'u', 'd']);
});
}
};

View File

@@ -0,0 +1,17 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* @return void
*/
public function run()
{
// $this->call(UsersTableSeeder::class)
}
}

View File

@@ -0,0 +1,170 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
class OriginV2bMigrationsTableSeeder extends Seeder
{
/**
* 原版V2b数据库迁移初始化
*
* @return void
*/
public function run()
{
try{
\Artisan::call("migrate:install");
}catch(\Exception $e){
}
\DB::table('migrations')->insert(array (
0 =>
array (
'id' => 1,
'migration' => '2019_08_19_000000_create_failed_jobs_table',
'batch' => 1,
),
1 =>
array (
'id' => 2,
'migration' => '2023_08_07_205816_create_v2_commission_log_table',
'batch' => 1,
),
2 =>
array (
'id' => 3,
'migration' => '2023_08_07_205816_create_v2_coupon_table',
'batch' => 1,
),
3 =>
array (
'id' => 4,
'migration' => '2023_08_07_205816_create_v2_invite_code_table',
'batch' => 1,
),
4 =>
array (
'id' => 5,
'migration' => '2023_08_07_205816_create_v2_knowledge_table',
'batch' => 1,
),
5 =>
array (
'id' => 6,
'migration' => '2023_08_07_205816_create_v2_log_table',
'batch' => 1,
),
6 =>
array (
'id' => 7,
'migration' => '2023_08_07_205816_create_v2_mail_log_table',
'batch' => 1,
),
7 =>
array (
'id' => 8,
'migration' => '2023_08_07_205816_create_v2_notice_table',
'batch' => 1,
),
8 =>
array (
'id' => 9,
'migration' => '2023_08_07_205816_create_v2_order_table',
'batch' => 1,
),
9 =>
array (
'id' => 10,
'migration' => '2023_08_07_205816_create_v2_payment_table',
'batch' => 1,
),
10 =>
array (
'id' => 11,
'migration' => '2023_08_07_205816_create_v2_plan_table',
'batch' => 1,
),
11 =>
array (
'id' => 12,
'migration' => '2023_08_07_205816_create_v2_server_group_table',
'batch' => 1,
),
12 =>
array (
'id' => 13,
'migration' => '2023_08_07_205816_create_v2_server_hysteria_table',
'batch' => 1,
),
13 =>
array (
'id' => 14,
'migration' => '2023_08_07_205816_create_v2_server_route_table',
'batch' => 1,
),
14 =>
array (
'id' => 15,
'migration' => '2023_08_07_205816_create_v2_server_shadowsocks_table',
'batch' => 1,
),
15 =>
array (
'id' => 16,
'migration' => '2023_08_07_205816_create_v2_server_trojan_table',
'batch' => 1,
),
16 =>
array (
'id' => 17,
'migration' => '2023_08_07_205816_create_v2_server_vless_table',
'batch' => 1,
),
17 =>
array (
'id' => 18,
'migration' => '2023_08_07_205816_create_v2_server_vmess_table',
'batch' => 1,
),
18 =>
array (
'id' => 19,
'migration' => '2023_08_07_205816_create_v2_stat_server_table',
'batch' => 1,
),
19 =>
array (
'id' => 20,
'migration' => '2023_08_07_205816_create_v2_stat_table',
'batch' => 1,
),
20 =>
array (
'id' => 21,
'migration' => '2023_08_07_205816_create_v2_stat_user_table',
'batch' => 1,
),
21 =>
array (
'id' => 22,
'migration' => '2023_08_07_205816_create_v2_ticket_message_table',
'batch' => 1,
),
22 =>
array (
'id' => 23,
'migration' => '2023_08_07_205816_create_v2_ticket_table',
'batch' => 1,
),
23 =>
array (
'id' => 24,
'migration' => '2023_08_07_205816_create_v2_user_table',
'batch' => 1,
)
));
}
}