首页
壁纸
直播
留言
关于
友链
统计
Search
1
tampermonkey油猴和谷歌访问助手的安装---破解谷歌访问助手
13,581 阅读
2
安装postcss-px-to-viewport,将px单位转换为视口单位的 (vw, vh, vmin, vmax) 的 PostCSS 插件(有更新postcss弃用,附带vite.config.ts文件)
3,172 阅读
3
编译asar文件与electron反编译
3,117 阅读
4
websocket封装带心跳和重连机制(vue3+ts+vite)
2,737 阅读
5
js一些小功能(持续更新)
2,439 阅读
大前端
JavaScript
CSS
HTML
框架
Vue
electron
element-ui/plus
小程序
微信小程序
uni-app
服务端
Node.js
nginx
PHP
MySQL
工具
杂记
登录
Search
标签搜索
Vue3
Vue
Axios
微信小程序
Javascript
Vuex
js
请求
request
前端
tampermonkey
Google
助手
脚本
小程序云开发
Bootstrap
壁纸
鼠标事件
跨域
css
大祥子i
累计撰写
55
篇文章
累计收到
128
条评论
首页
栏目
大前端
JavaScript
CSS
HTML
框架
Vue
electron
element-ui/plus
小程序
微信小程序
uni-app
服务端
Node.js
nginx
PHP
MySQL
工具
杂记
页面
壁纸
直播
留言
关于
友链
统计
搜索到
55
篇与
大祥子
的结果
2022-08-18
websocket封装带心跳和重连机制(vue3+ts+vite)
import { mitts } from "./tool"; /* * @Author: lzx * @Date: 2022-05-25 15:42:37 * @LastEditors: lzx * @LastEditTime: 2022-08-18 15:01:38 * @Description: Fuck Bug * @FilePath: \talk_pc\src\utils\socket.ts */ let socketUrl: any = ""; // socket地址 let websocket: any = null; // websocket 实例 let heartTime: any = null; // 心跳定时器实例 let socketHeart: number = 0; // 心跳次数 let HeartTimeOut: number = 3000; // 心跳超时时间 let socketError: number = 0; // 错误次数 // 初始化socket const initWebSocket = (url: any) => { socketUrl = url; // 初始化 websocket websocket = new WebSocket(url); websocketonopen(); websocketonmessage(); sendSocketHeart() }; // socket 连接成功 const websocketonopen = () => { websocket.onopen = function (e: any) { console.log("连接 websocket 成功", e); resetHeart(); }; }; // socket 连接失败 const websocketonerror = () => { websocket.onerror = function (e: any) { console.log("连接 websocket 失败", e); }; }; // socket 断开链接 const websocketclose = () => { websocket.onclose = function (e: any) { console.log("断开连接", e); }; }; // socket 接收数据 const websocketonmessage = () => { websocket.onmessage = function (e: any) { let msg = JSON.parse(e.data); if (msg.type === 'heartbeat') { resetHeart() console.log("心跳"); } // console.log("收到socket消息", JSON.parse(e.data)); test(msg) // 测试数据 }; }; // socket 发送数据 const sendMsg = (data: any) => { websocket.send(data); }; // socket 错误 const websocketError = () => { websocket.onerror = function (e: any) { console.log("socket 错误", e); }; }; // socket 重置心跳 const resetHeart = () => { socketHeart = 0; socketError = 0; clearInterval(heartTime); sendSocketHeart(); }; // socket心跳发送 const sendSocketHeart = () => { heartTime = setInterval(() => { if (socketHeart <= 2) { console.log("心跳发送:", socketHeart); websocket.send( JSON.stringify({ content: "", requestId: "aa9872be-d5b9-478e-aba4-50527cd3ef32", type: "heartbeat" }) ); socketHeart = socketHeart + 1; } else { reconnect() } }, HeartTimeOut); }; // socket重连 const reconnect = () => { if (socketError <= 2) { clearInterval(heartTime); initWebSocket(socketUrl); socketError = socketError + 1; console.log("socket重连", socketError); } else { console.log("重试次数已用完的逻辑", socketError); clearInterval(heartTime); } }; // 测试收到消息传递 const test = (msg: any) => { switch (msg.type) { case 'heartbeat': //加入会议 mitts.emit('heartbeat', msg) break; } } export { initWebSocket, websocketonmessage, sendMsg, websocketonopen, websocketonerror, websocketclose, websocketError, resetHeart, sendSocketHeart, reconnect, };
2022年08月18日
2,737 阅读
2 评论
2 点赞
2022-07-08
PresentationAPI使用教程(Vue3&html)
W3C在2020年12月份出台了Presentation API规范,这个api接口允许用户自由控制投放在其他屏幕上,并和投放窗口通信,查看W3C规范。演示地址:投屏演示,详细demo(Vue3/HTML)见文章末尾{alert type="error"} 特别注意:需要注意必须为https环境{/alert} 1、创建一个PresentationRequest对象,该对象将包含我们要在辅助附加显示器上显示的地址。const presentationRequest = new PresentationRequest('receiver.html'); 2、做控制及监听事件/* * @Author: lzx * @Date: 2022-07-08 15:34:16 * @LastEditors: lzx * @LastEditTime: 2022-07-08 17:14:31 * @Description: Fuck Bug * @FilePath: \test\js\index.js */ // 创建个投屏对象 const presentationRequest = new PresentationRequest(['https://blog.fxnws.com']); // 投屏网址 // const presentationRequest = new PresentationRequest(['test.html']);//投屏页面 // Make this presentation the default one when using the "Cast" browser menu. navigator.presentation.defaultRequest = presentationRequest; let presentationConnection; //监视连接是否可用 presentationRequest.addEventListener('connectionavailable', function (event) { presentationConnection = event.connection; presentationConnection.addEventListener('close', function () { console.log('> Connection closed.'); }); presentationConnection.addEventListener('terminate', function () { console.log('> Connection terminated.'); }); presentationConnection.addEventListener('message', function (event) { console.log('> ' + event.data); }); }); //监视可用的显示器 presentationRequest.getAvailability() .then(availability => { console.log('Available presentation displays: ' + availability.value); availability.addEventListener('change', function () { console.log('> Available presentation displays: ' + availability.value); }); }) .catch(error => { console.log('Presentation availability not supported, ' + error.name + ': ' + error.message); }); // 开启投屏 function startProjectionScreen () { presentationRequest.start() .then(connection => { console.log('Connected to ' + connection.url + ', id: ' + connection.id); }) .catch(error => { console.log(error); }); } //发送消息 function sendMsg () { const message = '发送消息测试'; const lang = document.body.lang || 'en-US'; console.log('Sending "' + message + '"...'); presentationConnection.send(JSON.stringify({ message, lang })); } //关闭连接,关闭连接后无法再控制弹出窗口 function closeLink () { console.log('Closing connection...'); presentationConnection.close(); } //关闭连接后,换可以重新再次连接,这里需要指定id // presentationRequest.reconnect(presentationId); //关闭弹窗,结束连接调用 function endLink () { console.log('Terminating connection...'); presentationConnection.terminate(); } 3、连接端页面消息的展示(搬运的官方)/* * @Author: lzx * @Date: 2022-07-08 15:34:16 * @LastEditors: lzx * @LastEditTime: 2022-07-08 15:34:30 * @Description: Fuck Bug * @FilePath: \test\js\test.js */ let connectionIdx = 0; let messageIdx = 0; //如果有连接建立,则调用该函数 function addConnection (connection) { connection.connectionId = ++connectionIdx; addMessage('New connection #' + connectionIdx); connection.addEventListener('message', function (event) { messageIdx++; const data = JSON.parse(event.data); const logString = 'Message ' + messageIdx + ' from connection #' + connection.connectionId + ': ' + data.message; addMessage(logString, data.lang); maybeSetFruit(data.message); connection.send('Received message ' + messageIdx); }); connection.addEventListener('close', function (event) { addMessage('Connection #' + connection.connectionId + ' closed, reason = ' + event.reason + ', message = ' + event.message); }); }; const fruitEmoji = { 'grapes': '\u{1F347}', 'watermelon': '\u{1F349}', 'melon': '\u{1F348}', 'tangerine': '\u{1F34A}', 'lemon': '\u{1F34B}', 'banana': '\u{1F34C}', 'pineapple': '\u{1F34D}', 'green apple': '\u{1F35F}', 'apple': '\u{1F34E}', 'pear': '\u{1F350}', 'peach': '\u{1F351}', 'cherries': '\u{1F352}', 'strawberry': '\u{1F353}' }; function addMessage (content, language) { const listItem = document.createElement("li"); if (language) { listItem.lang = language; } listItem.textContent = content; document.querySelector("#message-list").appendChild(listItem); }; function maybeSetFruit (message) { const fruit = message.toLowerCase(); if (fruit in fruitEmoji) { document.querySelector('#main').textContent = fruitEmoji[fruit]; } }; //文档载入后,监听连接 document.addEventListener('DOMContentLoaded', function () { if (navigator.presentation.receiver) { navigator.presentation.receiver.connectionList.then(list => { list.connections.map(connection => addConnection(connection)); list.addEventListener('connectionavailable', function (event) { addConnection(event.connection); }); }); } }); 4、接收端页面构<!-- * @Author: lzx * @Date: 2022-07-08 15:34:05 * @LastEditors: lzx * @LastEditTime: 2022-07-08 15:35:13 * @Description: Fuck Bug * @FilePath: \test\test.html --> <!doctype html> <html> <head> <meta charset="utf-8"> <title>Demo Receiver</title> <style type="text/css"> html, body { height: 100%; margin: 0; font-family: sans-serif; background: radial-gradient(ellipse at center, #333333 0%, #000000 100%); color: #fff; } #main { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; font-size: 54px; } </style> <script type="text/javascript" src="引入3的代码块"></script> </head> <body> <div id="main">Hello World!</div> <ul id="message-list"> </ul> </body> </html> 5、vue3页面<template> <div class="container"> <button @click="startProjectionScreen">开启投屏</button> <button @click="sendMsg">发送消息</button> <!-- <button @click="closeLink">关闭连接</button> --> <button @click="endLink">结束调用</button> </div> </template> <script lang="ts"> // @ts-nocheck 不在当前文件中执行类型检查 import { toRefs, reactive, onMounted, watchEffect, onUnmounted } from 'vue' export default { props: {}, components: {}, setup () { const presentationRequest = new PresentationRequest(['https://blog.fxnws.com']); // 投屏网址 // const presentationRequest = new PresentationRequest(['test.html']); // 投屏本地页面 navigator.presentation.defaultRequest = presentationRequest; let presentationConnection; // 传参 const state = reactive({ }) const startProjectionScreen = () => { presentationRequest.start() .then(connection => { console.log('Connected to ' + connection.url + ', id: ' + connection.id); }) .catch(error => { console.log(error); }); } //发送消息 const sendMsg = () => { const message = '发送消息测试'; const lang = document.body.lang || 'en-US'; console.log('Sending "' + message + '"...'); presentationConnection.send(JSON.stringify({ message, lang })); } //关闭连接,关闭连接后无法再控制弹出窗口 const closeLink = () => { console.log('Closing connection...'); presentationConnection.close(); } //关闭连接后,换可以重新再次连接,这里需要指定id // presentationRequest.reconnect(presentationId); //关闭弹窗,结束连接调用 const endLink = () => { console.log('Terminating connection...'); presentationConnection.terminate(); } // 挂载 onMounted(() => { //监视连接是否可用 presentationRequest.addEventListener('connectionavailable', function (event) { presentationConnection = event.connection; presentationConnection.addEventListener('close', function () { console.log('> Connection closed.'); }); presentationConnection.addEventListener('terminate', function () { console.log('> Connection terminated.'); }); presentationConnection.addEventListener('message', function (event) { console.log('> ' + event.data); }); }); //监视可用的显示器 presentationRequest.getAvailability() .then(availability => { console.log('Available presentation displays: ' + availability.value); availability.addEventListener('change', function () { console.log('> Available presentation displays: ' + availability.value); }); }) .catch(error => { console.log('Presentation availability not supported, ' + error.name + ': ' + error.message); }); }) // 监听 watchEffect(() => { console.log('监听') }) // 页面卸载 onUnmounted(() => { console.log('页面卸载') }) return { ...toRefs(state), endLink, closeLink, sendMsg, startProjectionScreen } } } </script> <style scoped> </style> 6、详细demo附件下载隐藏内容,请前往内页查看详情2024年11月04日更新,看到评论区有部分朋友,遇到问题,我更新了相关Git完整Demo地址见下文1、vue3+ts+vite 报错 PresentationRequest 未定义 答:应该是ts未定义的报错,我当时做这个的时候,这个功能刚推出ts支持应该不完善,我也不想去定义相关的ts就直接使用// @ts-nocheck(这个指令用于告诉TypeScript编译器不在当前文件中执行类型检查)2、发现用ip访问不行,用127.0.0.1可以 答:直接用IP不行是因为没有https支持吧,我记得这个协议是需要https的支持的,具体要看下报错信息了,127.0.0.1是本机地址所以没事{alert type="warning"} 码云 {/alert}{alert type="warning"} Github {/alert}
2022年07月08日
798 阅读
43 评论
0 点赞
2022-06-21
vue3使用vue-clipboard3复制到剪切板
使用vue-clipboard3实现复制到剪切板,首先引入:npm install --save vue-clipboard3(详见)使用教程<template lang="html"> <div> <button @click="copyInfo('我是copy的内容')">点我复制</button> </div> </template> <script lang="ts"> import useClipboard from 'vue-clipboard3' export default { setup() { const { toClipboard } = useClipboard() const copyInfo = async (info) => { try { await toClipboard(info) ElMessage.success('复制成功') } catch (e) { ElMessage.warning('您的浏览器不支持复制:', e) } } return { copyInfo } } } </script>
2022年06月21日
1,363 阅读
0 评论
0 点赞
2022-06-15
编译asar文件与electron反编译
这两天遇到了个软件,想反编一下,整理各种不太会,最后想着会不会是electron开发的,就突发奇想把软件.exe改成zip打开看看,果不其然看到了electron图标,看了下是用electron-quick-start写的(electron-quick-start)目录结构如下:打开resources目录可以看到app.asar(这个文件就是项目源码的归档文件,asar是一种归档格式)既然找到了app.asar,那就把它解压出来看看吧,具体操作如下: 1、npm install -g asar全局安装asar插件 2、使用asar命令解压asar extract app.asar(源文件路径) ./(解压路径) 3、解压后的样式,可以看到解压出来了个app文件夹,里面就是代码了,可以对着代码为所欲为了,逆向出来的package.json文件里是没有devDependencies的,而electron是开发环境依赖,所以要自己手动添加npm add electron --save-dev,然后加个启动方式script:"start" : " electron . "需要执行npm install就执行下,然后执行npm start跑起来即可。(也可以创建一个空项目,将上面从app.asar中逆向处理的源代码拷贝过去) 4、改写下代码就可以重新打包了,打包前需要先为项目添加一些打包选项,编辑项目根目录下的package.json文件,为其添加build选项:"build": { "appId": "程序包名", // 程序包名 "copyright": "版权相关信息", // 版权相关信息 "productName": "项目名字", // 项目名字 "dmg": { "background": "背景图片的路径", // 背景图片的路径 "window": { // 启动后窗口的大小 "width": 500, "height": 300 } }, "win": { // 打包后的文件会有个图标,这个图标的路径,不指定的话默认的不好看 "icon": "图标" } // 注意:图标、appId什么的要对应好,然后在项目的根路径下执行打包命令 5、如何重新打包app.asar,执行asar pack ./(路径) app.asar(路径&名称)虽然能重新打包个app.asar文件,但是无法文件夹打包成为exe文件(我暂时未找到好方法)结语:如果能直接文件夹打包exe的话,直接替换app.asar文件就很nice了
2022年06月15日
3,117 阅读
0 评论
1 点赞
2022-06-14
Vue3使用高德地图
1、首先要在高德开发平台申请开发者账号申请key(文档)// npm引入 npm i @amap/amap-jsapi-loader --save cnpm i @amap/amap-jsapi-loader --save2、封装map.ts// 创建map.js /* * @Author: lzx * @Date: 2022-06-09 11:33:28 * @LastEditors: lzx * @LastEditTime: 2022-06-09 13:01:47 * @Description: Fuck Bug * @FilePath: \lzds\src\utils\map.ts */ import AMapLoader from '@amap/amap-jsapi-loader' // 使用加载器加载JSAPI,可以避免异步加载、重复加载等常见错误加载错误 /** * 高德地图 * @param {*} map */ const initMap = (map: any) => { AMapLoader.load({ key: "XXXXXXXXXXXXXXXXXXX", // 申请好的Web端开发者Key,首次调用 load 时必填 version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15 plugins: [ "AMap.Scale", //工具条,控制地图的缩放、平移等 "AMap.ToolBar", //比例尺,显示当前地图中心的比例尺 "AMap.Geolocation", //定位,提供了获取用户当前准确位置、所在城市的方法 "AMap.HawkEye", //鹰眼,显示缩略图 ], // 需要使用的的插件列表,如比例尺'AMap.Scale'等 }) .then((AMap) => { let map = new AMap.Map("map", {//设置地图容器id zoom: 10, //初始化地图层级 viewMode: "3D", //是否为3D地图模式 center: [116.397128, 39.916527], //初始化地图中心点位置 dragEnable: true, //禁止鼠标拖拽 scrollWheel: true, //鼠标滚轮放大缩小 doubleClickZoom: true, //双击放大缩小 keyboardEnable: true, //键盘控制放大缩小移动旋转 }); map.setDefaultCursor("pointer"); //使用CSS默认样式定义地图上的鼠标样式(default/pointer/move/crosshair) map.addControl(new AMap.Scale()); //异步同时加载多个插件 map.addControl(new AMap.ToolBar()); map.addControl(new AMap.Geolocation()); let HawkEye = new AMap.HawkEye({ position: "LT", //控件停靠位置(LT/RT/LB/RB) }); map.addControl(HawkEye); map.add( new AMap.Marker({ position: map.getCenter(), }) ); // map.add(marker); // 地图添加标记 AMapLoader.load({ // 可多次调用load plugins: ["AMap.MapType"], key: '', version: '' }) .then((AMap) => { map.addControl(new AMap.MapType()); }) .catch((e) => { console.error(e); }); // 显示地图层级与中心点信息 function logMapinfo() { let zoom = map.getZoom(); //获取当前地图级别 let center = map.getCenter(); //获取当前地图中心位置 } //绑定地图移动与缩放事件 map.on("moveend", logMapinfo); map.on("zoomend", logMapinfo); //为地图注册click事件获取鼠标点击出的经纬度坐标 map.on("click", function (e: any) { // 点击事件 }); let infoWindow = new AMap.InfoWindow({ //创建信息窗体 isCustom: false, //使用自定义窗体 anchor: "top-right", //信息窗体的三角所在位置 content: `<a href="#">XXX信息</a>`, //信息窗体的内容可以是任意html片段 offset: new AMap.Pixel(-10, -5), }); infoWindow.open(map, [116.397128, 39.916527]); //填写想要窗体信息指示的坐标 }) .catch((e) => { console.log(e); }); } export { initMap };3、引入封装的map.ts并且使用// 使用ref获取dom <div id="map" ref="map"></div> import { initMap } from '@/utils/map' const map = ref(null) initMap(map)
2022年06月14日
1,043 阅读
0 评论
26 点赞
1
2
...
11