完成批量化 的支持
This commit is contained in:
parent
1880a8a135
commit
1f979b9b85
|
@ -5,6 +5,7 @@ node_modules
|
||||||
# Quasar core related directories
|
# Quasar core related directories
|
||||||
.quasar
|
.quasar
|
||||||
/dist
|
/dist
|
||||||
|
/public/res
|
||||||
|
|
||||||
# Cordova related directories and files
|
# Cordova related directories and files
|
||||||
/src-cordova/node_modules
|
/src-cordova/node_modules
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 7.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
|
@ -4,10 +4,10 @@
|
||||||
<h6 style="text-align: center;margin: 1rem;">{{ props.serve.tips }} <q-icon v-show="online" title="在线"
|
<h6 style="text-align: center;margin: 1rem;">{{ props.serve.tips }} <q-icon v-show="online" title="在线"
|
||||||
name="check_circle_outline" style="color: green;" /> <q-icon v-show="!online" title="离线" name="highlight_off"
|
name="check_circle_outline" style="color: green;" /> <q-icon v-show="!online" title="离线" name="highlight_off"
|
||||||
style="color: red;" /></h6>
|
style="color: red;" /></h6>
|
||||||
<q-input v-model="outtext" filled autogrow />
|
<q-input v-model="outtext" filled autogrow readonly />
|
||||||
<div style="text-align: center;margin-top: 1rem;display: flex;justify-content: space-around;">
|
<div style="text-align: center;margin-top: 1rem;display: flex;justify-content: space-around;">
|
||||||
<q-btn color="white" text-color="black" @click="copy('link')" label="复制" />
|
<q-btn color="white" text-color="black" @click="copy('link')" label="复制" />
|
||||||
<q-btn color="white" text-color="black" @click="copy('sub')" label="复制订阅" />
|
<!-- <q-btn color="white" text-color="black" @click="copy('sub')" label="复制订阅" /> -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,12 +36,8 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const online = ref(false);
|
const online = ref(false);
|
||||||
const isonline = () => {
|
const isonline = (ip: string) => {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
||||||
let obj = JSON.parse(decode(props.text!.replace('vmess://', '')));
|
|
||||||
let http = props.serve.istls == 0 ? 'http' : 'https'
|
let http = props.serve.istls == 0 ? 'http' : 'https'
|
||||||
let reg = new RegExp(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/);
|
|
||||||
let ip = obj.ps.match(reg)[0];
|
|
||||||
api.text_server(`${http}://${props.serve.ip}:${props.serve.port}/${ip}`).then(res => {
|
api.text_server(`${http}://${props.serve.ip}:${props.serve.port}/${ip}`).then(res => {
|
||||||
online.value = res.data.sataus == 400
|
online.value = res.data.sataus == 400
|
||||||
})
|
})
|
||||||
|
@ -49,18 +45,29 @@ export default defineComponent({
|
||||||
const api = new getdata;
|
const api = new getdata;
|
||||||
const $q = useQuasar()
|
const $q = useQuasar()
|
||||||
const outtext = computed(() => {
|
const outtext = computed(() => {
|
||||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
let tmp = ''
|
||||||
online.value = false
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
let obj = JSON.parse(decode(props.text!.replace('vmess://', '')));
|
let text = props.text!.replace(/\ +/g, '');
|
||||||
obj.add = props.serve.ip
|
text = text.replace(/[\r\n]/g, '');
|
||||||
obj.port = props.serve.port
|
let arr = text.split('vmess://');
|
||||||
obj.host = props.serve.host
|
for (let iterator of arr) {
|
||||||
obj.tls = props.serve.istls == 0 ? '' : 'tls'
|
if (!(iterator.length > 0)) continue
|
||||||
let reg = new RegExp(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/);
|
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||||
obj.path = '/' + obj.ps.match(reg)[0];
|
online.value = false
|
||||||
isonline()
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
return 'vmess://' + encode(JSON.stringify(obj))
|
let obj = JSON.parse(decode(iterator));
|
||||||
|
obj.add = props.serve.ip
|
||||||
|
obj.port = props.serve.port
|
||||||
|
obj.host = props.serve.host
|
||||||
|
obj.tls = props.serve.istls == 0 ? '' : 'tls'
|
||||||
|
let reg = new RegExp(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/);
|
||||||
|
obj.path = '/' + obj.ps.match(reg)[0];
|
||||||
|
let ip = obj.ps.match(reg)[0]
|
||||||
|
isonline(ip)
|
||||||
|
tmp += 'vmess://' + encode(JSON.stringify(obj)) + '\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmp
|
||||||
})
|
})
|
||||||
const copy = (type: string) => {
|
const copy = (type: string) => {
|
||||||
let tmp = ''
|
let tmp = ''
|
||||||
|
|
|
@ -65,11 +65,13 @@ const menuList = [
|
||||||
{
|
{
|
||||||
icon: 'file_download',
|
icon: 'file_download',
|
||||||
label: '下载程序',
|
label: '下载程序',
|
||||||
|
path: 'download',
|
||||||
separator: false
|
separator: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'error',
|
icon: 'share',
|
||||||
label: 'Spam',
|
label: '生成订阅',
|
||||||
|
path: 'subscription',
|
||||||
separator: true
|
separator: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -85,6 +87,7 @@ const menuList = [
|
||||||
{
|
{
|
||||||
icon: 'help_outline',
|
icon: 'help_outline',
|
||||||
iconColor: 'primary',
|
iconColor: 'primary',
|
||||||
|
path: 'help',
|
||||||
label: '帮助',
|
label: '帮助',
|
||||||
separator: false
|
separator: false
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,20 +35,28 @@ export default defineComponent({
|
||||||
return reg.test(ip);
|
return reg.test(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
watch(() => text.value, (newValue, oldValue) => { //直接监听
|
watch(() => text.value, (newValue, oldValue) => { //直接监听
|
||||||
let obj = JSON.parse(decode(def_link))
|
let obj = JSON.parse(decode(def_link))
|
||||||
console.log(newValue)
|
let array = newValue.split(/[\s\n]/)
|
||||||
if (!is_ip(newValue)) {
|
for (let index = 0; index < array.length; index++) {
|
||||||
outlink.value = 'erroe ip'
|
if (!is_ip(array[index])) {
|
||||||
return
|
outlink.value = 'erroe ip'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
outlink.value = ''
|
||||||
|
for (let index = 0; index < array.length; index++) {
|
||||||
|
api.get_country(array[index]).then(res => {
|
||||||
|
let name = res.data.country == '中国' ? res.data.province : res.data.country
|
||||||
|
obj.ps = name + array[index]
|
||||||
|
obj.add = array[index]
|
||||||
|
outlink.value += 'vmess://' + encode(JSON.stringify(obj)) + '\n'
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
api.get_country(newValue).then(res => {
|
|
||||||
let name = res.data.country == '中国' ? res.data.province : res.data.country
|
|
||||||
obj.ps = name + newValue
|
|
||||||
obj.add = newValue
|
|
||||||
outlink.value = 'vmess://' + encode(JSON.stringify(obj))
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
<template>
|
||||||
|
<div class="row ">
|
||||||
|
<div v-for="(item, index) in array" :key="index" class="col-sm-8 col-md-4 col-lg-2 col-xl-1 q-pa-md">
|
||||||
|
<q-card class="my-card">
|
||||||
|
<img class="rounded-full" :src="item.picture">
|
||||||
|
<q-card-section class="text-center">
|
||||||
|
<div class="text-h6 text-center">{{ item.name }}</div>
|
||||||
|
<q-btn @click="dow(`res/${item.name}_phone.apk`)" color="positive">
|
||||||
|
<q-icon left name="file_download" />
|
||||||
|
<div>安卓手机</div>
|
||||||
|
</q-btn>
|
||||||
|
<q-btn @click="dow(`res/${item.name}_moni.apk`)" class="q-ma-md" color="positive">
|
||||||
|
<q-icon left name="file_download" />
|
||||||
|
<div>模拟器</div>
|
||||||
|
</q-btn>
|
||||||
|
<q-btn @click="dow(`res/${item.name}_pc.zip`)" color="positive">
|
||||||
|
<q-icon left name="file_download" />
|
||||||
|
<div>PC</div>
|
||||||
|
</q-btn>
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
|
<q-card-section class="q-pt-none">
|
||||||
|
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="col-sm-8 col-md-4 col-lg-2 col-xl-1 q-pa-md">
|
||||||
|
<q-card class="my-card">
|
||||||
|
<img class="rounded-full q-pa-md" src="img/v2rayng.png">
|
||||||
|
<q-card-section class="text-center">
|
||||||
|
<div class="text-h6 text-center">v2ray</div>
|
||||||
|
<q-btn color="positive">
|
||||||
|
<q-icon left name="file_download" />
|
||||||
|
<div>安卓手机</div>
|
||||||
|
</q-btn>
|
||||||
|
<q-btn class="q-ma-md" color="positive">
|
||||||
|
<q-icon left name="file_download" />
|
||||||
|
<div>模拟器</div>
|
||||||
|
</q-btn>
|
||||||
|
<q-btn color="positive">
|
||||||
|
<q-icon left name="file_download" />
|
||||||
|
<div>PC</div>
|
||||||
|
</q-btn>
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
|
<q-card-section class="q-pt-none">
|
||||||
|
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.box {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-full {
|
||||||
|
border-radius: 9999px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const array = [{ 'name': 'v2ray', 'picture': 'img/v2rayng.png' }, { 'name': 'clash', 'picture': 'img/clash.png' }]
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'Download',
|
||||||
|
setup() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
array,
|
||||||
|
dow(url: string) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
window.open('', '_self')!.location.href = url
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -0,0 +1,84 @@
|
||||||
|
<template>
|
||||||
|
<div class="row ">
|
||||||
|
Help
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.box {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rounded-full {
|
||||||
|
border-radius: 9999px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref, watch } from 'vue';
|
||||||
|
import { getdata } from 'src/api/api'
|
||||||
|
import { decode, encode } from 'js-base64';
|
||||||
|
import { copyToClipboard, useQuasar } from 'quasar';
|
||||||
|
|
||||||
|
|
||||||
|
const array = [{ 'name': '', 'url': '', 'picture': '' }]
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'Help',
|
||||||
|
setup() {
|
||||||
|
const $q = useQuasar()
|
||||||
|
const api = new getdata;
|
||||||
|
const text = ref('');
|
||||||
|
const outlink = ref('');
|
||||||
|
const def_link = 'ew0KICAidiI6ICIyIiwNCiAgInBzIjogIjAiLA0KICAiYWRkIjogIjE4NS4yMTguNi4xMDgiLA0KICAicG9ydCI6ICI5MDAwIiwNCiAgImlkIjogIjJlZTU3ODA2LWY2ZTQtNDgyYS1lZjA4LTczNjBjMDRjZDNlNSIsDQogICJhaWQiOiAiMCIsDQogICJzY3kiOiAiYXV0byIsDQogICJuZXQiOiAid3MiLA0KICAidHlwZSI6ICJub25lIiwNCiAgImhvc3QiOiAiIiwNCiAgInBhdGgiOiAiLyIsDQogICJ0bHMiOiAiIiwNCiAgInNuaSI6ICIiLA0KICAiYWxwbiI6ICIiDQp9'
|
||||||
|
const is_ip = (ip: string) => {
|
||||||
|
var reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
|
||||||
|
return reg.test(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
watch(() => text.value, (newValue, oldValue) => { //直接监听
|
||||||
|
let obj = JSON.parse(decode(def_link))
|
||||||
|
console.log(newValue)
|
||||||
|
if (!is_ip(newValue)) {
|
||||||
|
outlink.value = 'erroe ip'
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
api.get_country(newValue).then(res => {
|
||||||
|
let name = res.data.country == '中国' ? res.data.province : res.data.country
|
||||||
|
obj.ps = name + newValue
|
||||||
|
obj.add = newValue
|
||||||
|
outlink.value = 'vmess://' + encode(JSON.stringify(obj))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
|
||||||
|
text,
|
||||||
|
outlink,
|
||||||
|
copy() {
|
||||||
|
copyToClipboard(outlink.value)
|
||||||
|
.then(() => {
|
||||||
|
// success!
|
||||||
|
$q.notify({
|
||||||
|
message: '复制成功',
|
||||||
|
color: 'positive',
|
||||||
|
position: 'top'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// fail
|
||||||
|
$q.notify({
|
||||||
|
message: '复制失败',
|
||||||
|
color: 'negative'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -44,24 +44,34 @@ export default defineComponent({
|
||||||
})
|
})
|
||||||
const isobj = computed(() => {
|
const isobj = computed(() => {
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
if (text.value.length <= 0) {
|
||||||
online.value = false
|
|
||||||
let obj = JSON.parse(decode(text.value.replace('vmess://', '')));
|
|
||||||
if (obj.id != '2ee57806-f6e4-482a-ef08-7360c04cd3e5' || obj.net != 'ws') {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
isonline()
|
let texttmp = text.value!.replace(/\ +/g, '');
|
||||||
|
texttmp = texttmp.replace(/[\r\n]/g, '');
|
||||||
|
let arr = texttmp.split('vmess://');
|
||||||
|
for (let iterator of arr) {
|
||||||
|
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||||
|
online.value = false
|
||||||
|
if (iterator.length > 0) {
|
||||||
|
let obj = JSON.parse(decode(iterator));
|
||||||
|
if (obj.id != '2ee57806-f6e4-482a-ef08-7360c04cd3e5' || obj.net != 'ws') {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
let reg = new RegExp(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/);
|
||||||
|
let ip = obj.ps.match(reg)[0];
|
||||||
|
isonline(ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
const isonline = () => {
|
const isonline = (ip: string) => {
|
||||||
let obj = JSON.parse(decode(text.value?.replace('vmess://', '')));
|
|
||||||
let reg = new RegExp(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/);
|
|
||||||
let ip = obj.ps.match(reg)[0];
|
|
||||||
api.text_server(`http://${ip}:9000/`).then(res => {
|
api.text_server(`http://${ip}:9000/`).then(res => {
|
||||||
online.value = res.data.sataus == 400
|
online.value = res.data.sataus == 400
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
<template lang="">
|
||||||
|
<div>
|
||||||
|
<div class="row" style="text-align:center">
|
||||||
|
<div class="col-xs-1 col-md-4"></div>
|
||||||
|
<div class="col-xs-10 col-md-4">
|
||||||
|
<h6 style="text-align: center;margin: 1rem;">生成订阅</h6>
|
||||||
|
<q-input v-model="text" filled autogrow placeholder="vmess" />
|
||||||
|
<div style="height:1rem"></div>
|
||||||
|
<q-btn color="white" text-color="black" @click="copy" label="复制" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="">
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, ref } from 'vue';
|
||||||
|
import { copyToClipboard, useQuasar } from 'quasar';
|
||||||
|
export default defineComponent({
|
||||||
|
// eslint-disable-next-line vue/multi-word-component-names
|
||||||
|
name: 'Subscription',
|
||||||
|
setup() {
|
||||||
|
const $q = useQuasar()
|
||||||
|
const text = ref('');
|
||||||
|
return {
|
||||||
|
text,
|
||||||
|
copy() {
|
||||||
|
copyToClipboard(`http://149.129.107.38/link.php?link=${text.value}`)
|
||||||
|
.then(() => {
|
||||||
|
// success!
|
||||||
|
$q.notify({
|
||||||
|
message: '复制成功',
|
||||||
|
color: 'positive',
|
||||||
|
position: 'top'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// fail
|
||||||
|
$q.notify({
|
||||||
|
message: '复制失败',
|
||||||
|
color: 'negative'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -4,7 +4,7 @@ const routes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
component: () => import('layouts/MainLayout.vue'),
|
component: () => import('layouts/MainLayout.vue'),
|
||||||
children: [{ path: '', name: 'home', component: () => import('pages/IndexPage.vue') }, { path: 'createlink', name: 'createlink', component: () => import('pages/CreateLink.vue') }],
|
children: [{ path: '', name: 'home', component: () => import('pages/IndexPage.vue') }, { path: 'createlink', name: 'createlink', component: () => import('pages/CreateLink.vue') }, { path: 'download', name: 'download', component: () => import('pages/Download.vue') }, { path: 'help', name: 'help', component: () => import('pages/Help.vue') }, { path: 'subscription', name: 'subscription', component: () => import('pages/Subscription.vue') }],
|
||||||
},
|
},
|
||||||
|
|
||||||
// Always leave this as last one,
|
// Always leave this as last one,
|
||||||
|
|
Loading…
Reference in New Issue