初始化代码
This commit is contained in:
33
src/views/layout/pc/footer/components/QRCode.vue
Normal file
33
src/views/layout/pc/footer/components/QRCode.vue
Normal file
@ -0,0 +1,33 @@
|
||||
<script setup>
|
||||
import {ref, onMounted} from 'vue'
|
||||
onMounted(() => {})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="QR-code">
|
||||
<img class="QR-img" :src="`./static/images/footer/QR_code.png`" />
|
||||
<div class="label">企业微信</div>
|
||||
<img class="QR-img item" :src="`./static/images/footer/mark.png`" alt="" />
|
||||
<div class="label">熊雨翔</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.QR-code {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: $white;
|
||||
.QR-img {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
}
|
||||
.label {
|
||||
margin-top: 10px;
|
||||
text-align: center;
|
||||
color: $white;
|
||||
}
|
||||
.item {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
40
src/views/layout/pc/footer/components/logo.vue
Normal file
40
src/views/layout/pc/footer/components/logo.vue
Normal file
@ -0,0 +1,40 @@
|
||||
<script setup>
|
||||
import {ref, onMounted} from 'vue'
|
||||
onMounted(() => {})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="logo flex column j-s">
|
||||
<img class="logo-img" src="/static/images/footer/logo.png" />
|
||||
<div class="logo-CN">燃谷科技</div>
|
||||
<div class="logo-EN">RANGUTECH</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.logo {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
color: $white;
|
||||
|
||||
.logo-img {
|
||||
width: 204px;
|
||||
height: 204px;
|
||||
}
|
||||
.logo-CN {
|
||||
font-family: 'HYDaHeiJ';
|
||||
font-weight: 400;
|
||||
font-style: 'normal';
|
||||
font-size: 38px;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
.logo-EN {
|
||||
font-family: 'HYZhongHeiJ';
|
||||
font-weight: 400;
|
||||
font-style: 'normal';
|
||||
font-size: 24px;
|
||||
letter-spacing: 0.23em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
37
src/views/layout/pc/footer/components/nav.vue
Normal file
37
src/views/layout/pc/footer/components/nav.vue
Normal file
@ -0,0 +1,37 @@
|
||||
<script setup>
|
||||
import {ref, onMounted} from 'vue'
|
||||
import NavNode from './navNode.vue'
|
||||
import {useNavStore} from '@/store/nav'
|
||||
import {useRouter} from 'vue-router'
|
||||
const navStore = useNavStore()
|
||||
const router = useRouter()
|
||||
const footerNav = ref([])
|
||||
|
||||
onMounted(() => {
|
||||
footerNav.value = window.nav.footer
|
||||
})
|
||||
|
||||
const navClick = (url) => {
|
||||
navStore.changeNavIndex(url)
|
||||
router.push(url)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ul class="footer-nav flex j-s">
|
||||
<NavNode
|
||||
v-for="node in footerNav"
|
||||
:key="node.id"
|
||||
:node="node"
|
||||
@nav-click="navClick"
|
||||
/>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.footer-nav {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
63
src/views/layout/pc/footer/components/navNode.vue
Normal file
63
src/views/layout/pc/footer/components/navNode.vue
Normal file
@ -0,0 +1,63 @@
|
||||
<script setup>
|
||||
defineProps({
|
||||
node: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const emits = defineEmits(['navClick'])
|
||||
|
||||
const onClick = (url) => emits('navClick', url)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<li class="footer-nav__item">
|
||||
<div class="item-label" @click="onClick(node.url)">
|
||||
{{ node.label }}
|
||||
</div>
|
||||
|
||||
<!-- 递归渲染子节点 -->
|
||||
<ul v-if="node.children?.length" class="footer-nav__sub">
|
||||
<NavNode
|
||||
class="sub-item"
|
||||
v-for="child in node.children"
|
||||
:key="child.id"
|
||||
:node="child"
|
||||
@nav-click="onClick"
|
||||
/>
|
||||
</ul>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.footer-nav__item {
|
||||
.item-label {
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
font-size: 24px;
|
||||
color: $white;
|
||||
user-select: auto;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
&:hover {
|
||||
-webkit-transform: translateY(-8px);
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer-nav__sub {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin-top: 40px;
|
||||
.sub-item {
|
||||
margin-bottom: 24px;
|
||||
.item-label {
|
||||
font-family: 'PingFang SC';
|
||||
font-weight: 400;
|
||||
font-size: 20px;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
75
src/views/layout/pc/footer/index.vue
Normal file
75
src/views/layout/pc/footer/index.vue
Normal file
@ -0,0 +1,75 @@
|
||||
<script setup>
|
||||
import {ref, onMounted} from 'vue'
|
||||
import Logo from './components/logo.vue'
|
||||
import Nav from './components/nav.vue'
|
||||
import QRCode from './components/QRCode.vue'
|
||||
onMounted(() => {})
|
||||
|
||||
const toMIIF = () => {
|
||||
window.open('https://beian.miit.gov.cn')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page flex a-c">
|
||||
<!-- logo -->
|
||||
<Logo id="logo" />
|
||||
|
||||
<!-- 内容 -->
|
||||
<Nav id="nav" />
|
||||
|
||||
<!-- 二维码 -->
|
||||
<QRCode id="QR" />
|
||||
|
||||
<div id="MIIT-Filing">
|
||||
<span class="company">
|
||||
Copyright © 2023.Rangu Technology Co.,Ltd. All rights reserved.
|
||||
燃谷科技(南京)有限公司
|
||||
</span>
|
||||
<span class="url" @click="toMIIF">苏ICP备2023030548号</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page {
|
||||
background-color: $bg_color;
|
||||
position: relative;
|
||||
#logo {
|
||||
width: 220px;
|
||||
height: 300px;
|
||||
position: absolute;
|
||||
top: 58px;
|
||||
left: 190px;
|
||||
}
|
||||
#nav {
|
||||
width: calc(100% - 410px - 380px);
|
||||
position: absolute;
|
||||
left: 410px;
|
||||
top: 87px;
|
||||
padding: 0 90px 0 55px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#QR {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
position: absolute;
|
||||
top: 87px;
|
||||
right: 180px;
|
||||
}
|
||||
#MIIT-Filing {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
.company {
|
||||
color: $white;
|
||||
}
|
||||
.url {
|
||||
margin-left: 50px;
|
||||
color: #0056b3;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
35
src/views/layout/pc/header/index.vue
Normal file
35
src/views/layout/pc/header/index.vue
Normal file
@ -0,0 +1,35 @@
|
||||
<script setup>
|
||||
import Nav from './nav.vue'
|
||||
import {ref, onMounted} from 'vue'
|
||||
onMounted(() => {})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page flex a-c">
|
||||
<div class="logo"></div>
|
||||
<Nav class="nav"></Nav>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.page {
|
||||
background-color: $bg_color;
|
||||
.logo {
|
||||
background-image: url('/static/images/header/logo.png');
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
width: 173px;
|
||||
height: 72px;
|
||||
position: absolute;
|
||||
left: 160px;
|
||||
}
|
||||
|
||||
.nav {
|
||||
width: 1000px;
|
||||
height: 100px;
|
||||
position: absolute;
|
||||
right: 160px;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
91
src/views/layout/pc/header/nav.vue
Normal file
91
src/views/layout/pc/header/nav.vue
Normal file
@ -0,0 +1,91 @@
|
||||
<script setup>
|
||||
import {ref, onMounted, watch, onUnmounted} from 'vue'
|
||||
import {useNavStore} from '@/store/nav'
|
||||
import {storeToRefs} from 'pinia'
|
||||
|
||||
// Store 相关
|
||||
const navStore = useNavStore()
|
||||
const {navIndex} = storeToRefs(navStore)
|
||||
|
||||
// 响应式数据
|
||||
const navList = ref([])
|
||||
const activeIndex = ref(null)
|
||||
|
||||
// 处理导航选择
|
||||
const handleSelect = (key) => {
|
||||
navStore.changeNavIndex(key)
|
||||
}
|
||||
|
||||
// 监听 store 中的 navIndex 变化
|
||||
const stopWatch = watch(
|
||||
navIndex,
|
||||
(newValue) => {
|
||||
activeIndex.value = newValue
|
||||
},
|
||||
{
|
||||
immediate: true,
|
||||
}
|
||||
)
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
navList.value = window.nav.header || []
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
stopWatch()
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page">
|
||||
<el-menu
|
||||
:default-active="activeIndex"
|
||||
class="el-menu-demo"
|
||||
mode="horizontal"
|
||||
@select="handleSelect"
|
||||
active-text-color="#FFFFFF"
|
||||
text-color="#999999"
|
||||
background-color="$bg_color"
|
||||
router
|
||||
>
|
||||
<el-menu-item
|
||||
v-for="item in navList"
|
||||
:key="item.id"
|
||||
:index="item.url"
|
||||
:class="{'is-active': activeIndex === item.url}"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-menu-item>
|
||||
</el-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 菜单容器样式 */
|
||||
.el-menu--horizontal {
|
||||
--el-menu-horizontal-height: 101px;
|
||||
}
|
||||
|
||||
/* 菜单项基础样式 */
|
||||
.el-menu-item {
|
||||
font-family: 'PingFang SC';
|
||||
padding: 0 25px;
|
||||
font-weight: 400;
|
||||
font-size: 24px;
|
||||
line-height: 100%;
|
||||
letter-spacing: 0.06em;
|
||||
border-bottom: none !important;
|
||||
transition: border-bottom 0.3s ease;
|
||||
|
||||
/* 激活状态样式 */
|
||||
&.is-active {
|
||||
border-bottom: 6px solid #ffffff !important;
|
||||
}
|
||||
|
||||
/* 悬停效果 */
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1) !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user