feat(new tool): ipinfo
This commit is contained in:
		
							parent
							
								
									bbf73747e4
								
							
						
					
					
						commit
						133b08dc83
					
				
							
								
								
									
										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…
	
		Reference in New Issue
	
	Block a user