Compare commits
2 Commits
dcf587dc8a
...
cb99b03c87
| Author | SHA1 | Date | |
|---|---|---|---|
| cb99b03c87 | |||
| 8e941d6fbd |
508
cli-traffic.html
508
cli-traffic.html
@ -36,6 +36,7 @@
|
|||||||
<script src="static/js/countdown.js"></script>
|
<script src="static/js/countdown.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/qrcode@1.4.4/build/qrcode.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/qrcode@1.4.4/build/qrcode.min.js"></script>
|
||||||
<script src="static/js/common.js?20250717"></script>
|
<script src="static/js/common.js?20250717"></script>
|
||||||
|
<link rel="stylesheet" href="static/css/cli-traffic.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
@ -116,6 +117,14 @@
|
|||||||
长效号码
|
长效号码
|
||||||
</vs-sidebar-item>
|
</vs-sidebar-item>
|
||||||
</vs-sidebar-group>
|
</vs-sidebar-group>
|
||||||
|
<vs-sidebar-group open title="API管理">
|
||||||
|
<vs-sidebar-item
|
||||||
|
index="5"
|
||||||
|
@click="handleActiveMenu(5)"
|
||||||
|
icon="vpn_key"
|
||||||
|
>API密钥</vs-sidebar-item
|
||||||
|
>
|
||||||
|
</vs-sidebar-group>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -182,7 +191,24 @@
|
|||||||
|
|
||||||
<div class="content-conter-header" v-if="activeMenu === 3||activeMenu===4">
|
<div class="content-conter-header" v-if="activeMenu === 3||activeMenu===4">
|
||||||
<vs-select
|
<vs-select
|
||||||
|
v-model="smsQuery.platform"
|
||||||
autocomplete
|
autocomplete
|
||||||
|
clearable
|
||||||
|
class="selectExample"
|
||||||
|
placeholder="平台"
|
||||||
|
label="平台"
|
||||||
|
@change="handlePlatformChange"
|
||||||
|
>
|
||||||
|
<vs-select-item v-for="item in smsPlatformList"
|
||||||
|
:key="'sms_platform_'+item.value"
|
||||||
|
:value="item.value"
|
||||||
|
:text="item.label"
|
||||||
|
>
|
||||||
|
</vs-select-item>
|
||||||
|
</vs-select>
|
||||||
|
<vs-select
|
||||||
|
autocomplete
|
||||||
|
clearable
|
||||||
v-model="smsQuery.serviceCode"
|
v-model="smsQuery.serviceCode"
|
||||||
autocomplete
|
autocomplete
|
||||||
class="selectExample"
|
class="selectExample"
|
||||||
@ -194,7 +220,7 @@
|
|||||||
:key="'sms_service_'+item.code"
|
:key="'sms_service_'+item.code"
|
||||||
:value="item.code"
|
:value="item.code"
|
||||||
:text="item.name"
|
:text="item.name"
|
||||||
@click="handleSmsServiceChange(item)"
|
@click="handleFormServiceChange(item)"
|
||||||
></vs-select-item>
|
></vs-select-item>
|
||||||
</vs-select>
|
</vs-select>
|
||||||
|
|
||||||
@ -375,6 +401,7 @@
|
|||||||
<vs-row v-else-if="activeMenu===3" class="content-conter-container">
|
<vs-row v-else-if="activeMenu===3" class="content-conter-container">
|
||||||
<vs-table class="tablex" :data="smsList">
|
<vs-table class="tablex" :data="smsList">
|
||||||
<template slot="thead">
|
<template slot="thead">
|
||||||
|
<vs-th> 通道 </vs-th>
|
||||||
<vs-th> 服务 </vs-th>
|
<vs-th> 服务 </vs-th>
|
||||||
<vs-th> Phone </vs-th>
|
<vs-th> Phone </vs-th>
|
||||||
<vs-th> 验证码 </vs-th>
|
<vs-th> 验证码 </vs-th>
|
||||||
@ -385,6 +412,10 @@
|
|||||||
|
|
||||||
<template slot-scope="{data}">
|
<template slot-scope="{data}">
|
||||||
<vs-tr :key="indextr" v-for="(tr, indextr) in data">
|
<vs-tr :key="indextr" v-for="(tr, indextr) in data">
|
||||||
|
<vs-td :data="data[indextr].platformName">
|
||||||
|
{{data[indextr].platformName}}
|
||||||
|
</vs-td>
|
||||||
|
|
||||||
<vs-td :data="data[indextr].service">
|
<vs-td :data="data[indextr].service">
|
||||||
{{data[indextr].service}}
|
{{data[indextr].service}}
|
||||||
</vs-td>
|
</vs-td>
|
||||||
@ -435,11 +466,13 @@
|
|||||||
<vs-row v-else-if="activeMenu===4" class="content-conter-container">
|
<vs-row v-else-if="activeMenu===4" class="content-conter-container">
|
||||||
<vs-table class="tablex" :data="smsList">
|
<vs-table class="tablex" :data="smsList">
|
||||||
<template slot="thead">
|
<template slot="thead">
|
||||||
|
<vs-th> 通道 </vs-th>
|
||||||
<vs-th> 服务 </vs-th>
|
<vs-th> 服务 </vs-th>
|
||||||
<vs-th> Phone </vs-th>
|
<vs-th> Phone </vs-th>
|
||||||
<vs-th> 期限(月)</vs-th>
|
<vs-th> 期限(月)</vs-th>
|
||||||
<vs-th> 验证码 </vs-th>
|
<vs-th> 验证码 </vs-th>
|
||||||
<vs-th> 状态 </vs-th>
|
<vs-th> 状态 </vs-th>
|
||||||
|
<vs-th> 说明 </vs-th>
|
||||||
<vs-th> 过期时间 </vs-th>
|
<vs-th> 过期时间 </vs-th>
|
||||||
<vs-th> 自动续期 </vs-th>
|
<vs-th> 自动续期 </vs-th>
|
||||||
<vs-th> 操作 </vs-th>
|
<vs-th> 操作 </vs-th>
|
||||||
@ -447,6 +480,9 @@
|
|||||||
|
|
||||||
<template slot-scope="{data}">
|
<template slot-scope="{data}">
|
||||||
<vs-tr :key="indextr" v-for="(tr, indextr) in data">
|
<vs-tr :key="indextr" v-for="(tr, indextr) in data">
|
||||||
|
<vs-td :data="data[indextr].platformName">
|
||||||
|
{{data[indextr].platformName}}
|
||||||
|
</vs-td>
|
||||||
<vs-td :data="data[indextr].service">
|
<vs-td :data="data[indextr].service">
|
||||||
{{data[indextr].service}}
|
{{data[indextr].service}}
|
||||||
</vs-td>
|
</vs-td>
|
||||||
@ -461,12 +497,31 @@
|
|||||||
{{data[indextr].code}}
|
{{data[indextr].code}}
|
||||||
</vs-td>
|
</vs-td>
|
||||||
<vs-td :data="data[indextr].status">
|
<vs-td :data="data[indextr].status">
|
||||||
|
<!-- 唤醒倒计时:当前时间小于startTime时显示 -->
|
||||||
|
<vs-chip v-if="data[indextr].status===1&&data[indextr].startTime && new Date() < new Date(data[indextr].startTime)" transparent color="info">
|
||||||
|
唤醒中
|
||||||
|
<countdown :time="new Date(data[indextr].startTime).getTime() - new Date().getTime()" v-slot="timeObj">
|
||||||
|
{{ timeObj.minutes.toString().padStart(2, '0') }}:{{ timeObj.seconds.toString().padStart(2, '0') }}
|
||||||
|
</countdown>
|
||||||
|
</vs-chip>
|
||||||
|
<!-- 接码中倒计时:当前时间在startTime和endTime之间时显示 -->
|
||||||
|
<vs-chip v-else-if="data[indextr].status===1&&data[indextr].startTime && data[indextr].endTime && new Date() >= new Date(data[indextr].startTime) && new Date() < new Date(data[indextr].endTime)" transparent color="warning">
|
||||||
|
接码中
|
||||||
|
<countdown :time="new Date(data[indextr].endTime).getTime() - new Date().getTime()" v-slot="timeObj">
|
||||||
|
{{ timeObj.minutes.toString().padStart(2, '0') }}:{{ timeObj.seconds.toString().padStart(2, '0') }}
|
||||||
|
</countdown>
|
||||||
|
</vs-chip>
|
||||||
|
<!-- 原有状态显示 -->
|
||||||
|
<div v-else>
|
||||||
<vs-chip v-if="data[indextr].status===0" transparent color="primary">未唤醒</vs-chip>
|
<vs-chip v-if="data[indextr].status===0" transparent color="primary">未唤醒</vs-chip>
|
||||||
<vs-chip v-else-if="data[indextr].status===1" transparent color="primary">等待中</vs-chip>
|
<vs-chip v-else-if="data[indextr].status===1" transparent color="primary">等待中</vs-chip>
|
||||||
<vs-chip v-else-if="data[indextr].status===2" transparent color="success">已使用</vs-chip>
|
<vs-chip v-else-if="data[indextr].status===2" transparent color="success">已使用</vs-chip>
|
||||||
<vs-chip v-else-if="data[indextr].status===3" transparent color="warning">过期</vs-chip>
|
<vs-chip v-else-if="data[indextr].status===3" transparent color="warning">过期</vs-chip>
|
||||||
|
</div>
|
||||||
|
</vs-td>
|
||||||
|
<vs-td :data="data[indextr].remark">
|
||||||
|
{{data[indextr].remark}}
|
||||||
</vs-td>
|
</vs-td>
|
||||||
|
|
||||||
<vs-td :data="data[indextr].expireTime">
|
<vs-td :data="data[indextr].expireTime">
|
||||||
{{formatDate(data[indextr].expireTime)}}
|
{{formatDate(data[indextr].expireTime)}}
|
||||||
</vs-td>
|
</vs-td>
|
||||||
@ -497,7 +552,49 @@
|
|||||||
:page-size="smsQuery.pageSize"
|
:page-size="smsQuery.pageSize"
|
||||||
@change="getSmsList"
|
@change="getSmsList"
|
||||||
></vs-pagination>
|
></vs-pagination>
|
||||||
|
</vs-row>
|
||||||
|
|
||||||
|
<!--API管理-->
|
||||||
|
<vs-row v-else-if="activeMenu===5" class="content-conter-container">
|
||||||
|
<div class="api-management">
|
||||||
|
<div class="api-section">
|
||||||
|
<h3>API密钥管理</h3>
|
||||||
|
<div class="api-key-container">
|
||||||
|
<div class="api-key-item">
|
||||||
|
<label>API Key:</label>
|
||||||
|
<div class="api-key-display">
|
||||||
|
<vs-input
|
||||||
|
:type="showApiKey ? 'text' : 'password'"
|
||||||
|
:value="apiKey"
|
||||||
|
readonly
|
||||||
|
placeholder="暂无API Key"
|
||||||
|
></vs-input>
|
||||||
|
<vs-button
|
||||||
|
icon="visibility"
|
||||||
|
type="flat"
|
||||||
|
size="small"
|
||||||
|
@click="toggleApiKeyVisibility"
|
||||||
|
>
|
||||||
|
{{ showApiKey ? '隐藏' : '显示' }}
|
||||||
|
</vs-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="api-status-item">
|
||||||
|
<label>API状态:</label>
|
||||||
|
<div class="api-status-display">
|
||||||
|
<vs-switch
|
||||||
|
v-model="apiStatus"
|
||||||
|
@input="handleApiStatusChange"
|
||||||
|
/>
|
||||||
|
<span class="status-text">
|
||||||
|
{{ apiStatus ? '开启' : '关闭' }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</vs-row>
|
</vs-row>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@ -700,6 +797,20 @@
|
|||||||
<!--获取号码-->
|
<!--获取号码-->
|
||||||
<vs-popup title="租赁号码" :active.sync="showGetSms" :loading="loading">
|
<vs-popup title="租赁号码" :active.sync="showGetSms" :loading="loading">
|
||||||
<div>
|
<div>
|
||||||
|
<vs-select
|
||||||
|
autocomplete
|
||||||
|
v-model="smsForm.platform"
|
||||||
|
autocomplete
|
||||||
|
class="selectExample"
|
||||||
|
placeholder="请选择平台"
|
||||||
|
label="平台"
|
||||||
|
@change="handlePlatformChange">
|
||||||
|
<vs-select-item
|
||||||
|
v-for="item in smsPlatformList"
|
||||||
|
:key="'form_platform'+item.value"
|
||||||
|
:value="item.value"
|
||||||
|
:text="item.label"></vs-select-item>
|
||||||
|
</vs-select>
|
||||||
<vs-select
|
<vs-select
|
||||||
autocomplete
|
autocomplete
|
||||||
v-model="smsForm.serviceCode"
|
v-model="smsForm.serviceCode"
|
||||||
@ -707,7 +818,7 @@
|
|||||||
class="selectExample"
|
class="selectExample"
|
||||||
placeholder="请选择服务"
|
placeholder="请选择服务"
|
||||||
label="服务"
|
label="服务"
|
||||||
>
|
@change="handleSmsServiceChange">
|
||||||
<vs-select-item
|
<vs-select-item
|
||||||
v-for="item in smsServices"
|
v-for="item in smsServices"
|
||||||
:key="'form_service'+item.code"
|
:key="'form_service'+item.code"
|
||||||
@ -720,10 +831,10 @@
|
|||||||
<vs-input class="inputx" placeholder="租赁月份" label="租赁月份" v-model="smsForm.period"/>
|
<vs-input class="inputx" placeholder="租赁月份" label="租赁月份" v-model="smsForm.period"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-item" style="text-align: right;">
|
<div class="form-item" style="text-align: right;">
|
||||||
价格U: {{ this.smsForm.type===1&&this.smsForm.period>0? this.smsPrice*this.smsForm.period :this.smsPrice}}
|
价格U: {{ totalSmsPrice}}
|
||||||
</div>
|
</div>
|
||||||
<div class="form-item" style="text-align: right">
|
<div class="form-item" v-if="totalSmsPrice>0" style="text-align: right">
|
||||||
<vs-button size="small" @click="getNumber"
|
<vs-button size="small" @click="getNumber" v-if="smsPrice"
|
||||||
>确认租赁</vs-button>
|
>确认租赁</vs-button>
|
||||||
</div>
|
</div>
|
||||||
</vs-popup>
|
</vs-popup>
|
||||||
@ -786,15 +897,23 @@
|
|||||||
pageSize:10,
|
pageSize:10,
|
||||||
total:0,
|
total:0,
|
||||||
serviceCode:"",
|
serviceCode:"",
|
||||||
|
platform:"",
|
||||||
},
|
},
|
||||||
//短信列表
|
//短信列表
|
||||||
smsList:[],
|
smsList:[],
|
||||||
showGetSms:false,
|
showGetSms:false,
|
||||||
smsForm:{},
|
smsForm:{},
|
||||||
|
smsPlatformList:[],
|
||||||
checkSmsCodeTimer:null,
|
checkSmsCodeTimer:null,
|
||||||
|
longSmsStatusTimer:null,
|
||||||
smsPrice:undefined,
|
smsPrice:undefined,
|
||||||
//Ip单价
|
//Ip单价
|
||||||
price:undefined,
|
price:undefined,
|
||||||
|
//API管理相关
|
||||||
|
apiId:undefined,
|
||||||
|
apiKey: '',
|
||||||
|
showApiKey: false,
|
||||||
|
apiStatus: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -815,10 +934,22 @@
|
|||||||
this.getMyProxy();
|
this.getMyProxy();
|
||||||
this.getTraffictList();
|
this.getTraffictList();
|
||||||
this.getTrafficServer();
|
this.getTrafficServer();
|
||||||
this.getSmsServices();
|
// this.getSmsServices();
|
||||||
|
this.getSmsPlatformList();
|
||||||
|
|
||||||
//定时器
|
//定时器
|
||||||
this.createCheckSmsCodeTimer();
|
this.createCheckSmsCodeTimer();
|
||||||
|
this.createLongSmsStatusTimer();
|
||||||
|
},
|
||||||
|
computed:{
|
||||||
|
totalSmsPrice(){
|
||||||
|
// 使用 parseFloat() 将值转换为浮点数,如果无法转换则默认为 0
|
||||||
|
const period = parseFloat(this.smsForm.period) || 1;
|
||||||
|
const price = parseFloat(this.smsPrice) || 0;
|
||||||
|
|
||||||
|
// 确保在执行乘法或 toFixed() 前,price 和 period 都是数字
|
||||||
|
return period > 0 ? (price * period).toFixed(2) : price.toFixed(2);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
showGetProxy(val, oldVal) {
|
showGetProxy(val, oldVal) {
|
||||||
@ -858,7 +989,7 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getSmsServices(){
|
getSmsServices(platform){
|
||||||
fetch(requestApi + "/sms-services/list", {
|
fetch(requestApi + "/sms-services/list", {
|
||||||
headers:{
|
headers:{
|
||||||
Authorization: `Bearer ${this.token}`,
|
Authorization: `Bearer ${this.token}`,
|
||||||
@ -868,9 +999,10 @@
|
|||||||
})
|
})
|
||||||
.then((res) => res.json())
|
.then((res) => res.json())
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
console.log('getSmsServices',response);
|
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
this.smsServices = response.data;
|
let datas= response.data.filter(x=>x.platformCode===platform)
|
||||||
|
console.log("getSmsServices:",datas)
|
||||||
|
this.smsServices = datas?datas:[];
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
@ -1265,8 +1397,9 @@
|
|||||||
this.smsForm.type=0;
|
this.smsForm.type=0;
|
||||||
this.smsForm.serviceCode="";
|
this.smsForm.serviceCode="";
|
||||||
this.smsForm.period=undefined;
|
this.smsForm.period=undefined;
|
||||||
|
this.smsForm.platform="";
|
||||||
this.reloadSmsList();
|
this.reloadSmsList();
|
||||||
this.handleGetPrice(this.smsForm.type);
|
// this.handleGetPrice(this.smsForm.type);
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
this.smsQuery.page=1;
|
this.smsQuery.page=1;
|
||||||
@ -1274,8 +1407,12 @@
|
|||||||
this.smsForm.type=1;
|
this.smsForm.type=1;
|
||||||
this.smsForm.serviceCode="";
|
this.smsForm.serviceCode="";
|
||||||
this.smsForm.period=undefined;
|
this.smsForm.period=undefined;
|
||||||
|
this.smsForm.platform="";
|
||||||
this.reloadSmsList();
|
this.reloadSmsList();
|
||||||
this.handleGetPrice(this.smsForm.type);
|
// this.handleGetPrice(this.smsForm.type);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
this.getApiKey();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1631,10 +1768,17 @@
|
|||||||
},
|
},
|
||||||
//sms service切换
|
//sms service切换
|
||||||
handleSmsServiceChange(item){
|
handleSmsServiceChange(item){
|
||||||
this.smsQuery.serviceCode=item.code;
|
let service=this.smsServices.find(x=>x.code===item);
|
||||||
|
|
||||||
|
if(service&&this.smsForm.type===1){
|
||||||
|
this.smsPrice=service.longPrice;
|
||||||
|
}else if(service&&this.smsForm.type===0){
|
||||||
|
this.smsPrice=service.price;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
//重置sms列表
|
//重置sms列表
|
||||||
handleResetSmsList(){
|
handleResetSmsList(){
|
||||||
|
this.smsQuery.platform="";
|
||||||
this.smsQuery.serviceCode="";
|
this.smsQuery.serviceCode="";
|
||||||
this.smsQuery.page=1;
|
this.smsQuery.page=1;
|
||||||
|
|
||||||
@ -1658,6 +1802,7 @@
|
|||||||
type:type,
|
type:type,
|
||||||
pageIndex: this.smsQuery.page,
|
pageIndex: this.smsQuery.page,
|
||||||
pageSize: this.smsQuery.pageSize,
|
pageSize: this.smsQuery.pageSize,
|
||||||
|
platformCode:this.smsQuery.platform,
|
||||||
serviceCode: this.smsQuery.serviceCode,
|
serviceCode: this.smsQuery.serviceCode,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1691,6 +1836,7 @@
|
|||||||
handleShowGetSms(){
|
handleShowGetSms(){
|
||||||
this.smsForm.period=undefined;
|
this.smsForm.period=undefined;
|
||||||
this.smsForm.serviceCode="";
|
this.smsForm.serviceCode="";
|
||||||
|
this.smsForm.platform="";
|
||||||
this.showGetSms = true;
|
this.showGetSms = true;
|
||||||
},
|
},
|
||||||
resetSmsForm(){
|
resetSmsForm(){
|
||||||
@ -1700,6 +1846,7 @@
|
|||||||
type = 1;
|
type = 1;
|
||||||
}
|
}
|
||||||
this.smsForm={
|
this.smsForm={
|
||||||
|
platform: "",
|
||||||
serviceCode: "",
|
serviceCode: "",
|
||||||
period:undefined,
|
period:undefined,
|
||||||
type:type,
|
type:type,
|
||||||
@ -1728,6 +1875,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
let data = JSON.stringify({
|
let data = JSON.stringify({
|
||||||
|
platformCode: this.smsForm.platform,
|
||||||
serviceCode: this.smsForm.serviceCode,
|
serviceCode: this.smsForm.serviceCode,
|
||||||
type: this.smsForm.type,
|
type: this.smsForm.type,
|
||||||
period: Number(this.smsForm.period),
|
period: Number(this.smsForm.period),
|
||||||
@ -1802,14 +1950,14 @@
|
|||||||
codesMap.set(item.activationId, item);
|
codesMap.set(item.activationId, item);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(codesMap);
|
|
||||||
|
|
||||||
this.smsList.forEach(item => {
|
this.smsList.forEach(item => {
|
||||||
const newItem = codesMap.get(item.activationId); // 尝试从 Map 中获取新 code
|
const newItem = codesMap.get(item.activationId); // 尝试从 Map 中获取新 code
|
||||||
|
|
||||||
if (newItem!==undefined&&newItem!==null&&newItem.status===2) { // 如果找到了匹配的 activationId
|
if (newItem!==undefined&&newItem!==null&&newItem.status===2) { // 如果找到了匹配的 activationId
|
||||||
item.code = newItem.code; // 替换 code
|
item.code = newItem.code; // 替换 code
|
||||||
item.status = newItem.status; // 修改 status 为 2
|
item.status = newItem.status; // 修改 status 为 2
|
||||||
|
}else if (newItem!==undefined&&newItem!==null&&newItem.status===3){
|
||||||
|
item.status=newItem.status
|
||||||
}})
|
}})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -1930,8 +2078,9 @@
|
|||||||
this.hiddenLoading();
|
this.hiddenLoading();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleGetPrice(type){
|
handleGetPrice(type,platformCode,servicesCode){
|
||||||
fetch(requestApi + "/sms-services/price?type=" + type, {
|
if (type&&platformCode&&servicesCode) {
|
||||||
|
fetch(`${requestApi}/sms-services/price?type=${type}&platformCode=${platformCode}&serviceCode=${servicesCode}`, {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${this.token}`,
|
Authorization: `Bearer ${this.token}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@ -1947,6 +2096,7 @@
|
|||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
//取消sms
|
//取消sms
|
||||||
handleCancelSms(row){
|
handleCancelSms(row){
|
||||||
@ -2244,156 +2394,182 @@
|
|||||||
this.hiddenLoading();
|
this.hiddenLoading();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
getSmsPlatformList(){
|
||||||
|
fetch(requestApi + "/sms-services/platform", {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.token}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((response) => {
|
||||||
|
console.log(response);
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.smsPlatformList = response.data;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handlePlatformChange(item){
|
||||||
|
console.log("handlePlatformChange:",item);
|
||||||
|
this.smsQuery.serviceCode="";
|
||||||
|
this.smsForm.serviceCode="";
|
||||||
|
|
||||||
|
this.getSmsServices(item);
|
||||||
|
},
|
||||||
|
handleFormServiceChange(serviceCode){
|
||||||
|
this.handleGetPrice(this.smsForm.type,this.smsForm.platformCode,serviceCode);
|
||||||
|
},
|
||||||
|
// API管理相关方法
|
||||||
|
getApiKey() {
|
||||||
|
console.log("",requestApi+"/api-info");
|
||||||
|
fetch(requestApi + "/api-info", {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.token}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((response) => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.apiId = response.data.id
|
||||||
|
this.apiKey = response.data.api || '';
|
||||||
|
this.apiStatus = response.data.status === 1;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
toggleApiKeyVisibility() {
|
||||||
|
this.showApiKey = !this.showApiKey;
|
||||||
|
},
|
||||||
|
handleApiStatusChange(status) {
|
||||||
|
this.showLoading();
|
||||||
|
const data = JSON.stringify({
|
||||||
|
id:this.apiId,
|
||||||
|
status: status ? 1 : 2
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch(requestApi + "/api-info", {
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.token}`,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
Accept: "application/json",
|
||||||
|
},
|
||||||
|
body: data,
|
||||||
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((response) => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.$vs.notify({
|
||||||
|
title: "提示",
|
||||||
|
color: "success",
|
||||||
|
text: `API已${status ? '开启' : '关闭'}`,
|
||||||
|
position: "top-right",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// 如果请求失败,恢复原状态
|
||||||
|
this.apiStatus = !status;
|
||||||
|
this.$vs.notify({
|
||||||
|
title: "提示",
|
||||||
|
color: "danger",
|
||||||
|
text: response.msg || "操作失败",
|
||||||
|
position: "top-right",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
// 如果请求失败,恢复原状态
|
||||||
|
this.apiStatus = !status;
|
||||||
|
console.log(error);
|
||||||
|
this.$vs.notify({
|
||||||
|
title: "提示",
|
||||||
|
color: "danger",
|
||||||
|
text: "网络错误,请稍后重试",
|
||||||
|
position: "top-right",
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.hiddenLoading();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 创建长效号码状态检查定时器
|
||||||
|
* 用于定期检查和更新长效号码的倒计时状态
|
||||||
|
*/
|
||||||
|
createLongSmsStatusTimer() {
|
||||||
|
if (this.longSmsStatusTimer) {
|
||||||
|
clearInterval(this.longSmsStatusTimer);
|
||||||
|
}
|
||||||
|
// 每秒检查一次状态更新
|
||||||
|
this.longSmsStatusTimer = setInterval(() => {
|
||||||
|
this.updateLongSmsStatus();
|
||||||
|
}, 1000);
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 清理长效号码状态检查定时器
|
||||||
|
*/
|
||||||
|
cleanLongSmsStatusTimer() {
|
||||||
|
if (this.longSmsStatusTimer) {
|
||||||
|
clearInterval(this.longSmsStatusTimer);
|
||||||
|
this.longSmsStatusTimer = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 更新长效号码状态
|
||||||
|
* 检查倒计时是否结束,并触发相应的状态更新
|
||||||
|
*/
|
||||||
|
updateLongSmsStatus() {
|
||||||
|
if (this.activeMenu !== 4 || !this.smsList.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
let needRefresh = false;
|
||||||
|
|
||||||
|
this.smsList.forEach(item => {
|
||||||
|
// 检查唤醒倒计时是否结束
|
||||||
|
if (item.startTime && now >= new Date(item.startTime) &&
|
||||||
|
item.endTime && now < new Date(item.endTime)) {
|
||||||
|
// 唤醒倒计时结束,进入接码中状态
|
||||||
|
if (!item._inReceivingState) {
|
||||||
|
item._inReceivingState = true;
|
||||||
|
needRefresh = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查接码中倒计时是否结束
|
||||||
|
if (item.endTime && now >= new Date(item.endTime)) {
|
||||||
|
// 接码中倒计时结束,恢复原有逻辑
|
||||||
|
if (item._inReceivingState) {
|
||||||
|
item._inReceivingState = false;
|
||||||
|
needRefresh = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 如果有状态变化,强制更新视图
|
||||||
|
if (needRefresh) {
|
||||||
|
this.$forceUpdate();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
// 清理定时器,防止内存泄漏
|
||||||
|
this.cleanLongSmsStatusTimer();
|
||||||
|
if (this.checkSmsCodeTimer) {
|
||||||
|
clearInterval(this.checkSmsCodeTimer);
|
||||||
|
}
|
||||||
|
if (this.checkOrderTimer) {
|
||||||
|
clearInterval(this.checkOrderTimer);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style>
|
|
||||||
html,
|
|
||||||
body,
|
|
||||||
#app {
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
font-family: DMSans-Regular;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
height: 60px;
|
|
||||||
background-color: #fff;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
padding: 0 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.parentx-static {
|
|
||||||
overflow: hidden;
|
|
||||||
height: 500px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 20px;
|
|
||||||
padding: 15px 0px 15px 15px;
|
|
||||||
height: 100%;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-area {
|
|
||||||
display: flex;
|
|
||||||
height: calc(100vh - 60px); /* 减去 header 高度 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
width: 200px;
|
|
||||||
background-color: #ffffff;
|
|
||||||
border-right: 1px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .vs-content-sidebar .vs-sidebar {
|
|
||||||
background-color: unset !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
|
||||||
flex: 1;
|
|
||||||
padding: 8px;
|
|
||||||
overflow: auto;
|
|
||||||
background: #eeeeee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-conter {
|
|
||||||
background-color: white;
|
|
||||||
padding: 16px;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* .user-dropdown{
|
|
||||||
color: #000;
|
|
||||||
} */
|
|
||||||
.dropdown-menu {
|
|
||||||
width: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tablex {
|
|
||||||
width: 100%;
|
|
||||||
padding-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-content {
|
|
||||||
padding-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.popup-bottom {
|
|
||||||
text-align: right;
|
|
||||||
padding-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.qr-code {
|
|
||||||
height: 155px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.success-contianer {
|
|
||||||
height: 100%;
|
|
||||||
line-height: 155px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.success-contianer img {
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-conter-header {
|
|
||||||
display: flex;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* .content-conter-header > *:not(:first-child) {
|
|
||||||
margin-left: 10px;
|
|
||||||
} */
|
|
||||||
|
|
||||||
.balance-btn[data-v-d585ebde] {
|
|
||||||
padding: 0 10px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
max-width: max-content;
|
|
||||||
height: 30px;
|
|
||||||
line-height: 30px;
|
|
||||||
background: #ff916f33;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 14px;
|
|
||||||
color: #ff916f;
|
|
||||||
margin-right: 28px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.table-cell-center {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-group {
|
|
||||||
display: flex;
|
|
||||||
gap: 10px;
|
|
||||||
place-items: end;
|
|
||||||
padding-left: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.operat-btn{
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-item{
|
|
||||||
padding-top: 10px
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-conter-container{
|
|
||||||
height: calc(100% - 45px);
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content-conter-footer{
|
|
||||||
height: 45px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
41
index.html
41
index.html
@ -1446,51 +1446,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer_right">
|
<div class="footer_right">
|
||||||
<!-- <div>
|
|
||||||
<h2>Solutions</h2>
|
|
||||||
<a href="download.html">Download</a>
|
|
||||||
<a href="socks5-ip.html">ISP S5</a>
|
|
||||||
<a href="enterprise-socks5-ip.html">Enterprise ISP S5</a>
|
|
||||||
<a href="iso-code.html">ISO Code</a>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h2>Pricing</h2>
|
|
||||||
<a href="isp-socks5.html">Residential (socks5) proxies</a>
|
|
||||||
<a href="residential-proxies.html"
|
|
||||||
>Residential proxies - Traffic Plan</a
|
|
||||||
>
|
|
||||||
<a href="static-isp.html">Static ISP - Long time</a>
|
|
||||||
<a href="unlimit-proxies.html">Unlimited residential proxies</a>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h2>Proxy Services</h2>
|
|
||||||
<a href="terms-service.html">Terms of Service</a>
|
|
||||||
<a href="privacy-policy.html">Privacy Policy</a>
|
|
||||||
<a href="refund-policy.html">Refund Policy</a>
|
|
||||||
<a href="anti-fraud.html">Anti-Money Laundering Policy</a>
|
|
||||||
</div> -->
|
|
||||||
<!-- <div>
|
|
||||||
<h2>Use Cases</h2>
|
|
||||||
<a href="price-monitoring.html">Price Monitoring</a>
|
|
||||||
<a href="advertising-verificat.html">Advertising Verificat</a>
|
|
||||||
<a href="brand-protection.html">Brand Protection</a>
|
|
||||||
<a href="market-research.html">Market Research</a>
|
|
||||||
<a href="travel-fare-summary.html">Travel Fare Summary</a>
|
|
||||||
<a href="serp-seo-proxies.html">SERP&SEO</a>
|
|
||||||
</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</footer>
|
</footer>
|
||||||
<!-- <script>
|
|
||||||
var _hmt = _hmt || [];
|
|
||||||
(function() {
|
|
||||||
var hm = document.createElement("script");
|
|
||||||
hm.src = "https://hm.baidu.com/hm.js?c4dddce310908c98ca8617f0056e59e9";
|
|
||||||
var s = document.getElementsByTagName("script")[0];
|
|
||||||
s.parentNode.insertBefore(hm, s);
|
|
||||||
})();
|
|
||||||
</script> -->
|
|
||||||
|
|
||||||
<script data-cfasync="false" src="static/js/email-decode.min.js"></script>
|
<script data-cfasync="false" src="static/js/email-decode.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
203
static/css/cli-traffic.css
Normal file
203
static/css/cli-traffic.css
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
/* CLI Traffic 页面样式 */
|
||||||
|
html,
|
||||||
|
body,
|
||||||
|
#app {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
font-family: DMSans-Regular;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
height: 60px;
|
||||||
|
background-color: #fff;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.parentx-static {
|
||||||
|
overflow: hidden;
|
||||||
|
height: 500px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 20px;
|
||||||
|
padding: 15px 0px 15px 15px;
|
||||||
|
height: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-area {
|
||||||
|
display: flex;
|
||||||
|
height: calc(100vh - 60px); /* 减去 header 高度 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
width: 200px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-right: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar .vs-content-sidebar .vs-sidebar {
|
||||||
|
background-color: unset !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
flex: 1;
|
||||||
|
padding: 8px;
|
||||||
|
overflow: auto;
|
||||||
|
background: #eeeeee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-conter {
|
||||||
|
background-color: white;
|
||||||
|
padding: 16px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .user-dropdown{
|
||||||
|
color: #000;
|
||||||
|
} */
|
||||||
|
.dropdown-menu {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tablex {
|
||||||
|
width: 100%;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-content {
|
||||||
|
padding-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-bottom {
|
||||||
|
text-align: right;
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.qr-code {
|
||||||
|
height: 155px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success-contianer {
|
||||||
|
height: 100%;
|
||||||
|
line-height: 155px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success-contianer img {
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-conter-header {
|
||||||
|
display: flex;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .content-conter-header > *:not(:first-child) {
|
||||||
|
margin-left: 10px;
|
||||||
|
} */
|
||||||
|
|
||||||
|
.balance-btn[data-v-d585ebde] {
|
||||||
|
padding: 0 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
max-width: max-content;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
background: #ff916f33;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #ff916f;
|
||||||
|
margin-right: 28px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-cell-center {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
place-items: end;
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.operat-btn {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item {
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-conter-container {
|
||||||
|
height: calc(100% - 45px);
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-conter-footer {
|
||||||
|
height: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* API管理样式 */
|
||||||
|
.api-management {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-section h3 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #333;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-key-container {
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #e9ecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-key-item, .api-status-item {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-key-item:last-child, .api-status-item:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-key-item label, .api-status-item label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #495057;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-key-display {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-key-display .vs-input {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-status-display {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-text {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #495057;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user