个人案例
Backdropia
助您壁纸自由。
Backdropia扫码体验
Customizer
定制手机壳,3.9元起。
Customizer扫码体验
- 接入deepseek的合作协议获取渠道?
小程序介入了deepseek的接口,审核时说是需要添加深度合成==》AI问答类目; 根据相关提示,可以获取到算法备案的资料,但是与备案算法的合作协议该如何获取呢? (联系deepseek客服,但是一直没有回复,咨询类目审核客服,说是需要提供相关合同资料) [图片][图片]
2025-04-08 - 小程序奇技淫巧之 -- 日志能力
日志与反馈 前端开发在进行某个问题定位的时候,日志是很重要的。因为机器兼容性问题、环境问题等,我们常常无法复现用户的一些bug。而微信官方也提供了较完整的日志能力,我们一起来看一下。 用户反馈 小程序官方提供了用户反馈携带日志的能力,大概流程是: 开发中日志打印,使用日志管理器实例 LogManager。 用户在使用过程中,可以在小程序的 profile 页面(【右上角胶囊】-【关于xxxx】),点击【投诉与反馈】-【功能异常】(旧版本还需要勾选上传日志),则可以上传日志。 在小程序管理后台,【管理】-【反馈管理】,就可以查看上传的日志(还包括了很详细的用户和机型版本等信息)。 这个入口可能对于用户来说过于深入(是的,官方也发现这个问题了,所以后面有了实时日志),我们小程序也可以通过[代码]button[代码]组件,设置[代码]openType[代码]为[代码]feedback[代码],然后用户点击按钮就可以直接拉起意见反馈页面了。利用这个能力,我们可以监听用户截屏的操作,然后弹出浮层引导用户主动进行反馈。 [代码]<view class="dialog" wx:if="{{isFeedbackShow}}"> <view>是否遇到问题?</view> <button open-type="feedback">点击反馈</button> </view> wx.onUserCaptureScreen(() => { // 设置弹窗出现 this.setData({isFeedbackShow: true}) }); [代码] LogManager 关于小程序的 LogManager,大概是非常实用又特别低调的一个能力了。它的使用方式其实和 console 很相似,提供了 log、info、debug、warn 等日志方式。 [代码]const logger = wx.getLogManager() logger.log({str: 'hello world'}, 'basic log', 100, [1, 2, 3]) logger.info({str: 'hello world'}, 'info log', 100, [1, 2, 3]) logger.debug({str: 'hello world'}, 'debug log', 100, [1, 2, 3]) logger.warn({str: 'hello world'}, 'warn log', 100, [1, 2, 3]) [代码] 打印的日志,从管理后台下载下来之后,也是很好懂: [代码]2019-6-25 22:11:6 [log] wx.setStorageSync api invoke 2019-6-25 22:11:6 [log] wx.setStorageSync return 2019-6-25 22:11:6 [log] wx.setStorageSync api invoke 2019-6-25 22:11:6 [log] wx.setStorageSync return 2019-6-25 22:11:6 [log] [v1.1.0] request begin 2019-6-25 22:11:6 [log] wx.request api invoke with seq 0 2019-6-25 22:11:6 [log] wx.request success callback with msg request:ok with seq 0 2019-6-25 22:11:6 [log] [v1.1.0] request done 2019-6-25 22:11:7 [log] wx.navigateTo api invoke 2019-6-25 22:11:7 [log] page packquery/pages/index/index onHide have been invoked 2019-6-25 22:11:7 [log] page packquery/pages/logs/logs onLoad have been invoked 2019-6-25 22:11:7 [log] [v1.1.0] logs | onShow | | [] 2019-6-25 22:11:7 [log] wx.setStorageSync api invoke 2019-6-25 22:11:7 [log] wx.setStorageSync return 2019-6-25 22:11:7 [log] wx.reportMonitor api invoke 2019-6-25 22:11:7 [log] page packquery/pages/logs/logs onShow have been invoked 2019-6-25 22:11:7 [log] wx.navigateTo success callback with msg navigateTo:ok [代码] LogManager 最多保存 5M 的日志内容,超过5M后,旧的日志内容会被删除。基础库默认会把 App、Page 的生命周期函数和 wx 命名空间下的函数调用写入日志,基础库的日志帮助我们定位具体哪些地方出了问题。 实时日志 小程序的 LogManager 有一个很大的痛点,就是必须依赖用户上报,入口又是右上角胶囊-【关于xxxx】-【投诉与反馈】-【功能异常】这么长的路径,甚至用户的反馈过程也会经常丢失日志,导致无法查问题。 为帮助小程序开发者快捷地排查小程序漏洞、定位问题,微信推出了实时日志功能。从基础库 2.7.1 开始,开发者可通过提供的接口打印日志,日志汇聚并实时上报到小程序后台。 使用方式如下: 使用 wx.getRealtimeLogManager 在代码⾥⾯打⽇志。 可从小程序管理后台【开发】-【运维中心】-【实时日志】进入日志查询页面,查看开发者打印的日志信息。 开发者可通过设置时间、微信号/OpenID、页面链接、FilterMsg内容(基础库2.7.3及以上支持setFilterMsg)等筛选条件查询指定用户的日志信息: [图片] 由于后台资源限制,实时日志使用规则如下: 为了定位问题方便,日志是按页面划分的,某一个页面,在onShow到onHide(切换到其它页面、右上角圆点退到后台)之间打的日志,会聚合成一条日志上报,并且在小程序管理后台上可以根据页面路径搜索出该条日志。 每个小程序账号每天限制500万条日志,日志会保留7天,建议遇到问题及时定位。 一条日志的上限是5KB,最多包含200次打印日志函数调用(info、warn、error调用都算),所以要谨慎打日志,避免在循环里面调用打日志接口,避免直接重写console.log的方式打日志。 意见反馈里面的日志,可根据OpenID搜索日志。 setFilterMsg 可以设置过滤的 Msg。这个接口的目的是提供某个场景的过滤能力,例如[代码]setFilterMsg('scene1')[代码],则在 MP 上可输入 scene1 查询得到该条日志。比如上线过程中,某个监控有问题,可以根据 FilterMsg 过滤这个场景下的具体的用户日志。FilterMsg 仅支持大小写字母。如果需要添加多个关键字,建议使用 addFilterMsg 替代 setFilterMsg。 日志开发技巧 既然官方提供了 LogManager 和实时日志,我们当然是两个都要用啦。 log.js 我们将所有日志的能力都封装在一起,暴露一个通用的接口给调用方使用: [代码]// log.js const VERSION = "0.0.1"; // 业务代码版本号,用户灰度过程中观察问题 const canIUseLogManage = wx.canIUse("getLogManager"); const logger = canIUseLogManage ? wx.getLogManager({level: 0}) : null; var realtimeLogger = wx.getRealtimeLogManager ? wx.getRealtimeLogManager() : null; /** * @param {string} file 所在文件名 * @param {...any} arg 参数 */ export function DEBUG(file, ...args) { console.debug(file, " | ", ...args); if (canIUseLogManage) { logger!.debug(`[${VERSION}]`, file, " | ", ...args); } realtimeLogger && realtimeLogger.info(`[${VERSION}]`, file, " | ", ...args); } /** * * @param {string} file 所在文件名 * @param {...any} arg 参数 */ export function RUN(file, ...args) { console.log(file, " | ", ...args); if (canIUseLogManage) { logger!.log(`[${VERSION}]`, file, " | ", ...args); } realtimeLogger && realtimeLogger.info(`[${VERSION}]`, file, " | ", ...args); } /** * * @param {string} file 所在文件名 * @param {...any} arg 参数 */ export function ERROR(file, ...args) { console.error(file, " | ", ...args); if (canIUseLogManage) { logger!.warn(`[${VERSION}]`, file, " | ", ...args); } if (realtimeLogger) { realtimeLogger.error(`[${VERSION}]`, file, " | ", ...args); // 判断是否支持设置模糊搜索 // 错误的信息可记录到 FilterMsg,方便搜索定位 if (realtimeLogger.addFilterMsg) { try { realtimeLogger.addFilterMsg( `[${VERSION}] ${file} ${JSON.stringify(args)}` ); } catch (e) { realtimeLogger.addFilterMsg(`[${VERSION}] ${file}`); } } } } // 方便将页面名字自动打印 export function getLogger(fileName: string) { return { DEBUG: function(...args) { DEBUG(fileName, ...args); }, RUN: function(...args) { RUN(fileName, ...args); }, ERROR: function(...args) { ERROR(fileName, ...args); } }; } [代码] 通过这样的方式,我们在一个页面中使用日志的时候,可以这么使用: [代码]import { getLogger } from "./log"; const PAGE_MANE = "page_name"; const logger = getLogger(PAGE_MANE); [代码] autolog-behavior 现在有了日志组件,我们需要在足够多的地方记录日志,才能在问题出现的时候及时进行定位。一般来说,我们需要在每个方法在被调用的时候都打印一个日志,所以这里封装了一个 autolog-behavior 的方式,每个页面(需要是 Component 方式)中只需要引入这个 behavior,就可以在每个方法调用的时候,打印日志: [代码]// autolog-behavior.js import * as Log from "../utils/log"; /** * 本 Behavior 会在小程序 methods 中每个方法调用前添加一个 Log 说明 * 需要在 Component 的 data 属性中添加 PAGE_NAME,用于描述当前页面 */ export default Behavior({ definitionFilter(defFields) { // 获取定义的方法 Object.keys(defFields.methods || {}).forEach(methodName => { const originMethod = defFields.methods![methodName]; // 遍历更新每个方法 defFields.methods![methodName] = function(ev, ...args) { if (ev && ev.target && ev.currentTarget && ev.currentTarget.dataset) { // 如果是事件类型,则只需要记录 dataset 数据 Log.RUN(defFields.data.PAGE_NAME, `${methodName} invoke, event dataset = `, ev.currentTarget.dataset, "params = ", ...args); } else { // 其他情况下,则都记录日志 Log.RUN( defFields.data.PAGE_NAME, `${methodName} invoke, params = `, ev, ...args); } // 触发原有的方法 originMethod.call(this, ev, ...args); }; }); } }); [代码] 我们能看到,日志打印依赖了页面中定义了一个[代码]PAGE_NAME[代码]的 data 数据,所以我们在使用的时候可以这么处理: [代码]import { getLogger } from "../../utils/log"; import autologBehavior from "../../behaviors/autolog-behavior"; const PAGE_NAME = "page_name"; const logger = getLogger(PAGE_NAME); Component({ behaviors: [autologBehavior], data: { PAGE_NAME, // 其他数据 }, methods: { // 定义的方法会在调用的时候自动打印日志 } }); [代码] 页面如何使用 Behavior 看看官方文档:事实上,小程序的页面也可以视为自定义组件。因而,页面也可以使用[代码]Component[代码]构造器构造,拥有与普通组件一样的定义段与实例方法。但此时要求对应[代码]json[代码]文件中包含[代码]usingComponents[代码]定义段。 完整的项目可以参考wxapp-typescript-demo。 参考 LogManager 实时日志 Component构造器 behaviors 结束语 使用自定义组件的方式来写页面,有特别多好用的技巧,behavior 就是其中一个比较重要的能力,大家可以发挥自己的想象力来实现很多奇妙的功能。
2019-12-10 - 激励视频用玩家观看上限次数是多少?
IAA游戏,用户在游戏内看激励视频,多少间隔算作有效?每小时/每天观看激励视频上线数量是多少啊?麻烦有了解的告知一下,谢谢了
2023-07-24 - onShareAppMessage 的 imageUrl 可以是base64吗?
onShareAppMessage 的 imageUrl 可以是base64吗? 我这里分享出去的是空白图片
2022-03-25 - 巧用伪元素(:after/before)放大手机端点击区域
问题场景 我们在使用手机的过程中,是不是遇到过一些特别让你累的交互,就如手机端的按钮或图标老是点击不到,要多点击几次才能命中! 如何解决 手机的屏幕普遍比较小且分辨率高,这就导致设计的时候不能过大且要保持美观,严格按钮设计图尺寸开发后在手机端又过小导致点击事件无法触发。 那么怎么解决呢?不按照设计图切图?增加内边距撑大容器?这些方案都有或多或少不合理的地方,我有妙计可骚一把! 解决方案:after/before 通过设置点击元素的:after或:before伪元素大小来放大点击元素的点击区域 示例代码如下: [代码]/* 放大点击区域功能类 */ .nice-focus{ position:relative; } .nice-focus::after{ content:''; position:absolute; width:80px; height:80px; top:50%; left:50%; margin-top:-40px; margin-left:-40px; } /*返回按钮*/ .back{ width:12px; heigh:24px; background-image: url(/static/img/icon-back.png); background-size: 100% auto; } [代码] [代码]<!-- 页面使用 --> <div class="back nice-focus">返回</div> [代码] 总结 很多看似不能解决问题,换个角度就可以轻松解决!此方法也同样适用于小程序开发。
2019-10-28