510 lines
23 KiB
HTML
510 lines
23 KiB
HTML
|
|
{{ template "page/head_start" .}}
|
|||
|
|
<style>
|
|||
|
|
/* 复制自 settings.html 的样式,确保布局响应式一致 */
|
|||
|
|
@media (min-width: 769px) {
|
|||
|
|
.ant-layout-content {
|
|||
|
|
margin: 24px 16px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/* 移动端适配 */
|
|||
|
|
@media (max-width: 768px) {
|
|||
|
|
.ant-layout-content {
|
|||
|
|
margin: 10px 10px;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
/* 调整表格卡片样式 */
|
|||
|
|
.ant-card-body {
|
|||
|
|
padding: 24px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 针对暗色主题(dark-theme)的 a-alert 强制样式覆盖 */
|
|||
|
|
/* 1、去掉暗色主题下 Modal 的默认灰色遮罩(解决“灰蒙蒙”问题) */
|
|||
|
|
/*
|
|||
|
|
.dark-theme .ant-modal-mask {
|
|||
|
|
background: transparent !important; /* 变为完全透明,更通透 */
|
|||
|
|
} */
|
|||
|
|
|
|||
|
|
/* 1、只去掉这个弹窗的灰色遮罩 */
|
|||
|
|
.dark-theme .ping-check-modal + .ant-modal-wrap .ant-modal-mask,
|
|||
|
|
.dark-theme .ping-check-modal .ant-modal-mask {
|
|||
|
|
background: transparent !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 2、弹窗中 info 提示框 强制使用浅色背景 + 蓝色边框 */
|
|||
|
|
.ant-modal .ant-alert-info {
|
|||
|
|
background-color: #f0f8ff !important; /* 浅蓝色背景 */
|
|||
|
|
border: 1px solid #91d5ff !important; /* 蓝色边框 */
|
|||
|
|
border-radius: 8px; /* 圆角更好看 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 3、弹窗中 a-alert 内所有文字,强制为深色(防止发灰/发白) */
|
|||
|
|
.ant-modal .ant-alert-info,
|
|||
|
|
.ant-modal .ant-alert-info * {
|
|||
|
|
color: #333333 !important; /* 深灰文字,更清晰 */
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 4、强制 info-circle 图标为标准 Ant 蓝色(恢复你之前看到的效果) */
|
|||
|
|
.ant-modal .ant-alert-info .anticon-info-circle {
|
|||
|
|
color: #1890ff !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 5、部分浏览器会把 svg 填充色变灰,这里强制修正 */
|
|||
|
|
.ant-modal .ant-alert-info svg {
|
|||
|
|
fill: #1890ff !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
</style>
|
|||
|
|
{{ template "page/head_end" .}}
|
|||
|
|
|
|||
|
|
{{ template "page/body_start" .}}
|
|||
|
|
<a-layout id="app" v-cloak :class="themeSwitcher.currentTheme">
|
|||
|
|
<a-sidebar></a-sidebar>
|
|||
|
|
|
|||
|
|
<a-layout id="content-layout">
|
|||
|
|
<a-layout-content>
|
|||
|
|
<a-spin :spinning="loading" tip="加载中...">
|
|||
|
|
<transition name="list" appear>
|
|||
|
|
<a-row :gutter="[isMobile ? 8 : 16, isMobile ? 0 : 12]">
|
|||
|
|
<a-col>
|
|||
|
|
<a-card hoverable>
|
|||
|
|
<a-row>
|
|||
|
|
<a-col :span="24">
|
|||
|
|
<a-space :size="15">
|
|||
|
|
|
|||
|
|
<a-button type="primary" @click="openAddModal(0)">
|
|||
|
|
<a-icon type="plus"></a-icon> 添加〔被控端 VPS〕
|
|||
|
|
</a-button>
|
|||
|
|
|
|||
|
|
<a-button type="primary" style="cursor: default;">
|
|||
|
|
<a-icon type="info-circle"></a-icon>
|
|||
|
|
当前已绑定:[[ normalCount ]] 台 (最多可绑:[[ maxLimit ]] 台)
|
|||
|
|
</a-button>
|
|||
|
|
|
|||
|
|
<a-button type="default" icon="reload" @click="getServers">
|
|||
|
|
刷新列表
|
|||
|
|
</a-button>
|
|||
|
|
|
|||
|
|
<a-button type="primary" icon="setting" @click="goToTgSettings">
|
|||
|
|
配置本机“主控机器人”
|
|||
|
|
</a-button>
|
|||
|
|
|
|||
|
|
</a-space>
|
|||
|
|
</a-col>
|
|||
|
|
</a-row>
|
|||
|
|
|
|||
|
|
<a-table :columns="columns" :data-source="normalServersPage" :row-key="record => record.ID" :pagination="normalPagination" @change="handleNormalTableChange" style="margin-top: 20px">
|
|||
|
|
<template slot="action" slot-scope="text, record">
|
|||
|
|
<a-space>
|
|||
|
|
<a-button type="danger" size="small" icon="delete" @click="deleteServer(record)">删除</a-button>
|
|||
|
|
</a-space>
|
|||
|
|
</template>
|
|||
|
|
</a-table>
|
|||
|
|
</a-card>
|
|||
|
|
|
|||
|
|
<a-card hoverable title="一键部署中转节点">
|
|||
|
|
<a-row>
|
|||
|
|
<a-col :span="24">
|
|||
|
|
<div style="margin-bottom: 15px; color: #666;">
|
|||
|
|
<a-icon type="info-circle"></a-icon>
|
|||
|
|
说明:在此添加远程中转机(落地机)信息,点击“一键部署”即可自动完成:
|
|||
|
|
远程Socks创建 --> 本机路由配置 --> 本机入口创建 --> 生成“二维码和链接”。
|
|||
|
|
</div>
|
|||
|
|
<a-space :size="15">
|
|||
|
|
<a-button type="primary" @click="openAddModal(1)">
|
|||
|
|
<a-icon type="plus"></a-icon> 添加〔中转机 VPS〕
|
|||
|
|
</a-button>
|
|||
|
|
|
|||
|
|
<a-button type="primary" style="cursor: default;">
|
|||
|
|
<a-icon type="info-circle"></a-icon>
|
|||
|
|
当前已绑定:[[ transitCount ]] 台 (最多可绑:[[ maxLimit ]] 台)
|
|||
|
|
</a-button>
|
|||
|
|
|
|||
|
|
<a-button type="default" icon="reload" @click="getServers">
|
|||
|
|
刷新列表
|
|||
|
|
</a-button>
|
|||
|
|
|
|||
|
|
<a-button type="primary" icon="thunderbolt" @click="openCheckModal">
|
|||
|
|
检测中转节点“连通性”
|
|||
|
|
</a-button>
|
|||
|
|
</a-space>
|
|||
|
|
</a-col>
|
|||
|
|
</a-row>
|
|||
|
|
|
|||
|
|
<a-table :columns="columns" :data-source="transitServersPage" :row-key="record => record.ID" :pagination="transitPagination" @change="handleTransitTableChange" :scroll="isMobile ? { x: 'max-content' } : {}" style="margin-top: 20px">
|
|||
|
|
<template slot="action" slot-scope="text, record">
|
|||
|
|
<a-space>
|
|||
|
|
<a-button v-if="record.LastLink || record.last_link" type="default" size="small" icon="link" @click="getLastLink(record)" :loading="record.linkLoading">
|
|||
|
|
获取上次链接
|
|||
|
|
</a-button>
|
|||
|
|
|
|||
|
|
<a-button type="primary" size="small" icon="rocket" @click="setupRelay(record)" :loading="record.setupLoading" :type="(record.LastLink || record.last_link) ? 'dashed' : 'primary'">
|
|||
|
|
[[ (record.LastLink || record.last_link) ? '重新部署' : '一键部署中转' ]]
|
|||
|
|
</a-button>
|
|||
|
|
|
|||
|
|
<a-button type="danger" size="small" icon="delete" @click="deleteServer(record)">删除</a-button>
|
|||
|
|
</a-space>
|
|||
|
|
</template>
|
|||
|
|
</a-table>
|
|||
|
|
</a-card>
|
|||
|
|
|
|||
|
|
</a-col>
|
|||
|
|
</a-row>
|
|||
|
|
</transition>
|
|||
|
|
</a-spin>
|
|||
|
|
</a-layout-content>
|
|||
|
|
</a-layout>
|
|||
|
|
|
|||
|
|
<a-modal v-model="visible" :title="formType === 1 ? '添加〔中转机 VPS〕' : '添加〔被控端 VPS〕'" @ok="submitServer" :confirm-loading="modalLoading">
|
|||
|
|
<a-form :model="form" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }">
|
|||
|
|
<a-form-item label="备注名称">
|
|||
|
|
<a-input v-model="form.name" placeholder="例如:香港鸡"></a-input>
|
|||
|
|
</a-form-item>
|
|||
|
|
<a-form-item label="面板地址">
|
|||
|
|
<a-input v-model="form.url" placeholder="https://aaa.xxxx.com:54321/nbxuiplus"></a-input>
|
|||
|
|
<span style="font-size: 12px; color: #888;">* 必须包含协议头 (https://) 和 “端口 + 路径”</span>
|
|||
|
|
</a-form-item>
|
|||
|
|
<a-form-item label="用 户 名">
|
|||
|
|
<a-input v-model="form.username" placeholder="面板登录用户名"></a-input>
|
|||
|
|
</a-form-item>
|
|||
|
|
<a-form-item label="登录密码">
|
|||
|
|
<a-input-password v-model="form.password" placeholder="面板登录密码"></a-input-password>
|
|||
|
|
</a-form-item>
|
|||
|
|
</a-form>
|
|||
|
|
|
|||
|
|
<div v-if="formType === 0" style="margin-top: 20px; color: red; font-style: italic; text-align: center; line-height: 1.6;">
|
|||
|
|
1、此功能用于集中管理多个〔X-Panel 面板〕,<br>
|
|||
|
|
2、是通过在后台〔配置绑定机器人〕去管理的,<br>
|
|||
|
|
3、若在输入框您已经添加了〔被控端 的 VPS 信息〕,<br>
|
|||
|
|
4、则您不能在对应的那台 VPS 中去绑定任何其他机器人,<br>
|
|||
|
|
5、并且,您的〔被控端 VPS〕面板不能去开启“两步验证”。
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div v-else style="margin-top: 20px; color: #1890ff; font-style: italic; text-align: center; line-height: 1.6;">
|
|||
|
|
1、此功能仅用于建立〔VLESS Reality --> Socks5〕中转链路,<br>
|
|||
|
|
2、在此处添加的〔中转/落地机 VPS〕面板不能去开启“两步验证”,<br>
|
|||
|
|
3、在添加输入信息后,请点击列表中的“一键部署”按钮即可去使用,<br>
|
|||
|
|
4、而“中转/落地机”无需做任何设置,只需确保防火墙放行端口即可,<br>
|
|||
|
|
5、请勿在连“本机节点”时去进行〔一键部署〕,因“Xray重启”会有卡顿,<br>
|
|||
|
|
6、注:在已经创建好“中转节点”之后,勿去随意更改“用户Email + 端口”。
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
</a-modal>
|
|||
|
|
|
|||
|
|
<a-modal v-model="resultModalVisible" :title="resultTitle" :footer="null" :width="450">
|
|||
|
|
<div style="text-align: center;">
|
|||
|
|
|
|||
|
|
<div style="text-align: left; color: #555; white-space: pre-wrap; line-height: 1.6; margin-bottom: 20px;">[[ resultSubtitle ]]</div>
|
|||
|
|
|
|||
|
|
<p style="color: #888; margin-bottom: 5px;">链路:本机(Reality) --->> 中转机(Socks) --->> 互联网</p>
|
|||
|
|
|
|||
|
|
<div
|
|||
|
|
id="qrcode-canvas"
|
|||
|
|
style="display: flex; justify-content: center; margin: 10px 0; cursor: pointer;"
|
|||
|
|
title="点击复制链接"
|
|||
|
|
@click="copyLink"
|
|||
|
|
></div>
|
|||
|
|
<p style="font-size: 12px; color: #aaa;">(点击二维码或链接即可复制)</p>
|
|||
|
|
|
|||
|
|
<p style="font-weight:bold; margin-top:15px; text-align: left;">👇 VLESS Reality 中转链接:</p>
|
|||
|
|
<a-input v-model="resultLink" read-only @click="copyLink">
|
|||
|
|
<a-icon slot="addonAfter" type="copy" @click="copyLink" style="cursor: pointer;"/>
|
|||
|
|
</a-input>
|
|||
|
|
</div>
|
|||
|
|
</a-modal>
|
|||
|
|
|
|||
|
|
<a-modal v-model="checkModalVisible" title="检测中转节点“连通性”" :footer="null" width="700px">
|
|||
|
|
|
|||
|
|
<!-- 这里是提示框:在暗黑模式下文字看不清的地方 -->
|
|||
|
|
<a-alert
|
|||
|
|
type="info"
|
|||
|
|
show-icon
|
|||
|
|
bordered
|
|||
|
|
style="margin-bottom: 15px;"
|
|||
|
|
>
|
|||
|
|
<template slot="message">
|
|||
|
|
此功能通过 TCP Ping 模拟 v2rayN 测试原理,<br><br>
|
|||
|
|
检测〔上次部署生成的链接〕对应的端口是否通畅?
|
|||
|
|
</template>
|
|||
|
|
</a-alert>
|
|||
|
|
|
|||
|
|
<a-table
|
|||
|
|
:columns="checkColumns"
|
|||
|
|
:data-source="checkList"
|
|||
|
|
:row-key="record => record.ID"
|
|||
|
|
:pagination="false"
|
|||
|
|
size="small"
|
|||
|
|
>
|
|||
|
|
<template slot="status" slot-scope="text, record">
|
|||
|
|
<span v-if="record.pingLoading">
|
|||
|
|
<a-icon type="loading" /> 检测中...
|
|||
|
|
</span>
|
|||
|
|
<span v-else>
|
|||
|
|
<a-tag v-if="record.pingResult === undefined">待检测</a-tag>
|
|||
|
|
<a-tag v-else-if="record.pingResult > 0" color="green">正常: [[ record.pingResult ]]ms</a-tag>
|
|||
|
|
<a-tag v-else color="red">无效 / 不通</a-tag>
|
|||
|
|
</span>
|
|||
|
|
</template>
|
|||
|
|
<template slot="action" slot-scope="text, record">
|
|||
|
|
<a-button type="primary" size="small" ghost @click="performPing(record)" :loading="record.pingLoading">
|
|||
|
|
立即检测
|
|||
|
|
</a-button>
|
|||
|
|
</template>
|
|||
|
|
</a-table>
|
|||
|
|
<div style="margin-top: 20px; text-align: right;">
|
|||
|
|
<a-button @click="checkModalVisible = false">关闭</a-button>
|
|||
|
|
</div>
|
|||
|
|
</a-modal>
|
|||
|
|
|
|||
|
|
</a-layout>
|
|||
|
|
|
|||
|
|
{{template "page/body_scripts" .}}
|
|||
|
|
{{template "component/aSidebar" .}}
|
|||
|
|
{{template "component/aThemeSwitch" .}}
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
// 初始化 Vue 实例
|
|||
|
|
const app = new Vue({
|
|||
|
|
// 重要:修改 Vue 分隔符,防止与 Go 模板引擎冲突
|
|||
|
|
delimiters: ['[[', ']]'],
|
|||
|
|
// 【关键修复】:引入 MediaQueryMixin,这能让布局像 settings.html 一样自动适应,消除异常间隙
|
|||
|
|
mixins: [MediaQueryMixin],
|
|||
|
|
el: '#app',
|
|||
|
|
data: {
|
|||
|
|
themeSwitcher, // 引入主题切换数据
|
|||
|
|
loading: false,
|
|||
|
|
modalLoading: false,
|
|||
|
|
visible: false,
|
|||
|
|
checkModalVisible: false,
|
|||
|
|
resultModalVisible: false,
|
|||
|
|
resultTitle: '部署结果',
|
|||
|
|
resultSubtitle: '',
|
|||
|
|
resultLink: '',
|
|||
|
|
|
|||
|
|
checkList: [],
|
|||
|
|
checkColumns: [
|
|||
|
|
{ title: 'ID', dataIndex: 'ID', key: 'ID', width: 60 },
|
|||
|
|
{ title: '节点名称', dataIndex: 'name', key: 'name' },
|
|||
|
|
{ title: '状态', key: 'status', scopedSlots: { customRender: 'status' } },
|
|||
|
|
{ title: '操作', key: 'action', scopedSlots: { customRender: 'action' }, align: 'right' }
|
|||
|
|
],
|
|||
|
|
|
|||
|
|
servers: [],
|
|||
|
|
// 【修改这里】:定义两个独立的计数变量
|
|||
|
|
normalCount: 0, // 被控端数量
|
|||
|
|
transitCount: 0, // 中转机数量
|
|||
|
|
maxLimit: 0,
|
|||
|
|
// 【新增数据字段结束】
|
|||
|
|
form: {
|
|||
|
|
name: '',
|
|||
|
|
url: '',
|
|||
|
|
username: '',
|
|||
|
|
password: '',
|
|||
|
|
type: 0
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 用于控制模态框显示的类型状态 (0=被控端, 1=中转机)
|
|||
|
|
formType: 0,
|
|||
|
|
// 【分页新增】:分页配置
|
|||
|
|
paginationConfig: {
|
|||
|
|
pageSize: 5, // 每页显示5条
|
|||
|
|
showSizeChanger: false,
|
|||
|
|
hideOnSinglePage: true,
|
|||
|
|
},
|
|||
|
|
// 【分页新增】:当前页数
|
|||
|
|
normalCurrentPage: 1,
|
|||
|
|
transitCurrentPage: 1,
|
|||
|
|
|
|||
|
|
// 表格列定义
|
|||
|
|
columns: [
|
|||
|
|
{ title: 'ID', dataIndex: 'ID', key: 'ID', width: 80 },
|
|||
|
|
{ title: '备注名称', dataIndex: 'name', key: 'name' },
|
|||
|
|
{ title: '面板地址', dataIndex: 'url', key: 'url' },
|
|||
|
|
{ title: '用户名', dataIndex: 'username', key: 'username' },
|
|||
|
|
{
|
|||
|
|
title: '添加时间',
|
|||
|
|
dataIndex: 'CreatedAt', // 修改点1:这里必须改成大写的 CreatedAt
|
|||
|
|
key: 'CreatedAt',
|
|||
|
|
width: 180,
|
|||
|
|
// 修改点2:添加格式化,把 "2023-11-21T..." 变成 "2023-11-21 10:00"
|
|||
|
|
customRender: (text) => {
|
|||
|
|
if (!text) return '';
|
|||
|
|
// 简单处理:去掉 T,截取前19位
|
|||
|
|
return text.replace('T', ' ').substring(0, 19);
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
{ title: '操作', key: 'action', scopedSlots: { customRender: 'action' }, width: 220 }
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
computed: {
|
|||
|
|
// 过滤普通被控端 (type=0)
|
|||
|
|
normalServers() {
|
|||
|
|
return this.servers.filter(s => s.type === 0 || s.type === undefined);
|
|||
|
|
},
|
|||
|
|
// 过滤中转机 (type=1)
|
|||
|
|
transitServers() {
|
|||
|
|
return this.servers.filter(s => s.type === 1);
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 【分页核心】:普通被控端 - 当前页数据 (返回空列表)
|
|||
|
|
normalServersPage() {
|
|||
|
|
// 因为 this.normalServers 始终为空,所以这里返回空
|
|||
|
|
return [];
|
|||
|
|
},
|
|||
|
|
// 【分页核心】:中转机 - 当前页数据 (返回空列表)
|
|||
|
|
transitServersPage() {
|
|||
|
|
// 因为 this.transitServers 始终为空,所以这里返回空
|
|||
|
|
return [];
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 【分页核心】:分页对象 (total 始终为 0)
|
|||
|
|
normalPagination() {
|
|||
|
|
return {...this.paginationConfig, current: this.normalCurrentPage, total: 0};
|
|||
|
|
},
|
|||
|
|
// 【分页核心】:分页对象 (total 始终为 0)
|
|||
|
|
transitPagination() {
|
|||
|
|
return {...this.paginationConfig, current: this.transitCurrentPage, total: 0};
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
methods: {
|
|||
|
|
// 【新增跳转逻辑】
|
|||
|
|
// 点击后跳转到 settings 页面,并带上 query 参数 tab=telegram
|
|||
|
|
goToTgSettings() {
|
|||
|
|
window.location.href = "./settings?tab=telegram";
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 【分页新增】:处理普通列表分页切换
|
|||
|
|
handleNormalTableChange(pagination) {
|
|||
|
|
this.normalCurrentPage = pagination.current;
|
|||
|
|
},
|
|||
|
|
// 【分页新增】:处理中转列表分页切换
|
|||
|
|
handleTransitTableChange(pagination) {
|
|||
|
|
this.transitCurrentPage = pagination.current;
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 【拦截方法】:拦截获取链接操作
|
|||
|
|
getLastLink(record) {
|
|||
|
|
// 【免费版】:拦截获取链接操作
|
|||
|
|
this.$message.warning("〔免费基础版〕不支持此操作");
|
|||
|
|
return;
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 执行一键中转部署
|
|||
|
|
async setupRelay(record) {
|
|||
|
|
// 【免费版修改】:拦截部署操作
|
|||
|
|
this.$message.warning("〔免费基础版〕不支持此操作");
|
|||
|
|
return;
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 获取服务器列表
|
|||
|
|
async getServers() {
|
|||
|
|
// 1. 模拟加载结束
|
|||
|
|
this.loading = false;
|
|||
|
|
// 2. 强制清空列表
|
|||
|
|
this.servers = [];
|
|||
|
|
// 3. 【关键】:强制设置数量和额度为 0
|
|||
|
|
this.normalCount = 0;
|
|||
|
|
this.transitCount = 0;
|
|||
|
|
this.maxLimit = 0; // 强制显示“最多可绑:0 台”
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
|
|||
|
|
// 打开添加弹窗
|
|||
|
|
// openAddModal 方法接收 type 参数
|
|||
|
|
// type: 0 = 普通被控端, 1 = 中转机
|
|||
|
|
openAddModal(type = 0) {
|
|||
|
|
// 1. 设置当前模态框的 UI 类型
|
|||
|
|
this.formType = type;
|
|||
|
|
|
|||
|
|
// 2. 初始化表单,并将 type 写入表单数据中
|
|||
|
|
this.form = {
|
|||
|
|
name: '',
|
|||
|
|
url: 'https://',
|
|||
|
|
username: '',
|
|||
|
|
password: '',
|
|||
|
|
type: type // 【关键】:这里确保提交给后端的数据包含正确的类型
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
this.visible = true;
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 提交添加请求
|
|||
|
|
async submitServer() {
|
|||
|
|
|
|||
|
|
// 1. 先关闭刚才填写的模态框,
|
|||
|
|
this.visible = false;
|
|||
|
|
|
|||
|
|
// 2. 使用 Vue 的 createElement 函数构建支持 HTML 的提示内容
|
|||
|
|
const h = this.$createElement;
|
|||
|
|
|
|||
|
|
// 3. 弹出警告提示框
|
|||
|
|
this.$warning({
|
|||
|
|
title: '功能受限提示',
|
|||
|
|
okText: '知道了',
|
|||
|
|
// 【核心修改点 1】:调整弹窗宽度,使其足够容纳一行文字
|
|||
|
|
width: 580,
|
|||
|
|
// 这里定义提示框的具体内容和样式
|
|||
|
|
content: h('div', { style: 'margin-top: 10px; font-size: 15px; line-height: 1.6;' }, [ // 增加行高,提升阅读体验
|
|||
|
|
|
|||
|
|
// 第一段:设置底部外边距,模拟空行
|
|||
|
|
h('p', { style: 'margin-bottom: 15px;' }, '此项功能是“付费Pro版”专属功能,免费版不能用,'),
|
|||
|
|
|
|||
|
|
// 第二段:设置底部外边距,模拟空行
|
|||
|
|
h('p', { style: 'margin-bottom: 15px;' }, '请联系面板管理员〔购买授权码〕之后才能继续使用。'),
|
|||
|
|
|
|||
|
|
// 第三段:TG 链接(无需底部外边距)
|
|||
|
|
h('p', { style: 'color: #ff4d4f; font-weight: bold; margin-bottom: 0;' }, [
|
|||
|
|
'----->>> “授权码购买”机器人:',
|
|||
|
|
h('a', {
|
|||
|
|
// 设置跳转链接到 Telegram
|
|||
|
|
attrs: {
|
|||
|
|
href: 'https://t.me/Buy_ShouQuan_Bot',
|
|||
|
|
target: '_blank' // 在新标签页打开
|
|||
|
|
},
|
|||
|
|
style: {
|
|||
|
|
color: '#1890ff', // 链接颜色
|
|||
|
|
fontWeight: 'bold',
|
|||
|
|
textDecoration: 'underline' // 链接下划线
|
|||
|
|
}
|
|||
|
|
}, '@Buy_ShouQuan_Bot')
|
|||
|
|
]),
|
|||
|
|
]),
|
|||
|
|
onOk() {}
|
|||
|
|
});
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 删除服务器
|
|||
|
|
deleteServer(record) {
|
|||
|
|
// 【免费版修改】:拦截删除操作
|
|||
|
|
this.$message.warning("〔免费基础版〕不支持此操作");
|
|||
|
|
return;
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 【拦截方法】:拦截【检测中转节点】操作
|
|||
|
|
openCheckModal() {
|
|||
|
|
// 【免费版修改】:拦截【检测中转节点】操作
|
|||
|
|
this.$message.warning("〔免费基础版〕不支持此操作");
|
|||
|
|
return;
|
|||
|
|
},
|
|||
|
|
copyLink() {
|
|||
|
|
if(!this.resultLink) return;
|
|||
|
|
const input = document.createElement('input');
|
|||
|
|
input.value = this.resultLink;
|
|||
|
|
document.body.appendChild(input);
|
|||
|
|
input.select();
|
|||
|
|
document.execCommand('Copy');
|
|||
|
|
document.body.removeChild(input);
|
|||
|
|
this.$message.success('复制成功');
|
|||
|
|
},
|
|||
|
|
performPing(record) {
|
|||
|
|
// 占位
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
mounted() {
|
|||
|
|
this.getServers();
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
</script>
|
|||
|
|
{{ template "page/body_end" .}}
|