mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-08-09 23:45:18 +02:00
feat(new tool): ipinfo
This commit is contained in:
parent
bbf73747e4
commit
133b08dc83
6 changed files with 173 additions and 1 deletions
3
components.d.ts
vendored
3
components.d.ts
vendored
|
@ -89,9 +89,11 @@ declare module '@vue/runtime-core' {
|
||||||
HtmlWysiwygEditor: typeof import('./src/tools/html-wysiwyg-editor/html-wysiwyg-editor.vue')['default']
|
HtmlWysiwygEditor: typeof import('./src/tools/html-wysiwyg-editor/html-wysiwyg-editor.vue')['default']
|
||||||
HttpStatusCodes: typeof import('./src/tools/http-status-codes/http-status-codes.vue')['default']
|
HttpStatusCodes: typeof import('./src/tools/http-status-codes/http-status-codes.vue')['default']
|
||||||
IbanValidatorAndParser: typeof import('./src/tools/iban-validator-and-parser/iban-validator-and-parser.vue')['default']
|
IbanValidatorAndParser: typeof import('./src/tools/iban-validator-and-parser/iban-validator-and-parser.vue')['default']
|
||||||
|
'IconMdi:brushVariant': typeof import('~icons/mdi/brush-variant')['default']
|
||||||
'IconMdi:kettleSteamOutline': typeof import('~icons/mdi/kettle-steam-outline')['default']
|
'IconMdi:kettleSteamOutline': typeof import('~icons/mdi/kettle-steam-outline')['default']
|
||||||
InputCopyable: typeof import('./src/components/InputCopyable.vue')['default']
|
InputCopyable: typeof import('./src/components/InputCopyable.vue')['default']
|
||||||
IntegerBaseConverter: typeof import('./src/tools/integer-base-converter/integer-base-converter.vue')['default']
|
IntegerBaseConverter: typeof import('./src/tools/integer-base-converter/integer-base-converter.vue')['default']
|
||||||
|
IpInfo: typeof import('./src/tools/ip-info/ip-info.vue')['default']
|
||||||
Ipv4AddressConverter: typeof import('./src/tools/ipv4-address-converter/ipv4-address-converter.vue')['default']
|
Ipv4AddressConverter: typeof import('./src/tools/ipv4-address-converter/ipv4-address-converter.vue')['default']
|
||||||
Ipv4RangeExpander: typeof import('./src/tools/ipv4-range-expander/ipv4-range-expander.vue')['default']
|
Ipv4RangeExpander: typeof import('./src/tools/ipv4-range-expander/ipv4-range-expander.vue')['default']
|
||||||
Ipv4SubnetCalculator: typeof import('./src/tools/ipv4-subnet-calculator/ipv4-subnet-calculator.vue')['default']
|
Ipv4SubnetCalculator: typeof import('./src/tools/ipv4-subnet-calculator/ipv4-subnet-calculator.vue')['default']
|
||||||
|
@ -121,6 +123,7 @@ declare module '@vue/runtime-core' {
|
||||||
MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
|
MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
|
||||||
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
|
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
|
||||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
||||||
|
NH1: typeof import('naive-ui')['NH1']
|
||||||
NIcon: typeof import('naive-ui')['NIcon']
|
NIcon: typeof import('naive-ui')['NIcon']
|
||||||
NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default']
|
NumeronymGenerator: typeof import('./src/tools/numeronym-generator/numeronym-generator.vue')['default']
|
||||||
OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default']
|
OtpCodeGeneratorAndValidator: typeof import('./src/tools/otp-code-generator-and-validator/otp-code-generator-and-validator.vue')['default']
|
||||||
|
|
|
@ -407,3 +407,25 @@ tools:
|
||||||
notification:
|
notification:
|
||||||
success: Export successful!
|
success: Export successful!
|
||||||
error: Export failed, please try again.
|
error: Export failed, please try again.
|
||||||
|
|
||||||
|
ip-info:
|
||||||
|
title: 'IP Info'
|
||||||
|
description: 'Query IP address information including location, ISP, and more'
|
||||||
|
placeholder: 'Enter IP address (e.g. 117.25.96.225)'
|
||||||
|
query: 'Query'
|
||||||
|
loading: 'Loading...'
|
||||||
|
copied: 'Copied to clipboard!'
|
||||||
|
errors:
|
||||||
|
emptyIp: 'Please enter an IP address'
|
||||||
|
fetchFailed: 'Failed to fetch IP information'
|
||||||
|
generic: 'An error occurred'
|
||||||
|
fields:
|
||||||
|
ip: 'IP Address'
|
||||||
|
hostname: 'Hostname'
|
||||||
|
city: 'City'
|
||||||
|
region: 'Region'
|
||||||
|
country: 'Country'
|
||||||
|
loc: 'Location'
|
||||||
|
org: 'Organization'
|
||||||
|
postal: 'Postal Code'
|
||||||
|
timezone: 'Timezone'
|
||||||
|
|
|
@ -403,3 +403,25 @@ tools:
|
||||||
notification:
|
notification:
|
||||||
success: 导出成功!
|
success: 导出成功!
|
||||||
error: 导出失败,请重试。
|
error: 导出失败,请重试。
|
||||||
|
|
||||||
|
ip-info:
|
||||||
|
title: 'IP 信息查询'
|
||||||
|
description: '查询 IP 地址信息,包括位置、ISP 等详细信息'
|
||||||
|
placeholder: '请输入 IP 地址(例如:117.25.96.225)'
|
||||||
|
query: '查询'
|
||||||
|
loading: '加载中...'
|
||||||
|
copied: '已复制到剪贴板!'
|
||||||
|
errors:
|
||||||
|
emptyIp: '请输入 IP 地址'
|
||||||
|
fetchFailed: '获取 IP 信息失败'
|
||||||
|
generic: '发生错误'
|
||||||
|
fields:
|
||||||
|
ip: 'IP 地址'
|
||||||
|
hostname: '主机名'
|
||||||
|
city: '城市'
|
||||||
|
region: '地区'
|
||||||
|
country: '国家'
|
||||||
|
loc: '位置'
|
||||||
|
org: '组织'
|
||||||
|
postal: '邮政编码'
|
||||||
|
timezone: '时区'
|
||||||
|
|
|
@ -88,6 +88,7 @@ import { tool as macAddressLookup } from './mac-address-lookup';
|
||||||
import { tool as xmlFormatter } from './xml-formatter';
|
import { tool as xmlFormatter } from './xml-formatter';
|
||||||
import { tool as yamlViewer } from './yaml-viewer';
|
import { tool as yamlViewer } from './yaml-viewer';
|
||||||
import { tool as markdownWord } from './markdown-to-word';
|
import { tool as markdownWord } from './markdown-to-word';
|
||||||
|
import { tool as ipInfo } from './ip-info';
|
||||||
|
|
||||||
export const toolsByCategory: ToolCategory[] = [
|
export const toolsByCategory: ToolCategory[] = [
|
||||||
{
|
{
|
||||||
|
@ -166,7 +167,7 @@ export const toolsByCategory: ToolCategory[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Network',
|
name: 'Network',
|
||||||
components: [ipv4SubnetCalculator, ipv4AddressConverter, ipv4RangeExpander, macAddressLookup, macAddressGenerator, ipv6UlaGenerator],
|
components: [ipv4SubnetCalculator, ipv4AddressConverter, ipv4RangeExpander, macAddressLookup, macAddressGenerator, ipv6UlaGenerator, ipInfo],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Math',
|
name: 'Math',
|
||||||
|
|
19
src/tools/ip-info/index.ts
Normal file
19
src/tools/ip-info/index.ts
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* @Author: guihouchang guihouchang@163.com
|
||||||
|
* @Date: 2025-06-05 17:06:24
|
||||||
|
* @LastEditors: guihouchang guihouchang@163.com
|
||||||
|
* @LastEditTime: 2025-06-05 17:42:33
|
||||||
|
* @FilePath: /it-tools/src/tools/ip-info/index.ts
|
||||||
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
||||||
|
*/
|
||||||
|
import { ArrowLeftBar } from '@vicons/tabler';
|
||||||
|
import { defineTool } from '../tool';
|
||||||
|
|
||||||
|
export const tool = defineTool({
|
||||||
|
name: 'ip-info',
|
||||||
|
path: '/ip-info',
|
||||||
|
component: () => import('./ip-info.vue'),
|
||||||
|
icon: ArrowLeftBar,
|
||||||
|
keywords: ['ip', 'query', 'info', 'location', 'isp'],
|
||||||
|
createdAt: new Date('2024-08-25'),
|
||||||
|
});
|
105
src/tools/ip-info/ip-info.vue
Normal file
105
src/tools/ip-info/ip-info.vue
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useMessage } from 'naive-ui';
|
||||||
|
import { useCopy } from '@/composable/copy';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
const message = useMessage();
|
||||||
|
const { copy } = useCopy();
|
||||||
|
|
||||||
|
interface IpInfo {
|
||||||
|
ip: string
|
||||||
|
hostname?: string
|
||||||
|
city?: string
|
||||||
|
region?: string
|
||||||
|
country?: string
|
||||||
|
loc?: string
|
||||||
|
org?: string
|
||||||
|
postal?: string
|
||||||
|
timezone?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const ipAddress = ref('');
|
||||||
|
const ipInfo = ref<IpInfo | null>(null);
|
||||||
|
const loading = ref(false);
|
||||||
|
const error = ref('');
|
||||||
|
|
||||||
|
function fetchIpInfo() {
|
||||||
|
if (!ipAddress.value) {
|
||||||
|
error.value = t('tools.ip-info.errors.emptyIp');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = true;
|
||||||
|
error.value = '';
|
||||||
|
|
||||||
|
return fetch(`https://ipinfo.io/${ipAddress.value}`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: 'Bearer 7a8a124a501f25',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(t('tools.ip-info.errors.fetchFailed'));
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
ipInfo.value = data;
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
error.value = e instanceof Error ? e.message : t('tools.ip-info.errors.generic');
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyToClipboard(text: string | undefined) {
|
||||||
|
if (text) {
|
||||||
|
copy(text);
|
||||||
|
message.success(t('tools.ip-info.copied'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex flex-col gap-4 p-4">
|
||||||
|
<div class="flex gap-4">
|
||||||
|
<input
|
||||||
|
v-model="ipAddress"
|
||||||
|
type="text"
|
||||||
|
:placeholder="t('tools.ip-info.placeholder')"
|
||||||
|
class="flex-1 border rounded px-4 py-2"
|
||||||
|
@keyup.enter="fetchIpInfo"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="rounded bg-blue-500 px-4 py-2 text-white hover:bg-blue-600"
|
||||||
|
:disabled="loading"
|
||||||
|
@click="fetchIpInfo"
|
||||||
|
>
|
||||||
|
{{ loading ? t('tools.ip-info.loading') : t('tools.ip-info.query') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="error" class="rounded bg-red-100 p-4 text-red-500">
|
||||||
|
{{ error }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="ipInfo" class="grid gap-4 border rounded p-4">
|
||||||
|
<div v-for="(value, key) in ipInfo" :key="key" class="flex items-center justify-between">
|
||||||
|
<span class="font-medium capitalize">{{ t(`tools.ip-info.fields.${key}`) }}:</span>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span>{{ value }}</span>
|
||||||
|
<button
|
||||||
|
class="p-1 text-gray-500 hover:text-gray-700"
|
||||||
|
@click="copyToClipboard(value)"
|
||||||
|
>
|
||||||
|
<i class="i-mdi-content-copy" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
Loading…
Add table
Add a link
Reference in a new issue