首页
归档
分类
标签
更多
留言板
说说
关于
Search
1
饥荒联机版控制台代码大全
1,025 阅读
2
编译安装带 Brotli 压缩的 Nginx
930 阅读
3
Obsidian多端快速同步插件
901 阅读
4
树莓派+EC20模块实现连接蜂窝网和短信收发
888 阅读
5
EC20通过gammu接收短信再转发优化
865 阅读
软件
CSS
Python
MySql
Java
typecho自定义
Vue
学习笔记
Linux
Shell脚本
Nginx
树莓派
邮件
拍照
热点
ec20
云盘
系统烧录
好玩
饥荒
硬件
工具
笔记
随心记
登录
Search
标签搜索
树莓派
Linux
Java
CSS
饥荒
小妙招
个人热点
nextcloud
云盘
DHT11
学习笔记
树莓派拍照
Nginx
MySql
ESP
娱乐
ec20模块
文件共享
git
图床
Mango
累计撰写
51
篇文章
累计收到
7
条评论
首页
栏目
软件
CSS
Python
MySql
Java
typecho自定义
Vue
学习笔记
Linux
Shell脚本
Nginx
树莓派
邮件
拍照
热点
ec20
云盘
系统烧录
好玩
饥荒
硬件
工具
笔记
随心记
页面
归档
分类
标签
留言板
说说
关于
搜索到
19
篇与
的结果
2025-02-16
微信小程序自定义Navbar自定义组件简单兼容写法
前引在小程序项目中经常有要自定义navbar的需求,网上有很多大佬分享的教程,但有的不太兼容,有的又写的比较麻烦,这里分享一种本人在用兼容性较好而且代码比较简单的一种写法。原理解释微信小程序navbar头部可以拆分为几部分构成:状态栏高度、胶囊高度、胶囊上下两侧外边距高度 。如下图所示:只要能取到各个部分的值,定位navbar和设置高度都会十分简单。获取状态栏高度const systemInfo = wx.getWindowInfo(); systemInfo.statusBarHeight胶囊按钮高度用胶囊按钮的bottom - topconst menuButtonInfo = wx.getMenuButtonBoundingClientRect(); menuButtonInfo.bottom - menuButtonInfo.top胶囊按钮的上下外边距menuButtonInfo.top - systemInfo.statusBarHeight完整代码ts代码Component({ data: { navHeight: 0, // 胶囊高度 即 navbar高度 navWidth: 0, // 显示宽度 navMarginY: 0, // 胶囊上下外边距 statusBarHeight: 0, // 状态栏高度 }, lifetimes: { attached() { const systemInfo = wx.getWindowInfo(); const menuButtonInfo = wx.getMenuButtonBoundingClientRect(); this.setData({ statusBarHeight: systemInfo.statusBarHeight, navHeight: menuButtonInfo.bottom - menuButtonInfo.top, navMarginY: menuButtonInfo.top - systemInfo.statusBarHeight, navWidth: systemInfo.screenWidth - menuButtonInfo.right + menuButtonInfo.left - 10, }) }, }, })wxml代码<view class="nav-box" style="padding-top: {{statusBarHeight}}px;"> <view style="height: {{navHeight}}px; margin: {{navMarginY}}px 0; " class="navbar"> <view>back</view> <view class="title">标题部分</view> </view> </view>wxss代码.navbar { position: relative; display: flex; align-items: center; background-color: coral; color: #ffffff; padding: 0 16rpx; box-sizing: border-box; } .navbar .title { position: absolute; top: 0; left: 0; height: 100%; width: 100%; display: flex; justify-content: center; align-items: center; font-size: 32rpx; }这只是一个介绍原理的简单示例,具体代码要根据业务需求来做出修改
2025年02月16日
355 阅读
0 评论
0 点赞
2024-12-24
Java使用SXSSFWorkbook导出Excel工具类
列 1col2 (列2)col3 前引在项目中经常有导出Excel的需求,为了方便就封装了一个导出Excel到前端的工具类,使用下来还比较好用使用JDK版本:1.8spring boot版本:2.6.15前端请求:axiosJava代码Excel所需Maven依赖 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.0.1</version> </dependency>完整代码如下:public class excelUtils { public static CellStyle headStyle(Workbook workbook) { // 创建单元格样式 CellStyle headerStyle = workbook.createCellStyle(); // 设置字体样式 Font headerFont = workbook.createFont(); headerFont.setBold(true); // 加粗 headerFont.setFontHeightInPoints((short) 12); // 字体大小 headerStyle.setFont(headerFont); // 可选:设置其他样式属性 headerStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中 headerStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中 return headerStyle; } public static CellStyle tableStyle(Workbook workbook) { CellStyle tableStyle = workbook.createCellStyle(); tableStyle.setAlignment(HorizontalAlignment.CENTER); // 水平居中 tableStyle.setVerticalAlignment(VerticalAlignment.CENTER); // 垂直居中 return tableStyle; } /** * @author Mango * * 获取对象的字段值 * @param object 对象 * @param key 字段名 * @return 字段值 */ public static String getFieldString(Object object, String key) { if(object instanceof Map){ return String.valueOf(((Map<?, ?>) object).get(key)); } Field field = null; String value = ""; try { field = object.getClass().getDeclaredField(key); field.setAccessible(true); String orgStr = String.valueOf(field.get(object)); if (orgStr != null) { value = orgStr; // 处理数组类型 if (orgStr.startsWith("[") && orgStr.endsWith("]")) { value = orgStr .replace("[", "") .replace("]", "") .replace("\"", ""); } } } catch (NoSuchFieldException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } return value; } /** * @author Mango * 导出Excel * @param response HttpServletResponse * @param srcList 数据源 * @param keys 数据源对应字段列表 * @param titles 表头 * @param excelName 文件名 */ public static void exportExcel(HttpServletResponse response, List<?> srcList, List<String> keys, List<String> titles, String excelName) { // 创建workbook // 使用 SXSSFWorkbook 比 XSSFWorkbook 内存占用少 SXSSFWorkbook workbook = new SXSSFWorkbook(); // 根据workbook创建sheet Sheet sheet = workbook.createSheet(excelName); //设置表头 Row titleRoe = sheet.createRow(0); // 设置表头样式 CellStyle headStyle = headStyle(workbook); // 向单元格中添加表头数据 for (int i = 0; i < titles.size(); i++) { Cell cell = titleRoe.createCell(i); cell.setCellValue(titles.get(i)); cell.setCellStyle(headStyle); } // 定义数据样式 CellStyle tableStyle = tableStyle(workbook); // 处理表格数据 for (int i = 0; i < srcList.size(); i++) { // 获取一组数据 Object object = srcList.get(i); // 生成行 Row rowData = sheet.createRow(i + 1); // 设置行高 rowData.setHeight((short) 400); // 向每一行中的单元格添加数据 // keys 为对象字段列表 for (int j = 0; j < keys.size(); j++) { String key = keys.get(j); Cell cell = rowData.createCell(j); cell.setCellStyle(tableStyle); String value = getFieldString(object, key); cell.setCellValue(value); } // 每100行就写一次磁盘,减少内存消耗 if (i % 100 == 0) { try { ((SXSSFSheet) sheet).flushRows(100); // 将缓存中的数据写入磁盘 } catch (IOException e) { throw new RuntimeException(e); } } } // 获取当前时间作为文件名 LocalDateTime localDateTime = LocalDateTime.now(); String fileName = excelName + localDateTime.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ".xlsx"; // 设置响应头 try { response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); } catch (UnsupportedEncodingException e) { // 发生异常不处理中文文件名 response.setHeader("Content-Disposition", "attachment;filename=" + fileName); throw new RuntimeException(e); } response.setContentType("application/vnd.ms-excel;charset=utf-8"); response.setHeader("Accept-Ranges", "bytes"); // 返回数据 返回进度条 try (ByteArrayOutputStream fileOutputStream = new ByteArrayOutputStream(); ServletOutputStream out = response.getOutputStream()) { // 这里假设 workbook 是生成的 Excel 文件对象 workbook.write(fileOutputStream); // 获取文件的总大小,并设置响应头 byte[] fileBytes = fileOutputStream.toByteArray(); response.setHeader("Content-Length", String.valueOf(fileBytes.length)); // 分块传输文件内容 int chunkSize = 256; // 每次写入数据字节 int totalSize = fileBytes.length; int currentPosition = 0; while (currentPosition < totalSize) { int remaining = totalSize - currentPosition; int chunk = Math.min(chunkSize, remaining); // 写入一块数据 out.write(fileBytes, currentPosition, chunk); out.flush(); // 刷新输出流,确保数据传送给客户端 // 更新当前下载位置 currentPosition += chunk; } out.close(); workbook.close(); // 关闭工作簿 } catch (IOException e) { // 处理异常 response.reset(); response.setContentType("application/json"); response.setCharacterEncoding("utf-8"); Map<String, String> map = new HashMap<>(); map.put("message", "下载文件失败: " + e.getMessage()); try { response.getWriter().println(JSON.toJSONString(map)); } catch (IOException ee) { ee.printStackTrace(); } e.printStackTrace(); } } }前端请求示例请求接口export const outExcel = async ( data: any, downloadProgress: Function, ) => { return await request({ url: "/test/outExcel", method: "post", data, responseType: "blob", onDownloadProgress: (event: any) => { downloadProgress(event); }, }); }注:这里的代码是已经封装过的统一封装的axiosresponseType: “blob” 指定文件为二进制onDownloadProgress利用回调函数返回下载进度下载示例const exportExcel = async () => { isProcessing.value = true; let response = null; try { response = await props.downloadMethod(props.searchForm, (event: any) => { progress.value = (event.loaded / event.total) * 100; if (progress.value > 0) { isProcessing.value = false; } }); } catch (e: any) { isProcessing.value = false; //出错时结束处理状态 isError.value = true; //下载失败 } if (response == null) return; // 没有返回数据 if (!response.status) { isError.value = true; //接口返回错误设置为下载失败 } const fileName = "教师参与情况" + formatDate(new Date(), "yy-MM-dd hh:mm:ss") + ".xlsx"; const blob = new Blob([response.data], { type: "application/vnd.ms-excel" }); // 创建一个链接来下载 Blob 对象 const downloadLink = document.createElement("a"); downloadLink.href = URL.createObjectURL(blob); downloadLink.download = decodeURI(fileName); downloadLink.style.display = "none"; document.body.appendChild(downloadLink); // 触发点击事件以下载文件 downloadLink.click(); // 清理创建的链接对象 document.body.removeChild(downloadLink); };将props.downloadMethod替换为下载接口props.searchFormt替换为筛选数据
2024年12月24日
779 阅读
2 评论
0 点赞
2024-11-22
keep-alive使用记录(返回界面不刷新)
前引keep-alive是vue自带的一个内置组件,可以实现缓存包裹在其中的动态切换组件。{% link Vue,Built-in Components,https://cn.vuejs.org/api/built-in-components#keepalive %}我这里是和路由结合全局使用全局添加keep-alive在界面切换的router-view处做修改 <router-view v-slot="{ Component }"> <keep-alive :include="cachedRoutes"> <component :is="Component" :key="$route.fullPath" /> </keep-alive> </router-view>cachedRoutes:为需要缓存界面路由name,可以根据使用情况设置,我这里写到了pinia中export const settingStore = defineStore("setting", { state: () => { return { cachedRoutes: Array<string>(), // 缓存的路由名称列表 }; }, getters: { getCachedRoutes(): string[] { return this.cachedRoutes; }, }, actions: { addRouteToCache(routeName: string) { if (!this.cachedRoutes.includes(routeName)) { this.cachedRoutes.push(routeName); } }, removeRouteFromCache(routeName: string) { const index = this.cachedRoutes.indexOf(routeName); if (index !== -1) { this.cachedRoutes.splice(index, 1); } }, }, });设置路由路由定义在需要缓存的界面路由mate中添加keepAlive: true { path: "/test/pageA", name: "pageA", meta: { title: "界面A", keepAlive: true }, component: () => import( "@/views/test/pageA/index.vue" as string ), }设置路由守卫,通过路由守卫向cachedRoutes 中添加需要缓存页面nameconst setRouteCache = (event: any) => { if (event.state) { const { name, meta } = currentRoute as any; if (meta.keepAlive) settingStore().removeRouteFromCache(name); } }; // 监听浏览器后退事件 window.addEventListener("popstate", setRouteCache); router.beforeEach(async (to: any, _from: any, next) => { // 设置浏览器标题 document.title = to.meta.title; window.history.state.action = to.name; currentRoute = _from; if (to.matched) { to.matched.forEach((record: any) => { if (record.name && record.components?.default) { const component = record.components.default; if (typeof component === "function") { // 处理异步组件 component().then((resolved: any) => { if (!resolved.default.name) { resolved.default.name = record.name; } }); } else if (!component.name) { // 处理普通组件 component.name = record.name; } } }); } if (to.meta.keepAlive) { const settingSate = settingStore(); settingSate.addRouteToCache(to.name); } next(); });其中下面这部分代码是设置页面name和路由的name绑定如果一致的可以去除 if (to.matched) { to.matched.forEach((record: any) => { if (record.name && record.components?.default) { const component = record.components.default; if (typeof component === "function") { // 处理异步组件 component().then((resolved: any) => { if (!resolved.default.name) { resolved.default.name = record.name; } }); } else if (!component.name) { // 处理普通组件 component.name = record.name; } } }); }
2024年11月22日
538 阅读
0 评论
0 点赞
2024-09-05
NextCloud更新404解决办法
前引最近两个版本的NextCloud更新时更新器出现404导致无法更新之前的版本都正常解决办法:使用命令手动更新通过手动运行更新命令,更新nextcloud版本在nextcloud根目录中运行命令:sudo -u www-data php updater/updater.phar基本流程和在有界面中是一样在更新过程中避免用户访问造成错误,可以启动维护模式sudo -u www-data php occ maintenance:mode --on关闭维护模式sudo -u www-data php occ maintenance:mode --off下载失败解决办法由于国内网络等原因,可能会出现更新下载失败可以在本地将新的 nextcloud 下载后上传到服务器中,替换掉data/updater-*/downloads/(nextcloud安装目录)的文件,同时修改data/updater-*/下的文件 .step替换文件中 start 为 stop{"state":"stop","step":4}再重新运行更新命令即可
2024年09月05日
657 阅读
0 评论
0 点赞
2024-07-14
为你的Typecho博客添加一个访问统计
前引在之前的静态Hexo 中借助的是第三方的统计平台,现在转到动态博客下,有了自己的数据库就没有必要再使用第三方的统计;于是就有了typecho访问统计插件TeohVistgithub地址:{% link github,TeohVisit,https://github.com/mstzf/TeohVisit.git %}插件实现的功能非常简单,就只是记录了访问数据,和在需要的界面提供数据安装将代码克隆到typecho插件目录,在管理后台找到 TeohVisit 之间开启使用即可git clone https://github.com/mstzf/TeohVisit.git使用具体使用需要修改主题源码,或者自定义独立界面模板插件提供了两种读取数据的方法getStat:返回所需要的单个值,具体值为:today,yesterday,month,totalgetAllStats:返回全部数据示例:if (TeohVisit_Plugin::isPluginEnabled()) { $stats = TeohVisit_Plugin::getAllStats(); $data = [ 'today_unique_visitors' => $stats['today']['unique_visitors'], 'today_views' => $stats['today']['views'], 'yesterday_unique_visitors' => $stats['yesterday']['unique_visitors'], 'yesterday_views' => $stats['yesterday']['views'], 'month_total_views' => $stats['month']['total_views'], 'total_total_views' => $stats['total']['total_views'] ]; }
2024年07月14日
814 阅读
0 评论
0 点赞
2024-05-12
TeoTag:在typecho中使用和butterfly一样的外挂标签
{% label 声明: red %} 绝大部分的样式都是hexo butterfly的原生样式,本人只是将功能在typecho中做了相应的移植。{% link Butterfly,Butterfly,https://butterfly.js.org/ %}我只是站在了巨人的肩膀上为什么会有TeoTag在此之前,博客使用了Hexo框架和Butterfly主题,文章内有很多样式都使用了Butterfly主题的写作语法;这两天将博客迁移到了typecho下,导致文章的很多非MarkDown格式内容都没法和原来一样正常显示,重新修改起来也比较麻烦,就想着把之前在Butterfly下的格式全部般过来,便有了TeoTag这个插件。{% link TeoTag,github,https://github.com/mstzf/TeoTags %}现有功能NoteTabslabeltimelinelinkhideToggle语法和渲染结果和Butterfly一样的用法 ButterflyNote{% note simple %} 默认 提示块标签 {% endnote %} {% note default simple %} default 提示块标签 {% endnote %} {% note primary simple %} primary 提示块标签 {% endnote %} {% note success simple %} success 提示块标签 {% endnote %} {% note info simple %} info 提示块标签 {% endnote %} {% note warning simple %} warning 提示块标签 {% endnote %} {% note danger simple %} danger 提示块标签 {% endnote %} {% note simple %}默认 提示块标签{% endnote %}{% note default simple %}default 提示块标签{% endnote %}{% note primary simple %}primary 提示块标签{% endnote %}{% note success simple %}success 提示块标签{% endnote %}{% note info simple %}info 提示块标签{% endnote %}{% note warning simple %}warning 提示块标签{% endnote %}{% note danger simple %}danger 提示块标签{% endnote %}Tabs{% tabs test1 %} <!-- tab --> **This is Tab 1.** <!-- endtab --> <!-- tab --> **This is Tab 2.** <!-- endtab --> <!-- tab --> **This is Tab 3.** <!-- endtab --> {% endtabs %}{% tabs test1 %}This is Tab 1.This is Tab 2.This is Tab 3.{% endtabs %}{% tabs test2, 3 %} <!-- tab --> **This is Tab 1.** <!-- endtab --> <!-- tab --> **This is Tab 2.** <!-- endtab --> <!-- tab --> **This is Tab 3.** <!-- endtab --> {% endtabs %}{% tabs test2, 3 %}This is Tab 1.This is Tab 2.This is Tab 3.{% endtabs %}{% tabs test3, -1 %} <!-- tab --> **This is Tab 1.** <!-- endtab --> <!-- tab --> **This is Tab 2.** <!-- endtab --> <!-- tab --> **This is Tab 3.** <!-- endtab --> {% endtabs %}{% tabs test3, -1 %}This is Tab 1.This is Tab 2.This is Tab 3.{% endtabs %}{% tabs test4 %} <!-- tab 第一个Tab --> **tab名字为第一个Tab** <!-- endtab --> <!-- tab @fab fa-apple-pay --> **只有图标 没有Tab名字** <!-- endtab --> <!-- tab 炸弹@fas fa-bomb --> **名字+icon** <!-- endtab --> {% endtabs %}{% tabs test4 %}tab名字为第一个Tab只有图标 没有Tab名字名字+icon{% endtabs %}label臣亮言:{% label 先帝 %}创业未半,而{% label 中道崩殂 blue %}。今天下三分,{% label 益州疲敝 pink %},此诚{% label 危急存亡之秋 red %}也!然侍衞之臣,不懈于内;{% label 忠志之士 purple %},忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气;不宜妄自菲薄,引喻失义,以塞忠谏之路也。 宫中、府中,俱为一体;陟罚臧否,不宜异同。若有{% label 作奸 orange %}、{% label 犯科 green %},及为忠善者,宜付有司,论其刑赏,以昭陛下平明之治;不宜偏私,使内外异法也。臣亮言:{% label 先帝 %}创业未半,而{% label 中道崩殂 blue %}。今天下三分,{% label 益州疲敝 pink %},此诚{% label 危急存亡之秋 red %}也!然侍衞之臣,不懈于内;{% label 忠志之士 purple %},忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气;不宜妄自菲薄,引喻失义,以塞忠谏之路也。宫中、府中,俱为一体;陟罚臧否,不宜异同。若有{% label 作奸 orange %}、{% label 犯科 green %},及为忠善者,宜付有司,论其刑赏,以昭陛下平明之治;不宜偏私,使内外异法也。timeline{% timeline 2022 %} <!-- timeline 01-02 --> 这是测试页面 <!-- endtimeline --> {% endtimeline %}{% timeline 2022 %}这是测试页面{% endtimeline %}{% timeline 2022,pink %} <!-- timeline 01-02 --> 这是测试页面 <!-- endtimeline --> {% endtimeline %}{% timeline 2022,pink %}这是测试页面{% endtimeline %}颜色可取: blue pink red purple orange greenlink这部分使用的是 (张洪Heo - 分享设计与科技生活 (zhheo.com)) 的样式{% link 获取网站的Favicon图标并显示在你的网页上,owen0o0,https://github.com/owen0o0/getFavicon %}{% link 获取网站的Favicon图标并显示在你的网页上,owen0o0,https://github.com/owen0o0/getFavicon %}{% link TeohZY,TeohZY,https://blog.teohzy.com %}{% link TeohZY,TeohZY,https://blog.teohzy.com %}hideToggle{% hideToggle 标题 %} 内容1 内容2 内容3 {% endhideToggle %}{% hideToggle 标题 %}内容1内容2内容3{% endhideToggle %}
2024年05月12日
823 阅读
0 评论
0 点赞
2023-12-26
堆叠轮播图(color ui原生小程序代码优化)
{% note info simple %}界面内容并非本人原创,只是适配了原生小程序代码{% endnote %}最近找了一些小程序的组件库,发现了Color UI界面和色彩搭配都比较符合我的需求,但是在进一步了解的时候发现这个项目已经停更了很长时间,有一部分功能已经无法正常使用。感兴趣的可以到作者仓库看看{% link coloruicss,github,https://github.com/weilanwl/coloruicss?tab=readme-ov-file %}项目中的堆叠轮播图挺好看,但是没有原生小程序代码,故此进行了简单的适配这里封装成了组件,组件属性根据自己需求修改tower-swiper.json{ "component": true, "usingComponents": {} }tower-swiper.wxml<view> <view class="tower-swiper" bindtouchmove="TowerMove" bindtouchstart="TowerStart" bindtouchend="TowerEnd"> <view class="tower-item {{item.zIndex==1?'none':''}}" wx:for="{{swiperList}}" wx:key="index" style="transform: scale(calc(0.5 + {{item.zIndex}} / 10));--index: {{item.zIndex}};margin-left: calc({{item.mLeft}} * 100rpx - 150rpx); z-index: {{item.zIndex}};"> <view class="swiper-item"> <image src="{{item.url}}" mode="aspectFill" wx:if="{{item.type=='image'}}"></image> <video src="{{item.url}}" autoplay loop muted data-show-play-btn="false" objectFit="cover" wx:if="{{item.type == 'video'}}"></video> </view> </view> </view> </view>tower-swiper.wxss.tower-swiper { height: 420rpx; position: relative; max-width: 750rpx; overflow: hidden; } .tower-swiper .tower-item { position: absolute; width: 300rpx; height: 380rpx; top: 0; bottom: 0; left: 50%; margin: auto; transition: all 0.2s ease-in 0s; opacity: 1; } .tower-swiper .tower-item .none { opacity: 0; } .tower-swiper .tower-item .swiper-item { width: 100%; height: 100%; border-radius: 6rpx; overflow: hidden; }tower-swiper.jsComponent({ /** * 组件的属性列表 */ properties: { swiperList:{ type:Array, value:[{ id: 0, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big84000.jpg' }, { id: 1, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big37006.jpg', }, { id: 2, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big39000.jpg' }, { id: 3, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big10001.jpg' }, { id: 4, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big25011.jpg' }, { id: 5, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big21016.jpg' }, { id: 6, type: 'image', url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big99008.jpg' }] }, towerStart:{ type:Number, value:0 } }, /** * 组件的初始数据 */ data: { timer:null, towerStart: 0, direction: 'left' }, lifetimes:{ attached(){ this.TowerSwiper(); this.direction = 'left'; this.setData({ direction: "left" }) this.swiperOn() } }, /** * 组件的方法列表 */ methods: { swiperOn(){ const _this = this let timer = this.data.timer if(!timer){ timer = setInterval(()=>{ _this.TowerEnd() },1000) this.setData({ timer }) } }, // 初始化towerSwiper TowerSwiper() { let list = this.data.swiperList; for (let i = 0; i < list.length; i++) { list[i].zIndex = parseInt(list.length / 2) + 1 - Math.abs(i - parseInt(list.length / 2)) list[i].mLeft = i - parseInt(list.length / 2) } this.setData({ swiperList: list }) }, // towerSwiper触摸开始 TowerStart(e) { const pageWidth = wx.getSystemInfoSync().windowWidth this.setData({ towerStart: e.touches[0].pageX, direction: e.touches[0].pageX < pageWidth/2 ? 'right':'left' }) }, // towerSwiper计算方向 TowerMove(e) { this.setData({ direction: e.touches[0].pageX - this.data.towerStart > 0 ? 'right' : 'left' }) }, // towerSwiper计算滚动 TowerEnd() { let direction = this.data.direction; let list = this.data.swiperList; if (direction == 'right') { let mLeft = list[0].mLeft; let zIndex = list[0].zIndex; for (let i = 1; i < this.data.swiperList.length; i++) { list[i - 1].mLeft = list[i].mLeft list[i - 1].zIndex = list[i].zIndex } list[list.length - 1].mLeft = mLeft list[list.length - 1].zIndex = zIndex } else { let mLeft = list[list.length - 1].mLeft; let zIndex = list[list.length - 1].zIndex; for (let i = list.length - 1; i > 0; i--) { list[i].mLeft = list[i - 1].mLeft list[i].zIndex = list[i - 1].zIndex } list[0].mLeft = mLeft; list[0].zIndex = zIndex; } this.setData({ direction, swiperList: list }) }, } })
2023年12月26日
450 阅读
0 评论
0 点赞
2023-11-18
使用MySql触发器简化各表数据操作
触发器基本语法生成一个触发器CREATE TRIGGER 触发器名 触发事件(BEFORE|AFTER INSERT|UPDATE|DELETE) ON 表名 FOR EACH ROW 触发器激活后需要执行的语句一些注意事项同一个数据库中不能创建同名触发器在同一张表中不能出现触发条件相同的触发器使用NEW和OLD来获取数据变化前后的记录值如果激活后只有一条操作,可以直接写,如果需要复杂操作则需要使用BEGIN...END;语句包围查看触发器SHOW TRIGGERS ;删除触发器DROP TRIGGER 触发器名; 修改触发器将已有触发器删除后再重新创建😂一个简单的触发器示例CREATE TRIGGER update_userinfo_trigger AFTER UPDATE ON user FOR EACH ROW BEGIN IF NEW.user_name <> OLD.user_name THEN UPDATE task_my SET user_name = NEW.user_name WHERE user_id = NEW.id; UPDATE table1 SET user_name = NEW.user_name WHERE user_id = NEW.id; UPDATE table2 SET user_name = NEW.user_name WHERE user_id = NEW.id; END IF; END;该触发器实现了,在更新user表中的name时,可以同时联动着将其他表中的name也更新掉,实现用户数据的统一
2023年11月18日
403 阅读
0 评论
0 点赞
2023-10-03
CSS实现水波纹扩散效果
主要CSSanimationtransform: scale()opacitynth-child()效果展示代码<div> <style> .ripple { width: 200px; height: 200px; position: absolute; top: calc(50% - 100px); left: calc(50% - 100px); border-radius: 50%; background-color: blueviolet; } /* 根据需求自定义 */ .content{ position: absolute; z-index: 99; /* 与.ripple的top和left相同 */ top: calc(50% - 100px); left: calc(50% - 100px); width: 200px; height: 200px; border-radius: 50%; background-color: rgb(42, 42, 180); font-size: 20px; font-weight: bold; color: #FFF; text-align: center; line-height: 200px; } .ripple:nth-child(2){ animation: wave 1s linear infinite; } .ripple:nth-child(3){ animation: wave 2s linear infinite; } .ripple:nth-child(4){ animation: wave 3s linear infinite; } .ripple:nth-child(5){ animation: wave 4s linear infinite; } @keyframes wave { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(1.5); } } </style> <div class="box"> <div class="content">内容</div> <div class="ripple"></div> <div class="ripple"></div> <div class="ripple"></div> <div class="ripple"></div> <div class="ripple"></div> </div> </div>实现的逻辑就是通过animation动画重复将这些元素放大1.5倍,同时将元素变为完全透明,从而达到波纹扩散的效果
2023年10月03日
423 阅读
1 评论
0 点赞
2023-08-06
树莓派访客抓拍视频版
前引由于在对移动的人体进行拍照的效果并不好,所以对抓拍图片版进行了升级,通过人体红外感应器在来访人员进入房间后录制视频,视频能比较好的看清来访人员起到看家的作用。拍照版{% link 树莓派64位系统实现对访客抓拍,Mstzf,https://mstzf.cn/posts/hc-rsAndcamera/index.html %}代码import RPi.GPIO as GPIO ##引入GPIO模块 import time from picamera2 import Picamera2, Preview from picamera2.encoders import H264Encoder from picamera2.outputs import FfmpegOutput def video(): now = time.strftime("%Y%m%d%H%M%S",time.localtime(time.time())) file_name="/Disk/MyCloud/Safe/"+now+".mp4" picam2 = Picamera2() video_config = picam2.create_video_configuration() picam2.configure(video_config) encoder = H264Encoder(10000000) output = FfmpegOutput(file_name) picam2.start_recording(encoder, output) time.sleep(5) picam2.stop_recording() picam2.close() HC_Pin = 18 GPIO.setmode(GPIO.BCM) GPIO.setup(HC_Pin, GPIO.IN) while True: if(GPIO.input(HC_Pin)): now = time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time())) f = open('/home/zh/code/.log','a',encoding='utf-8') try: video() except: str=now+' 相机调用失败\n' f.writelines(str) finally: str=now+" 有人来访\n" f.writelines(str) f.close() time.sleep(1)
2023年08月06日
497 阅读
0 评论
0 点赞
1
2