mirror of
https://github.com/CorentinTh/it-tools.git
synced 2025-08-07 06:25: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']
|
||||
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']
|
||||
'IconMdi:brushVariant': typeof import('~icons/mdi/brush-variant')['default']
|
||||
'IconMdi:kettleSteamOutline': typeof import('~icons/mdi/kettle-steam-outline')['default']
|
||||
InputCopyable: typeof import('./src/components/InputCopyable.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']
|
||||
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']
|
||||
|
@ -121,6 +123,7 @@ declare module '@vue/runtime-core' {
|
|||
MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
|
||||
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
|
||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
||||
NH1: typeof import('naive-ui')['NH1']
|
||||
NIcon: typeof import('naive-ui')['NIcon']
|
||||
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']
|
||||
|
|
|
@ -407,3 +407,25 @@ tools:
|
|||
notification:
|
||||
success: Export successful!
|
||||
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:
|
||||
success: 导出成功!
|
||||
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 yamlViewer } from './yaml-viewer';
|
||||
import { tool as markdownWord } from './markdown-to-word';
|
||||
import { tool as ipInfo } from './ip-info';
|
||||
|
||||
export const toolsByCategory: ToolCategory[] = [
|
||||
{
|
||||
|
@ -166,7 +167,7 @@ export const toolsByCategory: ToolCategory[] = [
|
|||
},
|
||||
{
|
||||
name: 'Network',
|
||||
components: [ipv4SubnetCalculator, ipv4AddressConverter, ipv4RangeExpander, macAddressLookup, macAddressGenerator, ipv6UlaGenerator],
|
||||
components: [ipv4SubnetCalculator, ipv4AddressConverter, ipv4RangeExpander, macAddressLookup, macAddressGenerator, ipv6UlaGenerator, ipInfo],
|
||||
},
|
||||
{
|
||||
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