commit
4d4600f974
1
.gitignore
vendored
1
.gitignore
vendored
@ -17,3 +17,4 @@ yarn-error.log
|
|||||||
/.idea
|
/.idea
|
||||||
/.vscode
|
/.vscode
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
/project
|
||||||
|
71
app/Http/Controllers/Admin/TrafficActivateCodeController.php
Normal file
71
app/Http/Controllers/Admin/TrafficActivateCodeController.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\TrafficActivateCode;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use Illuminate\View\View;
|
||||||
|
|
||||||
|
class TrafficActivateCodeController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$codes = TrafficActivateCode::all();
|
||||||
|
$count = $codes->count();
|
||||||
|
return view('admin.codes.index', ['codes' => $codes, 'count' => $count]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*/
|
||||||
|
public function create(): View
|
||||||
|
{
|
||||||
|
return view('admin.codes.create');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$amount = $request->input('amount');
|
||||||
|
$traffic = $request->input('traffic');
|
||||||
|
$codes = $this->generate_key($amount);
|
||||||
|
foreach ($codes as $code) {
|
||||||
|
TrafficActivateCode::create([
|
||||||
|
'code' => $code,
|
||||||
|
'traffic' => $traffic,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
return view('admin.codes.show', compact('codes'));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function generate_key($count): array
|
||||||
|
{
|
||||||
|
$codes = [];
|
||||||
|
for ($i = 0; $i < $count; $i++) {
|
||||||
|
$code = Str::random(25);
|
||||||
|
$code = strtoupper($code);
|
||||||
|
$formattedCode = preg_replace('/(\w{5})(\w{5})(\w{5})(\w{5})(\w{5})/', '$1-$2-$3-$4-$5', $code);
|
||||||
|
$codes[] = $formattedCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $codes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy(TrafficActivateCode $code)
|
||||||
|
{
|
||||||
|
$code->delete();
|
||||||
|
|
||||||
|
return back()->with('success', '删除成功');
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,6 @@ class UserController extends Controller
|
|||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$users = new User();
|
$users = new User();
|
||||||
$count = User::count();
|
|
||||||
|
|
||||||
foreach ($request->except(['page']) as $key => $value) {
|
foreach ($request->except(['page']) as $key => $value) {
|
||||||
if (empty($value)) {
|
if (empty($value)) {
|
||||||
|
33
app/Http/Controllers/Api/TrafficActivateCodeController.php
Normal file
33
app/Http/Controllers/Api/TrafficActivateCodeController.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\TrafficActivateCode;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class TrafficActivateCodeController extends Controller
|
||||||
|
{
|
||||||
|
public function useActivateCode(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'code' => 'required|string'
|
||||||
|
]);
|
||||||
|
$code = $request->post('code');
|
||||||
|
$trafficActivateCode = TrafficActivateCode::where('code', $code)->first();
|
||||||
|
if ($trafficActivateCode == null) {
|
||||||
|
return $this->error('激活码错误');
|
||||||
|
}
|
||||||
|
if ($trafficActivateCode->used_at != null) {
|
||||||
|
return $this->error('激活码已被使用');
|
||||||
|
}
|
||||||
|
$trafficActivateCode->user_id = $request->user()->id;
|
||||||
|
$trafficActivateCode->used_at = now();
|
||||||
|
$trafficActivateCode->update();
|
||||||
|
$user = User::find($request->user()->id);
|
||||||
|
$user->traffic += $trafficActivateCode->traffic;
|
||||||
|
$user->update();
|
||||||
|
return $this->success('激活成功');
|
||||||
|
}
|
||||||
|
}
|
28
app/Models/TrafficActivateCode.php
Normal file
28
app/Models/TrafficActivateCode.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
|
class TrafficActivateCode extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'code',
|
||||||
|
'traffic',
|
||||||
|
|
||||||
|
'user_id',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'used_at' => 'datetime',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function user(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
<?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('traffic_activate_codes', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('code')->index()->unique();
|
||||||
|
$table->bigInteger('traffic')->index();
|
||||||
|
$table->dateTime('used_at')->nullable();
|
||||||
|
$table->unsignedBigInteger('user_id')->nullable()->index();
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->nullOnDelete();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('traffic_activate_codes');
|
||||||
|
}
|
||||||
|
};
|
@ -1 +1 @@
|
|||||||
import{r as l,o as t,c as o,a as e,t as v,j as y,v as w,F as b,e as C,b as p,g as f,l as B}from"./app-22d7fab3.js";import{i as m}from"./http-1f667af7.js";const G=e("div",null,[e("h3",null,"流量充值")],-1),N=e("h5",null,"您要充值多少元的流量?",-1),T=f(" 每 GB 价格: "),U=f(" 元。 "),D={class:"input-group mb-3"},F=e("div",{class:"input-group-append"},[e("span",{class:"input-group-text"},"GB")],-1),M={key:0},j=f("大约 "),E=["textContent"],L=f(" 元。"),P={key:0},R=e("h5",{class:"mt-3"},"您将要使用哪个平台充值?",-1),S=e("p",null,"如果您在选中的平台没有账号,我们将会帮您自动创建一个。",-1),q={class:"form-group form-check"},z=["id","value"],A=["for","textContent"],H={key:1},I=e("h5",{class:"mt-3"},"暂时没有可用的",-1),J=[I],K={key:2},O=e("h5",{class:"mt-3"},"让我们来选择支付方式。",-1),Q=e("p",null,"在支付后,您的流量大概需要数秒钟到账。",-1),W={class:"form-group form-check"},X=["id","value"],Y=["for","textContent"],Z={key:3},$=["disabled","textContent"],ee={key:0},te={key:1,class:"mt-3"},oe=e("h5",null,"完成",-1),ne=e("p",null,"如果您浏览器没有打开新的创建,请点击以下链接来打开。",-1),se=["href"],ie={name:"Charge",setup(le){const g=l(0),u=l([]),i=l(""),r=l({}),d=l(""),c=l(10),h=l(""),_=l(!1);m.get("price").then(s=>{g.value=s.data.price_per_gb}),m.get("providers").then(s=>{u.value=s.data,u.value.length>0&&(i.value=u.value[0],x())});function x(){m.get("providers/"+i.value+"/payments").then(s=>{r.value=s.data,r.value.length>0&&(d.value=r.value[0].name)})}function V(){_.value=!0,m.post("providers/"+i.value+"/charge",{payment:d.value,traffic:c.value}).then(s=>{h.value=s.data.redirect_url,setTimeout(()=>{window.open(h.value,"_blank")})}).finally(()=>{_.value=!1})}return(s,a)=>(t(),o(b,null,[G,e("div",null,[N,e("p",null,[T,e("span",null,v(g.value),1),U]),e("div",D,[y(e("input",{"onUpdate:modelValue":a[0]||(a[0]=n=>c.value=n),autofocus:"",class:"form-control",placeholder:"输入您要的流量 (单位: GB)",type:"number"},null,512),[[w,c.value]]),F]),c.value?(t(),o("div",M,[e("p",null,[j,e("span",{textContent:v(c.value*g.value)},null,8,E),L]),u.value?(t(),o("div",P,[R,S,(t(!0),o(b,null,C(u.value,n=>(t(),o("div",q,[y(e("input",{id:"providers_"+n,"onUpdate:modelValue":a[1]||(a[1]=k=>i.value=k),value:n,class:"form-check-input",name:"provider",type:"radio",onChange:x},null,40,z),[[B,i.value,void 0,{value:!0}]]),e("label",{for:"providers_"+n,class:"form-check-label",textContent:v(n)},null,8,A)]))),256))])):(t(),o("div",H,J)),r.value?(t(),o("div",K,[O,Q,(t(!0),o(b,null,C(r.value,n=>(t(),o("div",W,[y(e("input",{id:"payments_"+n.name,"onUpdate:modelValue":a[2]||(a[2]=k=>d.value=k),value:n.name,class:"form-check-input",name:"payment",type:"radio"},null,8,X),[[B,d.value]]),e("label",{for:"payments_"+n.name,class:"form-check-label",textContent:v(n.title)},null,8,Y)]))),256))])):p("",!0),d.value?(t(),o("div",Z,[e("button",{disabled:_.value,class:"btn btn-primary mt-3",onClick:V,textContent:v(_.value?"请稍后":"立即支付")},null,8,$)])):p("",!0)])):p("",!0)]),_.value?(t(),o("p",ee,"正在创建订单...")):p("",!0),h.value?(t(),o("div",te,[oe,ne,e("a",{href:h.value,class:"link",target:"_blank"},"支付",8,se)])):p("",!0)],64))}};export{ie as default};
|
import{r as l,o as t,c as o,a as e,t as v,j as y,v as w,F as b,e as C,b as p,g as f,l as B}from"./app-65af0faa.js";import{i as m}from"./http-74266e01.js";const G=e("div",null,[e("h3",null,"流量充值")],-1),N=e("h5",null,"您要充值多少元的流量?",-1),T=f(" 每 GB 价格: "),U=f(" 元。 "),D={class:"input-group mb-3"},F=e("div",{class:"input-group-append"},[e("span",{class:"input-group-text"},"GB")],-1),M={key:0},j=f("大约 "),E=["textContent"],L=f(" 元。"),P={key:0},R=e("h5",{class:"mt-3"},"您将要使用哪个平台充值?",-1),S=e("p",null,"如果您在选中的平台没有账号,我们将会帮您自动创建一个。",-1),q={class:"form-group form-check"},z=["id","value"],A=["for","textContent"],H={key:1},I=e("h5",{class:"mt-3"},"暂时没有可用的",-1),J=[I],K={key:2},O=e("h5",{class:"mt-3"},"让我们来选择支付方式。",-1),Q=e("p",null,"在支付后,您的流量大概需要数秒钟到账。",-1),W={class:"form-group form-check"},X=["id","value"],Y=["for","textContent"],Z={key:3},$=["disabled","textContent"],ee={key:0},te={key:1,class:"mt-3"},oe=e("h5",null,"完成",-1),ne=e("p",null,"如果您浏览器没有打开新的创建,请点击以下链接来打开。",-1),se=["href"],ie={name:"Charge",setup(le){const g=l(0),u=l([]),i=l(""),r=l({}),d=l(""),c=l(10),h=l(""),_=l(!1);m.get("price").then(s=>{g.value=s.data.price_per_gb}),m.get("providers").then(s=>{u.value=s.data,u.value.length>0&&(i.value=u.value[0],x())});function x(){m.get("providers/"+i.value+"/payments").then(s=>{r.value=s.data,r.value.length>0&&(d.value=r.value[0].name)})}function V(){_.value=!0,m.post("providers/"+i.value+"/charge",{payment:d.value,traffic:c.value}).then(s=>{h.value=s.data.redirect_url,setTimeout(()=>{window.open(h.value,"_blank")})}).finally(()=>{_.value=!1})}return(s,a)=>(t(),o(b,null,[G,e("div",null,[N,e("p",null,[T,e("span",null,v(g.value),1),U]),e("div",D,[y(e("input",{"onUpdate:modelValue":a[0]||(a[0]=n=>c.value=n),autofocus:"",class:"form-control",placeholder:"输入您要的流量 (单位: GB)",type:"number"},null,512),[[w,c.value]]),F]),c.value?(t(),o("div",M,[e("p",null,[j,e("span",{textContent:v(c.value*g.value)},null,8,E),L]),u.value?(t(),o("div",P,[R,S,(t(!0),o(b,null,C(u.value,n=>(t(),o("div",q,[y(e("input",{id:"providers_"+n,"onUpdate:modelValue":a[1]||(a[1]=k=>i.value=k),value:n,class:"form-check-input",name:"provider",type:"radio",onChange:x},null,40,z),[[B,i.value,void 0,{value:!0}]]),e("label",{for:"providers_"+n,class:"form-check-label",textContent:v(n)},null,8,A)]))),256))])):(t(),o("div",H,J)),r.value?(t(),o("div",K,[O,Q,(t(!0),o(b,null,C(r.value,n=>(t(),o("div",W,[y(e("input",{id:"payments_"+n.name,"onUpdate:modelValue":a[2]||(a[2]=k=>d.value=k),value:n.name,class:"form-check-input",name:"payment",type:"radio"},null,8,X),[[B,d.value]]),e("label",{for:"payments_"+n.name,class:"form-check-label",textContent:v(n.title)},null,8,Y)]))),256))])):p("",!0),d.value?(t(),o("div",Z,[e("button",{disabled:_.value,class:"btn btn-primary mt-3",onClick:V,textContent:v(_.value?"请稍后":"立即支付")},null,8,$)])):p("",!0)])):p("",!0)]),_.value?(t(),o("p",ee,"正在创建订单...")):p("",!0),h.value?(t(),o("div",te,[oe,ne,e("a",{href:h.value,class:"link",target:"_blank"},"支付",8,se)])):p("",!0)],64))}};export{ie as default};
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
import{i as u}from"./http-1f667af7.js";import{r as c,o as l,c as n,a as t,F as r,e as d,t as o}from"./app-22d7fab3.js";const h=t("h3",null,"客户端下载",-1),_={class:"table table-bordered mt-3"},i=t("thead",null,[t("tr",null,[t("th",null,"名称"),t("th",null,"架构"),t("th",null,"下载")])],-1),m=["href"],B={name:"Downloads",setup(p){const a=c([]);return u.get("clients").then(s=>{a.value=s.data}),(s,f)=>(l(),n(r,null,[h,t("table",_,[i,t("tbody",null,[(l(!0),n(r,null,d(a.value,e=>(l(),n("tr",null,[t("td",null,o(e.name),1),t("td",null,o(e.arch),1),t("td",null,[t("a",{href:e.url},"下载",8,m)])]))),256))])])],64))}};export{B as default};
|
import{i as u}from"./http-74266e01.js";import{r as c,o as l,c as n,a as t,F as r,e as d,t as o}from"./app-65af0faa.js";const h=t("h3",null,"客户端下载",-1),_={class:"table table-bordered mt-3"},i=t("thead",null,[t("tr",null,[t("th",null,"名称"),t("th",null,"架构"),t("th",null,"下载")])],-1),m=["href"],B={name:"Downloads",setup(p){const a=c([]);return u.get("clients").then(s=>{a.value=s.data}),(s,f)=>(l(),n(r,null,[h,t("table",_,[i,t("tbody",null,[(l(!0),n(r,null,d(a.value,e=>(l(),n("tr",null,[t("td",null,o(e.name),1),t("td",null,o(e.arch),1),t("td",null,[t("a",{href:e.url},"下载",8,m)])]))),256))])])],64))}};export{B as default};
|
@ -1 +1 @@
|
|||||||
import{i as o}from"./http-1f667af7.js";import{r as u,o as l,c,a as e,t as n,u as i,b as d,F as h}from"./app-22d7fab3.js";const p=e("div",null,[e("h3",null,"欢迎")],-1),k={class:"mt-3"},f={key:0,class:"mt-3"},v=e("h3",null,"实名认证",-1),b=e("p",null," 注意,您没有完成实名认证,请点击下方按钮完成实名认证,否则您只能使用中国大陆以外的隧道。 ",-1),g=e("a",{class:"btn btn-primary",href:"https://oauth.laecloud.com/real_name",target:"_blank"},"实名认证",-1),y=e("h3",null,"访问密钥",-1),x={class:"mt-3"},B={key:0,class:"text-success"},A={name:"Index",setup(T){const r=window.Base.SiteName,s=u({name:"loading...",traffic:""}),a=u("");o.get("user").then(t=>{s.value=t.data});function _(){o.post("tokens").then(t=>{a.value=t.data.token})}function m(){o.delete("tokens").then(t=>{alert("所有 Token 删除成功。")})}return(t,w)=>(l(),c(h,null,[p,e("div",k,[e("p",null,"用户名: "+n(s.value.name),1),e("p",null,"剩余流量: "+n(s.value.traffic)+" GB",1)]),s.value.realnamed?d("",!0):(l(),c("div",f,[v,b,g,e("p",null,"在实名认证后,请重新登录 "+n(i(r))+"。",1)])),y,e("div",x,[e("p",null," 访问密钥是用于访问 "+n(i(r))+" API 的密钥,您可以使用它来开发自己的客户端。 ",1),a.value?(l(),c("p",B,"获取成功,请妥善保管您的 Token: "+n(a.value),1)):d("",!0),e("button",{class:"btn btn-primary",onClick:_}," 获取新密钥 "),e("button",{class:"btn btn-danger",style:{"margin-left":"5px"},onClick:m}," 删除所有密钥 ")])],64))}};export{A as default};
|
import{i as o}from"./http-74266e01.js";import{r as u,o as l,c,a as e,t as n,u as i,b as d,F as h}from"./app-65af0faa.js";const p=e("div",null,[e("h3",null,"欢迎")],-1),k={class:"mt-3"},f={key:0,class:"mt-3"},v=e("h3",null,"实名认证",-1),b=e("p",null," 注意,您没有完成实名认证,请点击下方按钮完成实名认证,否则您只能使用中国大陆以外的隧道。 ",-1),g=e("a",{class:"btn btn-primary",href:"https://oauth.laecloud.com/real_name",target:"_blank"},"实名认证",-1),y=e("h3",null,"访问密钥",-1),x={class:"mt-3"},B={key:0,class:"text-success"},A={name:"Index",setup(T){const r=window.Base.SiteName,s=u({name:"loading...",traffic:""}),a=u("");o.get("user").then(t=>{s.value=t.data});function _(){o.post("tokens").then(t=>{a.value=t.data.token})}function m(){o.delete("tokens").then(t=>{alert("所有 Token 删除成功。")})}return(t,w)=>(l(),c(h,null,[p,e("div",k,[e("p",null,"用户名: "+n(s.value.name),1),e("p",null,"剩余流量: "+n(s.value.traffic)+" GB",1)]),s.value.realnamed?d("",!0):(l(),c("div",f,[v,b,g,e("p",null,"在实名认证后,请重新登录 "+n(i(r))+"。",1)])),y,e("div",x,[e("p",null," 访问密钥是用于访问 "+n(i(r))+" API 的密钥,您可以使用它来开发自己的客户端。 ",1),a.value?(l(),c("p",B,"获取成功,请妥善保管您的 Token: "+n(a.value),1)):d("",!0),e("button",{class:"btn btn-primary",onClick:_}," 获取新密钥 "),e("button",{class:"btn btn-danger",style:{"margin-left":"5px"},onClick:m}," 删除所有密钥 ")])],64))}};export{A as default};
|
@ -1 +1 @@
|
|||||||
import{i as d}from"./http-1f667af7.js";import{r as p,d as _,o,c as r,a as e,F as c,e as i,t as s,f as h,w as u,g as m}from"./app-22d7fab3.js";const v=e("h3",null,"隧道列表",-1),k={class:"table table-hover"},f=e("thead",null,[e("tr",null,[e("th",{scope:"col"},"ID"),e("th",{scope:"col"},"名称"),e("th",{scope:"col"},"协议"),e("th",{scope:"col"},"本地地址"),e("th",{scope:"col"},"远程端口/域名"),e("th",{scope:"col"},"服务器"),e("th",{scope:"col"},"状态")])],-1),x={key:0},g={key:1},y={key:0,class:"text-success"},b={key:1,class:"text-danger"},V={name:"Index",setup(w){const a=p([{id:"0",protocol:"",server:{server_address:"",server_port:"",name:""},run_id:""}]);return d.get("tunnels").then(l=>{a.value=l.data}),(l,B)=>{const n=_("router-link");return o(),r(c,null,[v,e("table",k,[f,e("tbody",null,[(o(!0),r(c,null,i(a.value,t=>(o(),r("tr",null,[e("th",null,s(t.id),1),e("td",null,[h(n,{to:{name:"tunnels.show",params:{id:t.id}}},{default:u(()=>[m(s(t.name),1)]),_:2},1032,["to"])]),e("td",null,s(t.protocol.toString().toUpperCase()),1),e("td",null,s(t.local_address),1),e("td",null,[t.protocol==="http"||t.protocol==="https"?(o(),r("span",x,s(t.custom_domain),1)):(o(),r("span",g,s(t.server.server_address)+":"+s(t.remote_port),1))]),e("td",null,s(t.server.name),1),e("td",null,[t.run_id?(o(),r("span",y,"在线")):(o(),r("span",b,"离线"))])]))),256))])])],64)}}};export{V as default};
|
import{i as d}from"./http-74266e01.js";import{r as p,d as _,o,c as r,a as e,F as c,e as i,t as s,f as h,w as u,g as m}from"./app-65af0faa.js";const v=e("h3",null,"隧道列表",-1),k={class:"table table-hover"},f=e("thead",null,[e("tr",null,[e("th",{scope:"col"},"ID"),e("th",{scope:"col"},"名称"),e("th",{scope:"col"},"协议"),e("th",{scope:"col"},"本地地址"),e("th",{scope:"col"},"远程端口/域名"),e("th",{scope:"col"},"服务器"),e("th",{scope:"col"},"状态")])],-1),x={key:0},g={key:1},y={key:0,class:"text-success"},b={key:1,class:"text-danger"},V={name:"Index",setup(w){const a=p([{id:"0",protocol:"",server:{server_address:"",server_port:"",name:""},run_id:""}]);return d.get("tunnels").then(l=>{a.value=l.data}),(l,B)=>{const n=_("router-link");return o(),r(c,null,[v,e("table",k,[f,e("tbody",null,[(o(!0),r(c,null,i(a.value,t=>(o(),r("tr",null,[e("th",null,s(t.id),1),e("td",null,[h(n,{to:{name:"tunnels.show",params:{id:t.id}}},{default:u(()=>[m(s(t.name),1)]),_:2},1032,["to"])]),e("td",null,s(t.protocol.toString().toUpperCase()),1),e("td",null,s(t.local_address),1),e("td",null,[t.protocol==="http"||t.protocol==="https"?(o(),r("span",x,s(t.custom_domain),1)):(o(),r("span",g,s(t.server.server_address)+":"+s(t.remote_port),1))]),e("td",null,s(t.server.name),1),e("td",null,[t.run_id?(o(),r("span",y,"在线")):(o(),r("span",b,"离线"))])]))),256))])])],64)}}};export{V as default};
|
@ -1,4 +1,4 @@
|
|||||||
import{i as Tl}from"./http-1f667af7.js";import{r as tm,m as em,i as cL,n as pL,o as rm,c as am,a as Ke,t as kh,b as dL,F as gL}from"./app-22d7fab3.js";/*! *****************************************************************************
|
import{i as Tl}from"./http-74266e01.js";import{r as tm,m as em,i as cL,n as pL,o as rm,c as am,a as Ke,t as kh,b as dL,F as gL}from"./app-65af0faa.js";/*! *****************************************************************************
|
||||||
Copyright (c) Microsoft Corporation.
|
Copyright (c) Microsoft Corporation.
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for any
|
Permission to use, copy, modify, and/or distribute this software for any
|
@ -1 +0,0 @@
|
|||||||
import{p as R,r as u,i as L,q as B,o as p,c as v,a as r,t as _,f as C,u as b}from"./app-22d7fab3.js";import{i as m}from"./http-1f667af7.js";function y(){return y=Object.assign?Object.assign.bind():function(c){for(var e=1;e<arguments.length;e++){var t=arguments[e];for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&(c[a]=t[a])}return c},y.apply(this,arguments)}var E=function(){var e=!1,t=[],a=function(){if(!e){e=!0;for(var n=0,f=t.length;n<f;n++)t[n]()}},i=function(n){if(!e){t.push(n);return}n()},s={resolved:function(){return e},resolve:a,promise:{then:i}};return s},S=Object.prototype.hasOwnProperty;function A(){var c=E();return{notify:function(){c.resolve()},wait:function(){return c.promise},render:function(t,a,i){this.wait().then(function(){i(window.grecaptcha.render(t,a))})},reset:function(t){typeof t>"u"||(this.assertLoaded(),this.wait().then(function(){return window.grecaptcha.reset(t)}))},execute:function(t){typeof t>"u"||(this.assertLoaded(),this.wait().then(function(){return window.grecaptcha.execute(t)}))},checkRecaptchaLoad:function(){S.call(window,"grecaptcha")&&S.call(window.grecaptcha,"render")&&this.notify()},assertLoaded:function(){if(!c.resolved())throw new Error("ReCAPTCHA has not been loaded")}}}var l=A();typeof window<"u"&&(window.vueRecaptchaApiLoaded=l.notify);var M=R({name:"VueRecaptcha",props:{sitekey:{type:String,required:!0},theme:{type:String},badge:{type:String},type:{type:String},size:{type:String},tabindex:{type:String},loadRecaptchaScript:{type:Boolean,default:!0},recaptchaScriptId:{type:String,default:"__RECAPTCHA_SCRIPT"},recaptchaHost:{type:String,default:"www.google.com"},language:{type:String,default:""}},emits:["render","verify","expired","error"],setup:function(e,t){var a=t.slots,i=t.emit,s=u(null),o=u(null),n=function(h){i("verify",h)},f=function(){i("expired")},x=function(){i("error")};return L(function(){if(l.checkRecaptchaLoad(),e.loadRecaptchaScript&&!document.getElementById(e.recaptchaScriptId)){var d=document.createElement("script");d.id=e.recaptchaScriptId,d.src="https://"+e.recaptchaHost+"/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit&hl="+e.language,d.async=!0,d.defer=!0,document.head.appendChild(d)}var h=y({},e,{callback:n,"expired-callback":f,"error-callback":x}),g=s.value,k=a.default?g.children[0]:g;l.render(k,h,function(w){o.value=w,i("render",w)})}),{root:s,widgetId:o,reset:function(){l.reset(o.value)},execute:function(){l.execute(o.value)}}},render:function(){var e=this.$slots.default,t;return typeof e=="function"?t=e():t=e,B("div",{ref:"root"},t)}});const O=r("h3",null,"流量补给",-1),P={key:0},V={key:1},j=r("p",null,"完成验证码以签到",-1),H=r("button",{type:"button",class:"btn btn-primary",style:{display:"none"},id:"signinButton","data-bs-toggle":"modal","data-bs-target":"#signinModal"},null,-1),I={class:"modal fade",id:"signinModal",tabindex:"-1","aria-labelledby":"signinModalLabel","aria-hidden":"true"},q={class:"modal-dialog"},T={class:"modal-content"},$=r("div",{class:"modal-header"},[r("h1",{class:"modal-title fs-5",id:"signinModalLabel"},"签到")],-1),G={class:"modal-body"},N=r("div",{class:"modal-footer"},[r("button",{type:"button",class:"btn btn-primary","data-bs-dismiss":"modal"},"确定")],-1),F={name:"Sign",setup(c){const e=window.Base.ReCaptcha,t=u(""),a=u({last_sign_at:null,traffic:0}),i=u("");window.matchMedia("(prefers-color-scheme: dark)").matches?i.value="dark":i.value="light",m.get("user").then(o=>{a.value.traffic=o.data.traffic});function s(o){m.post("traffic",{recaptcha:o}).then(n=>{a.value=n.data,t.value=`获得了 ${n.data.traffic} GB 流量!`,n.data.traffic===0&&(t.value="没有获得流量~"),document.querySelector("#signinButton").click()}).finally(()=>{m.get("user").then(n=>{a.value.traffic=n.data.traffic}).finally(()=>{})})}return(o,n)=>(p(),v("div",null,[O,r("div",null,[r("p",null,"当前流量: "+_(a.value.traffic)+"GB",1),a.value.is_signed?(p(),v("div",P,"今日已签到")):(p(),v("div",V,[j,C(b(M),{sitekey:b(e),theme:i.value,loadRecaptchaScript:"",recaptchaHost:"www.recaptcha.net",onVerify:s},null,8,["sitekey","theme"])]))]),H,r("div",I,[r("div",q,[r("div",T,[$,r("div",G," 签到成功!"+_(t.value),1),N])])])]))}};export{F as default};
|
|
1
public/build/assets/Sign-f46d7e79.js
Normal file
1
public/build/assets/Sign-f46d7e79.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import{p as R,r as f,i as L,q as B,o as m,c as g,a,t as b,f as C,u as x,j as E,v as M}from"./app-65af0faa.js";import{i as h}from"./http-74266e01.js";function y(){return y=Object.assign?Object.assign.bind():function(c){for(var e=1;e<arguments.length;e++){var t=arguments[e];for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(c[n]=t[n])}return c},y.apply(this,arguments)}var V=function(){var e=!1,t=[],n=function(){if(!e){e=!0;for(var s=0,r=t.length;s<r;s++)t[s]()}},i=function(s){if(!e){t.push(s);return}s()},u={resolved:function(){return e},resolve:n,promise:{then:i}};return u},S=Object.prototype.hasOwnProperty;function j(){var c=V();return{notify:function(){c.resolve()},wait:function(){return c.promise},render:function(t,n,i){this.wait().then(function(){i(window.grecaptcha.render(t,n))})},reset:function(t){typeof t>"u"||(this.assertLoaded(),this.wait().then(function(){return window.grecaptcha.reset(t)}))},execute:function(t){typeof t>"u"||(this.assertLoaded(),this.wait().then(function(){return window.grecaptcha.execute(t)}))},checkRecaptchaLoad:function(){S.call(window,"grecaptcha")&&S.call(window.grecaptcha,"render")&&this.notify()},assertLoaded:function(){if(!c.resolved())throw new Error("ReCAPTCHA has not been loaded")}}}var p=j();typeof window<"u"&&(window.vueRecaptchaApiLoaded=p.notify);var A=R({name:"VueRecaptcha",props:{sitekey:{type:String,required:!0},theme:{type:String},badge:{type:String},type:{type:String},size:{type:String},tabindex:{type:String},loadRecaptchaScript:{type:Boolean,default:!0},recaptchaScriptId:{type:String,default:"__RECAPTCHA_SCRIPT"},recaptchaHost:{type:String,default:"www.google.com"},language:{type:String,default:""}},emits:["render","verify","expired","error"],setup:function(e,t){var n=t.slots,i=t.emit,u=f(null),l=f(null),s=function(v){i("verify",v)},r=function(){i("expired")},d=function(){i("error")};return L(function(){if(p.checkRecaptchaLoad(),e.loadRecaptchaScript&&!document.getElementById(e.recaptchaScriptId)){var o=document.createElement("script");o.id=e.recaptchaScriptId,o.src="https://"+e.recaptchaHost+"/recaptcha/api.js?onload=vueRecaptchaApiLoaded&render=explicit&hl="+e.language,o.async=!0,o.defer=!0,document.head.appendChild(o)}var v=y({},e,{callback:s,"expired-callback":r,"error-callback":d}),_=u.value,k=n.default?_.children[0]:_;p.render(k,v,function(w){l.value=w,i("render",w)})}),{root:u,widgetId:l,reset:function(){p.reset(l.value)},execute:function(){p.execute(l.value)}}},render:function(){var e=this.$slots.default,t;return typeof e=="function"?t=e():t=e,B("div",{ref:"root"},t)}});const O=a("h3",null,"流量补给",-1),P={key:0},H={key:1},I=a("p",null,"完成验证码以签到",-1),T={class:"mt-4"},q=a("h3",null,"兑换流量激活码",-1),$={class:"input-group mt-3"},D=a("button",{id:"signinButton",class:"btn btn-primary","data-bs-target":"#signinModal","data-bs-toggle":"modal",style:{display:"none"},type:"button"},null,-1),G={id:"signinModal","aria-hidden":"true","aria-labelledby":"signinModalLabel",class:"modal fade",tabindex:"-1"},N={class:"modal-dialog"},z={class:"modal-content"},U=a("div",{class:"modal-header"},[a("h1",{id:"signinModalLabel",class:"modal-title fs-5"},"签到")],-1),F={class:"modal-body"},J=a("div",{class:"modal-footer"},[a("button",{class:"btn btn-primary","data-bs-dismiss":"modal",type:"button"},"确定")],-1),W={name:"Sign",setup(c){const e=window.Base.ReCaptcha,t=f(""),n=f({last_sign_at:null,traffic:0}),i=f(""),u=f("");window.matchMedia("(prefers-color-scheme: dark)").matches?i.value="dark":i.value="light",h.get("user").then(r=>{n.value.traffic=r.data.traffic});function l(r){h.post("traffic",{recaptcha:r}).then(d=>{n.value=d.data,t.value=`获得了 ${d.data.traffic} GB 流量!`,d.data.traffic===0&&(t.value="没有获得流量~"),document.querySelector("#signinButton").click()}).finally(()=>{h.get("user").then(d=>{n.value.traffic=d.data.traffic}).finally(()=>{})})}function s(){h.post("/codes/use",{code:u.value}).then(r=>{alert(r.data.message)}).catch(r=>{alert(r.data.message)}).finally(()=>{h.get("user").then(r=>{n.value.traffic=r.data.traffic})})}return(r,d)=>(m(),g("div",null,[O,a("div",null,[a("p",null,"当前流量: "+b(n.value.traffic)+"GB",1),n.value.is_signed?(m(),g("div",P,"今日已签到")):(m(),g("div",H,[I,C(x(A),{sitekey:x(e),theme:i.value,loadRecaptchaScript:"",recaptchaHost:"www.recaptcha.net",onVerify:l},null,8,["sitekey","theme"])]))]),a("div",T,[q,a("div",$,[E(a("input",{"onUpdate:modelValue":d[0]||(d[0]=o=>u.value=o),class:"form-control",type:"text"},null,512),[[M,u.value]]),a("button",{class:"btn btn-primary",onClick:s},"兑换")])]),D,a("div",G,[a("div",N,[a("div",z,[U,a("div",F," 签到成功!"+b(t.value),1),J])])])]))}};export{W as default};
|
@ -1 +1 @@
|
|||||||
import{o as e,c as s,b as o,r as l,a as t,F as u,e as d,t as i,f as _}from"./app-22d7fab3.js";import{i as m}from"./http-1f667af7.js";const h={key:0,class:"text-success"},p={key:1,class:"text-danger"},b={key:2,class:"text-warning"},x={name:"ServerStatus",props:{status:{type:String,required:!0}},setup(a){return(n,r)=>a.status==="up"?(e(),s("span",h," 正常 ")):a.status==="down"?(e(),s("span",p," 离线 ")):a.status==="maintenance"?(e(),s("span",b," 维护 ")):o("",!0)}},f=t("h3",null,"节点状态",-1),g={class:"table table-hover table-bordered table-responsive align-middle mt-3"},v=t("thead",{class:"text-center"},[t("tr",null,[t("th",{scope:"col"},"节点名称"),t("th",{scope:"col"},"节点状态")])],-1),y={class:"text-center"},B={name:"Status",setup(a){const n=l([]);return m.get("servers").then(r=>{n.value=r.data}),(r,k)=>(e(),s("div",null,[f,t("table",g,[v,t("tbody",y,[(e(!0),s(u,null,d(n.value,c=>(e(),s("tr",null,[t("td",null,i(c.name),1),t("td",null,[_(x,{status:c.status},null,8,["status"])])]))),256))])])]))}};export{B as default};
|
import{o as e,c as s,b as o,r as l,a as t,F as u,e as d,t as i,f as _}from"./app-65af0faa.js";import{i as m}from"./http-74266e01.js";const h={key:0,class:"text-success"},p={key:1,class:"text-danger"},b={key:2,class:"text-warning"},x={name:"ServerStatus",props:{status:{type:String,required:!0}},setup(a){return(n,r)=>a.status==="up"?(e(),s("span",h," 正常 ")):a.status==="down"?(e(),s("span",p," 离线 ")):a.status==="maintenance"?(e(),s("span",b," 维护 ")):o("",!0)}},f=t("h3",null,"节点状态",-1),g={class:"table table-hover table-bordered table-responsive align-middle mt-3"},v=t("thead",{class:"text-center"},[t("tr",null,[t("th",{scope:"col"},"节点名称"),t("th",{scope:"col"},"节点状态")])],-1),y={class:"text-center"},B={name:"Status",setup(a){const n=l([]);return m.get("servers").then(r=>{n.value=r.data}),(r,k)=>(e(),s("div",null,[f,t("table",g,[v,t("tbody",y,[(e(!0),s(u,null,d(n.value,c=>(e(),s("tr",null,[t("td",null,i(c.name),1),t("td",null,[_(x,{status:c.status},null,8,["status"])])]))),256))])])]))}};export{B as default};
|
@ -1 +1 @@
|
|||||||
import{_ as w,r as u,o as t,c as o,a as e,j as m,v as k,b as r,F as f,e as I,t as b,g as x,l as S,s as B,x as N}from"./app-22d7fab3.js";import{i as y}from"./http-1f667af7.js";const a=_=>(B("data-v-37623621"),_=_(),N(),_),U=a(()=>e("div",null,[e("h3",null,"发工单")],-1)),D=a(()=>e("h5",null,"有遇到什么问题吗?",-1)),F=x(" 您可以选择以下常见问题: "),M=x(" "),j={class:"input-group mb-3"},E={key:0,class:"input-group"},L={key:1},R={key:0},q=a(()=>e("h5",{class:"mt-3"},"选择发工单的平台",-1)),z=a(()=>e("p",null,"如果您在选中的平台没有账号,我们将会帮您自动创建一个。",-1)),A={class:"form-group form-check"},G=["id","value"],H=["for","textContent"],J={key:1},K=a(()=>e("h5",{class:"mt-3"},"暂时没有可用的提供商",-1)),O=[K],P={key:2},Q=["disabled","textContent"],W={key:0},X={key:1,class:"mt-3"},Y=a(()=>e("h5",null,"完成",-1)),Z=a(()=>e("p",null,"如果您浏览器没有打开新的创建,请点击以下链接来打开。",-1)),$=["href"],ee={name:"Ticket",setup(_){const c=u([]),v=u(""),l=u(""),n=u(""),p=u(""),d=u(!1);y.get("providers").then(h=>{c.value=h.data,c.value.length>0&&(v.value=c.value[0])});function g(){d.value=!0,y.post("providers/"+v.value+"/ticket",{title:l.value,content:n.value}).then(h=>{p.value=h.data.redirect_url,setTimeout(()=>{window.open(p.value,"_blank")})}).finally(()=>{d.value=!1})}function C(){l.value="域名 {你的域名} 过白。",n.value="您好,我的域名已备案,请将我的域名 {你的域名} 加入白名单,谢谢。"}function T(){l.value="{节点} 的隧道无法连接。",n.value="您好,这个节点无法连接,请检查。"}return(h,i)=>(t(),o(f,null,[U,e("div",null,[D,e("div",{class:"mb-3"},[F,e("a",{class:"link",onClick:C},"域名白名单"),M,e("a",{class:"link",onClick:T},"映射问题")]),e("div",j,[m(e("input",{"onUpdate:modelValue":i[0]||(i[0]=s=>l.value=s),autofocus:"",class:"form-control",placeholder:"简要概述您遇到的问题",type:"text"},null,512),[[k,l.value]])]),l.value?(t(),o("div",E,[m(e("textarea",{"onUpdate:modelValue":i[1]||(i[1]=s=>n.value=s),class:"form-control",placeholder:"详细说明您遇到的问题..."},null,512),[[k,n.value]])])):r("",!0),l.value?(t(),o("div",L,[c.value?(t(),o("div",R,[q,z,(t(!0),o(f,null,I(c.value,s=>(t(),o("div",A,[m(e("input",{id:"providers_"+s,"onUpdate:modelValue":i[2]||(i[2]=V=>v.value=V),value:s,class:"form-check-input",name:"provider",type:"radio"},null,8,G),[[S,v.value,void 0,{value:!0}]]),e("label",{for:"providers_"+s,class:"form-check-label",textContent:b(s)},null,8,H)]))),256))])):(t(),o("div",J,O)),n.value?(t(),o("div",P,[e("button",{disabled:d.value,class:"btn btn-primary mt-3",onClick:g,textContent:b(d.value?"请稍后":"创建工单")},null,8,Q)])):r("",!0)])):r("",!0)]),d.value?(t(),o("p",W,"正在打开工单...")):r("",!0),p.value?(t(),o("div",X,[Y,Z,e("a",{href:p.value,class:"link",target:"_blank"},"打开工单",8,$)])):r("",!0)],64))}},se=w(ee,[["__scopeId","data-v-37623621"]]);export{se as default};
|
import{_ as w,r as u,o as t,c as o,a as e,j as m,v as k,b as r,F as f,e as I,t as b,g as x,l as S,s as B,x as N}from"./app-65af0faa.js";import{i as y}from"./http-74266e01.js";const a=_=>(B("data-v-37623621"),_=_(),N(),_),U=a(()=>e("div",null,[e("h3",null,"发工单")],-1)),D=a(()=>e("h5",null,"有遇到什么问题吗?",-1)),F=x(" 您可以选择以下常见问题: "),M=x(" "),j={class:"input-group mb-3"},E={key:0,class:"input-group"},L={key:1},R={key:0},q=a(()=>e("h5",{class:"mt-3"},"选择发工单的平台",-1)),z=a(()=>e("p",null,"如果您在选中的平台没有账号,我们将会帮您自动创建一个。",-1)),A={class:"form-group form-check"},G=["id","value"],H=["for","textContent"],J={key:1},K=a(()=>e("h5",{class:"mt-3"},"暂时没有可用的提供商",-1)),O=[K],P={key:2},Q=["disabled","textContent"],W={key:0},X={key:1,class:"mt-3"},Y=a(()=>e("h5",null,"完成",-1)),Z=a(()=>e("p",null,"如果您浏览器没有打开新的创建,请点击以下链接来打开。",-1)),$=["href"],ee={name:"Ticket",setup(_){const c=u([]),v=u(""),l=u(""),n=u(""),p=u(""),d=u(!1);y.get("providers").then(h=>{c.value=h.data,c.value.length>0&&(v.value=c.value[0])});function g(){d.value=!0,y.post("providers/"+v.value+"/ticket",{title:l.value,content:n.value}).then(h=>{p.value=h.data.redirect_url,setTimeout(()=>{window.open(p.value,"_blank")})}).finally(()=>{d.value=!1})}function C(){l.value="域名 {你的域名} 过白。",n.value="您好,我的域名已备案,请将我的域名 {你的域名} 加入白名单,谢谢。"}function T(){l.value="{节点} 的隧道无法连接。",n.value="您好,这个节点无法连接,请检查。"}return(h,i)=>(t(),o(f,null,[U,e("div",null,[D,e("div",{class:"mb-3"},[F,e("a",{class:"link",onClick:C},"域名白名单"),M,e("a",{class:"link",onClick:T},"映射问题")]),e("div",j,[m(e("input",{"onUpdate:modelValue":i[0]||(i[0]=s=>l.value=s),autofocus:"",class:"form-control",placeholder:"简要概述您遇到的问题",type:"text"},null,512),[[k,l.value]])]),l.value?(t(),o("div",E,[m(e("textarea",{"onUpdate:modelValue":i[1]||(i[1]=s=>n.value=s),class:"form-control",placeholder:"详细说明您遇到的问题..."},null,512),[[k,n.value]])])):r("",!0),l.value?(t(),o("div",L,[c.value?(t(),o("div",R,[q,z,(t(!0),o(f,null,I(c.value,s=>(t(),o("div",A,[m(e("input",{id:"providers_"+s,"onUpdate:modelValue":i[2]||(i[2]=V=>v.value=V),value:s,class:"form-check-input",name:"provider",type:"radio"},null,8,G),[[S,v.value,void 0,{value:!0}]]),e("label",{for:"providers_"+s,class:"form-check-label",textContent:b(s)},null,8,H)]))),256))])):(t(),o("div",J,O)),n.value?(t(),o("div",P,[e("button",{disabled:d.value,class:"btn btn-primary mt-3",onClick:g,textContent:b(d.value?"请稍后":"创建工单")},null,8,Q)])):r("",!0)])):r("",!0)]),d.value?(t(),o("p",W,"正在打开工单...")):r("",!0),p.value?(t(),o("div",X,[Y,Z,e("a",{href:p.value,class:"link",target:"_blank"},"打开工单",8,$)])):r("",!0)],64))}},se=w(ee,[["__scopeId","data-v-37623621"]]);export{se as default};
|
File diff suppressed because one or more lines are too long
@ -1 +1 @@
|
|||||||
import{y as a,m as n}from"./app-22d7fab3.js";let t=a.create({baseURL:"/api",timeout:1e4,headers:{"X-Requested-With":"XMLHttpRequest","X-CSRF-TOKEN":document.querySelector('meta[name="csrf-token"]').getAttribute("content")}});t.interceptors.request.use(e=>(e.headers,e.headers.Accept="application/json",e),e=>(console.error(e),Promise.reject(e)));t.interceptors.response.use(e=>Promise.resolve(e),e=>{console.error("axios error",e);let s=[];e.response.data.data&&(s=e.response.data.data),e.response.data.message&&(s=e.response.data.message),e.response.data.error&&(s=e.response.data.error.message),e.response.status===429?alert("请求次数过多"):e.response.status===401||(e.response.status===404?n.push({name:"index"}):s.length!==0&&alert(s))});export{t as i};
|
import{y as a,m as n}from"./app-65af0faa.js";let t=a.create({baseURL:"/api",timeout:1e4,headers:{"X-Requested-With":"XMLHttpRequest","X-CSRF-TOKEN":document.querySelector('meta[name="csrf-token"]').getAttribute("content")}});t.interceptors.request.use(e=>(e.headers,e.headers.Accept="application/json",e),e=>(console.error(e),Promise.reject(e)));t.interceptors.response.use(e=>Promise.resolve(e),e=>{console.error("axios error",e);let s=[];e.response.data.data&&(s=e.response.data.data),e.response.data.message&&(s=e.response.data.message),e.response.data.error&&(s=e.response.data.error.message),e.response.status===429?alert("请求次数过多"):e.response.status===401||(e.response.status===404?n.push({name:"index"}):s.length!==0&&alert(s))});export{t as i};
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"_http-1f667af7.js": {
|
"_http-74266e01.js": {
|
||||||
"file": "assets/http-1f667af7.js",
|
"file": "assets/http-74266e01.js",
|
||||||
"imports": [
|
"imports": [
|
||||||
"resources/js/app.js"
|
"resources/js/app.js"
|
||||||
]
|
]
|
||||||
@ -41,51 +41,51 @@
|
|||||||
"resources/js/views/Charge.vue",
|
"resources/js/views/Charge.vue",
|
||||||
"resources/js/views/Ticket.vue"
|
"resources/js/views/Ticket.vue"
|
||||||
],
|
],
|
||||||
"file": "assets/app-22d7fab3.js",
|
"file": "assets/app-65af0faa.js",
|
||||||
"isEntry": true,
|
"isEntry": true,
|
||||||
"src": "resources/js/app.js"
|
"src": "resources/js/app.js"
|
||||||
},
|
},
|
||||||
"resources/js/views/Charge.vue": {
|
"resources/js/views/Charge.vue": {
|
||||||
"file": "assets/Charge-e7d5afc9.js",
|
"file": "assets/Charge-0827f5c4.js",
|
||||||
"imports": [
|
"imports": [
|
||||||
"resources/js/app.js",
|
"resources/js/app.js",
|
||||||
"_http-1f667af7.js"
|
"_http-74266e01.js"
|
||||||
],
|
],
|
||||||
"isDynamicEntry": true,
|
"isDynamicEntry": true,
|
||||||
"src": "resources/js/views/Charge.vue"
|
"src": "resources/js/views/Charge.vue"
|
||||||
},
|
},
|
||||||
"resources/js/views/Downloads.vue": {
|
"resources/js/views/Downloads.vue": {
|
||||||
"file": "assets/Downloads-7b82c5f5.js",
|
"file": "assets/Downloads-d3293bd0.js",
|
||||||
"imports": [
|
"imports": [
|
||||||
"_http-1f667af7.js",
|
"_http-74266e01.js",
|
||||||
"resources/js/app.js"
|
"resources/js/app.js"
|
||||||
],
|
],
|
||||||
"isDynamicEntry": true,
|
"isDynamicEntry": true,
|
||||||
"src": "resources/js/views/Downloads.vue"
|
"src": "resources/js/views/Downloads.vue"
|
||||||
},
|
},
|
||||||
"resources/js/views/Index.vue": {
|
"resources/js/views/Index.vue": {
|
||||||
"file": "assets/Index-cdfbf04e.js",
|
"file": "assets/Index-29944ef4.js",
|
||||||
"imports": [
|
"imports": [
|
||||||
"_http-1f667af7.js",
|
"_http-74266e01.js",
|
||||||
"resources/js/app.js"
|
"resources/js/app.js"
|
||||||
],
|
],
|
||||||
"isDynamicEntry": true,
|
"isDynamicEntry": true,
|
||||||
"src": "resources/js/views/Index.vue"
|
"src": "resources/js/views/Index.vue"
|
||||||
},
|
},
|
||||||
"resources/js/views/Sign.vue": {
|
"resources/js/views/Sign.vue": {
|
||||||
"file": "assets/Sign-1ae8e0e0.js",
|
"file": "assets/Sign-f46d7e79.js",
|
||||||
"imports": [
|
"imports": [
|
||||||
"resources/js/app.js",
|
"resources/js/app.js",
|
||||||
"_http-1f667af7.js"
|
"_http-74266e01.js"
|
||||||
],
|
],
|
||||||
"isDynamicEntry": true,
|
"isDynamicEntry": true,
|
||||||
"src": "resources/js/views/Sign.vue"
|
"src": "resources/js/views/Sign.vue"
|
||||||
},
|
},
|
||||||
"resources/js/views/Status.vue": {
|
"resources/js/views/Status.vue": {
|
||||||
"file": "assets/Status-06a9b78c.js",
|
"file": "assets/Status-29982c8b.js",
|
||||||
"imports": [
|
"imports": [
|
||||||
"resources/js/app.js",
|
"resources/js/app.js",
|
||||||
"_http-1f667af7.js"
|
"_http-74266e01.js"
|
||||||
],
|
],
|
||||||
"isDynamicEntry": true,
|
"isDynamicEntry": true,
|
||||||
"src": "resources/js/views/Status.vue"
|
"src": "resources/js/views/Status.vue"
|
||||||
@ -98,36 +98,36 @@
|
|||||||
"css": [
|
"css": [
|
||||||
"assets/Ticket-ce48f17d.css"
|
"assets/Ticket-ce48f17d.css"
|
||||||
],
|
],
|
||||||
"file": "assets/Ticket-e5fc00f9.js",
|
"file": "assets/Ticket-72a5f323.js",
|
||||||
"imports": [
|
"imports": [
|
||||||
"resources/js/app.js",
|
"resources/js/app.js",
|
||||||
"_http-1f667af7.js"
|
"_http-74266e01.js"
|
||||||
],
|
],
|
||||||
"isDynamicEntry": true,
|
"isDynamicEntry": true,
|
||||||
"src": "resources/js/views/Ticket.vue"
|
"src": "resources/js/views/Ticket.vue"
|
||||||
},
|
},
|
||||||
"resources/js/views/Tunnels/Create.vue": {
|
"resources/js/views/Tunnels/Create.vue": {
|
||||||
"file": "assets/Create-7479ebe3.js",
|
"file": "assets/Create-9128b1c6.js",
|
||||||
"imports": [
|
"imports": [
|
||||||
"resources/js/app.js",
|
"resources/js/app.js",
|
||||||
"_http-1f667af7.js"
|
"_http-74266e01.js"
|
||||||
],
|
],
|
||||||
"isDynamicEntry": true,
|
"isDynamicEntry": true,
|
||||||
"src": "resources/js/views/Tunnels/Create.vue"
|
"src": "resources/js/views/Tunnels/Create.vue"
|
||||||
},
|
},
|
||||||
"resources/js/views/Tunnels/Index.vue": {
|
"resources/js/views/Tunnels/Index.vue": {
|
||||||
"file": "assets/Index-f4d5af43.js",
|
"file": "assets/Index-56619578.js",
|
||||||
"imports": [
|
"imports": [
|
||||||
"_http-1f667af7.js",
|
"_http-74266e01.js",
|
||||||
"resources/js/app.js"
|
"resources/js/app.js"
|
||||||
],
|
],
|
||||||
"isDynamicEntry": true,
|
"isDynamicEntry": true,
|
||||||
"src": "resources/js/views/Tunnels/Index.vue"
|
"src": "resources/js/views/Tunnels/Index.vue"
|
||||||
},
|
},
|
||||||
"resources/js/views/Tunnels/Show.vue": {
|
"resources/js/views/Tunnels/Show.vue": {
|
||||||
"file": "assets/Show-359be435.js",
|
"file": "assets/Show-a5280b04.js",
|
||||||
"imports": [
|
"imports": [
|
||||||
"_http-1f667af7.js",
|
"_http-74266e01.js",
|
||||||
"resources/js/app.js"
|
"resources/js/app.js"
|
||||||
],
|
],
|
||||||
"isDynamicEntry": true,
|
"isDynamicEntry": true,
|
||||||
|
@ -45,7 +45,7 @@ const items = ref([
|
|||||||
route: "tunnels.create",
|
route: "tunnels.create",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "签到",
|
name: "流量补给",
|
||||||
route: "sign",
|
route: "sign",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -17,27 +17,36 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
<h3>兑换流量激活码</h3>
|
||||||
|
<div class="input-group mt-3">
|
||||||
|
<input v-model="activate_code" class="form-control" type="text">
|
||||||
|
<button class="btn btn-primary" @click="exchange">兑换</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
|
||||||
class="btn btn-primary"
|
|
||||||
style="display: none"
|
|
||||||
id="signinButton"
|
id="signinButton"
|
||||||
|
class="btn btn-primary"
|
||||||
|
data-bs-target="#signinModal"
|
||||||
data-bs-toggle="modal"
|
data-bs-toggle="modal"
|
||||||
data-bs-target="#signinModal">
|
style="display: none"
|
||||||
|
type="button">
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
|
||||||
<div class="modal fade" id="signinModal" tabindex="-1" aria-labelledby="signinModalLabel" aria-hidden="true">
|
<div id="signinModal" aria-hidden="true" aria-labelledby="signinModalLabel" class="modal fade" tabindex="-1">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h1 class="modal-title fs-5" id="signinModalLabel">签到</h1>
|
<h1 id="signinModalLabel" class="modal-title fs-5">签到</h1>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
签到成功!{{ content }}
|
签到成功!{{ content }}
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">确定</button>
|
<button class="btn btn-primary" data-bs-dismiss="modal" type="button">确定</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -61,6 +70,7 @@ const traffic = ref({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const theme = ref("")
|
const theme = ref("")
|
||||||
|
const activate_code = ref("")
|
||||||
|
|
||||||
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||||
theme.value = "dark"
|
theme.value = "dark"
|
||||||
@ -101,6 +111,21 @@ function sign(captcha_token) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function exchange() {
|
||||||
|
http.post('/codes/use', {
|
||||||
|
'code': activate_code.value
|
||||||
|
}).then(res => {
|
||||||
|
alert(res.data.message)
|
||||||
|
}).catch(res => {
|
||||||
|
alert(res.data.message)
|
||||||
|
}).finally(() => {
|
||||||
|
http.get("user")
|
||||||
|
.then((res) => {
|
||||||
|
traffic.value.traffic = res.data.traffic;
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// function refreshSign() {
|
// function refreshSign() {
|
||||||
// const date = new Date(traffic.value.last_sign_at)
|
// const date = new Date(traffic.value.last_sign_at)
|
||||||
//
|
//
|
||||||
|
13
resources/views/admin/codes/create.blade.php
Normal file
13
resources/views/admin/codes/create.blade.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<x-app-layout>
|
||||||
|
<h3 class="mb-3">创建流量激活码</h3>
|
||||||
|
<form action="{{ route('admin.codes.store') }}" method="post">
|
||||||
|
@csrf
|
||||||
|
<label for="name" class="form-label">数量</label>
|
||||||
|
<input type="number" name="amount" id="amount" placeholder="数量" class="form-control mb-3" required>
|
||||||
|
|
||||||
|
<label for="name" class="form-label">流量</label>
|
||||||
|
<input type="number" name="traffic" id="traffic" placeholder="流量 (GB)" class="form-control mb-3" required>
|
||||||
|
|
||||||
|
<button class="btn btn-primary" type="submit">创建</button>
|
||||||
|
</form>
|
||||||
|
</x-app-layout>
|
20
resources/views/admin/codes/edit.blade.php
Normal file
20
resources/views/admin/codes/edit.blade.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<x-app-layout>
|
||||||
|
<h3 class="mb-3">编辑客户端</h3>
|
||||||
|
<form action="{{ route('admin.clients.update', $client->id) }}" method="post">
|
||||||
|
@csrf
|
||||||
|
@method('PUT')
|
||||||
|
<label for="name" class="form-label">名称</label>
|
||||||
|
<input type="text" name="name" id="name" placeholder="名称" class="form-control mb-3" required
|
||||||
|
value="{{ $client->name }}">
|
||||||
|
|
||||||
|
<label for="name" class="form-label">架构</label>
|
||||||
|
<input type="text" name="arch" id="arch" placeholder="架构" class="form-control mb-3" required
|
||||||
|
value="{{ $client->arch }}">
|
||||||
|
|
||||||
|
<label for="name" class="form-label">下载链接</label>
|
||||||
|
<input type="text" name="url" id="url" placeholder="下载链接" class="form-control mb-3" required
|
||||||
|
value="{{ $client->url }}">
|
||||||
|
|
||||||
|
<button class="btn btn-primary" type="submit">保存更改</button>
|
||||||
|
</form>
|
||||||
|
</x-app-layout>
|
45
resources/views/admin/codes/index.blade.php
Normal file
45
resources/views/admin/codes/index.blade.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<x-app-layout>
|
||||||
|
<h3>流量激活码</h3>
|
||||||
|
|
||||||
|
<a href="{{ route('admin.codes.create') }}">新建激活码</a>
|
||||||
|
|
||||||
|
<div class="alert alert-primary mt-3" role="alert">
|
||||||
|
总计: {{ $count }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="mt-3 table table-hover text-center table-bordered" style="vertical-align: middle">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>激活码</th>
|
||||||
|
<th>流量</th>
|
||||||
|
<th>使用用户</th>
|
||||||
|
<th>操作</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@foreach ($codes as $code)
|
||||||
|
<tr>
|
||||||
|
<td>{{ $code->id }}</td>
|
||||||
|
<td>{{ $code->code }}</td>
|
||||||
|
<td>{{ $code->traffic }}</td>
|
||||||
|
<td>
|
||||||
|
@isset($code->user_id)
|
||||||
|
{{ $code->user->name }} # {{ $code->user_id }}
|
||||||
|
@endisset
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<form action="{{ route('admin.codes.destroy', ['code' => $code]) }}" method="POST"
|
||||||
|
onsubmit="return confirm('真的要删除吗?')">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<button type="submit" class="btn btn-sm btn-danger">删除</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</x-app-layout>
|
8
resources/views/admin/codes/show.blade.php
Normal file
8
resources/views/admin/codes/show.blade.php
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<x-app-layout>
|
||||||
|
<h3 class="mb-3">流量激活码生成详情</h3>
|
||||||
|
<textarea class="form-control" id="code" rows="10" readonly>
|
||||||
|
@foreach($codes as $code)
|
||||||
|
{{ $code }}
|
||||||
|
@endforeach
|
||||||
|
</textarea>
|
||||||
|
</x-app-layout>
|
@ -86,7 +86,7 @@
|
|||||||
<td>{{ $host->created_at }}</td>
|
<td>{{ $host->created_at }}</td>
|
||||||
<td>{{ $host->updated_at }}</td>
|
<td>{{ $host->updated_at }}</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ route('admin.tunnels.show', ['tunnel' => $host]) }}"
|
<a href="{{ route('admin.tunnels.show', ['host' => $host]) }}"
|
||||||
class="btn btn-sm btn-primary">编辑</a>
|
class="btn btn-sm btn-primary">编辑</a>
|
||||||
|
|
||||||
<form action="{{ route('admin.tunnels.destroy', ['tunnel' => $host]) }}" method="POST"
|
<form action="{{ route('admin.tunnels.destroy', ['tunnel' => $host]) }}" method="POST"
|
||||||
|
@ -42,6 +42,9 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{ route('admin.clients.index') }}">客户端</a>
|
<a class="nav-link" href="{{ route('admin.clients.index') }}">客户端</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{{ route('admin.codes.index') }}">流量激活码</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="navbar-nav ml-auto mb-2 mb-lg-0">
|
<ul class="navbar-nav ml-auto mb-2 mb-lg-0">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
use App\Http\Controllers\Admin\ServerController;
|
use App\Http\Controllers\Admin\ServerController;
|
||||||
use App\Http\Controllers\Admin\UserController;
|
use App\Http\Controllers\Admin\UserController;
|
||||||
use App\Http\Controllers\Admin\ClientController;
|
use App\Http\Controllers\Admin\ClientController;
|
||||||
|
use App\Http\Controllers\Admin\TrafficActivateCodeController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
Route::withoutMiddleware('auth:admin')->group(function() {
|
Route::withoutMiddleware('auth:admin')->group(function() {
|
||||||
@ -20,6 +21,9 @@
|
|||||||
Route::resource('servers', ServerController::class);
|
Route::resource('servers', ServerController::class);
|
||||||
Route::resource('tunnels', TunnelController::class);
|
Route::resource('tunnels', TunnelController::class);
|
||||||
Route::resource('clients', ClientController::class);
|
Route::resource('clients', ClientController::class);
|
||||||
|
Route::resource('codes', TrafficActivateCodeController::class)->except([
|
||||||
|
'show', 'edit', 'update'
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
Route::get('/logout', [IndexController::class, 'logout'])->name('logout');
|
Route::get('/logout', [IndexController::class, 'logout'])->name('logout');
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
use App\Http\Controllers\Application\UserController as ApplicationUserController;
|
use App\Http\Controllers\Application\UserController as ApplicationUserController;
|
||||||
use App\Http\Controllers\Api\ClientController;
|
use App\Http\Controllers\Api\ClientController;
|
||||||
use App\Http\Controllers\Review\ReviewController;
|
use App\Http\Controllers\Review\ReviewController;
|
||||||
|
use App\Http\Controllers\Api\TrafficActivateCodeController;
|
||||||
|
|
||||||
Route::prefix('tunnel')->name('api.tunnel.')->group(function () {
|
Route::prefix('tunnel')->name('api.tunnel.')->group(function () {
|
||||||
Route::post('/handler/{key}', [PortManagerController::class, 'handler'])->name('handler');
|
Route::post('/handler/{key}', [PortManagerController::class, 'handler'])->name('handler');
|
||||||
@ -29,6 +30,7 @@
|
|||||||
Route::apiResource('servers', ServerController::class);
|
Route::apiResource('servers', ServerController::class);
|
||||||
|
|
||||||
Route::apiResource('clients', ClientController::class);
|
Route::apiResource('clients', ClientController::class);
|
||||||
|
Route::post('codes/use', [TrafficActivateCodeController::class, 'useActivateCode'])->name('codes.useActivateCode');
|
||||||
|
|
||||||
Route::get('traffic', [TrafficController::class, 'free']);
|
Route::get('traffic', [TrafficController::class, 'free']);
|
||||||
Route::post('traffic', [TrafficController::class, 'sign']);
|
Route::post('traffic', [TrafficController::class, 'sign']);
|
||||||
|
Loading…
Reference in New Issue
Block a user