|
@@ -7,6 +7,7 @@
|
|
<title>我的 - 饰品商城</title>
|
|
<title>我的 - 饰品商城</title>
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
|
<style>
|
|
<style>
|
|
|
|
+ /* 引入原来的CSS样式 */
|
|
* {
|
|
* {
|
|
margin: 0;
|
|
margin: 0;
|
|
padding: 0;
|
|
padding: 0;
|
|
@@ -305,6 +306,28 @@
|
|
.tab-item span {
|
|
.tab-item span {
|
|
font-size: 12px;
|
|
font-size: 12px;
|
|
}
|
|
}
|
|
|
|
+ /* 客服浮窗样式 */
|
|
|
|
+ .customer-service-float {
|
|
|
|
+ position: fixed;
|
|
|
|
+ bottom: 80px; /* 调整位置,避免和底部tab栏重叠 */
|
|
|
|
+ right: 20px;
|
|
|
|
+ width: 50px;
|
|
|
|
+ height: 50px;
|
|
|
|
+ border-radius: 50%;
|
|
|
|
+ background-color: #2ecc71; /* 鲜艳的绿色 */
|
|
|
|
+ color: white;
|
|
|
|
+ display: flex;
|
|
|
|
+ align-items: center;
|
|
|
|
+ justify-content: center;
|
|
|
|
+ font-size: 24px;
|
|
|
|
+ cursor: pointer; /* 修改 cursor 为 pointer */
|
|
|
|
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
|
|
|
|
+ z-index: 1000; /* 确保在最上层 */
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ .customer-service-float:active {
|
|
|
|
+ cursor: grabbing;
|
|
|
|
+ }
|
|
</style>
|
|
</style>
|
|
</head>
|
|
</head>
|
|
<body>
|
|
<body>
|
|
@@ -524,104 +547,117 @@
|
|
</a>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
-
|
|
|
|
-<script>
|
|
|
|
- // 简单的交互逻辑
|
|
|
|
- document.addEventListener('DOMContentLoaded', function(){
|
|
|
|
- // 切换标签
|
|
|
|
- const tabs = document.querySelectorAll('.tab');
|
|
|
|
|
|
+ <!-- 客服浮窗 -->
|
|
|
|
+ <a href="AI.html">
|
|
|
|
+ <div class="customer-service-float">
|
|
|
|
+ <i class="bi bi-headset"></i>
|
|
|
|
+ </div>
|
|
|
|
+ </a>
|
|
|
|
+
|
|
|
|
+ <script>
|
|
|
|
+ // 简单的交互逻辑
|
|
|
|
+ document.addEventListener('DOMContentLoaded', function(){
|
|
|
|
+ // 切换标签
|
|
|
|
+ const tabs = document.querySelectorAll('.tab');
|
|
tabs.forEach(tab => {
|
|
tabs.forEach(tab => {
|
|
tab.addEventListener('click', function() {
|
|
tab.addEventListener('click', function() {
|
|
tabs.forEach(t => t.classList.remove('active'));
|
|
tabs.forEach(t => t.classList.remove('active'));
|
|
this.classList.add('active');
|
|
this.classList.add('active');
|
|
- });
|
|
|
|
- });
|
|
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
|
|
- // 切换底部Tab
|
|
|
|
|
|
+ // 切换底部Tab
|
|
const tabItems = document.querySelectorAll('.tab-item');
|
|
const tabItems = document.querySelectorAll('.tab-item');
|
|
- tabItems.forEach(item => {
|
|
|
|
|
|
+ tabItems.forEach(item => {
|
|
item.addEventListener('click', function() {
|
|
item.addEventListener('click', function() {
|
|
tabItems.forEach(i => i.classList.remove('active'));
|
|
tabItems.forEach(i => i.classList.remove('active'));
|
|
this.classList.add('active');
|
|
this.classList.add('active');
|
|
- });
|
|
|
|
});
|
|
});
|
|
|
|
+ });
|
|
|
|
|
|
// 顶部标签栏滚动效果 (优化版)
|
|
// 顶部标签栏滚动效果 (优化版)
|
|
- const tabsContainer = document.querySelector('.tabs');
|
|
|
|
- let isDown = false;
|
|
|
|
|
|
+ const tabsContainer = document.querySelector('.tabs');
|
|
|
|
+ let isDown = false;
|
|
let startX;
|
|
let startX;
|
|
let scrollLeft;
|
|
let scrollLeft;
|
|
let velocity = 0;
|
|
let velocity = 0;
|
|
let lastTime = 0;
|
|
let lastTime = 0;
|
|
|
|
|
|
- // 惯性滚动参数
|
|
|
|
|
|
+ // 惯性滚动参数
|
|
const DECELERATION = 0.92;
|
|
const DECELERATION = 0.92;
|
|
- const FRAME_DURATION =16;
|
|
|
|
|
|
+ const FRAME_DURATION = 16;
|
|
|
|
|
|
- // 通用按下事件处理
|
|
|
|
- function handlePointerDown(e) {
|
|
|
|
- isDown = true;
|
|
|
|
- const clientX = e.type.includes('touch') ? e.touches[0].clientX : e.clientX;
|
|
|
|
- startX = clientX - tabsContainer.getBoundingClientRect().left;
|
|
|
|
- scrollLeft = tabsContainer.scrollLeft;
|
|
|
|
- lastTime = performance.now();
|
|
|
|
- velocity = 0;
|
|
|
|
- }
|
|
|
|
|
|
+ // 通用按下事件处理
|
|
|
|
+ function handlePointerDown(e) {
|
|
|
|
+ isDown = true;
|
|
|
|
+ const clientX = e.type.includes('touch') ? e.touches[0].clientX : e.clientX;
|
|
|
|
+ startX = clientX - tabsContainer.getBoundingClientRect().left;
|
|
|
|
+ scrollLeft = tabsContainer.scrollLeft;
|
|
|
|
+ lastTime = performance.now();
|
|
|
|
+ velocity = 0;
|
|
|
|
+ }
|
|
|
|
|
|
// 通用移动事件处理
|
|
// 通用移动事件处理
|
|
- function handlePointerMove(e) {
|
|
|
|
|
|
+ function handlePointerMove(e) {
|
|
if (!isDown) return;
|
|
if (!isDown) return;
|
|
- const clientX = e.type.includes('touch') ? e.touches[0].clientX : e.clientX;
|
|
|
|
- const x = clientX - tabsContainer.getBoundingClientRect().left;
|
|
|
|
|
|
+ const clientX = e.type.includes('touch') ? e.touches[0].clientX : e.clientX;
|
|
|
|
+ const x = clientX - tabsContainer.getBoundingClientRect().left;
|
|
const walk = (x - startX) * 1.5; // 调整滚动系数
|
|
const walk = (x - startX) * 1.5; // 调整滚动系数
|
|
|
|
|
|
// 记录速度用于惯性滚动
|
|
// 记录速度用于惯性滚动
|
|
const now = performance.now();
|
|
const now = performance.now();
|
|
- const deltaTime = now - lastTime;
|
|
|
|
|
|
+ const deltaTime = now - lastTime;
|
|
if (deltaTime > 0) {
|
|
if (deltaTime > 0) {
|
|
- velocity = (walk - (tabsContainer.scrollLeft - scrollLeft)) / deltaTime;
|
|
|
|
- }
|
|
|
|
|
|
+ velocity = (walk - (tabsContainer.scrollLeft - scrollLeft)) / deltaTime;
|
|
|
|
+ }
|
|
lastTime = now;
|
|
lastTime = now;
|
|
- tabsContainer.scrollLeft = scrollLeft - walk;
|
|
|
|
- }
|
|
|
|
|
|
+ tabsContainer.scrollLeft = scrollLeft - walk;
|
|
|
|
+ }
|
|
|
|
|
|
// 惯性滚动函数
|
|
// 惯性滚动函数
|
|
- function inertialScroll() {
|
|
|
|
- if (!isDown && Math.abs(velocity) > 0.1) {
|
|
|
|
- velocity *= DECELERATION;
|
|
|
|
|
|
+ function inertialScroll() {
|
|
|
|
+ if (!isDown && Math.abs(velocity) > 0.1) {
|
|
|
|
+ velocity *= DECELERATION;
|
|
tabsContainer.scrollLeft += velocity * FRAME_DURATION;
|
|
tabsContainer.scrollLeft += velocity * FRAME_DURATION;
|
|
requestAnimationFrame(inertialScroll);
|
|
requestAnimationFrame(inertialScroll);
|
|
- } else {
|
|
|
|
- velocity = 0;
|
|
|
|
|
|
+ } else {
|
|
|
|
+ velocity = 0;
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
+ }
|
|
|
|
|
|
// 事件监听优化
|
|
// 事件监听优化
|
|
- tabsContainer.addEventListener('mousedown', handlePointerDown);
|
|
|
|
|
|
+ tabsContainer.addEventListener('mousedown', handlePointerDown);
|
|
tabsContainer.addEventListener('touchstart', handlePointerDown);
|
|
tabsContainer.addEventListener('touchstart', handlePointerDown);
|
|
document.addEventListener('mousemove', handlePointerMove);
|
|
document.addEventListener('mousemove', handlePointerMove);
|
|
document.addEventListener('touchmove', (e) => {
|
|
document.addEventListener('touchmove', (e) => {
|
|
handlePointerMove(e);
|
|
handlePointerMove(e);
|
|
e.preventDefault(); // 阻止默认滚动行为
|
|
e.preventDefault(); // 阻止默认滚动行为
|
|
- }, { passive: false });
|
|
|
|
|
|
+ }, { passive: false });
|
|
|
|
|
|
- document.addEventListener('mouseup', () => {
|
|
|
|
- isDown = false;
|
|
|
|
- requestAnimationFrame(inertialScroll);
|
|
|
|
- });
|
|
|
|
- document.addEventListener('touchend', () => {
|
|
|
|
- isDown = false;
|
|
|
|
- requestAnimationFrame(inertialScroll);
|
|
|
|
- });
|
|
|
|
|
|
+ document.addEventListener('mouseup', () => {
|
|
|
|
+ isDown = false;
|
|
|
|
+ requestAnimationFrame(inertialScroll);
|
|
|
|
+ });
|
|
|
|
+ document.addEventListener('touchend', () => {
|
|
|
|
+ isDown = false;
|
|
|
|
+ requestAnimationFrame(inertialScroll);
|
|
|
|
+ });
|
|
|
|
|
|
// 容器边界限制
|
|
// 容器边界限制
|
|
- tabsContainer.addEventListener('scroll', () => {
|
|
|
|
- const maxScroll = tabsContainer.scrollWidth - tabsContainer.clientWidth;
|
|
|
|
- if (tabsContainer.scrollLeft < 0) {
|
|
|
|
|
|
+ tabsContainer.addEventListener('scroll', () => {
|
|
|
|
+ const maxScroll = tabsContainer.scrollWidth - tabsContainer.clientWidth;
|
|
|
|
+ if (tabsContainer.scrollLeft < 0) {
|
|
tabsContainer.scrollLeft = 0;
|
|
tabsContainer.scrollLeft = 0;
|
|
- } else if (tabsContainer.scrollLeft > maxScroll) {
|
|
|
|
|
|
+ } else if (tabsContainer.scrollLeft > maxScroll) {
|
|
tabsContainer.scrollLeft = maxScroll;
|
|
tabsContainer.scrollLeft = maxScroll;
|
|
}
|
|
}
|
|
- });
|
|
|
|
- }); // 结束DOMContentLoaded
|
|
|
|
- </script>
|
|
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 客服浮窗拖动
|
|
|
|
+ const floatButton = document.querySelector('.customer-service-float');
|
|
|
|
+ let isDragging = false;
|
|
|
|
+ let offsetX, offsetY;
|
|
|
|
+ }); // 结束DOMContentLoaded
|
|
|
|
+ </script>
|
|
|
|
+</body>
|
|
|
|
+</html>
|