feat:页面美化,添加广告位

This commit is contained in:
陶然
2026-03-02 18:49:02 +08:00
parent f492194fab
commit 226997fb25
8 changed files with 381 additions and 52 deletions
+4 -2
View File
@@ -12,5 +12,7 @@ VITE_SERVE = ''
VITE_HOST = '127.0.0.1'
# 第三方反馈互动地址
VITE_FEEDBACK_URL = ''
# 广告位开关
VITE_ADV_SHOW = 'false'
# 广告位开关(废弃)
VITE_ADV_SHOW = 'false'
# 左侧底部广告位
VITE_LEFT_ADV = ''
+62 -3
View File
@@ -13,9 +13,11 @@ const componentStore = useComponentStore()
<template>
<el-container>
<!-- left -->
<el-aside class="fixed top-0 left-0 h-full z-10 c-md:block c-sm:hidden c-xs:hidden" width="240px" v-show="!componentStore.leftCom">
<transition name="left-sidebar">
<el-aside v-if="!componentStore.leftCom" class="fixed top-0 left-0 h-full z-10 c-md:block c-sm:hidden c-xs:hidden" width="240px">
<Left></Left>
</el-aside>
</el-aside>
</transition>
<el-drawer
show-close
size="240px"
@@ -27,7 +29,7 @@ const componentStore = useComponentStore()
</el-drawer>
<!-- right -->
<el-container :class="!componentStore.leftCom ? 'c-md:ml-[240px]' : ''">
<el-container :class="!componentStore.leftCom ? 'c-md:ml-[240px]' : ''" class="main-container">
<el-header>
<Header/>
</el-header>
@@ -63,4 +65,61 @@ const componentStore = useComponentStore()
.animation-leave-active {
transition: all 0.3s cubic-bezier(1, 0.6, 0.6, 1);
}
/* 左侧菜单折叠动画 */
.left-sidebar-enter-from,
.left-sidebar-leave-to {
transform: translateX(-100%);
opacity: 0;
}
.left-sidebar-enter-to,
.left-sidebar-leave-from {
transform: translateX(0);
opacity: 1;
}
.left-sidebar-enter-active,
.left-sidebar-leave-active {
transition: all 0.3s ease;
}
/* 主内容区域动画 */
.main-container {
transition: margin-left 0.3s ease;
}
</style>
<style>
/* 全局科技感样式 */
body {
background-color: #f0f2f5;
background-image:
radial-gradient(circle at 10% 20%, rgba(64, 158, 255, 0.05) 0%, transparent 20%),
radial-gradient(circle at 80% 30%, rgba(118, 75, 162, 0.05) 0%, transparent 25%),
radial-gradient(circle at 40% 70%, rgba(102, 126, 234, 0.05) 0%, transparent 20%),
radial-gradient(circle at 90% 90%, rgba(64, 158, 255, 0.05) 0%, transparent 15%);
background-attachment: fixed;
min-height: 100vh;
}
/* 科技感滚动条 */
::-webkit-scrollbar {
width: 8px;
height: 8px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 4px;
}
::-webkit-scrollbar-thumb {
background: linear-gradient(180deg, #409EFF, #667eea);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: linear-gradient(180deg, #667eea, #764ba2);
}
</style>
+59 -4
View File
@@ -34,12 +34,12 @@ onMounted(() => {
<!-- 收藏工具 -->
<div id="collect">
<!-- 收藏标题 -->
<div class="mt-8 mb-3 text-xl font-bold text-[--base-black]">
<div class="mt-8 mb-3 text-xl font-bold text-[--base-black] tech-title">
收藏工具
</div>
<!-- 收藏卡片 -->
<div v-if="toolsStore.collectedTools.length > 0" class="flex justify-between flex-wrap self-card-div c-xs:ml-0" :gutter="10">
<router-link v-for="(item, index) in toolsStore.collectedTools" :key="index" :to="item.url" class="flex flex-col mt-5 border-solid rounded-2xl border-gray w-[24%] p-2 bg-white hover:shadow-md c-xs:w-[99.5%] c-md:w-[24%] c-sm:w-[32%] p-5 hover:-translate-y-2 duration-300">
<router-link v-for="(item, index) in toolsStore.collectedTools" :key="index" :to="item.url" class="flex flex-col mt-5 border-solid rounded-2xl border-gray w-[24%] p-2 bg-white hover:shadow-md c-xs:w-[99.5%] c-md:w-[24%] c-sm:w-[32%] p-5 hover:-translate-y-2 duration-300 tech-card">
<div class="flex items-center border-b pb-2">
<el-image :src="item.logo" class="w-10 h-10 min-h-[2.5rem] min-w-[2.5rem] rounded-full"></el-image>
<div class="flex flex-col ml-2 w-full">
@@ -73,12 +73,12 @@ onMounted(() => {
<!-- 工具分类列表 -->
<div v-for="(cate, index) in toolsStore.cates" :key="index">
<!-- cate title -->
<div class="mt-8 mb-3 text-xl font-bold text-[--base-black]" :id="'cate_' + cate.id">
<div class="mt-8 mb-3 text-xl font-bold text-[--base-black] tech-title" :id="'cate_' + cate.id">
{{ cate.title }}
</div>
<!-- card -->
<div class="flex justify-between flex-wrap self-card-div c-xs:ml-0" :gutter="10">
<router-link v-for="(item, index) in cate.list" :key="index" :to="item.url" class="flex flex-col mt-5 border-solid rounded-2xl border-gray w-[24%] p-2 bg-white hover:shadow-md c-xs:w-[99.5%] c-md:w-[24%] c-sm:w-[32%] p-5 hover:-translate-y-2 duration-300">
<router-link v-for="(item, index) in cate.list" :key="index" :to="item.url" class="flex flex-col mt-5 border-solid rounded-2xl border-gray w-[24%] p-2 bg-white hover:shadow-md c-xs:w-[99.5%] c-md:w-[24%] c-sm:w-[32%] p-5 hover:-translate-y-2 duration-300 tech-card">
<div class="flex items-center border-b pb-2">
<el-image :src="item.logo" class="w-10 h-10 min-h-[2.5rem] min-w-[2.5rem] rounded-full"></el-image>
<div class="flex flex-col ml-2 w-full">
@@ -109,4 +109,59 @@ onMounted(() => {
content: "";
width: 24%
}
/* 科技感卡片样式 */
.router-link-active .tech-card {
border-color: #409EFF;
box-shadow: 0 0 20px rgba(64, 158, 255, 0.3);
}
.tech-card {
position: relative;
overflow: hidden;
transition: all 0.3s ease;
border: 1px solid transparent;
background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%);
}
.tech-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 30px rgba(64, 158, 255, 0.2);
border-color: #409EFF;
}
.tech-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 2px;
background: linear-gradient(90deg, #409EFF, #667eea, #764ba2);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.3s ease;
}
.tech-card:hover::before {
transform: scaleX(1);
}
/* 科技感标题样式 */
.tech-title {
position: relative;
display: inline-block;
margin-bottom: 1rem;
}
.tech-title::after {
content: '';
position: absolute;
bottom: -5px;
left: 0;
width: 60px;
height: 3px;
background: linear-gradient(90deg, #409EFF, #667eea);
border-radius: 3px;
}
</style>
@@ -63,8 +63,8 @@ onMounted(() => {
</script>
<template>
<div class="flex justify-between items-center rounded-2xl bg-white p-4 mt-5 mb-5">
<div class="text-xl">
<div class="flex justify-between items-center rounded-2xl p-4 mt-5 mb-5 tech-detail-header">
<div class="text-xl tech-title">
{{ props.title }}
</div>
<div>
@@ -72,6 +72,8 @@ onMounted(() => {
:icon="isCollected ? StarFilled : Star"
:type="isCollected ? 'warning' : 'default'"
@click="toggleCollect"
class="tech-button"
size="medium"
>
{{ isCollected ? '已收藏' : '收藏' }}
</el-button>
@@ -80,5 +82,69 @@ onMounted(() => {
</template>
<style scoped>
/* 科技感详情页头部 */
.tech-detail-header {
background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%);
border: 1px solid rgba(64, 158, 255, 0.2);
position: relative;
overflow: hidden;
}
.tech-detail-header::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 2px;
background: linear-gradient(90deg, #409EFF, #667eea, #764ba2);
}
/* 科技感标题 */
.tech-title {
position: relative;
font-weight: 600;
color: #333;
}
/* 科技感按钮 */
.tech-button {
position: relative;
border-radius: 8px;
transition: all 0.3s ease;
overflow: hidden;
}
.tech-button:hover {
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
}
.tech-button:active {
transform: translateY(0);
}
/* 收藏状态按钮样式 */
.tech-button.is-warning {
background: linear-gradient(135deg, #ffc107, #ff9800);
border-color: #ffc107;
color: #fff;
}
.tech-button.is-warning:hover {
background: linear-gradient(135deg, #ffca28, #ff9800);
box-shadow: 0 4px 12px rgba(255, 193, 7, 0.4);
}
/* 未收藏状态按钮样式 */
.tech-button.is-default {
background: linear-gradient(135deg, #f8f9fa, #e9ecef);
border-color: #dee2e6;
color: #495057;
}
.tech-button.is-default:hover {
background: linear-gradient(135deg, #ffffff, #f8f9fa);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
</style>
+17 -2
View File
@@ -5,11 +5,26 @@ const currentYear: number = new Date().getFullYear();
</script>
<template>
<div class="w-full rounded-2xl z-10 p-5 text-center">
<el-text>{{ appDesc }} © {{ currentYear }} <a href="https://github.com/naroat/tools-web" target="_blank" class="text-blue-700">Tools-Web</a></el-text>
<div class="w-full rounded-2xl z-10 p-5 text-center tech-footer">
<el-text>{{ appDesc }} © {{ currentYear }} <a href="https://github.com/naroat/tools-web" target="_blank" class="text-blue-700 tech-link">Tools-Web</a></el-text>
</div>
</template>
<style scoped>
/* 简约页脚 */
.tech-footer {
background: transparent;
border: none;
position: relative;
}
/* 简约链接 */
.tech-link {
transition: all 0.2s ease;
text-decoration: none;
}
.tech-link:hover {
color: #409EFF;
}
</style>
+64 -30
View File
@@ -75,24 +75,19 @@ onMounted(() => {
<template>
<header class="h-24 w-full flex justify-between pt-2 pb-2 c-xs:h-16 c-xs:border-b-[1px] items-center">
<div class="flex items-center w-full">
<Transition name="fold" class="hidden c-sm:block c-md:hidden c-xs:block">
<svg v-if="!componentStore.leftComDrawer" @click="componentStore.setleftComDrawerStatus(true)" t="1702978210636" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7618" width="30" height="30">
<div class="hidden c-sm:block c-md:hidden c-xs:block">
<svg @click="componentStore.setleftComDrawerStatus(!componentStore.leftComDrawer)" :class="['icon', { 'rotate': componentStore.leftComDrawer }]" t="1702978210636" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7618" width="30" height="30">
<path fill="#444" fill-opacity=".9" d="M895.936 256l-768-0.896 0.128-64L896 192l-0.064 64zM179.2 689.152l202.688-152a32 32 0 0 0 0-51.2L179.2 333.952a32 32 0 0 0-51.2 25.6v304a32 32 0 0 0 51.2 25.6z m12.8-89.6v-176l117.312 88L192 599.552zM896 544H480v-64H896v64z m-0.064 288l-768-0.896 0.128-64L896 768l-0.064 64z" p-id="7619"></path>
</svg>
<svg v-else @click="componentStore.setleftComDrawerStatus(false)" t="1702978577170" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1587" width="30" height="30">
<path fill="#444" fill-opacity=".9" d="M128.064 192l768 0.896-0.128 64L128 256l0.064-64z m514.048 294.848a32 32 0 0 0 0 51.2l202.688 152a32 32 0 0 0 51.2-25.6v-304a32 32 0 0 0-51.2-25.6l-202.688 152zM832 424.448v176l-117.312-88L832 424.448zM128 480h416v64H128v-64z m0.064 288l768 0.896-0.128 64L128 832l0.064-64z" p-id="1588"></path>
</svg>
</Transition>
</div>
<!-- c-md:block -->
<Transition name="fold" class="hidden c-md:block">
<svg v-if="!componentStore.leftCom" @click="componentStore.setLeftComStatus(true)" t="1702978577170" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1587" width="30" height="30">
<path fill="#444" fill-opacity=".9" d="M128.064 192l768 0.896-0.128 64L128 256l0.064-64z m514.048 294.848a32 32 0 0 0 0 51.2l202.688 152a32 32 0 0 0 51.2-25.6v-304a32 32 0 0 0-51.2-25.6l-202.688 152zM832 424.448v176l-117.312-88L832 424.448zM128 480h416v64H128v-64z m0.064 288l768 0.896-0.128 64L128 832l0.064-64z" p-id="1588"></path>
</svg>
<svg v-else @click="componentStore.setLeftComStatus(false)" t="1702978210636" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7618" width="30" height="30">
<div class="hidden c-md:block">
<svg @click="componentStore.setLeftComStatus(!componentStore.leftCom)" :class="['icon', { 'rotate': componentStore.leftCom }]" t="1702978210636" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7618" width="30" height="30">
<path fill="#444" fill-opacity=".9" d="M895.936 256l-768-0.896 0.128-64L896 192l-0.064 64zM179.2 689.152l202.688-152a32 32 0 0 0 0-51.2L179.2 333.952a32 32 0 0 0-51.2 25.6v304a32 32 0 0 0 51.2 25.6z m12.8-89.6v-176l117.312 88L192 599.552zM896 544H480v-64H896v64z m-0.064 288l-768-0.896 0.128-64L896 768l-0.064 64z" p-id="7619"></path>
</svg>
</Transition>
</div>
<div class="ml-3 mr-1">
<router-link to="/">
@@ -177,25 +172,64 @@ onMounted(() => {
</template>
<style scoped>
.fold-enter-active {
transition: all 1s ease-out;
}
.fold-enter-from,
.fold-leave-to {
transform: translateX(20px);
opacity: 0;
}
:deep(.el-select__wrapper) {
box-shadow: 0 0 0 0px var(--el-input-border-color, var(--el-border-color)) inset;
cursor: default;
@apply md:w-full;
}
/* 科技感搜索框 */
.el-select :deep(.el-select__wrapper){
background-color: rgba(46, 51, 56, 0.05);
background-color: rgb(255, 255, 255);
background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%);
border: 1px solid rgba(64, 158, 255, 0.2);
border-radius: 8px;
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
}
/* 搜索框容器 */
.el-select {
transition: width 0.3s ease;
}
.el-select :deep(.el-select__wrapper):hover {
border-color: #409EFF;
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.2);
}
.el-select :deep(.el-select__wrapper.is-focus) {
border-color: #409EFF;
box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}
/* 科技感按钮 */
.el-button {
position: relative;
overflow: hidden;
transition: all 0.3s ease;
border-radius: 8px;
}
.el-button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
}
/* 科技感图标 */
.icon {
transition: all 0.3s ease;
transform-origin: center;
}
.icon:hover {
transform: scale(1.1);
filter: drop-shadow(0 0 8px rgba(64, 158, 255, 0.5));
}
/* 旋转动画 */
.icon.rotate {
transform: rotate(180deg);
}
/* 简约Header */
header {
background: transparent;
position: relative;
}
</style>
+78 -7
View File
@@ -8,6 +8,7 @@ const route = useRoute()
const appName = ref(import.meta.env.VITE_APP_TITLE || '工具坊')
const appNet = ref(import.meta.env.VITE_APP_DESC || '')
const leftAdv = ref(import.meta.env.VITE_LEFT_ADV || '')
//菜单选中
const defaultActive = ref('')
//默认展开的菜单
@@ -64,7 +65,7 @@ onMounted(async () => {
<el-scrollbar>
<!-- logo -->
<div class="flex justify-center">
<router-link class="flex flex-row h-24" to="/">
<router-link class="flex flex-row h-24 logo-container p-4" to="/">
<img class="h-12 w-auto rounded-lg mr-2 mt-auto mb-auto" src="@/assets/logo.png" :alt="appNet">
<div class="flex flex-col mt-auto mb-auto">
<div class="text-2xl">{{ appName }}</div>
@@ -112,6 +113,9 @@ onMounted(async () => {
</el-menu-item>
</el-menu>
</div>
<!-- 广告位 -->
<div class="ad-container" v-if="leftAdv != ''" v-html="leftAdv"></div>
</el-scrollbar>
<!-- </div> -->
</template>
@@ -122,17 +126,17 @@ onMounted(async () => {
list-style: none !important;
padding-left: 0 !important;
margin-top: 1rem;
background-color: none !important;
background-color: transparent !important;
}
.el-menu:hover{
background-color: none !important;
background-color: transparent !important;
}
.el-sub-menu{
border-radius: 10rem !important;
list-style: none !important;
margin: 0 !important;
padding-left: 0 !important;
background-color: none !important;
background-color: transparent !important;
}
/* 深选择器获取menu__title */
@@ -140,12 +144,17 @@ onMounted(async () => {
/* padding-left: 0 !important; */
font-size: 1rem;
border-radius: 1rem;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.el-sub-menu :deep(.el-sub-menu__title:hover){
/* padding-left: 0 !important; */
color: #fff;
background-color: #409EFF;
background: linear-gradient(135deg, #409EFF, #667eea);
border-radius: 1rem;
box-shadow: 0 4px 15px rgba(64, 158, 255, 0.3);
}
.el-menu-item{
@@ -154,15 +163,77 @@ onMounted(async () => {
height: 38px!important;
margin: 10px 0;
border-radius: 1rem !important;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.el-menu-item::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 3px;
height: 100%;
background: linear-gradient(180deg, #409EFF, #667eea);
transform: scaleY(0);
transform-origin: center;
transition: transform 0.3s ease;
border-radius: 0 1rem 1rem 0;
}
.el-menu-item:hover::before,
.el-menu-item.is-active::before {
transform: scaleY(1);
}
.el-menu-item.is-active{
color: #fff;
background-color: #409EFF;
background: linear-gradient(135deg, #409EFF, #667eea);
border-radius: 1rem;
box-shadow: 0 4px 15px rgba(64, 158, 255, 0.3);
}
.el-menu-item:hover{
color: #fff;
background-color: #409EFF;
background: linear-gradient(135deg, #409EFF, #667eea);
border-radius: 1rem;
box-shadow: 0 4px 15px rgba(64, 158, 255, 0.3);
}
/* 简约Logo区域 */
.logo-container {
position: relative;
border-radius: 12px;
}
/* 广告位样式 */
.ad-container {
position: fixed;
bottom: 20px;
left: 20px;
width: 200px;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
}
.ad-container:hover {
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
transform: translateY(-2px);
}
.ad-link {
display: block;
width: 100%;
height: 100%;
}
.ad-image {
width: 100%;
height: auto;
display: block;
border-radius: 8px;
}
</style>
@@ -13,8 +13,8 @@ onMounted(() => {
<template>
<!-- desc -->
<div class="mt-3 rounded-2xl bg-white p-4">
<el-divider content-position="left">{{ props.title }}</el-divider>
<div class="mt-3 rounded-2xl p-4 tech-detail-section">
<el-divider content-position="left" class="tech-divider">{{ props.title }}</el-divider>
<div class="m-4">
<slot></slot>
</div>
@@ -22,5 +22,32 @@ onMounted(() => {
</template>
<style scoped>
/* 科技感详情区块 */
.tech-detail-section {
background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%);
position: relative;
overflow: hidden;
}
/* 科技感分割线 */
.tech-divider {
position: relative;
}
.tech-divider .el-divider__text {
background: linear-gradient(135deg, #ffffff 0%, #f8f9ff 100%);
padding: 0 16px;
font-weight: 600;
color: #333;
}
.tech-divider::before {
background: linear-gradient(90deg, #409EFF, transparent);
}
.tech-divider::after {
background: linear-gradient(90deg, transparent, #667eea);
}
</style>