subweb/src/views/home/SubTable.vue

310 lines
11 KiB
Vue
Raw Normal View History

2023-12-13 17:31:39 +08:00
<template>
<div class="row g-4 custom-div">
<div class="col-12 col-lg-12 pt-4 pt-lg-0">
<div class="tab-content p-0">
<div class="tab-pane fade show active">
<div class="card mb-4">
<div class="card-body">
<div class="row mb-3 g-3">
<div class="col-12 col-md-12">
<label class="form-label" for="add-user-email">订阅链接</label>
<textarea class="form-control" v-model.trim="urls" :placeholder="placeholder" rows="3"></textarea>
</div>
<div class="col-5 col-md-6">
<label class="form-label" for="client">客户端</label>
<select class="form-select" id="client" v-model="target" @change="selectTarget">
<option v-for="option in targetOptions" :key="option" :value="option.value">
{{ option.text }}
</option>
</select>
</div>
<div class="col-7 col-md-6">
<label class="form-label" for="api">后端服务</label>
<select class="form-select" id="api" @change="selectApi">
<option :value="apiUrl">
{{ apiUrl }}
</option>
<option value="manual">自定义后端 API 地址</option>
</select>
</div>
<div class="col-12 col-md-12" v-if="isShowManualApiUrl">
<input class="form-control" placeholder="自定义后端 API 地址示例https://sub.ops.ci" v-model="api" />
</div>
<div class="col-8 col-md-10">
<label class="form-label" for="remote">远程配置</label>
<select class="form-select" id="remote" @change="selectRemoteConfig">
<option value="">默认配置</option>
<option v-for="option in remoteConfigOptions" :key="option" :value="option.value">
{{ option.text }}
</option>
<option value="manual">自定义远程配置地址</option>
</select>
</div>
<div class="col-4 col-md-2">
<label class="form-label">&nbsp;</label>
<button type="button" class="btn btn-warning" @click="showMoreConfig">参数</button>
</div>
<div class="col-12 col-md-12" v-if="isShowRemoteConfig">
<input class="form-control" placeholder="自定义远程配置地址:" v-model="remoteConfig" />
</div>
<div class="col-12 col-md-12" v-if="isShowMoreConfig">
<label class="form-label" for="add-user-email">可选参数</label>
<div class="row g-3">
<div class="col-12 col-md-12">
<input class="form-control" placeholder="Include: 可选" v-model="moreConfig.include" />
</div>
<div class="col-12 col-md-12">
2023-12-24 00:27:23 +08:00
<input class="form-control" placeholder="Exclude: 可选" v-model="moreConfig.exclude" />
2023-12-13 17:31:39 +08:00
</div>
<div class="col-md check-div" :style="{ display: 'flex', flexWrap: 'wrap' }">
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="emoji" v-model="moreConfig.emoji" />
<label class="form-check-label" for="emoji">Emoji</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="udp" v-model="moreConfig.udp" />
<label class="form-check-label" for="udp">开启UDP</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="sort" v-model="moreConfig.sort" />
<label class="form-check-label" for="sort">排序节点</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="scv" v-model="moreConfig.scv" />
<label class="form-check-label" for="scv">关闭证书检查</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="nodelist" v-model="moreConfig.list" />
<label class="form-check-label" for="nodelist">Node List</label>
</div>
</div>
</div>
</div>
<div class="col-12 col-md-12">
<div class="divider divider-dashed">
<div class="divider-text"><i class="ti ti-refresh" style="color: gray"></i></div>
</div>
</div>
<div class="col-12 col-md-10">
<input class="form-control" placeholder="点击转换链接" v-model.trim="result.subUrl" />
</div>
<div class="col-12 col-md-2">
<button type="button" class="btn btn-success" @click="getSubUrl()">转换</button>
</div>
<div class="col-12 col-md-10">
<input class="form-control" placeholder="点击获取短链" v-model.trim="result.shortUrl" />
</div>
<div class="col-12 col-md-2">
<button type="button" class="btn btn-primary" @click="getShortUrl()">短链</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { showLoading, hideLoading } from '@/components/loading';
import { getSubLink, regexCheck } from './index.js';
import { request } from '@/network';
import showNotification from '@/components/notification';
export default {
name: 'SubTable',
setup() {
const DEFAULT_MORECONFIG = {
include: '',
exclude: '',
emoji: true,
udp: true,
sort: false,
scv: false,
list: false,
};
return {
DEFAULT_MORECONFIG,
};
},
data() {
return {
placeholder: '多订阅链接或节点请确保每行一条\n支持手动使用"|"分割多链接或节点',
targetOptions: [
{ value: 'clash', text: 'Clash' },
{ value: 'clashr', text: 'ClashR' },
{ value: 'v2ray', text: 'V2Ray' },
{ value: 'quan', text: 'Quantumult' },
{ value: 'quanx', text: 'Quantumult X' },
{ value: 'surge&ver=2', text: 'SurgeV2' },
{ value: 'surge&ver=3', text: 'SurgeV3' },
{ value: 'surge&ver=4', text: 'SurgeV4' },
{ value: 'surfboard', text: 'Surfboard' },
{ value: 'ss', text: 'SS (SIP002)' },
{ value: 'sssub', text: 'SS Android' },
{ value: 'ssd', text: 'SSD' },
{ value: 'ssr', text: 'SSR' },
{ value: 'loon', text: 'Loon' },
],
apiUrl: window.config.apiUrl,
shortUrl: window.config.shortUrl,
remoteConfigOptions: window.config.remoteConfigOptions,
moreConfig: this.DEFAULT_MORECONFIG,
isShowMoreConfig: false,
isShowManualApiUrl: false,
isShowRemoteConfig: false,
result: {
subUrl: '',
shortUrl: '',
},
urls: [],
api: window.config.apiUrl,
target: 'clash',
remoteConfig: '',
};
},
methods: {
showMoreConfig() {
this.isShowMoreConfig = !this.isShowMoreConfig;
},
selectApi(event) {
if (event.target.value == 'manual') {
this.api = '';
this.isShowManualApiUrl = true;
} else {
this.isShowManualApiUrl = false;
this.api = event.target.value;
}
},
selectRemoteConfig(event) {
if (event.target.value == 'manual') {
this.remoteConfig = '';
this.isShowRemoteConfig = true;
} else {
this.isShowRemoteConfig = false;
this.remoteConfig = event.target.value;
}
},
toCopy(url, title) {
if (!url) {
this.$showDialog('warning', '注意', '复制失败 内容为空');
return;
}
var copyInput = document.createElement('input');
copyInput.setAttribute('value', url);
document.body.appendChild(copyInput);
copyInput.select();
try {
var copyed = document.execCommand('copy');
if (copyed) {
document.body.removeChild(copyInput);
showNotification(title + ' 复制成功', '成功');
}
} catch {
this.$showDialog('warning', '注意', '复制失败,请检查浏览器兼容性');
}
},
getConverter() {
if (this.urls == '') {
this.$showDialog('warning', '注意', '请输入订阅链接或节点');
return false;
}
if (!regexCheck(this.api)) {
this.$showDialog('warning', '注意', '请输入自定义后端 API 地址,或选择默认后端服务。');
return false;
}
if (this.remoteConfig == '' && this.isShowRemoteConfig) {
this.$showDialog('warning', '注意', '请输入远程配置地址,或选择默认配置。');
return false;
}
if (this.api.endsWith('/')) {
// 自动删除末尾的斜杠
this.api = this.api.slice(0, -1);
}
this.result.subUrl = getSubLink(
this.urls,
this.api,
this.target,
this.remoteConfig,
this.isShowMoreConfig,
this.moreConfig
);
return true;
},
getSubUrl() {
if (!this.getConverter()) {
return;
}
this.toCopy(this.result.subUrl, '订阅链接');
},
getShortUrl() {
if (!this.getConverter()) {
return;
}
let data = new FormData();
data.append('longUrl', btoa(this.result.subUrl));
showLoading();
request({
method: 'post',
url: this.shortUrl + '/short',
header: {
'Content-Type': 'application/form-data; charset=utf-8',
},
data: data,
})
.then((res) => {
if (res.data.Code === 1 && res.data.ShortUrl !== '') {
this.result.shortUrl = res.data.ShortUrl;
this.toCopy(this.result.shortUrl, '短链接');
}
hideLoading();
})
.catch(() => {
this.$showDialog('error', '失败', '短链接生成失败 请检查短链接服务是否可用');
hideLoading();
});
},
},
};
</script>
<style scoped>
.custom-div {
width: 100%;
margin: 0 auto;
}
@media (min-width: 767.98px) {
.custom-div {
width: 90%;
margin: 0 auto;
}
}
@media (min-width: 991.98px) {
.custom-div {
width: 80%;
margin: 0 auto;
}
}
@media (min-width: 1199.98px) {
.custom-div {
width: 70%;
margin: 0 auto;
}
}
.btn {
width: 100%;
}
.check-div {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
height: 100%; /* 可以设置固定高度或者根据需求调整 */
}
.divider {
margin: 1%;
}
</style>