当前位置: 首页 > news >正文

前端开发:创建可拖动的固定位置 `<div>` 和自动隐藏悬浮按钮

在前端开发中,实现一个可拖动的固定位置 <div>,并且根据拖动的状态控制其显示和隐藏,同时在特定条件下显示悬浮按钮,涉及以下技术和原理:

技术细节和实现步骤:

1. HTML 结构:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Draggable Fixed Div with Auto Hide and Floating Button</title>
<style>/* CSS 样式,定义拖拽元素和悬浮按钮的样式 */
</style>
</head>
<body><!-- 拖拽的固定位置的 div -->
<div id="draggable"><p>Drag me!</p><button>Click me</button>
</div><!-- 默认显示的悬浮按钮 -->
<div id="dragButton">Show</div><!-- JavaScript 脚本,实现拖拽、自动隐藏和按钮显示逻辑 -->
<script>// JavaScript 代码部分
</script></body>
</html>

2. CSS 样式:

#draggable {width: 200px;height: 200px;background-color: #ccc;position: fixed;top: 50px;left: 50px;touch-action: none; /* 禁止浏览器默认行为,如滚动 */transition: transform 0.3s ease;
}#draggable.hidden {transform: scale(0);visibility: hidden;
}#dragButton {position: fixed;bottom: 20px;right: 20px;background-color: #007bff;color: white;padding: 10px 20px;cursor: pointer;
}

        • #draggable 样式:定义拖拽元素的基本样式,包括固定位置、尺寸、背景色等。

        • .hidden 类样式:用于控制拖拽元素隐藏时的动画效果。

        • #dragButton 样式:定义悬浮按钮的基本样式,包括位置、背景色、文字颜色等。

3. JavaScript 交互:

const draggable = document.getElementById('draggable');
const dragButton = document.getElementById('dragButton');
let offsetX, offsetY;
let isDragging = false;
let autoHideTimeout;
let lastVisiblePosition = { top: 50, left: 50 }; // 初始位置// 触摸事件处理
draggable.addEventListener('touchstart', touchStart);
draggable.addEventListener('touchmove', touchMove);
draggable.addEventListener('touchend', touchEnd);// 鼠标事件处理
draggable.addEventListener('mousedown', mouseDown);
document.addEventListener('mousemove', mouseMove);
document.addEventListener('mouseup', mouseUp);// 初始隐藏拖拽元素
draggable.classList.add('hidden');function touchStart(e) {const touch = e.touches[0];offsetX = touch.clientX - draggable.getBoundingClientRect().left;offsetY = touch.clientY - draggable.getBoundingClientRect().top;isDragging = true;
}function touchMove(e) {if (!isDragging) return;e.preventDefault(); // 阻止默认的滚动行为const touch = e.touches[0];let newX = touch.clientX - offsetX;let newY = touch.clientY - offsetY;// 限制拖动范围在可视区域内const maxX = document.documentElement.clientWidth - draggable.offsetWidth;const maxY = document.documentElement.clientHeight - draggable.offsetHeight;newX = Math.max(0, Math.min(newX, maxX));newY = Math.max(0, Math.min(newY, maxY));draggable.style.left = `${newX}px`;draggable.style.top = `${newY}px`;// 判断靠近边缘并自动贴边if (newX < 10) {draggable.style.left = '0';} else if (newX > maxX - 10) {draggable.style.left = `${maxX}px`;}if (newY < 10) {draggable.style.top = '0';} else if (newY > maxY - 10) {draggable.style.top = `${maxY}px`;}// 更新最后显示位置lastVisiblePosition = { top: parseInt(draggable.style.top), left: parseInt(draggable.style.left) };// 自动隐藏计时器重置clearTimeout(autoHideTimeout);draggable.classList.remove('hidden');dragButton.style.display = 'none';
}function touchEnd() {isDragging = false;// 设置自动隐藏autoHideTimeout = setTimeout(() => {draggable.classList.add('hidden');// 固定悬浮按钮位置dragButton.style.top = '20px';dragButton.style.right = '20px';dragButton.style.display = 'block';}, 5000); // 5秒后自动隐藏
}function mouseDown(e) {offsetX = e.clientX - draggable.getBoundingClientRect().left;offsetY = e.clientY - draggable.getBoundingClientRect().top;isDragging = true;
}function mouseMove(e) {if (!isDragging) return;e.preventDefault(); // 阻止默认的拖动行为let newX = e.clientX - offsetX;let newY = e.clientY - offsetY;// 限制拖动范围在可视区域内const maxX = document.documentElement.clientWidth - draggable.offsetWidth;const maxY = document.documentElement.clientHeight - draggable.offsetHeight;newX = Math.max(0, Math.min(newX, maxX));newY = Math.max(0, Math.min(newY, maxY));draggable.style.left = `${newX}px`;draggable.style.top = `${newY}px`;// 判断靠近边缘并自动贴边if (newX < 10) {draggable.style.left = '0';} else if (newX > maxX - 10) {draggable.style.left = `${maxX}px`;}if (newY < 10) {draggable.style.top = '0';} else if (newY > maxY - 10) {draggable.style.top = `${maxY}px`;}// 更新最后显示位置lastVisiblePosition = { top: parseInt(draggable.style.top), left: parseInt(draggable.style.left) };// 自动隐藏计时器重置clearTimeout(autoHideTimeout);draggable.classList.remove('hidden');dragButton.style.display = 'none';
}function mouseUp() {isDragging = false;// 设置自动隐藏autoHideTimeout = setTimeout(() => {draggable.classList.add('hidden');// 固定悬浮按钮位置dragButton.style.top = '20px';dragButton.style.right = '20px';dragButton.style.display = 'block';}, 5000); // 5秒后自动隐藏
}dragButton.addEventListener('click', () => {draggable.classList.remove('hidden');dragButton.style.display = 'none';
});

技术和原理分析:

• HTML 结构:使用 <div> 元素创建拖拽的固定位置容器和悬浮按钮,配合 CSS 控制其样式。

• CSS 样式:定义了拖拽元素和悬浮按钮的基本样式,包括位置、背景色等,利用 transition 属性实现元素显示隐藏的动画效果。

• JavaScript 交互:

• 拖拽实现:通过 touchstart, touchmove, touchend, mousedown, mousemove, mouseup 等事件监听器,实现移动设备和桌面设备上的拖拽功能。在拖动过程中,更新拖拽元素的位置,并根据距离屏幕边缘的距离自动贴边。

• 自动隐藏和按钮显示逻辑:利用 setTimeout 实现拖拽元素在一定时间内无操作后自动隐藏,并显示固定位置的悬浮按钮。点击悬浮按钮则重新显示拖拽元素。可以根据需要选择显示固定位置或者根据最后显示位置动态调整的悬浮按钮。

最后完整代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Draggable Fixed Div with Auto Hide and Floating Button</title>
<style>#draggable {width: 200px;height: 200px;background-color: #ccc;position: fixed;top: 50px;left: 50px;touch-action: none; /* 禁止浏览器默认行为,如滚动 */transition: transform 0.3s ease;}#draggable.hidden {transform: scale(0);visibility: hidden;}/* 默认固定悬浮按钮 */#dragButton {position: fixed;bottom: 20px;right: 20px;background-color: #007bff;color: white;padding: 10px 20px;cursor: pointer;}/* 根据最后显示位置调整的悬浮按钮 *//*#dragButton.dynamic {position: fixed;background-color: #007bff;color: white;padding: 10px 20px;cursor: pointer;display: none;}*/
</style>
</head>
<body><div id="draggable"><p>Drag me!</p><button>Click me</button>
</div><div id="dragButton" class="fixed">Show</div>
<!-- <div id="dragButton" class="dynamic">Show</div> --><script>const draggable = document.getElementById('draggable');const dragButton = document.getElementById('dragButton');let offsetX, offsetY;let isDragging = false;let autoHideTimeout;let lastVisiblePosition = { top: 50, left: 50 }; // 初始位置// 触摸事件处理draggable.addEventListener('touchstart', touchStart);draggable.addEventListener('touchmove', touchMove);draggable.addEventListener('touchend', touchEnd);// 鼠标事件处理draggable.addEventListener('mousedown', mouseDown);document.addEventListener('mousemove', mouseMove);document.addEventListener('mouseup', mouseUp);draggable.classList.add('hidden');function touchStart(e) {const touch = e.touches[0];offsetX = touch.clientX - draggable.getBoundingClientRect().left;offsetY = touch.clientY - draggable.getBoundingClientRect().top;isDragging = true;}function touchMove(e) {if (!isDragging) return;e.preventDefault(); // 阻止默认的滚动行为const touch = e.touches[0];let newX = touch.clientX - offsetX;let newY = touch.clientY - offsetY;// 限制拖动范围在可视区域内const maxX = document.documentElement.clientWidth - draggable.offsetWidth;const maxY = document.documentElement.clientHeight - draggable.offsetHeight;newX = Math.max(0, Math.min(newX, maxX));newY = Math.max(0, Math.min(newY, maxY));draggable.style.left = `${newX}px`;draggable.style.top = `${newY}px`;// 判断靠近边缘并自动贴边if (newX < 10) {draggable.style.left = '0';} else if (newX > maxX - 10) {draggable.style.left = `${maxX}px`;}if (newY < 10) {draggable.style.top = '0';} else if (newY > maxY - 10) {draggable.style.top = `${maxY}px`;}// 更新最后显示位置lastVisiblePosition = { top: parseInt(draggable.style.top), left: parseInt(draggable.style.left) };// 自动隐藏计时器重置clearTimeout(autoHideTimeout);draggable.classList.remove('hidden');dragButton.style.display = 'none';}function touchEnd() {isDragging = false;// 设置自动隐藏autoHideTimeout = setTimeout(() => {draggable.classList.add('hidden');// 固定悬浮按钮位置dragButton.style.top = '20px';dragButton.style.right = '20px';dragButton.style.display = 'block';// 动态悬浮按钮位置/*dragButton.classList.add('dynamic');dragButton.style.top = `${lastVisiblePosition.top}px`;dragButton.style.left = `${lastVisiblePosition.left}px`;*/}, 5000); // 5秒后自动隐藏}function mouseDown(e) {offsetX = e.clientX - draggable.getBoundingClientRect().left;offsetY = e.clientY - draggable.getBoundingClientRect().top;isDragging = true;}function mouseMove(e) {if (!isDragging) return;e.preventDefault(); // 阻止默认的拖动行为let newX = e.clientX - offsetX;let newY = e.clientY - offsetY;// 限制拖动范围在可视区域内const maxX = document.documentElement.clientWidth - draggable.offsetWidth;const maxY = document.documentElement.clientHeight - draggable.offsetHeight;newX = Math.max(0, Math.min(newX, maxX));newY = Math.max(0, Math.min(newY, maxY));draggable.style.left = `${newX}px`;draggable.style.top = `${newY}px`;// 判断靠近边缘并自动贴边if (newX < 10) {draggable.style.left = '0';} else if (newX > maxX - 10) {draggable.style.left = `${maxX}px`;}if (newY < 10) {draggable.style.top = '0';} else if (newY > maxY - 10) {draggable.style.top = `${maxY}px`;}// 更新最后显示位置lastVisiblePosition = { top: parseInt(draggable.style.top), left: parseInt(draggable.style.left) };// 自动隐藏计时器重置clearTimeout(autoHideTimeout);draggable.classList.remove('hidden');dragButton.style.display = 'none';}function mouseUp() {isDragging = false;// 设置自动隐藏autoHideTimeout = setTimeout(() => {draggable.classList.add('hidden');// 固定悬浮按钮位置      dragButton.style.right = '20px';dragButton.style.display = 'block';// 动态悬浮按钮位置/*dragButton.classList.add('dynamic');dragButton.style.top = `${lastVisiblePosition.top}px`;dragButton.style.left = `${lastVisiblePosition.left}px`;*/}, 5000); // 5秒后自动隐藏}dragButton.addEventListener('click', () => {draggable.classList.remove('hidden');dragButton.style.display = 'none';// 动态悬浮按钮位置的显示控制// dragButton.classList.remove('dynamic');});
</script></body>
</html>

这篇博客文章介绍了如何利用 HTML、CSS 和 JavaScript 实现一个具有拖拽、自动隐藏和悬浮按钮的交互效果,适用于创建可定制的用户界面体验。

相关文章:

前端开发:创建可拖动的固定位置 `<div>` 和自动隐藏悬浮按钮

在前端开发中&#xff0c;实现一个可拖动的固定位置 <div>&#xff0c;并且根据拖动的状态控制其显示和隐藏&#xff0c;同时在特定条件下显示悬浮按钮&#xff0c;涉及以下技术和原理&#xff1a; 技术细节和实现步骤&#xff1a; 1. HTML 结构&#xff1a; <!DOC…...

Java Bean Validation 注解:@NotEmpty、@NotBlank 和 @NotNull 的区别

1. 概述 Bean Validation 是 Java 提供的一种对 Java Bean 实例的字段或方法参数进行校验的标准机制。它允许开发者使用注解的方式定义验证逻辑&#xff0c;这些注解可以在类、字段或者方法上声明&#xff0c;并且可以被任何实现了 JSR 303/JSR 349 规范的框架&#xff08;如 …...

Java | Leetcode Java题解之第322题零钱兑换

题目&#xff1a; 题解&#xff1a; public class Solution {public int coinChange(int[] coins, int amount) {int max amount 1;int[] dp new int[amount 1];Arrays.fill(dp, max);dp[0] 0;for (int i 1; i < amount; i) {for (int j 0; j < coins.length; j)…...

Linux初启征程指南:攻克常见系统指令与权限初理解

有时候觉得&#xff0c;电脑就像一个高贵冷艳的妹纸。 400&#xff0c;是她冷冰冰地说&#xff1a;“我听不懂你在说什么”&#xff1b; 401&#xff0c;是她无情地转身&#xff1a;“我不认识你&#xff0c;别说那些奇怪的话”&#xff1b; 403&#xff0c;是她残酷的拒绝&…...

第十九节、野猪受伤死亡逻辑动画

一、协程 在这个代码中&#xff0c;update更新非常快&#xff0c;不会有时间去addforce增加力 所以需要使用协程&#xff0c;同时开启 1、写法 WaitForSeconds(0.45f) 意思是等待时间0.45秒后 写完协程程序后&#xff0c;需要开启 &#xff0c;固定写法如下 2、注意 dir是局…...

vue 开发工具 Hbuilder 简介及应用

一、简介 HBuilderX 是一款流行的前端开发工具&#xff0c;由DCloud公司开发。它支持多种编程语言&#xff0c;如HTML、CSS、JavaScript、Vue、UniApp等&#xff0c;非常适合用来开发Web应用、移动端应用和跨平台应用。 官网地址&#xff1a;https://www.dcloud.io/hbuilderx.…...

【杂谈】-MQTT与HTTP在物联网中的比较:为什么MQTT是更好的选择

MQTT与HTTP在物联网中的比较&#xff1a;为什么MQTT是更好的选择 文章目录 MQTT与HTTP在物联网中的比较&#xff1a;为什么MQTT是更好的选择1、什么是MQTT2、什么是HTTP3、MQTT和HTTP之间的差异 MQTT&#xff08;消息队列遥测传输&#xff09;和HTTP&#xff08;超文本传输协议…...

冠豪猪优化算法(CPO)、卷积神经网络(CNN)与支持向量机(SVM)结合的预测模型(CPO-CNN-SVM)及其Python和MATLAB实现

### 一、背景 在现代数据挖掘和机器学习领域&#xff0c;特征选择与模型优化是两个重要的研究方向。随着深度学习的发展&#xff0c;卷积神经网络&#xff08;CNN&#xff09;在图像、视频等多媒体数据处理中的表现优异。然而&#xff0c;传统的CNN模型通常需要大量的标注数据和…...

【通信原理】

通信原理 二、频谱与随机信号2.1 频谱2.1.1 频谱or频谱密度函数2.1.2 幅度谱&#xff08;幅频特性&#xff09;or相位谱&#xff08;相频特性&#xff09; 2.2 能量信号2.2.1 什么是能量信号2.2.2 巴塞瓦尔定理2.2.3 维纳钦辛定理 2.3 功率信号2.3.1 功率信号2.3.2 巴塞瓦尔定理…...

有序数组的平方(LeetCode)

题目 给你一个按 非递减顺序 排序的整数数组 nums&#xff0c;返回 每个数字的平方 组成的新数组&#xff0c;要求也按 非递减顺序 排序。 解题 以下算法时间复杂度为 def sortedSquares(nums):n len(nums)result [0] * n # 创建一个结果数组&#xff0c;长度与 nums 相同le…...

Python配置镜像

1. 查看当前源 pip config get global.index-url 2. 临时变更源 pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple 3. 永久变更源 清华&#xff08;推荐速度最快&#xff09; pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple 百…...

Python新手错误集锦(PyCharm)

# 自学Python&#xff0c;用Pycharm作环境。我这个手新到这时我学习的第一个编程软件&#xff0c;且本人专业是化学&#xff0c;以前对电脑最高级的使用是玩扫雷游戏。所以这里集合的错误都是小透明错误&#xff0c;大部分人请绕道。不断更新中...... 缩进错误 记住“indent”…...

CTFHUB-web-RCE-php://input

开启题目 网页显示源代码&#xff0c;判断如果参数以 php:// 开头&#xff0c;那么执行 include 函数将参数值作为文件包含进来。否则&#xff0c;输出字符串 Hacker 。 点击下面的 phpinfo 跳转之后发现了一个 php 版本页面 使用 file 查看 php://input&#xff0c; 感觉这个…...

Python网络爬虫核心面试题

网络爬虫 1. 爬虫项目中如何处理请求失败的问题&#xff1f;2. 解释HTTP协议中的持久连接和非持久连接。3. 什么是HTTP的持久化Cookie和会话Cookie&#xff1f;4. 如何在爬虫项目中检测并处理网络抖动和丢包&#xff1f;5. 在爬虫项目中&#xff0c;如何使用HEAD请求提高效率&a…...

DSL domain specific language of Kola

How we design Kola - ApiHugKola background, Kola a consumer driver tester frameworkhttps://apihug.com/zhCN-docs/kola/003_dsl_contract Concept 在 Kola 定位中 Kola 是什么, 是致力于提供一个让相关各方都能够理解共同创造的测试框架和工具。 同时 Kola 是建立于业界…...

【RISC-V设计-05】- RISC-V处理器设计K0A之GPR

【RISC-V设计-05】- RISC-V处理器设计K0A之GPR 文章目录 【RISC-V设计-05】- RISC-V处理器设计K0A之GPR1.简介2.设计顶层3.内部结构4.端口说明5.设计代码6.总结 1.简介 通用寄存器&#xff08;General Purpose Register&#xff09;是处理器设计中的重要组成部分&#xff0c;在…...

Linux/C 高级——shell脚本

1. shell脚本基础概念 1.1概念 shell使用方式&#xff1a;手动下命令和脚本 脚本本质是一个文件&#xff0c;文件里面存放的是特定格式的指令&#xff0c;系统可以使用脚本解析器翻译或解析指令并执行&#xff08;它不需要编译&#xff09;。 shell脚本本质&#xff1a;shell命…...

SpringBoot面试题整理(1)

面试整理 前置知识 ApplicationContextInitializerApplicationListenerBeanFactoryBeanDefinitionBeanFactoryPostProcessorAwareInitializingBean/DisposableBeanBeanPostProcessor 面试题 SpringBoot启动流程IOC容器初始化流程Bean声明周期Bean循环依赖SpringMVC执行流程…...

LVS原理及实例

目录 LVS原理 LVS概念 lvs集群的类型 lvs-nat 解释 传输过程 lvs-dr 解释 传输过程 特点 lvs-tun LVS&#xff08;Linux Virtual Server&#xff09;常见的调度算法 防火墙标记&#xff08;Firewall Marking&#xff09;结合轮询调度 实战案例 lvs的nat模式配置 …...

Spring统一功能处理:拦截器、响应与异常的统一管理

目录 一.拦截器 二.统一数据返回格式 三.统一异常处理 一.拦截器 拦截器是Spring框架提供的核⼼功能之⼀&#xff0c;主要⽤来拦截⽤⼾的请求&#xff0c;在指定⽅法前后&#xff0c;根据业务需要执⾏预先设定的代码。 也就是说&#xff0c;允许开发⼈员提前预定义⼀些逻辑…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...