1、自动续期

This commit is contained in:
2025-07-28 18:06:46 +08:00
parent cb3857fc52
commit 5078ba1f79
151 changed files with 1454 additions and 50588 deletions

View File

@ -43,13 +43,13 @@
<div class="logo">
<img
style="height: 100%"
src="static/image/logo.png"
src="static/picture/logo.png?v=20250726"
@click="homeClick"
alt=""
/>
</div>
<div style="display: flex; align-items: center; gap: 20px">
<p data-v-d585ebde="" class="balance-btn">
<p data-v-d585ebde="" class="balance-btn" @click="handleRecharge">
余额 $ {{user.balance}}
</p>
<vs-select v-model="language" style="width: 100px">
@ -98,7 +98,7 @@
@click="handleActiveMenu(2)"
icon="dashboard"
>
账密模式
动态IP
</vs-sidebar-item>
</vs-sidebar-group>
<vs-sidebar-group open title="号码管理">
@ -174,14 +174,14 @@
@click="handleGetProxy"
>获取代理</vs-button
>
<vs-button
<!-- <vs-button
color="warning"
type="border"
size="small"
@click="handleRecharge"
>
余额充值
</vs-button>
</vs-button> -->
</div>
</div>
@ -227,22 +227,26 @@
</div>
</div>
<vs-row v-if="activeMenu === 2">
<vs-table class="tablex" :data="proxys">
<vs-row v-if="activeMenu === 2" class="content-conter-container">
<vs-table class="tablex" :data="proxys">
<template slot="thead">
<vs-th> ID</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>
</template>
<template slot-scope="{data}">
<vs-tr :key="indextr" v-for="(tr, indextr) in data">
<vs-td :data="data[indextr].id">
{{data[indextr].id}}
</vs-td>
<vs-td :data="data[indextr].area">
{{data[indextr].area}}
</vs-td>
@ -251,16 +255,6 @@
{{data[indextr].state}}
</vs-td>
<vs-td :data="data[indextr].port">
{{data[indextr].port}}
</vs-td>
<vs-td :data="data[indextr].userName">
{{data[indextr].userName}}
</vs-td>
<vs-td :data="data[indextr].password">
{{data[indextr].password}}
</vs-td>
<vs-td :data="data[indextr].status">
<vs-chip
v-if="data[indextr].status === 1"
@ -276,9 +270,9 @@
<vs-td :data="data[indextr].expired">
{{formatDate(data[indextr].expired)}}
</vs-td>
<vs-td :data="data[indextr].autoRenewal">
<!-- <vs-td :data="data[indextr].autoRenewal">
<vs-switch v-model="data[indextr].autoRenewal" @input="(val) => onSwitchChange(val, data[indextr],indextr)"/>
</vs-td>
</vs-td> -->
<vs-td :data="data[indextr].id">
<vs-button
v-if="data[indextr].status === 1"
@ -289,6 +283,9 @@
icon="qr_code"
@click="handleShowQrCode(data[indextr],2)"
></vs-button>
<vs-button color="warning"class="operat-btn" size="small" @click="handleDeleteProxy(data[indextr])">
删除
</vs-button>
<!-- <vs-button
style="margin-left: 10px"
class="operat-btn"
@ -298,25 +295,26 @@
@click="handleResetGenerateProxy(data[indextr])"
>重置</vs-button
> -->
<vs-button v-if="data[indextr].status === 1"
<!-- <vs-button v-if="data[indextr].status === 1"
color="rgb(187, 138, 200)"
class="operat-btn"
text-color="warning"
size="small"
@click="renewal(data[indextr])">续期</vs-button>
@click="renewal(data[indextr])">续期</vs-button> -->
</vs-td>
</vs-tr>
</template>
</vs-table>
<vs-pagination
v-model:current-page="query.page"
class="content-conter-footer"
v-model="query.page"
:total="query.total"
:page-size="query.pageSize"
@change="getMyProxy"
/>
></vs-pagination>
</vs-row>
<vs-row v-else-if="activeMenu===1">
<vs-row v-else-if="activeMenu===1" class="content-conter-container">
<vs-table class="tablex" :data="proxys">
<template slot="thead">
<vs-th> 国家/地区 </vs-th>
@ -326,6 +324,7 @@
<vs-th> 密码 </vs-th>
<vs-th> 状态 </vs-th>
<vs-th> 过期时间 </vs-th>
<vs-th> 自动续费 </vs-th>
<vs-th> 操作 </vs-th>
</template>
@ -364,6 +363,9 @@
<vs-td :data="data[indextr].expired">
{{formatDate(data[indextr].expired)}}
</vs-td>
<vs-td :data="data[indextr].autoRenewal">
<vs-switch v-if="data[indextr].status === 1" :value="data[indextr].autoRenewal" @input="(val) => onSwitchChange(val, data[indextr],indextr)"/>
</vs-td>
<vs-td :data="data[indextr].id">
<vs-button
v-if="data[indextr].status === 1"
@ -373,20 +375,28 @@
icon="qr_code"
@click="handleShowQrCode(data[indextr],1)"
></vs-button>
<vs-button v-if="data[indextr].status === 1"
color="rgb(187, 138, 200)"
text-color="warning"
size="small"
@click="renewal(data[indextr])">续期</vs-button>
<vs-button color="warning" size="small" @click="handleDeleteProxy(data[indextr])">
删除
</vs-button>
</vs-tr>
</template>
</vs-table>
<vs-pagination
v-model:current-page="query.page"
class="content-conter-footer"
v-model="query.page"
:total="query.total"
:page-size="query.pageSize"
@change="getMyProxy"
/>
></vs-pagination>
</vs-row>
<!--短效号码-->
<vs-row v-else-if="activeMenu===3">
<vs-row v-else-if="activeMenu===3" class="content-conter-container">
<vs-table class="tablex" :data="smsList">
<template slot="thead">
<vs-th> 服务 </vs-th>
@ -427,14 +437,6 @@
</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="primary" size="small"
v-if="data[indextr].actived === 1 && data[indextr].status === 1 &&new Date()<new Date(data[indextr].expireTime)"
@click="handleCancelSms(data[indextr])">取消</vs-button>
@ -445,15 +447,16 @@
</template>
</vs-table>
<vs-pagination
v-model:current-page="smsQuery.page"
class="content-conter-footer"
v-model="smsQuery.page"
:total="smsQuery.total"
:page-size="smsQuery.pageSize"
@change="getSmsList"
/>
></vs-pagination>
</vs-row>
<!--长效-->
<vs-row v-else-if="activeMenu===4">
<vs-row v-else-if="activeMenu===4" class="content-conter-container">
<vs-table class="tablex" :data="smsList">
<template slot="thead">
<vs-th> 服务 </vs-th>
@ -462,6 +465,7 @@
<vs-th> 验证码 </vs-th>
<vs-th> 状态 </vs-th>
<vs-th> 过期时间 </vs-th>
<vs-th> 自动续期 </vs-th>
<vs-th> 操作 </vs-th>
</template>
@ -490,6 +494,9 @@
<vs-td :data="data[indextr].expireTime">
{{formatDate(data[indextr].expireTime)}}
</vs-td>
<vs-td :data="data[indextr].autoRenewal">
<vs-switch :value="data[indextr].autoRenewal===1" @input="(val) => handleSmsRenew(val, data[indextr],indextr)"/>
</vs-td>
<vs-td :data="data[indextr].id">
<vs-button color="primary" size="small"
v-if="data[indextr].actived === 1 && data[indextr].status === 1 &&new Date()<new Date(data[indextr].expireTime)"
@ -508,13 +515,14 @@
</template>
</vs-table>
<vs-pagination
v-model:current-page="smsQuery.page"
class="content-conter-footer"
v-model="smsQuery.page"
:total="smsQuery.total"
:page-size="smsQuery.pageSize"
@change="getSmsList"
/>
</vs-row>
></vs-pagination>
</vs-row>
</div>
</div>
@ -745,6 +753,7 @@
>确认租赁</vs-button>
</div>
</vs-popup>
</div>
</body>
@ -784,7 +793,7 @@
area: "",
state: "",
page: 1,
pageSize: 50,
pageSize: 10,
total: 0,
},
proxys: [],
@ -800,7 +809,7 @@
//短信query
smsQuery:{
page:1,
pageSize:50,
pageSize:10,
total:0,
serviceCode:"",
},
@ -909,23 +918,45 @@
return;
}
fetch(`${requestApi}/configKey/${configKey}`,{
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/json",
Accept: "application/json",
}
})
.then((res) => res.json())
.then((response) => {
if (response.code === 200) {
this.price=Number(response.data.configValue);
}
this.getPriceByKey(configKey)
.then((price) => {
this.price=price;
})
.catch((error) => {
console.log(error);
console.error("Failed to fetch price:", error);
});
},
//根据key获取价格
async getPriceByKey(key){
try {
const response = await fetch(`${requestApi}/configKey/${key}`, {
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/json",
Accept: "application/json",
},
});
if (!response.ok) {
// 处理非 2xx 状态码
const errorData = await response.json();
throw new Error(`HTTP error! status: ${response.status}, message: ${errorData.message || 'Unknown error'}`);
}
const data = await response.json();
if (data.code === 200) {
return Number(data.data.configValue);
} else {
// 处理接口返回的业务错误码
throw new Error(`API error: ${data.message || 'Unknown API error'}`);
}
} catch (error) {
console.error("Failed to fetch price:", error); // 使用 console.error 更好地记录错误
// 你可以选择在这里重新抛出错误,或者返回一个默认值/undefined
throw error; // 重新抛出错误,让调用者处理
}
},
showLoading(ref) {
// ref.$el.setAttribute("disabled", true);
this.$vs.loading();
@ -1249,9 +1280,13 @@
switch(index){
case 1:
case 2:
this.query.page=1;
this.query.total=0;
this.reloadList();
break;
case 3:
this.smsQuery.page=1;
this.smsQuery.total=0;
this.smsForm.type=0;
this.smsForm.serviceCode="";
this.smsForm.period=undefined;
@ -1259,6 +1294,8 @@
this.handleGetPrice(this.smsForm.type);
break;
case 4:
this.smsQuery.page=1;
this.smsQuery.total=0;
this.smsForm.type=1;
this.smsForm.serviceCode="";
this.smsForm.period=undefined;
@ -1490,13 +1527,27 @@
});
},
// 切换状态
onSwitchChange(val,row,index){
async onSwitchChange(val,row,index){
let text = val?'启用':'取消';
let price=await this.getPriceByKey("long_number_renew_deduction_standard")
let tip=val?`费用:${price}U/30天`:'';
this.$vs.dialog({
color:"primary",
title:"提示",
text: `${tip}确定${text}自动续期吗?`,
acceptText:"确定",
accept:() => this.doSwitchProxyAutoRenewal(row,val)
});
},
// 代理自动续费修改changeStatus
doSwitchProxyAutoRenewal(row,val){
this.showLoading();
let data = JSON.stringify({
proxyId: row.id,
autoRenewal: val,
});
console.log('data:',data);
fetch(requestApi + "/member-proxy/change-auto-renewal", {
headers: {
Authorization: `Bearer ${this.token}`,
@ -1533,11 +1584,27 @@
this.hiddenLoading();
});
},
renewal(data){
async renewal(data){
let price=await this.getPriceByKey("ip_renew_deduction_standard");
if(!price){
return this.$vs.$notify({
title: "提示",
color: "danger",
text: "获取续期价格失败,请刷新重试",
position: "top-right",
})
return
}
let tip=`续期费用:${price}U/30天`;
this.$vs.dialog({
color:"primary",
title: `代理续期提示`,
text: '确定续期 30天吗',
text: `${tip},确定续期30天吗`,
acceptText:"确定",
accept:() => this.acceptAlert(data.id)
});
},
@ -1957,6 +2024,121 @@
this.hiddenLoading();
});
},
//长效号码续期状态修改
async handleSmsRenew(val,row,index){
let price=await this.getPriceByKey("long_number_renew_deduction_standard")
const newState=val?1:2;
const originalState = row.autoRenewal;
const title=val?`续费标准 ${price}U/30天 确定要对[${row.phone}]的短信服务续期吗?`:"确认取消自动续费吗?";
this.$vs.dialog({
color:"primary",
title: `提示`,
text: title,
acceptText:"确定",
accept: ()=>this.doSmsRenew(row,originalState,newState,index)
});
},
handleSmsRenewClose(){
console.log("close");
},
//修改长效号码续期状态
doSmsRenew(row,originalState,newState,index){
this.showLoading();
let data = JSON.stringify({
id:row.id,
autoRenew:newState
});
fetch(requestApi + "/sms-phone/auto-renewal", {
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/json",
Accept: "application/json",
},
method: "PUT",
body: data,
})
.then((res) => res.json())
.then((response) => {
if (response.code === 200) {
this.$vs.notify({
title: "提示",
color: "success",
text: "修改成功",
position: "top-right",
});
this.getMyBalance();
this.$set(this.smsList[index], 'autoRenewal', newState);
// this.getSmsList();
} else {
this.$vs.notify({
title: "提示",
color: "danger",
text: response.msg,
position: "top-right",
});
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
this.hiddenLoading();
});
},
handleDeleteProxy(row){
this.$vs.dialog({
color:"primary",
title: `提示`,
text:"确认删除吗?",
acceptText:"确定",
accept:() => this.doDeleteProxy(row)
});
},
//删除代理
doDeleteProxy(row){
this.showLoading();
let data = JSON.stringify({
id:row.id});
fetch(requestApi + "/member-proxy/my", {
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.getMyProxy();
} else {
this.$vs.notify({
title: "提示",
color: "danger",
text: response.msg,
position: "top-right",
});
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
this.hiddenLoading();
})
}
},
});
</script>
@ -2099,5 +2281,14 @@
.form-item{
padding-top: 10px
}
.content-conter-container{
height: calc(100% - 45px);
overflow-y: auto;
}
.content-conter-footer{
height: 45px;
}
</style>
</html>