Skip to content

Commit 7684cfc

Browse files
committed
ip查询功能
1 parent bcf32a9 commit 7684cfc

File tree

1 file changed

+75
-10
lines changed

1 file changed

+75
-10
lines changed

src/components/IPinfo.vue

+75-10
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<transition name="el-fade-in">
55
<div v-if="ipInfo.local && ipInfo.local.country && ipInfo.local.country.code == 'CN'">
66
<el-tooltip class="item" effect="dark" :content="ipInfo.local.ip" placement="top">
7-
<div @click="copy(ipInfo.local.ip)">
7+
<div @click.stop="onQuery(ipInfo.local.ip)">
88
<el-tag style="width: 50px;" class="ml-2" type="success">{{
99
ipInfo.layLocal?ipInfo.layLocal+"ms":"-ms" }}</el-tag>
1010
<el-text style="cursor: pointer;margin-left: 5px;white-space:nowrap;vertical-align: -1px;"
@@ -16,7 +16,7 @@
1616
<transition name="el-fade-in">
1717
<div v-if="ipInfo.cloudflare && ipInfo.cloudflare.country && ipInfo.cloudflare.country.code != 'CN'">
1818
<el-tooltip class="item" effect="dark" :content="ipInfo.cloudflare.ip" placement="top">
19-
<div @click="copy(ipInfo.cloudflare.ip)">
19+
<div @click.stop="onQuery(ipInfo.cloudflare.ip)">
2020
<el-tag style="width: 50px;" class="ml-2" type="success">{{
2121
ipInfo.layCloudflare?ipInfo.layCloudflare+"ms":"-ms" }}</el-tag>
2222
<el-text style="cursor: pointer;margin-left: 5px;white-space:nowrap;vertical-align: -1px;"
@@ -37,15 +37,70 @@
3737
</transition>
3838
</div>
3939
</div>
40+
<el-dialog align-center style="width: 95vw;max-width: 600px;max-height: 85vh;" v-model="queryWindow" title="IP查询">
41+
<el-input v-model="ipInput" style="max-width: 600px" placeholder="请输入IPV4/IPV6地址" clearable autocomplete="new-password">
42+
<template #append><el-button type="primary" :icon="Search" circle @click="onQuery(ipInput)"/></template>
43+
</el-input>
44+
<table class="ip-table" v-loading="isQuerying">
45+
<tr>
46+
<td @click="copy(ipRet.ip)">{{ ipRet.ip }}</td>
47+
</tr>
48+
<tr>
49+
<td>{{ ipRet.addr }}</td>
50+
</tr>
51+
<tr v-if="ipRet.as?.info || ipRet.type">
52+
<td>{{ ipRet.as?.info }} {{ ipRet.type }}</td>
53+
</tr>
54+
<tr v-if="ipRet.as">
55+
<td>
56+
ASN {{ ipRet.as?.number }}
57+
</td>
58+
</tr>
59+
<tr v-if="ipRet.country">
60+
<td>
61+
{{ ipRet.country?.name }}({{ ipRet.country?.code }}) {{ ipRet.regions?.join(" ") }}
62+
</td>
63+
</tr>
64+
<tr v-if="ipRet.registered_country?.code != ipRet.country?.code">
65+
<td>
66+
注册地 {{ ipRet.registered_country?.name }}({{ ipRet.registered_country?.code }})
67+
</td>
68+
</tr>
69+
<tr>
70+
<td>{{ ipRet.as?.name }}</td>
71+
</tr>
72+
</table>
73+
</el-dialog>
4074
</template>
4175

4276
<script lang="ts" setup>
4377
const props = defineProps({
4478
isVisible: Boolean
4579
})
46-
import { reactive } from 'vue'
80+
import { reactive,ref, type Ref } from 'vue'
4781
import { ElMessage } from 'element-plus'
4882
import { toClipboard } from '@soerenmartius/vue3-clipboard'
83+
import { Search } from '@element-plus/icons-vue'
84+
const queryWindow = ref(false)
85+
const isQuerying = ref(false)
86+
const ipInput = ref("")
87+
const ipRet: Ref<any> = ref({})
88+
const onQuery = async(ip:string) => {
89+
queryWindow.value = true
90+
try {
91+
const ipv4 = /^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$/;
92+
const ipv6 = /^([\da-fA-F]{1,4}:){6}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^::([\da-fA-F]{1,4}:){0,4}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:):([\da-fA-F]{1,4}:){0,3}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:){2}:([\da-fA-F]{1,4}:){0,2}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:){3}:([\da-fA-F]{1,4}:){0,1}((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:){4}:((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$|^([\da-fA-F]{1,4}:){7}[\da-fA-F]{1,4}$|^:((:[\da-fA-F]{1,4}){1,6}|:)$|^[\da-fA-F]{1,4}:((:[\da-fA-F]{1,4}){1,5}|:)$|^([\da-fA-F]{1,4}:){2}((:[\da-fA-F]{1,4}){1,4}|:)$|^([\da-fA-F]{1,4}:){3}((:[\da-fA-F]{1,4}){1,3}|:)$|^([\da-fA-F]{1,4}:){4}((:[\da-fA-F]{1,4}){1,2}|:)$|^([\da-fA-F]{1,4}:){5}:([\da-fA-F]{1,4})?$|^([\da-fA-F]{1,4}:){6}:$/;
93+
94+
if (!ipv4.test(ip) && !ipv6.test(ip)) {
95+
throw "请输入正确的IP地址"
96+
}
97+
isQuerying.value = true
98+
ipRet.value = await cachedQuery(ip)
99+
isQuerying.value = false
100+
} catch (error) {
101+
ElMessage.error(String(error))
102+
}
103+
}
49104
const ipInfo: {local:any, cloudflare:any,layLocal:any,layCloudflare:any} = reactive({local:null, cloudflare:null,layLocal:null,layCloudflare:null})
50105
const copy = (ip: string) => {
51106
toClipboard(ip)
@@ -70,13 +125,13 @@ let failure = false
70125
async function cachedQuery(ip: string) {
71126
let ret = JSON.parse(localStorage.getItem("cache_ip_"+ip) || "{}")
72127
if (!ret.ip || new Date().getTime() / 1000 - ret.time > 60 * 60 * 24){
73-
try {
74-
if(failure) throw ""
75-
ret = await queryIp(ip)
76-
} catch (error) {
77-
failure = true
78-
throw "查询IP信息失败"
79-
}
128+
try {
129+
if(failure) throw ""
130+
ret = await queryIp(ip)
131+
} catch (error) {
132+
failure = true
133+
throw "查询IP信息失败"
134+
}
80135
ret['time'] = new Date().getTime() / 1000
81136
localStorage.setItem("cache_ip_"+ip, JSON.stringify(ret))
82137
}
@@ -163,6 +218,16 @@ watchCloudflare("ipv4.ip.sb")
163218
padding: 2%
164219
}
165220
221+
.ip-table {
222+
height: 100%;
223+
margin: 20px auto;
224+
padding: 10px;
225+
border: #ffffff 1px solid;
226+
border-radius: 10px;
227+
228+
text-align: center;
229+
}
230+
166231
@media (prefers-color-scheme: dark) {
167232
.card {
168233
background-color: rgb(18, 18, 18);

0 commit comments

Comments
 (0)