mirror of https://github.com/dnomd343/sub-web
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
740 lines
24 KiB
740 lines
24 KiB
<template>
|
|
<div>
|
|
<el-row style="margin-top: 10px">
|
|
<el-col>
|
|
<el-card>
|
|
<div slot="header">
|
|
订阅转换
|
|
</div>
|
|
<el-container>
|
|
<el-form :model="form" label-width="80px" label-position="left" style="width: 100%">
|
|
<el-form-item label="模式选择:">
|
|
<el-radio v-model="advanced" label="1">基础模式</el-radio>
|
|
<el-radio v-model="advanced" label="2">高级模式</el-radio>
|
|
</el-form-item>
|
|
<el-form-item label="订阅链接:">
|
|
<el-input
|
|
v-model="form.sourceSubUrl"
|
|
type="textarea"
|
|
rows="3"
|
|
placeholder="支持订阅或ss/ssr/vmess链接"
|
|
@blur="saveSubUrl"
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item label="客户端:">
|
|
<el-select v-model="form.clientType" style="width: 100%">
|
|
<el-option v-for="(v, k) in options.clientTypes" :key="k" :label="k" :value="v"></el-option>
|
|
</el-select>
|
|
</el-form-item>
|
|
|
|
<div v-if="advanced === '2'">
|
|
<el-form-item label="后端地址:">
|
|
<el-autocomplete
|
|
style="width: 100%"
|
|
v-model="form.customBackend"
|
|
:fetch-suggestions="backendSearch"
|
|
placeholder="自定义后端服务地址"
|
|
>
|
|
</el-autocomplete>
|
|
</el-form-item>
|
|
<el-form-item label="远程配置:">
|
|
<el-select
|
|
v-model="form.remoteConfig"
|
|
allow-create
|
|
filterable
|
|
placeholder="请选择"
|
|
style="width: 100%"
|
|
>
|
|
<el-option-group
|
|
v-for="group in options.remoteConfig"
|
|
:key="group.label"
|
|
:label="group.label"
|
|
>
|
|
<el-option
|
|
v-for="item in group.options"
|
|
:key="item.value"
|
|
:label="item.label"
|
|
:value="item.value"
|
|
></el-option>
|
|
</el-option-group>
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="选择节点:">
|
|
<el-input v-model="form.includeRemarks" placeholder="节点名包含的关键字,支持正则" />
|
|
</el-form-item>
|
|
<el-form-item label="排除节点:">
|
|
<el-input v-model="form.excludeRemarks" placeholder="节点名不包含的关键字,支持正则" />
|
|
</el-form-item>
|
|
<el-form-item label="文件名:">
|
|
<el-input v-model="form.filename" placeholder="返回的订阅文件名" />
|
|
</el-form-item>
|
|
<el-form-item label-width="0px">
|
|
<el-row type="flex" justify="end">
|
|
<el-button
|
|
style="margin-top: 1px; width: 80px; height: 32px;"
|
|
type="default"
|
|
@click="dialogCustomConfigVisible = true"
|
|
:loading="loading"
|
|
>添加配置</el-button>
|
|
<el-button
|
|
style="margin-top: 1px; width: 80px; height: 32px;"
|
|
type="default"
|
|
@click="dialogUploadConfigVisible = true"
|
|
:loading="loading"
|
|
>上传配置</el-button>
|
|
<el-popover placement="bottom" v-model="form.extraset" style="margin-left: 10px">
|
|
<el-row>
|
|
<el-checkbox v-model="form.emoji" label="Emoji图标"></el-checkbox>
|
|
</el-row>
|
|
<el-row>
|
|
<el-checkbox v-model="form.new_name" label="Clash新参数"></el-checkbox>
|
|
</el-row>
|
|
<el-row>
|
|
<el-checkbox v-model="form.udp" @change="needUdp = true" label="启用UDP"></el-checkbox>
|
|
</el-row>
|
|
<el-row>
|
|
<el-checkbox v-model="form.appendType" label="节点类型"></el-checkbox>
|
|
</el-row>
|
|
<el-row>
|
|
<el-checkbox v-model="form.sort" label="排序节点"></el-checkbox>
|
|
</el-row>
|
|
<el-row>
|
|
<el-checkbox v-model="form.fdn" label="过滤非法节点"></el-checkbox>
|
|
</el-row>
|
|
<el-row>
|
|
<el-checkbox v-model="form.tpl.clash.doh" label="Clash使用DoH"></el-checkbox>
|
|
</el-row>
|
|
<el-row>
|
|
<el-checkbox v-model="form.tpl.surge.doh" label="Surge使用DoH"></el-checkbox>
|
|
</el-row>
|
|
<el-row>
|
|
<el-checkbox v-model="form.nodeList" label="输出为Node List"></el-checkbox>
|
|
</el-row>
|
|
<el-button slot="reference">其他选项</el-button>
|
|
</el-popover>
|
|
</el-row>
|
|
</el-form-item>
|
|
</div>
|
|
|
|
<div style="margin-top: 50px"></div>
|
|
|
|
<el-divider content-position="center">
|
|
<i class="el-icon-magic-stick"></i>
|
|
</el-divider>
|
|
|
|
<el-form-item label="定制订阅:">
|
|
<el-input class="copy-content" disabled v-model="customSubUrl">
|
|
<el-button
|
|
slot="append"
|
|
v-clipboard:copy="customSubUrl"
|
|
v-clipboard:success="onCopy"
|
|
ref="copy-btn"
|
|
icon="el-icon-document-copy"
|
|
>复制</el-button>
|
|
</el-input>
|
|
</el-form-item>
|
|
<el-form-item label="订阅短链:">
|
|
<el-input class="copy-content" disabled v-model="curtomShortSubUrl">
|
|
<el-button
|
|
slot="append"
|
|
v-clipboard:copy="curtomShortSubUrl"
|
|
v-clipboard:success="onCopy"
|
|
ref="copy-btn"
|
|
icon="el-icon-document-copy"
|
|
>复制</el-button>
|
|
</el-input>
|
|
</el-form-item>
|
|
<el-form-item label-width="0px" style="margin-top: 40px; text-align: center">
|
|
<el-button
|
|
style="width: 120px"
|
|
type="danger"
|
|
@click="makeUrl"
|
|
:disabled="form.sourceSubUrl.length === 0"
|
|
>生成订阅链接</el-button>
|
|
<el-button
|
|
style="width: 120px"
|
|
type="danger"
|
|
@click="makeShortUrl"
|
|
:loading="loading"
|
|
:disabled="customSubUrl.length === 0"
|
|
>生成短链接</el-button>
|
|
</el-form-item>
|
|
<el-form-item label-width="0px" style="text-align: center">
|
|
<el-button
|
|
style="width: 120px"
|
|
type="primary"
|
|
@click="clashInstall"
|
|
:disabled="customSubUrl.length === 0"
|
|
>导入Clash</el-button>
|
|
<el-button
|
|
style="width: 120px"
|
|
type="primary"
|
|
@click="surgeInstall"
|
|
:disabled="customSubUrl.length === 0"
|
|
>导入Surge</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</el-container>
|
|
</el-card>
|
|
</el-col>
|
|
</el-row>
|
|
<el-dialog
|
|
title="自定义远程配置"
|
|
:visible.sync="dialogCustomConfigVisible"
|
|
:show-close="false"
|
|
:close-on-click-modal="false"
|
|
:close-on-press-escape="false"
|
|
width="500px"
|
|
>
|
|
<el-form label-position="left">
|
|
<el-form-item>
|
|
<el-input v-model="customConfig" placeholder="配置文件地址" />
|
|
</el-form-item>
|
|
</el-form>
|
|
<span slot="footer" class="dialog-footer">
|
|
<el-button @click="customConfig = ''; dialogCustomConfigVisible = false">取 消</el-button>
|
|
<el-button
|
|
type="primary"
|
|
@click="confirmCustomConfig"
|
|
:disabled="customConfig.length === 0"
|
|
>确 定</el-button>
|
|
</span>
|
|
</el-dialog>
|
|
<el-dialog
|
|
:visible.sync="dialogUploadConfigVisible"
|
|
:show-close="false"
|
|
:close-on-click-modal="false"
|
|
:close-on-press-escape="false"
|
|
width="700px"
|
|
>
|
|
<div slot="title">
|
|
上传远程配置
|
|
<el-popover trigger="hover" placement="right" style="margin-left: 10px">
|
|
<el-link type="primary" :href="sampleConfig" target="_blank" icon="el-icon-info">参考配置</el-link>
|
|
<i class="el-icon-question" slot="reference"></i>
|
|
</el-popover>
|
|
</div>
|
|
<el-form label-position="left">
|
|
<el-form-item prop="uploadConfig">
|
|
<el-input
|
|
v-model="uploadConfig"
|
|
type="textarea"
|
|
:autosize="{ minRows: 15, maxRows: 15}"
|
|
maxlength="5000"
|
|
show-word-limit
|
|
></el-input>
|
|
</el-form-item>
|
|
</el-form>
|
|
<div slot="footer" class="dialog-footer">
|
|
<el-button @click="uploadConfig = ''; dialogUploadConfigVisible = false">取 消</el-button>
|
|
<el-button
|
|
type="primary"
|
|
@click="confirmUploadConfig"
|
|
:disabled="uploadConfig.length === 0"
|
|
>确 定</el-button>
|
|
</div>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
const project = process.env.VUE_APP_PROJECT
|
|
const remoteConfigSample = process.env.VUE_APP_SUBCONVERTER_REMOTE_CONFIG
|
|
const githubRelease = process.env.VUE_APP_BACKEND_RELEASE
|
|
const defaultBackend = process.env.VUE_APP_SUBCONVERTER_DEFAULT_BACKEND + '/sub?'
|
|
const shortUrlBackend = process.env.VUE_APP_MYURLS_DEFAULT_BACKEND + '/short'
|
|
const configUploadBackend = process.env.VUE_APP_CONFIG_UPLOAD_BACKEND + '/config/upload'
|
|
|
|
export default {
|
|
data() {
|
|
return {
|
|
backendVersion: "",
|
|
advanced: "1",
|
|
|
|
// 是否为 PC 端
|
|
isPC: true,
|
|
|
|
options: {
|
|
clientTypes: {
|
|
Clash: "clash",
|
|
ClashR: "clashr",
|
|
Surge2: "surge&ver=2",
|
|
Surge3: "surge&ver=3",
|
|
Surge4: "surge&ver=4",
|
|
Surfboard: "surfboard",
|
|
Quantumult: "quan",
|
|
QuantumultX: "quanx",
|
|
SS: "ss",
|
|
SSR: "ssr",
|
|
SSD: "ssd",
|
|
Loon: "loon",
|
|
V2Ray: "v2ray",
|
|
SSAndroid: "sssub",
|
|
},
|
|
backendOptions: [{ value: "https://api.dnomd343.top/subc/sub?" }],
|
|
remoteConfig: [
|
|
{
|
|
label: "默认",
|
|
options: [
|
|
{
|
|
label: "缺省",
|
|
value: ""
|
|
}
|
|
]
|
|
},
|
|
{
|
|
label: "机场定制",
|
|
options: [
|
|
{
|
|
label: "ARK",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ark.ini"
|
|
},
|
|
{
|
|
label: "Ytoo",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ytoo.ini"
|
|
},
|
|
{
|
|
label: "YoYu",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/yoyu.ini"
|
|
},
|
|
{
|
|
label: "Maying",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/maying.ini"
|
|
},
|
|
{
|
|
label: "SoCloud",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/socloud.ini"
|
|
},
|
|
{
|
|
label: "rixCloud",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/rixcloud.ini"
|
|
},
|
|
{
|
|
label: "ssrCloud",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ssrcloud.ini"
|
|
},
|
|
{
|
|
label: "Nexitally",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/nexitally.ini"
|
|
},
|
|
{
|
|
label: "NyanCAT",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/nyancat.ini"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
label: "ACL4SSR",
|
|
options: [
|
|
{
|
|
label: "ACL4SSR 默认版",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ACL4SSR_Online.ini"
|
|
},
|
|
{
|
|
label: "ACL4SSR_Mini 精简版",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ACL4SSR_Online_Mini.ini"
|
|
},
|
|
{
|
|
label: "ACL4SSR_Full 全分组",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ACL4SSR_Online_Full.ini"
|
|
},
|
|
{
|
|
label: "ACL4SSR_NoAuto 无自动测速",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ACL4SSR_Online_NoAuto.ini"
|
|
},
|
|
{
|
|
label: "ACL4SSR_NoReject 无广告拦截",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ACL4SSR_Online_NoReject.ini"
|
|
},
|
|
{
|
|
label: "ACL4SSR_AdblockPlus 去广告",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ACL4SSR_Online_AdblockPlus.ini"
|
|
},
|
|
{
|
|
label: "ACL4SSR_Full_Netflix 全分组 奈飞全量",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ACL4SSR_Online_Full_Netflix.ini"
|
|
},
|
|
{
|
|
label: "ACL4SSR_Full_NoAuto 全分组 无自动测速",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ACL4SSR_Online_Full_NoAuto.ini"
|
|
},
|
|
{
|
|
label: "ACL4SSR_Full_AdblockPlus 全分组 去广告",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ACL4SSR_Online_Full_AdblockPlus.ini"
|
|
},
|
|
{
|
|
label: "ACL4SSR_Mini_NoAuto 精简版 无自动测速",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ACL4SSR_Online_Mini_NoAuto.ini"
|
|
},
|
|
{
|
|
label: "ACL4SSR_Mini_AdblockPlus 精简版 去广告",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ACL4SSR_Online_Mini_AdblockPlus.ini"
|
|
},
|
|
{
|
|
label: "ACL4SSR_Mini_Fallback 精简版 带故障转移",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ACL4SSR_Online_Mini_Fallback.ini"
|
|
},
|
|
{
|
|
label: "ACL4SSR_Mini_MultiMode 精简版 带故障转移 负载均衡",
|
|
value:
|
|
"https://sub.dnomd343.top/rules/ACL4SSR_Online_Mini_MultiMode.ini"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
form: {
|
|
sourceSubUrl: "",
|
|
clientType: "",
|
|
customBackend: "",
|
|
remoteConfig: "",
|
|
excludeRemarks: "",
|
|
includeRemarks: "",
|
|
filename: "",
|
|
emoji: true,
|
|
nodeList: false,
|
|
extraset: false,
|
|
sort: false,
|
|
udp: false,
|
|
tfo: false,
|
|
scv: false,
|
|
fdn: false,
|
|
appendType: false,
|
|
insert: false, // 是否插入默认订阅的节点,对应配置项 insert_url
|
|
new_name: true, // 是否使用 Clash 新字段
|
|
|
|
// tpl 定制功能
|
|
tpl: {
|
|
surge: {
|
|
doh: false // dns 查询是否使用 DoH
|
|
},
|
|
clash: {
|
|
doh: false
|
|
}
|
|
}
|
|
},
|
|
|
|
loading: false,
|
|
customSubUrl: "",
|
|
curtomShortSubUrl: "",
|
|
|
|
dialogCustomConfigVisible: false,
|
|
dialogUploadConfigVisible: false,
|
|
uploadConfig: "",
|
|
customConfig: "",
|
|
uploadPassword: "",
|
|
sampleConfig: remoteConfigSample,
|
|
|
|
needUdp: false, // 是否需要添加 udp 参数
|
|
};
|
|
},
|
|
created() {
|
|
document.title = "Dnomd343 - SubConversion";
|
|
this.isPC = this.$getOS().isPc;
|
|
|
|
// 获取 url cache
|
|
if (process.env.VUE_APP_USE_STORAGE === 'true') {
|
|
this.form.sourceSubUrl = this.getLocalStorageItem('sourceSubUrl')
|
|
}
|
|
},
|
|
mounted() {
|
|
this.form.clientType = "clash";
|
|
// this.notify();
|
|
this.getBackendVersion();
|
|
},
|
|
methods: {
|
|
onCopy() {
|
|
this.$message.success("Copied!");
|
|
},
|
|
goToProject() {
|
|
window.open(project);
|
|
},
|
|
gotoGithub() {
|
|
window.open(githubRelease);
|
|
},
|
|
gotoRemoteConfig() {
|
|
window.open(remoteConfigSample);
|
|
},
|
|
clashInstall() {
|
|
if (this.customSubUrl === "") {
|
|
this.$message.error("请先填写必填项,生成订阅链接");
|
|
return false;
|
|
}
|
|
|
|
const url = "clash://install-config?url=";
|
|
window.open(
|
|
url +
|
|
encodeURIComponent(
|
|
this.curtomShortSubUrl !== ""
|
|
? this.curtomShortSubUrl
|
|
: this.customSubUrl
|
|
)
|
|
);
|
|
},
|
|
surgeInstall() {
|
|
if (this.customSubUrl === "") {
|
|
this.$message.error("请先填写必填项,生成订阅链接");
|
|
return false;
|
|
}
|
|
|
|
const url = "surge://install-config?url=";
|
|
window.open(url + this.customSubUrl);
|
|
},
|
|
makeUrl() {
|
|
if (this.form.sourceSubUrl === "" || this.form.clientType === "") {
|
|
this.$message.error("订阅链接与客户端为必填项");
|
|
return false;
|
|
}
|
|
|
|
let backend =
|
|
this.form.customBackend === ""
|
|
? defaultBackend
|
|
: this.form.customBackend;
|
|
|
|
let sourceSub = this.form.sourceSubUrl;
|
|
sourceSub = sourceSub.replace(/(\n|\r|\n\r)/g, "|");
|
|
|
|
this.customSubUrl =
|
|
backend +
|
|
"target=" +
|
|
this.form.clientType +
|
|
"&url=" +
|
|
encodeURIComponent(sourceSub) +
|
|
"&insert=" +
|
|
this.form.insert;
|
|
|
|
if (this.advanced === "2") {
|
|
if (this.form.remoteConfig !== "") {
|
|
this.customSubUrl +=
|
|
"&config=" + encodeURIComponent(this.form.remoteConfig);
|
|
}
|
|
if (this.form.excludeRemarks !== "") {
|
|
this.customSubUrl +=
|
|
"&exclude=" + encodeURIComponent(this.form.excludeRemarks);
|
|
}
|
|
if (this.form.includeRemarks !== "") {
|
|
this.customSubUrl +=
|
|
"&include=" + encodeURIComponent(this.form.includeRemarks);
|
|
}
|
|
if (this.form.filename !== "") {
|
|
this.customSubUrl +=
|
|
"&filename=" + encodeURIComponent(this.form.filename);
|
|
}
|
|
if (this.form.appendType) {
|
|
this.customSubUrl +=
|
|
"&append_type=" + this.form.appendType.toString();
|
|
}
|
|
|
|
this.customSubUrl +=
|
|
"&emoji=" +
|
|
this.form.emoji.toString() +
|
|
"&list=" +
|
|
this.form.nodeList.toString() +
|
|
"&tfo=" +
|
|
this.form.tfo.toString() +
|
|
"&scv=" +
|
|
this.form.scv.toString() +
|
|
"&fdn=" +
|
|
this.form.fdn.toString() +
|
|
"&sort=" +
|
|
this.form.sort.toString();
|
|
|
|
if (this.needUdp) {
|
|
this.customSubUrl += "&udp=" + this.form.udp.toString()
|
|
}
|
|
|
|
if (this.form.tpl.surge.doh === true) {
|
|
this.customSubUrl += "&surge.doh=true";
|
|
}
|
|
|
|
if (this.form.clientType === "clash") {
|
|
if (this.form.tpl.clash.doh === true) {
|
|
this.customSubUrl += "&clash.doh=true";
|
|
}
|
|
|
|
this.customSubUrl += "&new_name=" + this.form.new_name.toString();
|
|
}
|
|
}
|
|
|
|
this.$copyText(this.customSubUrl);
|
|
this.$message.success("定制订阅已复制到剪贴板");
|
|
},
|
|
makeShortUrl() {
|
|
if (this.customSubUrl === "") {
|
|
this.$message.warning("请先生成订阅链接");
|
|
return false;
|
|
}
|
|
|
|
this.loading = true;
|
|
|
|
let data = new FormData();
|
|
data.append("longUrl", btoa(this.customSubUrl));
|
|
|
|
this.$axios
|
|
.post(shortUrlBackend, data, {
|
|
header: {
|
|
"Content-Type": "application/form-data; charset=utf-8"
|
|
}
|
|
})
|
|
.then(res => {
|
|
if (res.data.Code === 1 && res.data.ShortUrl !== "") {
|
|
this.curtomShortSubUrl = res.data.ShortUrl;
|
|
this.$copyText(res.data.ShortUrl);
|
|
this.$message.success("短链接已复制到剪贴板");
|
|
} else {
|
|
this.$message.error("短链接获取失败:" + res.data.Message);
|
|
}
|
|
})
|
|
.catch(() => {
|
|
this.$message.error("短链接获取失败");
|
|
})
|
|
.finally(() => {
|
|
this.loading = false;
|
|
});
|
|
},
|
|
notify() {
|
|
const h = this.$createElement;
|
|
|
|
this.$notify({
|
|
title: "提示",
|
|
type: "warning",
|
|
message: h(
|
|
"i",
|
|
{ style: "color: teal" },
|
|
"订阅链接生成为纯前端实现,转换功能由后端服务提供"
|
|
)
|
|
});
|
|
},
|
|
confirmCustomConfig() {
|
|
if (this.customConfig === "") {
|
|
this.$message.error("配置链接不能为空");
|
|
return false;
|
|
}
|
|
this.form.remoteConfig = this.customConfig;
|
|
this.dialogCustomConfigVisible = false;
|
|
this.customConfig = "";
|
|
},
|
|
confirmUploadConfig() {
|
|
if (this.uploadConfig === "") {
|
|
this.$message.warning("远程配置不能为空");
|
|
return false;
|
|
}
|
|
|
|
this.loading = true;
|
|
|
|
let data = new FormData();
|
|
data.append("password", this.uploadPassword);
|
|
data.append("config", this.uploadConfig);
|
|
|
|
this.$axios
|
|
.post(configUploadBackend, data, {
|
|
header: {
|
|
"Content-Type": "application/form-data; charset=utf-8"
|
|
}
|
|
})
|
|
.then(res => {
|
|
if (res.data.Code === 1 && res.data.url !== "") {
|
|
this.$message.success(
|
|
"远程配置上传成功,链接已复制到剪贴板,有效期为三个月"
|
|
);
|
|
|
|
// 自动填充至『表单-远程配置』
|
|
this.form.remoteConfig = res.data.Url;
|
|
this.$copyText(this.form.remoteConfig);
|
|
|
|
this.dialogUploadConfigVisible = false;
|
|
} else {
|
|
this.$message.error("远程配置上传失败:" + res.data.Message);
|
|
}
|
|
})
|
|
.catch(() => {
|
|
this.$message.error("远程配置上传失败");
|
|
})
|
|
.finally(() => {
|
|
this.loading = false;
|
|
});
|
|
},
|
|
backendSearch(queryString, cb) {
|
|
let backends = this.options.backendOptions;
|
|
|
|
let results = queryString
|
|
? backends.filter(this.createFilter(queryString))
|
|
: backends;
|
|
|
|
// 调用 callback 返回建议列表的数据
|
|
cb(results);
|
|
},
|
|
createFilter(queryString) {
|
|
return candidate => {
|
|
return (
|
|
candidate.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0
|
|
);
|
|
};
|
|
},
|
|
getBackendVersion() {
|
|
this.$axios
|
|
.get(
|
|
defaultBackend.substring(0, defaultBackend.length - 5) + "/version"
|
|
)
|
|
.then(res => {
|
|
this.backendVersion = res.data.replace(/backend\n$/gm, "");
|
|
this.backendVersion = this.backendVersion.replace("subconverter", "");
|
|
});
|
|
},
|
|
saveSubUrl() {
|
|
if (this.form.sourceSubUrl !== '') {
|
|
this.setLocalStorageItem('sourceSubUrl', this.form.sourceSubUrl)
|
|
}
|
|
},
|
|
getLocalStorageItem(itemKey) {
|
|
const now = +new Date()
|
|
let ls = localStorage.getItem(itemKey)
|
|
|
|
let itemValue = ''
|
|
if (ls !== null) {
|
|
let data = JSON.parse(ls)
|
|
if (data.expire > now) {
|
|
itemValue = data.value
|
|
} else {
|
|
localStorage.removeItem(itemKey)
|
|
}
|
|
}
|
|
|
|
return itemValue
|
|
},
|
|
setLocalStorageItem(itemKey, itemValue) {
|
|
const ttl = process.env.VUE_APP_CACHE_TTL
|
|
const now = +new Date()
|
|
|
|
let data = {
|
|
setTime: now,
|
|
ttl: parseInt(ttl),
|
|
expire: now + ttl * 1000,
|
|
value: itemValue
|
|
}
|
|
localStorage.setItem(itemKey, JSON.stringify(data))
|
|
}
|
|
},
|
|
};
|
|
</script>
|
|
|