1、收码

This commit is contained in:
2025-07-24 23:34:35 +08:00
parent e046782e8e
commit 6f5a682c19

View File

@ -78,35 +78,51 @@
<!-- 左侧菜单 -->
<div class="sidebar">
<vs-sidebar
static-position
:hidden-background="true"
default-index="2"
color="primary"
spacer
v-model="active"
>
<vs-sidebar-item
index="1"
@click="handleActiveMenu(1)"
icon="settings"
>长效IP</vs-sidebar-item
static-position
:hidden-background="true"
default-index="2"
color="primary"
spacer
v-model="active"
>
<vs-sidebar-item
index="2"
@click="handleActiveMenu(2)"
icon="dashboard"
>
账密模式
</vs-sidebar-item>
<!--
<vs-sidebar-item index="3" icon="people">用户管理</vs-sidebar-item> -->
</vs-sidebar>
<vs-sidebar-group open title="代理管理">
<vs-sidebar-item
index="1"
@click="handleActiveMenu(1)"
icon="settings"
>长效IP</vs-sidebar-item
>
<vs-sidebar-item
index="2"
@click="handleActiveMenu(2)"
icon="dashboard"
>
账密模式
</vs-sidebar-item>
</vs-sidebar-group>
<vs-sidebar-group open title="号码管理">
<vs-sidebar-item
index="3"
@click="handleActiveMenu(3)"
icon="settings"
>短效号码</vs-sidebar-item
>
<vs-sidebar-item
index="4"
@click="handleActiveMenu(4)"
icon="dashboard"
>
长效号码
</vs-sidebar-item>
</vs-sidebar-group>
</div>
<!-- 内容展示区 -->
<div class="content">
<div class="content-conter">
<div class="content-conter-header">
<div class="content-conter-header" v-if="activeMenu === 1||activeMenu===2">
<vs-select
autocomplete
v-model="query.area"
@ -169,6 +185,48 @@
</div>
</div>
<div class="content-conter-header" v-if="activeMenu === 3||activeMenu===4">
<vs-select
autocomplete
v-model="smsQuery.serviceCode"
autocomplete
class="selectExample"
placeholder="服务"
label="服务"
>
<vs-select-item
v-for="item in smsServices"
:key="'sms_service_'+item.code"
:value="item.code"
:text="item.name"
@click="handleSmsServiceChange(item)"
></vs-select-item>
</vs-select>
<div class="btn-group">
<vs-button color="primary" size="small" @click="reloadSmsList"
>查询</vs-button
>
<vs-button
color="primary"
type="border"
size="small"
@click="handleResetSmsList"
>
重置
</vs-button>
<vs-button
color="primary"
type="border"
size="small"
@click="handleShowGetSms"
>租赁号码</vs-button
>
</div>
</div>
<vs-row v-if="activeMenu === 2">
<vs-table class="tablex" :data="proxys">
<template slot="thead">
@ -231,7 +289,7 @@
icon="qr_code"
@click="handleShowQrCode(data[indextr],2)"
></vs-button>
<vs-button
<!-- <vs-button
style="margin-left: 10px"
class="operat-btn"
v-if="data[indextr].status === 1"
@ -239,7 +297,7 @@
color="primary"
@click="handleResetGenerateProxy(data[indextr])"
>重置</vs-button
>
> -->
<vs-button v-if="data[indextr].status === 1"
color="rgb(187, 138, 200)"
class="operat-btn"
@ -258,7 +316,7 @@
/>
</vs-row>
<vs-row v-else>
<vs-row v-else-if="activeMenu===1">
<vs-table class="tablex" :data="proxys">
<template slot="thead">
<vs-th> 国家/地区 </vs-th>
@ -326,59 +384,121 @@
@change="getMyProxy"
/>
</vs-row>
</div>
<!-- <div v-else-if="activeMenu===1" class="content-conter">
<div class="content-conter-header">
<vs-select
v-model="query.area"
autocomplete
class="selectExample"
placeholder="area"
label="国家/地区"
>
<vs-select-item
v-for="item in traffictList"
:key="'area'+item.code"
:value="item.code"
:text="item.name"
@click="handleAreaChange(item)"
></vs-select-item>
</vs-select>
<vs-select
v-model="query.state"
class="selectExample"
label="城市"
placeholder="city"
>
<vs-select-item
v-for="(item,index) in cityList"
:key="'city'+index"
:value="item.state"
:text="item.state"
></vs-select-item>
</vs-select>
<vs-button color="primary" size="small" @click="getMyProxy"
>查询</vs-button
>
<vs-button
color="primary"
type="border"
size="small"
@click="handleGetProxy"
>获取代理</vs-button
>
<vs-button
color="warning"
type="border"
size="small"
@click="handleRecharge"
>
余额充值
</vs-button>
</div>
</div> -->
<!--短效号码-->
<vs-row v-else-if="activeMenu===3">
<vs-table class="tablex" :data="smsList">
<template slot="thead">
<vs-th> 服务 </vs-th>
<vs-th> Phone </vs-th>
<vs-th> 验证码 </vs-th>
<vs-th> 状态 </vs-th>
<vs-th> 操作 </vs-th>
</template>
<template slot-scope="{data}">
<vs-tr :key="indextr" v-for="(tr, indextr) in data">
<vs-td :data="data[indextr].service">
{{data[indextr].service}}
</vs-td>
<vs-td :data="data[indextr].phone">
{{data[indextr].phone}}
</vs-td>
<vs-td :data="data[indextr].code">
{{data[indextr].code}}
</vs-td>
<vs-td :data="data[indextr].status">
<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===2" transparent color="success">已使用</vs-chip>
<vs-chip v-else-if="data[indextr].status===3" transparent color="warning">过期</vs-chip>
</vs-td>
<vs-td :data="data[indextr].id">
<!-- <vs-button
v-if="data[indextr].status === 1||(data[indextr].type===1&&new Date().getTime()<data[indextr].expireUnix)"
color="success"
type="flat"
size="small"
icon="qr_code"
@click="handleShowQrCode(data[indextr],1)"
></vs-button> -->
<vs-button color="warning" size="small" @click="handleDeleteSms(data[indextr])">
删除
</vs-button>
</vs-tr>
</template>
</vs-table>
<vs-pagination
v-model:current-page="smsQuery.page"
:total="smsQuery.total"
:page-size="smsQuery.pageSize"
@change="getSmsList"
/>
</vs-row>
<!--长效-->
<vs-row v-else-if="activeMenu===4">
<vs-table class="tablex" :data="smsList">
<template slot="thead">
<vs-th> 服务 </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>
</template>
<template slot-scope="{data}">
<vs-tr :key="indextr" v-for="(tr, indextr) in data">
<vs-td :data="data[indextr].service">
{{data[indextr].service}}
</vs-td>
<vs-td :data="data[indextr].phone">
{{data[indextr].phone}}
</vs-td>
<vs-td :data="data[indextr].period">
{{data[indextr].period}}
</vs-td>
<vs-td :data="data[indextr].code">
{{data[indextr].code}}
</vs-td>
<vs-td :data="data[indextr].status">
<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===2" transparent color="success">已使用</vs-chip>
<vs-chip v-else-if="data[indextr].status===3" transparent color="warning">过期</vs-chip>
</vs-td>
<vs-td :data="data[indextr].expireTime">
{{formatDate(data[indextr].expireTime)}}
</vs-td>
<vs-td :data="data[indextr].id">
<vs-button
v-if="data[indextr].status !== 1&&new Date()<new Date(data[indextr].expireTime)"
color="primary"
size="small"
@click="handleWeakUp(data[indextr],1)"
>唤醒并获取</vs-button>
<vs-button color="warning" size="small" @click="handleDeleteSms(data[indextr])">
删除
</vs-button>
</vs-tr>
</template>
</vs-table>
<vs-pagination
v-model:current-page="smsQuery.page"
:total="smsQuery.total"
:page-size="smsQuery.pageSize"
@change="getSmsList"
/>
</vs-row>
</div>
</div>
</div>
@ -567,7 +687,37 @@
:active.sync="showQrCode"
>
<div id="proxy-qrcode"></div>
<!-- <div style="padding-top: 15px">socks5:{{}}</div> -->
</vs-popup>
<!--获取号码-->
<vs-popup title="租赁号码" :active.sync="showGetSms" :loading="loading">
<div>
<vs-select
autocomplete
v-model="smsForm.serviceCode"
autocomplete
class="selectExample"
placeholder="请选择服务"
label="服务"
>
<vs-select-item
v-for="item in smsServices"
:key="'form_service'+item.code"
:value="item.code"
:text="item.name"
></vs-select-item>
</vs-select>
</div>
<div class="form-item" v-if="smsForm.type===1">
<vs-input class="inputx" placeholder="租赁月份" label="租赁月份" v-model="smsForm.period"/>
</div>
<div class="form-item" style="text-align: right;">
价格U: {{ this.smsForm.type===1&&this.smsForm.period>0? this.smsPrice*this.smsForm.period :this.smsPrice}}
</div>
<div class="form-item" style="text-align: right">
<vs-button size="small" @click="getNumber"
>确认租赁</vs-button>
</div>
</vs-popup>
</div>
</body>
@ -619,6 +769,21 @@
trafficServer: [],
//可提取ip列表
useList: [],
//短信服务列表
smsServices:[],
//短信query
smsQuery:{
page:1,
pageSize:50,
total:0,
serviceCode:"",
},
//短信列表
smsList:[],
showGetSms:false,
smsForm:{},
checkSmsCodeTimer:null,
smsPrice:undefined
};
},
mounted() {
@ -634,9 +799,15 @@
}
}
this.resetSmsForm();
this.getMyProxy();
this.getTraffictList();
this.getTrafficServer();
this.getSmsServices();
//定时器
this.createCheckSmsCodeTimer();
},
watch: {
showGetProxy(val, oldVal) {
@ -676,6 +847,25 @@
},
},
methods: {
getSmsServices(){
fetch(requestApi + "/sms-services/list", {
headers:{
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/json",
Accept: "application/json",
}
})
.then((res) => res.json())
.then((response) => {
console.log('getSmsServices',response);
if (response.code === 200) {
this.smsServices = response.data;
}
})
.catch((error) => {
console.log("获取服务错误:",error);
});
},
showLoading(ref) {
// ref.$el.setAttribute("disabled", true);
this.$vs.loading();
@ -994,7 +1184,27 @@
},
handleActiveMenu(index) {
this.activeMenu = index;
this.reloadList();
console.log('index',index);
switch(index){
case 1:
case 2:
this.reloadList();
break;
case 3:
this.smsForm.type=0;
this.smsForm.serviceCode="";
this.smsForm.period=undefined;
this.reloadSmsList();
this.handleGetPrice(this.smsForm.type);
break;
case 4:
this.smsForm.type=1;
this.smsForm.serviceCode="";
this.smsForm.period=undefined;
this.reloadSmsList();
this.handleGetPrice(this.smsForm.type);
break;
}
},
reloadList() {
this.query.pageIndex = 1;
@ -1029,8 +1239,6 @@
);
this.query.total = total;
console.log("proxys", this.proxys);
}
})
.catch((error) => {
@ -1317,6 +1525,325 @@
this.hiddenLoading();
});
},
//sms service切换
handleSmsServiceChange(item){
this.smsQuery.serviceCode=item.code;
},
//重置sms列表
handleResetSmsList(){
this.smsQuery.serviceCode="";
this.smsQuery.page=1;
this.getSmsList();
},
//查询sms
reloadSmsList(){
this.smsQuery.page=1;
this.getSmsList();
},
//获取sms列表
getSmsList(){
this.showLoading();
let type=0;
if(this.activeMenu===4){
type=1
}
let query = {
type:type,
pageIndex: this.smsQuery.page,
pageSize: this.smsQuery.pageSize,
serviceCode: this.smsQuery.serviceCode,
};
const queryString = new URLSearchParams(query).toString();
fetch(requestApi + "/sms-phone/list?" + queryString, {
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/json",
Accept: "application/json",
}})
.then((res) => res.json())
.then((response) => {
if (response.code === 200) {
console.log(response);
this.smsList = response.data.list;
let total = Math.ceil(
response.data.count / this.smsQuery.pageSize
);
this.smsQuery.total = total;
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
this.hiddenLoading();
});
},
//显示租赁弹框
handleShowGetSms(){
this.smsForm.period=undefined;
this.smsForm.serviceCode="";
this.showGetSms = true;
},
resetSmsForm(){
let type =0;
if (this.activeMenu === 4) {
type = 1;
}
this.smsForm={
serviceCode: "",
period:undefined,
type:type,
}
},
//获取号码
getNumber(){
if(!this.smsForm.serviceCode){
this.$vs.notify({
title: "提示",
color: "danger",
text: "请选择服务",
position: "top-right",
});
return;
}
if (this.smsForm.type===1&& (this.smsForm.period===undefined||this.smsForm.period<=0)){
this.$vs.notify({
title: "提示",
color: "danger",
text: "请填写时间",
position: "top-right",
});
return;
}
let data = JSON.stringify({
serviceCode: this.smsForm.serviceCode,
type: this.smsForm.type,
period: Number(this.smsForm.period),
})
this.showLoading();
fetch(requestApi + "/sms-phone/getNumber", {
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/json",
Accept: "application/json",
},
method: "POST",
body: data,
})
.then((res) => res.json())
.then((response) => {
if (response.code === 200) {
this.$vs.notify({
title: "提示",
color: "success",
text: "获取成功",
position: "top-right",
});
this.showGetSms = false;
this.getSmsList();
this.user.balance=response.data;
} else {
this.$vs.notify({
title: "提示",
color: "danger",
text: response.msg,
position: "top-right",
});
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
this.hiddenLoading();
});
},
//查看接受中的验证码
getCodeByActivationIds(){
if(this.smsList&&this.smsList.length>0){
let activationIds=this.smsList.filter(x=>x.status===1).map(x=>x.activationId)
if(activationIds.length<=0){
return;
}
const params = new URLSearchParams();
activationIds.forEach(id => {
params.append('activationIds', id); // Appends 'activationIds=123', 'activationIds=456', etc.
});
fetch(`${requestApi}/sms-phone/getCodeByActivationId?${params}`, {
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/json",
Accept: "application/json",
},
})
.then((res) => res.json())
.then((response) => {
if (response.code === 200) {
const codesMap = new Map();
response.data.forEach(item => {
codesMap.set(item.activationId, item);
});
console.log(codesMap);
this.smsList.forEach(item => {
const newItem = codesMap.get(item.activationId); // 尝试从 Map 中获取新 code
if (newItem.status !== item.status) { // 如果找到了匹配的 activationId
item.code = newItem.code; // 替换 code
item.status = newItem.status; // 修改 status 为 2
}})
}
})
.catch((error) => {
console.log(error);
});
}
},
//定时检查等待中的验证码
createCheckSmsCodeTimer() {
if (this.checkSmsCodeTimer) {
clearInterval(this.checkSmsCodeTimer);
} else {
this.checkSmsCodeTimer = setInterval(() => {
this.getCodeByActivationIds(this.rechargeData.orderNo);
}, 10000);
}
},
handleWeakUp(row,index){
if(row.status===1){
this.$vs.notify({
title: "提示",
color: "danger",
text: "无需重复唤醒",
position: "top-right",
});
return;
}
this.showLoading();
let data = JSON.stringify({
activationId: row.activationId,
});
fetch(requestApi + "/sms-phone/weakUp", {
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/json",
Accept: "application/json",
},
method: "POST",
body: data,
})
.then((res) => res.json())
.then((response) => {
if (response.code === 200) {
this.$vs.notify({
title: "提示",
color: "success",
text: "唤醒成功",
position: "top-right",
});
this.getSmsList();
} else {
this.$vs.notify({
title: "提示",
color: "danger",
text: response.msg,
position: "top-right",
});
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
this.hiddenLoading();
});
},
handleDeleteSms(row){
this.$vs.dialog({
color:"primary",
title: `提示`,
text: `确定要删除[${row.phone}]`,
acceptText:"确定",
accept:() => this.deleteSms(row)
});
},
deleteSms(row){
this.showLoading();
let data = JSON.stringify({
id:row.id});
fetch(requestApi + "/sms-phone/my-number", {
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/json",
Accept: "application/json",
},
method: "DELETE",
body: data,
})
.then((res) => res.json())
.then((response) => {
if (response.code === 200) {
this.$vs.notify({
title: "提示",
color: "success",
text: "删除成功",
position: "top-right",
});
this.getSmsList();
} else {
this.$vs.notify({
title: "提示",
color: "danger",
text: response.msg,
position: "top-right",
});
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
this.hiddenLoading();
});
},
handleGetPrice(type){
fetch(requestApi + "/sms-services/price?type=" + type, {
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/json",
Accept: "application/json",
}
})
.then((res) => res.json())
.then((response) => {
if (response.code === 200) {
this.smsPrice = response.data;
}
})
.catch((error) => {
console.log(error);
});
},
},
});
</script>
@ -1455,5 +1982,9 @@
.operat-btn{
margin-top: 10px;
}
.form-item{
padding-top: 10px
}
</style>
</html>