完成批量化 的支持
This commit is contained in:
parent
1880a8a135
commit
1f979b9b85
|
@ -5,6 +5,7 @@ node_modules
|
|||
# Quasar core related directories
|
||||
.quasar
|
||||
/dist
|
||||
/public/res
|
||||
|
||||
# Cordova related directories and files
|
||||
/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="在线"
|
||||
name="check_circle_outline" style="color: green;" /> <q-icon v-show="!online" title="离线" name="highlight_off"
|
||||
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;">
|
||||
<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>
|
||||
|
@ -36,12 +36,8 @@ export default defineComponent({
|
|||
},
|
||||
setup(props) {
|
||||
const online = ref(false);
|
||||
const isonline = () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
let obj = JSON.parse(decode(props.text!.replace('vmess://', '')));
|
||||
const isonline = (ip: string) => {
|
||||
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 => {
|
||||
online.value = res.data.sataus == 400
|
||||
})
|
||||
|
@ -49,18 +45,29 @@ export default defineComponent({
|
|||
const api = new getdata;
|
||||
const $q = useQuasar()
|
||||
const outtext = computed(() => {
|
||||
let tmp = ''
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
let text = props.text!.replace(/\ +/g, '');
|
||||
text = text.replace(/[\r\n]/g, '');
|
||||
let arr = text.split('vmess://');
|
||||
for (let iterator of arr) {
|
||||
if (!(iterator.length > 0)) continue
|
||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||
online.value = false
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
let obj = JSON.parse(decode(props.text!.replace('vmess://', '')));
|
||||
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];
|
||||
isonline()
|
||||
return 'vmess://' + encode(JSON.stringify(obj))
|
||||
let ip = obj.ps.match(reg)[0]
|
||||
isonline(ip)
|
||||
tmp += 'vmess://' + encode(JSON.stringify(obj)) + '\n'
|
||||
}
|
||||
|
||||
return tmp
|
||||
})
|
||||
const copy = (type: string) => {
|
||||
let tmp = ''
|
||||
|
|
|
@ -65,11 +65,13 @@ const menuList = [
|
|||
{
|
||||
icon: 'file_download',
|
||||
label: '下载程序',
|
||||
path: 'download',
|
||||
separator: false
|
||||
},
|
||||
{
|
||||
icon: 'error',
|
||||
label: 'Spam',
|
||||
icon: 'share',
|
||||
label: '生成订阅',
|
||||
path: 'subscription',
|
||||
separator: true
|
||||
},
|
||||
{
|
||||
|
@ -85,6 +87,7 @@ const menuList = [
|
|||
{
|
||||
icon: 'help_outline',
|
||||
iconColor: 'primary',
|
||||
path: 'help',
|
||||
label: '帮助',
|
||||
separator: false
|
||||
}
|
||||
|
|
|
@ -35,20 +35,28 @@ export default defineComponent({
|
|||
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)) {
|
||||
let array = newValue.split(/[\s\n]/)
|
||||
for (let index = 0; index < array.length; index++) {
|
||||
if (!is_ip(array[index])) {
|
||||
outlink.value = 'erroe ip'
|
||||
return
|
||||
}
|
||||
|
||||
api.get_country(newValue).then(res => {
|
||||
}
|
||||
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 + newValue
|
||||
obj.add = newValue
|
||||
outlink.value = 'vmess://' + encode(JSON.stringify(obj))
|
||||
obj.ps = name + array[index]
|
||||
obj.add = array[index]
|
||||
outlink.value += 'vmess://' + encode(JSON.stringify(obj)) + '\n'
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
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(() => {
|
||||
try {
|
||||
if (text.value.length <= 0) {
|
||||
return false
|
||||
}
|
||||
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
|
||||
let obj = JSON.parse(decode(text.value.replace('vmess://', '')));
|
||||
if (iterator.length > 0) {
|
||||
let obj = JSON.parse(decode(iterator));
|
||||
if (obj.id != '2ee57806-f6e4-482a-ef08-7360c04cd3e5' || obj.net != 'ws') {
|
||||
return false
|
||||
}
|
||||
isonline()
|
||||
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) {
|
||||
console.log(error);
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
const isonline = () => {
|
||||
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];
|
||||
const isonline = (ip: string) => {
|
||||
api.text_server(`http://${ip}:9000/`).then(res => {
|
||||
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: '/',
|
||||
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,
|
||||
|
|
Loading…
Reference in New Issue