Files
proxy_web_site/cli-traffic.html
hucan 096b346d54 1、取消自动续费价格显示
2、增加清除数据
3、默认自动续期开启
2025-07-29 18:15:29 +08:00

2399 lines
78 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"
/>
<link
href="/static/images/favicon.ico"
rel="shortcut icon"
type="image/x-icon"
/>
<link rel="dns-prefetch" href="https://www.googletagmanager.com" />
<link rel="dns-prefetch" href="https://googleads.g.doubleclick.net" />
<title>Proxy - The world's best and fastest residential proxies</title>
<meta
name="description"
content="Proxy has the fastest residential IP, with 100 million residential IPs from 180+ countries."
/>
<link
rel="stylesheet"
href="https://unpkg.com/vuesax@3.11.13/dist/vuesax.css"
/>
<!-- 引入字体图标 -->
<link
rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Material+Icons"
/>
<!-- 引入 Vue 2 -->
<script src="https://unpkg.com/vue@2.7.16/dist/vue.js"></script>
<!-- 引入 Vuesax JS -->
<script src="https://unpkg.com/vuesax@3.11.13/dist/vuesax.umd.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="static/js/common.js?20250717"></script>
</head>
<body>
<div id="app">
<div class="header">
<div class="logo">
<img
style="height: 100%"
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" @click="handleRecharge">
余额 $ {{user.balance}}
</p>
<vs-select v-model="language" style="width: 100px">
<vs-select-item value="zh" text="中文" />
<vs-select-item value="en" text="English" />
</vs-select>
<vs-dropdown class="user-dropdown">
<vs-button
icon="account_circle"
color="rgba(0,0,0,0.9)"
type="flat"
>
{{ user.name }}
</vs-button>
<vs-dropdown-menu class="dropdown-menu">
<!-- <vs-dropdown-item>{{user}}</vs-dropdown-item> -->
<vs-dropdown-item @click="handleLogout">退出登录</vs-dropdown-item>
</vs-dropdown-menu>
</vs-dropdown>
</div>
</div>
<!-- 主体区域 -->
<div class="main-area">
<!-- 左侧菜单 -->
<div class="sidebar">
<vs-sidebar
static-position
:hidden-background="true"
default-index="2"
color="primary"
spacer
v-model="active"
>
<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"
>
动态IP
</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" v-if="activeMenu === 1||activeMenu===2">
<vs-select
autocomplete
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
autocomplete
style="margin-left: 10px;"
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>
<div class="btn-group">
<vs-button color="primary" size="small" @click="reloadList"
>查询</vs-button
>
<vs-button
color="primary"
type="border"
size="small"
@click="handleResetList"
>
重置
</vs-button>
<vs-button
color="primary"
type="border"
size="small"
@click="handleGetProxy"
>获取代理</vs-button
>
<vs-button color="danger" type="filled" size="small" @click="handleClearProxy">清除数据</vs-button>
</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
>
<vs-button color="danger" type="filled" size="small" @click="handleClearSms">清除数据</vs-button>
</div>
</div>
<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>
</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>
<vs-td :data="data[indextr].state">
{{data[indextr].state}}
</vs-td>
<vs-td :data="data[indextr].status">
<vs-chip
v-if="data[indextr].status === 1"
transparent
color="success"
>
启用
</vs-chip>
<vs-chip v-else transparent color="warning">
禁用
</vs-chip>
</vs-td>
<vs-td :data="data[indextr].expired">
{{formatDate(data[indextr].expired)}}
</vs-td>
<!-- <vs-td :data="data[indextr].autoRenewal">
<vs-switch v-model="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"
color="success"
class="operat-btn"
type="flat"
size="small"
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-td>
</vs-tr>
</template>
</vs-table>
<vs-pagination
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" class="content-conter-container">
<vs-table class="tablex" :data="proxys">
<template slot="thead">
<vs-th> 国家/地区 </vs-th>
<vs-th> 城市 </vs-th>
<vs-th> IP:端口 </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].area">
{{data[indextr].area}}
</vs-td>
<vs-td :data="data[indextr].state">
{{data[indextr].state}}
</vs-td>
<vs-td :data="data[indextr].ip">
{{data[indextr].ip}}:{{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].id">
<vs-chip
v-if="data[indextr].status === 1"
transparent
color="success"
>
启用
</vs-chip>
<vs-chip v-else transparent color="warning">
禁用
</vs-chip>
</vs-td>
<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"
color="success"
type="flat"
size="small"
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
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" class="content-conter-container">
<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>
</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].expireTime">
<countdown
:time="(new Date( data[indextr].expireTime)) - Date.now()"
v-if="data[indextr].expireTime &&new Date()<new Date(data[indextr].expireTime)&& data[indextr].status===1"
>
<template slot-scope="props">
{{ Math.floor((new Date( data[indextr].expireTime) - Date.now()) / 1000) || 0 }} 秒
</template>
</countdown>
</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)"
@click="handleCancelSms(data[indextr])">取消</vs-button>
<vs-button color="warning" size="small" @click="handleDeleteSms(data[indextr])">
删除
</vs-button>
</vs-tr>
</template>
</vs-table>
<vs-pagination
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" class="content-conter-container">
<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>
<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].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)"
@click="handleCancelSms(data[indextr])">取消</vs-button>
<vs-button
v-if="data[indextr].actived ===2 && 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
class="content-conter-footer"
v-model="smsQuery.page"
:total="smsQuery.total"
:page-size="smsQuery.pageSize"
@change="getSmsList"
></vs-pagination>
</vs-row>
</div>
</div>
</div>
<vs-popup
title="提取长效IP"
:active.sync="showUseProxy"
:loading="loading"
>
<div style="text-align: right">
<div style=" display: flex;align-items: center;scrollbar-gutter: 20px;column-gap: 20px;justify-content: right;">
<span>价格U: {{this.price}}</span> <vs-button olor="primary" type="border" size="small" @click="getIpList"
>刷新</vs-button
>
</div>
<vs-table :data="useList" class="tablex">
<template slot="thead">
<vs-th class="table-cell-center"> IP </vs-th>
<vs-th class="table-cell-center"> 国家 </vs-th>
<vs-th class="table-cell-center"> 城市 </vs-th>
<vs-th class="table-cell-center"> 操作 </vs-th>
</template>
<template slot-scope="{data}">
<vs-tr :key="indextr" v-for="(tr, indextr) in data">
<vs-td :data="data[indextr].ip" class="table-cell-center">
{{data[indextr].ip}}
</vs-td>
<vs-td :data="data[indextr].country" class="table-cell-center">
{{data[indextr].country}}
</vs-td>
<vs-td :data="data[indextr].city" class="table-cell-center">
{{data[indextr].city}}
</vs-td>
<vs-td :data="data[indextr].id" class="table-cell-center">
<vs-button
color="primary"
size="small"
@click="handleUseProxy(data[indextr])"
>提取</vs-button
>
</vs-td>
</vs-tr>
</template>
</vs-table>
</div>
</vs-popup>
<vs-popup class="holamundo" title="获取代理" :active.sync="showGetProxy">
<div>
<vs-select
autocomplete
v-model="proxyForm.area"
autocomplete
class="selectExample"
placeholder="area"
label="国家/地区"
>
<vs-select-item
v-for="item in traffictList"
:key="'detail_area'+item.code"
:value="item.code"
:text="item.name"
></vs-select-item>
</vs-select>
</div>
<div style="padding: top 10px">
<vs-select
autocomplete
v-model="proxyForm.state"
class="selectExample"
label="城市"
placeholder="city"
>
<vs-select-item
v-for="(item,index) in detailCityList"
:key="'detail_city'+index"
:value="item.state"
:text="item.state"
></vs-select-item>
</vs-select>
</div>
<div style="padding: top 10px">
<vs-select
autocomplete
v-model="proxyForm.port"
class="selectExample"
label="端口"
placeholder="port"
>
<vs-select-item
v-for="(item,index) in trafficServer"
:key="'detail_port'+index"
:value="item.hostname"
:text="item.hostname"
></vs-select-item>
</vs-select>
</div>
<div class="form-item" style="text-align: right;">
价格U: {{this.price}}
</div>
<div class="form-item" style="text-align: right">
<vs-button size="small" @click="handleGetTrafficProxy"
>提取</vs-button
>
</div>
</vs-popup>
<vs-popup title="余额充值" :active.sync="showRecharge" :loading="loading">
<div class="popup-content" v-if="step===1">
充值金额:<vs-input
class="inputx"
placeholder="请输入充值金额(U)"
v-model.number="rechargeForm.amount"
/>
</div>
<div v-else style="text-align: center">
<div class="qr-code">
<div v-show="!rechargeForm.finished" id="qrcode"></div>
<div v-show="rechargeForm.finished" class="success-contianer">
<img src="static/image/pay-sucess.png" alt="" />
</div>
</div>
<div class="wallet-info">
<p>主链:<strong>{{ rechargeData.blockChain }}</strong></p>
<p>钱包地址: <strong>{{ rechargeData.receiveAddress }}</strong></p>
<p>支付金额: <strong>{{ rechargeData.amount }} USDT</strong></p>
<div>
<countdown
:time="(rechargeData.expireUnix * 1000) - Date.now()"
v-if="rechargeData.expireUnix && (rechargeData.expireUnix * 1000) > Date.now() && !rechargeForm.finished"
>
<template slot-scope="props">
倒计时:
<span v-if="props.minutes>0||props.hours>0||props.days>0"
>{{ props.minutes }} 分</span
>
<span
v-if="props.seconds>0||props.minutes>0||props.hours>0||props.days>0"
>{{ props.seconds }} 秒</span
>
<span
style="color: red"
v-if="props.days==0&&props.hours==0&&props.minutes==0&&props.seconds==0"
>订单已过期,请勿支付!</span
>
</template>
</countdown>
<div v-else-if="rechargeForm.finished" style="color: green">
充值成功,请勿重复支付!
</div>
</div>
</div>
</div>
<div class="popup-bottom">
<vs-button
color="primary"
type="border"
size="small"
@click="handleCancelRecharge"
>
取消
</vs-button>
<vs-button
v-if="step===1"
ref="nextBtn"
color="primary"
type="filled"
size="small"
class="vs-con-loading__container"
:disabled="rechargeForm.amount<=0"
@click="handleNextStep()"
>
下一步
</vs-button>
<vs-button
v-else
color="primary"
size="small"
@click="handlePrevStep()"
>
上一步
</vs-button>
</div>
</vs-popup>
<vs-popup
title="扫码使用"
style="text-align: center"
:active.sync="showQrCode"
>
<div id="proxy-qrcode"></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>
<script>
new Vue({
el: "#app",
components: {
countdown: window.VueCountdown,
},
data() {
return {
active: false,
activeMenu: 2,
showGetProxy: false,
showUseProxy: false,
showQrCode: false,
proxyQrCode: "",
proxyForm: {},
showRecharge: false,
rechargeForm: {
amount: 10,
finished: false,
},
token: "",
rechargeData: {},
loading: false,
step: 1,
language: "zh",
languageList: [
{ value: "en", text: "English" },
{ value: "zh", text: "简体中文" },
],
user: {
name: "",
},
query: {
area: "",
state: "",
page: 1,
pageSize: 10,
total: 0,
},
proxys: [],
checkOrderTimer: null,
traffictList: [],
cityList: [],
detailCityList: [],
trafficServer: [],
//可提取ip列表
useList: [],
//短信服务列表
smsServices:[],
//短信query
smsQuery:{
page:1,
pageSize:10,
total:0,
serviceCode:"",
},
//短信列表
smsList:[],
showGetSms:false,
smsForm:{},
checkSmsCodeTimer:null,
smsPrice:undefined,
//Ip单价
price:undefined,
};
},
mounted() {
let token = localStorage.getItem("session");
if (token) {
this.token = token;
this.getUserInfo(token);
} else {
if (this.language === "zh") {
location.href = "sign-in1.html";
} else {
location.href = "sign-in.html";
}
}
this.resetSmsForm();
this.getMyProxy();
this.getTraffictList();
this.getTrafficServer();
this.getSmsServices();
//定时器
this.createCheckSmsCodeTimer();
},
watch: {
showGetProxy(val, oldVal) {
if (!val && val !== oldVal) {
this.proxyForm.area = "";
this.proxyForm.state = "";
this.proxyForm.port = "";
}
},
showRecharge(val, oldVal) {
console.log("showRecharge", val, oldVal);
if (!val && val !== oldVal) {
this.cleanCheckOrderTimer(this.checkOrderTimer);
this.resetRechargeForm();
this.rechargeData = {};
this.step = 1;
this.getMyBalance();
}
},
"query.area"(val, oldVal) {
console.log("xxxxxxx", val, oldVal);
if (val && val !== oldVal) {
let area = this.traffictList.find((item) => item.code === val);
if (area) {
this.cityList = area.states;
}
}
},
"proxyForm.area"(val, oldVal) {
if (val && val !== oldVal) {
let area = this.traffictList.find((item) => item.code === val);
if (area) {
this.detailCityList = area.states;
}
}
},
},
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);
});
},
getPrice(){
this.price=undefined;
let configKey;
switch(this.activeMenu){
case 1:
configKey="ip_deduction_standard";
break;
case 2:
configKey="deduction_standard";
break;
default:
return;
}
this.getPriceByKey(configKey)
.then((price) => {
this.price=price;
})
.catch((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();
},
getOrderStatus(orderNo) {
fetch(
requestApi + "/member-recharge/order-status?orderNo=" + orderNo,
{
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/json",
Accept: "application/json",
},
}
)
.then((res) => res.json())
.then((response) => {
if (response.code === 200 && response.data === 2) {
//订单已完成
this.rechargeForm.finished = true;
this.cleanCheckOrderTimer();
}
});
},
hiddenLoading(ref) {
// ref.$el.removeAttribute("disabled");
this.$vs.loading.close();
},
homeClick() {
window.location.href = "/";
},
handleGetProxy() {
this.getPrice();
if (this.activeMenu === 1) {
this.showUseProxy = true;
this.getIpList();
} else {
this.showGetProxy = true;
}
},
resetRechargeForm() {
this.rechargeForm = {
amount: 10,
};
},
handleCancelRecharge() {
this.showRecharge = false;
this.resetRechargeForm();
},
handleRecharge() {
this.step = 1;
this.showRecharge = true;
},
handleNextStep() {
this.loading = true;
this.showLoading(this.$refs.nextBtn);
fetch(requestApi + "/member-recharge/recharge", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${this.token}`,
},
body: JSON.stringify(this.rechargeForm),
})
.then((res) => res.json())
.then((response) => {
console.log(response);
if (response.code === 200) {
this.rechargeData = response.data;
this.step = 2;
this.$nextTick(() => {
this.generateQRCode(
this.rechargeData.receiveAddress,
"qrcode"
);
});
this.createCheckOrderTimer();
} else {
this.$vs.notify({
title: "Position top-center",
text: response.msg,
color: "danger",
position: "top-center",
});
}
})
.finally(() => {
this.hiddenLoading();
});
},
handlePrevStep() {
this.step = 1;
},
getUserInfo(token) {
let that = this;
fetch(requestApi + "/getinfo", {
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
Accept: "application/json",
},
})
.then((res) => res.json())
.then((response) => {
console.log(response);
console.log("code", response.code);
if (response.code === 200) {
that.user = response.data;
} else {
localStorage.removeItem("session");
if (this.language === "zh") {
location.href = "sign-in1.html";
} else {
location.href = "sign-in.html";
}
}
});
},
//生成二维码
generateQRCode(qrString, elId) {
const text = qrString.trim(); // 获取输入框内容并去除首尾空格
const qrcodeContainer = document.getElementById(elId);
if (text) {
// 1. 清空容器内的所有内容,包括旧的二维码或提示信息
qrcodeContainer.innerHTML = "";
this.showPlaceholder = false;
this.qrError = null;
// 2. 创建一个新的 canvas 元素
const canvasElement = document.createElement("canvas");
// 可以给 canvas 设置一个 ID 或者类名,如果需要后续引用或样式控制
// canvasElement.id = 'qrCanvas';
qrcodeContainer.appendChild(canvasElement); // 将 canvas 添加到容器中
// 3. 使用 QRCode.toCanvas 在新创建的 canvas 上生成二维码
QRCode.toCanvas(
canvasElement,
text,
{
// 将 canvasElement 传递给 toCanvas
width: 150, // 设置二维码宽度
color: {
dark: "#000000", // 二维码颜色
light: "#ffffff", // 背景颜色
},
},
(error) => {
if (error) {
qrcodeContainer.innerHTML = `<p class="text-red-500">获取地址失败请刷新</p>`; // 重新显示错误信息
} else {
console.log("二维码生成成功!");
}
}
);
} else {
// 如果输入为空,给出提示
qrcodeContainer.innerHTML = ""; // 清空可能存在的旧二维码
}
},
//定时检查订单状态
createCheckOrderTimer() {
if (this.checkOrderTimer) {
clearInterval(this.checkOrderTimer);
} else {
console.log("createCheckOrderTimer")
this.checkOrderTimer = setInterval(() => {
this.getOrderStatus(this.rechargeData.orderNo);
}, 10000);
}
},
getMyBalance(){
fetch(requestApi + "/member-balance/balance", {
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/json",
Accept: "application/json",
},
})
.then((res) => res.json())
.then((response) => {
if (response.code === 200) {
this.user.balance=response.data;
}
})
.catch((error) => {
console.log(error);
});
},
formatDate(expired) {
const date = new Date(expired);
// 自动格式化为用户本地时间格式
const readable = date.toLocaleString();
return readable;
},
cleanCheckOrderTimer() {
if (this.checkOrderTimer) {
clearInterval(this.checkOrderTimer);
}
},
getTraffictList() {
fetch(requestApi + "/member-proxy/traffic", {
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/json",
Accept: "application/json",
},
})
.then((res) => res.json())
.then((response) => {
if (response.code === 200) {
this.traffictList = response.data;
}
})
.catch((error) => {
console.log(error);
});
},
handleAreaChange(item) {
console.log("xxxxxxx", item);
if (item) {
this.cityList = item.states;
}
},
getTrafficServer() {
fetch(requestApi + "/member-proxy/traffic-server", {
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.data);
this.trafficServer = response.data;
}
})
.catch((error) => {
console.log(error);
});
},
//生成流量账号
handleGetTrafficProxy() {
if (!this.proxyForm.area) {
this.$vs.notify({
title: "提示",
text: "请先选择国家/区域",
color: "danger",
position: "top-right",
});
return;
}
if (!this.proxyForm.port) {
this.$vs.notify({
title: "提示",
text: "请选择主机:端口",
color: "danger",
position: "top-right",
});
return;
}
this.showLoading();
fetch(requestApi + "/member-proxy/generate-proxy", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${this.token}`,
},
body: JSON.stringify(this.proxyForm),
})
.then((res) => res.json())
.then((response) => {
if (response.code === 200) {
this.$vs.notify({
title: "提示",
color: "success",
text: "获取成功",
position: "top-right",
});
if(response.data){
this.user.balance=response.data;
}
this.showGetProxy = false;
this.getMyProxy();
} else {
this.$vs.notify({
title: "提示",
color: "danger",
text: response.msg,
position: "top-right",
});
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
this.hiddenLoading();
});
},
handleActiveMenu(index) {
this.activeMenu = index;
switch(index){
case 1:
case 2:
this.query.page=1;
this.query.total=1;
this.reloadList();
break;
case 3:
this.smsQuery.page=1;
this.smsQuery.total=1;
this.smsForm.type=0;
this.smsForm.serviceCode="";
this.smsForm.period=undefined;
this.reloadSmsList();
this.handleGetPrice(this.smsForm.type);
break;
case 4:
this.smsQuery.page=1;
this.smsQuery.total=1;
this.smsForm.type=1;
this.smsForm.serviceCode="";
this.smsForm.period=undefined;
this.reloadSmsList();
this.handleGetPrice(this.smsForm.type);
break;
}
},
reloadList() {
this.query.pageIndex = 1;
this.getMyProxy();
},
getMyProxy() {
console.log("触发getMyProxy");
this.showLoading();
let query = {
type: this.activeMenu,
pageIndex: this.query.page,
pageSize: this.query.pageSize,
area: this.query.area,
state: this.query.state,
};
const queryString = new URLSearchParams(query).toString();
const url = `${requestApi}/member-proxy/my-proxy?${queryString}`;
fetch(url, {
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/json",
Accept: "application/json",
},
})
.then((res) => res.json())
.then((response) => {
if (response.code === 200) {
this.proxys = response.data.list;
let total = Math.ceil(
response.data.count / this.query.pageSize
);
if(this.query.total!==total){
this.query.total = total;
}
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
this.hiddenLoading();
});
},
//提取长效ip
handleUseProxy(row) {
this.showLoading();
let data = JSON.stringify({
id: row.id,
lang: this.language,
code: row.code,
city: row.city,
});
fetch(requestApi + "/member-proxy/use", {
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",
});
if(response.data){
this.user.balance=response.data;
}
this.showUseProxy = false;
this.getMyProxy();
} else {
this.$vs.notify({
title: "提示",
color: "danger",
text: response.msg,
position: "top-right",
});
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
this.hiddenLoading();
});
},
//获取可提取ip列表
getIpList() {
this.showLoading();
fetch(requestApi + "/member-proxy/ip-list?lang=" + this.language, {
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.useList = response.data;
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
this.hiddenLoading();
});
},
handleResetList() {
this.query.area = "";
this.query.state = "";
this.query.page = 1;
this.getMyProxy();
},
//展示二维码
handleShowQrCode(row, type) {
this.showQrCode = true;
let baseData = "";
if (type === 1) {
baseData = `${row.userName}:${row.password}@${row.ip}:${row.port}`;
} else {
baseData = `${row.userName}:${row.password}@${row.port}`;
}
if(baseData){
console.log(baseData);
let code = `socks://${btoa(baseData)}`;
console.log(code);
this.generateQRCode(code, "proxy-qrcode");
}
},
//重置流量账号
handleResetGenerateProxy(row) {
this.showLoading();
let data = JSON.stringify({
id: row.id,
});
fetch(requestApi + "/member-proxy/reset-generate-proxy", {
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.showGetProxy = false;
this.getMyProxy();
} else {
this.$vs.notify({
title: "提示",
color: "danger",
text: response.msg,
position: "top-right",
});
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
this.hiddenLoading();
});
},
handleLogout(){
this.showLoading();
fetch(requestApi + "/logout", {
headers: {
Authorization: `Bearer ${this.token}`,
"Content-Type": "application/json",
Accept: "application/json",
},
method: "POST",})
.then((res) => res.json())
.then((response) => {
if (response.code === 200) {
localStorage.removeItem("session");
if (this.language === "zh") {
location.href = "sign-in1.html";
} else {
location.href = "sign-in.html";
}
} else {
this.$vs.notify({
title: "提示",
color: "danger",
text: response.msg,
position: "top-right",
});
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
this.hiddenLoading();
});
},
// 切换状态
async onSwitchChange(val,row,index){
let text = val?'启用':'取消';
this.$vs.dialog({
color:"primary",
title:"提示",
text: `确定${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}`,
"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.getMyProxy();
} else {
this.$vs.notify({
title: "提示",
color: "danger",
text: response.msg,
position: "top-right",
});
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
this.hiddenLoading();
});
},
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: `${tip},确定续期30天吗`,
acceptText:"确定",
accept:() => this.acceptAlert(data.id)
});
},
acceptAlert(id){
this.showLoading();
let data=JSON.stringify({
proxyId: id,
});
fetch(requestApi + "/member-proxy/user-renewal", {
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",
});
if(response.data){
this.user.balance=response.data;
}
this.getMyProxy();
} else {
this.$vs.notify({
title: "提示",
color: "danger",
text: response.msg,
position: "top-right",
});
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
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);
});
},
//取消sms
handleCancelSms(row){
this.$vs.dialog({
color:"primary",
title: `提示`,
text: `确定要取消[${row.phone}]的短信服务吗?`,
acceptText:"确定",
accept:() => this.cancelSms(row)
});
},
cancelSms(row){
this.showLoading();
let data = JSON.stringify({
id:row.id});
fetch(requestApi + "/sms-phone/cancel", {
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.getSmsList();
} else {
this.$vs.notify({
title: "提示",
color: "danger",
text: response.msg,
position: "top-right",
});
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
this.hiddenLoading();
});
},
//长效号码续期状态修改
async handleSmsRenew(val,row,index){
const newState=val?1:2;
const originalState = row.autoRenewal;
const title=val?`确定要对[${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();
})
},
//清理代理
handleClearProxy(){
let type,typeName;
switch(this.activeMenu){
case 1:
type=1;
typeName="长效ip";
break;
case 2:
type=2;
typeName="短效ip";
break;
default:
break;
}
this.$vs.dialog({
color:"primary",
title:"提示",
text:`确认清理${typeName}数据吗?`,
acceptText:"确定",
accept:()=>this.doCleanProxy(type)
})
},
doCleanProxy(type){
this.showLoading();
let data = JSON.stringify({
type:type});
fetch(requestApi + "/member-proxy/clean", {
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();
});
},
//清理短信
handleClearSms(){
let type,typeName;
switch(this.activeMenu){
case 4:
type=1;
typeName="长效号码";
break;
case 3:
type=0;
typeName="短效号码";
break;
default:
break;
}
this.$vs.dialog({
color:"primary",
title:"提示",
text:`确认清理${typeName}数据吗?`,
acceptText:"确定",
accept:()=>this.doCleanSms(type)
})
},
doCleanSms(type){
this.showLoading();
let data = JSON.stringify({
type:type});
fetch(requestApi + "/sms-phone/clean", {
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();
});
},
},
});
</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>