Merge branch 'main' of https://git.opencomputing.cn/yumoqing/kboss
This commit is contained in:
commit
89b29980de
@ -90,8 +90,10 @@ async def email_info(msg, indent=0):
|
||||
index = find_data.index("<")
|
||||
name = find_data[:index]
|
||||
if price and name:
|
||||
mail_code_sql = """SELECT * FROM mail_code WHERE LOCATE(mailcode, '%s') > 0 and del_flg = '0';""" % name
|
||||
mail_code = await sor.sqlExe(mail_code_sql, {})
|
||||
mail_code_sql = """SELECT * FROM mail_code WHERE mailcode= ${mailcode}$ and del_flg = '0';"""
|
||||
mail_code = await sor.sqlExe(mail_code_sql, {'mailcode': name})
|
||||
if len(mail_code) < 1:
|
||||
raise Exception(f'{name}不是合法的编码,数据库中没有找到')
|
||||
# mail_code = await sor.R('mail_code',{'mailcode':name,'del_flg':'0'})
|
||||
date = await get_business_date(sor=None)
|
||||
recharge_log = {'customerid': mail_code[0]['customer_id'], 'recharge_amt': price,
|
||||
@ -119,4 +121,4 @@ async def email_info(msg, indent=0):
|
||||
|
||||
msg = Parser().parsestr(msg_content)
|
||||
ret = await email_info(msg)
|
||||
return ret
|
||||
return ret
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
|
||||
<transition name="slide">
|
||||
<div v-show="windowsHidden" style="font-size: 14px">
|
||||
<div class="new-floating" style="z-index: 9999;">
|
||||
<div class="new-floating" style="z-index: 99;">
|
||||
<img src="./img/head.png" alt="">
|
||||
<div class="cloud-contact-us " @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
|
||||
<!-- <span class="cloud-contact-us-i"></span>-->
|
||||
@ -789,7 +789,7 @@ export default {
|
||||
top: -28px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
z-index: 9999;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
position: relative;
|
||||
|
||||
@ -171,7 +171,7 @@ Vue.use(HappyScroll)
|
||||
// });
|
||||
|
||||
// console.log(element);
|
||||
// console.clear(); // 清除测试日志
|
||||
// console.clear(); // 清除测试日志
|
||||
// }
|
||||
|
||||
// // 方法4: 检查Eruda等移动端调试工具
|
||||
@ -345,6 +345,77 @@ window.addEventListener('beforeunload', function () {
|
||||
Object.keys(filters).forEach(key => {
|
||||
Vue.filter(key, filters[key])
|
||||
})
|
||||
// 在 main.js 的 router.beforeEach 中添加
|
||||
router.beforeEach((to, from, next) => {
|
||||
// 清空面包屑状态的代码
|
||||
// store.commit('tagsView/resetBreadcrumbState');
|
||||
|
||||
// 新增:检测是否为移动设备
|
||||
const userAgent = navigator.userAgent;
|
||||
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
|
||||
|
||||
// 如果是移动设备且访问的是根路径,重定向到移动端首页
|
||||
if (isMobile && to.path === '/') {
|
||||
next('/h5HomePage');
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果是移动设备且访问的不是移动端页面,重定向到移动端首页
|
||||
if (isMobile && !to.meta?.isMobile && to.path !== '/h5HomePage' && !to.path.startsWith('/h5HomePage/')) {
|
||||
next('/h5HomePage');
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果已登录且有token,但Vuex状态丢失,从sessionStorage恢复
|
||||
if (store.getters.token && (!store.getters.user || !store.getters.userType)) {
|
||||
console.log("检测到状态丢失,从sessionStorage恢复用户状态");
|
||||
|
||||
const user = sessionStorage.getItem('user');
|
||||
const auths = sessionStorage.getItem('auths');
|
||||
const userType = sessionStorage.getItem('userType');
|
||||
const orgType = sessionStorage.getItem('orgType');
|
||||
|
||||
if (user) {
|
||||
store.commit('user/SET_USER', user);
|
||||
}
|
||||
if (auths) {
|
||||
store.commit('user/SET_AUTHS', JSON.parse(auths));
|
||||
}
|
||||
if (userType) {
|
||||
store.commit('user/SET_USER_TYPE', userType);
|
||||
}
|
||||
if (orgType) {
|
||||
store.commit('user/SET_ORG_TYPE', parseInt(orgType));
|
||||
}
|
||||
|
||||
// 重新生成路由
|
||||
try {
|
||||
const accessRoutes = store.dispatch('permission/generateRoutes', {
|
||||
user: store.getters.user,
|
||||
auths: store.getters.auths,
|
||||
userType: store.getters.userType,
|
||||
orgType: store.getters.orgType
|
||||
});
|
||||
|
||||
// 重新添加路由
|
||||
router.addRoutes(accessRoutes);
|
||||
|
||||
// 重定向到当前路由以确保路由更新
|
||||
next({ ...to, replace: true });
|
||||
return;
|
||||
} catch (error) {
|
||||
console.error('重新生成路由失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
onOverflow.forEach(element => {
|
||||
if (to.path == element) {
|
||||
document.querySelector("body").setAttribute("style", "overflow: auto !important;")
|
||||
}
|
||||
});
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
|
||||
@ -6,8 +6,83 @@ const userAgent = window.navigator.userAgent;
|
||||
// 判断是否为移动设备
|
||||
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
|
||||
|
||||
// 如果是移动设备,添加移动端首页路由和根路径重定向
|
||||
if (isMobile) {
|
||||
console.log("检测到移动设备,添加移动端路由");
|
||||
|
||||
// 先添加根路径重定向到移动端首页
|
||||
constantRoutes.unshift({
|
||||
path: '/',
|
||||
redirect: '/h5HomePage',
|
||||
hidden: true
|
||||
});
|
||||
|
||||
// 添加移动端首页路由
|
||||
constantRoutes.push({
|
||||
path: '/h5HomePage',
|
||||
name: 'H5HomePage',
|
||||
title: 'H5首页',
|
||||
component: () => import('@/views/H5/index.vue'),
|
||||
hidden: true,
|
||||
redirect: "/h5HomePage/index",
|
||||
meta: { isMobile: true },
|
||||
children: [
|
||||
{
|
||||
path: "index",
|
||||
title: 'H5首页',
|
||||
component: () => import('@/views/H5/official/index.vue'),
|
||||
meta: {
|
||||
title: "H5首页",
|
||||
fullPath: "/h5HomePage/index",
|
||||
isMobile: true
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "cloud",
|
||||
title: '云',
|
||||
component: () => import('@/views/H5/cloud/index.vue'),
|
||||
meta: {
|
||||
title: "云",
|
||||
fullPath: "/h5HomePage/cloud",
|
||||
isMobile: true
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "calculate",
|
||||
title: '算',
|
||||
component: () => import('@/views/H5/calculate/index.vue'),
|
||||
meta: {
|
||||
title: "算",
|
||||
fullPath: "/h5HomePage/calculate",
|
||||
isMobile: true
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "net",
|
||||
title: '网',
|
||||
component: () => import('@/views/H5/net/index.vue'),
|
||||
meta: {
|
||||
title: "网",
|
||||
fullPath: "/h5HomePage/net",
|
||||
isMobile: true
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "use",
|
||||
title: '用',
|
||||
component: () => import('@/views/H5/use/index.vue'),
|
||||
meta: {
|
||||
title: "用",
|
||||
fullPath: "/h5HomePage/use",
|
||||
isMobile: true
|
||||
},
|
||||
},
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
// 修复:更全面的路由过滤逻辑
|
||||
function filterAsyncRoutes(routes, permissions, userRoles = []) {
|
||||
function filterAsyncRoutes(routes, permissions, userRoles = [], deviceType = 'pc') {
|
||||
const res = [];
|
||||
|
||||
// 定义需要客户角色才能访问的路由
|
||||
@ -35,6 +110,14 @@ function filterAsyncRoutes(routes, permissions, userRoles = []) {
|
||||
return; // 跳过当前路由
|
||||
}
|
||||
|
||||
// 新增:根据设备类型过滤路由
|
||||
if (deviceType === 'mobile' && !(route.meta?.isMobile || route.meta?.isMobile === true)) {
|
||||
return; // 移动设备跳过非移动端路由
|
||||
}
|
||||
if (deviceType === 'pc' && route.meta?.isMobile === true) {
|
||||
return; // PC设备跳过移动端路由
|
||||
}
|
||||
|
||||
// 如果当前路由有权限,则加入结果
|
||||
if (hasPermission) {
|
||||
res.push(tmpRoute);
|
||||
@ -45,7 +128,7 @@ function filterAsyncRoutes(routes, permissions, userRoles = []) {
|
||||
}
|
||||
// 如果没有直接权限,但有子路由,递归处理子路由
|
||||
else if (tmpRoute.children) {
|
||||
const filteredChildren = filterAsyncRoutes(tmpRoute.children, permissions, userRoles);
|
||||
const filteredChildren = filterAsyncRoutes(tmpRoute.children, permissions, userRoles, deviceType);
|
||||
if (filteredChildren.length > 0) {
|
||||
tmpRoute.children = filteredChildren;
|
||||
res.push(tmpRoute); // 即使父路由本身没有权限,只要有子路由有权限,也要保留父路由
|
||||
@ -57,7 +140,7 @@ function filterAsyncRoutes(routes, permissions, userRoles = []) {
|
||||
}
|
||||
|
||||
// 新增:为普通用户添加订单管理和资源管理路由
|
||||
function addUserRoutes(routes, userType, orgType, userRoles = []) {
|
||||
function addUserRoutes(routes, userType, orgType, userRoles = [], deviceType = 'pc') {
|
||||
console.log("addUserRoutes - userType:", userType, "orgType:", orgType, "userRoles:", userRoles);
|
||||
|
||||
const userRoutes = [];
|
||||
@ -67,12 +150,13 @@ function addUserRoutes(routes, userType, orgType, userRoles = []) {
|
||||
const orderManagementRoute = routes.find(route => route.path === "/orderManagement");
|
||||
const resourceManagementRoute = routes.find(route => route.path === "/resourceManagement");
|
||||
|
||||
if (orderManagementRoute) {
|
||||
// 新增:根据设备类型过滤
|
||||
if (orderManagementRoute && (deviceType === 'pc' || orderManagementRoute.meta?.isMobile === true)) {
|
||||
console.log("添加订单管理路由");
|
||||
userRoutes.push(JSON.parse(JSON.stringify(orderManagementRoute))); // 深拷贝
|
||||
}
|
||||
|
||||
if (resourceManagementRoute) {
|
||||
if (resourceManagementRoute && (deviceType === 'pc' || resourceManagementRoute.meta?.isMobile === true)) {
|
||||
console.log("添加资源管理路由");
|
||||
userRoutes.push(JSON.parse(JSON.stringify(resourceManagementRoute))); // 深拷贝
|
||||
}
|
||||
@ -85,10 +169,10 @@ function addUserRoutes(routes, userType, orgType, userRoles = []) {
|
||||
routes.find(route => route.path === "/rechargeManagement"),
|
||||
routes.find(route => route.path === "/invoiceManagement"),
|
||||
routes.find(route => route.path === "/workOrderManagement")
|
||||
|
||||
].filter(route => {
|
||||
// 过滤掉undefined,并且只有客户角色才能看到这些路由
|
||||
return route && userRoles.includes('客户');
|
||||
return route && userRoles.includes('客户') &&
|
||||
(deviceType === 'pc' || route.meta?.isMobile === true);
|
||||
});
|
||||
|
||||
console.log("添加新的客户菜单路由:", newCustomerRoutes.map(r => r.path));
|
||||
@ -97,38 +181,11 @@ function addUserRoutes(routes, userType, orgType, userRoles = []) {
|
||||
return userRoutes;
|
||||
}
|
||||
|
||||
function filterRoutesMobile(routes) {
|
||||
return routes.filter(route => {
|
||||
if (route.children && route.children.length) {
|
||||
route.children = filterRoutesMobile(route.children);
|
||||
return route.children.length > 0;
|
||||
}
|
||||
if (route.meta?.isMobile || route.meta?.isMobile === true) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function filterRoutesPc(routes) {
|
||||
return routes.filter(route => {
|
||||
if (route.children && route.children.length) {
|
||||
route.children = filterRoutesPc(route.children);
|
||||
return route.children.length > 0;
|
||||
}
|
||||
if (!route.meta?.isMobile || route.meta?.isMobile === false) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const state = {
|
||||
routes: [],
|
||||
addRoutes: [],
|
||||
users: []
|
||||
users: [],
|
||||
isMobile: isMobile // 保存设备类型状态
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
@ -136,11 +193,15 @@ const mutations = {
|
||||
console.log("MUTATION SET_ROUTES - received routes:", routes);
|
||||
state.addRoutes = routes;
|
||||
sessionStorage.setItem("routes", JSON.stringify(routes));
|
||||
// 将移动端首页路由也包含在内
|
||||
state.routes = constantRoutes.concat(routes);
|
||||
console.log("MUTATION SET_ROUTES - final state.routes:", state.routes);
|
||||
},
|
||||
SETUSERS: (state, user) => {
|
||||
state.users = user;
|
||||
},
|
||||
SET_DEVICE_TYPE: (state, isMobile) => {
|
||||
state.isMobile = isMobile;
|
||||
}
|
||||
};
|
||||
|
||||
@ -161,7 +222,7 @@ const actions = {
|
||||
* @param {Object} [params.user] - 用户信息对象
|
||||
* @returns {Promise<Array>} 解析后的动态路由数组
|
||||
*/
|
||||
generateRoutes({ commit, rootState }, params) {
|
||||
generateRoutes({ commit, rootState, state }, params) {
|
||||
console.log("ACTION generateRoutes - params:", params);
|
||||
return new Promise((resolve) => {
|
||||
let accessedRoutes;
|
||||
@ -176,10 +237,18 @@ const actions = {
|
||||
|
||||
console.log("用户类型:", userType, "orgType:", orgType);
|
||||
|
||||
// 确定设备类型
|
||||
const deviceType = state.isMobile ? 'mobile' : 'pc';
|
||||
console.log("设备类型:", deviceType);
|
||||
|
||||
// 修复:包含 orgType 为 2 和 3 的情况
|
||||
if (params.user && params.user.includes("admin") && orgType != 2 && orgType != 3) {
|
||||
// 管理员:只显示超级管理员菜单
|
||||
accessedRoutes = asyncRoutes.filter(item => item.path === '/superAdministrator');
|
||||
// 管理员:只显示超级管理员菜单(仅PC端)
|
||||
if (deviceType === 'pc') {
|
||||
accessedRoutes = asyncRoutes.filter(item => item.path === '/superAdministrator');
|
||||
} else {
|
||||
accessedRoutes = [];
|
||||
}
|
||||
} else {
|
||||
const auths = params.auths ? JSON.parse(JSON.stringify(params.auths)) : [];
|
||||
console.log("ACTION generateRoutes - auths:", auths);
|
||||
@ -195,8 +264,8 @@ const actions = {
|
||||
// 如果权限列表包含空路径,认为用户有所有权限
|
||||
accessedRoutes = asyncRoutes || [];
|
||||
} else {
|
||||
// 使用修复后的过滤函数,传入用户角色
|
||||
accessedRoutes = filterAsyncRoutes(asyncRoutes, auths, userRoles);
|
||||
// 使用修复后的过滤函数,传入用户角色和设备类型
|
||||
accessedRoutes = filterAsyncRoutes(asyncRoutes, auths, userRoles, deviceType);
|
||||
}
|
||||
} else {
|
||||
// 如果没有权限列表,不显示任何动态路由
|
||||
@ -205,7 +274,7 @@ const actions = {
|
||||
|
||||
// 新增:为普通用户添加订单管理和资源管理路由以及新的五个客户菜单
|
||||
console.log("为用户添加特定路由");
|
||||
const userSpecificRoutes = addUserRoutes(asyncRoutes, userType, orgType, userRoles);
|
||||
const userSpecificRoutes = addUserRoutes(asyncRoutes, userType, orgType, userRoles, deviceType);
|
||||
|
||||
// 确保不重复添加路由,同时检查角色权限
|
||||
userSpecificRoutes.forEach(route => {
|
||||
|
||||
@ -4,7 +4,22 @@
|
||||
<div class="top-tit">
|
||||
开元云
|
||||
</div>
|
||||
|
||||
<!-- 搜索 -->
|
||||
<div class="search">
|
||||
<div class="search-box">
|
||||
<div class="input">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="请输入产品名称"
|
||||
v-model="searchValue"
|
||||
@keyup.enter="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
<div class="search-btn" @click="handleSearch">
|
||||
搜索
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 供应商 -->
|
||||
<div v-if="cloudData.secMenu && cloudData.secMenu.length > 0" class="supplier-container">
|
||||
<div
|
||||
@ -32,6 +47,7 @@
|
||||
v-for="product in thrMenu.value"
|
||||
:key="product.id"
|
||||
class="box-item"
|
||||
v-show="shouldShowProduct(product)"
|
||||
>
|
||||
<!-- 标题 -->
|
||||
<div class="item-tit">
|
||||
@ -83,6 +99,8 @@ export default {
|
||||
return {
|
||||
cloudData: {},
|
||||
activeSupplierIndex: 0, // 默认选中第一个供应商
|
||||
searchValue: '', // 搜索关键词
|
||||
isSearching: false, // 是否正在搜索
|
||||
|
||||
// 咨询弹窗相关
|
||||
showConsultDialog: false,
|
||||
@ -116,6 +134,26 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
// 处理搜索
|
||||
handleSearch() {
|
||||
this.isSearching = !!this.searchValue.trim()
|
||||
// 这里可以根据需要添加实际的搜索逻辑,比如调用API
|
||||
console.log('搜索关键词:', this.searchValue)
|
||||
},
|
||||
|
||||
// 判断产品是否应该显示
|
||||
shouldShowProduct(product) {
|
||||
if (!this.isSearching) {
|
||||
return true
|
||||
}
|
||||
// 模糊搜索:检查产品名称或描述中是否包含搜索关键词
|
||||
const keyword = this.searchValue.toLowerCase().trim()
|
||||
return (
|
||||
(product.name && product.name.toLowerCase().includes(keyword)) ||
|
||||
(product.description && product.description.toLowerCase().includes(keyword))
|
||||
)
|
||||
},
|
||||
|
||||
// 选择供应商
|
||||
selectSupplier(index) {
|
||||
this.activeSupplierIndex = index
|
||||
|
||||
@ -4,6 +4,22 @@
|
||||
<div class="top-tit">
|
||||
开元云
|
||||
</div>
|
||||
<!-- 搜索 -->
|
||||
<div class="search">
|
||||
<div class="search-box">
|
||||
<div class="input">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="请输入产品名称"
|
||||
v-model="searchValue"
|
||||
@keyup.enter="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
<div class="search-btn" @click="handleSearch">
|
||||
搜索
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 供应商 -->
|
||||
<div class="supplier-container">
|
||||
@ -19,7 +35,7 @@
|
||||
<!-- 只显示当前选中的供应商的产品 -->
|
||||
<template v-if="cloudData.secMenu && cloudData.secMenu.length > 0 && activeSupplierIndex >= 0">
|
||||
<template v-for="thrMenu in cloudData.secMenu[activeSupplierIndex].thrMenu">
|
||||
<div v-for="product in thrMenu.value" :key="product.id" class="box-item">
|
||||
<div v-for="product in thrMenu.value" :key="product.id" class="box-item" v-show="shouldShowProduct(product)">
|
||||
<!-- 标题 -->
|
||||
<div class="item-tit">
|
||||
{{ product.name }}
|
||||
@ -67,6 +83,8 @@ export default {
|
||||
return {
|
||||
cloudData: {},
|
||||
activeSupplierIndex: 0, // 默认选中第一个供应商
|
||||
searchValue: '', // 搜索关键词
|
||||
isSearching: false, // 是否正在搜索
|
||||
|
||||
// 咨询弹窗相关
|
||||
showConsultDialog: false,
|
||||
@ -98,6 +116,27 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 处理搜索
|
||||
handleSearch() {
|
||||
this.isSearching = !!this.searchValue.trim()
|
||||
console.log('搜索关键词:', this.searchValue)
|
||||
},
|
||||
|
||||
// 判断产品是否应该显示
|
||||
shouldShowProduct(product) {
|
||||
if (!this.isSearching) {
|
||||
return true
|
||||
}
|
||||
// 模糊搜索
|
||||
const keyword = this.searchValue.toLowerCase().trim()
|
||||
return (
|
||||
(product.name && product.name.toLowerCase().includes(keyword)) ||
|
||||
(product.description && product.description.toLowerCase().includes(keyword)) ||
|
||||
(product.label && product.label.toLowerCase().includes(keyword)) ||
|
||||
(product.ssecTitle && product.ssecTitle.toLowerCase().includes(keyword))
|
||||
)
|
||||
},
|
||||
|
||||
// 判断是否显示供应商标签
|
||||
showProductDesc(product) {
|
||||
// 如果是百度云且有label字段
|
||||
|
||||
BIN
f/web-kboss/src/views/H5/images/bg.png
Normal file
BIN
f/web-kboss/src/views/H5/images/bg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 595 KiB |
@ -2,23 +2,33 @@
|
||||
<div class="h5-container">
|
||||
<!-- 主要内容区域 -->
|
||||
<div ref="mainContent" class="main" @scroll="handleScroll">
|
||||
<router-view></router-view>
|
||||
<transition :name="transitionName" mode="out-in">
|
||||
<router-view></router-view>
|
||||
</transition>
|
||||
</div>
|
||||
<div style="height: 1.4rem;"></div>
|
||||
|
||||
<!-- 返回顶部按钮 -->
|
||||
<transition name="fade">
|
||||
<transition name="fade-scale">
|
||||
<div
|
||||
v-show="showBackToTop"
|
||||
class="back-to-top"
|
||||
@click="scrollToTop"
|
||||
>
|
||||
<div class="back-to-top-icon">↑</div>
|
||||
<div class="back-to-top-text">顶部</div>
|
||||
<div class="back-to-top-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none">
|
||||
<path d="M12 5L12 19M12 5L6 11M12 5L18 11"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="back-to-top-text">回顶部</div>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<!-- 底部导航栏 -->
|
||||
<!-- 底部导航栏 -->
|
||||
<div class="tabBar">
|
||||
<!-- 首页 -->
|
||||
<div
|
||||
@ -27,14 +37,20 @@
|
||||
@click="switchTab('index')"
|
||||
>
|
||||
<div class="item-img">
|
||||
<img
|
||||
:src="activeTab === 'index' ? require('./images/tabBar/homeColor.png') : require('./images/tabBar/home.png')"
|
||||
alt="首页"
|
||||
/>
|
||||
<transition name="icon-bounce" mode="out-in">
|
||||
<img
|
||||
:key="activeTab === 'index'"
|
||||
:src="activeTab === 'index' ? require('./images/tabBar/homeColor.png') : require('./images/tabBar/home.png')"
|
||||
alt="首页"
|
||||
/>
|
||||
</transition>
|
||||
</div>
|
||||
<div class="item-text">
|
||||
首页
|
||||
<transition name="text-slide" mode="out-in">
|
||||
<span :key="activeTab === 'index'">首页</span>
|
||||
</transition>
|
||||
</div>
|
||||
<div class="active-indicator" v-if="activeTab === 'index'"></div>
|
||||
</div>
|
||||
|
||||
<!-- 云 -->
|
||||
@ -44,14 +60,20 @@
|
||||
@click="switchTab('cloud')"
|
||||
>
|
||||
<div class="item-img">
|
||||
<img
|
||||
:src="activeTab === 'cloud' ? require('./images/tabBar/cloudColor.png') : require('./images/tabBar/cloud.png')"
|
||||
alt="云"
|
||||
/>
|
||||
<transition name="icon-bounce" mode="out-in">
|
||||
<img
|
||||
:key="activeTab === 'cloud'"
|
||||
:src="activeTab === 'cloud' ? require('./images/tabBar/cloudColor.png') : require('./images/tabBar/cloud.png')"
|
||||
alt="云"
|
||||
/>
|
||||
</transition>
|
||||
</div>
|
||||
<div class="item-text">
|
||||
云
|
||||
<transition name="text-slide" mode="out-in">
|
||||
<span :key="activeTab === 'cloud'">云</span>
|
||||
</transition>
|
||||
</div>
|
||||
<div class="active-indicator" v-if="activeTab === 'cloud'"></div>
|
||||
</div>
|
||||
|
||||
<!-- 算 -->
|
||||
@ -61,14 +83,20 @@
|
||||
@click="switchTab('calculate')"
|
||||
>
|
||||
<div class="item-img">
|
||||
<img
|
||||
:src="activeTab === 'calculate' ? require('./images/tabBar/calculateColor.png') : require('./images/tabBar/calculate.png')"
|
||||
alt="算"
|
||||
/>
|
||||
<transition name="icon-bounce" mode="out-in">
|
||||
<img
|
||||
:key="activeTab === 'calculate'"
|
||||
:src="activeTab === 'calculate' ? require('./images/tabBar/calculateColor.png') : require('./images/tabBar/calculate.png')"
|
||||
alt="算"
|
||||
/>
|
||||
</transition>
|
||||
</div>
|
||||
<div class="item-text">
|
||||
算
|
||||
<transition name="text-slide" mode="out-in">
|
||||
<span :key="activeTab === 'calculate'">算</span>
|
||||
</transition>
|
||||
</div>
|
||||
<div class="active-indicator" v-if="activeTab === 'calculate'"></div>
|
||||
</div>
|
||||
|
||||
<!-- 网 -->
|
||||
@ -78,14 +106,20 @@
|
||||
@click="switchTab('net')"
|
||||
>
|
||||
<div class="item-img">
|
||||
<img
|
||||
:src="activeTab === 'net' ? require('./images/tabBar/netColor.png') : require('./images/tabBar/net.png')"
|
||||
alt="网"
|
||||
/>
|
||||
<transition name="icon-bounce" mode="out-in">
|
||||
<img
|
||||
:key="activeTab === 'net'"
|
||||
:src="activeTab === 'net' ? require('./images/tabBar/netColor.png') : require('./images/tabBar/net.png')"
|
||||
alt="网"
|
||||
/>
|
||||
</transition>
|
||||
</div>
|
||||
<div class="item-text">
|
||||
网
|
||||
<transition name="text-slide" mode="out-in">
|
||||
<span :key="activeTab === 'net'">网</span>
|
||||
</transition>
|
||||
</div>
|
||||
<div class="active-indicator" v-if="activeTab === 'net'"></div>
|
||||
</div>
|
||||
|
||||
<!-- 用 -->
|
||||
@ -95,14 +129,20 @@
|
||||
@click="switchTab('use')"
|
||||
>
|
||||
<div class="item-img">
|
||||
<img
|
||||
:src="activeTab === 'use' ? require('./images/tabBar/userColor.png') : require('./images/tabBar/user.png')"
|
||||
alt="用"
|
||||
/>
|
||||
<transition name="icon-bounce" mode="out-in">
|
||||
<img
|
||||
:key="activeTab === 'use'"
|
||||
:src="activeTab === 'use' ? require('./images/tabBar/userColor.png') : require('./images/tabBar/user.png')"
|
||||
alt="用"
|
||||
/>
|
||||
</transition>
|
||||
</div>
|
||||
<div class="item-text">
|
||||
用
|
||||
<transition name="text-slide" mode="out-in">
|
||||
<span :key="activeTab === 'use'">用</span>
|
||||
</transition>
|
||||
</div>
|
||||
<div class="active-indicator" v-if="activeTab === 'use'"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -124,6 +164,8 @@ export default {
|
||||
],
|
||||
showBackToTop: false, // 是否显示返回顶部按钮
|
||||
scrollThreshold: 200, // 滚动多少距离后显示按钮(可根据需要调整)
|
||||
transitionName: 'fade', // 页面切换动画名称
|
||||
isSwitching: false, // 是否正在切换
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
@ -142,8 +184,11 @@ export default {
|
||||
* @param {string} tabId - 标签ID
|
||||
*/
|
||||
switchTab(tabId) {
|
||||
// 如果点击的是当前已激活的标签,不进行操作
|
||||
if (this.activeTab === tabId) return;
|
||||
// 如果正在切换或点击的是当前已激活的标签,不进行操作
|
||||
if (this.isSwitching || this.activeTab === tabId) return;
|
||||
|
||||
// 设置正在切换状态
|
||||
this.isSwitching = true;
|
||||
|
||||
// 更新激活状态
|
||||
this.activeTab = tabId;
|
||||
@ -151,7 +196,39 @@ export default {
|
||||
// 根据tabId跳转到对应的路由
|
||||
const tab = this.tabList.find(item => item.id === tabId);
|
||||
if (tab) {
|
||||
this.$router.push(tab.path);
|
||||
// 添加点击反馈动画
|
||||
this.animateTabClick(tabId);
|
||||
|
||||
// 延迟路由跳转,让动画先执行
|
||||
setTimeout(() => {
|
||||
this.$router.push(tab.path);
|
||||
// 重置切换状态
|
||||
setTimeout(() => {
|
||||
this.isSwitching = false;
|
||||
}, 300);
|
||||
}, 150);
|
||||
} else {
|
||||
this.isSwitching = false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 执行Tab点击动画
|
||||
* @param {string} tabId - 标签ID
|
||||
*/
|
||||
animateTabClick(tabId) {
|
||||
// 获取点击的tab元素
|
||||
const tabIndex = this.tabList.findIndex(item => item.id === tabId);
|
||||
const tabs = document.querySelectorAll('.tabBar-item');
|
||||
|
||||
if (tabs[tabIndex]) {
|
||||
// 添加点击动画类
|
||||
tabs[tabIndex].classList.add('click-animation');
|
||||
|
||||
// 动画结束后移除类
|
||||
setTimeout(() => {
|
||||
tabs[tabIndex].classList.remove('click-animation');
|
||||
}, 300);
|
||||
}
|
||||
},
|
||||
|
||||
@ -186,6 +263,15 @@ export default {
|
||||
*/
|
||||
scrollToTop() {
|
||||
if (this.$refs.mainContent) {
|
||||
// 添加点击反馈效果
|
||||
const btn = document.querySelector('.back-to-top');
|
||||
if (btn) {
|
||||
btn.classList.add('clicked');
|
||||
setTimeout(() => {
|
||||
btn.classList.remove('clicked');
|
||||
}, 300);
|
||||
}
|
||||
|
||||
this.$refs.mainContent.scrollTo({
|
||||
top: 0,
|
||||
behavior: 'smooth' // 平滑滚动
|
||||
@ -208,120 +294,5 @@ window.onresize = adapter()
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.h5-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.main {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch; /* 为iOS添加平滑滚动 */
|
||||
}
|
||||
|
||||
/* 返回顶部按钮样式 */
|
||||
.back-to-top {
|
||||
position: fixed;
|
||||
right: 0.4rem;
|
||||
bottom: 1.5rem; /* 在底部导航栏上方 */
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1.1rem;
|
||||
height: 1.1rem;
|
||||
background: linear-gradient(90deg, #275AFF 0%, #2EBDFA 100%);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0.04rem 0.12rem rgba(0, 0, 0, 0.3);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
box-shadow: 0 0.02rem 0.06rem rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: linear-gradient(90deg, #275AFF 0%, #2EBDFA 100%);
|
||||
}
|
||||
|
||||
.back-to-top-icon {
|
||||
color: white;
|
||||
font-size: 0.4rem;
|
||||
font-weight: bold;
|
||||
// line-height: 0.5rem;
|
||||
}
|
||||
|
||||
.back-to-top-text {
|
||||
color: white;
|
||||
font-size: 0.26rem;
|
||||
line-height: 0.2rem;
|
||||
// margin-top: -0.04rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* 淡入淡出动画 */
|
||||
.fade-enter-active, .fade-leave-active {
|
||||
transition: opacity 0.3s, transform 0.3s;
|
||||
}
|
||||
.fade-enter, .fade-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(0.2rem);
|
||||
}
|
||||
|
||||
.tabBar {
|
||||
padding: .2rem 0;
|
||||
background-color: #fff;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 -0.02rem .1rem rgba(0, 0, 0, 0.1);
|
||||
|
||||
.tabBar-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
&.active {
|
||||
.item-text {
|
||||
color: #1890ff;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.item-img {
|
||||
margin-bottom: .1rem;
|
||||
|
||||
img {
|
||||
width: .5rem;
|
||||
height: .5rem;
|
||||
display: block;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
}
|
||||
|
||||
.item-text {
|
||||
font-size: .24rem;
|
||||
color: #666;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
}
|
||||
@import url('./less/home/index.less');
|
||||
</style>
|
||||
|
||||
@ -110,9 +110,128 @@
|
||||
}
|
||||
.search {
|
||||
width: 100%;
|
||||
margin: 0.2rem 0;
|
||||
margin: 0.3rem 0;
|
||||
padding: 0 0.3rem;
|
||||
}
|
||||
.search .search-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 0.3rem;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
border: 0.02rem solid #e9ecef;
|
||||
box-shadow: 0 0.02rem 0.06rem rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
.search .search-box:focus-within {
|
||||
transform: translateY(-0.01rem);
|
||||
}
|
||||
.search .search-btn {
|
||||
font-size: 0.2rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 18%;
|
||||
color: #fff;
|
||||
padding: 0.18rem 0;
|
||||
background: linear-gradient(90deg, #1f70ff, #3a8cff);
|
||||
border-bottom-right-radius: 0.3rem;
|
||||
border-top-right-radius: 0.3rem;
|
||||
font-size: 0.28rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.search .search-btn::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0) 100%);
|
||||
transition: left 0.5s ease;
|
||||
}
|
||||
.search .search-btn:hover {
|
||||
background: linear-gradient(90deg, #0d5aff, #2a7aff);
|
||||
width: 20%;
|
||||
}
|
||||
.search .search-btn:hover::after {
|
||||
left: 100%;
|
||||
}
|
||||
.search .search-btn:active {
|
||||
background: linear-gradient(90deg, #0a50e6, #2575e6);
|
||||
transform: scale(0.98);
|
||||
}
|
||||
.search .input {
|
||||
flex: 1;
|
||||
padding: 0.16rem 0;
|
||||
padding-left: 0.25rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.search .input input {
|
||||
border: none;
|
||||
outline: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-size: 0.26rem;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.search .input input::placeholder {
|
||||
color: #adb5bd;
|
||||
font-size: 0.24rem;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
.search .input input:focus::placeholder {
|
||||
color: #868e96;
|
||||
}
|
||||
/* 为供应商容器和产品列表添加搜索状态样式 */
|
||||
.supplier-container {
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
.box {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
/* 当有搜索关键词时,调整一些元素的样式 */
|
||||
:global body.search-active .supplier-container {
|
||||
opacity: 0.8;
|
||||
}
|
||||
:global body.search-active .box {
|
||||
animation: searchResultAppear 0.4s ease;
|
||||
}
|
||||
@keyframes searchResultAppear {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(0.1rem);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 480px) {
|
||||
.search {
|
||||
padding: 0 0.2rem;
|
||||
margin: 0.25rem 0;
|
||||
}
|
||||
.search .search-box {
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
.search .search-btn {
|
||||
font-size: 0.26rem;
|
||||
padding: 0.16rem 0;
|
||||
}
|
||||
.search .input {
|
||||
padding: 0.14rem 0;
|
||||
padding-left: 0.2rem;
|
||||
}
|
||||
.search .input input {
|
||||
font-size: 0.24rem;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,20 +5,24 @@
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
font-size: .39rem; /* 增大30%: .3rem * 1.3 = .39rem */
|
||||
font-size: .39rem;
|
||||
/* 增大30%: .3rem * 1.3 = .39rem */
|
||||
font-weight: bold;
|
||||
margin: .3rem 0;
|
||||
}
|
||||
|
||||
.supplier-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap; /* 允许换行 */
|
||||
flex-wrap: wrap;
|
||||
/* 允许换行 */
|
||||
padding: .2rem .22rem;
|
||||
gap: .15rem; /* 使用gap控制间距 */
|
||||
gap: .15rem;
|
||||
/* 使用gap控制间距 */
|
||||
}
|
||||
|
||||
.supplier {
|
||||
flex-shrink: 0; /* 防止收缩 */
|
||||
flex-shrink: 0;
|
||||
/* 防止收缩 */
|
||||
|
||||
.supplier-title {
|
||||
font-size: .28rem;
|
||||
@ -29,7 +33,8 @@
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
white-space: nowrap; /* 防止文字换行 */
|
||||
white-space: nowrap;
|
||||
/* 防止文字换行 */
|
||||
|
||||
&:hover {
|
||||
background-color: #e0e0e0;
|
||||
@ -52,6 +57,7 @@
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
padding: 0 .3rem;
|
||||
|
||||
.box-item {
|
||||
display: flex;
|
||||
width: 48%;
|
||||
@ -69,19 +75,21 @@
|
||||
border-color: #1f70ff;
|
||||
}
|
||||
|
||||
.item-tit{
|
||||
.item-tit {
|
||||
font-size: .26rem;
|
||||
color: #000;
|
||||
font-weight: bold;
|
||||
margin-bottom: .1rem;
|
||||
}
|
||||
.item-detail{
|
||||
|
||||
.item-detail {
|
||||
color: #666;
|
||||
font-size: .22rem;
|
||||
margin: .15rem 0;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.item-desc{
|
||||
|
||||
.item-desc {
|
||||
color: #666;
|
||||
background-color: #f8f9fa;
|
||||
font-size: .2rem;
|
||||
@ -90,11 +98,13 @@
|
||||
margin-bottom: .15rem;
|
||||
border: .01rem solid #e9ecef;
|
||||
}
|
||||
.item-btn{
|
||||
|
||||
.item-btn {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
.btn{
|
||||
|
||||
.btn {
|
||||
background: linear-gradient(90deg, #1f70ff, #3a8cff);
|
||||
color: #fff;
|
||||
padding: .08rem .2rem;
|
||||
@ -113,11 +123,170 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.search{
|
||||
|
||||
.search {
|
||||
width: 100%;
|
||||
margin: .2rem 0;
|
||||
display: flex;
|
||||
.search-btn{
|
||||
font-size: .2rem;
|
||||
margin: .3rem 0;
|
||||
padding: 0 .3rem;
|
||||
|
||||
.search-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: .3rem;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
border: .02rem solid #e9ecef;
|
||||
box-shadow: 0 .02rem .06rem rgba(0, 0, 0, 0.04);
|
||||
|
||||
// &:hover {
|
||||
// border-color: #ced4da;
|
||||
// background-color: #fff;
|
||||
// box-shadow: 0 .04rem .12rem rgba(0, 0, 0, 0.08);
|
||||
// }
|
||||
|
||||
&:focus-within {
|
||||
// border-color: #1f70ff;
|
||||
// background-color: #fff;
|
||||
// box-shadow: 0 .04rem .16rem rgba(31, 112, 255, 0.15);
|
||||
transform: translateY(-0.01rem);
|
||||
}
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 18%;
|
||||
color: #fff;
|
||||
padding: .18rem 0;
|
||||
background: linear-gradient(90deg, #1f70ff, #3a8cff);
|
||||
border-bottom-right-radius: .3rem;
|
||||
border-top-right-radius: .3rem;
|
||||
font-size: .28rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.2) 50%,
|
||||
rgba(255, 255, 255, 0) 100%);
|
||||
transition: left 0.5s ease;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: linear-gradient(90deg, #0d5aff, #2a7aff);
|
||||
width: 20%;
|
||||
|
||||
&::after {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: linear-gradient(90deg, #0a50e6, #2575e6);
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
padding: .16rem 0;
|
||||
padding-left: .25rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
input {
|
||||
border: none;
|
||||
outline: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-size: .26rem;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
|
||||
&::placeholder {
|
||||
color: #adb5bd;
|
||||
font-size: .24rem;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
&::placeholder {
|
||||
color: #868e96;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 为供应商容器和产品列表添加搜索状态样式 */
|
||||
.supplier-container {
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.box {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
/* 当有搜索关键词时,调整一些元素的样式 */
|
||||
:global {
|
||||
body.search-active {
|
||||
.supplier-container {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.box {
|
||||
animation: searchResultAppear 0.4s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes searchResultAppear {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(.1rem);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 480px) {
|
||||
.search {
|
||||
padding: 0 .2rem;
|
||||
margin: .25rem 0;
|
||||
|
||||
.search-box {
|
||||
border-radius: .25rem;
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
font-size: .26rem;
|
||||
padding: .16rem 0;
|
||||
}
|
||||
|
||||
.input {
|
||||
padding: .14rem 0;
|
||||
padding-left: .2rem;
|
||||
|
||||
input {
|
||||
font-size: .24rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,3 +117,130 @@
|
||||
transform: translateY(-0.02rem);
|
||||
box-shadow: 0 0.04rem 0.1rem rgba(31, 112, 255, 0.3);
|
||||
}
|
||||
.search {
|
||||
width: 100%;
|
||||
margin: 0.3rem 0;
|
||||
padding: 0 0.3rem;
|
||||
}
|
||||
.search .search-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 0.3rem;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
border: 0.02rem solid #e9ecef;
|
||||
box-shadow: 0 0.02rem 0.06rem rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
.search .search-box:focus-within {
|
||||
transform: translateY(-0.01rem);
|
||||
}
|
||||
.search .search-btn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 18%;
|
||||
color: #fff;
|
||||
padding: 0.18rem 0;
|
||||
background: linear-gradient(90deg, #1f70ff, #3a8cff);
|
||||
border-bottom-right-radius: 0.3rem;
|
||||
border-top-right-radius: 0.3rem;
|
||||
font-size: 0.28rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.search .search-btn::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0) 100%);
|
||||
transition: left 0.5s ease;
|
||||
}
|
||||
.search .search-btn:hover {
|
||||
background: linear-gradient(90deg, #0d5aff, #2a7aff);
|
||||
width: 20%;
|
||||
}
|
||||
.search .search-btn:hover::after {
|
||||
left: 100%;
|
||||
}
|
||||
.search .search-btn:active {
|
||||
background: linear-gradient(90deg, #0a50e6, #2575e6);
|
||||
transform: scale(0.98);
|
||||
}
|
||||
.search .input {
|
||||
flex: 1;
|
||||
padding: 0.16rem 0;
|
||||
padding-left: 0.25rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.search .input input {
|
||||
border: none;
|
||||
outline: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-size: 0.26rem;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.search .input input::placeholder {
|
||||
color: #adb5bd;
|
||||
font-size: 0.24rem;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
.search .input input:focus::placeholder {
|
||||
color: #868e96;
|
||||
}
|
||||
/* 为供应商容器和产品列表添加搜索状态样式 */
|
||||
.supplier-container {
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
.box {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
/* 当有搜索关键词时,调整一些元素的样式 */
|
||||
:global body.search-active .supplier-container {
|
||||
opacity: 0.8;
|
||||
}
|
||||
:global body.search-active .box {
|
||||
animation: searchResultAppear 0.4s ease;
|
||||
}
|
||||
@keyframes searchResultAppear {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(0.1rem);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 480px) {
|
||||
.search {
|
||||
padding: 0 0.2rem;
|
||||
margin: 0.25rem 0;
|
||||
}
|
||||
.search .search-box {
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
.search .search-btn {
|
||||
font-size: 0.26rem;
|
||||
padding: 0.16rem 0;
|
||||
}
|
||||
.search .input {
|
||||
padding: 0.14rem 0;
|
||||
padding-left: 0.2rem;
|
||||
}
|
||||
.search .input input {
|
||||
font-size: 0.24rem;
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,3 +134,169 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.search {
|
||||
width: 100%;
|
||||
margin: .3rem 0;
|
||||
padding: 0 .3rem;
|
||||
|
||||
.search-box {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: .3rem;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
border: .02rem solid #e9ecef;
|
||||
box-shadow: 0 .02rem .06rem rgba(0, 0, 0, 0.04);
|
||||
|
||||
// &:hover {
|
||||
// border-color: #ced4da;
|
||||
// background-color: #fff;
|
||||
// box-shadow: 0 .04rem .12rem rgba(0, 0, 0, 0.08);
|
||||
// }
|
||||
|
||||
&:focus-within {
|
||||
// border-color: #1f70ff;
|
||||
// background-color: #fff;
|
||||
// box-shadow: 0 .04rem .16rem rgba(31, 112, 255, 0.15);
|
||||
transform: translateY(-0.01rem);
|
||||
}
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 18%;
|
||||
color: #fff;
|
||||
padding: .18rem 0;
|
||||
background: linear-gradient(90deg, #1f70ff, #3a8cff);
|
||||
border-bottom-right-radius: .3rem;
|
||||
border-top-right-radius: .3rem;
|
||||
font-size: .28rem;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.2) 50%,
|
||||
rgba(255, 255, 255, 0) 100%);
|
||||
transition: left 0.5s ease;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: linear-gradient(90deg, #0d5aff, #2a7aff);
|
||||
width: 20%;
|
||||
|
||||
&::after {
|
||||
left: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: linear-gradient(90deg, #0a50e6, #2575e6);
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
flex: 1;
|
||||
padding: .16rem 0;
|
||||
padding-left: .25rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
input {
|
||||
border: none;
|
||||
outline: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-size: .26rem;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
|
||||
&::placeholder {
|
||||
color: #adb5bd;
|
||||
font-size: .24rem;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
&::placeholder {
|
||||
color: #868e96;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 为供应商容器和产品列表添加搜索状态样式 */
|
||||
.supplier-container {
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.box {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
/* 当有搜索关键词时,调整一些元素的样式 */
|
||||
:global {
|
||||
body.search-active {
|
||||
.supplier-container {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.box {
|
||||
animation: searchResultAppear 0.4s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes searchResultAppear {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(.1rem);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 480px) {
|
||||
.search {
|
||||
padding: 0 .2rem;
|
||||
margin: .25rem 0;
|
||||
|
||||
.search-box {
|
||||
border-radius: .25rem;
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
font-size: .26rem;
|
||||
padding: .16rem 0;
|
||||
}
|
||||
|
||||
.input {
|
||||
padding: .14rem 0;
|
||||
padding-left: .2rem;
|
||||
|
||||
input {
|
||||
font-size: .24rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,7 +95,7 @@
|
||||
width: var(--dialog-width, 6rem) !important;
|
||||
max-width: 90%;
|
||||
border-radius: 0.08rem;
|
||||
z-index: 99999;
|
||||
z-index: 9999;
|
||||
}
|
||||
::v-deep .product-consult-dialog.el-dialog .el-dialog__header {
|
||||
padding: 0.2rem 0.3rem 0.1rem;
|
||||
|
||||
@ -108,7 +108,7 @@
|
||||
width: var(--dialog-width, 6rem) !important;
|
||||
max-width: 90%;
|
||||
border-radius: .08rem;
|
||||
z-index: 99999;
|
||||
z-index: 9999;
|
||||
|
||||
.el-dialog__header {
|
||||
padding: .2rem .3rem .1rem;
|
||||
|
||||
365
f/web-kboss/src/views/H5/less/home/index.css
Normal file
365
f/web-kboss/src/views/H5/less/home/index.css
Normal file
@ -0,0 +1,365 @@
|
||||
.h5-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.main {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
/* 为iOS添加平滑滚动 */
|
||||
}
|
||||
/* 页面切换动画 */
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.fade-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateY(0.2rem);
|
||||
}
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-0.2rem);
|
||||
}
|
||||
/* 返回顶部按钮样式 */
|
||||
.back-to-top {
|
||||
position: fixed;
|
||||
right: 0.4rem;
|
||||
bottom: 1.5rem;
|
||||
/* 在底部导航栏上方 */
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1.1rem;
|
||||
height: 1.1rem;
|
||||
background: linear-gradient(90deg, #275AFF 0%, #2EBDFA 100%);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0.08rem 0.24rem rgba(102, 126, 234, 0.4);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
/* 悬停效果 */
|
||||
/* 激活效果 */
|
||||
/* 点击动画 */
|
||||
}
|
||||
.back-to-top:hover {
|
||||
transform: translateY(-0.1rem);
|
||||
box-shadow: 0 0.12rem 0.36rem rgba(102, 126, 234, 0.6);
|
||||
background: linear-gradient(90deg, #275AFF 0%, #2EBDFA 100%);
|
||||
}
|
||||
.back-to-top:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
.back-to-top.clicked {
|
||||
animation: pulse 0.3s ease;
|
||||
}
|
||||
.back-to-top .back-to-top-icon {
|
||||
width: 0.45rem;
|
||||
height: 0.45rem;
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 0.04rem;
|
||||
}
|
||||
.back-to-top .back-to-top-icon svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
stroke: currentColor;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
.back-to-top .back-to-top-text {
|
||||
color: white;
|
||||
font-size: 0.24rem;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
letter-spacing: 0.02rem;
|
||||
text-shadow: 0 0.02rem 0.04rem rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
/* 脉冲动画 */
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
/* 返回顶部按钮动画 */
|
||||
.fade-scale-enter-active,
|
||||
.fade-scale-leave-active {
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.fade-scale-enter-from,
|
||||
.fade-scale-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0.8) translateY(0.2rem);
|
||||
}
|
||||
/* TabBar 样式 */
|
||||
.tabBar {
|
||||
padding: 0.2rem 0;
|
||||
background-color: rgba(255, 255, 255, 0.95);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 -0.02rem 0.2rem rgba(0, 0, 0, 0.08);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.tabBar .tabBar-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
padding: 0.1rem 0.15rem;
|
||||
border-radius: 0.3rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
/* 悬停效果 */
|
||||
/* 激活状态 */
|
||||
/* 点击动画 */
|
||||
/* 激活指示器 */
|
||||
}
|
||||
.tabBar .tabBar-item:hover {
|
||||
background-color: rgba(24, 144, 255, 0.08);
|
||||
transform: translateY(-0.05rem);
|
||||
}
|
||||
.tabBar .tabBar-item.active .item-text {
|
||||
color: #1890ff;
|
||||
font-weight: 600;
|
||||
}
|
||||
.tabBar .tabBar-item.click-animation {
|
||||
animation: tabClick 0.3s ease;
|
||||
}
|
||||
.tabBar .tabBar-item .active-indicator {
|
||||
position: absolute;
|
||||
bottom: 0.05rem;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 0.3rem;
|
||||
height: 0.04rem;
|
||||
border-radius: 0.02rem;
|
||||
animation: indicatorAppear 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
}
|
||||
.tabBar .item-img {
|
||||
margin-bottom: 0.08rem;
|
||||
position: relative;
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.tabBar .item-img img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
.tabBar .item-text {
|
||||
font-size: 0.24rem;
|
||||
color: #666;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
height: 0.3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
/* 图标动画 */
|
||||
.icon-bounce-enter-active {
|
||||
animation: iconBounceIn 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
}
|
||||
.icon-bounce-leave-active {
|
||||
animation: iconBounceOut 0.3s ease;
|
||||
}
|
||||
@keyframes iconBounceIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0.3) rotate(-30deg);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.2) rotate(10deg);
|
||||
}
|
||||
70% {
|
||||
transform: scale(0.9) rotate(-5deg);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1) rotate(0deg);
|
||||
}
|
||||
}
|
||||
@keyframes iconBounceOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: scale(1) rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: scale(0.5) rotate(30deg);
|
||||
}
|
||||
}
|
||||
/* 文字动画 */
|
||||
.text-slide-enter-active {
|
||||
animation: textSlideIn 0.3s ease-out;
|
||||
}
|
||||
.text-slide-leave-active {
|
||||
animation: textSlideOut 0.2s ease-in;
|
||||
}
|
||||
@keyframes textSlideIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(0.1rem);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
@keyframes textSlideOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateY(-0.1rem);
|
||||
}
|
||||
}
|
||||
/* Tab点击动画 */
|
||||
@keyframes tabClick {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
/* 指示器出现动画 */
|
||||
@keyframes indicatorAppear {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(-50%) scaleX(0);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateX(-50%) scaleX(1);
|
||||
}
|
||||
}
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 480px) {
|
||||
.back-to-top {
|
||||
right: 0.3rem;
|
||||
bottom: 1.6rem;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
}
|
||||
.back-to-top .back-to-top-icon {
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
margin-bottom: 0.03rem;
|
||||
}
|
||||
.back-to-top .back-to-top-text {
|
||||
font-size: 0.22rem;
|
||||
}
|
||||
.tabBar {
|
||||
padding: 0.15rem 0;
|
||||
}
|
||||
.tabBar .tabBar-item {
|
||||
padding: 0.08rem 0.12rem;
|
||||
}
|
||||
.tabBar .item-img {
|
||||
width: 0.45rem;
|
||||
height: 0.45rem;
|
||||
}
|
||||
.tabBar .item-text {
|
||||
font-size: 0.22rem;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.back-to-top {
|
||||
right: 0.5rem;
|
||||
bottom: 2rem;
|
||||
width: 1.2rem;
|
||||
height: 1.2rem;
|
||||
}
|
||||
.back-to-top .back-to-top-icon {
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
margin-bottom: 0.05rem;
|
||||
}
|
||||
.back-to-top .back-to-top-text {
|
||||
font-size: 0.26rem;
|
||||
}
|
||||
}
|
||||
/* 深色模式支持 */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.back-to-top {
|
||||
background: linear-gradient(90deg, #275AFF 0%, #2EBDFA 100%);
|
||||
box-shadow: 0 0.08rem 0.24rem rgba(138, 43, 226, 0.4);
|
||||
}
|
||||
.back-to-top:hover {
|
||||
background: linear-gradient(90deg, #275AFF 0%, #2EBDFA 100%);
|
||||
box-shadow: 0 0.12rem 0.36rem rgba(138, 43, 226, 0.6);
|
||||
}
|
||||
.tabBar {
|
||||
background-color: rgba(30, 30, 30, 0.95);
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
.tabBar .tabBar-item .item-text {
|
||||
color: #b0b0b0;
|
||||
}
|
||||
.tabBar .tabBar-item:hover {
|
||||
background-color: rgba(100, 181, 246, 0.08);
|
||||
}
|
||||
.tabBar .tabBar-item.active .item-text {
|
||||
color: #64b5f6;
|
||||
}
|
||||
.tabBar .tabBar-item.active .active-indicator {
|
||||
background: linear-gradient(90deg, #64b5f6, #81c784);
|
||||
}
|
||||
}
|
||||
/* 安全区域适配(iPhone X及以上机型) */
|
||||
@supports (padding: max(0px)) {
|
||||
.back-to-top {
|
||||
bottom: calc(1.5rem + env(safe-area-inset-bottom, 0));
|
||||
}
|
||||
.tabBar {
|
||||
padding-bottom: calc(0.2rem + env(safe-area-inset-bottom, 0));
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.back-to-top {
|
||||
bottom: calc(1.6rem + env(safe-area-inset-bottom, 0));
|
||||
}
|
||||
.tabBar {
|
||||
padding-bottom: calc(0.15rem + env(safe-area-inset-bottom, 0));
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.back-to-top {
|
||||
bottom: calc(2rem + env(safe-area-inset-bottom, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
438
f/web-kboss/src/views/H5/less/home/index.less
Normal file
438
f/web-kboss/src/views/H5/less/home/index.less
Normal file
@ -0,0 +1,438 @@
|
||||
.h5-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.main {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
/* 为iOS添加平滑滚动 */
|
||||
}
|
||||
|
||||
/* 页面切换动画 */
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.fade-enter-from {
|
||||
opacity: 0;
|
||||
transform: translateY(0.2rem);
|
||||
}
|
||||
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
transform: translateY(-0.2rem);
|
||||
}
|
||||
|
||||
/* 返回顶部按钮样式 */
|
||||
.back-to-top {
|
||||
position: fixed;
|
||||
right: 0.4rem;
|
||||
bottom: 1.5rem;
|
||||
/* 在底部导航栏上方 */
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 1.1rem;
|
||||
height: 1.1rem;
|
||||
background: linear-gradient(90deg, #275AFF 0%, #2EBDFA 100%);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0.08rem 0.24rem rgba(102, 126, 234, 0.4);
|
||||
cursor: pointer;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
user-select: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
|
||||
/* 悬停效果 */
|
||||
&:hover {
|
||||
transform: translateY(-0.1rem);
|
||||
box-shadow: 0 0.12rem 0.36rem rgba(102, 126, 234, 0.6);
|
||||
background: linear-gradient(90deg, #275AFF 0%, #2EBDFA 100%);
|
||||
}
|
||||
|
||||
/* 激活效果 */
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
/* 点击动画 */
|
||||
&.clicked {
|
||||
animation: pulse 0.3s ease;
|
||||
}
|
||||
|
||||
.back-to-top-icon {
|
||||
width: 0.45rem;
|
||||
height: 0.45rem;
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 0.04rem;
|
||||
|
||||
svg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
stroke: currentColor;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
}
|
||||
|
||||
.back-to-top-text {
|
||||
color: white;
|
||||
font-size: 0.24rem;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
letter-spacing: 0.02rem;
|
||||
text-shadow: 0 0.02rem 0.04rem rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
/* 脉冲动画 */
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* 返回顶部按钮动画 */
|
||||
.fade-scale-enter-active,
|
||||
.fade-scale-leave-active {
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.fade-scale-enter-from,
|
||||
.fade-scale-leave-to {
|
||||
opacity: 0;
|
||||
transform: scale(0.8) translateY(0.2rem);
|
||||
}
|
||||
|
||||
/* TabBar 样式 */
|
||||
.tabBar {
|
||||
padding: 0.2rem 0;
|
||||
background-color: rgba(255, 255, 255, 0.95);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 -0.02rem 0.2rem rgba(0, 0, 0, 0.08);
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.05);
|
||||
|
||||
.tabBar-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
padding: 0.1rem 0.15rem;
|
||||
border-radius: 0.3rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
|
||||
/* 悬停效果 */
|
||||
&:hover {
|
||||
background-color: rgba(24, 144, 255, 0.08);
|
||||
transform: translateY(-0.05rem);
|
||||
}
|
||||
|
||||
/* 激活状态 */
|
||||
&.active {
|
||||
.item-text {
|
||||
color: #1890ff;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
/* 点击动画 */
|
||||
&.click-animation {
|
||||
animation: tabClick 0.3s ease;
|
||||
}
|
||||
|
||||
/* 激活指示器 */
|
||||
.active-indicator {
|
||||
position: absolute;
|
||||
bottom: 0.05rem;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 0.3rem;
|
||||
height: 0.04rem;
|
||||
// background: linear-gradient(90deg, #1890ff);
|
||||
border-radius: 0.02rem;
|
||||
animation: indicatorAppear 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
}
|
||||
}
|
||||
|
||||
.item-img {
|
||||
margin-bottom: 0.08rem;
|
||||
position: relative;
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
}
|
||||
|
||||
.item-text {
|
||||
font-size: 0.24rem;
|
||||
color: #666;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
height: 0.3rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
/* 图标动画 */
|
||||
.icon-bounce-enter-active {
|
||||
animation: iconBounceIn 0.4s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
||||
}
|
||||
|
||||
.icon-bounce-leave-active {
|
||||
animation: iconBounceOut 0.3s ease;
|
||||
}
|
||||
|
||||
@keyframes iconBounceIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0.3) rotate(-30deg);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(1.2) rotate(10deg);
|
||||
}
|
||||
|
||||
70% {
|
||||
transform: scale(0.9) rotate(-5deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1) rotate(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes iconBounceOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: scale(1) rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: scale(0.5) rotate(30deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* 文字动画 */
|
||||
.text-slide-enter-active {
|
||||
animation: textSlideIn 0.3s ease-out;
|
||||
}
|
||||
|
||||
.text-slide-leave-active {
|
||||
animation: textSlideOut 0.2s ease-in;
|
||||
}
|
||||
|
||||
@keyframes textSlideIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(0.1rem);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes textSlideOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0;
|
||||
transform: translateY(-0.1rem);
|
||||
}
|
||||
}
|
||||
|
||||
/* Tab点击动画 */
|
||||
@keyframes tabClick {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* 指示器出现动画 */
|
||||
@keyframes indicatorAppear {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(-50%) scaleX(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateX(-50%) scaleX(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* 响应式调整 */
|
||||
@media (max-width: 480px) {
|
||||
.back-to-top {
|
||||
right: 0.3rem;
|
||||
bottom: 1.6rem;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
|
||||
.back-to-top-icon {
|
||||
width: 0.4rem;
|
||||
height: 0.4rem;
|
||||
margin-bottom: 0.03rem;
|
||||
}
|
||||
|
||||
.back-to-top-text {
|
||||
font-size: 0.22rem;
|
||||
}
|
||||
}
|
||||
|
||||
.tabBar {
|
||||
padding: 0.15rem 0;
|
||||
|
||||
.tabBar-item {
|
||||
padding: 0.08rem 0.12rem;
|
||||
}
|
||||
|
||||
.item-img {
|
||||
width: 0.45rem;
|
||||
height: 0.45rem;
|
||||
}
|
||||
|
||||
.item-text {
|
||||
font-size: 0.22rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.back-to-top {
|
||||
right: 0.5rem;
|
||||
bottom: 2rem;
|
||||
width: 1.2rem;
|
||||
height: 1.2rem;
|
||||
|
||||
.back-to-top-icon {
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
margin-bottom: 0.05rem;
|
||||
}
|
||||
|
||||
.back-to-top-text {
|
||||
font-size: 0.26rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 深色模式支持 */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.back-to-top {
|
||||
background: linear-gradient(90deg, #275AFF 0%, #2EBDFA 100%);
|
||||
box-shadow: 0 0.08rem 0.24rem rgba(138, 43, 226, 0.4);
|
||||
|
||||
&:hover {
|
||||
background: linear-gradient(90deg, #275AFF 0%, #2EBDFA 100%);
|
||||
box-shadow: 0 0.12rem 0.36rem rgba(138, 43, 226, 0.6);
|
||||
}
|
||||
}
|
||||
|
||||
.tabBar {
|
||||
background-color: rgba(30, 30, 30, 0.95);
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.05);
|
||||
|
||||
.tabBar-item {
|
||||
.item-text {
|
||||
color: #b0b0b0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(100, 181, 246, 0.08);
|
||||
}
|
||||
|
||||
&.active {
|
||||
.item-text {
|
||||
color: #64b5f6;
|
||||
}
|
||||
|
||||
.active-indicator {
|
||||
background: linear-gradient(90deg, #64b5f6, #81c784);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 安全区域适配(iPhone X及以上机型) */
|
||||
@supports (padding: max(0px)) {
|
||||
.back-to-top {
|
||||
bottom: calc(1.5rem + env(safe-area-inset-bottom, 0));
|
||||
}
|
||||
|
||||
.tabBar {
|
||||
padding-bottom: calc(0.2rem + env(safe-area-inset-bottom, 0));
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.back-to-top {
|
||||
bottom: calc(1.6rem + env(safe-area-inset-bottom, 0));
|
||||
}
|
||||
|
||||
.tabBar {
|
||||
padding-bottom: calc(0.15rem + env(safe-area-inset-bottom, 0));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.back-to-top {
|
||||
bottom: calc(2rem + env(safe-area-inset-bottom, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -26,7 +26,7 @@
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
font-size: 0.7rem;
|
||||
font-size: 0.68rem;
|
||||
}
|
||||
.title .title-top {
|
||||
font-size: 0.6rem;
|
||||
@ -72,13 +72,23 @@
|
||||
.journey-box .content .item-box,
|
||||
.latitude-box .content .item-box {
|
||||
width: 48%;
|
||||
background-color: #fff;
|
||||
border-radius: 0.1rem;
|
||||
padding: 0.2rem;
|
||||
box-shadow: 0 0.02rem 0.08rem rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 0.02rem 0.08rem rgba(39, 90, 255, 0.08);
|
||||
margin-bottom: 0.2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: linear-gradient(135deg, #f0f7ff 0%, #ffffff 100%);
|
||||
border: 1px solid rgba(39, 90, 255, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.base-box .content .item-box:hover,
|
||||
.journey-box .content .item-box:hover,
|
||||
.latitude-box .content .item-box:hover {
|
||||
box-shadow: 0 0.04rem 0.16rem rgba(39, 90, 255, 0.12);
|
||||
transform: translateY(-2px);
|
||||
border-color: rgba(39, 90, 255, 0.2);
|
||||
background: linear-gradient(135deg, #e8f2ff 0%, #ffffff 100%);
|
||||
}
|
||||
.base-box .content .item-box .item-title,
|
||||
.journey-box .content .item-box .item-title,
|
||||
@ -99,7 +109,7 @@
|
||||
.base-box .content .item-box .advantage-list,
|
||||
.journey-box .content .item-box .advantage-list,
|
||||
.latitude-box .content .item-box .advantage-list {
|
||||
margin: 0.1rem 0;
|
||||
display: block;
|
||||
}
|
||||
.base-box .content .item-box .advantage-list .advantage-item,
|
||||
.journey-box .content .item-box .advantage-list .advantage-item,
|
||||
@ -128,7 +138,6 @@
|
||||
.base-box .content .item-box .advantage-list .advantage-item .advantage-content,
|
||||
.journey-box .content .item-box .advantage-list .advantage-item .advantage-content,
|
||||
.latitude-box .content .item-box .advantage-list .advantage-item .advantage-content {
|
||||
flex: 1;
|
||||
font-size: 0.18rem;
|
||||
}
|
||||
.base-box .content .item-box .item-price,
|
||||
@ -245,7 +254,6 @@
|
||||
background: #f5f7fa;
|
||||
color: #fff;
|
||||
padding: 0.4rem 0.2rem;
|
||||
margin-top: 0.8rem;
|
||||
}
|
||||
.footer-content {
|
||||
max-width: 12rem;
|
||||
@ -256,7 +264,6 @@
|
||||
background: #f6f8fd;
|
||||
color: #333;
|
||||
padding: 0.6rem 0.2rem 0.4rem;
|
||||
margin-top: 1rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-top: 1px solid #e8edf5;
|
||||
@ -279,8 +286,6 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding-bottom: 0.4rem;
|
||||
margin-bottom: 0.4rem;
|
||||
}
|
||||
.logo-footer {
|
||||
width: 2.4rem;
|
||||
@ -292,38 +297,29 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.contact-info {
|
||||
flex: 1;
|
||||
.footer-center {
|
||||
font-size: 0.24rem;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 0.24rem;
|
||||
padding: 0.3rem 0.2rem;
|
||||
background: #fff;
|
||||
border-radius: 0.16rem;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
margin-top: 0.4rem;
|
||||
border: 1px solid #eef2f9;
|
||||
width: 100%;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.contact-info {
|
||||
.footer-center {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 0.3rem 0.6rem;
|
||||
}
|
||||
}
|
||||
.contact-info .contact-item {
|
||||
.footer-center .contact-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 0.16rem 0.2rem;
|
||||
background: #fff;
|
||||
border-radius: 0.12rem;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
border: 1px solid #eef2f9;
|
||||
}
|
||||
.contact-info .contact-item:hover {
|
||||
background: #fff;
|
||||
border-color: #2ebdfa;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 16px rgba(39, 90, 255, 0.12);
|
||||
}
|
||||
.contact-info .contact-item .iconfont {
|
||||
.footer-center .contact-item .iconfont {
|
||||
width: 0.2rem;
|
||||
height: 0.2rem;
|
||||
margin-right: 0.12rem;
|
||||
@ -332,31 +328,31 @@
|
||||
flex-shrink: 0;
|
||||
font-size: 0.26rem;
|
||||
}
|
||||
.contact-info .contact-item .label {
|
||||
.footer-center .contact-item .label {
|
||||
color: #666;
|
||||
flex-shrink: 0;
|
||||
font-weight: 500;
|
||||
margin-right: 0.08rem;
|
||||
font-size: 0.24rem;
|
||||
}
|
||||
.contact-info .contact-item .value {
|
||||
.footer-center .contact-item .value {
|
||||
color: #444;
|
||||
flex: 1;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.contact-info .contact-item .phone-numbers {
|
||||
.footer-center .contact-item .phone-numbers {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.08rem;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.contact-info .contact-item .phone-numbers {
|
||||
.footer-center .contact-item .phone-numbers {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 0.16rem;
|
||||
}
|
||||
}
|
||||
.contact-info .contact-item .phone-link {
|
||||
.footer-center .contact-item .phone-link {
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
transition: all 0.3s;
|
||||
@ -364,20 +360,20 @@
|
||||
font-size: 0.208rem;
|
||||
/* 增大30%: 0.16rem * 1.3 = 0.208rem */
|
||||
}
|
||||
.contact-info .contact-item .phone-link:hover {
|
||||
.footer-center .contact-item .phone-link:hover {
|
||||
color: #275AFF;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.contact-info .contact-item .phone-separator {
|
||||
.footer-center .contact-item .phone-separator {
|
||||
color: #999;
|
||||
font-weight: 300;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.contact-info .contact-item .phone-separator {
|
||||
.footer-center .contact-item .phone-separator {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.contact-info .contact-item .email-link {
|
||||
.footer-center .contact-item .email-link {
|
||||
color: #275AFF;
|
||||
text-decoration: none;
|
||||
word-break: break-all;
|
||||
@ -385,7 +381,7 @@
|
||||
font-size: 0.208rem;
|
||||
/* 增大30%: 0.16rem * 1.3 = 0.208rem */
|
||||
}
|
||||
.contact-info .contact-item .email-link:hover {
|
||||
.footer-center .contact-item .email-link:hover {
|
||||
color: #2ebdfa;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
font-size: .7rem;
|
||||
font-size: .68rem;
|
||||
}
|
||||
|
||||
.title-top {
|
||||
@ -78,13 +78,22 @@
|
||||
|
||||
.item-box {
|
||||
width: 48%;
|
||||
background-color: #fff;
|
||||
border-radius: 0.1rem;
|
||||
padding: 0.2rem;
|
||||
box-shadow: 0 .02rem .08rem rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 .02rem .08rem rgba(39, 90, 255, 0.08);
|
||||
margin-bottom: 0.2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: linear-gradient(135deg, #f0f7ff 0%, #ffffff 100%);
|
||||
border: 1px solid rgba(39, 90, 255, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 .04rem .16rem rgba(39, 90, 255, 0.12);
|
||||
transform: translateY(-2px);
|
||||
border-color: rgba(39, 90, 255, 0.2);
|
||||
background: linear-gradient(135deg, #e8f2ff 0%, #ffffff 100%);
|
||||
}
|
||||
|
||||
.item-title {
|
||||
font-size: 0.26rem;
|
||||
@ -101,14 +110,12 @@
|
||||
}
|
||||
|
||||
.advantage-list {
|
||||
margin: 0.1rem 0;
|
||||
display: block;
|
||||
|
||||
.advantage-item {
|
||||
display: block;
|
||||
font-size: 0.156rem;
|
||||
color: #666;
|
||||
// margin-bottom: 0.08rem;
|
||||
// line-height: 1.4;
|
||||
|
||||
.advantage-icon {
|
||||
width: 0.18rem;
|
||||
@ -126,7 +133,7 @@
|
||||
}
|
||||
|
||||
.advantage-content {
|
||||
flex: 1;
|
||||
// flex: 1;
|
||||
font-size: .18rem;
|
||||
}
|
||||
}
|
||||
@ -249,7 +256,7 @@
|
||||
background: #f5f7fa;
|
||||
color: #fff;
|
||||
padding: 0.4rem 0.2rem;
|
||||
margin-top: 0.8rem;
|
||||
// margin-top: 0.8rem;
|
||||
}
|
||||
|
||||
.footer-content {
|
||||
@ -262,7 +269,7 @@
|
||||
background: #f6f8fd;
|
||||
color: #333;
|
||||
padding: 0.6rem 0.2rem 0.4rem;
|
||||
margin-top: 1rem;
|
||||
// margin-top: 1rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-top: 1px solid #e8edf5;
|
||||
@ -289,8 +296,8 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding-bottom: 0.4rem;
|
||||
margin-bottom: 0.4rem;
|
||||
// padding-bottom: 0.4rem;
|
||||
// margin-bottom: 0.4rem;
|
||||
|
||||
}
|
||||
|
||||
@ -306,12 +313,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
.contact-info {
|
||||
flex: 1;
|
||||
.footer-center {
|
||||
font-size: 0.24rem;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 0.24rem;
|
||||
padding: 0.3rem 0.2rem;
|
||||
background: #fff;
|
||||
border-radius: 0.16rem;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
margin-top: 0.4rem;
|
||||
border: 1px solid #eef2f9;
|
||||
width: 100%;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
@ -323,19 +332,7 @@
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
padding: 0.16rem 0.2rem;
|
||||
background: #fff;
|
||||
border-radius: 0.12rem;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
border: 1px solid #eef2f9;
|
||||
|
||||
&:hover {
|
||||
background: #fff;
|
||||
border-color: #2ebdfa;
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 16px rgba(39, 90, 255, 0.12);
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
width: 0.2rem;
|
||||
@ -372,7 +369,9 @@
|
||||
gap: 0.16rem;
|
||||
}
|
||||
}
|
||||
|
||||
.center{
|
||||
// display: flex;
|
||||
}
|
||||
.phone-link {
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
@ -434,6 +433,7 @@
|
||||
|
||||
&:hover {
|
||||
background: #fff;
|
||||
|
||||
border-color: #2ebdfa;
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 8px 24px rgba(39, 90, 255, 0.15);
|
||||
|
||||
@ -4,7 +4,22 @@
|
||||
<div class="top-tit">
|
||||
开元云
|
||||
</div>
|
||||
|
||||
<!-- 搜索 -->
|
||||
<div class="search">
|
||||
<div class="search-box">
|
||||
<div class="input">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="请输入产品名称"
|
||||
v-model="searchValue"
|
||||
@keyup.enter="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
<div class="search-btn" @click="handleSearch">
|
||||
搜索
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 供应商 -->
|
||||
<div v-if="cloudData.secMenu && cloudData.secMenu.length > 0" class="supplier-container">
|
||||
<div
|
||||
@ -32,6 +47,7 @@
|
||||
v-for="product in thrMenu.value"
|
||||
:key="product.id"
|
||||
class="box-item"
|
||||
v-show="shouldShowProduct(product)"
|
||||
>
|
||||
<!-- 标题 -->
|
||||
<div class="item-tit">
|
||||
@ -76,13 +92,14 @@ import { reqProductConsult } from '@/api/H5/index'
|
||||
export default {
|
||||
components: {
|
||||
ProductConsultDialog,
|
||||
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
cloudData: {},
|
||||
activeSupplierIndex: 0, // 默认选中第一个供应商
|
||||
searchValue: '', // 搜索关键词
|
||||
isSearching: false, // 是否正在搜索
|
||||
|
||||
// 咨询弹窗相关
|
||||
showConsultDialog: false,
|
||||
@ -116,6 +133,25 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
// 处理搜索
|
||||
handleSearch() {
|
||||
this.isSearching = !!this.searchValue.trim()
|
||||
console.log('搜索关键词:', this.searchValue)
|
||||
},
|
||||
|
||||
// 判断产品是否应该显示
|
||||
shouldShowProduct(product) {
|
||||
if (!this.isSearching) {
|
||||
return true
|
||||
}
|
||||
// 模糊搜索
|
||||
const keyword = this.searchValue.toLowerCase().trim()
|
||||
return (
|
||||
(product.name && product.name.toLowerCase().includes(keyword)) ||
|
||||
(product.description && product.description.toLowerCase().includes(keyword))
|
||||
)
|
||||
},
|
||||
|
||||
// 选择供应商
|
||||
selectSupplier(index) {
|
||||
this.activeSupplierIndex = index
|
||||
|
||||
@ -21,17 +21,18 @@
|
||||
<!-- 内容 -->
|
||||
<div class="content">
|
||||
<div class="item-box" v-for="(item, key) in baseData" :key="key">
|
||||
|
||||
<div class="item-title">{{ item.title }}</div>
|
||||
<div class="item-description">{{ item.description }}</div>
|
||||
|
||||
<!-- 优势列表 -->
|
||||
<div class="advantage-list" v-if="item.list && item.list.length">
|
||||
<div class="advantage-item" v-for="listItem in item.list" :key="listItem.id">
|
||||
<p>
|
||||
<img v-if="listItem.icon" :src="getIconPath(listItem.icon)" alt="" class="advantage-icon" />
|
||||
<div>
|
||||
<img v-if="listItem.icon" :src="getIconPath(listItem.icon)" alt="" class="advantage-icon" />
|
||||
<span v-if="listItem.name" class="advantage-name">{{ listItem.name }} : </span>
|
||||
<span class="advantage-content">{{ listItem.content }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -61,11 +62,11 @@
|
||||
<!-- 优势列表 -->
|
||||
<div class="advantage-list" v-if="item.list && item.list.length">
|
||||
<div class="advantage-item" v-for="listItem in item.list" :key="listItem.id">
|
||||
<p>
|
||||
<img v-if="listItem.icon" :src="getIconPath(listItem.icon)" alt="" class="advantage-icon" />
|
||||
<div>
|
||||
<img v-if="listItem.icon" :src="getIconPath(listItem.icon)" alt="" class="advantage-icon" />
|
||||
<span v-if="listItem.name" class="advantage-name">{{ listItem.name }} : </span>
|
||||
<span class="advantage-content">{{ listItem.content }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -95,11 +96,11 @@
|
||||
<!-- 优势列表 -->
|
||||
<div class="advantage-list" v-if="item.advantageList && item.advantageList.length">
|
||||
<div class="advantage-item" v-for="advantage in item.advantageList" :key="advantage.id">
|
||||
<p>
|
||||
<img v-if="advantage.icon" :src="getIconPath(advantage.icon)" alt="" class="advantage-icon" />
|
||||
<span class="advantage-name">{{ advantage.name }}:</span>
|
||||
<span class="advantage-content">{{ advantage.content }}</span>
|
||||
</p>
|
||||
<div>
|
||||
<img v-if="advantage.icon" :src="getIconPath(advantage.icon)" alt="" class="advantage-icon" />
|
||||
<span class="advantage-name">{{ advantage.name }}:</span>
|
||||
<span class="advantage-content">{{ advantage.content }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -135,7 +136,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 修改footer部分 -->
|
||||
<!-- footer部分 -->
|
||||
<div class="footer">
|
||||
<div class="footer-content">
|
||||
<!-- 顶部信息 -->
|
||||
@ -144,12 +145,15 @@
|
||||
<img :src="logoImg" alt="公司logo" v-if="logoImg">
|
||||
<!-- <img src="@/assets/kyy/LOGO.png" alt="公司logo" class="img"> -->
|
||||
</div>
|
||||
<div class="contact-info">
|
||||
</div>
|
||||
<div class="footer-center">
|
||||
<div class="center">
|
||||
<div class="contact-item">
|
||||
<i class="iconfont icon-dizhi"></i>
|
||||
<span class="label">地址:</span>
|
||||
<span class="value">{{ address }}</span>
|
||||
</div>
|
||||
|
||||
<div class="contact-item">
|
||||
<i class="iconfont icon-dianhua"></i>
|
||||
<span class="label">电话:</span>
|
||||
@ -168,8 +172,25 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="mobile-qr">
|
||||
<div class="qr-item">
|
||||
<div class="qr-code">
|
||||
<img src="@/assets/kyy/kyy公众号.jpg" alt="微信客服二维码">
|
||||
</div>
|
||||
<span class="qr-desc">扫描关注二维码</span>
|
||||
</div>
|
||||
<div class="qr-item">
|
||||
<div class="qr-code">
|
||||
<img src="@/assets/kyy/客服wechat.png" alt="微信客服二维码">
|
||||
</div>
|
||||
<span class="qr-desc">微信客服</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
<!-- 备案信息 -->
|
||||
<div class="footer-bottom">
|
||||
<div class="icp-info">
|
||||
@ -182,6 +203,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="record-info">
|
||||
<div class="police-record">
|
||||
<img src="@/image/login/policeInsignia/policeInsignia.png" alt="公安备案图标" class="police-icon">
|
||||
@ -197,33 +219,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 移动端显示的二维码 -->
|
||||
<div class="mobile-qr">
|
||||
<div class="qr-item">
|
||||
<div class="qr-code">
|
||||
<img src="@/assets/kyy/kyy公众号.jpg" alt="微信客服二维码">
|
||||
</div>
|
||||
<span class="qr-desc">扫描关注二维码</span>
|
||||
</div>
|
||||
<div class="qr-item">
|
||||
<div class="qr-code">
|
||||
<img src="@/assets/kyy/客服wechat.png" alt="微信客服二维码">
|
||||
</div>
|
||||
<span class="qr-desc">微信客服</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- PC端显示的二维码(移动端隐藏) -->
|
||||
<div class="pc-qr">
|
||||
<div class="qr-box">
|
||||
<div class="qr-code">
|
||||
<img src="@/assets/kyy/客服wechat.png" alt="微信客服二维码">
|
||||
</div>
|
||||
<span class="qr-content">微信客服</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- 产品咨询弹窗 -->
|
||||
<ProductConsultDialog :visible.sync="showConsultDialog" :platform-name="platformName" :qr-code="qrCode"
|
||||
|
||||
@ -6,12 +6,19 @@
|
||||
</div>
|
||||
<!-- 搜索 -->
|
||||
<div class="search">
|
||||
<div class="search-box">
|
||||
<div class="input">
|
||||
<input type="text" placeholder="请输入产品名称" v-model="searchValue"></input>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="请输入产品名称"
|
||||
v-model="searchValue"
|
||||
@keyup.enter="handleSearch"
|
||||
/>
|
||||
</div>
|
||||
<div class="search-btn">
|
||||
搜索
|
||||
<div class="search-btn" @click="handleSearch">
|
||||
搜索
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 供应商 -->
|
||||
<div v-if="cloudData.secMenu && cloudData.secMenu.length > 0" class="supplier-container">
|
||||
@ -28,7 +35,7 @@
|
||||
<template v-if="cloudData.secMenu && cloudData.secMenu.length > 0 && activeSupplierIndex >= 0">
|
||||
<template v-for="thrMenu in cloudData.secMenu[activeSupplierIndex].thrMenu">
|
||||
<!-- 循环每个分类下的产品 -->
|
||||
<div v-for="product in thrMenu.value" :key="product.id" class="box-item">
|
||||
<div v-for="product in thrMenu.value" :key="product.id" class="box-item" v-show="shouldShowProduct(product)">
|
||||
<!-- 标题 -->
|
||||
<div class="item-tit">
|
||||
{{ product.name }}
|
||||
@ -73,6 +80,8 @@ export default {
|
||||
return {
|
||||
cloudData: {},
|
||||
activeSupplierIndex: 0, // 默认选中第一个供应商
|
||||
searchValue: '', // 搜索关键词
|
||||
isSearching: false, // 是否正在搜索
|
||||
|
||||
// 咨询弹窗相关
|
||||
showConsultDialog: false,
|
||||
@ -106,6 +115,25 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
// 处理搜索
|
||||
handleSearch() {
|
||||
this.isSearching = !!this.searchValue.trim()
|
||||
console.log('搜索关键词:', this.searchValue)
|
||||
},
|
||||
|
||||
// 判断产品是否应该显示
|
||||
shouldShowProduct(product) {
|
||||
if (!this.isSearching) {
|
||||
return true
|
||||
}
|
||||
// 模糊搜索:检查产品名称或分类名称中是否包含搜索关键词
|
||||
const keyword = this.searchValue.toLowerCase().trim()
|
||||
return (
|
||||
(product.name && product.name.toLowerCase().includes(keyword)) ||
|
||||
(this.currentCategory && this.currentCategory.thrTitle && this.currentCategory.thrTitle.toLowerCase().includes(keyword))
|
||||
)
|
||||
},
|
||||
|
||||
// 选择供应商
|
||||
selectSupplier(index) {
|
||||
this.activeSupplierIndex = index
|
||||
|
||||
@ -13,13 +13,11 @@
|
||||
</el-table-column>
|
||||
<el-table-column prop="content" label="内容" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column prop="create_time" label="咨询时间" min-width="180">
|
||||
<el-table-column prop="update_time" label="咨询时间" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column prop="update_time" label="联系时间" min-width="180">
|
||||
</el-table-column>
|
||||
<el-table-column prop="update_time" label="操作" min-width="180">
|
||||
<el-table-column prop="update_time" label="反馈状态" min-width="180">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="handleEdit(scope.row)">已回复</el-button>
|
||||
<el-button type="text" >{{ scope.row.feedback === '1' ? '已回复' : '未回复' }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user