2025-07-12 15:34:14 +08:00
|
|
|
|
<!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>
|
2025-07-18 18:06:55 +08:00
|
|
|
|
<script src="static/js/common.js?20250717"></script>
|
2025-07-12 15:34:14 +08:00
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
|
|
|
<div id="app">
|
|
|
|
|
|
<div class="header">
|
|
|
|
|
|
<div class="logo">
|
|
|
|
|
|
<img
|
|
|
|
|
|
style="height: 100%"
|
2025-07-28 18:06:46 +08:00
|
|
|
|
src="static/picture/logo.png?v=20250726"
|
2025-07-12 15:34:14 +08:00
|
|
|
|
@click="homeClick"
|
|
|
|
|
|
alt=""
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div style="display: flex; align-items: center; gap: 20px">
|
2025-07-28 18:06:46 +08:00
|
|
|
|
<p data-v-d585ebde="" class="balance-btn" @click="handleRecharge">
|
2025-07-12 15:34:14 +08:00
|
|
|
|
余额 :$ {{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
|
2025-07-24 23:34:35 +08:00
|
|
|
|
static-position
|
|
|
|
|
|
:hidden-background="true"
|
|
|
|
|
|
default-index="2"
|
|
|
|
|
|
color="primary"
|
|
|
|
|
|
spacer
|
|
|
|
|
|
v-model="active"
|
2025-07-12 15:34:14 +08:00
|
|
|
|
>
|
2025-07-24 23:34:35 +08:00
|
|
|
|
<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"
|
|
|
|
|
|
>
|
2025-07-28 18:06:46 +08:00
|
|
|
|
动态IP
|
2025-07-24 23:34:35 +08:00
|
|
|
|
</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>
|
|
|
|
|
|
|
2025-07-12 15:34:14 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 内容展示区 -->
|
|
|
|
|
|
<div class="content">
|
|
|
|
|
|
<div class="content-conter">
|
2025-07-24 23:34:35 +08:00
|
|
|
|
<div class="content-conter-header" v-if="activeMenu === 1||activeMenu===2">
|
2025-07-12 15:34:14 +08:00
|
|
|
|
<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
|
|
|
|
|
|
>
|
2025-07-29 18:15:29 +08:00
|
|
|
|
|
|
|
|
|
|
<vs-button color="danger" type="filled" size="small" @click="handleClearProxy">清除数据</vs-button>
|
2025-07-12 15:34:14 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
2025-07-24 23:34:35 +08:00
|
|
|
|
|
|
|
|
|
|
<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
|
|
|
|
|
|
>
|
2025-07-29 18:15:29 +08:00
|
|
|
|
<vs-button color="danger" type="filled" size="small" @click="handleClearSms">清除数据</vs-button>
|
2025-07-24 23:34:35 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-07-28 18:06:46 +08:00
|
|
|
|
<vs-row v-if="activeMenu === 2" class="content-conter-container">
|
|
|
|
|
|
<vs-table class="tablex" :data="proxys">
|
2025-07-12 15:34:14 +08:00
|
|
|
|
<template slot="thead">
|
2025-07-28 18:06:46 +08:00
|
|
|
|
<vs-th> ID</vs-th>
|
2025-07-12 15:34:14 +08:00
|
|
|
|
<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">
|
2025-07-28 18:06:46 +08:00
|
|
|
|
<vs-td :data="data[indextr].id">
|
|
|
|
|
|
{{data[indextr].id}}
|
|
|
|
|
|
</vs-td>
|
2025-07-12 15:34:14 +08:00
|
|
|
|
<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>
|
2025-07-28 18:06:46 +08:00
|
|
|
|
<!-- <vs-td :data="data[indextr].autoRenewal">
|
2025-07-12 15:34:14 +08:00
|
|
|
|
<vs-switch v-model="data[indextr].autoRenewal" @input="(val) => onSwitchChange(val, data[indextr],indextr)"/>
|
2025-07-28 18:06:46 +08:00
|
|
|
|
</vs-td> -->
|
2025-07-12 15:34:14 +08:00
|
|
|
|
<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>
|
2025-07-28 18:06:46 +08:00
|
|
|
|
<vs-button color="warning"class="operat-btn" size="small" @click="handleDeleteProxy(data[indextr])">
|
|
|
|
|
|
删除
|
|
|
|
|
|
</vs-button>
|
2025-07-12 15:34:14 +08:00
|
|
|
|
</vs-td>
|
|
|
|
|
|
</vs-tr>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</vs-table>
|
|
|
|
|
|
<vs-pagination
|
2025-07-28 18:06:46 +08:00
|
|
|
|
class="content-conter-footer"
|
|
|
|
|
|
v-model="query.page"
|
2025-07-12 15:34:14 +08:00
|
|
|
|
:total="query.total"
|
|
|
|
|
|
:page-size="query.pageSize"
|
|
|
|
|
|
@change="getMyProxy"
|
2025-07-28 18:06:46 +08:00
|
|
|
|
></vs-pagination>
|
2025-07-12 15:34:14 +08:00
|
|
|
|
</vs-row>
|
|
|
|
|
|
|
2025-07-28 18:06:46 +08:00
|
|
|
|
<vs-row v-else-if="activeMenu===1" class="content-conter-container">
|
2025-07-12 15:34:14 +08:00
|
|
|
|
<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>
|
2025-07-28 18:06:46 +08:00
|
|
|
|
<vs-th> 自动续费 </vs-th>
|
2025-07-12 15:34:14 +08:00
|
|
|
|
<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>
|
2025-07-28 18:06:46 +08:00
|
|
|
|
<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>
|
2025-07-12 15:34:14 +08:00
|
|
|
|
<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>
|
2025-07-28 18:06:46 +08:00
|
|
|
|
<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>
|
2025-07-12 15:34:14 +08:00
|
|
|
|
</vs-tr>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</vs-table>
|
|
|
|
|
|
<vs-pagination
|
2025-07-28 18:06:46 +08:00
|
|
|
|
class="content-conter-footer"
|
|
|
|
|
|
v-model="query.page"
|
2025-07-12 15:34:14 +08:00
|
|
|
|
:total="query.total"
|
|
|
|
|
|
:page-size="query.pageSize"
|
|
|
|
|
|
@change="getMyProxy"
|
2025-07-28 18:06:46 +08:00
|
|
|
|
></vs-pagination>
|
2025-07-12 15:34:14 +08:00
|
|
|
|
</vs-row>
|
|
|
|
|
|
|
2025-07-24 23:34:35 +08:00
|
|
|
|
<!--短效号码-->
|
2025-07-28 18:06:46 +08:00
|
|
|
|
<vs-row v-else-if="activeMenu===3" class="content-conter-container">
|
2025-07-24 23:34:35 +08:00
|
|
|
|
<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>
|
2025-07-25 17:26:04 +08:00
|
|
|
|
<vs-th> 过期时间 </vs-th>
|
2025-07-24 23:34:35 +08:00
|
|
|
|
<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>
|
2025-07-25 17:26:04 +08:00
|
|
|
|
<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>
|
2025-07-24 23:34:35 +08:00
|
|
|
|
|
|
|
|
|
|
<vs-td :data="data[indextr].id">
|
2025-07-25 17:26:04 +08:00
|
|
|
|
<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])">
|
2025-07-24 23:34:35 +08:00
|
|
|
|
删除
|
|
|
|
|
|
</vs-button>
|
|
|
|
|
|
</vs-tr>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</vs-table>
|
|
|
|
|
|
<vs-pagination
|
2025-07-28 18:06:46 +08:00
|
|
|
|
class="content-conter-footer"
|
|
|
|
|
|
v-model="smsQuery.page"
|
2025-07-24 23:34:35 +08:00
|
|
|
|
:total="smsQuery.total"
|
|
|
|
|
|
:page-size="smsQuery.pageSize"
|
|
|
|
|
|
@change="getSmsList"
|
2025-07-28 18:06:46 +08:00
|
|
|
|
></vs-pagination>
|
2025-07-24 23:34:35 +08:00
|
|
|
|
</vs-row>
|
|
|
|
|
|
|
|
|
|
|
|
<!--长效-->
|
2025-07-28 18:06:46 +08:00
|
|
|
|
<vs-row v-else-if="activeMenu===4" class="content-conter-container">
|
2025-07-24 23:34:35 +08:00
|
|
|
|
<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>
|
2025-07-28 18:06:46 +08:00
|
|
|
|
<vs-th> 自动续期 </vs-th>
|
2025-07-24 23:34:35 +08:00
|
|
|
|
<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>
|
2025-07-28 18:06:46 +08:00
|
|
|
|
<vs-td :data="data[indextr].autoRenewal">
|
|
|
|
|
|
<vs-switch :value="data[indextr].autoRenewal===1" @input="(val) => handleSmsRenew(val, data[indextr],indextr)"/>
|
|
|
|
|
|
</vs-td>
|
2025-07-24 23:34:35 +08:00
|
|
|
|
<vs-td :data="data[indextr].id">
|
2025-07-25 17:26:04 +08:00
|
|
|
|
<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>
|
|
|
|
|
|
|
2025-07-24 23:34:35 +08:00
|
|
|
|
<vs-button
|
2025-07-25 17:26:04 +08:00
|
|
|
|
v-if="data[indextr].actived ===2 && data[indextr].status!==1 && new Date()<new Date(data[indextr].expireTime)"
|
2025-07-24 23:34:35 +08:00
|
|
|
|
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
|
2025-07-28 18:06:46 +08:00
|
|
|
|
class="content-conter-footer"
|
|
|
|
|
|
v-model="smsQuery.page"
|
2025-07-24 23:34:35 +08:00
|
|
|
|
:total="smsQuery.total"
|
|
|
|
|
|
:page-size="smsQuery.pageSize"
|
|
|
|
|
|
@change="getSmsList"
|
2025-07-28 18:06:46 +08:00
|
|
|
|
></vs-pagination>
|
2025-07-24 23:34:35 +08:00
|
|
|
|
|
2025-07-28 18:06:46 +08:00
|
|
|
|
</vs-row>
|
2025-07-24 23:34:35 +08:00
|
|
|
|
|
|
|
|
|
|
</div>
|
2025-07-12 15:34:14 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<vs-popup
|
|
|
|
|
|
title="提取长效IP"
|
|
|
|
|
|
:active.sync="showUseProxy"
|
|
|
|
|
|
:loading="loading"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div style="text-align: right">
|
2025-07-26 09:07:49 +08:00
|
|
|
|
<div style=" display: flex;align-items: center;scrollbar-gutter: 20px;column-gap: 20px;justify-content: right;">
|
2025-07-29 18:15:29 +08:00
|
|
|
|
<span>价格U: {{this.price}}</span> <vs-button olor="primary" type="border" size="small" @click="getIpList"
|
2025-07-12 15:34:14 +08:00
|
|
|
|
>刷新</vs-button
|
|
|
|
|
|
>
|
2025-07-26 09:07:49 +08:00
|
|
|
|
</div>
|
2025-07-12 15:34:14 +08:00
|
|
|
|
<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"
|
2025-07-29 18:15:29 +08:00
|
|
|
|
size="small"
|
2025-07-12 15:34:14 +08:00
|
|
|
|
@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>
|
|
|
|
|
|
|
2025-07-26 09:07:49 +08:00
|
|
|
|
<div class="form-item" style="text-align: right;">
|
|
|
|
|
|
价格U: {{this.price}}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="form-item" style="text-align: right">
|
2025-07-12 15:34:14 +08:00
|
|
|
|
<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>
|
2025-07-24 23:34:35 +08:00
|
|
|
|
</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>
|
2025-07-12 15:34:14 +08:00
|
|
|
|
</vs-popup>
|
2025-07-28 18:06:46 +08:00
|
|
|
|
|
2025-07-12 15:34:14 +08:00
|
|
|
|
</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,
|
2025-07-28 18:06:46 +08:00
|
|
|
|
pageSize: 10,
|
2025-07-12 15:34:14 +08:00
|
|
|
|
total: 0,
|
|
|
|
|
|
},
|
|
|
|
|
|
proxys: [],
|
|
|
|
|
|
checkOrderTimer: null,
|
|
|
|
|
|
traffictList: [],
|
|
|
|
|
|
cityList: [],
|
|
|
|
|
|
detailCityList: [],
|
|
|
|
|
|
trafficServer: [],
|
|
|
|
|
|
//可提取ip列表
|
|
|
|
|
|
useList: [],
|
2025-07-24 23:34:35 +08:00
|
|
|
|
//短信服务列表
|
|
|
|
|
|
smsServices:[],
|
|
|
|
|
|
//短信query
|
|
|
|
|
|
smsQuery:{
|
|
|
|
|
|
page:1,
|
2025-07-28 18:06:46 +08:00
|
|
|
|
pageSize:10,
|
2025-07-24 23:34:35 +08:00
|
|
|
|
total:0,
|
|
|
|
|
|
serviceCode:"",
|
|
|
|
|
|
},
|
|
|
|
|
|
//短信列表
|
|
|
|
|
|
smsList:[],
|
|
|
|
|
|
showGetSms:false,
|
|
|
|
|
|
smsForm:{},
|
|
|
|
|
|
checkSmsCodeTimer:null,
|
2025-07-26 09:07:49 +08:00
|
|
|
|
smsPrice:undefined,
|
|
|
|
|
|
//Ip单价
|
|
|
|
|
|
price:undefined,
|
2025-07-12 15:34:14 +08:00
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
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";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-24 23:34:35 +08:00
|
|
|
|
this.resetSmsForm();
|
|
|
|
|
|
|
2025-07-12 15:34:14 +08:00
|
|
|
|
this.getMyProxy();
|
|
|
|
|
|
this.getTraffictList();
|
|
|
|
|
|
this.getTrafficServer();
|
2025-07-24 23:34:35 +08:00
|
|
|
|
this.getSmsServices();
|
|
|
|
|
|
|
|
|
|
|
|
//定时器
|
|
|
|
|
|
this.createCheckSmsCodeTimer();
|
2025-07-12 15:34:14 +08:00
|
|
|
|
},
|
|
|
|
|
|
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: {
|
2025-07-24 23:34:35 +08:00
|
|
|
|
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);
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2025-07-26 09:07:49 +08:00
|
|
|
|
getPrice(){
|
|
|
|
|
|
this.price=undefined;
|
|
|
|
|
|
let configKey;
|
|
|
|
|
|
|
|
|
|
|
|
switch(this.activeMenu){
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
configKey="ip_deduction_standard";
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 2:
|
|
|
|
|
|
configKey="deduction_standard";
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-28 18:06:46 +08:00
|
|
|
|
this.getPriceByKey(configKey)
|
|
|
|
|
|
.then((price) => {
|
|
|
|
|
|
this.price=price;
|
2025-07-26 09:07:49 +08:00
|
|
|
|
})
|
|
|
|
|
|
.catch((error) => {
|
2025-07-28 18:06:46 +08:00
|
|
|
|
console.error("Failed to fetch price:", error);
|
2025-07-26 09:07:49 +08:00
|
|
|
|
});
|
|
|
|
|
|
},
|
2025-07-28 18:06:46 +08:00
|
|
|
|
//根据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; // 重新抛出错误,让调用者处理
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
2025-07-12 15:34:14 +08:00
|
|
|
|
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() {
|
2025-07-26 09:07:49 +08:00
|
|
|
|
this.getPrice();
|
2025-07-12 15:34:14 +08:00
|
|
|
|
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;
|
2025-07-29 18:15:29 +08:00
|
|
|
|
|
2025-07-24 23:34:35 +08:00
|
|
|
|
switch(index){
|
|
|
|
|
|
case 1:
|
|
|
|
|
|
case 2:
|
2025-07-28 18:06:46 +08:00
|
|
|
|
this.query.page=1;
|
2025-07-29 18:15:29 +08:00
|
|
|
|
this.query.total=1;
|
2025-07-24 23:34:35 +08:00
|
|
|
|
this.reloadList();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 3:
|
2025-07-28 18:06:46 +08:00
|
|
|
|
this.smsQuery.page=1;
|
2025-07-29 18:15:29 +08:00
|
|
|
|
this.smsQuery.total=1;
|
2025-07-24 23:34:35 +08:00
|
|
|
|
this.smsForm.type=0;
|
|
|
|
|
|
this.smsForm.serviceCode="";
|
|
|
|
|
|
this.smsForm.period=undefined;
|
|
|
|
|
|
this.reloadSmsList();
|
|
|
|
|
|
this.handleGetPrice(this.smsForm.type);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 4:
|
2025-07-28 18:06:46 +08:00
|
|
|
|
this.smsQuery.page=1;
|
2025-07-29 18:15:29 +08:00
|
|
|
|
this.smsQuery.total=1;
|
2025-07-24 23:34:35 +08:00
|
|
|
|
this.smsForm.type=1;
|
|
|
|
|
|
this.smsForm.serviceCode="";
|
|
|
|
|
|
this.smsForm.period=undefined;
|
|
|
|
|
|
this.reloadSmsList();
|
|
|
|
|
|
this.handleGetPrice(this.smsForm.type);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-07-12 15:34:14 +08:00
|
|
|
|
},
|
|
|
|
|
|
reloadList() {
|
|
|
|
|
|
this.query.pageIndex = 1;
|
|
|
|
|
|
this.getMyProxy();
|
|
|
|
|
|
},
|
|
|
|
|
|
getMyProxy() {
|
2025-07-29 18:15:29 +08:00
|
|
|
|
console.log("触发getMyProxy");
|
2025-07-12 15:34:14 +08:00
|
|
|
|
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
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2025-07-29 18:15:29 +08:00
|
|
|
|
if(this.query.total!==total){
|
2025-07-12 15:34:14 +08:00
|
|
|
|
this.query.total = total;
|
2025-07-29 18:15:29 +08:00
|
|
|
|
}
|
2025-07-12 15:34:14 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.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();
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
// 切换状态
|
2025-07-28 18:06:46 +08:00
|
|
|
|
async onSwitchChange(val,row,index){
|
|
|
|
|
|
let text = val?'启用':'取消';
|
|
|
|
|
|
|
|
|
|
|
|
this.$vs.dialog({
|
|
|
|
|
|
color:"primary",
|
|
|
|
|
|
title:"提示",
|
2025-07-29 18:15:29 +08:00
|
|
|
|
text: `确定${text}自动续期吗?`,
|
2025-07-28 18:06:46 +08:00
|
|
|
|
acceptText:"确定",
|
|
|
|
|
|
accept:() => this.doSwitchProxyAutoRenewal(row,val)
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
// 代理自动续费修改changeStatus
|
|
|
|
|
|
doSwitchProxyAutoRenewal(row,val){
|
2025-07-12 15:34:14 +08:00
|
|
|
|
this.showLoading();
|
|
|
|
|
|
let data = JSON.stringify({
|
|
|
|
|
|
proxyId: row.id,
|
|
|
|
|
|
autoRenewal: val,
|
|
|
|
|
|
});
|
2025-07-28 18:06:46 +08:00
|
|
|
|
console.log('data:',data);
|
2025-07-12 15:34:14 +08:00
|
|
|
|
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();
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2025-07-28 18:06:46 +08:00
|
|
|
|
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天`;
|
|
|
|
|
|
|
2025-07-12 15:34:14 +08:00
|
|
|
|
this.$vs.dialog({
|
|
|
|
|
|
color:"primary",
|
|
|
|
|
|
title: `代理续期提示`,
|
2025-07-28 18:06:46 +08:00
|
|
|
|
text: `${tip},确定续期30天吗?`,
|
|
|
|
|
|
acceptText:"确定",
|
2025-07-12 15:34:14 +08:00
|
|
|
|
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();
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2025-07-24 23:34:35 +08:00
|
|
|
|
//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);
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2025-07-25 17:26:04 +08:00
|
|
|
|
//取消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();
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2025-07-28 18:06:46 +08:00
|
|
|
|
//长效号码续期状态修改
|
|
|
|
|
|
async handleSmsRenew(val,row,index){
|
|
|
|
|
|
const newState=val?1:2;
|
|
|
|
|
|
const originalState = row.autoRenewal;
|
2025-07-29 18:15:29 +08:00
|
|
|
|
const title=val?`确定要对[${row.phone}]的短信服务续期吗?`:"确认取消自动续费吗?";
|
2025-07-28 18:06:46 +08:00
|
|
|
|
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();
|
|
|
|
|
|
})
|
2025-07-29 18:15:29 +08:00
|
|
|
|
},
|
|
|
|
|
|
//清理代理
|
|
|
|
|
|
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();
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
2025-07-12 15:34:14 +08:00
|
|
|
|
},
|
|
|
|
|
|
});
|
|
|
|
|
|
</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;
|
|
|
|
|
|
}
|
2025-07-24 23:34:35 +08:00
|
|
|
|
|
|
|
|
|
|
.form-item{
|
|
|
|
|
|
padding-top: 10px
|
|
|
|
|
|
}
|
2025-07-28 18:06:46 +08:00
|
|
|
|
|
|
|
|
|
|
.content-conter-container{
|
|
|
|
|
|
height: calc(100% - 45px);
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.content-conter-footer{
|
|
|
|
|
|
height: 45px;
|
|
|
|
|
|
}
|
2025-07-12 15:34:14 +08:00
|
|
|
|
</style>
|
|
|
|
|
|
</html>
|