feat: 网站favicon获取

This commit is contained in:
osiris
2024-03-08 16:16:49 +08:00
parent 6ecafa8bc2
commit 101ee6dff2
9 changed files with 793 additions and 576 deletions
+16
View File
@@ -0,0 +1,16 @@
//统一管理咱们项目用户相关的接口
import request from '@/utils/request'
import type {
WebInfoReqData,
getWebInfoResponseData
} from './type'
//项目用户相关的请求地址
enum API {
//获取网站信息
WEBINFO = '/webinfo'
}
//获取ip
export const fetchWebInfo = (data: WebInfoReqData) => request.get<any, getWebInfoResponseData>(API.WEBINFO + '/' + data.link)
+18
View File
@@ -0,0 +1,18 @@
import { ResponseData } from "../common"
export interface WebInfoReqData {
link: string
}
export interface WebInfo {
link: string,
logo: string,
title: string,
keywords: string,
desc: string
}
//响应格式
export interface getWebInfoResponseData extends ResponseData {
data: WebInfo
}
+1 -1
View File
@@ -16,7 +16,7 @@ const info = reactive({
<div class="flex flex-col mt-3 flex-1">
<DetailHeader :title="info.title"></DetailHeader>
<div class="">
<div class="p-4 rounded-2xl bg-white">
</div>
</div>
+105
View File
@@ -0,0 +1,105 @@
<script setup lang="ts">
import { ref, reactive } from 'vue'
import DetailHeader from '@/components/Layout/DetailHeader/DetailHeader.vue'
import { copy } from '@/utils/string'
import { isUrl } from '@/utils/url'
import { useToolsStore } from '@/store/modules/tools'
import { ElMessage } from 'element-plus'
const info = reactive({
title: "网站favicon获取",
})
//store
const toolsStore = useToolsStore()
const searchUrl = ref()
const getWebInfo = async () => {
try {
if (isUrl(searchUrl.value)) {
//有效的域名
if (!searchUrl.value.includes('http://') && !searchUrl.value.includes('https://')) {
searchUrl.value = 'http://' + searchUrl.value;
}
const urlObj = new URL(searchUrl.value)
// webInfo.link = urlObj.hostname
searchUrl.value = urlObj.hostname
await toolsStore.getWebInfo({
link: searchUrl.value
})
} else {
//无效的域名
ElMessage({
message: "无效的域名或地址",
type: "error",
duration: 1500
})
}
} catch (error) {
console.error('Error fetching site info:', error);
}
};
//copy
const copyRes = async (resStr: string) => {
copy(resStr)
}
</script>
<template>
<div class="flex flex-col mt-3 flex-1">
<DetailHeader :title="info.title"></DetailHeader>
<div class="p-4 rounded-2xl bg-white">
<div>
<el-input
v-model="searchUrl"
style="max-width: 600px"
placeholder="请输入域名或地址"
class="input-with-select"
size="large"
>
<template #append>
<el-button type="primary" @click="getWebInfo">获取</el-button>
</template>
</el-input>
</div>
<div>
<ul>
<li class="mt-3">
<el-text>域名: </el-text>
<el-link :href="'https://' + searchUrl" type="primary" target="_blank">{{ searchUrl }}</el-link>
</li>
<li class="mt-3 flex">
<el-text>logo: </el-text>
<div v-if="toolsStore.webInfo.logo" class="ml-2 flex items-center">
<el-image :src="toolsStore.webInfo.logo" class="h-12"></el-image>
<el-button class="ml-3" link type="primary">下载</el-button>
</div>
</li>
<li class="mt-3 flex">
<el-text >标题: </el-text>
<div class="ml-2"></div>
<el-text>{{ toolsStore.webInfo.title }}</el-text>
</li>
<li class="mt-3 flex">
<el-text >关键词: </el-text>
<div class="ml-2"></div>
<el-text>{{ toolsStore.webInfo.keywords }}</el-text>
</li>
<li class="mt-3 flex">
<el-text>描述: </el-text>
<div class="ml-2"></div>
<el-text>{{ toolsStore.webInfo.desc }}</el-text>
<!-- <el-button>复制</el-button> -->
</li>
</ul>
</div>
</div>
</div>
</template>
<style scoped>
</style>
+10
View File
@@ -249,6 +249,16 @@ export const constantRoute = [
description: '把文本转换成图片,生成长图,具有超多个性文字排版',
}
},
{
path: '/webInfo',
component: () => import('@/components/WebInfo/WebInfo.vue'),
name: 'webInfo',
meta: {
title: "网站favicon获取",
keywords: '获取网站logo,获取网站icon,获取网站favicon,获取网站标题,获取网站关键词,获取网站描述',
description: '获取网站logo、icon、favicon、标题、关键词、描述等信息',
}
},
{
path: '/about',
component: () => import('@/components/Home/About.vue'),
+14 -1
View File
@@ -4,7 +4,9 @@ import { getTools, getToolCate, getToolRecommend, toolCollect, getToolCollect }
import { getIp } from '@/api/ip'
import type { ToolsReqData, ToolsInfo, ToolCate, CollectReqData } from '@/api/tools/type'
import type { IpReqData, IpInfo } from '@/api/ip/type'
import type { WebInfo, WebInfoReqData } from '@/api/webinfo/type'
import { useUserStore } from '@/store/modules/user'
import { fetchWebInfo } from '@/api/webinfo'
export const useToolsStore = defineStore('tools', {
//用来存放变量
@@ -14,6 +16,7 @@ export const useToolsStore = defineStore('tools', {
cates: [] as ToolCate[],
recommends: [] as ToolsInfo[],
ipData: {} as IpInfo,
webInfo: {} as WebInfo,
collect: [] as ToolsInfo[],
collectIds: [] as number[],
}),
@@ -102,6 +105,16 @@ export const useToolsStore = defineStore('tools', {
} else {
return Promise.reject(new Error(result.message))
}
}
},
//获取网站信息
async getWebInfo(data: WebInfoReqData) {
const result: any = await fetchWebInfo(data)
if (result.code == 200) {
this.webInfo = result.data
return result.message
} else {
return Promise.reject(new Error(result.message))
}
},
}
})
+14
View File
@@ -0,0 +1,14 @@
export function isUrl(str: string): boolean {
// const urlPattern = new RegExp(
// '^(https?:\\/\\/)?'+ // protocol
// '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name and extension
// '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
// '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
// '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
// '(\\#[-a-z\\d_]*)?$','i'); // fragment locator
// return urlPattern.test(str);
const urlPattern = new RegExp(
'^(https?:\\/\\/)?'+ // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,})','i'); // fragment locator
return urlPattern.test(str);
}