Commit 3d59ad6a by yang

首次提交

parents
# 企业官网
基于 Vue 3 + Element Plus + Vite + JavaScript 构建的现代化企业官网。
## 技术栈
- **Vue 3** - 渐进式 JavaScript 框架
- **Element Plus** - Vue 3 组件库
- **Vite** - 下一代前端构建工具
- **Vue Router** - Vue.js 官方路由管理器
## 项目结构
```
├── public/ # 静态资源
├── src/
│ ├── components/ # 组件
│ │ ├── Layout.vue # 布局组件
│ │ ├── Header.vue # 头部组件
│ │ └── Footer.vue # 底部组件
│ ├── views/ # 页面
│ │ └── Home.vue # 首页
│ ├── router/ # 路由配置
│ │ └── index.js
│ ├── App.vue # 根组件
│ ├── main.js # 入口文件
│ └── style.css # 全局样式
├── index.html # HTML 模板
├── package.json # 项目配置
├── vite.config.js # Vite 配置
└── README.md # 项目说明
```
## 功能特性
- ✅ 响应式布局设计
- ✅ 现代化 UI 界面
- ✅ 轮播图展示
- ✅ 产品服务展示
- ✅ 新闻动态
- ✅ 公司介绍
- ✅ 联系方式
- ✅ 移动端适配
## 快速开始
### 安装依赖
```bash
npm install
```
### 启动开发服务器
```bash
npm run dev
```
### 构建生产版本
```bash
npm run build
```
### 预览生产版本
```bash
npm run preview
```
## 页面布局
项目采用经典的头部 + 内容 + 底部布局:
- **头部 (Header)**: 包含 Logo、导航菜单和操作按钮
- **内容区 (Main Content)**: 根据页面内容自适应高度,最小高度为 100vh
- **底部 (Footer)**: 包含公司信息、快速链接、联系方式和社交媒体
## 自定义配置
### 修改公司信息
`src/components/Header.vue``src/components/Footer.vue` 中修改公司名称、联系方式等信息。
### 添加新页面
1.`src/views/` 目录下创建新的 Vue 组件
2.`src/router/index.js` 中添加路由配置
3.`src/components/Header.vue` 中添加导航菜单项
### 自定义样式
- 全局样式:修改 `src/style.css`
- 组件样式:在各组件的 `<style>` 标签中修改
## 浏览器支持
- Chrome >= 87
- Firefox >= 78
- Safari >= 14
- Edge >= 88
## 许可证
MIT License
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>企业官网</title>
<style>
::-webkit-scrollbar {
display: none;
}
</style>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
\ No newline at end of file
{
"name": "company-website",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"dependencies": {
"vue": "^3.4.0",
"element-plus": "^2.4.0",
"vue-router": "^4.2.0"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.5.0",
"sass-embedded": "^1.93.2",
"vite": "^5.0.0"
}
}
<template>
<div id="app">
<router-view />
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
@import url(../src/views/common.css);
#app {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.Bc{
background-color: #333;
}
.Border{
border: 1px solid red;
}
</style>
<template>
<div
class="button-container"
:class="{
'read-more': type === 'read-more',
'custom': type === 'custom'
}"
:style="customStyles"
@click="handleClick"
>
<div
v-if="type === 'read-more'"
class="read-more-wrapper"
>
<span class="read-more-text">{{ text }}</span>
</div>
<div
v-else-if="type === 'custom'"
class="custom-wrapper"
:style="innerStyles"
>
<span class="custom-text" :style="textStyles">{{ text }}</span>
</div>
<button
v-else
class="button-element"
:class="{
'submit-btn': type === 'submit',
'contact-btn': type === 'contact'
}"
:style="buttonStyles"
@click="handleClick"
>
{{ text }}
</button>
</div>
</template>
<script>
export default {
name: 'Button',
props: {
// 按钮类型
type: {
type: String,
default: 'default', // read-more, submit, contact, custom
validator: (value) => ['read-more', 'submit', 'contact', 'custom'].includes(value)
},
// 按钮文本
text: {
type: String,
default: '按钮'
},
// 尺寸
width: {
type: String,
default: ''
},
height: {
type: String,
default: ''
},
// 自定义样式
backgroundColor: {
type: String,
default: ''
},
borderRadius: {
type: String,
default: ''
},
fontSize: {
type: String,
default: ''
},
fontColor: {
type: String,
default: ''
},
fontWeight: {
type: String,
default: ''
},
fontFamily: {
type: String,
default: ''
},
// READ MORE 特定样式
readMoreWidth: {
type: String,
default: '10.42vw'
},
readMoreHeight: {
type: String,
default: '3.13vw'
},
// 联系按钮特定样式
contactSize: {
type: Object,
default: () => ({
width: '27.86vw',
height: '5.42vw'
})
},
// 禁用状态
disabled: {
type: Boolean,
default: false
}
},
computed: {
customStyles() {
const baseStyles = this.type === 'read-more' ? {
width: this.readMoreWidth,
height: this.readMoreHeight
} : this.type === 'custom' ? {
...this.contactSize
} : {}
return baseStyles
},
innerStyles() {
return {
backgroundColor: this.backgroundColor || 'rgba(0, 82, 217, 1)',
borderRadius: this.borderRadius || '48px'
}
},
textStyles() {
return {
fontSize: this.fontSize || '1.25vw',
fontWeight: this.fontWeight || '700',
fontFamily: this.fontFamily || '',
color: this.fontColor || 'rgba(255, 255, 255, 1)'
}
},
buttonStyles() {
const styles = {}
if (this.type === 'submit') {
Object.assign(styles, {
backgroundColor: 'rgba(0, 82, 217, 1)',
borderRadius: '7px',
fontSize: '1.25vw',
fontWeight: '700',
border: 'none',
color: 'rgba(255, 255, 255, 1)'
})
} else if (this.type === 'contact') {
Object.assign(styles, {
backgroundColor: 'rgba(0, 82, 217, 1)',
borderRadius: '48px',
width: this.contactSize.width || '27.86vw',
height: this.contactSize.height || '5.42vw',
fontSize: '1.25vw',
fontWeight: '700',
border: 'none',
color: 'rgba(255, 255, 255, 1)'
})
}
// 覆盖默认值
if (this.width) styles.width = this.width
if (this.height) styles.height = this.height
if (this.backgroundColor) styles.backgroundColor = this.backgroundColor
if (this.fontSize) styles.fontSize = this.fontSize
if (this.fontColor) styles.color = this.fontColor
return styles
}
},
methods: {
handleClick(event) {
if (this.disabled) return
this.$emit('click', event)
}
}
}
</script>
<style scoped>
.button-container {
cursor: pointer;
user-select: none;
}
.button-container.read-more {
background-image: url('https://lanhu-oss-proxy.lanhuapp.com/40fca7311ab5e3d5eabe97a53becf2da');
background-size: 100% 100%;
background-repeat: no-repeat;
display: flex;
align-items: center;
justify-content: center;
}
.button-element {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
outline: none;
transition: all 0.3s ease;
}
.button-element:hover:not(:disabled) {
opacity: 0.8;
transform: translateY(-1px);
}
.button-element:active:not(:disabled) {
transform: translateY(0);
}
.button-element:disabled {
cursor: not-allowed;
opacity: 0.6;
}
.read-more-wrapper {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.read-more-text {
font-size: 0.93vw;
font-family: 'Gilroy-Bold', sans-serif;
font-weight: 700;
color: rgba(255, 255, 255, 1);
white-space: nowrap;
text-align: center;
}
.custom-wrapper {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
transition: all 0.3s ease;
}
.custom-wrapper:hover {
opacity: 0.8;
transform: translateY(-1px);
}
.custom-text {
text-align: center;
white-space: nowrap;
}
</style>
<template>
<footer class="footer-container">
<div class="group_5 flex-row">
<div class="section_2 flex-col">
<span class="text_40">公司备案信息</span>
<span class="text_41">经营许可证编号:川B2-20240967&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ICP备案/许可证号:川ICP备2024173426号</span>
<div class="text-wrapper_11 flex-row justify-between">
<span class="text_42">联系我们</span>
<span class="text_43">导航</span>
</div>
<div class="text-wrapper_12 flex-row justify-between">
<span class="text_44">客服热线:400-888-9999</span>
<span class="text_45">企业总部地址:四川省成都市天府新区正兴街道上和领誉</span>
</div>
</div>
<span class="paragraph_6">微信扫一扫<br />关注阳生万物微信</span>
<img class="image_20"
src="https://lanhu-oss-proxy.lanhuapp.com/cef61f20ba097d29b200adb4299619aa" />
<img class="image_21"
src="https://lanhu-oss-proxy.lanhuapp.com/8af8fa0cbc04b171ff65e21f4116c917" />
</div>
</footer>
</template>
<script>
export default {
name: 'Footer',
}
</script>
<style scoped>
.footer-container {
position: relative;
left: 0;
top: 0;
width: 100vw;
height: 18.23vw;
background: url(https://lanhu-oss-proxy.lanhuapp.com/c2cb5daeef69f21f1d202a4cca135e34) 100% no-repeat;
background-size: 100% 100%;
justify-content: flex-center;
}
.section_2 {
width: 34.85vw;
height: 8.91vw;
margin: 4.68vw 0 0 13.48vw;
}
.text_40 {
width: 6.88vw;
height: 1.15vw;
overflow-wrap: break-word;
color: rgba(255, 255, 255, 1);
font-size: 1.14vw;
font-family: MicrosoftYaHei-Bold;
font-weight: 700;
text-align: left;
white-space: nowrap;
line-height: 1.25vw;
margin-left: 0.06vw;
}
.text_41 {
width: 30.11vw;
height: 0.84vw;
overflow-wrap: break-word;
color: rgba(255, 255, 255, 1);
font-size: 0.83vw;
text-align: left;
white-space: nowrap;
line-height: 1.25vw;
margin-top: 1.15vw;
}
.text-wrapper_11 {
width: 16.25vw;
height: 1.15vw;
margin: 2.65vw 0 0 0.1vw;
}
.text_42 {
width: 4.54vw;
height: 1.15vw;
overflow-wrap: break-word;
color: rgba(255, 255, 255, 1);
font-size: 1.14vw;
font-family: MicrosoftYaHei-Bold;
font-weight: 700;
text-align: left;
white-space: nowrap;
line-height: 1.25vw;
}
.text_43 {
width: 2.3vw;
height: 1.15vw;
overflow-wrap: break-word;
color: rgba(255, 255, 255, 1);
font-size: 1.14vw;
font-family: MicrosoftYaHei-Bold;
font-weight: 700;
text-align: left;
white-space: nowrap;
line-height: 1.25vw;
}
.text-wrapper_12 {
width: 34.8vw;
height: 0.84vw;
margin: 1.14vw 0 0 0.05vw;
}
.text_44 {
width: 9.8vw;
height: 0.84vw;
overflow-wrap: break-word;
color: rgba(255, 255, 255, 1);
font-size: 0.83vw;
text-align: left;
white-space: nowrap;
line-height: 1.25vw;
}
.text_45 {
width: 20.84vw;
height: 0.84vw;
overflow-wrap: break-word;
color: rgba(255, 255, 255, 1);
font-size: 0.83vw;
text-align: left;
white-space: nowrap;
line-height: 1.25vw;
}
.paragraph_6 {
width: 7.5vw;
height: 2.19vw;
overflow-wrap: break-word;
color: rgba(255, 255, 255, 1);
font-size: 0.93vw;
font-family: MicrosoftYaHei-Bold;
font-weight: 700;
text-align: right;
line-height: 1.25vw;
margin: 8.02vw 0 0 20.41vw;
}
.image_20 {
width: 8.86vw;
height: 8.86vw;
margin: 4.68vw 13.54vw 0 1.35vw;
}
.image_21 {
position: absolute;
left: 79.43vw;
top: -2.6vw;
width: 5.21vw;
height: 5.21vw;
}
</style>
\ No newline at end of file
<template>
<div class="form-input-container" :class="{ 'half-width': halfWidth, 'full-width': !halfWidth }">
<!-- 单行输入框 -->
<div
v-if="type === 'input'"
class="input-wrapper"
:style="{ backgroundColor: backgroundColor, borderRadius: borderRadius }"
:class="{ 'border': showBorder }"
>
<div class="input-content">
<span v-if="required" class="required-star">*</span>
<span class="placeholder-text">{{ placeholder }}</span>
<img
v-if="showDropdown"
class="dropdown-icon"
:src="dropdownIcon"
alt="Dropdown"
/>
</div>
<input
type="text"
v-model="inputValue"
@input="onInput"
@focus="onFocus"
@blur="onBlur"
class="actual-input"
/>
</div>
<!-- 多行文本框 -->
<div
v-else-if="type === 'textarea'"
class="textarea-wrapper"
:style="{ backgroundColor: backgroundColor, borderRadius: borderRadius }"
:class="{ 'border': showBorder }"
>
<span v-if="required" class="required-star">*</span>
<span class="placeholder-text">{{ placeholder }}</span>
<textarea
v-model="inputValue"
@input="onInput"
@focus="onFocus"
@blur="onBlur"
class="actual-textarea"
:rows="rows"
></textarea>
</div>
<!-- 按钮样式 -->
<div
v-else-if="type === 'button'"
class="button-wrapper"
:style="{
backgroundColor: buttonBackgroundColor,
borderRadius: borderRadius,
width: buttonWidth,
height: buttonHeight
}"
@click="onClick"
>
<span class="button-text">{{ buttonText }}</span>
</div>
</div>
</template>
<script>
export default {
name: 'FormInput',
props: {
// 基础属性
type: {
type: String,
default: 'input', // input, textarea, button
validator: (value) => ['input', 'textarea', 'button'].includes(value)
},
placeholder: {
type: String,
default: ''
},
value: {
type: String,
default: ''
},
required: {
type: Boolean,
default: false
},
// 样式相关
halfWidth: {
type: Boolean,
default: true
},
backgroundColor: {
type: String,
default: 'rgba(255, 255, 255, 1)'
},
borderRadius: {
type: String,
default: '7px'
},
showBorder: {
type: Boolean,
default: true
},
// 下拉框相关
showDropdown: {
type: Boolean,
default: false
},
dropdownIcon: {
type: String,
default: 'https://lanhu-oss-proxy.lanhuapp.com/521f55faa9b95a5334fb78149385111f'
},
// 文本域相关
rows: {
type: Number,
default: 10
},
// 按钮相关
buttonText: {
type: String,
default: ''
},
buttonBackgroundColor: {
type: String,
default: 'rgba(0, 82, 217, 1)'
},
buttonWidth: {
type: String,
default: '22.92vw'
},
buttonHeight: {
type: String,
default: '3.13vw'
}
},
data() {
return {
inputValue: this.value
}
},
watch: {
value(newVal) {
this.inputValue = newVal
},
inputValue(newVal) {
this.$emit('input', newVal)
}
},
methods: {
onInput(event) {
this.inputValue = event.target.value
this.$emit('input', this.inputValue)
},
onFocus(event) {
this.$emit('focus', event)
},
onBlur(event) {
this.$emit('blur', event)
},
onClick() {
this.$emit('click')
}
}
}
</script>
<style scoped>
.form-input-container {
margin-bottom: 1.04vw;
}
.half-width {
width: 35.94vw;
}
.full-width {
width: 72.92vw;
}
.input-wrapper, .textarea-wrapper {
border: 1px solid rgba(210, 210, 210, 1);
border-radius: 7px;
position: relative;
overflow: hidden;
}
.input-wrapper {
height: 3.13vw;
}
.textarea-wrapper {
height: 10.42vw;
}
.input-content {
display: flex;
align-items: center;
height: 100%;
padding: 0 1.09vw;
pointer-events: none;
}
.required-star {
color: rgba(255, 0, 0, 1);
font-size: 0.93vw;
font-family: OPPOSans-M;
font-weight: 500;
margin-right: 0.1vw;
}
.placeholder-text {
color: rgba(149, 149, 149, 1);
font-size: 0.93vw;
font-family: OPPOSans-M;
font-weight: 500;
flex: 1;
}
.dropdown-icon {
width: 1.05vw;
height: 0.58vw;
}
.actual-input, .actual-textarea {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: transparent;
border: none;
outline: none;
padding: 0 1.09vw;
font-size: 0.93vw;
font-family: OPPOSans-M;
font-weight: 500;
color: rgba(0, 0, 0, 1);
}
.actual-textarea {
padding-top: 1.09vw;
padding-bottom: 1.09vw;
resize: none;
}
.button-wrapper {
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.button-text {
color: rgba(255, 255, 255, 1);
font-size: 1.25vw;
font-family: OPPOSans-B;
font-weight: 700;
text-align: center;
}
input::placeholder {
color: rgba(149, 149, 149, 1);
}
input:focus::placeholder {
opacity: 0;
}
input:focus + .placeholder-text {
opacity: 0;
}
</style>
<template>
<div class="header-nav-container" :class="{ 'nav-scrolled': isScrolled }" @scroll="handleScroll">
<div class="header-nav flex-row justify-between">
<!-- Logo -->
<router-link to="/" class="logo-link">
<div></div>
<img class="logo" src="https://lanhu-oss-proxy.lanhuapp.com/ebd4f654aa980ff6d0ac01d3bf9724ee"
alt="自愈舱官网" />
</router-link>
<!-- 导航菜单 -->
<nav class="nav-menu flex-row">
<router-link to="/" class="nav-link" :class="{ 'active': currentRoute === '/' }">
首页
</router-link>
<router-link to="/brand" class="nav-link" :class="{ 'active': currentRoute === '/brand' }">
品牌介绍
</router-link>
<!-- 自愈舱下拉菜单 -->
<div class="dropdown-container" @mouseenter="showDropdown = true" @mouseleave="showDropdown = false">
<div class="nav-link dropdown-trigger" :class="{ 'active': isServeRouteActive }">
自愈舱
</div>
<div class="dropdown-menu" :class="{ 'show': showDropdown }">
<router-link to="/Product" class="dropdown-item" @click="hideDropdown">产品介绍</router-link>
<router-link to="/case" class="dropdown-item" @click="hideDropdown">用户案例</router-link>
<router-link to="/serve" class="dropdown-item" @click="hideDropdown">增值服务</router-link>
</div>
</div>
<router-link to="/cooperation" class="nav-link" :class="{ 'active': currentRoute === '/cooperation' }">
合作优势
</router-link>
<router-link to="/certification" class="nav-link"
:class="{ 'active': currentRoute === '/certification' }">
企业资质
</router-link>
<router-link to="/contact-us" class="nav-link" :class="{ 'active': currentRoute === '/contact-us' }">
联系我们
</router-link>
</nav>
</div>
</div>
</template>
<script>
export default {
name: 'HeaderNav',
data() {
return {
isScrolled: false,
currentRoute: '/',
showDropdown: false
}
},
computed: {
// 检查是否在自愈舱相关路由
isServeRouteActive() {
const serveRoutes = ['/serve', '/case', '/agent', '/operator', '/lease']
return serveRoutes.includes(this.currentRoute)
}
},
mounted() {
// 监听窗口滚动事件
window.addEventListener('scroll', this.handleScroll)
// 初始化当前路由
this.currentRoute = this.$route.path
// 监听路由变化
this.$watch('$route', (to) => {
this.currentRoute = to.path
})
},
beforeUnmount() {
// 清理事件监听器
window.removeEventListener('scroll', this.handleScroll)
},
methods: {
// 处理滚动事件
handleScroll() {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop
// 降低阈值,让白色背景更早出现
this.isScrolled = scrollTop > 20
},
// 隐藏下拉菜单
hideDropdown() {
this.showDropdown = false
},
// 切换移动端菜单
toggleMobileMenu() {
// 可以在这里添加移动端菜单逻辑
console.log('切换移动端菜单')
},
// 导航到指定路由
navigateTo(route) {
this.$router.push(route)
}
}
}
</script>
<style scoped>
.header-nav-container {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 1000;
transition: all 0.3s ease;
/* 默认状态:完全透明,无背景,不占用布局空间 */
background-color: transparent;
/* 确保不占用布局空间 */
pointer-events: auto;
}
.nav-scrolled {
/* 滚动状态:显示白色半透明背景 */
background-color: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
box-shadow: 0 2px 20px rgba(0, 0, 0, 0.1);
}
.header-nav {
width: 94.8vw;
height: 4.95vw;
margin: 0 auto;
align-items: center;
position: relative;
/* 确保HeaderNav本身也是透明的 */
background-color: transparent;
}
.logo-link {
display: flex;
align-items: center;
text-decoration: none;
}
.logo {
width: 6vw;
height: 4vw;
margin: auto;
object-fit: contain;
}
.nav-menu {
flex: 1;
gap: 2.5vw;
list-style: none;
margin-left: 4vw;
padding: 0;
}
.nav-link {
text-decoration: none;
color: rgba(255, 255, 255, 1);
font-size: 1.04vw;
font-family: OPPOSans-M;
font-weight: 500;
white-space: nowrap;
transition: all 0.3s ease;
position: relative;
/* 添加文字阴影增强在透明背景下的可见性 */
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
.nav-link:hover {
color: rgba(0, 82, 217, 1);
}
.nav-link.active {
color: rgba(0, 82, 217, 1);
}
.nav-link.active::after {
content: '';
position: absolute;
bottom: -0.5vw;
left: 50%;
transform: translateX(-50%);
width: 1.5vw;
height: 0.15vw;
background-color: rgba(0, 82, 217, 1);
border-radius: 0.075vw;
}
/* 滚动时的样式变化 */
.nav-scrolled .nav-link {
color: rgba(51, 51, 51, 1);
/* 在白色背景下移除文字阴影 */
text-shadow: none;
}
.nav-scrolled .nav-link:hover,
.nav-scrolled .nav-link.active {
color: rgba(0, 82, 217, 1);
}
/* 下拉菜单样式 */
.dropdown-container {
position: relative;
display: inline-block;
}
.dropdown-trigger {
cursor: pointer;
display: flex;
align-items: center;
gap: 0.3vw;
}
.dropdown-arrow {
font-size: 0.8vw;
transition: transform 0.3s ease;
}
.dropdown-container:hover .dropdown-arrow {
transform: rotate(180deg);
}
.dropdown-menu {
position: absolute;
top: 215%;
left: 50%;
transform: translateX(-50%);
background-color: rgba(255, 255, 255, 0.98);
backdrop-filter: blur(10px);
border-top-right-radius: 0;
border-top-left: 8px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
min-width: 8vw;
opacity: 0;
visibility: hidden;
padding: 10px 0;
transform: translateX(-50%) translateY(-10px);
transition: all 0.3s ease;
z-index: 1001;
}
.dropdown-menu.show {
opacity: 1;
visibility: visible;
transform: translateX(-50%) translateY(0);
}
.dropdown-item {
display: block;
padding: 0.8vw 1.5vw;
color: rgba(51, 51, 51, 1);
text-decoration: none;
font-size: 0.9vw;
font-family: OPPOSans-M;
font-weight: 500;
transition: all 0.3s ease;
border-radius: 4px;
margin: 0 0.5vw;
}
.dropdown-item:hover {
background-color: rgba(0, 82, 217, 0.1);
color: rgba(0, 82, 217, 1);
}
.dropdown-item.router-link-active {
background-color: rgba(0, 82, 217, 0.1);
color: rgba(0, 82, 217, 1);
}
/* 滚动时下拉菜单样式 */
.nav-scrolled .dropdown-menu {
background-color: rgba(255, 255, 255, 0.98);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
}
/* 响应式设计 */
@media (max-width: 768px) {
.header-nav {
width: 100vw;
height: 12vw;
padding: 0 3vw;
}
.logo {
width: 15vw;
height: 12vw;
}
.nav-menu {
gap: 4vw;
display: none;
/* 移动端隐藏导航菜单 */
}
.nav-link {
font-size: 2.5vw;
}
}
@media (max-width: 480px) {
.header-nav {
height: 15vw;
}
.logo {
width: 18vw;
height: 15vw;
}
}
</style>
\ No newline at end of file
<template>
<div class="hero-section flex-col justify-end" :style="{ backgroundColor: backgroundColor, backgroundImage: `url(${backgroundImage})` }">
<!-- Tabs导航 (可选) -->
<div v-if="showTabNav" class="tab-navigation flex-row">
<div
v-for="(tab, index) in tabs"
:key="index"
class="tab-item flex-row"
:class="{ active: activeTab === index }"
@click="switchTab(index)"
>
<div
v-if="index === activeTab"
class="tab-active-bg flex-col"
:style="{ backgroundImage: `url(${activeTabBg})` }"
>
<span class="tab-text">{{ tab }}</span>
</div>
<span v-else class="tab-text">{{ tab }}</span>
<img
v-if="index < tabs.length - 1"
class="tab-divider"
:src="tabDivider"
alt=""
/>
</div>
</div>
<!-- 主要内容区域 -->
<div class="hero-content">
<!-- 标题区域 -->
<div v-if="title" class="title-section">
<h1 class="hero-title" v-if="title">{{ title }}</h1>
<h2 class="hero-subtitle" v-if="subtitle">{{ subtitle }}</h2>
<img
v-if="titleIcon"
class="title-icon"
:src="titleIcon"
alt=""
/>
</div>
<!-- 面包屑导航 (可选) -->
<div v-if="showBreadcrumb" class="breadcrumb-container flex-row">
<div class="breadcrumb-bg flex-col" :style="{ backgroundImage: `url(${breadcrumbBg})` }">
<span class="breadcrumb-text">{{ currentPage }}</span>
</div>
<img v-if="showHomeIcon" class="home-icon" :src="homeIcon" alt="HOME" />
<span v-if="showHomeIcon" class="home-text">HOME</span>
<img v-if="showHomeIcon" class="home-arrow" :src="homeArrow" alt="" />
</div>
</div>
</div>
</template>
<script>
export default {
name: 'HeroSection',
props: {
// 背景相关
backgroundColor: {
type: String,
default: ''
},
backgroundImage: {
type: String,
default: ''
},
// 标题相关
title: {
type: String,
default: ''
},
subtitle: {
type: String,
default: ''
},
titleIcon: {
type: String,
default: ''
},
// Tab导航相关
showTabNav: {
type: Boolean,
default: false
},
tabs: {
type: Array,
default: () => []
},
activeTab: {
type: Number,
default: 0
},
activeTabBg: {
type: String,
default: ''
},
tabDivider: {
type: String,
default: ''
},
// 面包屑相关
showBreadcrumb: {
type: Boolean,
default: true
},
currentPage: {
type: String,
default: ''
},
showHomeIcon: {
type: Boolean,
default: false
},
breadcrumbBg: {
type: String,
default: ''
},
homeIcon: {
type: String,
default: ''
},
homeArrow: {
type: String,
default: ''
}
},
methods: {
switchTab(index) {
this.$emit('tab-change', index)
}
}
}
</script>
<style scoped>
.hero-section {
height: 51.05vw;
background-size: 100% 100%;
width: 100vw;
position: relative;
}
.tab-navigation {
width: 86.46vw;
height: 5.21vw;
margin: 12.44vw 0 0 13.54vw;
background-size: 100% 100%;
}
.tab-item {
height: 5.21vw;
align-items: center;
}
.tab-text {
color: rgba(255, 255, 255, 1);
font-size: 1.56vw;
font-family: OPPOSans-R;
font-weight: normal;
text-align: center;
white-space: nowrap;
line-height: 2.19vw;
margin: 1.82vw 1vw 0;
}
.tab-active-bg {
height: 5.21vw;
background-repeat: no-repeat;
background-size: 100% 100%;
}
.tab-divider {
width: 0.06vw;
height: 2.3vw;
margin: 1.45vw 0;
}
.title-section {
position: absolute;
top: 2.86vw;
left: 13.54vw;
}
.hero-title {
width: auto;
height: 3.03vw;
font-size: 4.16vw;
font-family: Gilroy-Bold;
font-weight: 700;
text-align: left;
white-space: nowrap;
line-height: 3.75vw;
margin-bottom: 1.72vw;
color: rgba(255, 255, 255, 1);
}
.hero-subtitle {
width: auto;
height: 1.83vw;
font-size: 1.87vw;
font-family: OPPOSans-R;
font-weight: normal;
text-align: left;
white-space: nowrap;
line-height: 2.19vw;
margin-bottom: 1.56vw;
color: rgba(255, 255, 255, 1);
}
.title-icon {
width: 0.27vw;
height: 3.08vw;
}
.breadcrumb-container {
width: 86.46vw;
height: 5.21vw;
margin: 0;
}
.breadcrumb-bg {
height: 5.21vw;
background-repeat: no-repeat;
background-size: 100% 100%;
width: 18.23vw;
}
.breadcrumb-text {
width: 6.15vw;
height: 1.57vw;
color: rgba(255, 255, 255, 1);
font-size: 1.56vw;
font-family: OPPOSans-R;
font-weight: normal;
text-align: center;
white-space: nowrap;
line-height: 2.19vw;
margin: 1.82vw 0 0 6.04vw;
}
.home-icon {
width: 0.94vw;
height: 1.05vw;
margin: 2.03vw 2.6vw 0 2.6vw;
}
.home-text {
width: 2.56vw;
height: 0.73vw;
color: rgba(255, 255, 255, 1);
font-size: 0.93vw;
font-family: Gilroy-Medium;
font-weight: 500;
text-align: left;
white-space: nowrap;
line-height: 2.19vw;
margin-top: 0.21vw;
}
.home-arrow {
width: 0.94vw;
height: 1.05vw;
margin-left: 2.6vw;
}
</style>
<template>
<div class="layout">
<!-- 全局Header导航栏 -->
<HeaderNav />
<!-- 主要内容区域 -->
<main class="main-content">
<router-view />
</main>
<!-- 全局Footer页脚 -->
<Footer />
</div>
</template>
<script>
import HeaderNav from '@/components/HeaderNav.vue'
import Footer from '@/components/Footer.vue'
export default {
name: 'Layout',
components: {
HeaderNav,
Footer
}
}
</script>
<style scoped>
.layout {
min-height: 100vh;
display: flex;
flex-direction: column;
}
.main-content {
flex: 1;
/* 移除固定高度,让内容自然流动 */
}
</style>
<template>
<div
class="section-wrapper"
:class="sectionClasses"
:style="sectionStyles"
:id="sectionId"
>
<!-- 标题栏 -->
<div v-if="showTitle" class="section-title" :style="titleStyles">
<div v-if="titleIcon" class="title-icon-wrapper">
<img :src="titleIcon" alt="标题图标" class="title-icon" />
</div>
<span class="title-text">{{ title }}</span>
<div v-if="showTitleDecoration" class="title-decoration">
<span class="title-deco-text">了解更多</span>
<div class="title-deco-line"></div>
<img :src="arrowIcon" alt="箭头" class="title-arrow" />
</div>
</div>
<!-- 副标题 -->
<div v-if="subtitle" class="section-subtitle" :style="subtitleStyles">
<span>{{ subtitle }}</span>
</div>
<!-- 内容区域 -->
<div class="section-content" :class="contentClasses">
<slot></slot>
</div>
<!-- 背景图片 -->
<div
v-if="backgroundImage"
class="section-bg-image"
:style="{ backgroundImage: `url(${backgroundImage})` }"
></div>
<!-- 背景装饰 -->
<div
v-if="backgroundDecoration"
class="section-bg-decoration"
:style="{ backgroundImage: `url(${backgroundDecoration})` }"
></div>
</div>
</template>
<script>
export default {
name: 'SectionWrapper',
props: {
// 基础属性
sectionId: {
type: String,
default: ''
},
// 标题相关
showTitle: {
type: Boolean,
default: true
},
title: {
type: String,
default: ''
},
subtitle: {
type: String,
default: ''
},
titleIcon: {
type: String,
default: ''
},
// 布局相关
layout: {
type: String,
default: 'column', // column, row, two-column
validator: (value) => ['column', 'row', 'two-column'].includes(value)
},
align: {
type: String,
default: 'center', // flex-start, center, flex-end
validator: (value) => ['flex-start', 'center', 'flex-end'].includes(value)
},
justify: {
type: String,
default: 'space-between', // flex-start, center, flex-end, space-between
validator: (value) => ['flex-start', 'center', 'flex-end', 'space-between'].includes(value)
},
// 背景相关
backgroundImage: {
type: String,
default: ''
},
backgroundDecoration: {
type: String,
default: ''
},
backgroundColor: {
type: String,
default: ''
},
// 样式相关
padding: {
type: String,
default: ''
},
margin: {
type: String,
default: ''
},
borderRadius: {
type: String,
default: '5px'
},
boxShadow: {
type: String,
default: ''
},
// 特定布局样式
twoColumnContent: {
type: Object,
default: () => ({
leftWidth: '',
rightWidth: '',
leftHeight: '',
rightHeight: ''
})
},
// 标题装饰
showTitleDecoration: {
type: Boolean,
default: false
},
arrowIcon: {
type: String,
default: 'https://lanhu-oss-proxy.lanhuapp.com/c5c3af3e0d0b2b2b2b2b2b2b2b2b2b2b'
},
// 额外的CSS类
customClasses: {
type: String,
default: ''
}
},
computed: {
sectionClasses() {
const classes = ['flex-col']
if (this.customClasses) {
classes.push(this.customClasses)
}
return classes.join(' ')
},
contentClasses() {
const classes = []
switch (this.layout) {
case 'row':
classes.push('flex-row')
break
case 'two-column':
classes.push('flex-row', 'space-x-0') /* Tailwind equivalent */
break
default:
classes.push('flex-col')
}
classes.push(`justify-${this.justify}`, `items-${this.align}`)
return classes.join(' ')
},
sectionStyles() {
const styles = {}
if (this.padding) {
if (this.padding.includes('rem')) {
styles.padding = this.padding
} else {
styles.padding = `${this.padding}vw`
}
}
if (this.margin) {
if (this.margin.includes('rem')) {
styles.margin = this.margin
} else {
styles.margin = `${this.margin}vw`
}
}
if (this.backgroundColor) {
styles.backgroundColor = this.backgroundColor
}
if (this.borderRadius) {
styles.borderRadius = this.borderRadius
}
if (this.boxShadow) {
styles.boxShadow = this.boxShadow
}
return styles
},
titleStyles() {
const styles = {
height: this.showTitleDecoration ? '6.46vw' : 'auto',
paddingTop: '1.67vw',
paddingBottom: '0'
}
if (this.layout === 'row') {
styles.width = '26.11vw'
}
return styles
},
subtitleStyles() {
return {
paddingTop: '1.25vw',
paddingBottom: '1.25vw'
}
}
}
}
</script>
<style scoped>
.section-wrapper {
position: relative;
overflow: hidden;
}
.section-title {
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
}
.title-icon-wrapper {
width: 7.99vw;
height: 3.75vw;
position: relative;
}
.title-icon {
width: 100%;
height: 100%;
object-fit: contain;
}
.title-text {
overflow-wrap: break-word;
color: rgba(255, 255, 255, 1);
font-size: 2.5vw;
font-family: 'Gilroy-Bold', sans-serif;
font-weight: 700;
text-align: left;
white-space: nowrap;
line-height: 2.81vw;
margin: 0 1vw;
}
.title-decoration {
display: flex;
align-items: center;
height: 6.46vw;
}
.title-deco-text {
color: rgba(255, 255, 255, 1);
font-size: 1.25vw;
font-family: OPPOSans-M;
font-weight: 500;
white-space: nowrap;
line-height: 2.19vw;
}
.title-deco-line {
width: 5vw;
height: 1px;
background: rgba(255, 255, 255, 0.6);
margin-left: 1vw;
}
.title-arrow {
width: 0.52vw;
height: 0.52vw;
margin-left: 0.67vw;
}
.section-subtitle {
/* 样式根据需要调整 */
}
.section-content {
flex: 1;
position: relative;
z-index: 1;
}
.section-bg-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: 100% 100%;
background-repeat: no-repeat;
z-index: 0;
}
.section-bg-decoration {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
z-index: 0;
}
/* Tailwind-like classes for layout */
.flex-row {
display: flex;
flex-direction: row;
}
.flex-col {
display: flex;
flex-direction: column;
}
.justify-flex-start {
justify-content: flex-start;
}
.justify-center {
justify-content: center;
}
.justify-flex-end {
justify-content: flex-end;
}
.justify-space-between {
justify-content: space-between;
}
.items-flex-start {
align-items: flex-start;
}
.items-center {
align-items: center;
}
.items-flex-end {
align-items: flex-end;
}
.space-x-0 > * + * {
margin-left: 0;
}
/* 响应式设计 */
@media (max-width: 768px) {
.section-title {
flex-direction: column;
text-align: center;
}
.title-decoration {
margin-top: 1rem;
}
.section-content.flex-row,
.section-content.two-column {
flex-direction: column;
}
}
</style>
<template>
<div class="page_btn_box flex-row">
<div class="box_group_left flex-row">
<div v-for="item in btnGroup">
<div class=" align-center justify-around flex-col" @click="toPage(item)"
:class="item.isSelect == true ? 'item_select':'item_noselect'">
<span class="itemName">{{item.name}}</span>
</div>
</div>
</div>
<div class="box_group_right justify-around align-center">
<div>
<span class="home_title">HOME</span>
<img src="@/assets/common/home.png" />
</div>
</div>
</div>
</template>
<script setup>
import {
useRouter
} from 'vue-router/dist/vue-router';
const props = defineProps({
btnGroup: []
})
const router = useRouter()
const toPage = (item) => {
router.push(item.url)
}
</script>
<style scoped>
.page_btn_box {
width: 86vw;
height: 5.2vw;
margin: 12.4vw 0 0 14vw;
background-color: #00C7DA;
background-size: 100% 100%;
}
.box_group_left {
width: 70vw;
}
.box_group_right {
width: 16vw;
}
.item_select {
height: 5.2vw;
background-color: #0052D9;
background-size: 100% 100%;
width: 18vw;
}
.item_noselect {
height: 5.2vw;
background-size: 100% 100%;
width: 18vw;
}
.itemName {
overflow-wrap: break-word;
color: rgba(255, 255, 255, 1);
font-size: 1.6vw;
font-family: OPPOSans-R;
font-weight: normal;
text-align: center;
white-space: nowrap;
}
.home_title {
overflow-wrap: break-word;
color: rgba(255, 255, 255, 1);
font-size: 1vw;
font-family: Gilroy-Medium;
font-weight: 500;
text-align: left;
white-space: nowrap;
margin-right: 1vw;
position: relative;
top: -0.1vw;
}
</style>
\ No newline at end of file
/* src/assets/css/fonts.css */
/* 粗体 - Bold */
@font-face {
font-family: 'OPPOSans';
src: url('./OPPOSans/OPPOSans-B-2.ttf') format('truetype');
font-weight: 700;
/* Bold 对应 700 */
font-style: normal;
font-display: swap;
}
/* 特粗 - Heavy */
@font-face {
font-family: 'OPPOSans';
src: url('./OPPOSans/OPPOSans-H-2.ttf') format('truetype');
font-weight: 900;
/* Heavy 对应 900 */
font-style: normal;
font-display: swap;
}
/* 细体 - Light */
@font-face {
font-family: 'OPPOSans';
src: url('./OPPOSans/OPPOSans-L-2.ttf') format('truetype');
font-weight: 300;
/* Light 对应 300 */
font-style: normal;
font-display: swap;
}
/* 中等 - Medium */
@font-face {
font-family: 'OPPOSans';
src: url('./OPPOSans/OPPOSans-M-2.ttf') format('truetype');
font-weight: 500;
/* Medium 对应 500 */
font-style: normal;
font-display: swap;
}
/* 常规 - Regular */
@font-face {
font-family: 'OPPOSans';
src: url('./OPPOSans/OPPOSans-R-2.ttf') format('truetype');
font-weight: 400;
/* Regular 对应 400 */
font-style: normal;
font-display: swap;
}
/* DINEngsbek - Regular */
@font-face {
font-family: 'DINEngsbek-Alternate';
src: url('./DINEngAlt/DINEngAlt.ttf') format('truetype');
font-weight: 400;
font-style: normal;
font-display: swap;
}
\ No newline at end of file
import {
createApp
} from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import router from './router'
import App from './App.vue'
import './style.css'
import './font/fonts.css' // 引入字体样式
const app = createApp(App)
app.use(ElementPlus)
app.use(router)
app.mount('#app')
\ No newline at end of file
import {
createRouter,
createWebHistory
} from 'vue-router'
import Layout from '@/components/Layout.vue'
import Case from '@/views/Case.vue'
import Cooperation from '@/views/Cooperation.vue'
import Product from '@/views/Product.vue'
import Serve from '@/views/Serve.vue'
import lease from '@/views/lease.vue'
import operator from '@/views/operator.vue'
import agent from '@/views/agent.vue'
import certification from '@/views/certification.vue'
import contactUs from '@/views/contact-us.vue'
import tip from '@/views/tip.vue'
import brand from '@/views/brand.vue'
import homepage from '@/views/homepage.vue'
const routes = [{
path: '/',
component: Layout,
children: [{
path: '',
name: 'homepage',
component: homepage
},
{
path: 'brand',
name: 'brand',
component: brand
},
{
path: 'serve',
name: 'serve',
component: Serve
},
{
path: 'cooperation',
name: 'cooperation',
component: Cooperation
},
{
path: 'certification',
name: 'certification',
component: certification
},
{
path: 'contact-us',
name: 'contact-us',
component: contactUs
},
// 其他页面路由
{
path: 'tip',
name: 'tip',
component: tip
},
{
path: 'agent',
name: 'agent',
component: agent
},
{
path: 'operator',
name: 'operator',
component: operator
},
{
path: 'lease',
name: 'lease',
component: lease
},
{
path: 'Product',
name: 'Product',
component: Product
},
{
path: 'case',
name: 'case',
component: Case
}
]
}]
const router = createRouter({
history: createWebHistory(),
routes,
// 添加滚动行为,确保每次路由切换都滚动到顶部
scrollBehavior(to, from, savedPosition) {
// 如果有保存的位置(比如用户点击浏览器的前进/后退按钮),则恢复到该位置
if (savedPosition) {
return savedPosition
}
// 否则滚动到页面顶部
return {
top: 0
}
}
})
export default router
\ No newline at end of file
/* 全局样式重置 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
height: 100%;
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
}
#app {
min-height: 100vh;
display: flex;
flex-direction: column;
}
/* 自定义滚动条 */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #a8a8a8;
}
body * {
box-sizing: border-box;
flex-shrink: 0;
}
body {
font-family: PingFangSC-Regular, Roboto, Helvetica Neue, Helvetica, Tahoma,
Arial, PingFang SC-Light, Microsoft YaHei;
}
input {
background-color: transparent;
border: 0;
}
button {
margin: 0;
padding: 0;
border: 1px solid transparent;
outline: none;
background-color: transparent;
}
button:active {
opacity: 0.6;
}
.van-nav-bar__left:active,
.van-nav-bar__right:active {
opacity: 1;
}
[class*='van-']::after {
border-bottom: 0;
}
.flex-col {
display: flex;
flex-direction: column;
}
.flex-row {
display: flex;
flex-direction: row;
}
.justify-start {
display: flex;
justify-content: flex-start;
}
.justify-center {
display: flex;
justify-content: center;
}
.justify-end {
display: flex;
justify-content: flex-end;
}
.justify-evenly {
display: flex;
justify-content: space-evenly;
}
.justify-around {
display: flex;
justify-content: space-around;
}
.justify-between {
display: flex;
justify-content: space-between;
}
.align-start {
display: flex;
align-items: flex-start;
}
.align-center {
display: flex;
align-items: center;
}
.align-end {
display: flex;
align-items: flex-end;
}
/* HeaderNav现在是完全透明的,悬浮在背景图片之上,不需要预留空间 */
\ No newline at end of file
<template>
<div class="page flex-col">
<!-- 使用HeaderNav组件替代重复的导航栏 -->
<HeaderNav />
<div class="box_1 flex-col">
<div class="group_1 flex-col">
<div class="group_2 flex-col">
<div class="section_1 flex-col">
<div class="image-wrapper_1 flex-row">
<img
class="label_1"
src="https://lanhu-oss-proxy.lanhuapp.com/35353ba23ff97ba65d60f7ae05464f60"
/>
</div>
<div class="box_2 flex-row">
<div class="block_1 flex-col"></div>
</div>
<div class="box_3 flex-row">
<div class="text-group_1 flex-col justify-between">
<span class="text_1">感谢您的提交!</span>
<span class="text_2"
>我们已收到您的合作意向,专业的人员将在24小时内与您联系,请保持电话畅通。</span
>
</div>
</div>
<div class="image-wrapper_2 flex-row">
<img
class="image_1"
src="https://lanhu-oss-proxy.lanhuapp.com/51a16d5445a24b9a5bdadd501edf4e2b"
/>
</div>
<div class="box_4 flex-row">
<div class="text-wrapper_1">
<span class="text_3">直接联系信息:</span>
<span class="text_4">13641398000(雷女士)</span>
</div>
</div>
</div>
</div>
</div>
<!-- 使用Footer组件 -->
<Footer />
</div>
</div>
</template>
<script>
import HeaderNav from '@/components/HeaderNav.vue'
import Footer from '@/components/Footer.vue'
import HeroSection from '@/components/HeroSection.vue'
export default {
components: {
HeaderNav,
Footer,
HeroSection
},
data() {
return {
constants: {},
};
},
methods: {},
};
</script>
<style src="./common.css" />
<style scoped>
.page {
position: relative;
width: 100vw;
height: 165.32vw;
overflow: hidden;
}
.box_1 {
height: 165.32vw;
background: url(https://lanhu-oss-proxy.lanhuapp.com/8c77c00fde8dc36a7663b507929f3dee)
100% no-repeat;
background-size: 100% 100%;
width: 100vw;
}
.group_1 {
height: 165.32vw;
background: url(https://lanhu-oss-proxy.lanhuapp.com/54f3adbf4fe2132c839bfe4bb854384a)
100% no-repeat;
background-size: 100% 100%;
width: 100vw;
}
.group_2 {
height: 165.32vw;
background: url(https://lanhu-oss-proxy.lanhuapp.com/022182794b19df8ae1fc92da124ff6d8)
100% no-repeat;
background-size: 100% 100%;
width: 100vw;
}
.section_1 {
background-color: rgba(255, 255, 255, 1);
border-radius: 40px;
height: 36.36vw;
width: 52.09vw;
margin: 64.58vw 0 0 23.95vw;
}
.image-wrapper_1 {
width: 2.3vw;
height: 2.3vw;
margin: 0.98vw 0 0 48.75vw;
}
.label_1 {
width: 2.3vw;
height: 2.3vw;
}
.box_2 {
width: 6.2vw;
height: 6.2vw;
margin: 2.91vw 0 0 22.96vw;
}
.block_1 {
width: 6.2vw;
height: 6.2vw;
background: url(https://lanhu-oss-proxy.lanhuapp.com/3e5331b5e3303e1b2218ad355c8e2813)
100% no-repeat;
background-size: 100% 100%;
}
.box_3 {
width: 34.43vw;
height: 7.09vw;
margin: 1.66vw 0 0 8.43vw;
}
.text-group_1 {
width: 34.43vw;
height: 7.09vw;
}
.text_1 {
width: 15.79vw;
height: 2.5vw;
overflow-wrap: break-word;
color: rgba(67, 67, 67, 1);
font-size: 2.5vw;
font-family: OPPOSans-B;
font-weight: 700;
text-align: left;
white-space: nowrap;
line-height: 1.57vw;
margin-left: 9.74vw;
}
.text_2 {
width: 34.43vw;
height: 3.13vw;
overflow-wrap: break-word;
color: rgba(67, 67, 67, 1);
font-size: 1.25vw;
font-family: OPPOSans-M;
font-weight: 500;
text-align: center;
line-height: 1.88vw;
margin-top: 1.46vw;
}
.image-wrapper_2 {
width: 34.8vw;
height: 0.06vw;
margin: 3.33vw 0 0 8.38vw;
}
.image_1 {
width: 34.8vw;
height: 0.06vw;
}
.box_4 {
width: 22.35vw;
height: 1.25vw;
margin: 2.6vw 0 7.96vw 14.84vw;
}
.text-wrapper_1 {
width: 22.35vw;
height: 1.25vw;
overflow-wrap: break-word;
font-size: 0;
font-family: OPPOSans-B;
font-weight: 700;
text-align: left;
white-space: nowrap;
line-height: 1.57vw;
}
.text_3 {
width: 22.35vw;
height: 1.25vw;
overflow-wrap: break-word;
color: rgba(67, 67, 67, 1);
font-size: 1.25vw;
font-family: OPPOSans-B;
font-weight: 700;
text-align: left;
white-space: nowrap;
line-height: 1.57vw;
}
.text_4 {
width: 22.35vw;
height: 1.25vw;
overflow-wrap: break-word;
color: rgba(67, 67, 67, 1);
font-size: 1.25vw;
font-family: OPPOSans-M;
font-weight: 500;
text-align: left;
white-space: nowrap;
line-height: 1.88vw;
}
</style>
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { resolve } from 'path'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': resolve(__dirname, 'src')
}
},
server: {
port: 3001,
open: true
}
})
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment