关于小程序:如何实现H5和小程序之间相互跳转

嗨,各位小伙伴们,我是你们的好敌人咕噜铁蛋!明天,我要和大家分享一下对于如何实现H5和小程序之间互相跳转的话题。随着挪动互联网的倒退,H5网页和小程序曾经成为了咱们日常生活中不可或缺的一部分。那么,如何让它们之间可能互相跳转呢?接下来,就跟着我一起来理解一下吧!一、H5和小程序简介首先,让咱们简略介绍一下H5和小程序。H5即HTML5,是一种新一代的HTML规范,它提供了丰盛的多媒体性能和更弱小的图形能力,实用于各种挪动设施。而小程序是一种不须要装置即可应用的应用程序,用户能够间接关上应用,无需下载安装包,具备轻量化、便捷等特点。二、H5和小程序之间跳转的场景在理论开发中,咱们常常会遇到这样的场景:用户在浏览H5页面时,心愿可能便捷地跳转到对应的小程序进行操作,或者在小程序中点击某个按钮后跳转到相干的H5页面。这种跳转行为对于用户体验和性能完整性都十分重要。三、H5跳转到小程序首先,咱们来看一下如何实现H5页面跳转到小程序。在H5页面中,咱们能够通过调用微信提供的JSAPI,应用wx.miniProgram.navigateTo办法实现跳转到指定的小程序页面。具体的步骤能够分为以下几步: 引入微信JS-SDK库,在H5页面中引入微信提供的JS-SDK库,并进行初始化操作。调用JSAPI接口,在须要跳转的中央,通过调用wx.miniProgram.navigateTo办法传入小程序的AppID和门路,即可进行跳转操作。四、小程序跳转到H5接下来,咱们再来看一下小程序如何跳转到H5页面。在小程序中,咱们能够通过应用<web-view>组件实现在小程序内嵌H5页面,也能够通过调用wx.navigateTo办法实现在微信客户端中关上指定的H5页面。具体的步骤如下:应用<web-view>组件,在小程序中应用<web-view>标签,设置src属性为要跳转的H5页面地址,即可在小程序中嵌入H5页面。调用JSAPI接口,通过调用wx.navigateTo办法传入H5页面的URL,即可在微信客户端中关上对应的H5页面。五、注意事项和兼容性解决在理论跳转过程中,咱们还须要留神一些事项和解决兼容性的工作。例如,须要在H5页面中判断用户是否在微信环境中关上,以及在小程序中应用<web-view>组件时,须要思考H5页面的适配和交互成果等。通过以上的介绍,咱们理解了H5和小程序之间互相跳转的实现办法和注意事项。在理论开发中,咱们能够依据具体的业务需要和场景抉择适合的办法来实现跳转,并留神解决好兼容性和用户体验问题。心愿明天的分享可能对大家有所帮忙。如果你对H5和小程序跳转有更多的疑难或者想要深刻理解,欢送留言给我,咱们一起交换探讨吧!感激大家的浏览,咱们下期再见!

February 23, 2024 · 1 min · jiezi

关于小程序:中国信通院马飞小程序生态与标准建设规划

9 月 8 日,2023 外滩大会 聚焦「云端 AI:摸索新兴技术和倒退模式」主题的见解论坛在上海胜利举办。中国信息通信研究院云计算与大数据研究所云计算部主任 马飞 从政策和产业的宏观视角,为咱们带来了《小程序生态与规范建设布局》的主题分享。 马飞示意:“小程序产业倒退在资源、性能、经营等层面仍面临多方挑战,为此建设小程序规范体系和生态评估机制,对焦规范和标准,促成生态衰弱倒退。将来小程序会更加规范化,并联合智能化和大模型,加强服务体验。” 以下是演讲全文。 大家下午好,我是来自于中国信通院的马飞,很快乐受蚂蚁邀请参加会议,次要跟大家聊一下小程序的倒退。 从产业和国家的视角来看,寰球进入了数字化时代,包含“十四五”布局、党中央国务院文件,尤其去年二十大报告屡次提到了建设数字中国,应该说整个数字化倒退是当下的大趋势。 从政策角度,利用新技术做数字化转型,是建设数字中国十分重要的抓手,这是宏观政策方面在推动数字化的倒退。在这个过程中为什么独自提到小程序呢? 咱们看到这几年小程序倒退十分迅猛,从五年前有几十万个小程序到去年靠近 800 万个,应该说增长十分迅猛和迅速,年均复合增速近 30%。能够看到整个小程序在过来几年从互联网进入到挪动互联网、将来进入智能互联网当前,是一个应运而生、疾速倒退的过程。 从政策环境、产业环境来看,为什么小程序可能进入大视野、倒退这么快?后面能够看到,整个小程序特点有几个个性,方才主持人也强调了交互性,还有轻量级的部署,不像其余利用要去下载,它的体量比拟小,随时更新不须要装置等。 置信在座各位常常会用到小程序,不论是买票、吃饭、购物等,小程序曾经成为整个互联网时代下一个十分重要的基础设施存在。同时,咱们看到产业界也曾经造成了一些生态,不论是支付宝、蚂蚁还是腾讯、京东都造成了一种生态,日活度也十分多,有 8 亿多的量,整个生态曾经贯彻到生存方方面面了。 同时,小程序让老百姓各种办事更不便,不论是政务办事,政务推出了很多最多跑一次服务,还有购物、餐饮、理财、物流、交通、游览等。从整个价值作用来说,小程序与生存曾经紧密联系在一起了,也是整个挪动互联网新基建的基础设施存在。 咱们是来自于中国信通院的云计算部,咱们看到云计算也在撑持小程序的各个方面。一方面小程序在各个行业深刻倒退,尤其是在电商和金融畛域,走在最后面。包含医疗也在一直进行数字化,小程序正在广泛应用。另一方面,作为撑持小程序疾速倒退的一种形式,小程序云的概念也在一直进入大家的视线。 为什么十年前没有呈现小程序和小程序云呢? 如果理解云计算倒退特点的话,咱们晓得十年前的云计算更多在虚拟化层面,但随着过来五六年整个云原生畛域的倒退,通过容器、微服务、 Serverless 、DevOps 等理念把利用变得越来越“小”,所以整个云计算倒退也在背地对小程序的倒退做了很好的撑持,因为它更加灵便、更加便捷。云计算技术倒退到了肯定的阶段,催生了小程序云的倒退。 代码能够放到平台托管,能够做智能的营销,包含研发效力的晋升等,这也是随着云的精细化倒退、技术一直成熟,能很好撑持整个小程序云的倒退,进而带动小程序的倒退,而后去助力行业数字化转型,这是一脉相承的。 上面说一下小程序生态。小程序倒退这么快不仅仅有平台角色,也贯通了上、中、上游产业链。技术服务商提供了各种小程序的设计、开发环境,经营方像支付宝平台提供了一种根底平台,同时平台里积攒了数据帮忙小程序做更好的经营,包含提供了一些开发和测试接口,来帮忙小程序落地。同时,用户体验反馈能够造成一个闭环。 后面说的都是好的方面,咱们看到整个小程序倒退十分迅速,有各种各样的长处,同时在一些行业落地,造成了初步的生态。然而小程序在疾速倒退和利用的同时,也存在着一些问题或者须要晋升的中央: 1.资源层面。 大家应用小程序有周期性,对资源的利用水平变动是多态的,存在不确定性。如果没有对突发状况有很好的预判、做好相应的布局,有可能造成购票等零碎解体的状况。 2.性能层面 小程序体验的量化指标其实业内没有一个统一标准,所以从产业界角度认为小程序层面还不足一个对立的性能评估办法。比如说一些性能指标须要有一个统一标准和标准,来保障统一的用户体验。 3.经营层面 一方面整个小程序数量泛滥,另一方面在业内有很多不同的平台,平台多的益处是大家能够抉择不同的平台,然而同时也会带来统一性的问题。每个平台的政策、规定都是不一样的,进而造成了用户的体验感触不尽相同。 中国信通院有这样的责任和使命去推动产业的标准化,晋升整个产业倒退的品质。所以在这样一个背景下,信通院与蚂蚁等业内企业独特成立了“小程序生态推动方阵”,心愿把更多产业界相干上下游的各方角色汇集起来,整合各种优质资源,搭建交流平台。 通过技术钻研、规范、测试评估、供需对接等,建设一个生态组织,把多方拉齐,把衡量标准进行规范化,晋升整个行业的倒退速度。 中国信通院也与业内专家独特编写了一些规范。 首先是《小程序品质工程能力要求与评估办法》,依照整个小程序的生命周期,包含了开发测试品质阶段进行功能测试、稳固测试、性能测试、兼容性测试等,上架审核品质阶段的技术审查、平安审查、经营审查等,以及上线之后运维/经营阶段的巡检、告警、应急处理等。 以其中一个阶段举例,在开发测试阶段,涵盖了功能测试、性能测试、稳定性、兼容性、平安、能耗、压力测试等。进而以性能测试为例,性能对高流量流动场景的小程序来说,用户体验至关重要,这其中包含了资源筹备性能、页面切换、网络性能等测试类别。通过这本规范的编写和施行,心愿对于整个小程序包含开发、经营、应用等做一套“体检”,如果某项略微差一点,将来能够有晋升改良的中央,咱们心愿把整个行业程度能力进行标准化,有差别、有有余能够依据规范做晋升,这也是做规范的目标。 后面也提到了小程序倒退离不开生态,中国信通院围绕小程序生态正在建设评估机制。在可操作性、社区生态、经营标准上别离有不同维度的考量。 最初,展望未来小程序的倒退,分为以下方面: 第一,小程序走向规范化。 某个产业增长到肯定的阶段,从产业角度须要进行标准化、规范化,否则将限度这个产业的进一步倒退,所以标准化、规范化是必然要经验的阶段。 第二,小程序走向智能化。 云上的智能开发服务,将帮忙小程序倒退。当初支付宝、微信等小程序都在上云,背地有云的撑持,可能更好地实现智能化。 第三,小程序走向自主学习。 将来小程序与大模型、人工智能深度联合,利用大模型赋能用户体验晋升,实现更好的服务质量保障。 以上是我的分享,谢谢大家!

September 28, 2023 · 1 min · jiezi

关于小程序:小程序图片体验优化的思考总结

背景在开发小程序的时候,用户体验是一个重要的关注点。蹩脚的用户体验会让用户应用小程序的志愿大大降低,甚至不再应用。优化用户体验是一门简单的学识,波及到产品交互设计、程序性能等等各方面的工作,很难欲速不达,只能在各个场景下,对于不同的关注点,别离去采取对应措施进行优化,并且还要辅以对应的设计规范、防劣化措施等等,使得体验可能始终维持在设立的基线之上。明天想要分享的体验优化以我的项目中的图片为切入点,针对图片加载场景,优化用户在应用小程序时浏览图片相干的体验。 如何优化图片浏览体验的次要优化指标有两点: 让图片加载更快,可能疾速为用户提供内容,晋升加速度,进而进步转化率;在加载过程中给用户明确的反馈和预期,如加载时的动画、加载失败的提醒; 给用户带来焦虑的体验 达到以上指标,咱们能够从图片资源自身以及图片加载过程这两个角度去思考优化措施。 图片资源优化图片资源优化的目标是减小传输内容的大小,从而缩小图片下载耗时,进而放慢图片展现。扭转图片资源的体积有三大办法,次要波及压缩品质、图片资源的格局、图片分辨率。我应用了火山引擎的 veImageX 来解决图片,通过肯定配置之后,只须要批改 URL 里的参数,就能够动静批改图片的格局、品质等等参数,很不便,搜索引擎,搜寻关键词“火山引擎 ImageX”,能够找到他们的体验版本,不必注册就能用。 适合的图片品质咱们给用户提供的图片品质,应该与各种场景挂钩。比方,当咱们检测到用户处于弱网环境时、亦或者以后图片场景(比方列表预览)并不需要高质量品质图片时,能够给用户提供小体积而品质稍差的图片,升高图片传输的老本;当用户处于wifi环境、或者是须要预览高清大图时,提供高质量的图片以强化用户的看图体验。具体的图片加载品质应该有着各种各样的场景化策略。veImageX 反对在 URL 中传入品质参数值来管制下发的图片品质,转换了一张 lena 的 jpeg 格局图片来比照下成果。 压缩品质2550 758595100图片体积35KB49KB77KB116KB250KB583KB这几张图片别离应用了 25、50、75、85、95、100 的品质参数,体积也是随着品质参数的增大而收缩。咱们能够看到 25、50、75 这几张图片的品质差别还是相当显著的,高质量图片中的色块和噪点一样的货色显著缩小了,而品质 75 以上的几张图片,说实话肉眼看区别不太大,然而体积却收缩了不少。所以个别状况下应该抉择 80 左右的品质参数就差不多了。 更优的图片格式我放了张常见的 720*862 的图片转换了一下格局,下载下来比照文件大小。能够看到,古代图片格式(webp、avif、heic)的图片体积显著比 png、jpeg 这些格局要小不少。而且图片品质上,肉眼根本看不出差别。 压缩品质75 png(有损)jpegwebpavifheic 图片信息体积219KB102KB69KB32KB26KB与png相比--53%-68%-85%-88%解决的图片,分辨率不变的前提下最多比 png 格局图片缩小了 88% 的大小(heic 格局),并且肉眼看不出品质的显著差别。如果可能用上这些高压缩率的图片格式,必定可能节俭图片下载的网络耗时。 编解码性能除了关注图片的体积之外也依然须要关注不同图片格式在终端的性能,这里编码和解码都用开发机进行测试了,咱们找了几千张图片在服务端的测试后果,测试图片以分辨率 400x300、1200x700 为界,在三个区间内取雷同图片样本量。测试环境:开发机,8C16G,Intel(R) Xeon(R) Platinum 8260 CPU @ 2.40GHz 图片格式品质参数压缩比例解码耗时ms编码耗时msPSNRjpeg3030%11.015.138 5040%12.015.040 7560%12.016.246 90100%13.516.751webp3020%16.9170.139 5028%19.3179.241 7538%21.5190.242 9076%29.4221.947HEIC/BVC13010%58.913.938 5010%60.813.938 7522%70.913.842 9043%78.214.345AVIF307%60.61224.936 5018%65.41413.540 7524%67.31497.842 9044%76.41382.346所以从表格上来看,在解码性能上抉择:jpeg<webp<HEIC<AVIF从编码性能上抉择,在编码性能上抉择:HEIC>>jpeg >webp>AVIF,(图片加载应用云服务的状况下每次都是同步解决的,这个指标十分影响用户首次加载的耗时);最初在决策抉择上,咱们优选体积小、解码耗时和编码耗时尽可能短的格局。 自适应的图片分辨率 一张分辨率为 3648*2736 的壁纸,体积为 8M ...

September 26, 2023 · 2 min · jiezi

关于小程序:500道微信小程序创新创意毕业设计选题持续更新

大家好,我是程序员徐师兄,最近有很多同学征询,说毕业设计了,不晓得选怎么题目好,有哪些是想须要留神的。 明天,我整顿了一些微信小程序毕业设计的题目,能够参考一下,心愿对大家有所帮忙。原文地址 一、大体实现思路微信小程序,当初是十分热门的,基于微信生态开发的。当初很多计算机毕业的同学,都会抉择微信小程序作为毕业设计 小程序端通常都是展现数据给用户去看的,大多数状况下,这些数据不是写死的,而是前端申请服务器接口获取数据的。 博主介绍:✌程序员徐师兄、7年大厂程序员经验。全网粉丝30W+,Csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专一于Java技术畛域和毕业我的项目实战✌二、如何避坑?俗话说万事开头难,对于计算机小程序的毕设而言更是如此,选题适合会让你在毕业季轻松很多 1、本人选题的不要凭空进行设想,肯定要做到不能自觉选题,定题目就意味着当前要实全力以赴实现题目对应的性能(要在可控范畴内),要联合本身现实情况来抉择难度和本人所在学校现阶段合乎的。有些看似简略问题,理论不合乎现阶段,老本也会成倍增加,如果有选题/开题不明确的中央能够与我随时沟通,欢送打搅。 2、老师指定,尽量避开一些科研题目,除非是老师做好的,就是让你拿来用的,要联合本人理解档次,学习老本太高的间接和老师进行沟通。如果老师不能残缺的帮到本人,申请换题目。 3、 能够在网上或者 Github 先搜一下,看有没有相干的源码借鉴,做到成竹在胸 三、可借鉴题目参考个人简介:7 年大厂程序员经验,善于Java、微信小程序、Python、Android等,大家有这一块的问题能够一起交换!各类成品。 java、javaweb,ssh,ssm,springboot等等我的项目框架,源码丰盛,欢送征询。学习材料、程序开发、技术解答、代码解说、文档报告 第一局部题目技术栈基于微信小程序的网络公选课零碎小程序微信小程序基于微信小程序的在线点餐零碎与实现微信小程序基于微信小程序的校园餐饮服务零碎的钻研与实现微信小程序基于微信小程序的零食盒子与实现微信小程序基于垃圾分类微信小程序的钻研与实现微信小程序基于微信小程序的微信商城小程序微信小程序基于微信小程序的小区物管理系统与实现微信小程序基于面向文艺影视社群的微信小程序微信小程序基于微信小程序的校园信息管理系统-小程序微信小程序基于微信小程序的预约挂号零碎与实现微信小程序基于微信小程序的报名零碎小程序作微信小程序基于微信小程序的“校园帮”零碎微信小程序基于微信小程序的小程序挪动图书馆微信小程序基于微信小程序的校园跑腿生存服务平台微信小程序微信小程序的基于微信序的跑腿平台的钻研与实现微信小程序基于微信小程序的体育场地预订零碎的钻研与实现微信小程序基于微信小程序的实现电子书城阅读器微信小程序基于微信小程序的家庭理财管理系统微信小程序基于微信小程序的小程序论坛微信小程序基于微信小程序的美食社区小程序的钻研与实现微信小程序基于微信小程序的街舞交流平台微信小程序基于高校食堂点餐微信小程序钻研与微信小程序基于微信小程序的日常学习打卡零碎微信小程序基于微信小程序的育机构管理系统的钻研与实现微信小程序基于微信小程序的校园车辆管理系统与实现微信小程序基于微信小程序的在线电子书浏览零碎微信小程序基于微信小程序的学校便捷食堂小程序与开发微信小程序基于微信小程序的校园订餐零碎的与开发微信小程序基于微信小程序的停车位共享平台微信小程序基于微信小程序的校园易平台的钻研与实现微信小程序基于微信小程序的篮球部落小程序的钻研与实现微信小程序基于微信小程序的校园圈子小程序微信小程序基于微信小程序的师生交流平台小程序微信小程序微信小程序的基于微信的辅导机构治理小程序的钻研与实现微信小程序基于微信小程序的小学语文学习打卡小程序微信小程序基于微信小程序的微信休闲小游戏微信小程序基于微信小程序的考研小程序微信小程序基于微信小程序的微信商城小程序(毕业设计,包含源码,数据库,教程2)微信小程序基于微信小程序的我爱美食美餐的与开发微信小程序基于微信小程序的专利剖析android小程序微信小程序微信小程序的基于小程序的钢琴交流平台微信小程序微信小程序的基于微信的宠物寄养交流平台微信小程序基于微信小程序的零担物流智慧治理平台微信小程序基于微信小程序的校园失物招领零碎的钻研与实现微信小程序基于校园失物招领微信小程序微信小程序基于微信小程序的开发的古筝论坛微信小程序微信小程序的基于小程序的警务流动管理系统微信小程序基于微信小程序的护肤品商城的钻研与实现微信小程序基于微信小程序的智能举荐的电影举荐小程序微信小程序基于微信小程序的借书小程序微信小程序基于微信小程序的校园互助平台微信小程序基于校园代取快递微信小程序微信小程序基于微信小程序的集体记账小程序微信小程序基于微信小程序的预约挂号小程序微信小程序基于微信小程序的校招资讯平台的钻研与实现微信小程序基于微信小程序的社团治理的小程序微信小程序基于微信小程序的在线诗歌赏析零碎的钻研与实现微信小程序基于微信小程序的小程序乐器商城微信小程序基于微信小程序的校园帮扶小程序的钻研与实现微信小程序uniaapp微信小程序基于ssm微信小程序的出租车打车预约零碎的钻研与实现微信小程序基于“构造与算法”闯关答题微信小程序的钻研与实现微信小程序基于微信小程序的智能班务管理系统微信小程序基于微信小程序的企流动积分小程序微信小程序基于ssm微信小程序的公考上岸通公考学习通微信小程序基于居民小区疫情防控微信小程序的钻研与实现微信小程序基于ssm微信小程序的太极锤炼打卡零碎与实现微信小程序基于微信小程序的位置服务的图书馆座位预约管理系统微信小程序基于微信小程序的沁心茶叶商城小程序的钻研与实现微信小程序基于微信小程序的网络公选课零碎小程序微信小程序基于ssmuniapp的字智慧校园挪动端电子签到模块的钻研与实现微信小程序基于微信平台的动植物辨认小程序与实现微信小程序基于微信小程序的车位预约零碎的钻研与实现微信小程序第二局部题目技术栈基于微信小程序的灾情救助零碎设计与实现微信小程序基于加油站微信小程序的钻研与实现微信小程序基于微信小程序的育教幼教常识学习零碎微信小程序基于微信小程序的琴房管理系统的设计与实现微信小程序基于微信小程序的校园告诉小程序零碎的钻研与实现微信小程序基于快递柜管理系统微信小程序微信小程序基于微信小程的mhk在线学习小程序微信小程序基于微信小程序高速公路服务区充电桩在线预订零碎设计微信小程序微信小程序基于微信小程序的桃婚恋交友app微信小程序基于心理服务平台微信小程序的设计与实现微信小程序基于讲座预约零碎微信小程序微信小程序基于微信小程序的美甲店铺座位预约零碎nodejs微信小程序基于微信小程序的早茶预约零碎与实现微信小程序基于微信小程序的南通农商银行微银行零碎的钻研与实现微信小程序基于微信小程序的新乡学院自习室预约零碎微信小程序基于微信小程序的一起考研小程序微信小程序基于青少年心理健康科普平台微信小程序微信小程序基于微信小程序的中餐外卖零碎的钻研与实现nodejs微信小程序基于微信小程序乐旋乒乓球课程管理微信小程序的设计与实现微信小程序基于微信小程序的汉服租赁平台的钻研与实现微信小程序基于心理咨询服务微信小程序的钻研与实现微信小程序基于微信小程序的衰弱治理微信小程序基于微信小程序的学校心理咨询聊天室的设计与实现微信小程序基于微信小程的高校科研管理系统设计与实现小程序微信小程序基于加油站微信小程序的钻研与实现微信小程序基于微信小程序的游泳馆管理系统微信小程序基于微信小程序的面向企事单位的我的项目申报小程序微信小程序基于微信小程序的同城交易小程序微信小程序基于微信小程序的校园兼职零碎微信小程序基于微信小程序的党建工作小秘书微信小程序基于微信小程序的食堂线上预约点餐零碎微信小程序基于微信小程序的ssm的衰弱早晓得管理系统微信小程序基于微信小程序的医院核酸检测预约挂号微信小程序基于微信小程序的集体衰弱信息管理小程序微信小程序基于微信小程序的“最多跑一次”微信小程序基于微信小程序的微信点餐零碎微信小程序基于微信小程序的校园作反馈的家校分割微信小程序基于微信小程序的药店管理系统微信小程序基于微信小程序的书籍销售零碎微信小程序基于微信小程序的学生宿舍管理系统微信小程序基于微信小程序的新生报到零碎微信小程序基于微信小程序的小程序的企产品推广零碎微信小程序基于微信小程序的农产品自主供销小程序微信小程序基于微信小程序的django平台小区服务零碎微信小程序基于微信小程序的游乐园智慧向导小程序微信小程序基于微信小程序的springboot宿舍治理小程序微信小程序基于微信小程序的微信浏览小程序微信小程序基于微信小程序的驾校报名小程序微信小程序基于微信小程序的学生选课零碎微信小程序基于微信小程序的校园二手交易平台小程序微信小程序基于微信小程序的摄影比赛小程序微信小程序基于微信小程序的springboot 的点餐零碎微信小程序基于微信小程序的ssm的付费自习室零碎微信小程序基于微信小程序的医院预约挂号零碎小程序微信小程序基于微信小程序的高校餐厅食品留样管理系统微信小程序基于微信小程序的校园订餐小程序微信小程序基于微信小程序的ssm研常识题小程序微信小程序基于微信小程序的校园失物招领微信小程序基于微信小程序的疫情核酸预约小程序微信小程序基于微信小程序的电影院票务零碎微信小程序基于微信小程序的新冠疫苗预约小程序微信小程序基于微信小程序的英语学习激励零碎微信小程序基于微信小程序的童心党史小程序微信小程序基于微信小程序的学习材料销售平台微信小程序基于微信小程序的鲜花销售微信小程序基于微信小程序的ssm的短视频零碎微信小程序基于微信小程序的捷邻小程序微信小程序基于微信小程序的足浴城生产零碎微信小程序基于微信小程序的高校管理系统小程序微信小程序基于微信小程序的springboot的学生宿舍管理系统微信小程序基于微信小程序的坛小程序微信小程序基于微信小程序的自习室预约零碎微信小程序基于微信小程序的青少年素质育培训零碎微信小程序基于微信小程序的电影交流平台微信小程序基于微信小程序的在线办公小程序微信小程序基于微信小程序的学生购电小程序微信小程序基于微信小程序的租房平台微信小程序基于微信小程序的自助购药小程序微信小程序基于微信小程序的ssm的高校课堂学管理系统微信小程序基于微信小程序的智能停车场管理系统微信小程序基于微信小程序的食堂窗口自助点餐零碎微信小程序基于微信小程序的校园商铺零碎微信小程序基于微信小程序的美容院管理系统微信小程序基于微信小程序的学辅导微信小程序基于微信小程序的党员之家服务零碎小程序微信小程序基于微信小程序的新生自助报到零碎微信小程序基于微信小程序的驾校预约管理系统微信小程序基于微信小程序的图书馆座位再利用零碎微信小程序第三局部题目技术栈校园失物招领小程序(java)微信小程序微信小程序微信小程序汉堡点餐零碎(java)微信小程序微信小程序食疗微信小程序的设计与实现(java)微信小程序小程序 - 快捷方式.lnk微信小程序社区户口治理的零碎(java)微信小程序微信小程序在线浏览零碎微信小程序(java)微信小程序微信小程序微信小程序开发的投票评比零碎(java)微信小程序餐饮外卖零碎(java)cx1微信小程序小程序新能源汽车信息安全服务平台(java)微信小程序精准扶贫数据收集小程序平台(java)微信小程序学生信息管理平台(java)微信小程序惠农小店零碎设计与开发(java)微信小程序二手物品交易小程序(java)微信小程序微信小程序查寝打卡微信小程序(java)微信小程序老年人衰弱治理平台(java)微信小程序电影票订票小程序软件(java)微信小程序微信大学校园二手教材与书籍拍卖零碎(java)微信小程序流动报名管理系统(java)微信小程序微信小程序基于微信小程序的图书馆预约零碎(java)微信小程序互动打卡小程序(java)wlw微信小程序医院预约挂号小程序(java)微信小程序微信小程序智慧流调微信小程序(java)微信小程序微信小程序基于微信小程序的校园闲置发售平台(java)微信小程序微信平台的4s店管理系统(java)微信小程序小程序理发店预约零碎(java)微信小程序微信小程序基于微信小程序炸鸡外卖app(java)微信小程序悬赏信息公布零碎(java)微信小程序软件学院会议室管理系统(java)微信小程序基于小程序的名片管理系统(java)微信小程序校园二手物品交易系统(ssm)微信小程序消防常识每天学(java)微信小程序牙齿衰弱科普小程序(java)微信小程序局部效果图 源码征询原文地址

September 22, 2023 · 1 min · jiezi

关于小程序:uniapp小程序隐私协议弹窗组件

为标准开发者的用户集体信息处理行为,保障用户的合法权益,自2023年9月15日起,对于波及解决用户个人信息的小程序开发者,微信要求,仅当开发者被动向平台同步用户已浏览并批准了小程序的隐衷爱护指引等信息处理规定后,方可调用微信提供的隐衷接口。 官网文档用户隐衷爱护 成果展现原插件地址 uniapp的操作指引1、批改文件mainfest新增参数 "__usePrivacyCheck__" : true, 如图 2、新建组件新建目录文件为 components/privacy-popup/privacy-popup.vue <template> <view v-if="showPrivacy" :class="privacyClass"> <view :class="contentClass"> <view class="title">用户隐衷爱护指引</view> <view class="des"> 感谢您抉择应用咱们的小程序,咱们非常重视您的集体信息安全和隐衷爱护。应用咱们的产品前,请您仔细阅读“ <text class="link" @tap="openPrivacyContract">{{privacyContractName}} </text>”, 如您批准此隐衷爱护指引,请点击批准按钮,开始应用此小程序,咱们将尽全力爱护您的个人信息及合法权益,感谢您的信赖!<br /> </view> <view class="btns"> <button class="item reject" @tap="exitMiniProgram">回绝</button> <button id="agree-btn" class="item agree" open-type="agreePrivacyAuthorization" @agreeprivacyauthorization="handleAgreePrivacyAuthorization">批准</button> </view> </view> </view></template><script> export default { name: 'PrivacyPopup', data() { return { isRead: false, showPrivacy: false, privacyContractName: '', resolvePrivacyAuthorization: null, }; }, props: { position: { type: String, default: 'center' } }, computed: { privacyClass() { return this.position === 'bottom' ? 'privacy privacy-bottom' : 'privacy'; }, contentClass() { return this.position === 'bottom' ? 'content content-bottom' : 'content'; } }, mounted() { if (wx.onNeedPrivacyAuthorization) { wx.onNeedPrivacyAuthorization((resolve) => { this.resolvePrivacyAuthorization = resolve; }); } if (wx.getPrivacySetting) { wx.getPrivacySetting({ success: (res) => { console.log(res, 'getPrivacySetting'); if (res.needAuthorization) { this.privacyContractName = res.privacyContractName; this.showPrivacy = true; } }, }); } }, methods: { openPrivacyContract() { wx.openPrivacyContract({ success: () => { this.isRead = true; }, fail: () => { uni.showToast({ title: '遇到谬误', icon: 'error', }); }, }); }, exitMiniProgram() { wx.exitMiniProgram(); }, handleAgreePrivacyAuthorization() { this.showPrivacy = false; if (typeof this.resolvePrivacyAuthorization === 'function') { this.resolvePrivacyAuthorization({ buttonId: 'agree-btn', event: 'agree', }); } }, }, };</script><style scoped> .privacy { position: fixed; top: 0; right: 0; bottom: 0; left: 0; background: rgba(0, 0, 0, .5); z-index: 9999999; display: flex; align-items: center; justify-content: center; } .privacy-bottom { align-items: flex-end; } .content { width: 632rpx; padding: 48rpx; box-sizing: border-box; background: #fff; border-radius: 16rpx; } .content-bottom { position: absolute; bottom: 0; width: 96%; padding: 36rpx; padding-bottom: constant(safe-area-inset-bottom); padding-bottom: env(safe-area-inset-bottom); border-radius: 16rpx 16rpx 0 0; } .content .title { text-align: center; color: #333; font-weight: bold; font-size: 32rpx; } .content .des { font-size: 26rpx; color: #666; margin-top: 40rpx; text-align: justify; line-height: 1.6; } .content .des .link { color: #07c160; text-decoration: underline; } .btns { margin-top: 48rpx; margin-bottom: 12rpx; display: flex; } .btns .item { width: 200rpx; height: 72rpx; overflow: visible; display: flex; align-items: center; justify-content: center; /* border-radius: 16rpx; */ box-sizing: border-box; border: none !important; } .btns .reject { background: #f4f4f5; color: #666; font-size: 14px; font-weight: 300; margin-right: 16rpx; } .btns .agree { width: 320rpx; background: #07c160; color: #fff; font-size: 16px; } .privacy-bottom .btns .agree { width: 440rpx; }</style>3、应用形式在index.vue中增加上面代码 ...

September 10, 2023 · 2 min · jiezi

关于小程序:京东小程序数据中心架构设计与最佳实践-京东云技术团队

一、京东小程序是什么京东小程序平台可能提供凋谢、平安的产品,成为品牌开发者链接京东外部外围产品的桥梁,致力于服务每一个信赖咱们的内部开发者,为不同开发能力的品牌商家提供适合的服务和产品,让技术凋谢成为品牌的新机会。“Once Build, Run Anywhere”,一个小程序能够在多个APP运行,引擎层抹平差别,一套代码,雷同页面,云端下发,多端运行。 可能大家还不太理解咱们的京东小程序,京东小程序到底是什么呢?它和微信小程序有什么区别?首先呢,须要明确的是,京东小程序不是运行在微信端的京东商城购物小程序,而是运行在京东APP的,基于京东小程序引擎的一套京东系的小程序。 它是和支付宝小程序或者微信小程序对标的一类京东化的小程序。 举个例子,大家能够体验一下,比方在主站搜寻宝格丽,会通过搜寻中转间接跳转到宝格丽小程序上,咱们能够在这里购买奢侈品,或者在首页的同城Tab页下,能够浏览到十分多的到家门店类的小程序,总之,京东小程序所笼罩的业务还是极其宽泛的! 当然,京东小程序不仅仅能够运行在京东APP上,只有宿主在运行时依赖了咱们的小程序SDK引擎,就能够实现在各类其余宿主APP上的运行,譬如,在京东小家APP上,能够通过小程序去管制智能IOT设施,在京ME的APP上,能够近程操作打印机,实现一键打印。小程序作为一种轻量级的即用即走的工具,用户群体宽泛,早已笼罩到了咱们生存的方方面面。 京东小程序是链接商家和京东外部外围产品的重要桥梁,也是助力商家实现流量增长、业务倒退的一个重要形式。 那么,小程序平台是怎么保障商家业务的稳固、衰弱倒退,服务好这些内部商家的呢?这外面十分重要的是咱们平台对小程序根本流量的经营与监控。如何不让业务的小程序在线上裸奔?如何帮忙业务对本身小程序流量的冲高回落有一种直观的把握和监测?如何基于海量数据领导业务去进行一个精细化的经营?实际上,京东小程序数据中心就表演了一个这样的小程序数据问题终结者的角色,充分利用各类数据伎俩,解决这些痛点问题。 二、京东小程序数据中心建设里程碑 京东小程序数据中心的建设,次要经验了四个阶段,从最开始的由0到1搭建了数据根底能力,到丰盛拓展各类数据指标,接着下钻剖析到用户,帮忙商家实现基于用户的精细化的经营,到目前的小程序数智化建设,在整个小程序的迭代建设的过程中,都从各个维度为小程序的业务倒退实现了保驾护航。 三、京东小程序数据中心业务全景图 从性能角度,京东小程序经营数据分析,京东小程序监控数据分析;从展示角度,开发者控制台,治理后盾,挪动端小程序助手,宙斯凋谢能力;从性能畛域角度,用户行为剖析,交易链路数据分析,用户画像,流失率监控,流量监控等;从上报通道角度,子午线,自定义上报,服务端埋点;从数据存储角度,JED,JimDB,ES,HBase等;目前京东小程序数据中心性能范畴宽泛,咱们在依据业务倒退的需要,不断完善整个京东小程序数据中心的性能架构。 从展示角度看,包含开发者控制台,治理后盾,挪动端小程序助手,实时数据大屏, 凋谢openApi能力; 其次是从性能畛域角度看,次要包含经营数据分析,监控数据分析。 经营数据分析,包含用户行为剖析,比方小程序根底的pv和uv; 起源剖析,能够去剖析小程序在各个广告投放渠道下的营销转化成果; 用户画像剖析,能够剖析到浏览过小程序的人群中的哪些是高净值用户群体,以及性别以及年龄等根底的用户画像数据。 监控数据分析,次要是针对线上运行的小程序的奔溃异样,网络申请异样,启动性能数据的剖析,用户流失率的实时监测等,能够在小程序出现异常时第一工夫告诉到开发者。 四、京东小程序数据中心技术架构图 对于整体的架构设计,其实在我看来,数据的剖析,次要是解决三个问题,第一个要解决的是数据如何上报的问题,第二个是解决数据如何存储的问题?第三个才是解决数据如何剖析的问题? 1、京东小程序数据中心的数据上报次要包含三个路径,次要包含客户端埋点,服务端埋点或者其余内部的数据源,客户端埋点次要利用的是子午线,服务端埋点次要是咱们服务之间采集数据,服务之间生产和同步。 2、数据存到哪里去,这个须要基于咱们业务上对这些数据的实时性要求,判断是实时还是离线,进而采纳不同的数据源进行存储,数据指标是要秒级的?分钟级的?还是T+1l类型的,实时性要求不同,那么存储的数据源天然也就不同。 3、数据如何剖析,实际上就是咱们的业务逻辑,在设计时也须要充分考虑数据模型的复用性和可拓展性。 小程序数据中心对于来自子午线客户端埋点数据,以离线的形式构建小程序本人的业务数仓,一层一层地进行数据的降噪,荡涤和计算,将聚合好的维度数据再推送到关系型数据库,不便业务疾速接入。对于来自自建通道的实时数据以及内部零碎的埋点数据,通过对立上报服务将数据上报到音讯队列,进行流量数据的异步解决和消峰,采纳专门的消费者服务对上报数据进行生产落库,存储到ES和HBase数据库,便于平台进行多维度的明细或者汇总数据查问;同时,也会基于Flink对音讯队列中的数据进行流式实时计算,实现异样稳定流量的告警和剖析。 五、它山之石可以攻玉,借助团体数据工具打造小程序业务数仓痛点问题: 1.京东小程序的数据起源多样化,数据量级宏大,如何立足业务数据,施展数据价值,帮忙商家实现精细化的经营? 2.如何复用主站已有的数据模型和能力,让更多的小程序商家参加到京东主站的流量场,让数据驱动商家精准营销? 3.业务指标纷繁复杂,如何积淀和抽离通用数据模型,缩小反复工作? 如何解决: 基于团体BDP平台,自上而下构建京东小程序的业务数仓,借助BDP平台丰盛的数据产品工具,多维度地构建小程序的数据能力。离线计算+实时计算相结合,小程序业务数据+团体模型数据相结合。 1.数据分类化,将小程序流量进行主题划分,拆分为点击、浏览、曝光、订单等大维度的主题模型,不便数据定位,减少业务了解; 2.数据分层化,同一个流量主题下,进一步依照ODS->DWD->DWS->ADS的层级构造进行分层,不便追踪数据血统,缩小反复数据模型的开发; 3.数据多元化,上游零碎可从小程序数据仓库拉取合乎业务须要的畛域数据,比方数纺,搜推广等零碎,利用上游零碎成熟稳固的数据能力,为商家营销充沛赋能; 在京东小程序的业务数仓搭建过程中,次要还是利用了团体BDP大数据平台提供的丰盛的产品工具和通用能力。 几种典型的应用案例是: 1、离线hive表数据同步到jed等关系型业务库,应用buffalo工作中的出库算子; 2、业务产生的实时MQ数据同步到hive数仓,应用DTS,实时数据传输工作,能够把业务数据同步到数仓; 3、咱们须要在数仓中构建业务维表,比方构建小程序根本信息的维表,业务数据须要同步到hive表,能够采纳数据直通车DataBus,在表记录的生成上,能够依据业务的须要,采纳全量表,增量表,快照表,拉链表或者流水表的不同的记录生成形式。 京东小程序客户端埋点对立上报的子午线,须要从最原始的gdm层底表提取小程序本人的业务数据,原始底表数据量级十分大,不可能每次间接对原始底表查问,这样的话消耗计算资源,效率较低。所以,咱们尽量进步底层数据模型的复用度,对数据进行分类化和分层化解决。 所谓分类话,就是将小程序流量进行主题划分,拆分为点击、浏览、曝光、订单等大维度的主题模型,不便数据定位,减少业务了解; 所谓分层化,就是在同一个流量主题下,进一步依照ODS->DWD->DWS->ADS的层级构造进行数据分层,不便追踪数据血统,缩小反复数据模型的开发。 所谓多元化,就是复用度,加工好的这些数据,能够给上游的团队接入应用,比方商智,黄金眼,数纺这些团队。以小程序广告投放为例,在小程序数仓中咱们构建了各个类型的用户群体,在数纺注册了用户群体标签,比方关注用户,粉丝用户或者提单用户等,上游的广告精准通零碎会基于咱们的这些标签进行人群的圈选,进而实现小程序广告的投放。 总之,依据业务特点,充分利用好团体BDP的数据工具,帮忙咱们实现数仓的搭建。 六、基于FLINK实时计算,落地小程序异样奔溃监控利器痛点问题:京东小程序在线上运行时,须要实时监测到小程序的业务代码解体异样、性能数据稳定,网络申请耗时等,在有异样解体的状况下,保障能够第一工夫告诉到商家开发者,帮忙业务及时止损。 如何解决: 1.报警规定可配置,基于Zookeeper分布式配置核心存储小程序自定义的告警规定,实时监听规定节点变动,当节点数据变动时,实时聚合到业务流; 2.自定义滑动窗口,每个小程序的告警窗口大小不一样,拓展实现WindowAssigner,基于用户动静规定确定告警窗口开始工夫和截止工夫; 3.播送变量,broadcast机制,将告警配置信息播送到各个Task工作内存,播送变量就是一个公共的共享变量,将一个数据集播送后,不同的Task都能够在节点上获取到,每个节点只存一份,否则,每一个Task都会拷贝一份数据集,会造成内存资源节约。 对于小程序的实时监控能力,咱们采纳flink作为实时计算的框架,小程序在线上运行时,须要实时监测到小程序的业务代码解体异样、这种异样很可能会导致小程序白屏或者闪退,须要在探测到有异样解体的状况下,保障第一工夫告诉到商家开发者,帮忙业务及时止损。 这里的难点在于告警的规定是反对用户自定义的,比方配置观测多长时间窗口内的异样数据,当达到多少的异样阈值,应该去触发告警,应该断定为异样,这里是须要把告警规定配置的的主动权交给用户的,在这样的背景下, 1、 咱们采纳的是将告警规定放到分布式的对立配置核心,实时监听节点规定的变动,将业务流和规定流进行connet双流合并; 2、 而后依据告警规定,实现windowAssigner生成自定义的动静计算窗口,从而实现窗口动态化; 3、 最初,采纳播送变量的broadcast机制,当告警规定变更时,能够高效地将告警配置播送刷新到各个Task工作内存,进步资源利用率,保障计算时效性。 七、摸索OLAP畛域的黑马,基于ClickHouse搭建自定义数据分析引擎痛点问题:小程序外部的数据稳定如何自在埋点剖析?京东外部业务间接基于子午线埋点上报,业务团队外部自行剖析;内部的开发者须要依赖神策,GA等内部的剖析零碎,无奈将数据回流京东,且复用京东现有流量工具进行精细化经营。 ...

August 22, 2023 · 1 min · jiezi

关于小程序:大学生活动社交小程序开发笔记1

可研剖析大学生流动社交小程序是一种基于挪动互联网的社交平台,旨在为大学生提供一个不便、快捷、平安的社交和流动交流平台 性能布局流动公布:平台能够公布将要举办的流动,包含工夫、地点、费用等信息,并邀请其余用户加入。流动搜寻:用户能够依据本人的兴趣爱好搜寻流动,并加入感兴趣的流动。流动评估:用户能够对加入过的流动进行评估和反馈,帮忙其余用户更好地抉择流动。打卡模块:能够帮忙大学生记录和评比每天的学习、浏览、文艺、体育、体育等流动。通过实现一个个小指标帮忙大学生更好地治理本人的工夫和指标。 实现目标大学生流动社交小程序能够帮忙大学生更好地组织和加入流动,扩大社交圈子,丰盛大学生存。 本我的项目前后端残缺代码包含布告告诉,校园风采,流动分类与列表,流动报名与评估,打卡我的项目列表,打卡排行与每日动静,我的流动报名,我的每日打卡;后盾打卡项目管理,打卡记录治理与导出,后盾流动与报名治理,报名审核与数据导出等性能,流动组织方能够自定义要填写的内容 数据库设计ActivityModel.DB_STRUCTURE = { _pid: 'string|true', ACTIVITY_ID: 'string|true', ACTIVITY_TITLE: 'string|true|comment=题目', ACTIVITY_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=应用中', ACTIVITY_CATE_ID: 'string|true|default=0|comment=分类', ACTIVITY_CATE_NAME: 'string|false|comment=分类冗余', ACTIVITY_CANCEL_SET: 'int|true|default=1|comment=勾销设置 0=不允,1=容许,2=仅截止前可勾销', ACTIVITY_CHECK_SET: 'int|true|default=0|comment=审核 0=不须要审核,1=须要审核', ACTIVITY_IS_MENU: 'int|true|default=1|comment=是否公开展现名单', ACTIVITY_MAX_CNT: 'int|true|default=20|comment=人数下限 0=不限', ACTIVITY_START: 'int|false|comment=流动开始工夫', ACTIVITY_END: 'int|false|comment=流动截止工夫', ACTIVITY_STOP: 'int|true|default=0|comment=报名截止工夫 0=永不过期', ACTIVITY_ORDER: 'int|true|default=9999', ACTIVITY_VOUCH: 'int|true|default=0', ACTIVITY_FORMS: 'array|true|default=[]', ACTIVITY_OBJ: 'object|true|default={}', ACTIVITY_JOIN_FORMS: 'array|true|default=[]', ACTIVITY_ADDRESS: 'string|false|comment=具体地址', ACTIVITY_ADDRESS_GEO: 'object|false|comment=具体地址坐标参数', ACTIVITY_QR: 'string|false', ACTIVITY_VIEW_CNT: 'int|true|default=0', ACTIVITY_JOIN_CNT: 'int|true|default=0', ACTIVITY_COMMENT_CNT: 'int|true|default=0', ACTIVITY_USER_LIST: 'array|true|default=[]|comment={name,id,pic}', ACTIVITY_ADD_TIME: 'int|true', ACTIVITY_EDIT_TIME: 'int|true', ACTIVITY_ADD_IP: 'string|false', ACTIVITY_EDIT_IP: 'string|false',};ActivityJoinModel.DB_STRUCTURE = { _pid: 'string|true', ACTIVITY_JOIN_ID: 'string|true', ACTIVITY_JOIN_ACTIVITY_ID: 'string|true|comment=报名PK', ACTIVITY_JOIN_IS_ADMIN: 'int|true|default=0|comment=是否管理员增加 0/1', ACTIVITY_JOIN_CODE: 'string|true|comment=核验码15位', ACTIVITY_JOIN_IS_CHECKIN: 'int|true|default=0|comment=是否签到 0/1 ', ACTIVITY_JOIN_CHECKIN_TIME: 'int|false|default=0|签到工夫', ACTIVITY_JOIN_USER_ID: 'string|true|comment=用户ID', ACTIVITY_JOIN_FORMS: 'array|true|default=[]|comment=表单', ACTIVITY_JOIN_OBJ: 'object|true|default={}', ACTIVITY_JOIN_STATUS: 'int|true|default=1|comment=状态 0=待审核 1=报名胜利, 99=审核未过', ACTIVITY_JOIN_REASON: 'string|false|comment=审核回绝或者勾销理由', ACTIVITY_JOIN_ADD_TIME: 'int|true', ACTIVITY_JOIN_EDIT_TIME: 'int|true', ACTIVITY_JOIN_ADD_IP: 'string|false', ACTIVITY_JOIN_EDIT_IP: 'string|false',};外围实现class ActivityService extends BaseProjectService { // 获取以后活动状态 getJoinStatusDesc(activity) { let timestamp = this._timestamp; if (activity.ACTIVITY_STATUS == 0) return '流动进行'; else if (activity.ACTIVITY_END <= timestamp) return '流动完结'; else if (activity.ACTIVITY_STOP <= timestamp) return '报名完结'; else if (activity.ACTIVITY_MAX_CNT > 0 && activity.ACTIVITY_JOIN_CNT >= activity.ACTIVITY_MAX_CNT) return '报名已满'; else return '报名中'; } /** 浏览信息 */ async viewActivity(userId, id) { let fields = '*'; let where = { _id: id, ACTIVITY_STATUS: ActivityModel.STATUS.COMM } let activity = await ActivityModel.getOne(where, fields); if (!activity) return null; ActivityModel.inc(id, 'ACTIVITY_VIEW_CNT', 1); // 判断是否有报名 let whereJoin = { ACTIVITY_JOIN_USER_ID: userId, ACTIVITY_JOIN_ACTIVITY_ID: id, ACTIVITY_JOIN_STATUS: ['in', [ActivityJoinModel.STATUS.WAIT, ActivityJoinModel.STATUS.SUCC]] } let activityJoin = await ActivityJoinModel.getOne(whereJoin); if (activityJoin) { activity.myActivityJoinId = activityJoin._id; activity.myActivityJoinTag = (activityJoin.ACTIVITY_JOIN_STATUS == ActivityJoinModel.STATUS.WAIT) ? '待审核' : '已报名'; } else { activity.myActivityJoinId = ''; activity.myActivityJoinTag = ''; } return activity; } /** 获得分页列表 */ async getActivityList({ cateId, //分类查问条件 search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 page, size, isTotal = true, oldTotal }) { orderBy = orderBy || { 'ACTIVITY_ORDER': 'asc', 'ACTIVITY_ADD_TIME': 'desc' }; let fields = 'ACTIVITY_USER_LIST,ACTIVITY_STOP,ACTIVITY_JOIN_CNT,ACTIVITY_OBJ,ACTIVITY_VIEW_CNT,ACTIVITY_TITLE,ACTIVITY_MAX_CNT,ACTIVITY_START,ACTIVITY_END,ACTIVITY_ORDER,ACTIVITY_STATUS,ACTIVITY_CATE_NAME,ACTIVITY_OBJ'; let where = {}; where.and = { _pid: this.getProjectId() //简单的查问在此处标注PID }; if (cateId && cateId !== '0') where.and.ACTIVITY_CATE_ID = cateId; where.and.ACTIVITY_STATUS = ActivityModel.STATUS.COMM; // 状态 if (util.isDefined(search) && search) { where.or = [{ ACTIVITY_TITLE: ['like', search] },]; } else if (sortType && util.isDefined(sortVal)) { // 搜寻菜单 switch (sortType) { case 'cateId': { if (sortVal) where.and.ACTIVITY_CATE_ID = String(sortVal); break; } case 'sort': { // 排序 orderBy = this.fmtOrderBySort(sortVal, 'ACTIVITY_ADD_TIME'); break; } case 'today': { //明天 let start = timeUtil.getDayFirstTimestamp(); let end = start + 86400 * 1000 - 1; where.and.ACTIVITY_START = ['between', start, end]; break; } case 'tomorrow': { //明日 let start = timeUtil.getDayFirstTimestamp() + 86400 * 1000; let end = start + 86400 * 1000 - 1; where.and.ACTIVITY_START = ['between', start, end]; break; } case 'month': { //本月 let day = timeUtil.time('Y-M-D'); let start = timeUtil.getMonthFirstTimestamp(day); let end = timeUtil.getMonthLastTimestamp(day); where.and.ACTIVITY_START = ['between', start, end]; break; } } } return await ActivityModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal); } /** 获得某一个报名分页列表 */ async getActivityJoinList(activityId, { search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 page, size, isTotal = true, oldTotal }) { orderBy = orderBy || { 'ACTIVITY_JOIN_ADD_TIME': 'desc' }; let fields = 'ACTIVITY_JOIN_OBJ,ACTIVITY_JOIN_IS_CHECKIN,ACTIVITY_JOIN_REASON,ACTIVITY_JOIN_ACTIVITY_ID,ACTIVITY_JOIN_STATUS,ACTIVITY_JOIN_ADD_TIME,user.USER_PIC,user.USER_NAME,user.USER_OBJ'; let where = { ACTIVITY_JOIN_ACTIVITY_ID: activityId, ACTIVITY_JOIN_STATUS: ActivityModel.STATUS.COMM }; let joinParams = { from: UserModel.CL, localField: 'ACTIVITY_JOIN_USER_ID', foreignField: 'USER_MINI_OPENID', as: 'user', }; let result = await ActivityJoinModel.getListJoin(joinParams, where, fields, orderBy, page, size, isTotal, oldTotal); return result; } /** 获得我的报名分页列表 */ async getMyActivityJoinList(userId, { search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 page, size, isTotal = true, oldTotal }) { orderBy = orderBy || { 'ACTIVITY_JOIN_ADD_TIME': 'desc' }; let fields = 'ACTIVITY_JOIN_IS_CHECKIN,ACTIVITY_JOIN_REASON,ACTIVITY_JOIN_ACTIVITY_ID,ACTIVITY_JOIN_STATUS,ACTIVITY_JOIN_ADD_TIME,activity.ACTIVITY_END,activity.ACTIVITY_START,activity.ACTIVITY_TITLE'; let where = { ACTIVITY_JOIN_USER_ID: userId }; if (util.isDefined(search) && search) { where['activity.ACTIVITY_TITLE'] = { $regex: '.*' + search, $options: 'i' }; } else if (sortType) { // 搜寻菜单 switch (sortType) { case 'timedesc': { //按工夫倒序 orderBy = { 'activity.ACTIVITY_START': 'desc', 'ACTIVITY_JOIN_ADD_TIME': 'desc' }; break; } case 'timeasc': { //按工夫正序 orderBy = { 'activity.ACTIVITY_START': 'asc', 'ACTIVITY_JOIN_ADD_TIME': 'asc' }; break; } case 'succ': { where.ACTIVITY_JOIN_STATUS = ActivityJoinModel.STATUS.SUCC; break; } case 'wait': { where.ACTIVITY_JOIN_STATUS = ActivityJoinModel.STATUS.WAIT; break; } case 'cancel': { where.ACTIVITY_JOIN_STATUS = ActivityJoinModel.STATUS.ADMIN_CANCEL; break; } } } let joinParams = { from: ActivityModel.CL, localField: 'ACTIVITY_JOIN_ACTIVITY_ID', foreignField: '_id', as: 'activity', }; let result = await ActivityJoinModel.getListJoin(joinParams, where, fields, orderBy, page, size, isTotal, oldTotal); return result; } /** 获得我的报名详情 */ async getMyActivityJoinDetail(userId, activityJoinId) { let fields = '*'; let where = { _id: activityJoinId, ACTIVITY_JOIN_USER_ID: userId }; let activityJoin = await ActivityJoinModel.getOne(where, fields); if (activityJoin) { activityJoin.activity = await ActivityModel.getOne(activityJoin.ACTIVITY_JOIN_ACTIVITY_ID, 'ACTIVITY_TITLE,ACTIVITY_START,ACTIVITY_END'); } return activityJoin; } //################## 报名 // 报名 async activityJoin(userId, activityId, forms) { // 报名是否完结 let whereActivity = { _id: activityId, ACTIVITY_STATUS: ActivityModel.STATUS.COMM } let activity = await ActivityModel.getOne(whereActivity); if (!activity) this.AppError('该流动不存在或者曾经进行'); // 是否流动完结 if (activity.ACTIVITY_END < this._timestamp) this.AppError('该流动曾经完结,请抉择其余流动'); // 是否过了报名截止期 if (activity.ACTIVITY_STOP < this._timestamp) this.AppError('该流动报名曾经截止,请抉择其余流动'); // 人数是否满 if (activity.ACTIVITY_MAX_CNT > 0) { let whereCnt = { ACTIVITY_JOIN_ACTIVITY_ID: activityId, ACTIVITY_JOIN_STATUS: ['in', [ActivityJoinModel.STATUS.WAIT, ActivityJoinModel.STATUS.SUCC]] } let cntJoin = await ActivityJoinModel.count(whereCnt); if (cntJoin >= activity.ACTIVITY_MAX_CNT) this.AppError('该流动报名已满,请抉择其余流动'); } // 本人是否曾经有报名 let whereMy = { ACTIVITY_JOIN_USER_ID: userId, ACTIVITY_JOIN_ACTIVITY_ID: activityId, ACTIVITY_JOIN_STATUS: ['in', [ActivityJoinModel.STATUS.WAIT, ActivityJoinModel.STATUS.SUCC]] } let my = await ActivityJoinModel.getOne(whereMy); if (my) { if (my.ACTIVITY_JOIN_STATUS == ActivityJoinModel.STATUS.WAIT) this.AppError('您曾经报名,正在期待审核,毋庸反复报名'); else this.AppError('您曾经报名胜利,毋庸反复报名'); } // 入库 let data = { ACTIVITY_JOIN_USER_ID: userId, ACTIVITY_JOIN_ACTIVITY_ID: activityId, ACTIVITY_JOIN_STATUS: (activity.ACTIVITY_CHECK_SET == 0) ? ActivityJoinModel.STATUS.SUCC : ActivityJoinModel.STATUS.WAIT, ACTIVITY_JOIN_FORMS: forms, ACTIVITY_JOIN_OBJ: dataUtil.dbForms2Obj(forms), ACTIVITY_JOIN_CODE: dataUtil.genRandomIntString(15), } let activityJoinId = await ActivityJoinModel.insert(data); // 统计数量 await this.statActivityJoin(activityId); let check = activity.ACTIVITY_CHECK_SET; return { activityJoinId, check } } async statActivityJoin(id) { // 报名数 let where = { ACTIVITY_JOIN_ACTIVITY_ID: id, ACTIVITY_JOIN_STATUS: ['in', [ActivityJoinModel.STATUS.WAIT, ActivityJoinModel.STATUS.SUCC]] } let cnt = await ActivityJoinModel.count(where); // 用户列表 where = { ACTIVITY_JOIN_ACTIVITY_ID: id, ACTIVITY_JOIN_STATUS: ActivityJoinModel.STATUS.SUCC } let joinParams = { from: UserModel.CL, localField: 'ACTIVITY_JOIN_USER_ID', foreignField: 'USER_MINI_OPENID', as: 'user', }; let orderBy = { ACTIVITY_JOIN_ADD_TIME: 'desc' } let list = await ActivityJoinModel.getListJoin(joinParams, where, 'ACTIVITY_JOIN_ADD_TIME,user.USER_MINI_OPENID,user.USER_NAME,user.USER_PIC', orderBy, 1, 6, false, 0); list = list.list; for (let k = 0; k < list.length; k++) { list[k] = list[k].user; } await ActivityModel.edit(id, { ACTIVITY_JOIN_CNT: cnt, ACTIVITY_USER_LIST: list }); } /** 报名前获取要害信息 */ async detailForActivityJoin(userId, activityId) { let fields = 'ACTIVITY_JOIN_FORMS, ACTIVITY_TITLE'; let where = { _id: activityId, ACTIVITY_STATUS: ActivityModel.STATUS.COMM } let activity = await ActivityModel.getOne(where, fields); if (!activity) this.AppError('该流动不存在'); // 取出自己最近一次的填写表单 let whereMy = { ACTIVITY_JOIN_USER_ID: userId, } let orderByMy = { ACTIVITY_JOIN_ADD_TIME: 'desc' } let joinMy = await ActivityJoinModel.getOne(whereMy, 'ACTIVITY_JOIN_FORMS', orderByMy); let myForms = joinMy ? joinMy.ACTIVITY_JOIN_FORMS : []; activity.myForms = myForms; return activity; } /** 勾销我的报名 只有胜利和待审核能够勾销 勾销即为删除记录 */ async cancelMyActivityJoin(userId, activityJoinId) { let where = { ACTIVITY_JOIN_USER_ID: userId, _id: activityJoinId, ACTIVITY_JOIN_STATUS: ['in', [ActivityJoinModel.STATUS.WAIT, ActivityJoinModel.STATUS.SUCC]] }; let activityJoin = await ActivityJoinModel.getOne(where); if (!activityJoin) { this.AppError('未找到可勾销的报名记录'); } if (activityJoin.ACTIVITY_JOIN_IS_CHECKIN == 1) this.AppError('该流动曾经签到,无奈勾销'); let activity = await ActivityModel.getOne(activityJoin.ACTIVITY_JOIN_ACTIVITY_ID); if (!activity) this.AppError('该流动不存在'); if (activity.ACTIVITY_END <= this._timestamp) this.AppError('该流动曾经完结,无奈勾销'); if (activity.ACTIVITY_CANCEL_SET == 0) this.AppError('该流动不能取消'); if (activity.ACTIVITY_CANCEL_SET == 2 && activity.ACTIVITY_STOP < this._timestamp) this.AppError('该流动曾经截止报名,不能取消'); await ActivityJoinModel.del(where); // 统计 await this.statActivityJoin(activityJoin.ACTIVITY_JOIN_ACTIVITY_ID); } /** 用户自助签到 */ async myJoinSelf(userId, activityId) { let activity = await ActivityModel.getOne(activityId); if (!activity) this.AppError('流动不存在或者曾经敞开'); let day = timeUtil.timestamp2Time(activity.ACTIVITY_START, 'Y-M-D'); let today = timeUtil.time('Y-M-D'); if (day != today) this.AppError('仅在流动当天能够签到,以后签到码的日期是' + day); let whereSucc = { ACTIVITY_JOIN_USER_ID: userId, ACTIVITY_JOIN_STATUS: ActivityJoinModel.STATUS.SUCC } let cntSucc = await ActivityJoinModel.count(whereSucc); let whereCheckin = { ACTIVITY_JOIN_USER_ID: userId, ACTIVITY_JOIN_IS_CHECKIN: 1, ACTIVITY_JOIN_STATUS: ActivityJoinModel.STATUS.SUCC } let cntCheckin = await ActivityJoinModel.count(whereCheckin); let ret = ''; if (cntSucc == 0) { ret = '您没有本次流动报名胜利的记录,请在「集体核心 - 我的流动报名」查看详情~'; } else if (cntSucc == cntCheckin) { // 同一流动屡次报名的状况 ret = '您已签到,毋庸反复签到,请在「集体核心 - 我的流动报名」查看详情~'; } else { let where = { ACTIVITY_JOIN_USER_ID: userId, ACTIVITY_JOIN_IS_CHECKIN: 0, ACTIVITY_JOIN_STATUS: ActivityJoinModel.STATUS.SUCC } let data = { ACTIVITY_JOIN_IS_CHECKIN: 1, ACTIVITY_JOIN_CHECKIN_TIME: this._timestamp, } await ActivityJoinModel.edit(where, data); ret = '签到胜利,请在「集体核心 - 我的流动报名」查看详情~' } return { ret }; } /** 按天获取报名我的项目 */ async getActivityListByDay(day) { let start = timeUtil.time2Timestamp(day); let end = start + 86400 * 1000 - 1; let where = { ACTIVITY_STATUS: ActivityModel.STATUS.COMM, ACTIVITY_START: ['between', start, end], }; let orderBy = { 'ACTIVITY_ORDER': 'asc', 'ACTIVITY_ADD_TIME': 'desc' }; let fields = 'ACTIVITY_TITLE,ACTIVITY_START,ACTIVITY_OBJ.cover'; let list = await ActivityModel.getAll(where, fields, orderBy); let retList = []; for (let k = 0; k < list.length; k++) { let node = {}; node.timeDesc = timeUtil.timestamp2Time(list[k].ACTIVITY_START, 'h:m'); node.title = list[k].ACTIVITY_TITLE; node.pic = list[k].ACTIVITY_OBJ.cover[0]; node._id = list[k]._id; retList.push(node); } return retList; } /** * 获取从某天开始可报名的日期 * @param {*} fromDay 日期 Y-M-D */ async getActivityHasDaysFromDay(fromDay) { let where = { ACTIVITY_START: ['>=', timeUtil.time2Timestamp(fromDay)], }; let fields = 'ACTIVITY_START'; let list = await ActivityModel.getAllBig(where, fields); let retList = []; for (let k = 0; k < list.length; k++) { let day = timeUtil.timestamp2Time(list[k].ACTIVITY_START, 'Y-M-D'); if (!retList.includes(day)) retList.push(day); } return retList; }}UI设计 ...

July 11, 2023 · 7 min · jiezi

关于小程序:云供应链管理系统怎样实现打印

 人们对物流速度的要求越来越高,快递投递速度放慢,不仅是对物流服务的高要求,更是对供应链治理的考验。 不论是电商行业,还是制造业,供应链都是将供应商、制造商、分销商直到最终消费者连成一个整体的性能网链构造。这就意味着供应链治理波及多方,其服务范畴是多层次和宽泛的。 供应链治理,能够无效整合供应链中的打算、洽购、制作、交付、回收五大环节,简化生产、物流和分销,是企业实现降本增效的重要伎俩。 当下,得益于云计算技术的疾速倒退,供应链治理正迈向高效麻利的云供应链治理,各行业云供应链管理系统也如雨后春笋般冒出。怎么能够怀才不遇? 在理论的供应链治理过程中,像生产、洽购、制作、物流、仓储等环节每天都会有大量的的单据、文件须要打印,而传统打印机往往受间隔、空间等限度,影响企业的经营效率。这也是当下市场上云供应链管理软件的一个难题。 云打印利用互联网打印技术,满足云供应链治理的SaaS软件、挪动端软件应用的打印需要,可打印各个环节的单据、文件。软件装置在手机、平板、智能POS机、电脑等设施都可云打印。 特点1.挪动端打印满足挪动端设施(手机/平板电脑)间接打印的需要,无需再上传电脑打印。 2.近程打印实现挪动端近程打印需要,打印不受间隔限度,近程办公、异地仓库发货、车载打单等状况都实用。

July 7, 2023 · 1 min · jiezi

关于小程序:开源一个能学赚习钱的应用-十一节头像小程序

大家好,我是程序员饭哥,一个前端码农,目前还在打怪降级中,心愿本人成为全栈,另外也不想卷了,想做点有意思的事件。 本文技术上没啥深度,只是堆代码,没设计可言,比拟适宜老手。 明天带来一个能赚钱的国庆头像小程序。 文章次要包含以下几个内容, 利用介绍外围性能实现和遇到的问题盈利模式经营思路利用介绍这个利用是一个头像合成的工具,之前十一假期的时候这类的小程序可是火了一把,当然很多人也赚了一笔。 另外本次开发也降级了一些性能,算是比拟残缺了。 1.优化整体布局 2.新增更多头像款式 3.新增自定头像性能(可本人上传照片) 4.降级获取微信头像能力,原来的getUserProfile又不能用了,定位了半天,后果是官网降级了。当初依照官网要求实现了 5.接入了广告,目前又3个广告。 6.减少了对于作者,更容易找到我 自定义头像 外围性能实现和遇到的问题图片合成实现利用canvas来实现,把咱们的图片和国旗图片依照程序绘制到canvas上,另外要保障国旗图片是通明的。另外canvas是只反对绘制本地图片,所以在应用前须要把图片下载到本地,两个图片的绘制要依照程序来,第一个绘制实现后能力绘制第二个。 外围代码 //绘图 drawImg(headImg, index) { let that = this wx.showLoading({ title: '头像生成中...', }) let promiseHead = new Promise((resolve, reject) => { wx.getImageInfo({ src: headImg, success(res) { resolve(res) }, fail(e) { reject("调用失败head"); wx.hideLoading() } }) }) Promise.all([promiseHead]).then(promiseRes => { let num = 1024 let width_userIcon = num let x_userIcon = (num - (num)) / 2 let frameImgUrl = that.data.photo_bj_num[index]; const query = wx.createSelectorQuery() query.select('#genimg') .fields({ node: true, size: true }) .exec((res) => { const canvas = res[0].node const ctx = canvas.getContext('2d'); // 初始化画布大小 const dpr = wx.getWindowInfo().pixelRatio; canvas.width = 1024 * dpr canvas.height = 1024 * dpr ctx.scale(dpr, dpr) const bg1 = canvas.createImage(); const bg2 = canvas.createImage(); bg1.src = promiseRes[0].path; bg1.onload = () => { ctx.drawImage(bg1, x_userIcon, x_userIcon, width_userIcon, width_userIcon); bg2.onload = () => { ctx.drawImage(bg2, 0, 0, num, num); } bg2.src = frameImgUrl; } setTimeout(() => { // 第一个参数为false,示意先清空画布再绘制 wx.canvasToTempFilePath({ x: 0, y: 0, width: num, height: num, destWidth: num, destHeight: num, canvas, quality: 1, success(res) { that.setData({ new_userImage: res.tempFilePath, new_showuserImage: true, userImage: headImg }) wx.hideLoading() }, fail(res) { console.log("绘图谬误:" + JSON.stringify(res)); wx.hideLoading(); } }, that); }, 1000); }) }).catch(e => console.log(e)); }获取微信头像问题之前获取微信头像应用wx.getUserProfile即可,过后搞了良久发现是官网曾经放弃了这个api,有点坑了。 ...

July 2, 2023 · 2 min · jiezi

关于小程序:wx小程序抓取流程

抓包抓不到包时可尝试 低版本安卓、低版本微信 或者拉取wxapkg包 解包通过微信开发者工具加载抓包小程序前端组成部分.wxml -页面构造.wxcss -页面款式.js -管制交互.json -配置数据wxapkg拉取/解包当咱们点击关上小程序时,会将wxapkg包下载到本地从手机或者模拟器拉取wxapkg包目录个别在:/data/data/com.tencent.mm/MicroMsg/微信号id文件夹/appbrand/pkg/ 小程序有大小限度,超过8m或会拆分成多个子包加载拉取解包程序https://gitee.com/_being/wxappUnpacker/blob/master/README.md运行须要有node.js环境并装置依赖包解包先解主包node wuWxapkg.js xxxxx.wxapkg而后解分包,将解包后的文件在主包找到雷同的文件进行笼罩node wuWxapkg.js 分包.wxapkg -s=主包的目录解包胜利的标识:根目录下生成:app.js app.json app.wxss或者应用UnpackMiniApp的一个程序间接解包,毛病:不能解分包调试微信小程序 1.申请小程序开发者账号 https://mp.weixin.qq.com 2.下载小程序开发者工具 https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html 3.登陆开发者工具,导入解包的小程序 4.调试形式和chrome统一。要在详情里选中 不校验https证书

June 30, 2023 · 1 min · jiezi

关于小程序:京东到家小程序在性能及多端能力的探索实践-京东云技术团队

一、前言京东到家小程序最后只有微信小程序,随着业务的倒退,同样的性能须要反对容器越来越多,包含支付宝小程序、京东小程序、到家APP、京东APP等,然而每个端离开实现要面临研发老本高、不统一等问题。 为了进步研发效率,通过技术选型采纳了taro3+原生混合开发模式,本文次要解说咱们是如何基于taro框架,进行多端能力的摸索和性能优化。 二、多端能力的摸索1.到家小程序基于taro3的架构流程图 框架分层解释 1.配置层:次要蕴含编译配置、路由配置、分包加载、拓展口子。 2.视图层:次要实现App生命周期初始化、页面初始化、注入宿主事件、解析配置为页面和组件绑定事件和属性。 3.组件库:是一个独自保护的我的项目,多端组件库包含业务组件和原子组件,可由视图层依据配置动静加载组件。 //渲染主入口 render() { let { configData, isDefault, isLoading } = this.state; const pageInfo = { ...this.pageInfoValue, ...this._pageInfo } return ( <MyContext.Provider value={pageInfo}> <View className={style.bg} > {//动静渲染模板组件 configData && configData.map((item, key) => { return this.renderComponent(item, key); }) } </View> {isLoading && <Loading></Loading>} </MyContext.Provider> ); } //渲染组件 注入下发配置事件和属性 renderComponent(item, key) { const AsyncComponent = BussinesComponent[item.templateName]; if (AsyncComponent) { return ( <AsyncComponent key={key} dataSource={item.data} {...item.config} pageEvent={pageEvent} ></AsyncComponent> ); } else { return null; } }4.逻辑层:包含业务解决逻辑,申请、异样、状态、性能、公共工具类,以及与根底库对接的适配能力。 ...

June 29, 2023 · 3 min · jiezi

关于小程序:已完成小程序拼团小程序授权微信地址信息逻辑

小程序受权微信地址信息逻辑第一步:查阅微信小程序文档第二步:评估实现办法wx.chooseAddress app.js 中 requiredPrivateInfos 小程序管理后盾 -「开发」-「开发治理」-「接口设置」申请获取地址权限 第三步:新增获取微信按钮第四步:如何将获取的地址间接把数据,传到后盾解决。通过数据库查找定位城市编号。思考地址反复的问题。 微信增加按钮,事件为addressWxHandle 复制addAddress函数,并命名为addWxAddress 并编辑申请接口地址为,wxminiapp 第五步:新增后端代码逻辑

June 25, 2023 · 1 min · jiezi

关于小程序:小程序微信登录后端使用SpringBoot

前言官网给了这么一张图:原文:https://developers.weixin.qq.com/miniprogram/dev/framework/op... 微信登录和一般登录一般登录的过程是: 用户提交username和password后端查数据库,username和password是否正确如果正确,设置用户登录状态,生成token,返回token微信登录的过程: 用户提交微信生成的长期code后端问一下微信服务器:这code是谁啊?微信会返回用户的openid后端查数据库,这openid的用户注册了吗?如果注册了,设置用户登录状态,生成token,返回token这么一比不难发现,微信登录只不过是把提交明码和验证明码的过程,变成了查问用户身份和验证用户身份的过程。至于前面怎么生成token,怎么返回,怎么设置生效工夫,就和以前明码验证是截然不同的,本文不再赘述。 操作一、前端:wx.login获取长期code数据流:用户的小程序->微信服务器官网接口文档:https://developers.weixin.qq.com/miniprogram/dev/api/open-api... /** * 生命周期函数--监听页面加载 */ onLoad() { wx.login().then((res) => { console.log(res); }) }, 二、后端:起个我的项目这一步的作用是测试前后端连通,临时不进行逻辑解决。 @RestController@RequestMapping("wxLogin")public class WxLoginController { @PostMapping() @CrossOrigin("*") public String Login(@RequestBody String code) { System.out.println(code); return "success"; }}三、前端:拿着code申请后端的登录接口数据流:用户的小程序->开发者服务器 /** * 生命周期函数--监听页面加载 */ onLoad() { // 向微信服务器获取code wx.login().then((res) => { // 拿着code向开发者服务器登录 wxLogin(res.code).then((res_1) => { console.log(res_1.data); }) }) },此处WxLogin办法是本人写的申请办法,本人实现即可,给出一个参考: /** * 登录 * @param username 用户名 * @param password 明码 */async function wxLogin(code: string) { const res = await httpPost({ url: '/wxLogin', header: { 'content-type': 'application/json' // 默认值 }, data: { code: code } }) return res;}// 后端地址const baseUrl="http://localhost:8080"/** * Post形式的HTTP申请 * @param requestOptions */function httpPost(requestOptions: WechatMiniprogram.RequestOption) { wx.showLoading({ title: '加载中', }) requestOptions.url = baseUrl + requestOptions.url requestOptions.header = { ...requestOptions.header, // "Authorization": getToken() } return new Promise((resolve, reject) => { wx.request({ ...requestOptions, method: "POST", success(res: any) { wx.hideLoading() resolve(res) }, fail(error) { wx.hideLoading() reject(error) } }) })}运行后果——后端:打印了code前端:收到了胜利信息 ...

June 14, 2023 · 2 min · jiezi

关于小程序:读书会活动打卡小程序开发笔记一

背景剖析书籍是人类提高的阶梯,在信息高度发达而塌实的当下,静下心来读书成为都市人群的新趋势, 很多读书社团应运而生,那么通过设计一款小程序,把读书会搬到手机上,通过小程序理解最热门的书单和作家,能够每天组织浏览打卡和评比;书友会时常组织书友进行线下流动,那么通过小程序能够不便的搞定报名、签到、流动信息收集,流动完结后还能够进行评估。 性能布局 数据库设计EnrollModel.DB_STRUCTURE = { _pid: 'string|true', ENROLL_ID: 'string|true', ENROLL_TITLE: 'string|true|comment=题目', ENROLL_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=应用中', ENROLL_CATE_ID: 'string|true|default=0|comment=分类', ENROLL_CATE_NAME: 'string|false|comment=分类冗余', ENROLL_START: 'int|false|comment=开始工夫', ENROLL_END: 'int|false|comment=完结工夫', ENROLL_DAY_CNT: 'int|false|comment=继续天数', ENROLL_ORDER: 'int|true|default=9999', ENROLL_VOUCH: 'int|true|default=0', ENROLL_FORMS: 'array|true|default=[]', ENROLL_OBJ: 'object|true|default={}', ENROLL_JOIN_FORMS: 'array|true|default=[]', ENROLL_DAYS: 'array|true|default=[]', ENROLL_QR: 'string|false', ENROLL_VIEW_CNT: 'int|true|default=0', ENROLL_JOIN_CNT: 'int|true|default=0', ENROLL_USER_CNT: 'int|true|default=0', ENROLL_USER_LIST: 'array|true|default=[]|comment={name,id,pic}', ENROLL_ADD_TIME: 'int|true', ENROLL_EDIT_TIME: 'int|true', ENROLL_ADD_IP: 'string|false', ENROLL_EDIT_IP: 'string|false',};EnrollJoinModel.DB_STRUCTURE = { _pid: 'string|true', ENROLL_JOIN_ID: 'string|true', ENROLL_JOIN_ENROLL_ID: 'string|true|comment=打卡PK', ENROLL_JOIN_USER_ID: 'string|true|comment=用户ID', ENROLL_JOIN_DAY: 'string|true|comment=日期', ENROLL_JOIN_FORMS: 'array|true|default=[]|comment=表单', ENROLL_JOIN_STATUS: 'int|true|default=1|comment=状态 1=胜利', ENROLL_JOIN_ADD_TIME: 'int|true', ENROLL_JOIN_EDIT_TIME: 'int|true', ENROLL_JOIN_ADD_IP: 'string|false', ENROLL_JOIN_EDIT_IP: 'string|false',};外围实现class EnrollService extends BaseProjectService { // 获取以后打卡状态 getJoinStatusDesc(enroll) { let timestamp = this._timestamp; if (enroll.ENROLL_STATUS == 0) return '已进行'; else if (enroll.ENROLL_START > timestamp) return '未开始'; else if (enroll.ENROLL_END <= timestamp) return '已完结'; else return '进行中'; } // 获取某日动静 async getEnrollJoinByDay(enrollId, day = '') { if (!day) day = timeUtil.time('Y-M-D'); let where = { ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_DAY: day, ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC } let joinParams = { from: UserModel.CL, localField: 'ENROLL_JOIN_USER_ID', foreignField: 'USER_MINI_OPENID', as: 'user', }; let orderBy = { ENROLL_JOIN_ADD_TIME: 'desc' } let list = await EnrollJoinModel.getListJoin(joinParams, where, 'ENROLL_JOIN_ADD_TIME,user.USER_NAME,user.USER_PIC', orderBy, 1, 100, false, 0); return list.list; } // 获取某流动排行 async getEnrollUserRank(enrollId) { let where = { ENROLL_USER_ENROLL_ID: enrollId } let joinParams = { from: UserModel.CL, localField: 'ENROLL_USER_MINI_OPENID', foreignField: 'USER_MINI_OPENID', as: 'user', }; let orderBy = { ENROLL_USER_JOIN_CNT: 'desc' } let fields = 'ENROLL_USER_JOIN_CNT,ENROLL_USER_LAST_DAY,user.USER_NAME,user.USER_PIC'; let list = await EnrollUserModel.getListJoin(joinParams, where, fields, orderBy, 1, 100, false, 0); return list.list; } /** 浏览信息 */ async viewEnroll(userId, id) { let fields = '*'; let where = { _id: id, ENROLL_STATUS: EnrollModel.STATUS.COMM } let enroll = await EnrollModel.getOne(where, fields); if (!enroll) return null; EnrollModel.inc(id, 'ENROLL_VIEW_CNT', 1); // 判断用户今日是否有打卡 let whereJoin = { ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: id, ENROLL_JOIN_DAY: timeUtil.time('Y-M-D'), ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC } let enrollJoin = await EnrollJoinModel.getOne(whereJoin); if (enrollJoin) { enroll.myEnrollJoinId = enrollJoin._id; } else { enroll.myEnrollJoinId = ''; } // 某日打卡列表 enroll.activity = await this.getEnrollJoinByDay(id); // 打卡日期数组 let dayList = []; let start = timeUtil.timestamp2Time(enroll.ENROLL_START, 'Y-M-D'); start = timeUtil.time2Timestamp(start); let today = timeUtil.time2Timestamp(timeUtil.time('Y-M-D')); for (let k = start; k <= today;) { let month = timeUtil.timestamp2Time(k, 'M月'); if (month.startsWith('0')) month = month.substring(1); let date = timeUtil.timestamp2Time(k, 'D'); let day = timeUtil.timestamp2Time(k, 'Y-M-D'); dayList.push({ month, date, day }); k = k + 86400 * 1000; } enroll.dayList = dayList; // 排行榜 let rankList = await this.getEnrollUserRank(id); enroll.rankList = rankList; return enroll; } /** 获得分页列表 */ async getEnrollList({ search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 page, size, isTotal = true, oldTotal }) { orderBy = orderBy || { 'ENROLL_ORDER': 'asc', 'ENROLL_ADD_TIME': 'desc' }; let fields = 'ENROLL_USER_LIST,ENROLL_JOIN_CNT,ENROLL_OBJ,ENROLL_USER_CNT,ENROLL_TITLE,ENROLL_START,ENROLL_END,ENROLL_ORDER,ENROLL_STATUS,ENROLL_CATE_NAME,ENROLL_OBJ'; let where = {}; where.and = { _pid: this.getProjectId() //简单的查问在此处标注PID }; where.and.ENROLL_STATUS = EnrollModel.STATUS.COMM; // 状态 if (util.isDefined(search) && search) { where.or = [{ ENROLL_TITLE: ['like', search] },]; } else if (sortType && util.isDefined(sortVal)) { // 搜寻菜单 switch (sortType) { case 'cateId': { if (sortVal) where.and.ENROLL_CATE_ID = String(sortVal); break; } case 'sort': { orderBy = this.fmtOrderBySort(sortVal, 'ENROLL_ADD_TIME'); break; } case 'today': { //明天 let day = timeUtil.time('Y-M-D'); where.and.ENROLL_DAYS = day; break; } case 'tomorrow': { //明日 let day = timeUtil.time('Y-M-D', 86400); where.and.ENROLL_DAYS = day; break; } case 'yesterday': { //昨天 let day = timeUtil.time('Y-M-D', -86400); where.and.ENROLL_DAYS = day; break; } case 'month': { //本月 let day = timeUtil.time('Y-M-D'); let start = timeUtil.getMonthFirstTimestamp(day); let end = timeUtil.getMonthLastTimestamp(day); start = timeUtil.timestamp2Time(start, 'Y-M-D'); end = timeUtil.timestamp2Time(end, 'Y-M-D'); where.and.ENROLL_DAYS = ['between', start, end]; break; } } } return await EnrollModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal); } /** 获得我的打卡分页列表 */ async getMyEnrollUserList(userId, { search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 page, size, isTotal = true, oldTotal }) { orderBy = orderBy || { 'ENROLL_USER_ADD_TIME': 'asc' }; let fields = 'ENROLL_USER_LAST_DAY,ENROLL_USER_ENROLL_ID,ENROLL_USER_JOIN_CNT,enroll.ENROLL_TITLE,enroll.ENROLL_OBJ.cover,enroll.ENROLL_USER_CNT,enroll.ENROLL_CATE_NAME,enroll.ENROLL_DAY_CNT,enroll.ENROLL_START,enroll.ENROLL_END,enroll.ENROLL_STATUS'; let where = { ENROLL_USER_MINI_OPENID: userId }; if (util.isDefined(search) && search) { where['enroll.ENROLL_TITLE'] = { $regex: '.*' + search, $options: 'i' }; } else if (sortType) { // 搜寻菜单 let timestamp = this._timestamp; switch (sortType) { case 'stop': { where['enroll.ENROLL_STATUS'] = 0; break; } case 'un': { where['enroll.ENROLL_START'] = ['>', timestamp]; break; } case 'over': { where['enroll.ENROLL_END'] = ['<=', timestamp]; break; } case 'run': { where['enroll.ENROLL_STATUS'] = 1; where['enroll.ENROLL_START'] = ['<=', timestamp]; where['enroll.ENROLL_END'] = ['>', timestamp]; break; } } } let joinParams = { from: EnrollModel.CL, localField: 'ENROLL_USER_ENROLL_ID', foreignField: '_id', as: 'enroll', }; let result = await EnrollUserModel.getListJoin(joinParams, where, fields, orderBy, page, size, isTotal, oldTotal); let list = result.list; for (let k = 0; k < list.length; k++) { let enroll = { ENROLL_START: list[k].enroll.ENROLL_START, ENROLL_END: list[k].enroll.ENROLL_END, ENROLL_STATUS: list[k].enroll.ENROLL_STATUS, } let status = this.getJoinStatusDesc(enroll); if (status == '进行中') { if (list[k].ENROLL_USER_LAST_DAY == timeUtil.time('Y-M-D')) status = '已打卡'; } list[k].status = status; list[k].last = list[k].ENROLL_USER_LAST_DAY.split('-')[1] + '-' + list[k].ENROLL_USER_LAST_DAY.split('-')[2]; } return result; } /** 获得我的打卡清单列表 */ async getMyEnrollJoinList(userId, { enrollId, search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 page, size, isTotal = true, oldTotal }) { orderBy = orderBy || { 'ENROLL_JOIN_ADD_TIME': 'desc' }; let fields = '*'; let where = { ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: enrollId }; return await EnrollJoinModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal); } //################## 打卡 addEnrollUserList(userList, user) { //查问是否存在 并删除 for (let k = 0; k < userList.length; k++) { if (userList[k].id == user.id) userList.splice(k, 1); } userList.unshift(user); // 判断个数, 多的删除 if (userList.length > 3) userList.splice(userList.length - 1, 1); return userList; } // 打卡 async enrollJoin(userId, enrollId, forms) { let user = await UserModel.getOne({ USER_MINI_OPENID: userId, USER_STATUS: UserModel.STATUS.COMM }); if (!user) this.AppError('用户不存在'); // 打卡是否完结 let whereEnroll = { _id: enrollId, ENROLL_STATUS: EnrollModel.STATUS.COMM } let enroll = await EnrollModel.getOne(whereEnroll); if (!enroll) this.AppError('该打卡流动不存在或者曾经进行'); // 是否打卡开始 if (enroll.ENROLL_START > this._timestamp) this.AppError('该打卡流动尚未开始'); // 是否过了打卡完结期 if (enroll.ENROLL_END < this._timestamp) this.AppError('该打卡流动曾经完结'); let day = timeUtil.time('Y-M-D'); // 本人今日是否曾经有打卡 let whereMy = { ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_DAY: day, ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC } let my = await EnrollJoinModel.getOne(whereMy); if (my) { this.AppError('您今日已打卡,毋庸反复打卡'); } // 入库 let data = { ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC, ENROLL_JOIN_DAY: day, ENROLL_JOIN_FORMS: forms } let enrollJoinId = await EnrollJoinModel.insert(data); // 统计数量 this.statEnrollJoin(enrollId, userId); // 更新用户头像 let userList = enroll.ENROLL_USER_LIST; userList = this.addEnrollUserList(userList, { pic: user.USER_PIC, id: userId, name: user.USER_NAME }); EnrollModel.edit(enrollId, { ENROLL_USER_LIST: userList }); return { enrollJoinId } } // 统计 async statEnrollJoin(enrollId, userId = '', del = false) { // 总体统计 let where = { ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC } let joinCnt = await EnrollJoinModel.count(where); let userCnt = await EnrollJoinModel.distinctCnt(where, 'ENROLL_JOIN_USER_ID'); let data = { ENROLL_JOIN_CNT: joinCnt, ENROLL_USER_CNT: userCnt, } await EnrollModel.edit(enrollId, data); // 用户统计 if (!userId) return; where = { ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC } let userJoinCnt = await EnrollJoinModel.count(where); let enrollUserData = {}; enrollUserData.ENROLL_USER_LAST_DAY = timeUtil.time('Y-M-D'); enrollUserData.ENROLL_USER_JOIN_CNT = userJoinCnt; enrollUserData.ENROLL_USER_DAY_CNT = userJoinCnt; where = { ENROLL_USER_MINI_OPENID: userId, ENROLL_USER_ENROLL_ID: enrollId }; await EnrollUserModel.insertOrUpdate(where, enrollUserData); if (del) { //删除打卡记录,则更新最近打卡工夫 let last = ''; where = { ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC } let lastModel = await EnrollJoinModel.getOne(where, 'ENROLL_JOIN_DAY', { 'ENROLL_JOIN_ADD_TIME': 'desc' }); if (lastModel) last = lastModel.ENROLL_JOIN_DAY; where = { ENROLL_USER_MINI_OPENID: userId, ENROLL_USER_ENROLL_ID: enrollId }; await EnrollUserModel.edit(where, { ENROLL_USER_LAST_DAY: last }); } }}UI设计 ...

June 13, 2023 · 6 min · jiezi

关于小程序:小程序项目结构与组件基础

文章和代码曾经归档至【Github仓库:https://github.com/timerring/front-end-tutorial 】或者公众号【AIShareLab】回复 小程序 也可获取。我的项目构造理解我的项目的根本组成构造 pages 用来寄存所有小程序的页面utils 用来寄存工具性质的模块(例如:格式化工夫的自定义模块)app.js 小程序我的项目的入口文件app.json 小程序我的项目的全局配置文件app.wxss 小程序我的项目的全局款式文件project.config.json 我的项目的配置文件sitemap.json 用来配置小程序及其页面是否容许被微信索引小程序页面的组成部分小程序官网倡议把所有小程序的页面,都寄存在 pages 目录 中,以独自的文件夹存在,如图所示: 其中,每个页面由 4 个根本文件 组成,它们别离是: .js 文件(页面的脚本文件,寄存页面的数据、事件处理函数等).json 文件(以后页面的配置文件,配置窗口的外观、体现等).wxml 文件(页面的模板构造文件).wxss 文件(以后页面的样式表文件)json配置文件的作用json是一种数据格式,在理论开发中,json总是以 配置文件的模式呈现。小程序我的项目中也不例外:通过不同的.json配置文件,能够对小程序我的项目进行不同级别的配置。 小程序我的项目中有4种json配置文件,别离是: 我的项目根目录的app.json配置文件;我的项目根目录中的project.config.json配置文件;我的项目根目录中的sitemap.json配置文件;每个页面文件夹中的.json配置文件全局配置文件app.jsonapp.json是以后小程序的全局配置 ,包含了小程序的所有页面门路 、窗口外观、界面体现 、底部 tab 等。 app.json 中的局部配置,也反对对单个页面进行配置,能够在页面对应的 .json 文件来对本页面的体现进行配置。页面中配置项在以后页面会笼罩 app.json 中雷同的配置项。 { "pages":[ "pages/index/index", "pages/logs/logs" ], "window":{ "backgroundTextStyle":"light", //加载小圆圈的色彩 "navigationBarBackgroundColor": "#fff", //导航栏背景色彩 "navigationBarTitleText": "Weixin", //导航栏的文本内容 "navigationBarTextStyle":"black" //导航栏题目色彩,仅反对 black / white }, "style": "v2", "sitemapLocation": "sitemap.json"}这 4 个配置项的作用: pages :用来记录以后小程序所有页面的门路 未指定 entryPagePath 时,数组的第一项代表小程序的初始页面(首页)。 ...

June 8, 2023 · 3 min · jiezi

关于小程序:体验微信问一问的新时代功能

hello,搭档们,我是索奇置信很多搭档们曾经体验了【微信问一问】的新性能但也有一些搭档们还不晓得如何开启应用,当初并不是所谓的仅内测可用(互联网上很多人说搜一搜都说是内测,一跟十,十跟百,不如本人摸索验证一下,目前是否仅内测可用)两种办法开启问一问能够通过「问一问」种子用户招募进行投递 https://doc.weixin.qq.com/forms/AJEAIQdfAAoAdcAIgYqADkPgBep3j...这种办法须要期待,期待审核,会有点慢另外一种办法就是间接去问一问社区,这种办法须要敌人邀请,刚刚试了一下不能复制分享链接,只可能分享敌人或者分享朋友圈这两种形式(须要在手机端,目前PC端被邀请也不能关上链接) 一键开启 : https://mp.weixin.qq.com/s/nAivqs1AuQ5rxYn9cifowg

June 8, 2023 · 1 min · jiezi

关于小程序:从0到1活动报名小程序开发笔记

背景在日常生活中,大家也常常有组织流动,比方体育、才艺较量报名,户外、聚餐、出游报名,休闲小聚,会议报名,守业团聚,校友团聚,公益活动,培训报名等需要。如果一个个收集就十分费时间和人力老本,这个时候只须要一款在线报名小程序就能够疾速搞定,报名、签到、流动收集零打碎敲! 概要设计包含布告告诉,流动分类,流动列表,流动报名,流动评估,我的流动报名,后盾流动项目管理,后盾报名记录治理,后盾报名审核,后盾报名数据导出等性能,组织方能够自定义要填写的内容,比方姓名、性别、年龄,身份证、手机号等 数据库设计ActivityJoinModel.DB_STRUCTURE = { _pid: 'string|true', ACTIVITY_JOIN_ID: 'string|true', ACTIVITY_JOIN_ACTIVITY_ID: 'string|true|comment=报名PK', ACTIVITY_JOIN_IS_ADMIN: 'int|true|default=0|comment=是否管理员增加 0/1', ACTIVITY_JOIN_CODE: 'string|true|comment=核验码15位', ACTIVITY_JOIN_IS_CHECKIN: 'int|true|default=0|comment=是否签到 0/1 ', ACTIVITY_JOIN_CHECKIN_TIME: 'int|false|default=0|签到工夫', ACTIVITY_JOIN_USER_ID: 'string|true|comment=用户ID', ACTIVITY_JOIN_FORMS: 'array|true|default=[]|comment=表单', ACTIVITY_JOIN_OBJ: 'object|true|default={}', ACTIVITY_JOIN_STATUS: 'int|true|default=1|comment=状态 0=待审核 1=报名胜利, 99=审核未过', ACTIVITY_JOIN_REASON: 'string|false|comment=审核回绝或者勾销理由', ACTIVITY_JOIN_ADD_TIME: 'int|true', ACTIVITY_JOIN_EDIT_TIME: 'int|true', ACTIVITY_JOIN_ADD_IP: 'string|false', ACTIVITY_JOIN_EDIT_IP: 'string|false',};外围实现async statActivityJoin(id) { let where = { ACTIVITY_JOIN_ACTIVITY_ID: id, ACTIVITY_JOIN_STATUS: ['in', [ActivityJoinModel.STATUS.WAIT, ActivityJoinModel.STATUS.SUCC]] } let cnt = await ActivityJoinModel.count(where); where = { ACTIVITY_JOIN_ACTIVITY_ID: id, ACTIVITY_JOIN_STATUS: ActivityJoinModel.STATUS.SUCC } let joinParams = { from: UserModel.CL, localField: 'ACTIVITY_JOIN_USER_ID', foreignField: 'USER_MINI_OPENID', as: 'user', }; let orderBy = { ACTIVITY_JOIN_ADD_TIME: 'desc' } let list = await ActivityJoinModel.getListJoin(joinParams, where, 'ACTIVITY_JOIN_ADD_TIME,user.USER_MINI_OPENID,user.USER_NAME,user.USER_PIC', orderBy, 1, 6, false, 0); list = list.list; for (let k = 0; k < list.length; k++) { list[k] = list[k].user; } await ActivityModel.edit(id, { ACTIVITY_JOIN_CNT: cnt, ACTIVITY_USER_LIST: list });}/** 报名前获取要害信息 */async detailForActivityJoin(userId, activityId) { let fields = 'ACTIVITY_JOIN_FORMS, ACTIVITY_TITLE'; let where = { _id: activityId, ACTIVITY_STATUS: ActivityModel.STATUS.COMM } let activity = await ActivityModel.getOne(where, fields); if (!activity) this.AppError('该流动不存在'); // 取出自己最近一次的填写表单 let whereMy = { ACTIVITY_JOIN_USER_ID: userId, } let orderByMy = { ACTIVITY_JOIN_ADD_TIME: 'desc' } let joinMy = await ActivityJoinModel.getOne(whereMy, 'ACTIVITY_JOIN_FORMS', orderByMy); let myForms = joinMy ? joinMy.ACTIVITY_JOIN_FORMS : []; activity.myForms = myForms; return activity;}/** 勾销我的报名 只有胜利和待审核能够勾销 勾销即为删除记录 */async cancelMyActivityJoin(userId, activityJoinId) { let where = { ACTIVITY_JOIN_USER_ID: userId, _id: activityJoinId, ACTIVITY_JOIN_STATUS: ['in', [ActivityJoinModel.STATUS.WAIT, ActivityJoinModel.STATUS.SUCC]] }; let activityJoin = await ActivityJoinModel.getOne(where); if (!activityJoin) { this.AppError('未找到可勾销的报名记录'); } if (activityJoin.ACTIVITY_JOIN_IS_CHECKIN == 1) this.AppError('该流动曾经签到,无奈勾销'); let activity = await ActivityModel.getOne(activityJoin.ACTIVITY_JOIN_ACTIVITY_ID); if (!activity) this.AppError('该流动不存在'); if (activity.ACTIVITY_END <= this._timestamp) this.AppError('该流动曾经完结,无奈勾销'); if (activity.ACTIVITY_CANCEL_SET == 0) this.AppError('该流动不能取消'); if (activity.ACTIVITY_CANCEL_SET == 2 && activity.ACTIVITY_STOP < this._timestamp) this.AppError('该流动曾经截止报名,不能取消'); await ActivityJoinModel.del(where); // 统计 await this.statActivityJoin(activityJoin.ACTIVITY_JOIN_ACTIVITY_ID);}UI设计 ...

June 4, 2023 · 2 min · jiezi

关于小程序:C端用户体验度量实战篇京东快递小程序体验度量全面升级-京东云技术团队

本文通过介绍体验度量模型降级钻研过程、钻研办法及钻研后果等内容,结合实际C端产品利用,观测新模型运行周期的体现,验证了其在高速倒退的业务状态和日益变动的用户需要上的适用性和有效性。咱们从体验价值为导向的底层模型设计,到主客观体验影响因子在理论业务使用的办法,摸索出一套切实可行的验证设计价值的体系。通过对体验度量模型一直地调优,不仅可能诊断出过往产品策略和口头是否对用户无效,而且可能前瞻性的预测出将来的体验走势。 一、背景本次用户体验度量模型3.0是在2.0度量模型根底上进行的全新降级。如果说体验度量模型2.0是让团队共识了体验须要“迷信”度量这件事,那么这次体验度量模型3.0则要求模型验证体验的"价值"。 在降级前咱们始终在思考这样的问题,如何让度量模型可能更实用于疾速倒退的业务以及一直变动的用户,可能预判出将来体验趋势。 咱们将此次降级体验度量模型的内容残缺的分享给正在搭建度量模型或者是想要降级度量模型的设计团队,心愿能给大家带来更多的启发。 二、现状问题过来一段时间里,体验度量模型2.0的内容普适性很好,在物流各个系统运行失常。但因为各条业务线倒退不对立,体验度量模型2.0度量进去的内容与日益倒退的C端业务零碎产生不匹配的状况。为了进一步确认问题,筹备后期咱们通盘对度量模型利用在客户端上体验的问题和倡议进行收集。次要波及三个方面问题: 视角繁多,问题不聚焦:原先度量模型业务参与度不高,缺失对指标深刻理解;加上业务高速倒退,旧的指标领导理论业务价值不高,导致产品和业务的人员关注度不高;而度量进去的内容又无奈聚焦问题。度量值无基准线参考,分数差别不显著:模型自身度量值无基线值参考,也没有对标值,对以后产品达成好坏状况比拟含糊。另外,体验分数档位差距不显著,尤其是10分值小数点后的变动感知度不强,很难直观看出问题所在。短少行业视角,规范不明确:对产品所处的行业状况存疑,长期以往则会陷入自我感觉良好而没有实在反映产品竞争力的状况。基于此,本次模型降级围绕解决问题不聚焦视角繁多、度量值无基准参考、度量规范不明确等问题进行。 三、钻研指标和方向依据现有问题找差距,根据差距确立口头指标。 更聚焦问题。确定钻研框架,重构钻研流程。相较于度量模型2.0,在公司策略“自上而下”视角中业务须要看什么之外,减少“自下而上”可感知的用户视角。更突显比照。丰盛指标,优化度量形式。拆解业现有业务指标,丰盛主、主观指标库,严选每个指标及确定各指标基线值和目标值。更看清差距。优化、引入其余比照维度。从外部本人与本人比变为与内部行业垂类TOP1比。本次度量模型降级以C端产品为终点,明确度量模型价值,作为过程治理的工具,补救零碎层细节体验缺失问题,疾速帮忙业务、产品、体验进行决策,达到青出于蓝而胜于蓝的成果。 四、钻研框架和过程 在确定口头指标的指引下也确定本次降级次要从四方面进行:维度确定、权重确定、指标确定、度量值确定。 4.1 模型框架度量模型共五层,第一层为度量分数——体验总分;第二层为权重层,蕴含主观、主观权重;第三层为主主观对应的维度层;第四层则是对应维度下指标层;第五层则是具体指标赋分状况。 4.2 维度钻研4.2.1 维度钻研办法及过程介绍本次降级对维度钻研办法上做了优化。一方面从公司视角“自上而下”,专家意见作为参考深度绑定,对度量模型从新进行打乱和重排。另一方面从用户可感知的“自下而上”登程,联合定性和定量钻研,进行用户访谈、从新绘制用户旅程图,进而用因子分析办法确定指标维度。确立好的钻研办法之后咱们开始重构维度钻研。 搭建维度库:在维度钻研后期对行业内体验度量维度内容进行了剖析和整顿,取并集进行总结,搭建出一套残缺的维度库。组建专家组,专家访谈:基于三大职能六个岗位选出资深9位专家成立了专家小组。通过一对一深访确定专家诉求以及将来预期,明确快递小程序体验度量的关注重点及维度。探讨验证确定维度:本着MECE准则(互相独立,齐全穷尽准则)、可度量、可晋升三个规范进行维度确定。期间,依据专家组给出的度量后果与维度库后果进行匹配,也是将实践与理论进行联合后输入3套可行计划。咱们对每一套计划劣势和劣势进行了充沛探讨,在经验6轮探讨后最终确定维度计划。 4.2.2 维度钻研后果最终咱们失去了性能体验、性能体验、易用体验、情感体验四个维度 性能体验:性能是否欠缺,根底性能笼罩以及蕴含用户用意辨认的定制化性能性能体验:产品根底性能、稳定性体现易用体验:易操作、易学、易查找、清晰可见情感体验:蕴含满意度、忠诚度、举荐度,蕴含用户抉择产品的起因这四个维度基于产品零碎自身,从有用的根底的性能体验至卓越的性能体验,直到成为好用的易用体验升华至用户爱用的情感体验。 从最终确定的维度后果上看,相较于之前,维度的内容范畴更明确更易懂,最重要的是各方达成对立共识,这一点对于前期度量进去的内容受各方高度关注起到了关键性的作用。 4.3 各维度权重钻研4.3.1 主客观权重、主观各维度权重钻研办法维度确定后,接着就须要对主观权重、主观权重进行确定,以及各维度权重系数进行确认。主客观的权重采纳的是AHP档次分析法。具体的定义可参考上面词条的内容,咱们重点介绍如何应用的 “AHP档次分析法是一种将定性与定量分析办法相结合的多指标决策分析办法 。该办法的次要思维是通过将简单问题合成为若干档次和若干因素, 对两两指标之间的重要水平作出比拟判断, 建设判断矩阵, 通过计算判断矩阵的最大特征值以及对应特征向量,就可得出不同计划重要性水平的权重, 为最佳计划的抉择提供根据。”——引自百度百科 首先建设层次结构模型,其次通过专家重要性比拟打分,最终通过软件剖析效验计算得出权重系数。 建设层次结构模型:将零碎体验度量合成为维度,依照因素间的互相关联影响以及附属关系将因素按不同的档次汇集组合,造成一个多层次的剖析构造模型。例如体验度量分主、主观维度,而主观维度下又是由性能、易用、性能、情感四个因素形成。构建好层次模型后就能够将所有因素放在一起进行两两比拟了。专家重要性比拟:组建的9名职能专家组别离对主观维度及主观维度的绝对重要性进行了评估。软件剖析效验:依照专家评估后果,通过软件yaahp计算出各维度权重系数。最终专家组针对后果进行探讨,确定权重系数。 通过这样的办法,咱们同时确定了主客观权重,以及主观各维度的权重系数。这次主客观权重相较于之前是有变动的,而这种变动的根本原因在于,自上而下对现有产品清晰定位及最终目标导向的后果,能够说是团队共识之后,致力做好用户体验信心的一种体现。另外,主观各维度的权重也会随着产品的倒退阶段而进行调整。 4.3.2 主观各维度权重确定与主观维度确定不同,主观各维度权重的确定采纳的是因子分析法(Factor Analysis)。它是一种数据简化的办法,次要用于对一组数据较多而且互相关联的变量进行提炼与概括。因子分析的目标是以尽可能是少的信息损失,把大量互相关联的变量稀释为少数几个因子,便于对数据的了解和进一步的统计分析。 如果说档次分析法输入的专家组认可的维度,那因子分析取得则是用户可感知到维度。因子分析最难的局部是因子后果能够与档次分析法失去的维度匹配上,在这个阶段中可能须要一直的调整量表、剖析后果、测验到再调整、再剖析、再测验。因子分析是本次模型降级最大的亮点,它不仅解决旧模型可信度的问题,更重要的是帮忙咱们看清从用户感知层面评估进去的维度以及对应的权重调配,为前期体验问题的聚焦及决策上提供了撑持根据。 4.4 指标钻研4.4.1 主观指标钻研在主观各维度钻研的时候提到形成主观各维度的主观指标,主观指标钻研分为两步,先搭建主观指标库,在筛选指标。因为主观指标库是在原有根底上进行的,本次次要从细化指标和裁减维度进行。一方面是依照用户视角,对用户旅程阶段的触点进行细化,另一方面依据业务视角,通过业务的指标拆解进行指标裁减。当有这些指标后,以满意度的形式回收用户反馈,继而对问卷后果进行因子分析,确定最终对整体分数的贡献度状况。 4.4.2 主观指标钻研在主观指标钻研上也是先搭建主观指标库,再进行主观指标筛选。主观指标库搭建的准则:业务指标导向、数据品质、产研侧专家评估。在搭建主观指标库时,首要是强绑定业务指标导向,纳入指标库的指标要与业务指标关联严密。其次指标数据的品质要实在、主观,观测一个好的指标要看过往数据反映问题的状况以及无效的领导一线业务口头。最初也须要产研侧专家筛选最贴近产品理论和指标的主观指标。基于这样三层准则咱们搭建出快递小程序主观指标库。在进行主观指标筛选过程中确定筛选指标的四个规范:可掂量用户价值、反映产品策略、指标直观可拆解、与营收相干的先导性指标,最终确定每个维度下的主观指标。当然,过程中也有发现指标利用价值高但数据统计口径有出入的,以及现有指标不满足需要的额定须要新设计指标的状况。 4.5 度量值钻研4.5.1 主观赋分度量值简略了解就是赋分,主观分数是通过因子分析中用户打分的后果得出分数。 4.5.2 主观赋分度量模型2.0主观指标赋分采纳的是分箱法,选取过来一段时间的数据,查看其最小值、最大值及平均值、中位数的散布状况,进而设定本身的主观评分标准。这种根据数据等频进行的划档赋分,理论得出的分数不够敏锐,看不出来每个指标数据变动的状况。另外,主观赋分延用主观用户打分的非常值,因为之前没有基准线和目标值的比照,加权之后的分数难以直观的裸露问题。这会导致大家容易疏忽实在的体验问题。新模型赋分则采纳了区间映射法。简略了解,当期要测量值在度量规范区间内实现的状况。咱们也是在比照多种赋分办法后发现该种赋分形式最直观、清晰反映数据变动状况。 采纳该种赋分形式须要留神两个方面内容。 数据分布要合乎正态分布特色:在咱们选取的指标中,大部分的数据间接出现正态分布特色,显著性测验p值大于0.05。而小局部的数据并未出现这种特色,须要进行数据特定函数关系转化使其出现正态分布特色。度量值范畴选取2个标准差:咱们选取2个标准差的起因一方面是根据正态分布特色,95.45%的数据是在2个标准差范畴内,另一方面也是结合实际状况尤其是历史数据变动的笼罩无余,既不好高骛远也能捕风捉影。以上是咱们降级模型的全过程,那么最初咱们介绍下降级后的度量模型在理论产品运行的状况。 五、小结最初,通过一张全景图咱们回顾下度量模型降级的内容。比照旧模型,新的模型在分数映射上更加敏锐,减少双面感知评估框架更迷信,丰盛后的指标库对问题的洞察更聚焦。 降级后的度量模型在C端产品上曾经运行近一年了,它以全新的视角让咱们看到了实在的业务倒退的状况。在大环境的变动、业务的变动、用户需要变动下,度量进去的内容第一工夫能让咱们观测到这种变动。既而咱们可能无效的抓住工夫窗口期,迅速做了响应的策略进行体验改良落地。 作者:京东物流 穆倩雯 起源:京东云开发者社区

May 31, 2023 · 1 min · jiezi

关于小程序:京东小程序折叠屏适配探索-京东云技术团队

前言随着近年来手机行业的飞速发展,手机从性能机进入到智能机,手机屏幕占比也随着技术和零碎的提高越来越大,特地是Android 10推出当前,折叠屏逐步成为Android手机倒退的趋势。 图 1 Android手机屏幕发展趋势 京东小程序近年来也反对了越来越多的业务和利用,做好小程序的折叠屏的适配也是合乎将来的发展趋势,能为用户和业务方提供更好的体验和价值。 Android利用折叠屏适配摘要利用在折叠屏运行时,能够从一个屏幕切换到另一个屏幕。利用应该做好配置变更的适配和界面状态的保留,以保障利用当前任务能无缝迁徙到转换后的屏幕,从而为用户提供杰出的连续性体验。 1.resizeableActivity默认状况下,Activity resizableActivity 属性为 true,零碎假设该利用齐全反对多窗口并且可调整大小。 图 2 Android手机折叠屏 如果您不心愿本人的利用在多窗口模式下调整大小,你能够设置Activity resizableActivity 属性为false,零碎会将利用置于兼容模式。某些原始设施制造商 (OEM) 可能会施行一项性能,即每当 Activity 的显示区域产生更改时,都会在屏幕上增加一个小型重启图标。这为用户提供了在新配置中重启 Activity 的机会。下图示例展现了一次内屏到外屏,外屏到内屏切换中零碎相干解决。 图 3 折叠屏利用重启示例 此外,用户须要“设置”-“显示”中关上利用的“在外屏上持续应用应用程序”开关,否则,切换到外屏时零碎将回到锁屏界面,利用会被压至后盾。不反对resize的利用会无奈关上此开关。 图 4 Android折叠屏展现开关 2.屏幕宽高比Android 10 (API 级别 29) 或更高版本 反对更多种宽高比。对于可折叠设施而言,设施类型能够是超长、超薄的屏幕(例如屏幕宽高比为 21:9 的折叠设施),也能够是 1:1 的屏幕。 如要与尽可能多的设施兼容,您应该尽量多针对以下屏幕宽高比测试本人的利用: 图 5 Android手机屏幕宽高比 如果无奈反对上述某些高宽比,您能够应用 maxAspectRatio(同之前一样)以及 minAspectRatio 来指明本人利用能够解决的最高宽高比和最低宽高比。如果屏幕宽高比超出这些限度,利用可能会进入兼容模式。 3.解决配置变更某些设施配置可能会在运行时发生变化(例如屏幕方向、键盘可用性,以及当用户启用多窗口模式时)。产生这种变动时,Android 会重启正在运行的 Activity(先后调用 onDestroy() 和 onCreate())。重启行为旨在通过利用与新设施配置相匹配的备用资源来主动从新加载您的利用,从而帮忙它适应新配置。 如要妥善处理重启行为,Activity 必须复原其先前的状态。您能够同时应用 onSaveInstanceState()、ViewModel 对象以及长久存储,以在配置变更时保留并复原 Activity 的界面状态。 然而,您可能会遇到这种状况:重启利用并复原大量数据不仅老本昂扬,而且会造成蹩脚的用户体验。在此状况下,咱们通常能够自行处理配置变更,以防止系统资源变更引起Activity重启,通过在标签中增加android:configChanges申明实现。android:configChanges 属性文档中列出该属性的可能值。最罕用的值包含 "orientation"、"screenSize" 和 "keyboardHidden” 等。 ...

May 8, 2023 · 1 min · jiezi

关于小程序:从0到100小区物业报修小程序开发笔记

背景本来遇到须要培修问题时,业主须要先拨通物业客服电话,告知培修事项,再由客服调配培修员上门培修。现在,培修人员可在小程序上第一工夫收知业主反馈的信息,实现报修、接单的无缝对接,省去了原有物业客服接单、派单的简约流程。 功能模块小程序分为“服务分类”、“报事报修”、“物业告诉”、“我的工单”四个板块。 业主能够通过“报事报修”进行线上报修,物业方则可在“治理后盾”上接单、调配外部工作等,极大地缩短为楼宇、居民区业主服务的中间环节,进步上门服务的响应速度和及时率 。 本我的项目前后端残缺代码包含布告告诉,报修记录,我的工单,物业告诉,后盾报修治理与处理,报修记录导出,后盾用户治理,后盾报修记录导出等性能 数据字段设计TaskModel.DB_STRUCTURE = { _pid: 'string|true', TASK_ID: 'string|true', TASK_USER_ID: 'string|true|comment=用户ID', TASK_STATUS: 'int|true|default=0|comment=状态 0=待处理,1=解决中 9=已办结', TASK_FORMS: 'array|true|default=[]', TASK_OBJ: 'object|true|default={}', TASK_LAST_TIME: 'int|true|default=0', TASK_ADD_TIME: 'int|true', TASK_EDIT_TIME: 'int|true', TASK_ADD_IP: 'string|false', TASK_EDIT_IP: 'string|false',};UserModel.DB_STRUCTURE = { _pid: 'string|true', USER_ID: 'string|true', USER_MINI_OPENID: 'string|true|comment=小程序openid', USER_STATUS: 'int|true|default=1|comment=状态 0=待审核,1=失常,8=审核未过,9=禁用', USER_CHECK_REASON: 'string|false|comment=审核未过的理由', USER_NAME: 'string|false|comment=用户昵称', USER_MOBILE: 'string|false|comment=联系电话', USER_FORMS: 'array|true|default=[]', USER_OBJ: 'object|true|default={}', USER_LOGIN_CNT: 'int|true|default=0|comment=登陆次数', USER_LOGIN_TIME: 'int|false|comment=最近登录工夫', USER_ADD_TIME: 'int|true', USER_ADD_IP: 'string|false', USER_EDIT_TIME: 'int|true', USER_EDIT_IP: 'string|false',}外围实现async getTaskCountByType(userId) { let status0Cnt = await TaskModel.count({ TASK_STATUS: 0, TASK_USER_ID: userId }); let status1Cnt = await TaskModel.count({ TASK_STATUS: 1, TASK_USER_ID: userId }); let status2Cnt = await TaskModel.count({ TASK_STATUS: 2, TASK_USER_ID: userId }); let task = { status0Cnt, status1Cnt, status2Cnt } return task; } async getTaskDetail(userId, id, isAdmin = false) { let where = { _id: id } if (!isAdmin) where.TASK_USER_ID = userId; return await TaskModel.getOne(where); } /**增加 */ async insertTask(userId, { forms }) { // 赋值 let data = {}; data.TASK_USER_ID = userId; data.TASK_OBJ = dataUtil.dbForms2Obj(forms); data.TASK_FORMS = forms; let id = await TaskModel.insert(data); return { id }; } /**批改 */ async editTask(userId, { id, forms }) { // 异步解决 新旧文件 let oldForms = await TaskModel.getOneField(id, 'TASK_FORMS'); if (!oldForms) return; cloudUtil.handlerCloudFilesForForms(oldForms, forms); // 赋值 let data = {}; data.TASK_USER_ID = userId; data.TASK_OBJ = dataUtil.dbForms2Obj(forms); data.TASK_FORMS = forms; await TaskModel.edit(id, data); } // 更新forms信息 async updateTaskForms({ id, hasImageForms }) { await TaskModel.editForms(id, 'TASK_FORMS', 'TASK_OBJ', hasImageForms); } /**删除数据 */ async delTask(userId, id, isAdmin) { let where = { _id: id } if (!isAdmin) where.TASK_USER_ID = userId; // 异步解决 新旧文件 let task = await TaskModel.getOne(id, 'TASK_FORMS'); if (!task) return; cloudUtil.handlerCloudFilesForForms(task.TASK_FORMS, []); await TaskModel.del(where); } /** 获得我的 */ async getMyTaskList(userId, { search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 page, size, isTotal = true, oldTotal }) { orderBy = orderBy || { 'TASK_ADD_TIME': 'desc' }; let fields = '*'; let where = {}; where.and = { _pid: this.getProjectId(), //简单的查问在此处标注PID TASK_USER_ID: userId }; if (util.isDefined(search) && search) { where.or = [{ ['TASK_OBJ.title']: ['like', search] }]; } else if (sortType && sortVal !== '') { // 搜寻菜单 switch (sortType) { case 'level': { where.and['TASK_OBJ.level'] = sortVal; break; } case 'type': { where.and['TASK_OBJ.type'] = sortVal; break; } case 'status': { where.and.TASK_STATUS = Number(sortVal); break; } case 'sort': { orderBy = this.fmtOrderBySort(sortVal, 'TASK_ADD_TIME'); break; } } } let result = await TaskModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal); return result; }业主端 UI ...

May 4, 2023 · 2 min · jiezi

关于小程序:从0开始活动打卡小程序开发笔记

概要设计打卡是一种习惯的养成,是当下最风行、最受欢迎的工具,利用塌景宽泛多样;各个人为了促活会定期发展一些闯关打卡流动;找一群气味相投的人,一起去打卡 功能定位:集学习、趣味、生存、静止于一身的打卡小程序用户群:面向学校学生、学生家长、老师、各种趣味个人(跑步,静止,体育,艺术等)次要模块:打卡我的项目列表,打卡排行,每日动静,后盾打卡项目管理,后盾打卡记录治理,后盾打卡记录导出等性能性能布局 数据字典EnrollModel.DB_STRUCTURE = { _pid: 'string|true', ENROLL_ID: 'string|true', ENROLL_TITLE: 'string|true|comment=题目', ENROLL_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=应用中', ENROLL_CATE_ID: 'string|true|default=0|comment=分类', ENROLL_CATE_NAME: 'string|false|comment=分类冗余', ENROLL_START: 'int|false|comment=开始工夫', ENROLL_END: 'int|false|comment=完结工夫', ENROLL_DAY_CNT: 'int|false|comment=继续天数', ENROLL_ORDER: 'int|true|default=9999', ENROLL_VOUCH: 'int|true|default=0', ENROLL_FORMS: 'array|true|default=[]', ENROLL_OBJ: 'object|true|default={}', ENROLL_JOIN_FORMS: 'array|true|default=[]', ENROLL_QR: 'string|false', ENROLL_VIEW_CNT: 'int|true|default=0', ENROLL_JOIN_CNT: 'int|true|default=0', ENROLL_USER_CNT: 'int|true|default=0', ENROLL_USER_LIST: 'array|true|default=[]|comment={name,id,pic}', ENROLL_ADD_TIME: 'int|true', ENROLL_EDIT_TIME: 'int|true', ENROLL_ADD_IP: 'string|false', ENROLL_EDIT_IP: 'string|false',};EnrollJoinModel.DB_STRUCTURE = { _pid: 'string|true', ENROLL_JOIN_ID: 'string|true', ENROLL_JOIN_ENROLL_ID: 'string|true|comment=打卡PK', ENROLL_JOIN_USER_ID: 'string|true|comment=用户ID', ENROLL_JOIN_DAY: 'string|true|comment=日期', ENROLL_JOIN_FORMS: 'array|true|default=[]|comment=表单', ENROLL_JOIN_STATUS: 'int|true|default=1|comment=状态 1=胜利', ENROLL_JOIN_ADD_TIME: 'int|true', ENROLL_JOIN_EDIT_TIME: 'int|true', ENROLL_JOIN_ADD_IP: 'string|false', ENROLL_JOIN_EDIT_IP: 'string|false',};外围难点 // 获取以后打卡状态 getJoinStatusDesc(enroll) { let timestamp = this._timestamp; if (enroll.ENROLL_STATUS == 0) return '已进行'; else if (enroll.ENROLL_START > timestamp) return '未开始'; else if (enroll.ENROLL_END <= timestamp) return '已完结'; else return '进行中'; } // 获取某日动静 async getEnrollJoinByDay(enrollId, day = '') { if (!day) day = timeUtil.time('Y-M-D'); let where = { ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_DAY: day, ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC } let joinParams = { from: UserModel.CL, localField: 'ENROLL_JOIN_USER_ID', foreignField: 'USER_MINI_OPENID', as: 'user', }; let orderBy = { ENROLL_JOIN_ADD_TIME: 'desc' } let list = await EnrollJoinModel.getListJoin(joinParams, where, 'user.USER_NAME,user.USER_PIC', orderBy, 1, 100, false, 0); return list.list; } // 获取某流动排行 async getEnrollUserRank(enrollId) { let where = { ENROLL_USER_ENROLL_ID: enrollId } let joinParams = { from: UserModel.CL, localField: 'ENROLL_USER_MINI_OPENID', foreignField: 'USER_MINI_OPENID', as: 'user', }; let orderBy = { ENROLL_USER_JOIN_CNT: 'desc' } let fields = 'ENROLL_USER_JOIN_CNT,ENROLL_USER_LAST_DAY,user.USER_NAME,user.USER_PIC'; let list = await EnrollUserModel.getListJoin(joinParams, where, fields, orderBy, 1, 100, false, 0); return list.list; } /** 浏览信息 */ async viewEnroll(userId, id) { let fields = '*'; let where = { _id: id, ENROLL_STATUS: EnrollModel.STATUS.COMM } let enroll = await EnrollModel.getOne(where, fields); if (!enroll) return null; EnrollModel.inc(id, 'ENROLL_VIEW_CNT', 1); // 判断用户今日是否有打卡 let whereJoin = { ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: id, ENROLL_JOIN_DAY: timeUtil.time('Y-M-D'), ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.SUCC } let enrollJoin = await EnrollJoinModel.getOne(whereJoin); if (enrollJoin) { enroll.myEnrollJoinId = enrollJoin._id; } else { enroll.myEnrollJoinId = ''; } // 某日打卡列表 enroll.activity = await this.getEnrollJoinByDay(id); // 打卡日期数组 let dayList = []; let start = timeUtil.timestamp2Time(enroll.ENROLL_START, 'Y-M-D'); start = timeUtil.time2Timestamp(start); let today = timeUtil.time2Timestamp(timeUtil.time('Y-M-D')); for (let k = start; k <= today;) { let month = timeUtil.timestamp2Time(k, 'M月'); if (month.startsWith('0')) month = month.substring(1); let date = timeUtil.timestamp2Time(k, 'D'); let day = timeUtil.timestamp2Time(k, 'Y-M-D'); dayList.push({ month, date, day }); k = k + 86400 * 1000; } enroll.dayList = dayList; // 排行榜 let rankList = await this.getEnrollUserRank(id); enroll.rankList = rankList; return enroll; } /** 获得分页列表 */ async getEnrollList({ search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 page, size, isTotal = true, oldTotal }) { orderBy = orderBy || { 'ENROLL_ORDER': 'asc', 'ENROLL_ADD_TIME': 'desc' }; let fields = 'ENROLL_USER_LIST,ENROLL_JOIN_CNT,ENROLL_OBJ,ENROLL_USER_CNT,ENROLL_TITLE,ENROLL_START,ENROLL_END,ENROLL_ORDER,ENROLL_STATUS,ENROLL_CATE_NAME,ENROLL_OBJ'; let where = {}; where.and = { _pid: this.getProjectId() //简单的查问在此处标注PID }; where.and.ENROLL_STATUS = EnrollModel.STATUS.COMM; // 状态 if (util.isDefined(search) && search) { where.or = [{ ENROLL_TITLE: ['like', search] },]; } else if (sortType && util.isDefined(sortVal)) { // 搜寻菜单 switch (sortType) { case 'cateId': { if (sortVal) where.and.ENROLL_CATE_ID = String(sortVal); break; } case 'sort': { orderBy = this.fmtOrderBySort(sortVal, 'ENROLL_ADD_TIME'); break; } } } return await EnrollModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal); }用户打卡 UI设计 ...

May 4, 2023 · 3 min · jiezi

关于小程序:从0到1可自定义数据列的成绩查询小程序开发笔记

背景问题公布与查问小程序作为问题治理的一个工具,用户能够通过小程序随时按条件(可自定义)查问各科问题(可自定义)。另外,问题查问小程序还提供新闻资讯,用户能够及时理解学校各种流动,免得错过重大告诉。校方或者老师能够在后盾登录零碎,录入考生的问题信息,并能够自定义多个考试科目,自定义查问条件,反对多个查问条件组合等。 次要性能布局我的项目立项布局了如下性能:告诉布告,问题列表,多条件问题查问,问题分享,后盾Excel批量录入问题,后盾批量导出问题,后盾自定义问题科目,后盾自定义查问条件等性能。 数据库设计SheetModel.DB_STRUCTURE = { _pid: 'string|true', SHEET_ID: 'string|true', SHEET_TITLE: 'string|true|comment=题目', SHEET_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=应用中', SHEET_CATE_ID: 'string|true|default=0|comment=分类', SHEET_CATE_NAME: 'string|false|comment=分类冗余', SHEET_ORDER: 'int|true|default=9999', SHEET_VOUCH: 'int|true|default=0', SHEET_FORMS: 'array|true|default=[]', SHEET_OBJ: 'object|true|default={}', SHEET_QR: 'string|false', SHEET_VIEW_CNT: 'int|true|default=0', SHEET_DATA_CNT: 'int|true|default=0', SHEET_ADD_TIME: 'int|true', SHEET_EDIT_TIME: 'int|true', SHEET_ADD_IP: 'string|false', SHEET_EDIT_IP: 'string|false',};SheetDataModel.DB_STRUCTURE = { _pid: 'string|true', SHEET_DATA_ID: 'string|true', SHEET_DATA_SHEET_ID: 'string|true|comment=FK', SHEET_DATA_SHEET_TITLE: 'string|false', SHEET_DATA_FORMS: 'array|true|default=[]', SHEET_DATA_ADD_TIME: 'int|true', SHEET_DATA_EDIT_TIME: 'int|true', SHEET_DATA_ADD_IP: 'string|false', SHEET_DATA_EDIT_IP: 'string|false',};外围实现/** 浏览信息 */ async viewSheet(id) { let fields = '*'; let where = { _id: id, SHEET_STATUS: SheetModel.STATUS.COMM } let sheet = await SheetModel.getOne(where, fields); if (!sheet) return null; SheetModel.inc(id, 'SHEET_VIEW_CNT', 1); return sheet; } /** 获得分页列表 */ async getSheetList({ cateId, //分类查问条件 search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 page, size, isTotal = true, oldTotal }) { orderBy = orderBy || { 'SHEET_ORDER': 'asc', 'SHEET_ADD_TIME': 'desc' }; let fields = 'SHEET_QR,SHEET_ADD_TIME,SHEET_OBJ,SHEET_VIEW_CNT,SHEET_TITLE,SHEET_ORDER,SHEET_STATUS,SHEET_CATE_NAME'; let where = {}; where.and = { _pid: this.getProjectId() //简单的查问在此处标注PID }; if (cateId && cateId !== '0') where.and.SHEET_CATE_ID = cateId; where.and.SHEET_STATUS = SheetModel.STATUS.COMM; // 状态 if (util.isDefined(search) && search) { where.or = [{ SHEET_TITLE: ['like', search] },]; } else if (sortType && util.isDefined(sortVal)) { // 搜寻菜单 switch (sortType) { case 'cateId': { if (sortVal) where.and.SHEET_CATE_ID = String(sortVal); break; } case 'sort': { orderBy = this.fmtOrderBySort(sortVal, 'SHEET_ADD_TIME'); break; } } } return await SheetModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal); }用户端UI设计 ...

May 4, 2023 · 2 min · jiezi

关于小程序:微信小程序头像图片压缩上传

因为 CanvasContext wx.createCanvasContext 进行保护,导致微信小程序压缩图片性能提醒报错小程序开发所应用的性能为了避免出现谬误,首先通过wx.getImageInfo获取图片信息,之后通过wx.createOffscreenCanvas生成画布,最初生成图片,获取到图片的base64格局地址,通过wx.uploadFile上传后盾。具体代码如下 wxml文件内容 <button class="head-img" open-type="chooseAvatar" bind:chooseavatar="onChooseAvatar"> <image class="avatar" src="{{avatarUrl}}"></image></button> <canvas canvas-id="canvas" id="mycanvas" type="2d" style="width:{{cWidth}}px;height:{{cHeight}}px;position: absolute;left:-1000px;top:-1000px;"></canvas>js文件内容 /** * 抉择头像 */onChooseAvatar(e) { const that = this let avatarUrl = e.detail.avatarUrl that.compressImage(avatarUrl, 100)},/** * 压缩图片 * imageUrl: 图片地址 * width:压缩后的图片宽度 */compressImage(imageUrl, width) { const that = this; wx.getImageInfo({ src: imageUrl, success: res => { const height = res.height * width / res.width; const offscreenCanvas = wx.createOffscreenCanvas({ type: '2d', width, height }) const context = offscreenCanvas.getContext('2d') const image = offscreenCanvas.createImage() image.src = imageUrl; image.onload = () => { context.clearRect(0, 0, width, height) context.drawImage(image, 0, 0, width, height) const imageBase64 = offscreenCanvas.toDataURL("image/jpeg", 0.7) const base64 = imageBase64.replace(/^data:image\/\w+;base64,/, "") that.uploadPic(imageUrl, base64) } } })},/** * 上传图片 */uploadPic(imgData, base64) { const that = this; //调用接口上传图片 let openId = wx.getStorageSync('userOpenid') wx.uploadFile({ url: "https://xxx.xxx.com/upload", // 这里换成你们后端的上传接口即可 method: 'POST', filePath: imgData, name: 'file', formData: { 'content': base64 //这里传base64类型 }, // 胜利回调 success: (res) => { console.log(res) let result = JSON.parse(res.data); // JSON.parse()办法是将JSON格局字符串转换为JSON对象 let newAvatarUrl = result.data; // 返回的图片url // 将返回的url替换调默认的url,渲染在页面上 that.setData({ avatarUrl: newAvatarUrl }) } })},

April 12, 2023 · 1 min · jiezi

关于小程序:从0100物业缴费支付小程序开发笔记

设计背景小区物业费用缴纳,公寓租金收取,出租屋租金收取等场景,大部分都是靠人工收取,而宽广业主和住户可能工夫或者工作忙碌,不能到现场付款,那么设计一个这样的小程序,不便物业公司进行账务收款,账务统计,节俭人力物力老本,不管在家中或者当地,都能够通过小程序间接缴费,不受工夫、地点束缚,操作简略,方便快捷 概要设计 数据字典SheetModel.DB_STRUCTURE = { _pid: 'string|true', SHEET_ID: 'string|true', SHEET_TITLE: 'string|true|comment=题目', SHEET_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=应用中', SHEET_CATE_ID: 'string|true|default=0|comment=分类', SHEET_CATE_NAME: 'string|false|comment=分类冗余', SHEET_ORDER: 'int|true|default=9999', SHEET_VOUCH: 'int|true|default=0', SHEET_FORMS: 'array|true|default=[]', SHEET_OBJ: 'object|true|default={}', SHEET_QR: 'string|false', SHEET_VIEW_CNT: 'int|true|default=0', SHEET_CNT: 'int|true|default=0', SHEET_PAY_CNT: 'int|true|default=0', SHEET_WAIT_CNT: 'int|true|default=0', SHEET_NO_CNT: 'int|true|default=0', SHEET_FEE: 'int|true|default=0', SHEET_PAY_FEE: 'int|true|default=0', SHEET_WAIT_FEE: 'int|true|default=0', SHEET_ADD_TIME: 'int|true', SHEET_EDIT_TIME: 'int|true', SHEET_ADD_IP: 'string|false', SHEET_EDIT_IP: 'string|false',};SheetDataModel.DB_STRUCTURE = { _pid: 'string|true', SHEET_DATA_ID: 'string|true', SHEET_DATA_SHEET_ID: 'string|true|comment=FK', SHEET_DATA_SHEET_TITLE: 'string|false', SHEET_DATA_PAY_TRADE_NO: 'string|false|comment=商家订单号 32位', SHEET_DATA_PAY_STATUS: 'int|true|default=0|comment=领取状态 0=未领取 1=已领取 99=无需领取', SHEET_DATA_PAY_FEE: 'int|true|default=0|comment=已领取费用 分', SHEET_DATA_PAY_TIME: 'int|true|default=0|comment=领取工夫', SHEET_DATA_NAME: 'string|false|姓名', SHEET_DATA_MOBILE: 'string|false|手机号', SHEET_DATA_FEE: 'int|true|default=0|comment=需领取费用 分', SHEET_DATA_FORMS: 'array|true|default=[]', SHEET_DATA_OBJ: 'object|true|default={}', SHEET_DATA_ADD_TIME: 'int|true', SHEET_DATA_EDIT_TIME: 'int|true', SHEET_DATA_ADD_IP: 'string|false', SHEET_DATA_EDIT_IP: 'string|false',};要害实现 async getMySheetChartList(userId, time = 180) { let where = {}; if (!config.IS_DEMO) { let user = await UserModel.getOne({ USER_MINI_OPENID: userId }); if (!user) return null; where = { SHEET_DATA_PAY_STATUS: 1, SHEET_DATA_NAME: user.USER_NAME, SHEET_DATA_MOBILE: user.USER_MOBILE, 'sheet.SHEET_STATUS': SheetModel.STATUS.COMM }; } else { where = { SHEET_DATA_PAY_STATUS: 1, SHEET_DATA_NAME: 'Tom', SHEET_DATA_MOBILE: '14600000000', 'sheet.SHEET_STATUS': SheetModel.STATUS.COMM }; } time = Number(time); time = this._timestamp - time * 86400 * 1000; where.SHEET_DATA_PAY_TIME = ['>=', time]; let fields = 'SHEET_DATA_PAY_TIME,SHEET_DATA_FORMS,SHEET_DATA_FEE,sheet.SHEET_TITLE '; let orderBy = { 'SHEET_DATA_PAY_TIME': 'desc', 'SHEET_DATA_ADD_TIME': 'desc' }; let joinParams = { from: SheetModel.CL, localField: 'SHEET_DATA_SHEET_ID', foreignField: '_id', as: 'sheet', }; let list = await SheetDataModel.getListJoin(joinParams, where, fields, orderBy, 1, 200, false); list = list.list; if (list.length == 0) return null; let categories = []; let data = []; for (let k = 0; k < list.length; k++) { data.push(Number(list[k].SHEET_DATA_FEE / 100)); categories.push(list[k].sheet.SHEET_TITLE.substr(0, 15)); list[k].SHEET_DATA_PAY_TIME = timeUtil.timestamp2Time(list[k].SHEET_DATA_PAY_TIME); } return { categories, data, list: list.reverse() }; } // 获得账单详情 async getMySheetDataDetail(userId, sheetDataId) { let where = {}; if (!config.IS_DEMO) { let user = await UserModel.getOne({ USER_MINI_OPENID: userId, USER_STATUS: UserModel.STATUS.COMM }); if (!user) this.AppError('用户不存在或者状态异样'); where = { _id: sheetDataId, SHEET_DATA_NAME: user.USER_NAME, SHEET_DATA_MOBILE: user.USER_MOBILE, } } else { where = { _id: sheetDataId, SHEET_DATA_NAME: 'Tom', SHEET_DATA_MOBILE: '14600000000', } } let sheetData = await SheetDataModel.getOne(where); if (!sheetData) return null; let sheet = await SheetModel.getOne({ _id: sheetData.SHEET_DATA_SHEET_ID, SHEET_STATUS: SheetModel.STATUS.COMM }); if (!sheet) this.AppError('领取我的项目不存在'); sheetData.sheet = sheet; return sheetData; } /** 获得我的分页列表 */ async getMySheetDataList(userId, { search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 page, size = 30, isTotal = true, oldTotal }) { orderBy = orderBy || { 'SHEET_DATA_ADD_TIME': 'desc' }; let fields = 'SHEET_DATA_PAY_TIME,SHEET_DATA_ADD_TIME,SHEET_DATA_FEE,SHEET_DATA_FORMS,SHEET_DATA_PAY_FEE,SHEET_DATA_PAY_STATUS,sheet.SHEET_TITLE,sheet.SHEET_OBJ'; let where = {}; if (!config.IS_DEMO) { let user = await UserModel.getOne({ USER_MINI_OPENID: userId }); if (!user) return null; where = { SHEET_DATA_NAME: user.USER_NAME, SHEET_DATA_MOBILE: user.USER_MOBILE, 'sheet.SHEET_STATUS': SheetModel.STATUS.COMM }; } else { where = { SHEET_DATA_NAME: 'Tom', SHEET_DATA_MOBILE: '14600000000', 'sheet.SHEET_STATUS': SheetModel.STATUS.COMM }; } if (util.isDefined(search) && search) { where['SHEET_DATA_SHEET_TITLE'] = { $regex: '.*' + search, $options: 'i' }; } else if (sortType) { // 搜寻菜单 switch (sortType) { case 'status': { where['SHEET_DATA_PAY_STATUS'] = Number(sortVal); break; } case 'sort': { //按工夫倒序 orderBy = this.fmtOrderBySort(sortVal, 'SHEET_DATA_ADD_TIME'); break; } } } let joinParams = { from: SheetModel.CL, localField: 'SHEET_DATA_SHEET_ID', foreignField: '_id', as: 'sheet', }; let result = await SheetDataModel.getListJoin(joinParams, where, fields, orderBy, page, size, isTotal, oldTotal); return result; } async statSheetData(sheetId) { let where = { SHEET_DATA_SHEET_ID: sheetId } // 总数 let cnt = await SheetDataModel.count(where); // 总费用 let fee = await SheetDataModel.sum(where, 'SHEET_DATA_FEE'); // 已领取记录 let wherePayCnt = { SHEET_DATA_SHEET_ID: sheetId, SHEET_DATA_PAY_STATUS: 1, } let payCnt = await SheetDataModel.count(wherePayCnt); // 毋庸领取 let whereNoCnt = { SHEET_DATA_SHEET_ID: sheetId, SHEET_DATA_PAY_STATUS: 99, } let noCnt = await SheetDataModel.count(whereNoCnt); // 已领取金额 let wherePayFee = { SHEET_DATA_SHEET_ID: sheetId, SHEET_DATA_PAY_STATUS: 1, } let payFee = await SheetDataModel.sum(wherePayFee, 'SHEET_DATA_PAY_FEE'); let waitCnt = cnt - payCnt - noCnt; let waitFee = fee - payFee; let data = { SHEET_CNT: cnt, SHEET_PAY_CNT: payCnt, SHEET_WAIT_CNT: waitCnt, SHEET_NO_CNT: noCnt, SHEET_FEE: fee, SHEET_PAY_FEE: payFee, SHEET_WAIT_FEE: waitFee } await SheetModel.edit(sheetId, data); return { cnt, payCnt, waitCnt, noCnt, fee, payFee, waitFee }; } // 修改本地订单状态 async fixSheetDataPay(tradeNo, sheetId) { if (!tradeNo) { // 无领取号空单 let data = { SHEET_DATA_PAY_STATUS: 0, SHEET_DATA_PAY_TRADE_NO: '', SHEET_DATA_PAY_FEE: 0, SHEET_DATA_PAY_TIME: 0, } await SheetDataModel.edit({ SHEET_DATA_PAY_TRADE_NO: tradeNo }, data); // 从新统计 this.statSheetData(sheetId); return false; } let payService = new PayService(); if (!await payService.fixPayResult(tradeNo)) { // 敞开未领取单 payService.closePay(tradeNo); // 未领取 let data = { SHEET_DATA_PAY_STATUS: 0, SHEET_DATA_PAY_TRADE_NO: '', SHEET_DATA_PAY_FEE: 0, SHEET_DATA_PAY_TIME: 0, } await SheetDataModel.edit({ SHEET_DATA_PAY_TRADE_NO: tradeNo }, data); // 从新统计 this.statSheetData(sheetId); return false; } // 已领取 let pay = await PayModel.getOne({ PAY_TRADE_NO: tradeNo }); if (!pay) this.AppError('领取流水异样,请核查'); // 更新领取信息 let data = { SHEET_DATA_PAY_STATUS: 1, SHEET_DATA_PAY_TRADE_NO: tradeNo, SHEET_DATA_PAY_FEE: pay.PAY_TOTAL_FEE, SHEET_DATA_PAY_TIME: pay.PAY_END_TIME, } await SheetDataModel.edit({ SHEET_DATA_PAY_TRADE_NO: tradeNo }, data); // 从新统计 this.statSheetData(sheetId); return true; } // 预领取 async prepay(userId, sheetDataId) { this.AppError('[物业缴费]该性能暂不凋谢,如有须要请加作者微信:cclinux0730'); } // 查问领取后果 async queryPayResult(sheetDataId) { let sheetData = await SheetDataModel.getOne(sheetDataId); if (!sheetData) return { status: 0 }; return { status: sheetData.SHEET_DATA_PAY_STATUS } }住户端 UI设计 ...

April 7, 2023 · 4 min · jiezi

关于小程序:从0到100中小学运动体育设施开放预约小程序

开发背景随着全民健身的遍及,为进一步贯彻落实《“衰弱中国2030”布局大纲》和《全民健身条例》,更好地满足宽广青少年学生和人民大众就近、便当加入体育健身活动的需要,继续扩充公共服务配套资源供应, 中小学校园的操场,静止设施周也开始对市民凋谢,那么为了正当工夫,不便各项设施的无效利用, 缩小不必要的人员汇集, 预订小程序提供了线上预约的便捷性 性能概要设计 技术选型本我的项目应用微信小程序平台进行开发。应用腾讯专门的小程序云开发技术,云资源蕴含云函数,数据库,带宽,存储空间,定时器等,资源配额价格低廉,无需域名和服务器即可搭建。小程序自身的即用即走,适宜小工具的应用场景,也适宜疾速开发迭代。云开发技术采纳腾讯外部链路,没有被黑客攻击的危险,不会 DDOS攻打,节俭防火墙费用,安全性高且免保护。资源承载力可依据业务倒退须要随时弹性扩大。数据库设计EnrollJoinModel.DB_STRUCTURE = { _pid: 'string|true', ENROLL_JOIN_ID: 'string|true', ENROLL_JOIN_PRICE: 'int|true|default=0', ENROLL_JOIN_IS_ADMIN: 'int|true|default=0|comment=是否管理员增加 0/1', ENROLL_JOIN_ENROLL_ID: 'string|true|comment=报名PK', ENROLL_JOIN_ENROLL_TITLE: 'string|false', ENROLL_JOIN_CATE_ID: 'string|false|default=0|comment=分类', ENROLL_JOIN_CATE_NAME: 'string|false|comment=分类冗余', ENROLL_JOIN_CODE: 'string|true|comment=核验码15位', ENROLL_JOIN_IS_CHECKIN: 'int|true|default=0|comment=是否核销 0/1 ', ENROLL_JOIN_CHECKIN_TIME: 'int|true|default=0', ENROLL_JOIN_DAY: 'string|false|comment=日期', ENROLL_JOIN_START: 'string|false|comment=开始工夫', ENROLL_JOIN_END: 'string|false|comment=完结工夫', ENROLL_JOIN_END_POINT: 'string|false|comment=完结工夫开端', ENROLL_JOIN_END_FULL: 'string|false|comment=残缺的完结工夫 YYYY-MM-DD hh:mm', ENROLL_JOIN_START_FULL: 'string|false|comment=残缺的开始工夫 YYYY-MM-DD hh:mm', ENROLL_JOIN_USER_ID: 'string|true|comment=用户ID', ENROLL_JOIN_FORMS: 'array|true|default=[]|comment=表单', ENROLL_JOIN_OBJ: 'object|true|default={}', ENROLL_JOIN_STATUS: 'int|true|default=1|comment=状态 0=待审核 1=胜利, 9=用户勾销, 99=零碎勾销', ENROLL_JOIN_LAST_TIME: 'int|true|default=0', ENROLL_JOIN_ADD_TIME: 'int|true', ENROLL_JOIN_EDIT_TIME: 'int|true', ENROLL_JOIN_ADD_IP: 'string|false', ENROLL_JOIN_EDIT_IP: 'string|false',};// 字段前缀EnrollJoinModel.FIELD_PREFIX = "ENROLL_JOIN_";/** * 状态 0=待审核 1=胜利,9=用户勾销, 99=审核未过 */EnrollJoinModel.STATUS = { WAIT: 0, SUCC: 1, CANCEL: 9, ADMIN_CANCEL: 99};EnrollJoinModel.STATUS_DESC = { WAIT: '待审核', SUCC: '胜利', CANCEL: '用户勾销', ADMIN_CANCEL: '零碎勾销'};EnrollModel.DB_STRUCTURE = { _pid: 'string|true', ENROLL_ID: 'string|true', ENROLL_TITLE: 'string|true|comment=题目', ENROLL_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=应用中', ENROLL_CATE_ID: 'string|true|default=0|comment=分类', ENROLL_CATE_NAME: 'string|false|comment=分类冗余', ENROLL_CANCEL_SET: 'int|true|default=1|comment=勾销设置 0=不允,1=容许,2=开始前可勾销,3=完结前可勾销', ENROLL_EDIT_SET: 'int|true|default=1|comment=批改 0=不允,1=容许,2=开始前可批改,3=完结前可批改', ENROLL_ORDER: 'int|true|default=9999', ENROLL_VOUCH: 'int|true|default=0', ENROLL_FORMS: 'array|true|default=[]', ENROLL_OBJ: 'object|true|default={}', ENROLL_JOIN_FORMS: 'array|true|default=[]', ENROLL_DAYS: 'array|true|default=[]|comment=最近一次批改保留的可用日期', ENROLL_DAY_CNT: 'int|true|default=0', ENROLL_QR: 'string|false', ENROLL_VIEW_CNT: 'int|true|default=0', ENROLL_JOIN_CNT: 'int|true|default=0', ENROLL_ADD_TIME: 'int|true', ENROLL_EDIT_TIME: 'int|true', ENROLL_ADD_IP: 'string|false', ENROLL_EDIT_IP: 'string|false',};要害难点 // 获取某天某个场合下的可约工夫点 async getOneDayTimePoint(day, enrollId) { let where = { DAY_ENROLL_ID: enrollId, day }; let fields = 'times'; let data = await DayModel.getOne(where, fields); if (!data) data = []; else data = data.times; return data; } // 获得某天内所有场地信息 async getAllEnroll(cateId, day) { let where = { ENROLL_CATE_ID: String(cateId), ENROLL_STATUS: EnrollModel.STATUS.COMM } let orderBy = { ENROLL_ORDER: 'asc', ENROLL_ADD_TIME: 'asc' } let list = await EnrollModel.getAll(where, '*', orderBy); let arr = []; let startTime = 23; let endTime = 0; for (let k = 0; k < list.length; k++) { let times = await this.getOneDayTimePoint(day, list[k]._id); // 合成小时 let t = []; for (let j = 0; j < times.length; j++) { if (times[j].start < startTime) startTime = times[j].start; if (times[j].end > endTime) endTime = times[j].end; for (let i = times[j].start; i <= times[j].end; i++) { let node = { t: i, //工夫点 price: times[j].price, //价格 }; t.push(node); } } if (t.length > 0) arr.push({ enrollId: list[k]._id, label: list[k].ENROLL_TITLE, timePrice: t }) } // 获得可预订的最大日期 let maxDay = await DayModel.max({ day: ['>=', day], DAY_CATE_ID: cateId }, 'day'); if (maxDay == 0) maxDay = ''; return { maxDay, startTime, endTime, list: arr }; } // 获取某天预订状况 async getUsedByDay(cateId, day) { let where = { ENROLL_JOIN_CATE_ID: String(cateId), ENROLL_JOIN_DAY: day, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]], }; return EnrollJoinModel.getAll(where); } /** 获得我的注销分页列表 */ async getMyEnrollJoinList(userId, { search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 page, size, isTotal = true, oldTotal }) { orderBy = orderBy || { 'ENROLL_JOIN_ADD_TIME': 'desc' }; let fields = 'ENROLL_JOIN_IS_CHECKIN,ENROLL_JOIN_CATE_NAME,ENROLL_JOIN_ENROL_TITLE,ENROLL_JOIN_PRICE,ENROLL_JOIN_END_FULL,ENROLL_JOIN_OBJ,ENROLL_JOIN_DAY,ENROLL_JOIN_START,ENROLL_JOIN_END,ENROLL_JOIN_END_POINT,ENROLL_JOIN_LAST_TIME,ENROLL_JOIN_ENROLL_ID,ENROLL_JOIN_STATUS,ENROLL_JOIN_ADD_TIME,enroll.ENROLL_TITLE,enroll.ENROLL_EDIT_SET,enroll.ENROLL_CANCEL_SET'; let where = { ENROLL_JOIN_USER_ID: userId }; if (util.isDefined(search) && search) { where['ENROLL_JOIN_OBJ.name'] = { $regex: '.*' + search, $options: 'i' }; } else if (sortType) { // 搜寻菜单 switch (sortType) { case 'timedesc': { //按工夫倒序 orderBy = { 'ENROLL_JOIN_START_FULL': 'desc' }; break; } case 'timeasc': { //按工夫正序 orderBy = { 'ENROLL_JOIN_START_FULL': 'asc' }; break; } case 'status': { break; } case 'today': { where.ENROLL_JOIN_DAY = timeUtil.time('Y-M-D'); where.ENROLL_JOIN_STATUS = EnrollJoinModel.STATUS.SUCC; break; } case 'run': { where.ENROLL_JOIN_END_FULL = ['>', timeUtil.time('Y-M-D h:m')]; where.ENROLL_JOIN_STATUS = EnrollJoinModel.STATUS.SUCC; where.ENROLL_JOIN_IS_CHECKIN = 0; break; } case 'check': { where.ENROLL_JOIN_END_FULL = ['>', timeUtil.time('Y-M-D h:m')]; where.ENROLL_JOIN_STATUS = EnrollJoinModel.STATUS.SUCC; where.ENROLL_JOIN_IS_CHECKIN = 1; break; } case 'out': { where.ENROLL_JOIN_END_FULL = ['<=', timeUtil.time('Y-M-D h:m')]; where.ENROLL_JOIN_STATUS = EnrollJoinModel.STATUS.SUCC; break; } case 'cancel': { where.ENROLL_JOIN_STATUS = EnrollJoinModel.STATUS.CANCEL; break; } case 'syscancel': { where.ENROLL_JOIN_STATUS = EnrollJoinModel.STATUS.ADMIN_CANCEL; break; } } } let joinParams = { from: EnrollModel.CL, localField: 'ENROLL_JOIN_ENROLL_ID', foreignField: '_id', as: 'enroll', }; let result = await EnrollJoinModel.getListJoin(joinParams, where, fields, orderBy, page, size, isTotal, oldTotal); return result; } /** 获得我的注销详情 */ async getMyEnrollJoinDetail(enrollJoinId) { let fields = '*'; let where = { _id: enrollJoinId }; let enrollJoin = await EnrollJoinModel.getOne(where, fields); if (enrollJoin) { enrollJoin.enroll = await EnrollModel.getOne(enrollJoin.ENROLL_JOIN_ENROLL_ID, 'ENROLL_TITLE'); } return enrollJoin; } //################## 注销 // 把工夫格局'hh:mm'转为数组[1,2,3,4] getTimeArr(start, end) { start = start.replace(':00', '').trim(); start = start.replace(':30', '').trim(); start = Number(start); end = end.replace(':00', ''); end = end.replace(':30', '').trim(); end = Number(end); let ret = []; for (let k = start; k <= end; k++) { ret.push(k); } return ret; } // 注销 async enrollJoin(userId, { enrollId, price, start, end, endPoint, day, forms }) { // 注销是否完结 let whereEnroll = { _id: enrollId, ENROLL_STATUS: EnrollModel.STATUS.COMM } let enroll = await EnrollModel.getOne(whereEnroll); if (!enroll) this.AppError('该' + ENROLL_NAME + '不存在或者曾经进行'); // 判断是否曾经被约(数组交加) let nowTimeArr = this.getTimeArr(start, end); let joinWhere = { ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_DAY: day, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]], } let joinList = await EnrollJoinModel.getAll(joinWhere, 'ENROLL_JOIN_START,ENROLL_JOIN_END', { 'ENROLL_JOIN_START': 'asc' }); for (let k = 0; k < joinList.length; k++) { let listTimeArr = this.getTimeArr(joinList[k].ENROLL_JOIN_START, joinList[k].ENROLL_JOIN_END); for (let j = 0; j < nowTimeArr.length; j++) { if (listTimeArr.includes(nowTimeArr[j])) { this.AppError(nowTimeArr[j] + '点曾经被预订,请从新抉择'); } } } // 入库 let data = { ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_CATE_ID: enroll.ENROLL_CATE_ID, ENROLL_JOIN_CATE_NAME: enroll.ENROLL_CATE_NAME, ENROLL_JOIN_CODE: dataUtil.genRandomIntString(15), ENROLL_JOIN_PRICE: price, ENROLL_JOIN_START: start, ENROLL_JOIN_END: end, ENROLL_JOIN_END_POINT: endPoint, ENROLL_JOIN_DAY: day, ENROLL_JOIN_ENROLL_TITLE: enroll.ENROLL_TITLE, ENROLL_JOIN_END_FULL: day + ' ' + endPoint, ENROLL_JOIN_START_FULL: day + ' ' + start, ENROLL_JOIN_FORMS: forms, ENROLL_JOIN_OBJ: dataUtil.dbForms2Obj(forms), } let enrollJoinId = await EnrollJoinModel.insert(data); // 统计数量 this.statEnrollJoin(enrollId); return { enrollJoinId } } // 批改注销 async enrollJoinEdit(userId, enrollId, enrollJoinId, forms) { let whereJoin = { _id: enrollJoinId, ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]], } let enrollJoin = await EnrollJoinModel.getOne(whereJoin); if (!enrollJoin) this.AppError('该' + ENROLL_NAME + '记录不存在或者曾经被零碎勾销'); // 注销是否完结 let whereEnroll = { _id: enrollId, ENROLL_STATUS: EnrollModel.STATUS.COMM } let enroll = await EnrollModel.getOne(whereEnroll); if (!enroll) this.AppError('该' + ENROLL_NAME + '不存在或者曾经进行'); if (enrollJoin.ENROLL_JOIN_IS_CHECKIN == 1) this.AppError('该预订已核销,不能批改'); if (enroll.ENROLL_EDIT_SET == 0) this.AppError('该' + ENROLL_NAME + '不容许批改材料'); if (enroll.ENROLL_EDIT_SET == 2 && enrollJoin.ENROLL_JOIN_START_FULL <= timeUtil.time('Y-M-D h:m')) this.AppError('该' + ENROLL_NAME + '曾经开始,不能批改材料'); if (enroll.ENROLL_EDIT_SET == 3 && enrollJoin.ENROLL_JOIN_END_FULL <= timeUtil.time('Y-M-D h:m')) this.AppError('该' + ENROLL_NAME + '曾经完结,不能批改材料'); let data = { ENROLL_JOIN_FORMS: forms, ENROLL_JOIN_OBJ: dataUtil.dbForms2Obj(forms), ENROLL_JOIN_LAST_TIME: this._timestamp, } await EnrollJoinModel.edit(whereJoin, data); } async statEnrollJoin(id) { let where = { ENROLL_JOIN_ENROLL_ID: id, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]] } let cnt = await EnrollJoinModel.count(where); await EnrollModel.edit(id, { ENROLL_JOIN_CNT: cnt }); } /** 注销前获取要害信息 */ async detailForEnrollJoin(userId, enrollId, enrollJoinId = '') { let fields = 'ENROLL_JOIN_FORMS, ENROLL_TITLE, ENROLL_CATE_NAME'; let where = { _id: enrollId, ENROLL_STATUS: EnrollModel.STATUS.COMM } let enroll = await EnrollModel.getOne(where, fields); if (!enroll) this.AppError('该' + ENROLL_NAME + '不存在'); let joinMy = null; if (enrollJoinId) { // 编辑 let whereMy = { ENROLL_JOIN_USER_ID: userId, _id: enrollJoinId } joinMy = await EnrollJoinModel.getOne(whereMy); enroll.join = { start: joinMy.ENROLL_JOIN_START, end: joinMy.ENROLL_JOIN_END, endPoint: joinMy.ENROLL_JOIN_END_POINT, day: joinMy.ENROLL_JOIN_DAY, } } else { // 取出自己最近一次的填写表单 let whereMy = { ENROLL_JOIN_USER_ID: userId, } let orderByMy = { ENROLL_JOIN_ADD_TIME: 'desc' } joinMy = await EnrollJoinModel.getOne(whereMy, 'ENROLL_JOIN_FORMS', orderByMy); } let myForms = joinMy ? joinMy.ENROLL_JOIN_FORMS : []; enroll.myForms = myForms; return enroll; } /** 勾销我的注销 */ async cancelMyEnrollJoin(userId, enrollJoinId) { let where = { ENROLL_JOIN_USER_ID: userId, _id: enrollJoinId, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]] }; let enrollJoin = await EnrollJoinModel.getOne(where); if (!enrollJoin) { this.AppError('未找到可勾销的记录'); } if (enrollJoin.ENROLL_JOIN_IS_CHECKIN == 1) this.AppError('该预订已核销,不能取消'); let enroll = await EnrollModel.getOne(enrollJoin.ENROLL_JOIN_ENROLL_ID); if (!enroll) this.AppError('该' + ENROLL_NAME + '不存在'); if (enroll.ENROLL_CANCEL_SET == 0) this.AppError('该' + ENROLL_NAME + '不能取消'); if (enroll.ENROLL_CANCEL_SET == 2 && enrollJoin.ENROLL_JOIN_START_FULL <= timeUtil.time('Y-M-D h:m')) this.AppError('该' + ENROLL_NAME + '曾经开始,不能取消'); if (enroll.ENROLL_CANCEL_SET == 3 && enrollJoin.ENROLL_JOIN_END_FULL <= timeUtil.time('Y-M-D h:m')) this.AppError('该' + ENROLL_NAME + '曾经完结,不能取消'); if (enroll.ENROLL_CANCEL_SET > 20) { let step = enroll.ENROLL_CANCEL_SET - 20; let day = timeUtil.time2Timestamp(enrollJoin.ENROLL_JOIN_END_FULL + ':00') - step * 86400 * 1000; day = timeUtil.timestamp2Time(day, 'Y-M-D'); let now = timeUtil.time('Y-M-D'); if (now > day) this.AppError('仅开始前' + step + '天可勾销'); } await EnrollJoinModel.edit(where, { ENROLL_JOIN_STATUS: EnrollJoinModel.STATUS.CANCEL, ENROLL_JOIN_IS_CHECKIN: 0 }); await this.statEnrollJoin(enrollJoin.ENROLL_JOIN_ENROLL_ID); }前端UI设计 ...

March 27, 2023 · 6 min · jiezi

关于小程序:从0到1学员课时预约与扣课小程序开发笔记

开发背景机构:各类音体美,数理化培训机构须要进行课时治理、课时统计、课时计算、课时记录、上课预约注销,学员:须要实时查看本人的课程耗费状况,应用记录。管理者:须要随时查看,增减学员的课程数量 性能布局 技术选型应用微信小程序平台进行开发。应用腾讯专门的小程序云开发技术,云资源蕴含云函数,数据库,带宽,存储空间,定时器等,资源配额价格低廉,无需域名和服务器即可搭建。小程序自身的即用即走,适宜小工具的应用场景,也适宜疾速开发迭代。云开发技术采纳腾讯外部链路,没有被黑客攻击的危险,不会 DDOS攻打,节俭防火墙费用,安全性高且免保护。资源承载力可依据业务倒退须要随时弹性扩大数据库设计LessonLogModel.DB_STRUCTURE = { _pid: 'string|true', LESSON_LOG_ID: 'string|true', LESSON_LOG_USER_ID: 'string|true|comment=用户ID', LESSON_LOG_MEET_ID: 'string|false|comment=预约我的项目PK', LESSON_LOG_DESC: 'string|false|comment=备注', LESSON_LOG_TYPE: 'int|true|default=1|comment=类型 0=用户约课-,1=用户勾销预约+,10=后盾减少课时+,11=后盾缩小课时-,12=后盾勾销预约+,13=后盾复原+', LESSON_LOG_EDIT_ADMIN_ID: 'string|false|comment=最近批改的管理员ID', LESSON_LOG_EDIT_ADMIN_NAME: 'string|false|comment=最近批改的管理员名', LESSON_LOG_EDIT_ADMIN_TIME: 'int|true|default=0|comment=管理员最近批改的工夫', LESSON_LOG_CHANGE_CNT: 'int|true|default=0|comment=当变动课时数(可正负)', LESSON_LOG_LAST_CNT: 'int|true|default=0|comment=变动前次数', LESSON_LOG_NOW_CNT: 'int|true|default=0|comment=以后次数', LESSON_LOG_ADD_TIME: 'int|true', LESSON_LOG_ADD_IP: 'string|false', LESSON_LOG_EDIT_TIME: 'int|true', LESSON_LOG_EDIT_IP: 'string|false',}// 字段前缀LessonLogModel.FIELD_PREFIX = "LESSON_LOG_";/** * 类型 0=初始赠送,1=学员约课,2=学员勾销预约,10=后盾减少课时,11=后盾缩小课时,12=后盾勾销预约,13=后盾复原 */LessonLogModel.TYPE = { INIT: 0, USER_APPT: 1, USER_CANCEL: 2, ADMIN_ADD: 10, ADMIN_REDUCE: 11, ADMIN_CANCEL: 12, ADMIN_RECOVER: 13};LessonLogModel.TYPE_DESC = { INIT: '初始赠送', USER_APPT: '学员约课', USER_CANCEL: '学员勾销预约', ADMIN_ADD: '后盾减少课时', ADMIN_REDUCE: '后盾缩小课时', ADMIN_CANCEL: '后盾勾销预约', ADMIN_RECOVER: '后盾复原预约'};JoinModel.DB_STRUCTURE = { _pid: 'string|true', JOIN_ID: 'string|true', JOIN_EDIT_ADMIN_ID: 'string|false|comment=最近批改的管理员ID', JOIN_EDIT_ADMIN_NAME: 'string|false|comment=最近批改的管理员名', JOIN_EDIT_ADMIN_TIME: 'int|true|default=0|comment=管理员最近批改的工夫', JOIN_EDIT_ADMIN_STATUS: 'int|false|comment=最近管理员批改为的状态 ', JOIN_IS_ADMIN: 'int|true|default=0|comment=是否管理员增加 0/1', JOIN_CODE: 'string|true|comment=核验码15位', JOIN_IS_CHECKIN: 'int|true|default=0|comment=是否核销 0/1 ', JOIN_CHECKIN_TIME: 'int|true|default=0', JOIN_USER_ID: 'string|true|comment=用户ID', JOIN_MEET_ID: 'string|true|comment=预约PK', JOIN_MEET_CATE_ID: 'string|true', JOIN_MEET_CATE_NAME: 'string|true', JOIN_MEET_TITLE: 'string|true|comment=我的项目', JOIN_MEET_DAY: 'string|true|comment=日期', JOIN_MEET_TIME_START: 'string|true|comment=时段开始', JOIN_MEET_TIME_END: 'string|true|comment=时段完结', JOIN_MEET_TIME_MARK: 'string|true|comment=时段标识', JOIN_COMPLETE_END_TIME: 'string|false|comment=残缺完结工夫', JOIN_START_TIME: 'int|true|comment=开始工夫戳', JOIN_FORMS: 'array|true|default=[]|comment=表单', /* title: mark: type: val: */ JOIN_OBJ: 'object|true|default={}', JOIN_STATUS: 'int|true|default=1|comment=状态 1=预约胜利,10=已勾销, 99=零碎勾销', JOIN_REASON: 'string|false|comment=审核回绝或者勾销理由', JOIN_ADD_TIME: 'int|true', JOIN_EDIT_TIME: 'int|true', JOIN_ADD_IP: 'string|false', JOIN_EDIT_IP: 'string|false',};要害代码实现// 用户预约逻辑 async join(userId, meetId, timeMark, formsList) { // 预约时段是否存在 let meetWhere = { _id: meetId }; let day = this.getDayByTimeMark(timeMark); let meet = await this.getMeetOneDay(meetId, day, meetWhere); if (!meet) { this.AppError('预约时段抉择谬误1,请从新抉择'); } let daySet = this.getDaySetByTimeMark(meet, timeMark); if (!daySet) this.AppError('预约时段抉择谬误2,请从新抉择'); let timeSet = this.getTimeSetByTimeMark(meet, timeMark); if (!timeSet) this.AppError('预约时段抉择谬误3,请从新抉择'); // 规定校验 await this.checkMeetRules(userId, meetId, timeMark, formsList); let data = {}; data.JOIN_USER_ID = userId; data.JOIN_MEET_ID = meetId; data.JOIN_MEET_CATE_ID = meet.MEET_CATE_ID; data.JOIN_MEET_CATE_NAME = meet.MEET_CATE_NAME; data.JOIN_MEET_TITLE = meet.MEET_TITLE; data.JOIN_MEET_DAY = daySet.day; data.JOIN_MEET_TIME_START = timeSet.start; data.JOIN_MEET_TIME_END = timeSet.end; data.JOIN_MEET_TIME_MARK = timeMark; data.JOIN_START_TIME = timeUtil.time2Timestamp(daySet.day + ' ' + timeSet.start + ':00'); data.JOIN_STATUS = JoinModel.STATUS.SUCC; data.JOIN_COMPLETE_END_TIME = daySet.day + ' ' + timeSet.end; // 入库 for (let k = 0; k < formsList.length; k++) { let forms = formsList[k]; data.JOIN_FORMS = forms; data.JOIN_OBJ = dataUtil.dbForms2Obj(forms); data.JOIN_CODE = dataUtil.genRandomIntString(15); await JoinModel.insert(data); } // 统计 await this.statJoinCnt(meetId, timeMark); // 课时统计 await this.editUserMeetLesson(null, userId, -1, LessonLogModel.TYPE.USER_APPT, meetId, '《' + meet.MEET_TITLE + '》') return { result: 'ok', } }前端UI设计 ...

March 27, 2023 · 2 min · jiezi

关于小程序:利用姿态相似度比较功能对运动动作识别检测秒适配

本周迎来了「AI静止辨认小程序插件」一个具备里程碑意义的性能更新:“姿势类似度比拟”性能。利用此个性能够极大的进步您适配静止(动作)辨认检测的速度,上面就带您体验一下此个性的魅力。一、确保将插件版本升级至v1.0.7。//app.json{ "plugins": { "aiSport": { "version": "1.0.7", "provider": "wx6130e578c4a26a1a" } }}二、姿势类似度比拟API介绍「姿势类似度比拟」性能,是对给定的两组“人体关键点”进行分区及综合比拟,并给出评分,省去了您在适配静止(动作)辨认检测时,配置检测规定的繁琐。性能有三个次要对象搁置在插件的calc命名空间,别离是:calc.PoseComparer、calc.PoseComparerResult、calc.PoseComparerPartItem,详情的请参考api-docs。 三、取姿势样本进行姿势比拟前您须要取一个规范姿势的关键点样本,您能够通过咱们为您提供的「静止构建调试工具」来提取样本。 四、执行样本比拟//样本姿势人体关键点const sample = [{y:95.41808288282594,x:214.42673274576924,score:0.51611328125,name:"nose"}, {y:84.61684727250136,x:221.80983627909686,score:0.7265625,name:"left_eye"}, {y:87.59059985661885,x:202.12153237356293,score:0.59130859375,name:"right_eye"}, {y:92.85449529945058,x:234.93538334278358,score:0.814453125,name:"left_ear"}, {y:99.07546188234281,x:188.58581196413604,score:0.6806640625,name:"right_ear"}, {y:149.86859452983884,x:271.3040866650822,score:0.7246093153953552,name:"left_shoulder"}, {y:162.78905492065545,x:158.09624324078422,score:0.82666015625,name:"right_shoulder"}, {y:236.41516213602512,x:280.8747980656871,score:0.728515625,name:"left_elbow"}, {y:246.8062369181066,x:156.3188420992395,score:0.55859375,name:"right_elbow"}, {y:305.46100866896046,x:286.61722490605007,score:0.6591796875,name:"left_wrist"}, {y:313.80120003234475,x:152.9006975047454,score:0.70849609375,name:"right_wrist"}, {y:304.5039375289,x:251.342317172392,score:0.87646484375,name:"left_hip"}, {y:303.68360752741575,x:189.6796075527766,score:0.8740234375,name:"right_hip"}, {y:431.38422581120494,x:237.66987231438497,score:0.70703125,name:"left_knee"}, {y:430.01698132540423,x:189.6796075527766,score:0.8017578125,name:"right_knee"}, {y:529.8258287888553,x:229.19295650242066,score:0.6884765625,name:"left_ankle"}, {y:534.747908937738,x:201.71134233782658,score:0.578125,name:"right_ankle"}];//以后帧动作,抽帧并且辨认后,取人体辨认后果中的keypointsconst frame = [{y:154.06250001297832,x:258.7499999883252,score:0.728515625,name:"nose"}, {y:143.12500001305142,x:254.37499998835446,score:0.56298828125,name:"left_eye"}, {y:143.75001908653357,x:255.937499988344,score:0.69482421875,name:"right_eye"}, {y:143.984394086532,x:229.99999998851743,score:0.43115234375,name:"left_ear"} ,{y:146.17187501303107,x:236.09374998847667,score:0.4919433891773224,name:"right_ear"}, {y:201.4062690861481,x:205.9375190621646,score:0.51416015625,name:"left_shoulder"}, {y:202.03125001265758,x:227.96874998853102,score:0.66259765625,name:"right_shoulder"}, {y:281.25001908561427,x:234.6874999884861,score:0.26416015625,name:"left_elbow"}, {y:270.6250190856853,x:254.06249998835656,score:0.278076171875,name:"right_elbow"}, {y:246.09376908584932,x:289.06249998812257,score:0.1997070610523224,name:"left_wrist"}, {y:238.43750001241418,x:300.62499998804526,score:0.50927734375,name:"right_wrist"}, {y:321.5624618648858,x:218.59376906208004,score:0.58154296875,name:"left_hip"}, {y:323.43750001184594,x:224.06249998855716,score:0.5615234375,name:"right_hip"}, {y:453.43750001097675,x:217.34376906208837,score:0.6103515625,name:"left_knee"}, {y:455.6250000109622,x:214.06249998862396,score:0.51416015625,name:"right_knee"}, {y:572.5000000101808,x:215.31249998861563,score:0.403564453125,name:"left_ankle"}, {y:593.1250000100429,x:216.0937499886104,score:0.52294921875,name:"right_ankle"}];//新建比拟器,执行比拟 const poseComparer = new AiSports.calc.PoseComparer(); const result = poseComparer.compare(sample, frame); console.log(result);//输入后果//{items:// [{key:"head",score:0.4327263684686711,summary:"头部偏转类似度"},// {key:"trunk",score:0.8407704975917485,summary:"躯干状态类似度"},// {key:"left_hand",score:0.2155245751055277,summary:"左手类似度"},// {key:"right_hand",score:0.21361728579451628,summary:"左手类似度"},// {key:"left_foot",score:0.5147016736506456,summary:"左脚类似度"},// {key:"right_foot",score:0.5190758118853293,summary:"右脚类似度"}],// score:0.5110266728697409 //整体类似度评分//}五、类似度后果利用获得类似后果后,您能够依据静止(动作)的要求,间接进行总体评分或指定分区的评分判断(倡议类似度在≥0.80时视为通过)。若有更精密的要求,也能够再配置一些增强规定进行再检测,详情请参考集成文档的body-calc相干章节。 ...

March 23, 2023 · 1 min · jiezi

关于小程序:uniapp开发小程序判断文本是否有溢出

最近开发小程序遇到须要通过文本长度管制tooltip展现css设置文字在元素中不够宽度显示为… 并且同时能够展现气泡(前提是气泡是自定义的款式),文字够宽度,则不显示气泡。并且追随手机屏幕宽度变动。 小程序如何监听和实现呢? 效果图展现 解决办法: 溢出暗藏css款式.hide { word-break: break-word; //换行模式 overflow: hidden; text-overflow: ellipsis; //修剪文字,超过2行显示省略号 display: -webkit-box; -webkit-line-clamp: 2; //此处为下限行数 -webkit-box-orient: vertical;}获取到文本离页面顶部的间隔let query = wx. createSelectorQuery() .in(this); query .select('.toll-station-name-en').boundingClientRect(data => { console.log("节点离页面顶部的间隔为" + data.height); if (data.height > 40) {//管制你文本展现的最大高度 this.enOverflow = true } }).exec();残缺代码<template> <view class="detail-content"> <view class="block"></view> <view class="content"> <view class="park-lot"> <view class="toll-station" style="margin-right: 30rpx;"> <view class="toll-station-name toll-station-name-en" :class="{hide:enOverflow}" :style="{height:(exOverflow&&!enOverflow?'40px':'auto')}" @click.stop="showEn()" ref="enStation">{{detail.enStation}}</view> <view class="tooltip" v-if="showToolTipEn"> {{detail.enStation}} </view> </view> <image src="../../static/to.png" mode="" class="to"></image> <view class="toll-station" style="margin-left: 30rpx;"> <view class="toll-station-name toll-station-name-ex" :class="{hide:exOverflow}" :style="{height:(enOverflow&&!exOverflow?'40px':'')}" @click.stop="showEx()"> {{detail.exStation}} </view> <view class="tooltip" v-if="showToolTipEx"> {{detail.exStation}} </view> </view> </view> </view> </view></template><script> export default { data() { return { detail: { enStation: '我不暗藏', exStation: '我暗藏啦我暗藏啦我暗藏啦我暗藏啦我暗藏啦我暗藏啦' }, showToolTipEn: false, showToolTipEx: false, enOverflow: false, //是否溢出 exOverflow: false, //是否溢出 } }, onLoad() { this.judgmentOverflow() }, methods: { judgmentOverflow() { let query = wx. createSelectorQuery() .in(this); query .select('.toll-station-name-en').boundingClientRect(data => { console.log("节点离页面顶部的间隔为" + data.height); if (data.height > 40) { this.enOverflow = true } }).exec(); query .select('.toll-station-name-ex').boundingClientRect(data => { console.log("节点离页面顶部的间隔为" + data.height); if (data.height > 40) { this.exOverflow = true } }).exec(); }, showEn() { if (!this.enOverflow) { return } this.showToolTipEn = !this.showToolTipEn }, showEx() { if (!this.exOverflow) { return } this.showToolTipEx = !this.showToolTipEx }, } }</script><style lang="scss" scoped> .detail-content { .content { width: calc(100% - 60rpx); margin: 0 30rpx 0; background-color: #fff; border-radius: 10rpx; height: 1018rpx; .park-lot { display: flex; padding-top: 60rpx; margin: 0 30rpx; .toll-station { width: 40%; text-align: center; position: relative; .toll-station-name { min-height: 39rpx; // max-height: 78rpx; // height: auto; font-size: 32rpx; font-weight: 500; color: #333333; line-height: 20px; } .hide { word-break: break-word; //换行模式 overflow: hidden; text-overflow: ellipsis; //修剪文字,超过2行显示省略号 display: -webkit-box; -webkit-line-clamp: 2; //此处为下限行数 -webkit-box-orient: vertical; } //气泡提示框 .tooltip { width: 120px; height: auto; background: #000000; opacity: 0.69; padding: 8px; position: relative; font-size: 13px; border-radius: 6px; font-weight: 400; color: #FFFFFF; line-height: 15px; position: absolute; top: 95rpx; left: 0; z-index: 999; } .tooltip::before { content: ''; width: 0; height: 0; border-width: 8px; border-color: transparent transparent #000 transparent; border-style: dashed dashed solid dashed; position: absolute; top: -16px; left: 45%; } } .to { width: 67rpx; height: 18rpx; margin-top: 26rpx; background-size: 100%; } } } }</style>有用关注下哦~ ...

February 28, 2023 · 2 min · jiezi

关于小程序:火山引擎推出一站式小程序监控方案

背景小程序作为轻量级的利用倒退迅速,国内已有多家小程序厂商相继推出。为了洞察用户实在体验及程序本身运行状况,监控已成为开发套件中必不可少的一环。随着业务愈来愈简单,各厂商小程序管理后盾收费提供的监控能力逐步满足不了大部分业务与市场的需要。以后有小程序监控需要的用户都面临以下痛点: 仅反对 1 ~ 2 个小程序平台,不反对支流小程序跨端开发框架,如 uni-app 和 Taro。异样监控、申请监控、启动/运行时性能监控能力单薄。SDK 配置繁琐、体积大、性能损耗高,接入老本高。基于以上痛点,火山引擎 APM 团队针对小程序监控的的需要场景进行摸索,再通过字节跳动外部多条业务线利用积淀和多轮迭代,打造出了一站式小程序监控平台,旨在为开发者提供可跨平台、监控能力欠缺、简略易用的小程序监控服务。 火山引擎小程序监控的性能亮点灵便低成本的接入形式,适配多厂商、多框架反对抖音、微信、支付宝、百度、飞书等多个厂商的原生小程序接入,也适配三方框架Uni App和Taro。低成本接入,仅需两行代码即可实现初始化。性能损耗可控,中高端机型齐全初始化仅需 7 ~ 12 ms。反对按需加载适配层以及集成模块,且蕴含丰盛的生命周期,满足不同业务场景的自定义配置需要。 欠缺的启动和运行时性能指标体系小程序启动过程是指从用户关上小程序至小程序首页渲染实现。 SDK 侧会收集该阶段全副指标,包含下载耗时、JS注入耗时、App 各阶段耗时、首次 Page 各阶段耗时、FR(firstRender))、FP(firstPaint-,firstPaint,-%E9%A1%B5%E9%9D%A2%E9%A6%96%E6%AC%A1))、FCP(firstContentfulPaint) 等等惯例性能指标。 运行时性能包含页面切换性能、setData 性能 setData 性能:包含 setData 次数、耗时、频率以及大小。小程序页面切换过程是指从用户触发路由切换事件至新页面渲染实现。SDK 侧会收集该阶段全副指标,包含路由切换耗时、页面构建耗时、页面渲染耗时、FR、FP、FCP 等等惯例性能指标。 从小程序启动到页面切换,咱们不仅有欠缺的性能指标体系,而且各项指标均可在「自定义看板」中进行任意组合以称心业务方的个性化需要。除此之外,字节外部依据实践经验预约义了一套默认参考线,当然也反对用户依据业务本身复杂程度来动静调整参考线。 性能领先体验,点击体验平台能力概览 发现问题:通过配置JS 谬误或性能报警来第一工夫洞察线上运行状况,也可通过看板订阅的形式定时推送可视化图表发送至你的邮箱或其余形式。剖析问题: 异样问题:通过 sourcemap 反解将艰涩难懂的谬误堆栈还原至开发环境,再通过数据摸索回溯产生谬误前的用户操作行为,包含网络申请、路由跳转、setData 调用等等,帮你更疾速定位问题所在。性能问题:配合默认指标参考线,性能监控总览能直观展现启动 / 运行时性能在某段时间内的达标水平,而后针对于异样指标,进入数据摸索进一步下钻至单次 Session 信息,Session 囊括了首屏 冷启动 阶段、页面渲染阶段等等,直观展现线上实在用户体验的瀑布图,助你更快发现性能根因所在。成果验证:品质优化上线后,可通过以下性能来灵便量化和验证优化成果。 天级报表:字节工程师在晋升前端利用品质的过程中,预设计的一系列与业务指标强相干的指标看板。以天为粒度展现所选工夫周期内小程序的体现分以及各外围指标的趋势图,可直观比照品质优化前后外围指标的变动。自定义看板:用户可灵便配置各项性能或异样指标,并可自定义工夫维度来观测品质优化前后外围指标的变动。典型利用场景察看并改良页面性能「性能监控」提供以冷启动总耗时、小程序初始化耗时、下载耗时、JS注入耗时等多项指标并依照 AVG、PTC75、PTC90、PCT95排序得出性能欠佳页面和劣化Top 5,帮忙您更好的发现和定位优化对象。 而后,咱们反对更进一步的数据下钻与现场还原,进入「数据摸索」下的「Session Tab」具体查看某单次会话的详细信息。 同时,针对单个会话的某次页面拜访,咱们能够在「View Tab」中通过「启动性能指标」和「资源加载瀑布图」察看到首次冷启动的残缺链路,从而找出问题要害。 联合「Session Tab」和「View Tab」视图,咱们初步判断:该页面的 FCP 与网络申请 user_info 以及响应回调中的 setData 是强相干,以此来推动该申请速度的优化或 setData 逻辑优化。 ...

February 23, 2023 · 1 min · jiezi

关于小程序:小程序线上调试

连贯手机到电脑(只反对安卓手机)须要关上usb调试模式微信关上调试模式在微信内关上http://debugxweb.qq.com/?inspector=true,跳转之后就是关上了关上想要调试的小程序在chrome中关上调试页面输出chrome://inspect/#devices找到Device => WebView in com.tencent.mminspect即可

February 16, 2023 · 1 min · jiezi

关于小程序:从0到100-基于微信云开发的驾校预约学车小程序

背景随着机动车逐步走进寻常百姓家中,学车也随之被人们提上了日程,这使得汽车驾驶培训行业失去迅猛发展。挪动互联网技术的广泛应用,使手机约车成为可能,如何正当地调配已有资源,进步资源利用率,加强驾校服务水平,己成为驾校越来越迫切的需要。驾校学车预约小程序使预约者只需拿起手机,就能够线上约车,能够做到“足不出户选教练”,这样可能无效缩小学习者的等待时间,从而为学员提供更优质的服务。 本零碎蕴含学员端,教练端,治理端三方,不前后端残缺,包含布告,驾校教练预约,科目培训预约,后盾治理,用户治理,预约名单治理,预约记录治理与导出,我的预约,历史浏览,我的珍藏等模块,采纳腾讯提供的小程序云开发解决方案,毋庸服务器和域名。 概要设计本我的项目分为学员端,驾校教练端,后盾端3个组成部分: 后盾端:能够增加和设定教练的根本信息,账号,登陆密码等。驾校教练端:能够编辑本人的个人资料(头像,简介,星级等),设定预约时段排期(可预约时段,各时段人数限定), 在现场核销用户的预约码。学员端:抉择本人须要的教练和时段,下单预约,预约胜利后到健身房出示预约码给教练或者工作人员核销 数据库设计MeetModel.DB_STRUCTURE = { _pid: 'string|true', MEET_ID: 'string|true', MEET_ADMIN_ID: 'string|true|comment=增加的管理员', MEET_TITLE: 'string|true|comment=题目', MEET_JOIN_FORMS: 'array|true|default=[]|comment=表单字段设置', MEET_DAYS: 'array|true|default=[]|comment=最近一次批改保留的可用日期', MEET_CATE_ID: 'string|true|comment=分类编号', MEET_CATE_NAME: 'string|true|comment=分类冗余', MEET_FORMS: 'array|true|default=[]', MEET_OBJ: 'object|true|default={}', MEET_CANCEL_SET: 'int|true|default=1|comment=勾销设置 0=不允,1=容许,2=仅开始前可勾销', MEET_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=应用中,9=进行预约,10=已敞开', MEET_ORDER: 'int|true|default=9999', MEET_VOUCH: 'int|true|default=0', MEET_QR: 'string|false', MEET_PHONE: 'string|false|comment=登录手机', MEET_PASSWORD: 'string|false|comment=登录明码', MEET_TOKEN: 'string|false|comment=以后登录token', MEET_TOKEN_TIME: 'int|true|default=0|comment=以后登录token time', MEET_MINI_OPENID: 'string|false|comment=小程序openid', MEET_LOGIN_CNT: 'int|true|default=0|comment=登陆次数', MEET_LOGIN_TIME: 'int|false|comment=最近登录工夫', MEET_ADD_TIME: 'int|true', MEET_EDIT_TIME: 'int|true', MEET_ADD_IP: 'string|false', MEET_EDIT_IP: 'string|false',};技术使用本我的项目应用微信小程序平台进行开发。应用腾讯专门的小程序云开发技术,云资源蕴含云函数,数据库,带宽,存储空间,定时器等,资源配额价格低廉,无需域名和服务器即可搭建。小程序自身的即用即走,适宜小工具的应用场景,也适宜疾速开发迭代。云开发技术采纳腾讯外部链路,没有被黑客攻击的危险,不会 DDOS攻打,节俭防火墙费用,安全性高且免保护。资源承载力可依据业务倒退须要随时弹性扩大难点实现/** 获取日期设置 */ async getDaysSet(meetId, startDay, endDay = null) { let where = { DAY_MEET_ID: meetId } if (startDay && endDay && endDay == startDay) where.day = startDay; else if (startDay && endDay) where.day = ['between', startDay, endDay]; else if (!startDay && endDay) where.day = ['<=', endDay]; else if (startDay && !endDay) where.day = ['>=', startDay]; let orderBy = { 'day': 'asc' } let list = await DayModel.getAllBig(where, 'day,dayDesc,times', orderBy, 1000); for (let k = 0; k < list.length; k++) { delete list[k]._id; } return list; } // 按时段统计某时段报名状况 async statJoinCnt(meetId, timeMark) { let whereDay = { DAY_MEET_ID: meetId, day: this.getDayByTimeMark(timeMark) }; let day = await DayModel.getOne(whereDay, 'times'); if (!day) return; let whereJoin = { JOIN_MEET_TIME_MARK: timeMark, JOIN_MEET_ID: meetId }; let ret = await JoinModel.groupCount(whereJoin, 'JOIN_STATUS'); let stat = { //统计数据 succCnt: ret['JOIN_STATUS_1'] || 0, //1=预约胜利, cancelCnt: ret['JOIN_STATUS_10'] || 0, //10=已勾销, adminCancelCnt: ret['JOIN_STATUS_99'] || 0, //99=后盾勾销 }; let times = day.times; for (let j in times) { if (times[j].mark === timeMark) { let data = { ['times.' + j + '.stat']: stat } await DayModel.edit(whereDay, data); return; } } }学员端UI设计 ...

February 7, 2023 · 2 min · jiezi

关于小程序:国产工具好强大一个可以允许小程序运行在任意APP的容器技术

小程序的定义提到小程序,大多数第一眼恐怕想到的就是微信小程序或者是支付宝小程序,这也是因为微信和支付宝两者的用户基量大,很多人都是从应用微信或者支付宝开始晓得小程序的,也正因为如此,小程序才被特指微信小程序或者是支付宝小程序。 也因而很多人一听到小程序下意识的就会认为是指微信小程序或者是支付宝,可事实上,小程序是一个宽泛的概念,并不特指某一个代表,微信小程序或者是支付宝小程序都只能算作是小程序的一个代表。 在这里集体了解小程序应该指的是一种轻利用,能够不须要下载并且装置就能够在app内运行的轻利用,小程序体现了用完即走的理念,也实现了用户触手可及的幻想,用户只须要扫一下或者是搜一下就能够拜访小程序,因而用户也不必放心装置小程序就相当于是装置一个app一样,小程序真正做到了随处可用。 小程序的接入小程序既然这么弱小,那么是不是除了微信,支付宝这些大型的APP才具备运行小程序的能力呢? 答案当然不是。尽管相干互联网大厂并没有将这些小程序的运行能力给凋谢进去,然而咱们仍然能够借助于一些技术来实现小程序的运行,这种运行能力咱们也称之为小程序容器技术。 上面咱们来看一下一款比拟热门的小程序容器技术——FinClip,如下是官网的一个介绍视频。 <video id="video" onplay="videoPlay()" preload="none" controls="controls" width="100%" poster="https://public-1251849568.cos.ap-guangzhou.myqcloud.com/homeSite/picture/intro-cover.jpg" src="https://public-1251849568.cos.ap-guangzhou.myqcloud.com/homeSite/video/finclipv5.mp4"></video> 简略来说,不论是挪动 App,还是电脑、电视、车载主机等设施,在集成FinClip小程序 SDK之后,都能疾速取得运行小程序的能力,这就是FinClip的能力。 FinClip是由凡泰极客公司推出的小程序容器技术,一个能够让任何 APP 都能具备小程序运行能力的前端容器技术,只需简略集成 FinClipSDK ,即可在 iPhone、Android、Windows、Linux、macOS、统信等平台下的利用中运行你的小程序,这意味着,挪动端、PC 端、车载设施、智能电视、智能手表都能运行小程序了。同时,它还提供一个后盾管理系统,对立治理小程序的上架和下架。 FinClip的劣势FinClip小程序容器技术次要有如下几点劣势: 多平台终端的兼容: 该技术自带终端小程序SDK,简略集成了之后就能够在 iPhone,Android,Windows,Linux,macOS等平台下运行你的小程序。 开发体验好: FinClip针对小程序的开发语法,SDK的体积大小以及开发者工具都进行了相应的设计优化,每个平台中的小程序 SDK 都分为外围与拓展两局部,开发者可依据业务场景灵便选用,并且挪动 App 在集成外围 SDK 后的打包体积不超过3 MB。学习门槛低: FinClip兼容小程序语法,开发者不须要学习新的小程序语言,就能够在集成了FinClip小程序 SDK的APP中运行,换句话说,你只有在你的APP中集成了FinClip的SDK,你就能够应用你相熟的开发语言来运行你的小程序。 FinClip的生态能力很强,利用场景也很宽泛: FinClip曾经落地银行证券、社交 IM、政务民生、传媒教育、文化娱乐、生存服务等多个行业,开发者能够依据已有 App 的开发语言,抉择 iOS,Android,Flutter,React Native,uni-app 中的小程序 SDK。FinClip也提供了本人的IDE:FIDE。该编辑器的界面与微信小程序的开发工具相似,自带调试和真机预览,简略易上手,同时反对小程序生成 APP,能够将已有小程序代码导出为 IOS 与 Android 中可用的工程文件(也是近期开发者最喜爱的性能)FinClip的开发通过官网提供的一些demo,咱们能够很疾速的相熟FinClip的开发,并且可能本人独立搭建一个小程序工程,赶快来试试吧。 总结咱们能够通过如下流程图来相熟FinClip容器技术: FinClip当初反对多种应用与部署计划,SaaS/私有化都能够,真正的开箱即用,而且 SaaS 版,每月领有 10,000 次收费公布调用,感兴趣的敌人能够尝试体验一下。

January 16, 2023 · 1 min · jiezi

关于小程序:魔方带壳截图让你的截图看起来更加高大上

1、什么是带壳截图咱们在日常工作和生存中,往往须要截图去做汇报或分享。普通人的做法:手机或电脑截图,而后就拿去汇报或分享。这样你的截图显得平平无奇,没有给人眼前一亮的感觉。然而,如果咱们给这张截图穿上一件“衣服”,把它装扮一下,让她出类拔萃,不同凡响,那么就会给人留下粗浅的印象!! 无设施边框带设施边框那给截图穿上一件什么“衣服”能力让它显得分外难看呢?咱们能够给她"穿上"设施的边框图,让她看起来更像是有人给手机或者电脑拍了一张难看的照片,而不是截图,这样就不会给人很一般的感觉了。 2、反对哪些设施目前「魔方带壳截图」反对的设施蕴含iPhone系列、iPad系列、MacBook系列以及iWatch系列。 iPhoneiPadMacBookiWatch3、魔方带壳截图小程序魔方带壳截图小程序,是一款收费的小程序,扫码即可立马体验:

January 1, 2023 · 1 min · jiezi

关于小程序:用友开发者中心全新升级YonBuilder移动开发入门指南

据说用友新上线了全新的开发者核心,有YonBuilder利用开发,集成开发、数据开发、智能与自动化、DevOps 等板块,自己作为用户老客户,对其中的挪动开发比拟感兴趣,本文重点解说其中的挪动开发平台。登录后,如果没有进行企业认证,须要先填相干材料进行企业认证。认证通过后再登录网站,会疏导开启体验沙箱,开启沙箱后,会进入以下界面:接着点击左侧 【挪动开发】导航, 进入挪动开发工作台:在这里能够创立挪动利用创立实现后,进入利用详情页面,能够进行APP图标、启动图、证书的上传,能够增加插件(封装好的功能模块,在代码中集成调用),能够进行打包操作,经营治理中还有版本更新性能。应用YonBuilder挪动开发平台开发,有多种模式,能够应用其开发工具 YonStudio 拖拽式开发,也能够应用HTML ,JavaScript 语言进行开发,也能够应用avm.js 框架开发。这里举荐用avm.js 框架开发,其具备以下长处:应用 avm.js 一个技术栈可同时开发 Android & iOS 原生 App、小程序和 iOS 轻 App,且多端渲染成果对立;全新的 App 渲染引擎 DeepEngine 3.0 不依赖 webView,提供百分百的原生渲染,保障 App 性能和体验与原生 App 统一;

December 29, 2022 · 1 min · jiezi

关于小程序:微信小程序归结

*是的,在这个框架满天飞的年代,我既然有有幸应用了原生小程序开发我的项目,除了麻烦些,倒也不是满载而归,耕耘总有收货嘛,写博客自身不是为了炫技还是什么,单纯的是忘性不好,有些知识点 本人是花了工夫去查找的,工夫久了,下次会忘,所以仅做记录的成份高一些,前言不搭后语莫怪。而后早上看到一句诗也不错:追风赶月莫停留,平芜止境是春山。回正题吧:* 上传头像changeAvatar() { var that = this; wx.chooseImage({ count: 1, // 最多能够抉择的图片张数,默认9 sizeType: ['original', 'compressed'], // original 原图,compressed 压缩图,默认二者都有 sourceType: ['album', 'camera'], // album 从相册选图,camera 应用相机,默认二者都有 success: async function (res) { var avatar = res.tempFilePaths; await that.filebBatchDeletes() let resImage = await uploadImage(avatar[0]) if (resImage.data.code == 200) { that.setData({ avatar: avatar[0], picId: resImage.data.result }) } }, fail: function () { // console.log("上传图片没有胜利"); }, complete: function () { // complete } }) },export const uploadImage = (uploadFile: string) => { return new Promise((resolve, reject) => { wx.uploadFile({ url: config.otherBaseUrl + 'load/file-upload', filePath: uploadFile, header: { "Content-Type": "multipart/form-data", 'token': wx.getStorageSync('accessToken'), }, formData: { 'caseNum': wx.getStorageSync('userId'), "caseType": 'image', }, name: 'file', success: (res) => { const data = JSON.parse(res.data) resolve({ data }) }, fail: (err) => { reject(err) } }) })}前端小程序拿到图片流解决成Base64async readImageByDataIds(id: string) { let res = await getPicStream(`/readImageByDataId/${id}`) this.setData({ processPic: res }) },export const getPicStream = (url:string) => { return new Promise((resolve,reject) => { wx.request({ url: config.baseUrl + url, header: { 'X-Access-Token': wx.getStorageSync('token'), 'X-TIMESTAMP': getDateTimeToString(), }, responseType: 'arraybuffer', success: res => { let url ='data:image/png;base64,'+ wx.arrayBufferToBase64(res.data) resolve(url) }, fail: err => { reject(err) } }) })}返回上一个页面并触发上一个页面的办法因为小程序不像浏览器会主动刷新,所以须要手动刷新var pages = getCurrentPages(); var beforePage = pages[pages.length - 2]; wx.navigateBack({ delta: 1, success: function () { beforePage.getInfo(); // 执行前一个页面的getInfo办法 } })Base64模式的文件做预览preClick(event: any) { if (event.detail.type == 'file') { const fileSystemManager = wx.getFileSystemManager() try { let strPath = event.detail.url.substring(event.detail.url.indexOf(',') + 1) fileSystemManager.writeFileSync(wx.env.USER_DATA_PATH + `/${event.detail.materialName}`, strPath, "base64"); wx.openDocument({ filePath: wx.env.USER_DATA_PATH + `/${event.detail.materialName}` }) } catch (err) { console.log("调用失败", err); } } return true }v-button自定义通明用于绑定或获取用户信息<button bind:getuserinfo="onGetUserInfo" open-type='{{openType}}' plain='{{true}}' class="container"> <slot name="img"></slot></button>Component({ /** * 组件的属性列表 */ options: { multipleSlots: true // 在组件定义时的选项中启用多slot反对 }, // externalClasses: ['ex-btn-class'], properties: { openType: { type: String }, imageSrc: { type: String }, bindgetuserinfo: { type: String } }, /** * 组件的初始数据 */ data: { }, /** * 组件的办法列表 */ methods: { onGetUserInfo(event) { this.triggerEvent('getuserinfo', event.detail, {}) }, }}).container{ padding: 0 !important; border:none !important;}一个小程序跳转到另一个小程序async getPayInfos(item:any) { const { buildId, id, estateId } = item let params = { buildId, estateId, houseId: id, } let infos = await getPayInfo(params) let that = this wx.navigateToMiniProgram({ appId: 'wxe7550', //appid path: `pages/index/index?token=${infos.data.payData}`,//path success(res) { that.data.isPay = true that.data.mchOrderNo = infos.data.mchOrderNo } }) },wxswxs是小程序的一套脚本语言 ,联合WXML,能够构建出页面的构造  wxs不依赖于运行时的根底库版本  能够在所有版本的小程序中运行wxs与javascript是不同的语言  有本人的语法 并不和javascript统一wxs的运行环境和其余javascript代码是隔离的  wxs不能调用其余JavaScript文件中定义的函数  也不能调用小程序提供的APIwxs函数不能作为组件的事件回调与es5类似,不能用es6的语法这里作为独自文件应用 ...

December 18, 2022 · 5 min · jiezi

关于小程序:短说通用版-380测试版发布积分清零排行榜全新表情包等功能

Hi 大家好, 我是给你们带来惊喜的经营小番茄。 本期小番茄为大家汇报一下短说最新过程:短说通用版 3.8.0测试版,本次更新大量性能,次要围绕大家心心念念的积分清零、全新表情包、数据导出、积分排行榜等,波及平台:H5、App、微信小程序。可查看此文章: 新增性能: 新增数据导出:用户数据、问卷数据;个人主页新增全副分类,且反对将公布的内容置顶到个人主页;新增反对挪动端首页公布栏的内容类型自定义排序/显示/暗藏/;新增积分行为规定:勾销点赞、勾销关注用户、勾销退出版块、用户被关注、用户被点赞。反对自定义设置积分处分或扣除的规定;新增匿名性能可针对版块或版块分类独自开启;新增积分对立清零性能;新增反对用户将未通过AI审核的内容手动提交至人工二次审核;新增治理后盾反对查看版块内新增成员、 新增内容、新增浏览的数据走势;全新开源的可恶表情包替换原有的表情包;排行榜(榜单)新增反对积分排行榜;用户端版主/超级版主新增了迁徙内容至其余版块的性能;马甲模块新增马甲用户反对自定义用户等级、可反对编辑共性签名;次要性能介绍: 01 治理后盾新增数据导出性能:用户数据、问卷数据反对导出 ① 用户数据导出 用户列表减少用户数据“导出数据”按钮,导出数据反对自定义勾选字段 ② 问卷数据导出 问卷列表减少用户数据导出性能,导出数据反对自定义勾选字段 02 小名片/个人主页新增全副分类,反对将曾公布过的内容置顶在个人主页 ① 个人主页公布的内容,减少全副分类 ② 内容置顶至小名片/主页 反对将曾公布的内容置顶至个人主页/小名片 03 治理后盾新增反对挪动端首页公布栏的内容类型自定义排序/显示/暗藏 ① 挪动端首页公布栏内容类型反对自定义 治理后盾-社区配置-公布配置,反对暗藏/显示/拖拽排序 04新增积分行为规定 新增积分行为规定:勾销点赞、勾销关注用户、勾销退出版块、用户被关注、用户被点赞。反对自定义设置积分处分或扣除的规定。 05匿名性能可针对版块或版块分类独自开启 匿名性能可针对版块或版块分类独自开启可设置局部版块为匿名版块,减少社区不同的玩法。同时也可仅反对某版块的某分类独自设置匿名。 06新增积分对立清零性能 某些经营场景下,会须要反对年底积分清零,新版本曾经新增此性能,可在后盾手动对立清零某种类型的积分。 07新增反对用户将未通过AI审核的内容手动提交至人工二次审核 新增反对用户将AI审核不通过的内容再次提交人工审核(版主/超版前台审核、管理员后盾审核) AI审核较为严格,容易被误审核,因而推出可提交给人工审核的性能,此性能是否开启可在后盾配置。 08治理后盾反对查看版块内新增成员、 新增内容、新增浏览的数据走势 治理后盾反对查看版块内新增成员、 新增内容、新增浏览的数据走势 版块列表-找到相应版块,数据统计-查看更多。 09全新开源的可恶表情包 全新的可恶表情包 新版本仅反对新版本表情包(老数据已做解决,保留老版本表情包展现) 10排行榜新增积分排行榜 排行榜/榜单新增积分排行榜,积分榜是用户激励的重要组成部分,排行榜新增积分榜单,可独自配置导航,也可在榜单列表中查看。 11用户端版主/超级版主可在用户端迁徙内容至其余版块 用户端版主/超级版主可在用户端迁徙内容至其余版块 用户公布的内容偶然会呈现内容不合乎版块分类的状况,版主/超版可在用户端操作移帖了,是不是比管理员在后盾操作更不便了呢~ 12马甲模块新增马甲用户反对自定义用户等级、可反对编辑共性签名 马甲号反对编辑等级、ip属地和共性签名 为了让马甲看起来更像一个实在的用户,咱们给马甲账号退出了可编辑等级、增加ip属地以及共性签名的性能。ip属地需填写号段,倡议联合“ip地址生成器”工具一起应用。 性能优化 优化了治理后盾帖子、视频、动静、资讯等内容治理页面,晋升经营治理的操作效率;优化了治理后盾积分日志,反对依照加分、减分筛选日志;优化新增了治理后盾反对设置前端每个用户可创立的圈子数量;治理后盾反对配置评论的默认排序形式;优化了治理后盾问卷治理页面,减少版块筛选性能;治理后盾公布内容反对搜寻版块和分类;AI审核反对针对审核类型进行开启和敞开。;治理后盾设置版主时反对通过输出昵称、UID、手机号搜寻用户;用户昵称反对应用常见特殊字符;用户帐号登记协定反对治理后盾编辑;挪动端评论框疏导文案反对后盾自定义;治理后盾发布公告反对抉择作者;“剥比”性能减少具体的解释阐明;优化了治理后盾评论治理页面链接跳转性能;优化了草稿箱保留机制;挪动端邀请记录页面反对点击查看用户集体小名片;积分商城虚构商品交易流程优化,移除发货流程。频道信息流列表中反对展现内容的加精和热门标签;治理后盾反对将马甲用户帐号手动设置IP地址;小程序端内部链接点击后减少实现复制的提醒;优化了在版块内公布流程,优先提醒用户进行分类抉择;治理后盾音讯揭示减少创立版块审核音讯;优化了领取渠道在后盾敞开后,前端不再显示;优化用户版块页面数据空状态款式;优化了列表图片款式;优化调整了用户最初拜访工夫机制;反对问答模块可配置问题和评论需通过后盾审核;挪动端内容详情页字体款式优化。短说产品介绍: 短说社区产品是想天软件研发的社区论坛零碎,集社区,电商,常识付费性能于一体,笼罩Web网页、微信小程序、APP、H5网页全平台。 可交付源码版本,也可交付加密版本。均为私有化部署,一次付费一生应用,数据齐全私有化。 目前短说产品有两个方向: ①短说通用版:次要服务于经营行业,比方行业社区、粉丝社区、产品型社区、车友社区、政务民生等等; ②短说企业版:次要用于企业外部社区,用于员工沟通交流的平台,进步团队凝聚力,帮忙做好企业文化建设。

November 27, 2022 · 1 min · jiezi

关于小程序:微信小程序子组件使用父组件传入的样式

微信小程序应用externalClasses能够让父组件的款式更改到子组件外面。 子组件: 子组件js:Component({ externalClasses: ['my-class'], // 组件选项 options: { styleIsolation: 'apply-shared', },})子组件wxml:<view class="my-class">测试父组件传递的款式</view>父组件: 父组件wxml:<childern my-class="check-child"></childern>父组件wxss:.check-child { background: red;}下面就能够使子组件应用父组件传入的款式了。子组件定义的styleIsolation一共有三个值:isolated 示意启用款式隔离,在自定义组件内外,应用 class 指定的款式将不会相互影响(个别状况下的默认值);apply-shared 示意页面 wxss 款式将影响到自定义组件,但自定义组件 wxss 中指定的款式不会影响页面;shared 示意页面 wxss 款式将影响到自定义组件,自定义组件 wxss 中指定的款式也会影响页面和其余设置了 apply-shared 或 shared 的自定义组件。(这个选项在插件中不可用。)留神:我在子组件应用styleIsolation: 'shared' 时候父组件设置的款式在子组件是有效的,应用的时候须要留神

October 20, 2022 · 1 min · jiezi

关于小程序:关于打开公众号推文

关联公众号1.首先,登录微信公众号的后盾,而后找到小程序,并点击小程序管理; 其次,在小程序管理中,找到疾速注册并认证小程序,点击当前用管理员身份验证一下。而后搜寻想要关联的小程序,点击下一步,就关联胜利了。 2.小程序与公众号关联的时候,有一些事项是要理解并留神的: 首先,一个公众号个别能够关联10个同一主体的小程序,而小程序则能够绑定最多50个公众号,能够说相当不便了; 其次,关联的时候,有两个选项须要特地留神:显示在公众号材料页和给已关注公众号的用户发送告诉,这两个选项,能够依据理论状况来抉择。 关上公众号推文关上关联的公众号推文须要用到web-view标签 具体请看 web-view | 微信凋谢文档 (qq.com) .wxml文件.js文件创立web-view文件 web-view.jsweb-view.wxml

October 17, 2022 · 1 min · jiezi

关于小程序:js对比对象数组的原数据和传递过来的新数据如果有新数据则替换成新数据否则保留原数据

最近新开发一个性能,点击立刻下单,会把售罄,库存有余的商品id和异样类型返回给我,我须要将状态在页面上展现:须要做的就是将我上一次的商品列表和最新返回的商品列表进行比照,最新的数据是不蕴含售售罄和库存有余的,我须要替换并且保留上一次的蕴含售罄和库存有余,用来在页面上展现标识: 模仿旧列表:var arr1 = [ { id:'1',name:'zhangsan', age:'15'}, { id:'2', name:'lisi', age:'16' }, { id:'3', name:'ani', age:'17'},] 模仿新列表:var arr2 = [ { id:'1',name:'zhangsan', age:'100' }, { id:'2', name:'lisi' },]// 值传递和援用传递function concatFailSpecs(oldList, newList) { let oldList1= oldList.map((item) => { newList.forEach((item2) => { if(item.id == item2.id) { item = item2 } }) return item }); return oldList1;}// 或者function concatFailSpecs(oldList, newList) { return oldList.map(oldItem=> { const newItem = newList.map(newItem=> newItem.id === oldItem.id); return newItem || oldItem; });}实在渲染数据:this.setData({ productList: concatFailSpecs(this.data.productList, res.body.productList),});通过封装的concatFailSpecs办法,就能够把最新返回的数据替换我的老列表里的数据,并且保留售罄和库存有余的商品。因为如果有库存有余或者售罄会另外返回一个FailSpecs列表,外面是异样类型和商品id,我拿到解决过的商品列表和FailSpecs列表比照,将符合条件的异样作为属性增加到productList外面: ...

October 15, 2022 · 1 min · jiezi

关于小程序:关于小程序打开外部链接

一.首先,如果是集体小程序,就不必思考关上内部链接了。这里须要应用web-view组件,具体的请看https://developers.weixin.qq....实现线上的h5通过小程序配置业务域名,通过web-view组件实现内嵌h5页面。间接拿来链接是打不开的。须要配置业务域名,并且在服务器的根目录下形式验证文件。        登录微信公众平台下载效验文件   开发治理——>开发设置——>业务域名——>下载效验文件而后把效验文件放在 npm run build打包后的h5我的项目根目录里 部署上传到线上  留神肯定要打包后放入根目录下,保障能够拜访。 二. 小程序配置业务域名配置业务域名 由上图能够看出 要留神两点  1.h5的我的项目域名必须是https的 2.我的项目链接不能由/api的  正确格局www.baidu.com 三. 通过组件web-view进行传参跳转应用 click点击事件跳转到webview页面  在通过web-view组件跳转到h5我的项目 1.在WXML文件里某个须要触发点击事件的标签外面加上点击事件bindtap=" navigateToURL"。记得带上参数data-url="{{item.url}}" 2.在.js文件上,写入对应的函数如图创立web-view文件夹 3.在app.json外面退出门路。 4.在webview.wxml写入 <web-view src="{{url}}"></web-view> 5.在webview.js文件中写上逻辑

October 12, 2022 · 1 min · jiezi

关于小程序:基于云开发的大学社团招新小程序开发笔记

需要剖析又是一年开学季,万众瞩目的社团招新又开始啦!社团涵盖了文化体育、学术科技、意愿公益等方面。面对着目不暇接的社团活动,你会pick哪一个呢? 概要设计次要性能包含布告告诉,社团风采,社团招新列表,社团培训列表,社团活动列表,社团简介,我的报名,后盾招新/培训/流动项目管理,后盾告诉治理,后盾管理员治理等性能 技术选型应用腾讯专门的小程序云开发技术,云资源蕴含云函数,数据库,带宽,存储空间,定时器等,资源配额价格低廉,无需域名和服务器即可搭建。小程序自身的即用即走,适宜小工具的应用场景,也适宜疾速开发迭代。云开发技术采纳腾讯外部链路,没有被黑客攻击的危险,不会 DDOS攻打,节俭防火墙费用,安全性高且免保护。资源承载力可依据业务倒退须要随时弹性扩大。数据字典NewsModel.DB_STRUCTURE = { _pid: 'string|true', NEWS_ID: 'string|true', NEWS_TITLE: 'string|false|comment=题目', NEWS_DESC: 'string|false|comment=形容', NEWS_STATUS: 'int|true|default=1|comment=状态 0/1', NEWS_CATE_ID: 'string|true|comment=分类编号', NEWS_CATE_NAME: 'string|true|comment=分类冗余', NEWS_ORDER: 'int|true|default=9999', NEWS_VOUCH: 'int|true|default=0', NEWS_CONTENT: 'array|true|default=[]|comment=内容', NEWS_QR: 'string|false', NEWS_VIEW_CNT: 'int|true|default=0|comment=拜访次数', NEWS_PIC: 'array|false|default=[]|comment=封面图 [cloudId1,cloudId2,cloudId3...]', NEWS_FORMS: 'array|true|default=[]', NEWS_OBJ: 'object|true|default={}', NEWS_ADD_TIME: 'int|true', NEWS_EDIT_TIME: 'int|true', NEWS_ADD_IP: 'string|false', NEWS_EDIT_IP: 'string|false',};UserModel.DB_STRUCTURE = { _pid: 'string|true', USER_ID: 'string|true', USER_MINI_OPENID: 'string|true|comment=小程序openid', USER_STATUS: 'int|true|default=1|comment=状态 0=待审核,1=失常,8=审核未过,9=禁用', USER_CHECK_REASON: 'string|false|comment=审核未过的理由', USER_NAME: 'string|false|comment=用户昵称', USER_MOBILE: 'string|false|comment=联系电话', USER_FORMS: 'array|true|default=[]', USER_OBJ: 'object|true|default={}', USER_LOGIN_CNT: 'int|true|default=0|comment=登陆次数', USER_LOGIN_TIME: 'int|false|comment=最近登录工夫', USER_ADD_TIME: 'int|true', USER_ADD_IP: 'string|false', USER_EDIT_TIME: 'int|true', USER_EDIT_IP: 'string|false',}外围实现// 注册 async register(userId, { mobile, name, forms, status }) { // 判断是否存在 let where = { USER_MINI_OPENID: userId } let cnt = await UserModel.count(where); if (cnt > 0) return await this.login(userId); where = { USER_MOBILE: mobile } cnt = await UserModel.count(where); if (cnt > 0) this.AppError('该手机已注册'); // 入库 let data = { USER_MINI_OPENID: userId, USER_MOBILE: mobile, USER_NAME: name, USER_OBJ: dataUtil.dbForms2Obj(forms), USER_FORMS: forms, USER_STATUS: Number(status) } await UserModel.insert(data); return await this.login(userId); } /** 获取手机号码 */ async getPhone(cloudID) { let cloud = cloudBase.getCloud(); let res = await cloud.getOpenData({ list: [cloudID], // 假如 event.openData.list 是一个 CloudID 字符串列表 }); if (res && res.list && res.list[0] && res.list[0].data) { let phone = res.list[0].data.phoneNumber; return phone; } else return ''; } /** 获得我的用户信息 */ async getMyDetail(userId) { let where = { USER_MINI_OPENID: userId } let fields = 'USER_MOBILE,USER_NAME,USER_FORMS,USER_OBJ,USER_STATUS,USER_CHECK_REASON' return await UserModel.getOne(where, fields); } /** 批改用户材料 */ async editBase(userId, { mobile, name, forms }) { let whereMobile = { USER_MOBILE: mobile, USER_MINI_OPENID: ['<>', userId] } let cnt = await UserModel.count(whereMobile); if (cnt > 0) this.AppError('该手机已注册'); let where = { USER_MINI_OPENID: userId } let user = await UserModel.getOne(where); if (!user) return; let data = { USER_MOBILE: mobile, USER_NAME: name, USER_OBJ: dataUtil.dbForms2Obj(forms), USER_FORMS: forms, }; if (user.USER_STATUS == UserModel.STATUS.UNCHECK) data.USER_STATUS = UserModel.STATUS.UNUSE; await UserModel.edit(where, data); } /** 登录 */ async login(userId) { let where = { 'USER_MINI_OPENID': userId }; let fields = 'USER_ID,USER_MINI_OPENID,USER_NAME,USER_PIC,USER_STATUS'; let user = await UserModel.getOne(where, fields); let token = {}; if (user) { // 失常用户 token.id = user.USER_MINI_OPENID; token.key = user.USER_ID; token.name = user.USER_NAME; token.pic = user.USER_PIC; token.status = user.USER_STATUS; // 异步更新最近更新工夫 let dataUpdate = { USER_LOGIN_TIME: this._timestamp }; UserModel.edit(where, dataUpdate); UserModel.inc(where, 'USER_LOGIN_CNT', 1); } else token = null; return { token }; }/** 浏览资讯信息 */ async viewNews(id) { let fields = '*'; let where = { _id: id, NEWS_STATUS: 1 } let news = await NewsModel.getOne(where, fields); if (!news) return null; return news; } /** 获得分页列表 */ async getNewsList({ search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 cateId, //附加查问条件 page, size, isTotal = true, oldTotal }) { orderBy = orderBy || { 'NEWS_ORDER': 'asc', 'NEWS_ADD_TIME': 'desc' }; let fields = 'NEWS_PIC,NEWS_VIEW_CNT,NEWS_TITLE,NEWS_DESC,NEWS_CATE_ID,NEWS_ADD_TIME,NEWS_ORDER,NEWS_STATUS,NEWS_CATE_NAME,NEWS_OBJ'; let where = {}; where.NEWS_STATUS = 1; // 状态 if (cateId && cateId !== '0') where.NEWS_CATE_ID = cateId; if (util.isDefined(search) && search) { where.NEWS_TITLE = { $regex: '.*' + search, $options: 'i' }; } else if (sortType && util.isDefined(sortVal)) { // 搜寻菜单 switch (sortType) { case 'sort': { orderBy = this.fmtOrderBySort(sortVal, 'NEWS_ADD_TIME'); break; } } } return await NewsModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal); } 原型设计 ...

October 10, 2022 · 3 min · jiezi

关于小程序:基于微信小程序的老年大学招生报名小程序开发笔记

业务背景老年大学是“空巢”老人更新常识的课堂,健身养心的场合,开心娱乐的园地,广交朋友的平台,智力开发的基地!在手机网络遍及明天,宽广老年人足不出户,就能够通过小程序的形式理解培训班级和课程,注销材料,查看报名后果,后盾工作人员也能够通过电子化的伎俩收集报名材料,大大节俭老年人奔走的劳顿工夫,也进步老年大学的工作效率。 性能布局次要性能包含布告告诉,课堂风采,培训班列表,培训课程介绍,我的报名,后盾培训项目管理,报名名单治理,后盾告诉治理,后盾管理员治理等性能 报名模块报名项目管理:开始/截止工夫/是否审核/是否可勾销/是否可批改/人数等参数均可灵便设置,并能够自定义老人报名填写的数据项报名审核:能够设定报名名单是否审核,审核不通过可提醒用户欠缺材料我的报名记录:能够批改,勾销我的报名记录详尽的报名数据:反对报名名单数据导出Excel,打印技术选型本我的项目应用微信小程序平台进行开发。应用腾讯专门的小程序云开发技术,云资源蕴含云函数,数据库,带宽,存储空间,定时器等,资源配额价格低廉,无需域名和服务器即可搭建。小程序自身的即用即走,适宜小工具的应用场景,也适宜疾速开发迭代。云开发技术采纳腾讯外部链路,没有被黑客攻击的危险,不会 DDOS攻打,节俭防火墙费用,安全性高且免保护。资源承载力可依据业务倒退须要随时弹性扩大。数据库设计EnrollJoinModel.DB_STRUCTURE = { _pid: 'string|true', ENROLL_JOIN_ID: 'string|true', ENROLL_JOIN_ENROLL_ID: 'string|true|comment=报名PK', ENROLL_JOIN_IS_ADMIN: 'int|true|default=0|comment=是否管理员增加 0/1', ENROLL_JOIN_USER_ID: 'string|true|comment=用户ID', ENROLL_JOIN_FORMS: 'array|true|default=[]|comment=表单', ENROLL_JOIN_STATUS: 'int|true|default=1|comment=状态 0=待审核 1=报名胜利, 99=审核未过', ENROLL_JOIN_REASON: 'string|false|comment=审核回绝或者勾销理由', ENROLL_JOIN_LAST_TIME: 'int|true|default=0', ENROLL_JOIN_ADD_TIME: 'int|true', ENROLL_JOIN_EDIT_TIME: 'int|true', ENROLL_JOIN_ADD_IP: 'string|false', ENROLL_JOIN_EDIT_IP: 'string|false',};UserModel.DB_STRUCTURE = { _pid: 'string|true', USER_ID: 'string|true', USER_MINI_OPENID: 'string|true|comment=小程序openid', USER_STATUS: 'int|true|default=1|comment=状态 0=待审核,1=失常,8=审核未过,9=禁用', USER_CHECK_REASON: 'string|false|comment=审核未过的理由', USER_NAME: 'string|false|comment=用户昵称', USER_MOBILE: 'string|false|comment=联系电话', USER_FORMS: 'array|true|default=[]', USER_OBJ: 'object|true|default={}', USER_LOGIN_CNT: 'int|true|default=0|comment=登陆次数', USER_LOGIN_TIME: 'int|false|comment=最近登录工夫', USER_ADD_TIME: 'int|true', USER_ADD_IP: 'string|false', USER_EDIT_TIME: 'int|true', USER_EDIT_IP: 'string|false',}外围实现class EnrollService extends BaseProjectService { // 获取以后注销状态 getJoinStatusDesc(enroll) { let timestamp = this._timestamp; if (enroll.ENROLL_STATUS == 0) return '已进行'; else if (enroll.ENROLL_START > timestamp) return '未开始'; else if (enroll.ENROLL_END <= timestamp) return '已截止'; else if (enroll.ENROLL_MAX_CNT > 0 && enroll.ENROLL_JOIN_CNT >= enroll.ENROLL_MAX_CNT) return '人数已满'; else return '进行中'; } /** 浏览信息 */ async viewEnroll(userId, id) { let fields = '*'; let where = { _id: id, ENROLL_STATUS: EnrollModel.STATUS.COMM } let enroll = await EnrollModel.getOne(where, fields); if (!enroll) return null; EnrollModel.inc(id, 'ENROLL_VIEW_CNT', 1); // 判断是否有注销 let whereJoin = { ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: id, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]] } let enrollJoin = await EnrollJoinModel.getOne(whereJoin); if (enrollJoin) { enroll.myEnrollJoinId = enrollJoin._id; enroll.myEnrollJoinTag = (enrollJoin.ENROLL_JOIN_STATUS == EnrollJoinModel.STATUS.WAIT) ? '待审核' : '已填报'; } else { enroll.myEnrollJoinId = ''; enroll.myEnrollJoinTag = ''; } return enroll; } /** 获得分页列表 */ async getEnrollList({ search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 page, size, isTotal = true, oldTotal }) { orderBy = orderBy || { 'ENROLL_ORDER': 'asc', 'ENROLL_ADD_TIME': 'desc' }; let fields = 'ENROLL_STOP,ENROLL_JOIN_CNT,ENROLL_OBJ,ENROLL_VIEW_CNT,ENROLL_TITLE,ENROLL_MAX_CNT,ENROLL_START,ENROLL_END,ENROLL_ORDER,ENROLL_STATUS,ENROLL_CATE_NAME,ENROLL_OBJ'; let where = {}; where.and = { _pid: this.getProjectId() //简单的查问在此处标注PID }; where.and.ENROLL_STATUS = EnrollModel.STATUS.COMM; // 状态 if (util.isDefined(search) && search) { where.or = [{ ENROLL_TITLE: ['like', search] },]; } else if (sortType && util.isDefined(sortVal)) { // 搜寻菜单 switch (sortType) { case 'cateId': { if (sortVal) where.and.ENROLL_CATE_ID = String(sortVal); break; } case 'sort': { orderBy = this.fmtOrderBySort(sortVal, 'ENROLL_ADD_TIME'); break; } } } return await EnrollModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal); } /** 获得我的注销分页列表 */ async getMyEnrollJoinList(userId, { search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 page, size, isTotal = true, oldTotal }) { orderBy = orderBy || { 'ENROLL_JOIN_ADD_TIME': 'desc' }; let fields = 'ENROLL_JOIN_LAST_TIME,ENROLL_JOIN_REASON,ENROLL_JOIN_ENROLL_ID,ENROLL_JOIN_STATUS,ENROLL_JOIN_ADD_TIME,enroll.ENROLL_TITLE,enroll.ENROLL_EDIT_SET,enroll.ENROLL_CANCEL_SET'; let where = { ENROLL_JOIN_USER_ID: userId }; if (util.isDefined(search) && search) { where['enroll.ENROLL_TITLE'] = { $regex: '.*' + search, $options: 'i' }; } else if (sortType) { // 搜寻菜单 switch (sortType) { case 'timedesc': { //按工夫倒序 orderBy = { 'ENROLL_JOIN_ADD_TIME': 'desc' }; break; } case 'timeasc': { //按工夫正序 orderBy = { 'ENROLL_JOIN_ADD_TIME': 'asc' }; break; } case 'succ': { where.ENROLL_JOIN_STATUS = EnrollJoinModel.STATUS.SUCC; break; } case 'wait': { where.ENROLL_JOIN_STATUS = EnrollJoinModel.STATUS.WAIT; break; } case 'cancel': { where.ENROLL_JOIN_STATUS = EnrollJoinModel.STATUS.ADMIN_CANCEL; break; } } } let joinParams = { from: EnrollModel.CL, localField: 'ENROLL_JOIN_ENROLL_ID', foreignField: '_id', as: 'enroll', }; let result = await EnrollJoinModel.getListJoin(joinParams, where, fields, orderBy, page, size, isTotal, oldTotal); return result; } /** 获得我的注销详情 */ async getMyEnrollJoinDetail(userId, enrollJoinId) { let fields = '*'; let where = { _id: enrollJoinId, ENROLL_JOIN_USER_ID: userId }; let enrollJoin = await EnrollJoinModel.getOne(where, fields); if (enrollJoin) { enrollJoin.enroll = await EnrollModel.getOne(enrollJoin.ENROLL_JOIN_ENROLL_ID, 'ENROLL_TITLE'); } return enrollJoin; } //################## 注销 // 注销 async enrollJoin(userId, enrollId, forms) { // 注销是否完结 let whereEnroll = { _id: enrollId, ENROLL_STATUS: EnrollModel.STATUS.COMM } let enroll = await EnrollModel.getOne(whereEnroll); if (!enroll) this.AppError('该' + ENROLL_NAME + '不存在或者曾经进行'); // 是否注销开始 if (enroll.ENROLL_START > this._timestamp) this.AppError('该' + ENROLL_NAME + '尚未开始'); // 是否过了注销截止期 if (enroll.ENROLL_END < this._timestamp) this.AppError('该' + ENROLL_NAME + '曾经截止'); // 人数是否满 if (enroll.ENROLL_MAX_CNT > 0) { let whereCnt = { ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]] } let cntJoin = await EnrollJoinModel.count(whereCnt); if (cntJoin >= enroll.ENROLL_MAX_CNT) this.AppError('该' + ENROLL_NAME + '人数已满'); } // 本人是否曾经有注销 let whereMy = { ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]] } let my = await EnrollJoinModel.getOne(whereMy); if (my) { if (my.ENROLL_JOIN_STATUS == EnrollJoinModel.STATUS.WAIT) this.AppError('您曾经填报,正在期待审核,毋庸反复填报'); else this.AppError('您曾经填报胜利,毋庸反复填报'); } // 入库 let data = { ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_STATUS: (enroll.ENROLL_CHECK_SET == 0) ? EnrollJoinModel.STATUS.SUCC : EnrollJoinModel.STATUS.WAIT, ENROLL_JOIN_FORMS: forms } let enrollJoinId = await EnrollJoinModel.insert(data); // 统计数量 this.statEnrollJoin(enrollId); let check = enroll.ENROLL_CHECK_SET; return { enrollJoinId, check } } // 批改注销 async enrollJoinEdit(userId, enrollId, enrollJoinId, forms) { let whereJoin = { _id: enrollJoinId, ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]], } let enrollJoin = await EnrollJoinModel.getOne(whereJoin); if (!enrollJoin) this.AppError('该' + ENROLL_NAME + '记录不存在或者曾经被零碎勾销'); // 注销是否完结 let whereEnroll = { _id: enrollId, ENROLL_STATUS: EnrollModel.STATUS.COMM } let enroll = await EnrollModel.getOne(whereEnroll); if (!enroll) this.AppError('该' + ENROLL_NAME + '不存在或者曾经进行'); if (enroll.ENROLL_EDIT_SET == 0) this.AppError('该' + ENROLL_NAME + '不容许批改材料'); if (enroll.ENROLL_EDIT_SET == 2 && enroll.ENROLL_END < this._timestamp) this.AppError('该' + ENROLL_NAME + '曾经截止,不能批改材料'); if (enroll.ENROLL_EDIT_SET == 3 && enroll.ENROLL_CHECK_SET == 1 && enrollJoin.ENROLL_JOIN_STATUS == EnrollJoinModel.STATUS.SUCC ) this.AppError('该' + ENROLL_NAME + '已通过审核,不能批改材料'); let data = { ENROLL_JOIN_FORMS: forms, ENROLL_JOIN_LAST_TIME: this._timestamp, } await EnrollJoinModel.edit(whereJoin, data); } async statEnrollJoin(id) { let where = { ENROLL_JOIN_ENROLL_ID: id, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]] } let cnt = await EnrollJoinModel.count(where); await EnrollModel.edit(id, { ENROLL_JOIN_CNT: cnt }); } /** 注销前获取要害信息 */ async detailForEnrollJoin(userId, enrollId, enrollJoinId = '') { let fields = 'ENROLL_JOIN_FORMS, ENROLL_TITLE'; let where = { _id: enrollId, ENROLL_STATUS: EnrollModel.STATUS.COMM } let enroll = await EnrollModel.getOne(where, fields); if (!enroll) this.AppError('该' + ENROLL_NAME + '不存在'); let joinMy = null; if (enrollJoinId) { // 编辑 let whereMy = { ENROLL_JOIN_USER_ID: userId, _id: enrollJoinId } joinMy = await EnrollJoinModel.getOne(whereMy); } else { // 取出自己最近一次的填写表单 /* let whereMy = { ENROLL_JOIN_USER_ID: userId, } let orderByMy = { ENROLL_JOIN_ADD_TIME: 'desc' } joinMy = await EnrollJoinModel.getOne(whereMy, 'ENROLL_JOIN_FORMS', orderByMy);*/ } let myForms = joinMy ? joinMy.ENROLL_JOIN_FORMS : []; enroll.myForms = myForms; return enroll; } /** 勾销我的注销 只有胜利和待审核能够勾销 勾销即为删除记录 */ async cancelMyEnrollJoin(userId, enrollJoinId) { let where = { ENROLL_JOIN_USER_ID: userId, _id: enrollJoinId, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]] }; let enrollJoin = await EnrollJoinModel.getOne(where); if (!enrollJoin) { this.AppError('未找到可勾销的记录'); } let enroll = await EnrollModel.getOne(enrollJoin.ENROLL_JOIN_ENROLL_ID); if (!enroll) this.AppError('该' + ENROLL_NAME + '不存在'); if (enroll.ENROLL_CANCEL_SET == 0) this.AppError('该' + ENROLL_NAME + '不能取消'); if (enroll.ENROLL_CANCEL_SET == 2 && enroll.ENROLL_END < this._timestamp) this.AppError('该' + ENROLL_NAME + '曾经截止,不能取消'); if (enroll.ENROLL_CANCEL_SET == 3 && enroll.ENROLL_CHECK_SET == 1 && enrollJoin.ENROLL_JOIN_STATUS == EnrollJoinModel.STATUS.SUCC ) this.AppError('该' + ENROLL_NAME + '已通过审核,不能取消'); await EnrollJoinModel.del(where); this.statEnrollJoin(enrollJoin.ENROLL_JOIN_ENROLL_ID); }}UI设计 ...

October 10, 2022 · 5 min · jiezi

关于小程序:共享会议室开发笔记

性能介绍共享会议室预约小程序,有了这个小程序,在凋谢的会议室任你抉择,随时随地线上自主预约,清晰直观的会议室可预约时段,让您辞别期待,辞别繁冗的人工手续,把效率牢牢抓在手心。会议室申请:点击会议室预约,依据场地需要抉择会议室→点击当初预约→抉择可预订时间段→提交申请即可。前后端残缺代码,包含抉择会议室,批改会议日期、工夫,以及备注进行会议创立。预约胜利后,能够查看会议详情。后盾性能包含:会议室创立,预约记录查问,生成单个会议室小程序码海报,发布公告,用户注册审核等。采纳腾讯提供的小程序云开发解决方案,毋庸服务器和域名即可疾速上线。 性能布局 技术使用本我的项目应用微信小程序平台进行开发。应用腾讯专门的小程序云开发技术,云资源蕴含云函数,数据库,带宽,存储空间,定时器等,资源配额价格低廉,无需域名和服务器即可搭建。小程序自身的即用即走,适宜小工具的应用场景,也适宜疾速开发迭代。云开发技术采纳腾讯外部链路,没有被黑客攻击的危险,不会 DDOS攻打,节俭防火墙费用,安全性高且免保护。资源承载力可依据业务倒退须要随时弹性扩大。 数据库设计NewsModel.DB_STRUCTURE = { _pid: 'string|true', NEWS_ID: 'string|true', NEWS_TITLE: 'string|false|comment=题目', NEWS_DESC: 'string|false|comment=形容', NEWS_STATUS: 'int|true|default=1|comment=状态 0/1', NEWS_CATE_ID: 'string|true|comment=分类编号', NEWS_CATE_NAME: 'string|true|comment=分类冗余', NEWS_ORDER: 'int|true|default=9999', NEWS_VOUCH: 'int|true|default=0', NEWS_CONTENT: 'array|true|default=[]|comment=内容', NEWS_QR: 'string|false', NEWS_VIEW_CNT: 'int|true|default=0|comment=拜访次数', NEWS_PIC: 'array|false|default=[]|comment=封面图 [cloudId1,cloudId2,cloudId3...]', NEWS_FORMS: 'array|true|default=[]', NEWS_OBJ: 'object|true|default={}', NEWS_ADD_TIME: 'int|true', NEWS_EDIT_TIME: 'int|true', NEWS_ADD_IP: 'string|false', NEWS_EDIT_IP: 'string|false',};EnrollModel.DB_STRUCTURE = { _pid: 'string|true', ENROLL_ID: 'string|true', ENROLL_TITLE: 'string|true|comment=题目', ENROLL_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=应用中', ENROLL_CATE_ID: 'string|true|default=0|comment=分类', ENROLL_CATE_NAME: 'string|false|comment=分类冗余', ENROLL_CANCEL_SET: 'int|true|default=1|comment=勾销设置 0=不允,1=容许,2=仅截止前可勾销,3=审核后不可勾销', ENROLL_EDIT_SET: 'int|true|default=1|comment=批改 0=不允,1=容许,2=仅截止前可,3=审核后不可批改', ENROLL_CHECK_SET: 'int|true|default=0|comment=审核 0=不须要审核,1=须要审核', ENROLL_ORDER: 'int|true|default=9999', ENROLL_VOUCH: 'int|true|default=0', ENROLL_FORMS: 'array|true|default=[]', ENROLL_OBJ: 'object|true|default={}', ENROLL_JOIN_FORMS: 'array|true|default=[]', ENROLL_QR: 'string|false', ENROLL_VIEW_CNT: 'int|true|default=0', ENROLL_JOIN_CNT: 'int|true|default=0', ENROLL_ADD_TIME: 'int|true', ENROLL_EDIT_TIME: 'int|true', ENROLL_ADD_IP: 'string|false', ENROLL_EDIT_IP: 'string|false',};UI设计 ...

October 7, 2022 · 1 min · jiezi

关于小程序:从0到1文化馆门户小程序开发笔记

性能介绍文化馆小程序,各地文化馆都会举办各类展览、讲座、培训等,遍及迷信文化常识,发展社会教育,进步大众文化素质,收集钻研非物质文化遗产,组织发展丰富多彩的、大众脍炙人口的文化流动,同时发展老年文化、老年教育、少儿文化工作!本零碎前后端残缺,次要性能包含布告告诉,非遗介绍,文化流动,课堂风采,培训班列表,培训课程介绍,文化个人招募,我的报名,后盾培训项目管理,报名名单治理,后盾告诉治理,后盾管理员治理等性能 技术使用本我的项目应用微信小程序平台进行开发。应用腾讯专门的小程序云开发技术,云资源蕴含云函数,数据库,带宽,存储空间,定时器等,资源配额价格低廉,无需域名和服务器即可搭建。小程序自身的即用即走,适宜小工具的应用场景,也适宜疾速开发迭代。云开发技术采纳腾讯外部链路,没有被黑客攻击的危险,不会 DDOS攻打,节俭防火墙费用,安全性高且免保护。资源承载力可依据业务倒退须要随时弹性扩大。性能布局 数据库设计EnrollModel.DB_STRUCTURE = { _pid: 'string|true', ENROLL_ID: 'string|true', ENROLL_TITLE: 'string|true|comment=题目', ENROLL_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=应用中', ENROLL_CATE_ID: 'string|true|default=0|comment=分类', ENROLL_CATE_NAME: 'string|false|comment=分类冗余', ENROLL_CANCEL_SET: 'int|true|default=1|comment=勾销设置 0=不允,1=容许,2=仅截止前可勾销,3=审核后不可勾销', ENROLL_EDIT_SET: 'int|true|default=1|comment=批改 0=不允,1=容许,2=仅截止前可,3=审核后不可批改', ENROLL_CHECK_SET: 'int|true|default=0|comment=审核 0=不须要审核,1=须要审核', ENROLL_MAX_CNT: 'int|true|default=20|comment=人数下限 0=不限', ENROLL_START: 'int|false|comment=开始工夫', ENROLL_END: 'int|false|comment=截止工夫', ENROLL_ORDER: 'int|true|default=9999', ENROLL_VOUCH: 'int|true|default=0', ENROLL_FORMS: 'array|true|default=[]', ENROLL_OBJ: 'object|true|default={}', ENROLL_JOIN_FORMS: 'array|true|default=[]', ENROLL_QR: 'string|false', ENROLL_VIEW_CNT: 'int|true|default=0', ENROLL_JOIN_CNT: 'int|true|default=0', ENROLL_ADD_TIME: 'int|true', ENROLL_EDIT_TIME: 'int|true', ENROLL_ADD_IP: 'string|false', ENROLL_EDIT_IP: 'string|false',};UserModel.DB_STRUCTURE = { _pid: 'string|true', USER_ID: 'string|true', USER_MINI_OPENID: 'string|true|comment=小程序openid', USER_STATUS: 'int|true|default=1|comment=状态 0=待审核,1=失常,8=审核未过,9=禁用', USER_CHECK_REASON: 'string|false|comment=审核未过的理由', USER_NAME: 'string|false|comment=用户昵称', USER_MOBILE: 'string|false|comment=联系电话', USER_FORMS: 'array|true|default=[]', USER_OBJ: 'object|true|default={}', USER_LOGIN_CNT: 'int|true|default=0|comment=登陆次数', USER_LOGIN_TIME: 'int|false|comment=最近登录工夫', USER_ADD_TIME: 'int|true', USER_ADD_IP: 'string|false', USER_EDIT_TIME: 'int|true', USER_EDIT_IP: 'string|false',}EnrollJoinModel.DB_STRUCTURE = { _pid: 'string|true', ENROLL_JOIN_ID: 'string|true', ENROLL_JOIN_ENROLL_ID: 'string|true|comment=报名PK', ENROLL_JOIN_IS_ADMIN: 'int|true|default=0|comment=是否管理员增加 0/1', ENROLL_JOIN_USER_ID: 'string|true|comment=用户ID', ENROLL_JOIN_FORMS: 'array|true|default=[]|comment=表单', ENROLL_JOIN_STATUS: 'int|true|default=1|comment=状态 0=待审核 1=报名胜利, 99=审核未过', ENROLL_JOIN_REASON: 'string|false|comment=审核回绝或者勾销理由', ENROLL_JOIN_LAST_TIME: 'int|true|default=0', ENROLL_JOIN_ADD_TIME: 'int|true', ENROLL_JOIN_EDIT_TIME: 'int|true', ENROLL_JOIN_ADD_IP: 'string|false', ENROLL_JOIN_EDIT_IP: 'string|false',};UI设计 ...

October 7, 2022 · 1 min · jiezi

关于小程序:中文排序分块

有个相似微信通讯录的性能 然而安卓有兼容性问题,不过也记录一下吧 // arr是传入的数组groupByDesc(arr) { const [...zhCN] = '啊八擦搭蛾发噶哈击喀垃妈拿哦啪期然撒塌挖昔压匝' // const [...EN] = 'abcdefghijklmnopqrstuvwxyz' const [...EN] = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' // 中文在i、u、v下没有对应的汉字 // const [...desc] = 'abcdefghjklmnopqrstwxyz' const [...desc] = 'ABCDEFGHJKLMNOPQRSTWXYZ' // 中文 const isChinese = /[\u4e00-\u9fa5]+/ // 英文 const pattern = /[a-zA-Z]/; // const isSpecial = /[0-9*#@!%$&(),.+-]+/ const hashMap = {} function findIndex(obj) { let check var length let type = 'EN' if(isChinese.test(obj) ){ length = zhCN.length check = zhCN type = 'zhCN' console.log('中文') }else{ length = EN.length check = EN console.log('英文') } for (var i = 0; i < length ; i++) { console.log(obj,check[i],obj.localeCompare(check[i])) if (obj.localeCompare(check[i]) < 0) { if (type == 'zhCN') { return i -1 } else { return i } }else if(obj.localeCompare(check[i]) == 0){ return i } } return 22 } arr.forEach(item => { let hashCode // 判断不是中文和英文 if(!pattern.test(item.nickname[0])&&!isChinese.test(item.nickname[0])){ hashCode = '#' // 中文 }else if(isChinese.test(item.nickname[0] )){ hashCode = desc[findIndex(item.nickname[0] )] // 英文 }else{ hashCode = EN[findIndex(item.nickname[0] )] } // 空 if (!hashMap[hashCode]) { hashMap[hashCode] = [] } // 赋值 hashMap[hashCode].push(item) }) console.log(hashMap) return hashMap}

September 28, 2022 · 1 min · jiezi

关于小程序:从0到1公益培训报名小程序开发笔记

业务背景公益培训报名小程序,提供给文化馆,图书馆,文体核心,青少年活动中心,少年宫等社会公益机构进行公益培训流动报名注销的小工具 性能合成 技术选型应用腾讯专门的小程序云开发技术,云资源蕴含云函数,数据库,带宽,存储空间,定时器等,资源配额价格低廉,无需域名和服务器即可搭建。小程序自身的即用即走,适宜小工具的应用场景,也适宜疾速开发迭代。云开发技术采纳腾讯外部链路,没有被黑客攻击的危险,不会 DDOS攻打,节俭防火墙费用,安全性高且免保护。资源承载力可依据业务倒退须要随时弹性扩大。数据库设计EnrollJoinModel.DB_STRUCTURE = { _pid: 'string|true', ENROLL_JOIN_ID: 'string|true', ENROLL_JOIN_ENROLL_ID: 'string|true|comment=报名PK', ENROLL_JOIN_IS_ADMIN: 'int|true|default=0|comment=是否管理员增加 0/1', ENROLL_JOIN_USER_ID: 'string|true|comment=用户ID', ENROLL_JOIN_FORMS: 'array|true|default=[]|comment=表单', ENROLL_JOIN_STATUS: 'int|true|default=1|comment=状态 0=待审核 1=报名胜利, 99=审核未过', ENROLL_JOIN_REASON: 'string|false|comment=审核回绝或者勾销理由', ENROLL_JOIN_LAST_TIME: 'int|true|default=0', ENROLL_JOIN_ADD_TIME: 'int|true', ENROLL_JOIN_EDIT_TIME: 'int|true', ENROLL_JOIN_ADD_IP: 'string|false', ENROLL_JOIN_EDIT_IP: 'string|false',};UI设计 外围代码 // 获取以后注销状态 getJoinStatusDesc(enroll) { let timestamp = this._timestamp; if (enroll.ENROLL_STATUS == 0) return '已进行'; else if (enroll.ENROLL_START > timestamp) return '未开始'; else if (enroll.ENROLL_END <= timestamp) return '已截止'; else if (enroll.ENROLL_MAX_CNT > 0 && enroll.ENROLL_JOIN_CNT >= enroll.ENROLL_MAX_CNT) return '人数已满'; else return '进行中'; } /** 浏览信息 */ async viewEnroll(userId, id) { let fields = '*'; let where = { _id: id, ENROLL_STATUS: EnrollModel.STATUS.COMM } let enroll = await EnrollModel.getOne(where, fields); if (!enroll) return null; EnrollModel.inc(id, 'ENROLL_VIEW_CNT', 1); // 判断是否有注销 let whereJoin = { ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: id, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]] } let enrollJoin = await EnrollJoinModel.getOne(whereJoin); if (enrollJoin) { enroll.myEnrollJoinId = enrollJoin._id; enroll.myEnrollJoinTag = (enrollJoin.ENROLL_JOIN_STATUS == EnrollJoinModel.STATUS.WAIT) ? '待审核' : '已填报'; } else { enroll.myEnrollJoinId = ''; enroll.myEnrollJoinTag = ''; } return enroll; } /** 获得分页列表 */ async getEnrollList({ search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 page, size, isTotal = true, oldTotal }) { orderBy = orderBy || { 'ENROLL_ORDER': 'asc', 'ENROLL_ADD_TIME': 'desc' }; let fields = 'ENROLL_STOP,ENROLL_JOIN_CNT,ENROLL_OBJ,ENROLL_VIEW_CNT,ENROLL_TITLE,ENROLL_MAX_CNT,ENROLL_START,ENROLL_END,ENROLL_ORDER,ENROLL_STATUS,ENROLL_CATE_NAME,ENROLL_OBJ'; let where = {}; where.and = { _pid: this.getProjectId() //简单的查问在此处标注PID }; where.and.ENROLL_STATUS = EnrollModel.STATUS.COMM; // 状态 if (util.isDefined(search) && search) { where.or = [{ ENROLL_TITLE: ['like', search] },]; } else if (sortType && util.isDefined(sortVal)) { // 搜寻菜单 switch (sortType) { case 'cateId': { if (sortVal) where.and.ENROLL_CATE_ID = String(sortVal); break; } case 'sort': { orderBy = this.fmtOrderBySort(sortVal, 'ENROLL_ADD_TIME'); break; } } } return await EnrollModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal); } /** 获得我的注销分页列表 */ async getMyEnrollJoinList(userId, { search, // 搜寻条件 sortType, // 搜寻菜单 sortVal, // 搜寻菜单 orderBy, // 排序 page, size, isTotal = true, oldTotal }) { orderBy = orderBy || { 'ENROLL_JOIN_ADD_TIME': 'desc' }; let fields = 'ENROLL_JOIN_LAST_TIME,ENROLL_JOIN_REASON,ENROLL_JOIN_ENROLL_ID,ENROLL_JOIN_STATUS,ENROLL_JOIN_ADD_TIME,enroll.ENROLL_TITLE,enroll.ENROLL_EDIT_SET,enroll.ENROLL_CANCEL_SET'; let where = { ENROLL_JOIN_USER_ID: userId }; if (util.isDefined(search) && search) { where['enroll.ENROLL_TITLE'] = { $regex: '.*' + search, $options: 'i' }; } else if (sortType) { // 搜寻菜单 switch (sortType) { case 'timedesc': { //按工夫倒序 orderBy = { 'ENROLL_JOIN_ADD_TIME': 'desc' }; break; } case 'timeasc': { //按工夫正序 orderBy = { 'ENROLL_JOIN_ADD_TIME': 'asc' }; break; } case 'succ': { where.ENROLL_JOIN_STATUS = EnrollJoinModel.STATUS.SUCC; break; } case 'wait': { where.ENROLL_JOIN_STATUS = EnrollJoinModel.STATUS.WAIT; break; } case 'cancel': { where.ENROLL_JOIN_STATUS = EnrollJoinModel.STATUS.ADMIN_CANCEL; break; } } } let joinParams = { from: EnrollModel.CL, localField: 'ENROLL_JOIN_ENROLL_ID', foreignField: '_id', as: 'enroll', }; let result = await EnrollJoinModel.getListJoin(joinParams, where, fields, orderBy, page, size, isTotal, oldTotal); return result; } /** 获得我的注销详情 */ async getMyEnrollJoinDetail(userId, enrollJoinId) { let fields = '*'; let where = { _id: enrollJoinId, ENROLL_JOIN_USER_ID: userId }; let enrollJoin = await EnrollJoinModel.getOne(where, fields); if (enrollJoin) { enrollJoin.enroll = await EnrollModel.getOne(enrollJoin.ENROLL_JOIN_ENROLL_ID, 'ENROLL_TITLE'); } return enrollJoin; } //################## 注销 // 注销 async enrollJoin(userId, enrollId, forms) { // 注销是否完结 let whereEnroll = { _id: enrollId, ENROLL_STATUS: EnrollModel.STATUS.COMM } let enroll = await EnrollModel.getOne(whereEnroll); if (!enroll) this.AppError('该' + ENROLL_NAME + '不存在或者曾经进行'); // 是否注销开始 if (enroll.ENROLL_START > this._timestamp) this.AppError('该' + ENROLL_NAME + '尚未开始'); // 是否过了注销截止期 if (enroll.ENROLL_END < this._timestamp) this.AppError('该' + ENROLL_NAME + '曾经截止'); // 人数是否满 if (enroll.ENROLL_MAX_CNT > 0) { let whereCnt = { ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]] } let cntJoin = await EnrollJoinModel.count(whereCnt); if (cntJoin >= enroll.ENROLL_MAX_CNT) this.AppError('该' + ENROLL_NAME + '人数已满'); } // 本人是否曾经有注销 let whereMy = { ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]] } let my = await EnrollJoinModel.getOne(whereMy); if (my) { if (my.ENROLL_JOIN_STATUS == EnrollJoinModel.STATUS.WAIT) this.AppError('您曾经填报,正在期待审核,毋庸反复填报'); else this.AppError('您曾经填报胜利,毋庸反复填报'); } // 入库 let data = { ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_STATUS: (enroll.ENROLL_CHECK_SET == 0) ? EnrollJoinModel.STATUS.SUCC : EnrollJoinModel.STATUS.WAIT, ENROLL_JOIN_FORMS: forms } let enrollJoinId = await EnrollJoinModel.insert(data); // 统计数量 this.statEnrollJoin(enrollId); let check = enroll.ENROLL_CHECK_SET; return { enrollJoinId, check } } // 批改注销 async enrollJoinEdit(userId, enrollId, enrollJoinId, forms) { let whereJoin = { _id: enrollJoinId, ENROLL_JOIN_USER_ID: userId, ENROLL_JOIN_ENROLL_ID: enrollId, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]], } let enrollJoin = await EnrollJoinModel.getOne(whereJoin); if (!enrollJoin) this.AppError('该' + ENROLL_NAME + '记录不存在或者曾经被零碎勾销'); // 注销是否完结 let whereEnroll = { _id: enrollId, ENROLL_STATUS: EnrollModel.STATUS.COMM } let enroll = await EnrollModel.getOne(whereEnroll); if (!enroll) this.AppError('该' + ENROLL_NAME + '不存在或者曾经进行'); if (enroll.ENROLL_EDIT_SET == 0) this.AppError('该' + ENROLL_NAME + '不容许批改材料'); if (enroll.ENROLL_EDIT_SET == 2 && enroll.ENROLL_END < this._timestamp) this.AppError('该' + ENROLL_NAME + '曾经截止,不能批改材料'); if (enroll.ENROLL_EDIT_SET == 3 && enroll.ENROLL_CHECK_SET == 1 && enrollJoin.ENROLL_JOIN_STATUS == EnrollJoinModel.STATUS.SUCC ) this.AppError('该' + ENROLL_NAME + '已通过审核,不能批改材料'); let data = { ENROLL_JOIN_FORMS: forms, ENROLL_JOIN_LAST_TIME: this._timestamp, } await EnrollJoinModel.edit(whereJoin, data); } async statEnrollJoin(id) { let where = { ENROLL_JOIN_ENROLL_ID: id, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]] } let cnt = await EnrollJoinModel.count(where); await EnrollModel.edit(id, { ENROLL_JOIN_CNT: cnt }); } /** 注销前获取要害信息 */ async detailForEnrollJoin(userId, enrollId, enrollJoinId = '') { let fields = 'ENROLL_JOIN_FORMS, ENROLL_TITLE'; let where = { _id: enrollId, ENROLL_STATUS: EnrollModel.STATUS.COMM } let enroll = await EnrollModel.getOne(where, fields); if (!enroll) this.AppError('该' + ENROLL_NAME + '不存在'); let joinMy = null; if (enrollJoinId) { // 编辑 let whereMy = { ENROLL_JOIN_USER_ID: userId, _id: enrollJoinId } joinMy = await EnrollJoinModel.getOne(whereMy); } else { // 取出自己最近一次的填写表单 /* let whereMy = { ENROLL_JOIN_USER_ID: userId, } let orderByMy = { ENROLL_JOIN_ADD_TIME: 'desc' } joinMy = await EnrollJoinModel.getOne(whereMy, 'ENROLL_JOIN_FORMS', orderByMy);*/ } let myForms = joinMy ? joinMy.ENROLL_JOIN_FORMS : []; enroll.myForms = myForms; return enroll; } /** 勾销我的注销 只有胜利和待审核能够勾销 勾销即为删除记录 */ async cancelMyEnrollJoin(userId, enrollJoinId) { let where = { ENROLL_JOIN_USER_ID: userId, _id: enrollJoinId, ENROLL_JOIN_STATUS: ['in', [EnrollJoinModel.STATUS.WAIT, EnrollJoinModel.STATUS.SUCC]] }; let enrollJoin = await EnrollJoinModel.getOne(where); if (!enrollJoin) { this.AppError('未找到可勾销的记录'); } let enroll = await EnrollModel.getOne(enrollJoin.ENROLL_JOIN_ENROLL_ID); if (!enroll) this.AppError('该' + ENROLL_NAME + '不存在'); if (enroll.ENROLL_CANCEL_SET == 0) this.AppError('该' + ENROLL_NAME + '不能取消'); if (enroll.ENROLL_CANCEL_SET == 2 && enroll.ENROLL_END < this._timestamp) this.AppError('该' + ENROLL_NAME + '曾经截止,不能取消'); if (enroll.ENROLL_CANCEL_SET == 3 && enroll.ENROLL_CHECK_SET == 1 && enrollJoin.ENROLL_JOIN_STATUS == EnrollJoinModel.STATUS.SUCC ) this.AppError('该' + ENROLL_NAME + '已通过审核,不能取消'); await EnrollJoinModel.del(where); this.statEnrollJoin(enrollJoin.ENROLL_JOIN_ENROLL_ID); }后盾治理设计 ...

September 23, 2022 · 5 min · jiezi

关于小程序:基于微信小程序的会议室预定平台开发笔记

业务背景会议室是一个单位或部门的共用资源,但在应用的时候往往会遇到工夫抵触、预约艰难、不不便协调等问题。目前大部分公司是对立在公司群聊中预约,每次预约时,都须要翻一下聊天记录,理解是否有人预约以及预约工夫等。如果抵触则须要找到相干联系人进行沟通。查找历史预约记录麻烦。而当初员工人人都有微信,基于微信环境下的小程序,不必装置独立APP,拜访不便。所以咱们能够基于小程序,借助于会议室预约零碎改善这种状况,实现会议室资源的最优应用 需要剖析 数据库设计EnrollModel.DB_STRUCTURE = { _pid: 'string|true', ENROLL_ID: 'string|true', ENROLL_TITLE: 'string|true|comment=题目', ENROLL_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=应用中', ENROLL_CATE_ID: 'string|true|default=0|comment=分类', ENROLL_CATE_NAME: 'string|false|comment=分类冗余', ENROLL_CANCEL_SET: 'int|true|default=1|comment=勾销设置 0=不允,1=容许,2=仅截止前可勾销,3=审核后不可勾销', ENROLL_EDIT_SET: 'int|true|default=1|comment=批改 0=不允,1=容许,2=仅截止前可,3=审核后不可批改', ENROLL_CHECK_SET: 'int|true|default=0|comment=审核 0=不须要审核,1=须要审核', ENROLL_ORDER: 'int|true|default=9999', ENROLL_VOUCH: 'int|true|default=0', ENROLL_FORMS: 'array|true|default=[]', ENROLL_OBJ: 'object|true|default={}', ENROLL_JOIN_FORMS: 'array|true|default=[]', ENROLL_QR: 'string|false', ENROLL_VIEW_CNT: 'int|true|default=0', ENROLL_JOIN_CNT: 'int|true|default=0', ENROLL_ADD_TIME: 'int|true', ENROLL_EDIT_TIME: 'int|true', ENROLL_ADD_IP: 'string|false', ENROLL_EDIT_IP: 'string|false',};EnrollJoinModel.DB_STRUCTURE = { _pid: 'string|true', ENROLL_JOIN_ID: 'string|true', ENROLL_JOIN_ENROLL_ID: 'string|true|comment=报名PK', ENROLL_JOIN_IS_ADMIN: 'int|true|default=0|comment=是否管理员增加 0/1', ENROLL_JOIN_DAY: 'string|false|comment=预约日期', ENROLL_JOIN_START: 'string|false|comment=开始工夫', ENROLL_JOIN_END: 'string|false|comment=完结工夫', ENROLL_JOIN_END_POINT: 'string|false|comment=完结工夫开端', ENROLL_JOIN_USER_ID: 'string|true|comment=用户ID', ENROLL_JOIN_FORMS: 'array|true|default=[]|comment=表单', ENROLL_JOIN_OBJ: 'object|true|default={}', ENROLL_JOIN_STATUS: 'int|true|default=1|comment=状态 0=待审核 1=报名胜利, 99=审核未过', ENROLL_JOIN_REASON: 'string|false|comment=审核回绝或者勾销理由', ENROLL_JOIN_LAST_TIME: 'int|true|default=0', ENROLL_JOIN_ADD_TIME: 'int|true', ENROLL_JOIN_EDIT_TIME: 'int|true', ENROLL_JOIN_ADD_IP: 'string|false', ENROLL_JOIN_EDIT_IP: 'string|false',};UI设计 ...

September 23, 2022 · 5 min · jiezi

关于小程序:小程序开发踩坑定位及高德地图api相关

问题1:开发版本间断点击获取定位,会报错【起因】:高德地图的api应用的是wx.getLocation,而小程序中wx.getLocation在开发版本、体验版本,间断调用会进行报错。生产版本会应用缓存,不会呈现这个问题,详见:https://developers.weixin.qq....【解决办法】:须要辨别版本进行解决,在生产版本不进行限度,在开发体验版本进行节流解决,30S内点击不进行解决或者提醒获取过于频繁。 问题2:用户回绝受权定位之后,不做相干解决,再次wx.getLocation不会弹出受权页面【起因】:微信小程序设计如此。【解决办法】:在定位操作之前,去判断用户是否有受权定位权限,如果没有,提醒用户受权,关上设置页面。(ps.怪不得买奶茶之类的小程序一进来就先要求受权定位,都是为了避免之后的没有权限的问题)代码如下: let _this = this; wx.getSetting({ success(res) { if (!res.authSetting['scope.userLocation']) { wx.authorize({ scope: 'scope.userLocation', success() { _this.throttleGetLocation(); //有权限间接获取定位 }, fail(err){ //没有权限关上设置 _this.$modal.alert({ title: '提醒', content: '检测到您没关上定位性能权限,是否去设置关上?', okFun: () => { wx.openSetting({ success(res) {} }) } }); } }) }})问题3:调试状态下获取地址胜利,非调试状态获取不胜利【起因】:没有设置高德地图api的域名【解决办法】:在微信公众平台设置域名 https://restapi.amap.com

September 20, 2022 · 1 min · jiezi

关于小程序:微信小程序转为App并上架应用市场

先说说背景吧,笔者开发了一款微信工具类小程序,刚开始,小程序的日访问量和用户数都还能够,但前面缓缓的发现,受限于微信小程序平台规定,很难对用户进行更深刻的经营,用户散失问题也将逐步凸显进去。另一方面,自己始终想开发一个属于本人地App,但又限于对原生技术把握的不够深刻所以始终没有上手去做。 偶尔一次机会,在技术社区看到曾经有比拟成熟的「小程序转 App」工具后,便有了把现有小程序间接通过工具转为 App 的念头。我应用的是 FinClip 的 IDE 转 App 性能,整个过程其实比较简单,不须要太多的技术要求。 上面我也把本人在 FinClip 小程序转 App 的步骤大家简要介绍下,更具体的内容能够间接查阅官网文档。 一、下载安装工具首先, 去FinClip 官网下载安装最新版本的 IDE 工具。 二、App 配置关上FinClip IDE工具,而后咱们须要依据Appp打包规定,配置包含logo、开屏动画和权限等内容。关上 App 配置窗口,如下图所示。 根底配置App 根底配置: 配置需打包的利用的利用名称,利用 App 版本号,利用 build 版本号。 App 版本号装置 x.y.z 的格局填写利用 build 版本号 IDE 会主动生成 图标配置App 图标配置分为两种模式: 简略模式和定制模式。 简略模式下,用户只需配置一张图标图片。定制模式下用户须要配置多张图片:iOS 配置 iphone , ipad 两个尺寸android 则须要配置 48 48, 72 72, 96 96, 144 144, 192* 192 尺寸图标 闪屏配置接下来,是闪屏配置,也即是启动 App 的闪屏画面配置,只须要依据提醒上传相应尺寸的图片即可。 URL Scheme 配置App URL Scheme 作为不同 App 间唤起的标识信息,可供您基于推送等渠道关上 App。 目前 iOS 与 Android 均只反对一条 URL Scheme 配置。 ...

September 17, 2022 · 1 min · jiezi

关于小程序:小程序

小程序简介何为小程序在用户的角度上,就是便捷的跟用户连贯的形式。在技术的角度上,就是在微信伟人的肩膀上疾速便捷的开发程序。小程序的组成JSON配置WXML模板WXSS款式JS脚本JSON配置(以.json结尾的文件)1. 作用JSON其实咱们都很理解,就是一种数据格式。那么它在小程序充当的角色就是配置的作用。比方app.json,能够进行页面注册的配置。 2. 语法跟JS对象表达式很相像,然而有一些差异 key值必须用双引号包裹起来,并且不能用单引号数字,包含浮点数和整数字符串,须要包裹在双引号中bool值,true或者false数组,须要包裹在方括号中对象,须要包裹在大括号中NULL其余格局都会报undefined不能增加正文WXML模板(以.wxml结尾的文件)WXML能够类比HTML,语法上很多类似的中央。 1. 语法正文 <!-- 正文 --> 根本语法 <标签名 属性名1="属性值1" 属性名2="属性值2" ...> ...</标签名>严格闭合大小写敏感2.数据绑定web开发是应用JS通过DOM接口进行动静的渲染页面,小程序应用数据绑定进行动静渲染。 1.根本语法: 通过{{变量名}}的模式进行动静的绑定 //WXML模板<view>{{time}}</view>//JSPage({ data: { time: (new.Date()).toString() }, })2. 属性也能够进行动静绑定,然而须要包含在双引号内 //WXML模板<view height="{{height}}">{{time}}</view>//JSPage({ data: { height: 1 }, })3. 除了动静绑定,也能够在该语法下绑定常量 //WXML模板<view >{{1,2,3}}</view>变量名对大小写敏感没有定义的变量或者设置为undefined的变量不会同步到WXML模板。3.逻辑语法1. 三元运算 //WXML模板<view >{{a === 10 ? "a等于10的要执行的语句" : "a不等于10的要执行的语句"}}</view>2. 字符串拼接 {{ name: world }}//WXML模板<view >{{"hello" + name}}</view>输入hello world3. 算术运算 { a:10, b:2, c:5, d:2}<view >{{a + b}} + {{c}} + d</view>输入:12 + 5 + d4. 条件逻辑 ...

September 14, 2022 · 2 min · jiezi

关于小程序:如何让原生小程序支持less语法最新教程

前言大家写小程序的时候,预计最不爽的就是写wxss款式了吧。保护差,可读性差,如果Dom嵌套的多的话,预计写下去得疯。于是上网搜了一下怎么让原生小程序反对less写法,然而发现很多文章都很老了,微信本人的IDE曾经更新了n个版本了,文章的步骤外面曾经跟IDE里的不一样。于是本人摸索总结了一下,本文算是让原生小程序反对less语法的最新版本教程了。 补充:本文应用的是IDE是:原生小程序自带的IDE,vscode下载Easy LESS插件在vscode市场外面下载less编译插件——Easy LESS。装置的时候倡议不要抉择同步,不然的话,这个插件会同步到你别的电脑里的vscode。因为当初咱们工程根本都用webpack等构建工具,能够间接编译less啥的,所以这个插件同步了没什么意义,下载它只是为了给原生小程序用。 图示: 比拟懒的同学,也能够间接在百度云下,提取码: 7777。这样的话,没有用vscode的同学,也能够间接下载插件装置。开始配置(这里跟网上的教程不一样了)1.装置插件 图示: 抉择“导入已装置的vscode扩大”形式(不倡议)这个形式不太倡议。因为这种形式,会将你vscode外面装置过的插件,都装到原生小程序IDE外面。然而有很多插件,实际上在原生小程序IDE里是用不到也用不了的,比方:Live Server、Vetur、open in browser等。集体喜爱IDE里能不装的货色,相对不装。 抉择“从已解包的扩大文件夹装置”形式(倡议)这个形式强烈建议。算是一种按需载入,须要什么就加什么,很合乎“编程思维”。 如果是在vscode下面下载的,则找到vscode外面插件的门路: windows门路:C:\Users\Administrator\.vscode\extensionsMac门路:User/(你的用户名)/.vscode/extensions(关上Finder,转到Macintosh HD文件夹(从左栏中的设施拜访),按住Cmd + Shift + . 所有暗藏文件都将变为可见)2.配置插件相干的配置信息 ctr + p,输出>setting.json,抉择关上首选项:关上设置(json),拉到最上面,退出配置: "less.compile": { "outExt": ".wxss"},如果胜利配置的话,下面那几行代码是会高亮的,如果没有高亮,阐明没有配置胜利 验证下面的步骤都实现了当前,重启一下IDE,输出新建一个less文件测试一下,如果ctr + s能够输入一个.wxss的文件,则阐明所有配置胜利了,以下为胜利示例: PS:在所有步骤实现后,有时可能会呈现ctr + s 不能输入.wxss文件的状况,这时能够更新小程序自带的IDE试试。 完满Ending其实实现以上步骤,根本就能够了。然而为了更完满一点,咱们还须要再加多一个疏忽上传文件的配置。 公布体验小程序的时候,大家都晓得包是有大小限度的,所以当咱们的页面越多,.less文件也会越多,这多多少少会减少咱们进入小程序时耗得工夫。所以咱们在公布预览小程序的时候,要疏忽掉.less文件的上传(测试如同理论不会上传.less,但为了保险起见,还是加上疏忽配置)。关上根目录的project.config.json文件,退出以下配置: "packOptions": { "ignore": [ { "value": ".less", "type": "suffix" },},对于project.config.json文件相干介绍,大家能够去官网文档具体看看

September 13, 2022 · 1 min · jiezi

关于小程序:小程序容器助力建设自有app小程序生态

在各大互联网平台都在做大做强"超级App"的同时,市场中客户的大部分碎片化工夫均被其“霸占”,对应的流量都把握在这些平台的手中,其余企业很难与之抗衡,而小程序正好具备人造的跨平台连贯能力,可能多端上架至这些“超级App”,在通过提供企业本身的服务,开掘更广大的公域流量,甚至逐渐将这部分公域流量导入企业的私域流量池,大幅升高企业本身的获客老本。小程序的个性和劣势次要有以下: (1)便捷性 不必下载安装,随时可用,不占内存,很便捷。 (2)唯一性(名称抢注) 抢注平台名称,具备唯一性抢注了他人就不能再注册了,属于稀缺资源,具备贬值空间 (3)流量风口 抢占用户流量制高点;小程序的入口已有60多种,搜寻、扫码、公众号、左近小程序等等都是其流量入口,而其中对于流量最大的当属“左近小程序”了。 (4)数据同步 绝对于APP利用,门户小程序其功能属性和APP性能是没有区别的,数据是同步不须要离开治理的,用完即走,实现了门户网站的五网合一。 (5)流传能力强 “左近小程序”可能做到笼罩左近5公里所有微信用户,而且联合线上引流与流传,成果更佳。 目前的小程序生态有哪些目前大型互联网巨头简直全都投入到小程序生态的建设中,包含腾讯、阿里、百度、字节、快利用、美团、快手、网易、华为、360和京东这十系平台。 如果将以后支流的小程序生态进行比照,也能发现一些差异化的特色,各大平台根本都是依据本身平台基因来定位小程序生态的使命。 微信散发小程序的特点是基于社交关系的分享,重点放在社交服务的衍生与降级。支付宝侧重于特色的资金和信用服务。百度定位于搜寻与中转的转化。字节跳动则是要“连贯内容与服务”。美团显然是围绕“衣食住行”的生存场景。京东连贯“进驻”的商家与客户。如何打造本人的小程序生态在整个智能手机销量下滑的现状和互联网流量红利殆尽的双重背景下,要减少一个App装置量和注册量的代价越来越贵,企业埋头本人开发各种服务App的时代已去。但针对银行、证券、政务、电商、车企等大型企业机构继续拓展本身的服务圈,以丰盛的服务去沉闷自有平台海量的存量用户又是必有动作,该怎么搞呢? 过往运行小程序始终被认为是超级平台的“特权”,它是“超级App”为用户提供连贯所有服务的最佳延长载体,可能丰盛这些平台各自的用户生命周期。让本人的App具备运行小程序能力是打造自有小程序生态的首要前提,这个门槛对于很多企业机构来讲已是十分大的挑战,除了要思考开发的微小投入外还要保障运行的可靠性和兼容度。 其实市场中也有十分成熟的解决方案能够间接便捷的应用,在《2021 年度小程序互联网倒退白皮书》就看到凡泰极客推出了 FinClip 去填补市场的空白,介绍中讲到正是基于企业数字化转型过程中构建数字生态连贯能力的需要,向市场提供了兼容互联网支流小程序技术的轻利用平台,帮忙企业打造本人的利用商店,开发、上架、治理与风控以小程序状态存在的碎片化业务场景,以乐高组件形式组装业务利用,赋能业务部门进行跨组织、跨机构、跨行业、跨终 端的数字生态经营。  相当于他们把“App领有小程序运行能力”做成小程序容器技术,任何企业机构的App均能够通过简略嵌入 iOS、Android、MacOS、Windows、UOS、麒麟等零碎对应的FinClip 小程序运行时 SDK 而霎时取得运行小程序的能力,后续各个企业机构能够通过治理后盾以对立高低架的形式,治理本人以及合作伙伴们的业务场景。

September 5, 2022 · 1 min · jiezi

关于小程序:独立站小程序化电商出海多元化直连消费者

对于海内市场而言,社交平台做电商导购,远没有国内容易,这和海内消费者生产习惯有着间接的关系。 依据Insider Intelligence于2021年公布的“美国顶级社交平台消费者购物信赖考察”显示,用户对在Facebook上间接购买商品的态度能够说是两极分化:45%的受访用户示意本人会在Facebook上间接购买商品,35%的受访用户示意不会,20%的受访用户对Facebook的电商化持中立态度。 独一无二,海内营销媒体Eventige在其博文中示意,50%的千禧一代会在网上、社交媒体上搜寻一个产品的信息,而后在实体店进行购买。换句话说,海内相当一部分消费者仍偏向于将社媒当作种草渠道,而非购物渠道。 中国品牌出海面临的挑战阿里国内站总裁张阔,在2022年3月承受36氪出海专访时提及,“品牌出海”的过程总共分为三步:“第一步,必定要先做到供应链出海,至多有能力生产产品并把产品运到目的地。第二步是商标出海,海内用户用这个产品的时候晓得他用的是你的产品。第三步,才是品牌出海。” 随着近两年跨境电商热潮的推动,让泛滥企业实现了前两个步骤,但在品牌出海这个步骤上,依然有微小倒退空间。2021年 BrandZ 最具价值寰球品牌100强中,中国仅有18个品牌上榜,而美国有56个。中国品牌出海,企业除了须要精心设计一个合乎海内消费者胃口的品牌故事之外,还须要克服消费者对于品牌的认知接管“水土不服”的阻碍。消费者对个性化品牌体验高冀望,促成独立站工具的疾速成长海内消费者有着相比于国内消费者不一样的购买思维,造就了企业品牌有异于外乡推广的市场环境。海内消费者最器重的是品牌提供的个性化体验。依据Stackla的2021年考察结果显示,72%的消费者示意,如果一个品牌可能继续为他们提供更多的个性化体验,他们就更有可能从该品牌购买。也就是说,用户更心愿与有特色的、辨认度更高的品牌进行互动。 互联网时代,消费者大部分工夫在线,企业能在线讲好一个品牌故事,还须要能逻辑清晰的在线表达出来。于是乎,品牌网站构建工具--独立站(如:Wordpress,Shopify等)应“需”而生。其“去中心化”,“塑造个性化品牌”,“DTC直面消费者”,“积淀流量”等劣势,始终是外乡品牌出海青眼的品牌建站工具。 这种品牌个性化倒退的趋势,还导致了海内头部社交平台不会抉择自建电商,而是和独立站平台单干。2022年4月,Pinterest发表与独立站建站SaaS平台WooCommerce建设合作伙伴关系,使WooCommerce的360万中小商家能够将产品目录转换为Pinterest上的可购物Pin图。同年6月,社交媒体平台Twitter亦进一步发表和Shopify结为合作伙伴。 技术标准的演变:从HTML5到小程序技术从Web 1.0进化到2.0之后的十几年间,挪动App都是各大软件提供商用于抢夺消费者碎片化工夫的主战场。HTML5这种标准化的、普适的文本化内容编码格局,被广泛应用,并最终成为了互联网的基石之一。Web2.0向3.0的进化过程中,软件技术标准的扩大,小程序类技术的编码和内容格局,整体基于HTML5根底上,更加轻量,也更加凋谢有生命力。 从规范的角度看,以后互联网上的小程序类技术,简直都借鉴了这个畛域的先行者微信的标准。能够说,微信小程序就是这个畛域的“既成事实”规范。 故此互联网系列寰球规范的制定者W3C,也正在通过其Mini-Apps工作组制订国际标准。技术在提高,规范在提高,构建在规范之上的独立站,也在提高。 FinClip+微幕小程序,给企业出海一个新的设想空间Wordpress因代码开源、对搜索引擎SEO敌对、海量收费典范等劣势,被寰球企业广泛应用于建设独立站。 微幕小程序的设计初衷,是帮忙wordpress站长将本人的网站对接到小程序中来。 目前微幕已实现反对微信、百度、QQ、支付宝、头条等5种小程序的适配。微幕小程序利用适配FinClip后,用户的内容不仅能疾速搬至社交平台,还能通过FinClip的「小程序一键转换App」的性能,疾速生成App并上架至利用市场。 FinClip+微幕,不仅可能疾速触达、承接支流社交平台公域流量,还能疾速生成企业自有App,将公域流量引入企业私域阵地盘活,真正实现“公域-私域流量互联互通”。 据微幕团队介绍,他们正在实现一个APP可对接治理多个站点的小程序,这个性能对于中大型企业出海疾速建站十分实用,因为它可能助力企业对于多分支机构或多门店的独立经营及治理。 您是否有趣味理解更多无关小程序容器技术如何助力企业公私域流量闭环?更多信息,请至FinClip官网分割咱们。

August 31, 2022 · 1 min · jiezi

关于小程序:企业新风口深圳开发小程序优势详解

置信大家当初对微信小程序必定不生疏,随着微信小程序的深刻倒退,微信小程序的性能一直优化,尤其是微信还优化了小程序的进入入口,平时应用小程序更加不便,这让更多企业发现了新的商机和时机通过微信小程序引来更多的用户量,这对企业倒退来说具备重要的意义。上面深圳至佳科技就跟大家阐明一下企业开发小程序的劣势所在。企业开发小程序有什么劣势? 1、节俭企业老本 无论是开发挪动APP或者开发挪动网站,投资实际上绝对较高,小程序不同,基于微信,不须要思考平台兼容性,老本和开发工夫会升高,应用也十分不便。 2、开发的门槛较低 相比于挪动APP一方面,开发小程序的门槛要低得多,所以没有必要思考框架.UI组件等一系列问题,因为微信曾经筹备好了。 3、更加人性化 企业要想倒退好,多元素.人性化的特点至关重要。这两点的治理办法能够反映在微信小程序的开发中,能够让用户更容易、更不便地把握公司的商品.这些服务项目,对于塑造企业形象有很好的晋升,也能让用户对企业产生信任感。 4、拓展客源: 小程序背靠微信,有着微小的流量红利,对于企业而言,是一个十分好的拓客渠道、引流渠道、品牌曝光渠道。 5、扩充企业的业务范围 微信为用户提供了80多个小程序入口,容许用户通过多个端口找到并关上小程序。微信每月沉闷用户超过12亿。如此微小的流量能够齐全满足商家对流量转换的需要。 虽说小程序的劣势显著,然而前提是要理解如何做好一个小程序,企业能力抓住倒退的风口,迎难而上。如果您有小程序开发这方面的需要,能够分割深圳至佳科技,咱们竭诚为您服务。

August 30, 2022 · 1 min · jiezi

关于小程序:基于小程序的小区物业管理平台开发笔记

背景以后小区的物业事务越来越多、越来越杂,而很多业主工作沉重,加班很晚,以往对于重大事项投票,报修报检,装修申请,搬家申请,投诉倡议都须要去小区物业核心, 同时对于小区重要布告,租售信息个别都在群里很难翻看历史信息, 小区的一些文体活动也因为难于统计而难于发展。这是一款不便业主,业委会,物业三方而制作的小程序。业主能够通过其智能治理物业,在线报修报检,参加重大事项投票,报名加入小区流动,查看小区最新布告告诉,业委会公示,租售房屋信息等,而不必出门奔波。本小程序前后端残缺代码,采纳腾讯提供的小程序云开发解决方案,毋庸服务器和域名。 次要性能资讯治理:录入和展现物业布告,业委会布告,租售信息,小区规章制度等社区活动报名:反对录入社区活动,提交报名,用户扫码签到,工作人员核销签到,导出报名名单Excel等投票:反对录入投票我的项目,业主按单选多选投票,后盾查看投票后果等业主报修:业主通过提交报修内容,上传图片文字信息等,物业公司进行办理, 随时更新办理状态。总体架构图 技术选型本我的项目应用微信小程序平台进行开发。应用腾讯专门的小程序云开发技术,云资源蕴含云函数,数据库,带宽,存储空间,定时器等,资源配额价格低廉,无需域名和服务器即可搭建。小程序自身的即用即走,适宜小工具的应用场景,也适宜疾速开发迭代。云开发技术采纳腾讯外部链路,没有被黑客攻击的危险,安全性高且免保护。资源承载力可依据业务倒退须要随时弹性扩大。数据设计TaskModel.DB_STRUCTURE = { _pid: 'string|true', TASK_ID: 'string|true', TASK_USER_ID: 'string|true|comment=用户ID', TASK_STATUS: 'int|true|default=0|comment=状态 0=待处理,1=解决中 9=已办结', TASK_FORMS: 'array|true|default=[]', TASK_OBJ: 'object|true|default={}', TASK_LAST_TIME: 'int|true|default=0', TASK_ADD_TIME: 'int|true', TASK_EDIT_TIME: 'int|true', TASK_ADD_IP: 'string|false', TASK_EDIT_IP: 'string|false',};VoteModel.DB_STRUCTURE = { _pid: 'string|true', VOTE_ID: 'string|true', VOTE_TITLE: 'string|true|comment=题目', VOTE_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=应用中', VOTE_CATE_ID: 'string|true|default=0|comment=分类', VOTE_CATE_NAME: 'string|false|comment=分类冗余', VOTE_CANCEL_SET: 'int|true|default=1|comment=勾销设置 0=不允,1=容许,2=仅截止前可勾销', VOTE_START: 'int|true|comment=开始工夫', VOTE_END: 'int|true|comment=截止工夫', VOTE_ORDER: 'int|true|default=9999', VOTE_VOUCH: 'int|true|default=0', VOTE_ITEM: 'array|false|default=[]|comment=投票我的项目 [{label=名称,cnt=数量}]', VOTE_TYPE: 'int|true|default=0|comment=状态 0-单选 1=多选', VOTE_USER: 'array|false|default=[]|comment=投票用户[{id,time,selected}]', VOTE_FORMS: 'array|true|default=[]', VOTE_OBJ: 'object|true|default={}', VOTE_QR: 'string|false', VOTE_VIEW_CNT: 'int|true|default=0', VOTE_USER_CNT: 'int|true|default=0', VOTE_CNT: 'int|true|default=0', VOTE_ADD_TIME: 'int|true', VOTE_EDIT_TIME: 'int|true', VOTE_ADD_IP: 'string|false', VOTE_EDIT_IP: 'string|false',};UI设计 ...

August 20, 2022 · 1 min · jiezi

关于小程序:1000套微信小程序源码开源版附H5小游戏源码及商城源码

 随着微信小程序性能和生态的日益完善,很多企业的产品业务逐步从App扩大到微信小程序和微信公众号。随着小程序我的项目页面越来越多,业务逻辑越来越简单,现有的小程序元源码数量和品种不能满足快速增长的业务需要。 残缺源码:y.wxlbyx.icu 但因为小程序自身的一些个性,业界不足成熟欠缺的解决方案,总会呈现各种问题(包含腾讯微信官网提供的自动化工具)。明天咱们要带来的是一些微信小程序自动化测试的最佳实际和教训,包含微信小程序的根本测试技术和操作方法,以及如何应用appium的WebView测试技术+ADB代理来实现微信小程序的自动化测试(可能是目前最实用的小程序自动测试技术),并附上PHP版源码。 小程序源码运行环境 平台差别:尽管运行环境很类似,但还是有一些区别: JavaScript 语法和 API 反对不统一:从语法上来说,开发者能够通过开启 ES6 到 Es5 的性能来防止(详情);此外,applet 根底库内置了必要的 Polyfill 来补救 API 的差别。 wxss渲染性能不统一:尽管开启款式补全能够防止大部分问题,但倡议开发者须要别离在IOS和Android上查看小程序的真实性能。 微信小程序技术架构 微信小程序的技术架构如下图所示: 应用 chrome 调试小程序 应用Chrome浏览器提供的inspect剖析工具,在浏览器中输出如下地址: chrome://inspect/#devices 应用Chrome浏览器查看手机上关上的WebView过程和根本信息: 能够应用chrome inspect来剖析微信小程序的控制结构和布局: 应用控制台执行您本人的 JavaScript 代码: 小程序性能测试 这里附上一个小程序性能测试图: 微信小程序自动测试 微信小程序自动测试关键步骤 1.原生自动化模式。 ●能够应用appium来实现。毛病是管制定位不够精确,无奈深刻小程序; 2、WebView自动化模式:能够取得更多小程序外部品质数据。 ●设置正确的chromedriver版本 ●设置 chrome 选项并将其传递给 chromedriver ●应用ADB代理解决修复chromedriver的bug 3、为什么很多人还不确定? ●低版本的chromedriver在高版本的手机上有bug ●chromedriver与微信定制的chrome内核的连贯实现有问题 源码示例: ...

August 19, 2022 · 2 min · jiezi

关于小程序:招生报名小程序开发笔记三数据库设计

小程序云开发提供了一个 JSON 数据库,顾名思义,数据库中的每条记录都是一个 JSON 格局的对象。 我这个小程序就打算利用这个json数据库, 一个数据库能够有多个汇合(相当于关系型数据中的表),汇合可看做一个 JSON 数组,数组中的每个对象就是一条记录,记录的格局是 JSON 对象。 关系型数据库和 JSON 数据库的概念对应关系如下表 用户表 资讯表 报名项目表 用户报名表 珍藏表 校园相册表

August 11, 2022 · 1 min · jiezi

关于小程序:招生报名小程序开发笔记二功能需求设计

随着小程序越来越受公众的欢送,很多大中学校甚至幼儿园都领有本人的微信小程序, 能够很便捷的通过小程序进行信息注销、现场报名确认、普查审核等多个阶段。 我简略布局了一下招生报名小程序的次要职能为: 前端:学校详情,校园图文,招生政策,退学指南,各业余班级特色介绍,报名注销、勾销,用户材料补注销,珍藏,历史浏览,分享海报等后端:报名我的项目开设,参数设定,用户审核,用户材料导出Excel, 管理员设定等,操作日志等对照这些,初步打算了如下功能模块: 首页模块banner图学校详情招生指南退学指南待业升学热门业余最新动静报名模块报名我的项目列表:学制,招生人数,学费,根本状况介绍详情:报名状态马上报名:填报材料(审核,非审核),勾销报名,批改材料- 多彩校园校园环境教学场合生存设施文体娱乐- 集体核心注册与材料批改我的报名我的珍藏历史浏览对于咱们后盾治理模块系统管理:管理员治理,操作日志,明码设置用户治理:检索,详情,删除内容治理:新增,批改,删除,检索报名治理:我的项目创立,参数设置,介绍与图集,举荐与置顶,专属海报报名名单治理:名单审核,导出Excel, 清理数据-

August 11, 2022 · 1 min · jiezi

关于小程序:招生报名小程序开发笔记一开发背景和技术方案的选型确定

业务背景对每所学校而言,每年招生退学工作启动后,都免不了信息注销、现场报名、普查审核等多个阶段。特地是来到现场报名审核环节时,以往都是学校公众号发个告诉,家长们在凋谢现场注销的那几天,本人找工夫过去,头一两天来的人会比拟多,老师们接待压力也比拟大,家长办理审核注销也须要期待较长时间。 但近年来,为了缩小现场家长排队期待,以及更好防备疫情,应用小程序来实现在线预约、对家长有序分流,成为了各学校踊跃采纳的形式,老师接待和现场秩序治理起来也更轻松。 前端技术计划选型原生:对性能特地刻薄 or 谋求稳固 or 要用最新性能,请记住任何时刻原生都是最稳定性能最好的抉择!!!!KBone:kbone 是一个致力于微信小程序和 Web 端同构的解决方案,微信小程序的底层模型和 Web 端不同,咱们想间接把 Web 端的代码挪到小程序环境内执行是不可能的。kbone 的诞生就是为了解决这个问题,它实现了一个适配器,在适配层里模拟出了浏览器环境,让 Web 端的代码能够不做什么改变便可运行在小程序里。MPVue:是美团点评开源的一个应用 Vue.js 开发小程序的前端框架。框架基于 Vue.js 外围,mpvue 批改了 Vue.js 的 runtime 和 compiler 实现,使其能够运行在小程序环境中,从而为小程序开发引入了整套 Vue.js 开发体验。WePY:腾讯团队开源的一款类vue语法标准的小程序框架,借鉴了Vue的语法格调和性能个性,反对了Vue的诸多特色,比方父子组件、组件之间的通信、computed属性计算、wathcer监听器、props传值、slot槽散发,还有很多高级的特色反对:Mixin混合、拦截器等;Taro:京东凹凸实验室开源的一款应用 React.js 开发微信小程序的前端框架。它采纳与 React 统一的组件化思维,组件生命周期与 React 保持一致,同时反对应用 JSX 语法,让代码具备更丰盛的表现力,应用 Taro 进行开发能够取得和 React 统一的开发体验。,同时因为应用了react的起因所以除了能编译h5, 小程序外还能够编译为ReactNative;Uni-app:应用 Vue.js 开发小程序、H5、App的对立前端框架。开发者应用 Vue 语法编写代码,uni-app 框架将其编译到 小程序(微信/支付宝/百度/字节跳动/QQ/钉钉)、App(iOS/Android)、H5等多个平台,保障其正确运行并达到优良体验。Chameleon:滴滴跨端解决方案。不是很理解,欢送大家补充 抉择论断:预约小程序性能点不多(前台大略20个左右性能点,后盾大略50个性能点),没有简单的业务关系,且没有跨端的需要,要求是简略高效,这里的简略高效既是开发的简略高效,也是治理公布的简略高效,所以抉择了原生框架作为前端计划,当然,小程序在十分疾速的更新迭代,就算是原生框架也还是有一些坑的。 前端UI技术计划选型原生 : 基于WXML,WXSS,组件,模板构建,根本也就是写view的弹性布局啦!!!WeUI:腾讯官网UI组件库WeUI的小程序版,提供了跟微信界面风格统一的用户体验,感觉比拟死板,中庸,没有视觉冲击力ColorUI:一个Css类的UI组件库!不是一个Js框架。相比于同类小程序组件库,ColorUI更重视于视觉交互!其组件在好看性方面比较突出。iView WeApp: TalkingData公布的一款高质量的基于Vue.js组件库,而iView weapp则是它们的小程序版本ZanUI WeApp:是有赞挪动 Web UI 标准 ZanUI 的小程序实现版本,联合了微信的视觉标准,为用户提供更加对立的应用感触MinUI :蘑菇街前端开发团队开发的基于微信小程序自定义组件个性开发而成的一套简洁、易用、高效的组件库,实用场景广,笼罩小程序原生框架,各种小程序组件支流框架等,并且提供了专门的命令行工具。抉择论断:WeUI过于平庸,和微信原生组件差不多,而iView,ZanUI, MinUI学习曲线较高,所以抉择了原生+ColorUI作为UI框架后端框架技术计划选型ThinkPHP(PHP):国人最引以为自豪的PHP框架,大略从200X年就开始风行,繁殖了N个版本,因为其本身蕴含了底层架构、兼容解决、基类库、数据库拜访层、模板引擎、缓存机制、插件机制、角色认证、表单解决等罕用的组件,并且对于跨版本、跨平台和跨数据库移植都比拟不便。Laravel(PHP): 号称宇宙中最简洁、最优雅的PHP Web开发框架。它能够让你从面条一样芜杂的代码中解脱进去;它能够帮你构建一个完满的网络APP,而且每行代码都能够简洁、富于表达力。.NET Core WebAPI:微软为了通吃Linux/Win平台的得意之作,长期以来C#+SQLServer组合只沉闷于企业级利用,或者古董利用中,无奈飞入寻常百姓家(程序员家),为此推出了了.NET Core, 指标是跨平台Java SpringBoot:设计目标是用来简化新Spring利用的初始搭建以及开发过程。该框架应用了特定的形式来进行配置,从而使开发人员不再须要定义样板化的配置小程序云开发:云开发为开发者提供残缺的原生云端反对和微信服务反对,弱化后端和运维概念,无需搭建服务器,应用平台提供的 API 进行外围业务开发,即可实现疾速上线和迭代,同时这一能力,同开发者曾经应用的云服务互相兼容,并不互斥。抉择论断:小程序云开发能够提供前后端的免鉴权用户身份获取,同时能够间接提供云函数调用,也提供了IO存储空间,Json数据库,同时还能够和公众号数据互通,且防止繁琐的认证受权,所以Selected IT数据库计划选型MySQL:挪动互联网守业大军的首选,收费,高效,适中PostgreSQL:是一种个性十分齐全的自由软件的对象-关系型数据库管理系统(ORDBMS),是以加州大学计算机系开发的POSTGRES,4.2版本为根底的对象关系型数据库管理系统。小程序Json数据库:与小程序云开发紧密结合,而且根底版是收费的,当然抉择她啊!!!综合论断小程序原生+ColorUI+云函数+云开发+Json数据库 ...

August 11, 2022 · 1 min · jiezi

关于小程序:从0到100招生报名小程序开发笔记

背景这是一个以报名为外围的职业学校招生小程序,目标是不便想要零碎学习技能,入门某项技能或者畛域的初高中毕业生,理解该学校的根本状况及各个业余,并提供报名门路,致力于技能型人才培养。 性能次要性能包含业余介绍,业余抉择,材料填报,查看审核后果,学校详情,招生指南,退学须知,待业升学,多彩校园等性能,后盾能够创立报名我的项目,查看和导出名单Excel,审核报名记录等。本小程序采纳腾讯提供的小程序云开发解决方案,毋庸服务器和域名。能够设定报名的起始工夫,是否须要审核,是否能够批改和勾销等多项规定 数据库设计报名主表: enroll报名明细: enroll_join校园资讯表: news用户表: user校园风采表:album珍藏表:fav管理员表:admin管理员操作日志表:log设置表:setup 报名主表设计EnrollModel.DB_STRUCTURE = { _pid: 'string|true', ENROLL_ID: 'string|true', ENROLL_TITLE: 'string|true|comment=题目', ENROLL_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=应用中', ENROLL_CATE_ID: 'string|true|default=0|comment=分类', ENROLL_CATE_NAME: 'string|false|comment=分类冗余', ENROLL_CANCEL_SET: 'int|true|default=1|comment=勾销设置 0=不允,1=容许,2=仅截止前可勾销', ENROLL_EDIT_SET: 'int|true|default=1|comment=批改 0=不允,1=容许,2=仅截止前可', ENROLL_CHECK_SET: 'int|true|default=0|comment=审核 0=不须要审核,1=须要审核', ENROLL_MAX_CNT: 'int|true|default=20|comment=人数下限 0=不限', ENROLL_START: 'int|false|comment=开始工夫', ENROLL_END: 'int|false|comment=截止工夫', ENROLL_ORDER: 'int|true|default=9999', ENROLL_VOUCH: 'int|true|default=0', ENROLL_FORMS: 'array|true|default=[]', ENROLL_OBJ: 'object|true|default={}', ENROLL_JOIN_FORMS: 'array|true|default=[]', ENROLL_QR: 'string|false', ENROLL_VIEW_CNT: 'int|true|default=0', ENROLL_JOIN_CNT: 'int|true|default=0', ENROLL_ADD_TIME: 'int|true', ENROLL_EDIT_TIME: 'int|true', ENROLL_ADD_IP: 'string|false', ENROLL_EDIT_IP: 'string|false',};报名明细设计EnrollJoinModel.DB_STRUCTURE = { _pid: 'string|true', ENROLL_JOIN_ID: 'string|true', ENROLL_JOIN_ENROLL_ID: 'string|true|comment=报名PK', ENROLL_JOIN_IS_ADMIN: 'int|true|default=0|comment=是否管理员增加 0/1', ENROLL_JOIN_USER_ID: 'string|true|comment=用户ID', ENROLL_JOIN_FORMS: 'array|true|default=[]|comment=表单', ENROLL_JOIN_STATUS: 'int|true|default=1|comment=状态 0=待审核 1=报名胜利, 99=审核未过', ENROLL_JOIN_REASON: 'string|false|comment=审核回绝或者勾销理由', ENROLL_JOIN_LAST_TIME: 'int|true|default=0', ENROLL_JOIN_ADD_TIME: 'int|true', ENROLL_JOIN_EDIT_TIME: 'int|true', ENROLL_JOIN_ADD_IP: 'string|false', ENROLL_JOIN_EDIT_IP: 'string|false',};UI设计 ...

July 29, 2022 · 1 min · jiezi

关于小程序:蚂蚁核心科技产品亮相数字中国建设峰会-持续助力企业数字化转型

近日,第五届数字中国建设峰会在福州市揭幕。在会上,蚂蚁团体首次全面展现其在五大前沿科技领域的摸索和以数字技术助力实体经济的实际成绩。 此次亮相展会的云原生分布式解决方案SOFAStack和挪动开发平台mPaaS是蚂蚁数字科技的外围科技产品,已广泛应用于金融、政务民生、交通、能源等行业,继续助力企业的数字化转型。 云原生分布式解决方案SOFAStack 助力企业架构转型降级近年来,越来越多金融机构意识到被动寻求数字化转型是倒退的必然选择,尤其银行业纷纷采纳先进技术减速外围业务零碎向云架构转型,同时放慢产品翻新和改善服务体验。 蚂蚁团体多年来在数字金融畛域一直深耕布局,积攒了大量的架构设计准则、最佳实际和产品服务案例,其中蚂蚁数字SOFAStack是具备代表性、创新性的金融科技产品。作为蚂蚁数字推出的云原生分布式解决方案, SOFAStack具备高稳定性、高兼容性及可靠性,能在国产设施和零碎平台上稳固运行,帮忙金融机构及企业客户安全可靠地实现IT架构向云原生分布式降级,从而升高IT开发与运维老本,晋升研发效力,撑持业务疾速翻新。 以四川农信为例,作为首期国家发改委的数字化转型搭档口头的金融机构,在过来几年里,四川农信借助阿里金融云平台、SOFAStack云原生分布式解决方案等技术撑持,推动其IT架构由集中式向分布式的架构转型,构建的“蜀信云”平台,曾经反对智能营销、智能柜面、凋谢银行服务平台等十多个重要业务零碎的平安稳固运行。 目前,SOFAStack曾经服务于中国工商银行、四川农信、中华保险等超百家金融机构。国内TOP50的金融机构中,曾经有超过60%抉择SOFAStack助力云原生分布式转型。 挪动开发平台mPaaS 驱动业务增长数字经济时代,各行各业都在放慢业务线上化迁徙步调。挪动化、场景化、智能化成为了金融业务的重要倒退方向。 蚂蚁数字mPaaS是蚂蚁自主研发的挪动开发平台,为挪动利用开发、测试、经营及运维提供云到端的一站式解决方案,可能无效晋升APP的交互体验和保障APP合规及平安,同时配套精细化经营、丰盛营销场景能力帮助企业疾速实现业务增长。 以云南惟一的省属城商行富滇银行为例,往年1月,富滇银行正式上线基于mPaaS打造的新版手机APP,并首次投放了模式丰盛的数字化营销流动。流动期间,权利、积分等营销体系在短时间内,将手机银行生存板块交易订单拉升至百万级,无效带动了用户增长与活跃度。截至5月份,手机银行新增用户数同比增长305%,MAU同比增长52%。 目前,mPaaS曾经服务富滇银行、招商银行、12306、上海地铁等泛滥机构及企业。值得一提地是,mPaaS在非金融行业的客户数增长迅猛,过来一年,mPaaS的非金客户同比增长翻倍。 据理解,除了SOFAStack和mPaaS,蚂蚁数字科技还打造了分布式金融外围套件、数字经营等数十款外围产品和行业解决方案,并继续将蚂蚁自主研发的技术能力和实践经验对外开放,携手各方为中小金融机构的数字化降级、服务业小微商家的数字化经营、产业链的数字化合作贡献力量,目前已服务数百家客户。

July 26, 2022 · 1 min · jiezi

关于小程序:微信小程序二学妹问我微信小程序左滑删除怎么实现

背景上篇文章记录了小程序的自定义导航栏的实现过程和小程序根底组件 cover-image 中 应用 fiexd 生效的坑。前天忽然在qq上看到一个学妹在群里@我问我小程序怎么实现左滑删除,明天正好周末有空,于是就写了这篇文章。 成果展现 实现过程用小程序根底组件 movable-area 和 movable-view 搭建视图架子拿到后盾的商品数据循环展现左滑展现右侧暗藏的红色删除按钮点击按钮,通过 dataset 拿到以后索引,删除数组中对应的数据伪代码: <block wx:for="{{infoList}}" wx:for-index="index" wx:key="id" wx:for-item="item"> <movable-area > <movable-view class="item" damping="100" direction="horizontal" out-of-bounds="true" animation="true"> <!-- 滑动删除右边显示信息的盒子 --> <view></view> <!-- 左边删除按钮的盒子 --> <view bindtap="handleDelShop">删除</view> </movable-view> </movable-area></block> // js 代码 // 删除商品处理事件async handleDelShop(e) { let { index, id } = e.currentTarget.dataset; let infoList = this.data.cartData.goods; infoList.splice(index, 1); this.setData({ [infoList]: infoList, })},须要留神的中央右边显示的区域宽度肯定要设置 100vw,并且加上 overflow: hidden 防止出现x轴方向的滑动条,在外层的整个盒子加上 box-sizing: border-box;。给根底组件设置高度movable-area 和 movable-view 是有默认的高度的,必须设置这两个根底组件的高度,如果不设置的话,就算外面的盒子有固定高度,也不会失效的,所以特地肯定要留神,设置固定高度,在写代码前就要算好外面的盒子的高度,如果因为数据不确定,依据不同数据展现不同高度的话,能够用条件判断,设置不同高度。优化为了用户体验更好,我做了一下优化,相似这种成果: (因为在网吧写的文章,没有动图素材,就用了他人的动态图,遗记起源了,不过释怀哈,代码实现的成果是一样的!有晓得动静起源的能够通知我,前面我加上。) 做了以下优化: ...

July 21, 2022 · 2 min · jiezi

关于小程序:厚积而薄发CRMEB-Pro-商城系统每一步都很扎实

CRMEB Pro 版作为众邦科技的龙头产品,始终都被寄托着厚望,CRMEB 也投入了十分大的人力、财力,欲将其打造成一款企业级产品,使其成为 CRMEB 的品牌担当,它是众邦人用技术助力企业倒退的长远目标,稳中求新也必将是其倒退的必经之路。 在 CRMEB Pro v1.1.5 版本中,新增的大小性能有 10 多个,性能优化上百处,大小细节修复 30 多项,从字体色彩大小到每一个操作步骤,一遍遍的亲自试用体验,从应用逻辑到界面 UI,每一个细节 CRMEB 都在一一校对打磨。 CRMEB Pro v1.1.5 内容亮点:一、营销流动1、新增虚构成团,一键复制流动商品性能 2、砍价性能调整为砍价人数设置,新增砍价列表 3、秒杀工夫配置优化 4、新增优惠券时,首页弹窗揭示用户并减少会员专属优惠券 5、新增领取后赠送优惠券,增加商品时关联优惠券,可一键复制优惠券 二、客服性能新增 PC 端以及挪动端独立客服功能模块 可做到用户征询主动调配,辨别出用户是通过挪动端还是 PC 端进入,多个客服之间能够一键疾速转接,聊天界面可间接治理订单,发货,改价、增加用户标签等重要操作。 三、用户治理及付费会员1、可手动增加用户,用户标签减少一级分类 2、新增付费会员性能 3、新增实体卡会员,可导出会员卡进行印制 4、新增多项会员权利 四、商品及数据统计1、新增商品口令,可自在增加淘宝口令、抖音口令等 2、新增可分享挪动端商品详情到微信好物圈性能 3、新增商品、用户及交易等多维度具体数据统计性能 五、一号通及模板音讯1、后盾可批改短信签名,短信验证码过期工夫设置 2、推广员胜利推广上级及佣金入账时发送模板音讯告诉 3、新增一号通,短信、商品采集、物流查问、面单打印多账户合一 六、商家配送1、后盾新增配送员治理 2、挪动端用户订单新增核销码,配送员货物可扫码核销 七、支付宝领取1、新增支付宝领取 2、新增佣金主动提现到零钱配置 八、渠道二维码每个渠道二维码对应后盾主动回复增加的每个关键词信息。 通过生成独立渠道二维码前期可统计用户起源,将依据此性能开发更多的营销玩法,比方扫码抽奖等! 九、后盾组件【DIY】1、新增专题流动页面自定义组件 2、相干组件优化调整 源码附件曾经打包好上传到百度云了,大家自行下载即可~ 链接: https://pan.baidu.com/s/14G-b...提取码: yu27百度云链接不稳固,随时可能会生效,大家放松保留哈。 如果百度云链接生效了的话,请留言通知我,我看到后会及时更新~ 开源地址码云地址:http://github.crmeb.net/u/defu Github 地址:http://github.crmeb.net/u/defu

July 11, 2022 · 1 min · jiezi

关于小程序:微信小程序开发-问题记录

本文记录小程序发时,遇见的疑难杂症,随时更新。 image 标签周边有间隔,设置padding|border|margin:0 仍然有效,应该设置 display:block;内容少,望大家不要举报。

July 9, 2022 · 1 min · jiezi

关于小程序:开发一个小程序商城需要多少钱

开发一个小程序商城须要多少钱?小程序商城的制作流程是什么?明天 CRMEB 就和大家来聊一聊开发小程序商城的办法以及费用,感兴趣的敌人连忙来看一看! 办法一:源码开发(4 万左右) 开发小程序商城,首先咱们要组织延聘残缺业余的开发团队。其中要蕴含项目经理、前后端开发人员、UI 设计师以及测试人员等。在团队成员有良好的单干沟通这样的现实状况下,个别小程序的的开发周期快的话是半个月左右,而下面的团队成员均匀月薪在 1.5w 左右,按每个岗位设置一人的条件,计算出的小程序商城总体开发老本至多为 1.5 x 5 x 0.5=3.75w,预留一些其余的开发花销的话就按 4w 来算。如果想要抉择源码开发的形式的话,咱们的估算必须超过 4w 成能够。 办法二:本人开发(不超过 3000 元) 本人开发制作微信小程序,只须要领取 300 元微信小程序注册认证费用。再加上购买域名与服务器等不会超过 3000 元,但这个形式须要你有肯定微信小程序开发编程代码和页面设计等综合能力。如果你具备这些能力的话,能够采纳这种形式。 办法三:套用模板(2000 左右) 当初网上就有十分多提供业余的小程序商城模板第三方建站平台,大多数商城模板都是能够收费搭建的,只有如果想要实现一些专业性的高级性能的话,通常须要用户购买一些指定的套餐方。套餐的价格越高,蕴含的服务性能也就越多,不过这些套餐的价格根本顶多是在几千左右,加上另外的域名和空间等资料,总体的老本也不会减少太多。 办法四:定制开发(5 万以上) 选用定制开发的形式,软件开发商依据你的需要来进行开发,耗时较长,开发费用也是绝对较高的。以一个商城类型的小程序为例来说,定制开发的费用个别要 5 万 - 20 万之间,耗时 3 个月以上。 小结:以上就是对于开发一个商城小程序的办法与所需的费用,心愿可能帮忙到您!如需理解更多小程序常识与小程序开发等服务,欢送征询 CRMEB,咱们期待您的到来! 源码附件曾经打包好上传到百度云了,大家自行下载即可~ 链接: https://pan.baidu.com/s/14G-b...提取码: yu27百度云链接不稳固,随时可能会生效,大家放松保留哈。 如果百度云链接生效了的话,请留言通知我,我看到后会及时更新~ 开源地址码云地址:http://github.crmeb.net/u/defu Github 地址:http://github.crmeb.net/u/defu

July 7, 2022 · 1 min · jiezi

关于小程序:模板小程序或定制小程序有什么区别

小程序定制开发服务绝对模板来说,价格是高一些的;个别得,要找小程序定制开发,定制开发大略须要以下这些人:1)产品经理次要负责产品的整体设计和需要的文档,就像是一个货色必须要有重心一样,产品经理就是担当着这个重任2)UI设计师一个好的小程序利用不仅须要合乎公众的需要,还须要适宜公众的审美页面,设计师就是充当着投合公众审美的重任,3)前端开发师就是将页面设计师设计的图纸完满复制到页面下来,页面搭建在好看上肯定要严格,当然这个是不须要有多高的审美,只须要有足够的急躁和仔细就好了,可能依照UI图下面设计的货色做到1:1还原,那就是很合格的前端开发师了4)后端开发师如果说前端只是把UI图下面的模样搬下来,后端就是将这些赋予生命吧,把一些动态的货色用代码去让他们变成动静的5)测试人员对于开发进去的APP前后端进行一个具体的测试,无论发现任何问题都需及时反馈给对应的开发人去进行批改,APP开发须要留神的细节较多,一个业余的测试人员非常重要,算是我的项目最初的把关人员。对于模板小程序的性能,它必须是零碎中的一个通用函数。它不能独自为企业开发新的性能,不能满足一些企业的个性化需要。而定制开发就是要充沛遵循企业的需要,对企业想要的性能进行定制、开发,这样能力领有更好的用户体验。模板小程序的价格绝对定制开发小程序的价格要低很多,以一个根底商城类小程序为例,他的价格大概是几千元,价格比拟低的起因是因为模板开发,其实就相当于替换一下小程序里的商品、链接、图片等等,工作非常简单。而定制小程序相当于是给企业量身定制的,所以价格会高一点,一个商城类小程序价格也得在1万元以上。尽管定制小程序的价格比拟高,但这类小程序往往能更合乎本身企业的产品特点和需要,所以抉择定制小程序的企业会更多一点。

July 1, 2022 · 1 min · jiezi

关于小程序:支付宝微信小程序常见开发问题汇总

支付宝小程序:(2020.12.4 - 2022-3期间批改)1.自定义组件内申明的事件,事件处理函数只能写在自定义组件js中进行治理。2.template模板中不能引用自定义组件。并且如果要动静渲染某一个字段,必须在page的data对象里申明一个配置对象。例如:data:{indexBannerConfig:{indexBannerList:''}} this.setData({{indexBannerList:[...,...,]}} 而后用template的 data属性就行传递<template is="some" data={{...{indexBannerList:''}} />3.axml的style解决模式:<view style="color:{{ isRed ? 'red' : ' '}}">4.axml的属性要绑定动态数据不须要加双引号,wxml,swan需加双引号。<view a:for={{list}} > success in axml <view a:for=”{{list}}“ > success in wxml,swan5.tab组件的tab-content不能用a:for循环6.image,依赖引入资源时能够应用绝对路径。引入自定义组件不行7.自定义组件申明的事件如何放在page里对立治理?首先子组件申明的事件,只能在子组件中设置监听函数。子组件外部的数据只能由子组件应用this.setData来更改,父组件触发无用。子组件 <view onTap="testClick"> method:{testClick(){this.props.onTestClick() //此处父组件必须是on结尾的自定义属性绑定的事件,否则编译器会把它转成字符串。父组件 <myView onTestClick="本人命名的函数"> 本人命名的函数():{......}8.多目运算法this.maskRight=(speed<18 || speed>95) ? 0 :((speed>18 && speed<=85)? 1080 : 1080 - 1080/10(speed-85)) /遮罩层间隔左边*/9.async和await解决异步async doOne(){ let res = await this.doTwo() //await承受一个promise对象console.log(res)}, async doTwo(){ return new Promise(res=>{ res('1233')})}10.相对不要这样赋值App({ isAuthorized:false},onLaunch,onShow) //在onLaunch,onShow中进行”this.isAuthorized=true"扭转而后page里的data({isAuthorized:app.isAuthorized})//只会获取默认的false,必须通过setData进行更新this.setData({isAuthorized:app.isAuthorized})11.防抖:n秒内,传参函数提早执行,也就是说用户在主handler函数里点击屡次,触发屡次响应函数会提早执行,但不会只执行一次;节流:n秒内,传参函数提早执行,也就是说用户在主handler函数里点击屡次,触发屡次响应函数会只执行一次 12.<focus-on-fortune onClosed="敞开监听办法" onFollowAndFavorite="关注&珍藏监听办法" onFollow="关注监听办法" onFavorite="珍藏监听办法"/> 组件展现固定在小程序页面顶部,加载显示时会有向下推出动画;组件一共2套显示格调,深色和浅色,会依据 title bar 的背景色彩主动抉择,如果title bar是深色,那组件就是深色格调,反之如果是浅色,那组件就是浅色格调;组件是为有关联财产号的小程序打造的一键关注财产号,并珍藏小程序的性能;如果小程序没有珍藏,并且没有关注关联的财产号,组件按钮显示“立刻增加”,logo是对应的财产号,title是对应的财产号名称,点击logo或文字跳转到对应的财产号页面,点击“立刻增加”,胜利变成“查看”,之后“查看”也是对应跳到财产号页面;如果小程序已珍藏,但没有关注财产号,组件按钮显示“关注”,其余的操作&显示和第4条统一;如果小程序已关注,但未珍藏,组件按钮显示“珍藏”,logo是对应小程序logo,logo和文字不可点击,“珍藏”胜利之后,按钮隐没;如果小程序已关注&已珍藏,组件不显示;组件点击敞开按钮,组件隐没,并有向上推的动画;组件有4种事件可增加捕捉,敞开,关注&珍藏,关注,珍藏; 问题1:测试的时候,为什么组件不呈现了?答复: 组件的呈现有对立的疲劳度管制,若用户点击敞开组件后,3天内不再呈现组件;用户最多有3次敞开组件行为,即用户有一次敞开组件,后续组件显示中,如果再被敞开第二次、第三次时,永远不再对该用户显示组件;若要解决该状况,能够重新安装客户端包;组件对应支付宝最低版本是10.1.55,低于这个版本组件不显示;对于网络异样,网络谬误等起因,组件也是降级不显示;如果应用组件的小程序,没有关联的财产号,组件也不显示;如果小程序曾经实现了珍藏,并且对应的财产号曾经关注,也不显示;13.①小程序模板音讯退订,步骤如下:1、在“服务揭示”页面,左滑单条音讯;2、点击“退订此类音讯”; 14.音讯订阅插件会存在点击'回绝,下次不再拜访'或者’批准承受音讯‘都会走success回调,如果要监听’回绝下次不再拜访‘能够通过res.refuse字段来操作,为true代表用户点击了 下次不再展现. ...

June 27, 2022 · 1 min · jiezi

关于小程序:送给小程序开发者的一份问卷调研❤️

https://survey.umeng.com/apps... 你是否收到过用户的这些投诉? “页面关上太慢了”“关上后是空白的” “看不到想要的内容”“页面关上后有局部显示空白” 不晦涩、加载慢、打不开....在终端用户的日常应用中,可能遇到多种小程序的问题。 用户的急躁是无限的 经钻研发现,如果一个页面5秒还没有反馈,约80%以上的用户会抉择放弃。他们可能正在下单付款、正在参加流动、正在写好评……页面的失败可能间接导致这所有行为的中断。那么如何保护好页面的性能,怎么利用性能监控工具进行页面性能保护,就成为承载业务的要害。 友盟+U-APM性能监控平台近期上线小程序利用性能监控性能,能够疾速帮忙开发者监控JavaScript报错状况、API申请情况。利用SDK进行多场景的问题采集并提供监控告警的能力,7*24治理页面性能。 JS异样监控 反对采集小程序中的JS异样,并提供谬误数据统计、谬误列表聚合、多维度查问与散布、谬误详情、SourceMap解析的能力、单设施查问 申请监控 反对API申请的申请趋势、申请散布数据查看,以及慢申请、失败申请的详情。能够灵便依据Apdex设置申请的定义阈值,并且查看散布数据,如果开发者想与服务端URL做联动,也可在平台中设置,采集后会主动拼接,能够一键跳转服务端URL。 灵便多平台自定义告警 反对灵便自定义告警、触达通道蕴含邮件、企业微信群、钉钉群和飞书群,随时发现网页问题。

June 16, 2022 · 1 min · jiezi

关于小程序:APP该如何顺应数字化时代

C 端 App 已死,有事烧纸在咱们日常生活中,每天都会关上应用的 App 有几个?咱们的手机上满屏的 App,绝大部分都是僵尸 App;作为消费者,咱们日常应用的都是超级 App 而且数量不会超过十根手指。社交电商、衣食住行、银行服务、视频娱乐等较为高频的场景日益聚合在互联网大平台所提供的 “超级 App” 中,独立第三方 App 即使聚焦细分畛域的特定群体,仍然不得不与大量其余竞争者强烈抢夺消费者掌中那方寸之屏。 B 端 App 都是毫无怄气的信息孤岛作为打工人,谁手机还没有那么几个东家或者甲方指定应用的 App – 挪动办公、企业协同、与行业合作伙伴的商务连贯、服务客户专用的展业工具等等。大部分这类 App 用起来都是很不爽的,例如体验差却迟迟等不到优化降级、想要的性能久久不能上线、齐全是信息孤岛无奈与其余常用工具买通、看不到其余共事的流动无奈与之互动等等。导致咱们打工人对同是打工人的 IT 同志们产生肯定的误会和吐槽有没有? 信息化的思维定式对于不足互联网基因的传统行业 IT 来说,迄今大部分还是沿着 “信息化” 时代的思维定式来对待 App 的开发:C 端和 B 端的 App 都是手机利用、技术上并无差别,而 App 只不过是在一个更小的屏幕上以更敌对的交互体验出现应用逻辑 – 总不能让用户在几英寸的手机屏幕上关上浏览器敲网址吧?屏幕上的 App 其实就是一个个快捷链接…这种思维定式下,无论用什么计算机语言开发 App,跟 30 年前用 HTML + CGI 开发一个网站,没有什么区别,就是:咱们公司曾经有了这些那些零碎,当初咱们得给它们包一层,输入到网上给咱们的客户、合作伙伴应用。这就是传说中的信息化,即在 “电算化”(以本地软件系统代替手工劳作)的根底上,再接上网络从而使数据字节可能被提交进来、输送进来,造成 “信息”。 App 是这么玩的吗? C 端 App 该怎么玩?消费者侧,全副是互联网平台的天下,它们才是流量入口、超级利用,才是消费者日常高频应用的货色。对于大部分垂直行业的企业而言,研发 App 的能力无限、经营 App 流量日活的技能有余、互联网化的基因欠缺,要把本人的 App 做好,在利用市场怀才不遇,堪称艰巨。研发的投入产出比也很差。但西谚有云:“如果你不能战胜他们,那就退出他们”。所以更理论的策略只能如下:首先,拥抱消费者所在的互联网流量平台,采纳该平台所凋谢的技术框架,把本人的产品与服务 “进驻” 到该平台上,让该平台的用户发现、应用。任何能称得上是 “平台” 的互联网产品,肯定是有技术标准、技术接口、凋谢生态、欢送第三方 “进驻” 的。典型例子,就是家喻户晓的 “小程序” 了;其次,咱们还是能够向消费者提供 App 的。指标受众,是把通过上述平台 “引流” 过去并积淀下来的存量用户,他们可能作为客户须要更间接、更权威、更功能强大的连贯工具触达企业。所以咱们的策略,是让本人变身 “八爪鱼”,把本人的产品与服务像触须一样延长到第三方流量平台,例如用户在第三方平台应用咱们的小程序的时候,能够被提醒去下载采纳更弱小更间接的 App。别忘了,咱们向消费者提供的 App 须要充分利用手机的社交通信属性,让消费者通过 App 能找到咱们的客服、客户经理、专家。如果用户在 App 里却无奈分割到你的员工,有槽无奈吐、有倡议无奈提,这所有明明在一个通讯设备上,是不是一件很愚昧的事件?你的员工也应该在同一个 App、或者另一个与之连贯的所谓 B 端 App 上。 ...

June 16, 2022 · 2 min · jiezi

关于小程序:小程序发展史知多少

在 2022年的明天,小程序曾经渗透到咱们生存的方方面面,每一天的生存与办公场景中,「小程序」都在扮演着不同的角色。你好奇小程序发展史吗?明天让咱们聊聊小程序是怎么诞生的吧! 一、小程序是什么?在 2016 年的「微信公开课 Pro」演讲中,微信事业群总裁张小龙这样形容了小程序的前景与将来: “小程序是一种不须要下载安装即可应用的利用,它实现了利用“触手可及”的幻想,用户扫一扫或者搜一下即可关上利用。也体现了“用完即走”的理念,用户不必关怀是否装置太多利用的问题。利用将无处不在,随时可用,但又毋庸装置卸载”。苹果官网对「轻利用」的介绍页面 而在 2020年的「WWDC 苹果寰球开发者大会」中,轻利用则被作为 iOS 14 的次要性能进行强调与推介: “App Clip 就是一种无需用户在 iPhone 或 iPad 上装置残缺的应用程序,就能够拜访应用该应用程序的局部性能的轻量级利用,它们专一于解决简略疾速的工作”。不论是张小龙对「微信小程序」略带文艺的形容,还是在 WWDC 上对于「轻利用」在 iOS 生态中的位置形容,咱们都能大抵能了解小程序诞生的初衷。而如果咱们把工夫从这两场发布会的转至今日,却会发现小程序早已不再局限于「用完即走」与「疾速关上」,各式各样的小程序已出现百花齐放的状态,不论是工具小程序,内容小程序,交易小程序,直播小程序,各种类型包罗万象。 无妨让我尝试用本人的工作日常举例,早上出门下班,我会关上「天府衰弱通」扫描地铁场合码,并把衰弱码给地铁安检查看,邻近中午11点 30分,我会用「美团」或「饿了么」为本人订一份工作餐,吃完午饭后我会关上「动物餐厅」看看小猫咪又赚了多少小鱼干,下午会议时应用「腾讯文档」查看会议纪要,快下班的时候用「叮咚买菜」购买晚饭所需的食材,早晨回家做饭时,用「懒饭 App」看看想吃的番茄肥牛饭怎么做。 各种类型小程序的应用截图:时至今日,当咱们说到小程序时,也不仅仅在特指微信小程序,各式各样的平台都纷纷推出了本人专属的小程序平台,不管支付宝、字节跳动、美团还是百度等其余互联网大厂,都纷纷推出了本人专属的小程序平台,且都基于本人的生态业务,为小程序提供流量进行反对,心愿用户与开发者可能抉择自有平台中的小程序进行开发。 随着小程序业务的愈演愈烈,越来越多的流量都被引入了互联网巨头的小程序战场中,但在这个过程中,对于战场中「关闭,不通明」的吐槽与争议也逐步呈现,有数企业都心愿本人的利用中也能具备运行小程序的能力,心愿可能借此抗争小程序被引入寡头所管制的战场,但「知易行难」,疾速实现对小程序的底层与容器的研发,所须要破费的精力与工夫并不是短时间就可能实现的。 事实上,小程序能够被了解为是「挪动利用 App」的一个细分子集,如果依照「平等通明」的构想,小程序不应该仅仅存在于微信之中,那些咱们并不常常应用的利用都能够通过小程序进行从新优化,咱们能够通过各式各样的专门利用关上相干的小程序,从而对那些「太重的利用」进行减负操作。 当然了,小程序还会有这样一些个性须要咱们留神: 小程序不具备「被关注」的能力,获取流量留存用户的操作须要由独立利用或其余渠道实现;小程序不具备「推送音讯与群发音讯」的能力,对用户的信息触达与消息传递的操作须要由其余渠道实现;小程序不具备「跨 App 分享 」的能力,因而对于小程序的分享与关上门路,须要在设计产品时提前思考,而不是把鸡蛋放在一个篮子里。 二、什么利用适宜用小程序开发?很多敌人在理解到 FinClip 的小程序容器时,都会想请咱们看看对方的业务场景是否适宜应用小程序进行开发,尽管小程序市场时至今日仍然是一片蓝海,但我想也不是所有利用「都能够,都应该」应用小程序开发的。 基于咱们的教训与积攒来说,合乎「逻辑简略,应用低频,对性能要求不极致」的利用场景,更加适宜应用小程序进行研发。 「逻辑简略」是指利用的操作逻辑并不十分复杂,各类生存服务(如打车,订餐,查地图与导航等等)都须要给用户提供简略清晰的操作逻辑,而这一类也人造的合乎起初小程序「用完即走」的定义,因而非常合乎应用小程序研发。一些逻辑简单的利用场景想要通过小程序进行适配,就可能会面临更多的设计与研发艰难,同时在性能和体验也可能会面对更多须要解决的问题。 「应用低频」是指小程序的应用频率不应该太高,比方社交类的钉钉或飞书,金融类的掌上生存或浦大喜奔,媒体类的网易云音乐或斗鱼都不太适宜应用小程序进行从新设计。对于用户应用的频率较高的利用来说,间接关上利用进行体验的步骤必定最快的,此外因为某些行业的非凡性质(比方具备交易,领取等能力)要求,对于安全性与保密性的首选危险判断准则,也不宜应用常见的小程序进行设计。 「对性能要求不极致」是指因为小程序始终存在于某个独立利用(也被称为宿主利用)中,思考到目前的性能与研发所限度,临时不太适宜开发对于这两者有更高要求的挪动利用。比方把原神,王者光荣这样的游戏利用通过小程序进行从新设计,在目前来说必定是不事实的。 FinClip 客户案例当然,随着相干研发实力的加强与产业生态的逐步补充,也有越来越多的「不可能」变为了「可能」,比方华西证券的「华彩人生」,浦发银行的「浦大喜奔」,某省的挪动警务平台等客户,都纷纷抉择应用 FinClip 的小程序容器计划进行落地实现。 三、小程序与 H5,原生利用有何区别?很多敌人在理解小程序技术的时候,都会有这样的纳闷“到底与 H5,原生利用”这些技术相比,小程序具备哪些劣势与劣势呢? H5 挪动利用咱们常说的 H5 其实也通常能够被视为一种 Web App,相比于咱们在桌面端浏览器中关上的网页,次要是减少了一些响应式的设计与交互优化,从而使得这些网页更适宜在挪动端的浏览器中显示运行。既然是网页利用,那仍然是基于 JavaScript,CSS 和 HTML 进行实现的,因为是基于各类前端技术栈进行实现,最大的益处就是疾速、简略、不便,且有各种技术材料能够参考。 同样,H5 的毛病与长处也是并存的,比方因为技术曾经很成熟了,对于前端教训欠缺的新人来说,面对各式各样的框架,模块、工作管理工具,UI 库可能会呈现无从下手的问题;此外相比于原生利用,对于零碎权限的获取(比方数据缓存能力,网络通信状态等)都显得比拟鸡肋,当低性能的设施加载蕴含简单逻辑的页面时,会呈现显著的卡顿与提早问题。 原生利用原生利用也被叫做 Native App,相比于 H5 利用通过前端三大件进行实现不同,原生利用次要会采纳 iOS 与 Android 的专有语言 Object-C(或 Swift),Java(或 Kotlin)进行实现,大多咱们所常见的国民利用,比方微信,支付宝等都属于这种原生利用。 ...

June 16, 2022 · 2 min · jiezi

关于小程序:数字化转型有必要吗

如果你接触过数字化,那应该晓得“全球化和数字化转型是 21 世纪的两大经济趋势”,国内政治格局变动导致全球化正受到去全球化的挑战,而疫情加剧,使得数字化转型没有进行反而放慢了速度,近几年也衍生出了大量的线上业务。 随着“企业数字化转型”概念的越发炽热,各行各业都纷纷张开双手,基于本身对数字化转型的构想,设计出本身可能提供的解决方案,比方: IBM 基于工业物联网提供的数字化转型计划;西门子基于数据赋能提供的数字化转型计划;泛微基于办公 OA 提供的数字化转型计划;Red Hat 基于开源准则提供的数字化转型电子书;麦肯锡寰球研究院在 “中国的数字化转型”一文中,表白了这样的观点: 对于中国的小企业,数字化的晋升可能会帮忙他们进步劳动生产率,寻找新的合作形式,并使其能够利用电子商务扩充其经营范围。预计在将来的十几年中,互联网将有可能在国内 GDP 增长总量中奉献 7%到 22%。预计在将来的十几年中,互联网将有可能在中国 GDP 增长总量中奉献 7%到 22%。互联网也能够借助本身的倒退,为各行各业提供相干的帮忙。 如果你已经关上过 FinClip.com 的产品官网,会在关上首页的第一屏看到一行大字“疾速打造数字化超级 App”,很多前来征询的客户也表白过本人是因为“数字化转型”的背景找到了咱们。 互联网为生产电子类产品开释出微小的翻新能源,包含智能家电和网络电视等连贯设施。借助互联网,中国二手车市场领有微小的增长后劲。互联网还能帮忙化工企业晋升研发能力,促成与客户及内部专家的单干。网上货币市场基金、折扣券商和第三方在线市场开始呈现。中国的购房者和租房者越来越偏向于在网上搜寻现实居所。互联网更扭转了商业房地产的需要,网络批发升高了实体网点的需要,却进步了领有先进物流的古代仓储地产的需要。互联网还能利用电子衰弱记录和临床决策支持系统等翻新技术晋升医疗品质,而病人能够通过在线预约工具和点评平台理解医疗服务提供商的资质评级。这些转型计划和剖析文章中论述了各种宏观必要性和因果关系,如同咱们曾经充分认识到了“数字化转型”这件事的必要性,但我始终认为有一个外围的问题答案大家仿佛都不太明确。 数字化转型计划为谁而做?从销售和商务达成的角度来说,天经地义须要围绕企业或机构的须要来实现,近些年各种类型“数据大屏、智慧座舱”充沛印证了这一点。 有数“数字化转型”的最终交付物变成了一块“数据大屏”,这块大屏能够从采集数据、数字化管控直至数据汇报,充沛满足所有和数字化转型相干的需要。 但千篇一律的行政地图,扇形图和柱状图不由得让洽购者开始狐疑“这就是数字化转型吗?” 数字化转型应该为用户的体验而做数字化转型须要围绕企业或机构的须要实现并没有谬误,但我认为数字化转型的第一工作,是通过数字化相干的技术晋升每个行业的客户体验。仅仅简略地实现数字化座舱就认为数字化转型工作完结当然是大错特错的。 正因如此,任何行业发展数字化转型的计划才有清晰的指标与指引。如果想要打造数字化医院,注册上线微信公众号和微信小程序并不能解决这个问题,晋升前来就医的患者和挂号免费员工的体验才是;如果想要设计车联网数字化零碎,引入安卓车机和各种场景的 App 并不能解决这个问题,让车机的滑动更加晦涩,利用的加载工夫更短才更高效;如果想要打造数字化电力运检零碎,提供一块数字化大屏实时显示以后的零碎流量与异样并不能让所有人的体验更加高效,让巡检人员可能快捷地摘抄数据查看状态更加有意义。而发现这些问题,须要咱们察看那些用户,他们在什么工夫,什么背景和场景之下,进入了这个零碎,他们的操作流程大略是怎么的,他们会在每个步骤上破费多长时间。 之前去医院做查看的时候,我发现太多人都在手机屏幕背后露出踌躇与不解的表情。 明明曾经领取胜利,却无奈取得核酸测试的条码;明明曾经过了 2 个小时,然而屏幕上却只会显示“数据异样”和一串错误代码;老年人把手机字号调大了,因而每个按钮也只能看到一个字了;人手不短缺导致患者找不到导诊护士发问,找语音机器人发问却只会收到空洞反复的“道歉,我听不懂你在说什么”……国家网信办也曾专题讲述,应留神数字化转型中的问题 国家网信办在《减速数字化转型 助力央企高质量倒退》一文中专门表述“数字化转型须要一个过程,绝非久而久之,也不应仅限于某个倒退阶段,而是一个长期重要工作,能够说数字化转型没有起点。” 下面提到的这些问题,并不会因为新注册了一个小程序或公众号就有所缓解,也不会因为把所有业务挪到 App 上就能彻底去除。小程序与 App 实质上都是服务的载体,咱们更加须要联合不同技术形式的优缺点,来全盘考虑。 但不论如何剖析,我想“数字化转型归根结底须要晋升用户的体验”应该是咱们所达成的共识。 如果您也在数字化转型过程之中,为用户提供更加敌对的用户体验,能够试着思考通过小程序进行技术实现。在《小程序的昨日与明天》一文中,咱们曾专题解说了小程序,H5 与 App 之间的各种差别,相比于 H5 与 App,小程序人造具备跨平台,体验更优,体积更小,安全性更高,上手门槛更低的各种劣势。

June 15, 2022 · 1 min · jiezi

关于小程序:零基础搭建智能垃圾分类小程序

1、先上图 2、筹备工作一、申请一个小程序申请地址:微信公众平台,申请小程序的操作很简略,大家百度一下跟着步骤申请就行,某宝上还有认证小程序代申请代认证,老铁们能够自行抉择。 二、下载微信开发者工具下载地址:https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html 三、下载解压HBuilderX 下载地址:https://www.dcloud.io/hbuilderx.html 3、搭建开始请确保 HBuilderX 更新到最新版 一、小程序源码地址,点击购买一般受权版本,只须要8.88 二、我这里云空间叫demo,如果没有新建个阿里云空间即可(创立 uniCloud 服务空间),右键uniCloud目录关联到与治理后盾同一个服务空间,全副勾选,点击间接部署服务空间,导入HBuilderX 关上文件 uniCloud => cloudfunctions => common => wx-auth => index.js 配置 wxConfigMp 内的 appid 和 secret(在微信小程序官网的后盾获取) 三、我的项目装置依赖 我的项目根目录 npm install 装置依赖 四、配置我的项目1、关上微信微信开发者工具,在平安设置中关上服务端口 2、关上HBuilderX,点击“运行-运行到小程序模拟器-运行配置”中设置你装置微信开发者工具的门路。 四、公布小程序1、右键我的项目文件夹,点击“发行-小程序-微信(仅实用于uniapp)” 2、填写小程序名称和小程序appid即可唤起微信开发者工具。 3、在小程序后盾,开发治理中配置服务器request非法域名:https://api.bspapp.com; https://zy-api.wxthe.com 4、在微信开发者工具点击上传,在小程序后盾提交审核,审核通过后即可失常经营 作者相干文章反编译获取任何微信小程序源码——看这篇就够了 抽签小程序,妈妈再也不必放心谁洗碗(分配任务)了,so easy 5分钟实现微信云小程序领取性能(含源码)

June 14, 2022 · 1 min · jiezi

关于小程序:小程序

引入第三方包微信小程序反对 echarts, 微信小程序加载 echarts 引入 echarts微信小程序引入 github 地址 echarts 体积过大的时候, 采纳压缩, 不要下最新的, 下 5.0 就行了 echarts 刷新性能, 通过调用 setOptions 办法 援用 vant weappnpm init -y 创立package.jsonnpm i -s 装置vant点击详情, 默认应用npm模块点击工具, 构建npm, 每次装置新的npm包的时候都要构建一下在.json文件中的, userComponents中注入批改 vant 的款式<van-search backgroun="#aaa" /><!-- 笼罩款式 -->去页面下面, 选中类名, 而后在wxss外面笼罩掉, 应用 !important组件组件创立去 components 中创立一个组件, 会主动生成模板, 组件生命周期和页面的生命周期不雷同 发送事件methods: { hadnleRightClick() { this.triggerEvent("click") }}bind:click="handleClick"组件监听事件this.triggerEvent("父组件自定义事件的名称", 要传递的参数) <list-item bind:change="handleChange" ></list-item>点击事件 bindtap传值<child-com count="{countData}">承受properties: { count: { type: "", value: "" }}小程序属性想要获取绑定后的值通过 data-jidjj="" 的模式来获取const idx = event.target.dataset.idx指令用法循环wx:for="{{arr}}" key="*this"默认有item, index, 对象的时候有差别显示wx:if = {{true}}生命周期app 生命周期app.js ...

June 13, 2022 · 3 min · jiezi

关于小程序:小程序启动性能优化实践

本期技术加油站给大家带来百度一线的同学对小程序启动性能优化的小技巧:本文从性能优化的价值、性能指标的定义域掂量以及如何优化性能这几局部内容来帮忙大家疾速对小程序性能优化相干的办法有肯定的了解。 一、小程序简述小程序作为新型的 APP 利用解决方案,因为它快捷的开发效率,高效的公布能力,以及丰盛的与端协同能力,被越来越多的被互联网各个厂商所认同,不谋而合的转战到这个赛场上。性能是推动业务飞轮的技术突破点,未免也会引发大家对小程序的性能这一块的疑虑?小程序的性能如何掂量,有没有比较完善的针对性能优化的思路与工具?针对下面的问题,咱们从性能优化的价值、性能指标的定义域掂量以及如何优化性能这几局部内容来帮忙大家疾速对小程序性能优化相干的办法有肯定的了解。 二、为什么要进行性能优化小程序性能是指小程序在百度 APP 或其它宿主 APP 中加载和出现的速度,以及小程序对用户交互的响应水平。性能欠佳的小程序显示速度和对输出响应的速度较慢,甚至会呈现内容不可拜访的状况,这将在不同水平上影响用户体验,从而导致用户散失。 晋升应用时长开发者心愿用户可能通过小程序进行有意义的行为。例如电商类小程序心愿用户购买商品;内容类小程序心愿用户浏览、订阅;政务类小程序则心愿更加简略便捷的为用户提供服务。 多项案例钻研表明好的性能,能够更好的留住用户: Pinterest 将用户等待时间缩小 40% 后,搜索引擎流量和注册人数随即增长 15%;COOK 将均匀加载工夫缩小 850ms 后,转化率晋升 7%、跳出率降落 7%,同时每次会话浏览页数减少 10%。而性能欠佳则将散失更多用户: BBC 钻研发现网站加载工夫每减少 1s 将多失去 10% 的用户;DoubleClick by Google 则示意,如果页面加载工夫超过 3 秒,53% 的挪动网站拜访流动将受到摈弃。进步转化率转化率是指用户进行了某些指标行为的拜访次数与总拜访次数的比率,这些行为包含订阅、购买等。留住用户对于晋升转化率至关重要,已有钻研表明缩短渲染工夫可进步转化率:Tokopedia 将 3G 连贯的出现工夫从 14s 缩小到 2s 后,访问者减少了 19%,会话总数减少了 35%,新用户减少了 7%,沉闷用户减少了 17%。同理,缩短小程序渲染工夫,将无效进步转换率。 晋升用户体验性能是发明良好用户体验的基本要素。当用户进入小程序时,良好的性能能够疾速加载页面。如果性能欠佳,加载速度过慢,用户则不得不期待,当用户忍耐低性能的小程序到肯定水平后,则会抉择放弃。《High performance iOS Apps》一书中的数据显示, 25% 的用户在利用启动工夫超过 3s 时会放弃应用。 三、性能指标与掂量应用性能指标来评估小程序的加载速度是十分必要的。首先回顾一下小程序页面加载的几个要害阶段。 这几个阶段的含意别离如下: 阶段含意Loading下载小程序包阶段First Paint(FP)>界面的首次绘制First Contentful Paint(FCP)首次有内容的绘制First Meaningful Paint(FMP)首次有意义的绘制Time to Interactive(TTI)页面绘制实现,达到可交互状咱们最为关怀的是,从用户点击小程序到第一个页面首次有意义绘制(FMP)的总耗时。百度智能小程序为开发者提供了性能监控指标平台,帮忙开发者监控小程序的线上加载性能。开发者能够在“开发者平台-开发治理-运维核心”的界面,看到小程序的加载性能监控。在运维核心中,用户能够监控小程序的性能指标(在运维核心中,FMP 称为上屏时长),如下图所示: 四、如何进行性能优化==============4.1 小程序启动流程---------------无效地辨认小程序性能问题并制订优化策略的重要前提是可能理解、相熟小程序启动流程。因而,咱们首先大抵介绍下百度智能小程序的启动流程,如下图所示:接下来简要介绍下各个环节小程序框架次要做的内容:1、用户点击关上小程序小程序启动的终点。2、下载小程序包用户首次关上小程序时会下载最新版本的小程序包。3、启动小程序运行框架初始化小程序逻辑层* 加载逻辑代码:逻辑代码指的是App、页面、自定义组件和用到的其余js模块的汇合。 * 执行 APP 生命周期函数:必要的 js 资源加载实现后,小程序框架会执行 App.onLaunch、App.onShow 生命周期函数。 初始化小程序渲染层* 加载以后页面显示所须要的多种资源,包含:app.css、页面和所有自定义组件的模板(.swan)与 css 相干文件等。 * 自定义组件资源加载实现后,小程序框架会初始化自定义组件,将其解决为渲染所须要的组件。 4、initData 与首次渲染逻辑层初始化实现后,小程序框架会收集页面显示所须要的数据(initData),而后将此数据发送给渲染层(sendInitData)。渲染层收到 initData 后,会初始化页面,绑定模板与数据,并开始首次渲染(FCP)。5、执行页面生命周期渲染层实现页面首次渲染后,会告诉逻辑层(firstPageRender)开始执行页面生命周期。开发者通常会在 onLoad-onReady 生命周期中,开始申请页面主数据(小程序心愿首屏展现给用户的数据)。6、首次有意义的渲染数据申请实现后,开发者通常会将数据发送给渲染层(setData),而后渲染层绘制实现后触发 FMP。> 后文中,咱们会把页面主数据的申请和之后对应的 setData 称为外围申请(request)和外围 setData。 ---4.2 如何辨认性能问题?-----------------性能问题可能会产生在启动流程中的不同阶段。不同的小程序,面向的应用场景不同,业务逻辑不同,展示给用户的页面构造也不同,因而性能问题的体现会有微小的差别。即便对于同一小程序,不同阶段存在的问题对最终性能的影响水平也不同。咱们往往须要关注性能瓶颈,而漠视绝对不重要的局部。此外,小程序启动流程中的各个阶段并不是独立的,会存在一些分割。当实现一部分性能优化后,性能问题的体现可能会和之前存在较大的差异,须要从新剖析思考。 因而小程序性能问题的剖析与辨认是一个绝对简单的过程。过来,剖析小程序性能问题,通常依据过往的性能优化教训或者通过浏览小程序代码等形式来做到。但这一过程不仅耗时耗力,且最终后果不肯定精确。 工欲善其事,必先利其器。应用好的工具,会极大地提高咱们剖析、解决问题的效率。百度智能小程序提供了启动性能剖析工具(https://t.hk.uy/bbsQ),能够将启动流程形象化地展现进去,以帮忙开发者疾速定位性能问题与影响。> 后文中,有时会将启动性能剖析工具简称为性能工具。上图为启动性能剖析工具的展现页面,次要由三个局部组成:顶部栏、左侧栏与主面板。顶部栏地方是两个选择器,别离用于抉择历史性能数据和对应的不同页面的性能数据。左侧栏用于切换不同的主面板,以显示不同类型的性能数据分析后果。在 FMP 面板中,启动性能剖析工具将启动流程转化为了时序图:1、左侧为逻辑层,右侧为渲染层2、从上到下,工夫逐步减少3、线的长度,示意了这一阶段在整体启动流程中的耗时比例(相对值)> 时序图的右侧,通过表列出各个阶段具体的开始、完结与耗时状况(绝对值)4、绿线示意以后线程繁忙,灰线示意闲暇,左右侧连接线示意通信(事件、数据传输),蓝线示意申请。能够通过时序图,疾速断定哪个阶段,相对而言是最耗时的。 ---4.3 如何解决性能问题?-----------------不同的性能问题,对应着不同的解决办法。依据教训,小程序的性能问题,通常呈现在初始化小程序逻辑层、申请主数据(onLoad 执行)、首次有意义的渲染这几个阶段中。下文将形容这些性能问题的具体表现与相应的优化策略。 ### 小程序包优化:缩小小程序初始化耗时在时序图中,通常体现为在 App.onLaunch 前耗时过长,如下图所示:在 app.onLaunch 前,次要阶段为加载和执行逻辑代码。加载逻辑代码的时长,次要和小程序逻辑代码体积相干。一般而言,小程序包越大,逻辑层代码体积也越大,因而加载会越耗时。开发者能够应用分包、独立分包(https://t.hk.uy/bbsS)或剔除无用代码等模式,升高小程序包的代码体积。执行逻辑代码的时长,次要和小程序逻辑代码业务相干。除了优化 js 代码自身执行的耗时外,开发者也须要关注 swan API 的调用状况。很多 swan API 因为波及到与客户端 APP 的通信,因而比 js 代码执行更加耗时。而小程序可能会反复调用很多 API,但这些 API 的调用后果是不变的,例如 getSystemInfoSync 等。因而倡议依据业务状况,将后果进行缓存,会无效缩小执行逻辑代码的时长。 ### 申请提前:尽可能早收回外围申请很多开发者会在 onLoad 中收回外围申请。但如启动流程所示,onLoad 执行依赖于首次渲染实现,如果首次渲染较慢,则会导致 onLoad 执行过晚。百度智能小程序提供一种页面级别的生命周期Page.onInit。此生命周期会在页面首次渲染前触发,相较于 onLoad,生命周期执行工夫会有极大的晋升。下图为将申请提前至 onInit 的时序图成果:能够看出,申请响应与首次页面渲染是并行处理的。因而会有非常明显的优化成果。百度晓得、百度百科、宝宝晓得小程序进行此优化后,别离带来了 210ms、100ms、150ms 的性能晋升。开发者要接入 onInit,可参考:Page.onInit 接入指南(https://t.hk.uy/bbsT)。### ### 申请响应优化:缩小外围申请耗时在时序图中,体现为外围 request 蓝线过长:除了优化网络服务器自身的性能外,优化申请响应也能够从如下几方面思考: 开启 prelink用于提前和业务服务器建设网络连接,使随后的主申请能够复用该连贯,晋升申请速度。上图为应用 prelink 前后的比照:在配置了prelink时,小程序框架会在加载逻辑代码的同时发送一个预连贯申请。在发送主申请时,能够间接复用该连贯,达到缩小主申请时长的目标。prelink 配置指南(https://t.hk.uy/bbsW)开启服务端 gzipgzip 是节俭带宽和放慢数据速度传输的无效办法。当服务端开启 gzip 后,能够减小申请传输的体积,使得传输速度更快。 缩小申请响应的体积某些状况下,申请响应中蕴含了较多与页面显示无关的数据,导致了传输体积过大,响应耗时太长;例如响应体积有 200K,其中只有 50K 与页面显示无关。蕴含过多无用数据的起因可能是因为一个数据接口服务于多种需要,而每种需要须要的数据不尽相同,因而导致了体积过大。能够思考与服务端约定新的数据格式与接口,以减小申请响应体积。### ### 渲染优化:防止首次渲染较多内容如下时序图所示,申请实现后,外围 setData 的渲染成为了最耗时的阶段。通常而言,这意味着开发者渲染了过多的内容。在很多业务场景中,小程序渲染的页面的高度是超过一屏的。但在首次进入页面时,只需渲染出可视范畴的内容即可。当页面首次渲染结束后,再持续异步渲染剩下的页面内容。因而能够对首次渲染的内容做肯定取舍或删减,例如:* 如果页面从上到下,由多个不同的独立局部组成,那么不在首屏内的局部,能够稍后渲染。 * 如果页面是由一组构造雷同的多个列表项形成,那么首次渲染时,被动管制列表项的长度,不在首屏中的列表项,稍后渲染。 案例参考:宝宝晓得问答页按需渲染优化(https://t.hk.uy/bbsY) 五、总结与瞻望===========开发者在理解小程序的性能指标和启动流程之后,能够比拟容易地通过启动性能剖析工具,发现性能问题并进行优化。除了上述提到的性能问题与优化策略外,开发者也能够进一步浏览百度智能小程序官网提供的性能优化文档,获取更多、更具体的优化办法与实际案例。除了依据时序图开发者自行剖析外,目前性能工具同时提供了性能剖析清单,能够主动剖析出小程序的性能问题并给出优化倡议。查看项与倡议,基于小程序以后运行的后果与线上的统计数据,交融了小程序性能优化的实践经验,因而通常会更加直观无效。在将来,咱们会尽可能提前将可能存在的性能问题提醒给开发者:将自动化的性能剖析与小程序公布流程有机地联合在一起,将性能问题拦挡在全量公布前,防止到了上线后才发现改变会引起非预期的性能进化。 ---------- END ---------- 举荐浏览【技术加油站】系列:百度工程师教你玩转设计模式(单例模式) 代码语言的魅力 百度程序员Android开发小技巧

June 9, 2022 · 1 min · jiezi

关于小程序:微信云开发

什么是微信云开发?微信云开发简介云开发又简称TCB,是微信官网给咱们提供的基于腾讯云的云服务器。 云开发蕴含:云数据库,云函数,云存储,云调用四项。 援用自官网的介绍 微信云开发是微信团队联结腾讯云推出的业余的小程序开发服务。 开发者能够应用云开发疾速开发小程序、小游戏、公众号网页等,并且原生买通微信凋谢能力。 开发者无需搭建服务器,可免鉴权间接应用平台提供的 API 进行业务开发。 官网:https://cloud.weixin.qq.com/c... 云开发的劣势 云开发的能力概览 云开发的筹备工作PS:如果小程序安装应用你都懂了,这些筹备工作你能够不必看,间接能够从步骤11看起了。1.微信官网文档中下载微信者开发工具:https://developers.weixin.qq.... 2.点击红色框中进入下载详情页,也能够间接点击上面链接,间接进入下载页面。下载地址:https://developers.weixin.qq.... 3.抉择本人须要的版本 4.找到下载的安装包,装置就是始终下一步,没什么可说的 5.登陆微信开发者工具,应用本人的微信扫码登陆即可 6.新建一个小程序 7.小程序注册(曾经注册的略过),注册地址:https://mp.weixin.qq.com/ 因为我本人的邮箱都用过了,就不一一演示了,注册的时候抉择集体就行了。 8.AppID的获取(晓得怎么应用和获取AppID的略过),红色框中就是你本人的AppID 9.填写小程序信息,填写本人的项目名称,目录就是小程序文件寄存地址,AppID要应用本人的,须要本人去官网注册,才有本人的AppID。后端服务默认是微信云开发,然而咱们也能够先不抉择不应用云开发。须要的时候咱们本人再开明,最初点击确定。 10.微信开发者工具登陆胜利的页面 11-1.间接应用云开发,在登陆胜利界面点击云开发按钮,这里的环境id能够先复制,上面要用 11-2.不应用云开发,在登陆胜利界面,点击云开发按钮,须要本人填写环境名称,名称随便,语义化最好,然而不能用中文,付费形式抉择按量付费就行了,毕竟有收费的能够先用着,一般来说,本人够用,最初点击确定,去开明云服务,失去的页面和间接应用(11-1)一样的页面。 12.增加云开发环境id,记得增加本人的环境id 云数据库官网文档:https://developers.weixin.qq.... 创立数据库中的汇合创立汇合并命名。(PS:集体喜爱仙剑,你们依据本人业务须要起名,这里只是举例。这里咱们能够点击页面上的增加记录,在这里间接增加一条记录,抉择默认就行,间接点击确定这样就有了第一条数据,然而只有默认的id,并没有数据,咱们点击增加字段,自行添加字段这里说一下,字段类型,就如下图,这些就是云数据库蕴含的数据类型数据权限阐明,默认抉择仅创建者可读写,依据本人需要扭转云数据库的增删改查在开始应用数据库 API 进行增删改查操作之前,须要先获取数据库的援用。以下调用获取默认环境的数据库的援用: const db = wx.cloud.database()// 如需获取其余环境的数据库援用,能够在调用时传入一个对象参数,在其中通过 `env` 字段指定要应用的环境。此时办法会返回一个对测试环境数据库的援用。// 示例:假如有一个环境名为 `test`,用做测试环境,那么能够如下获取测试环境数据库:const testDB = wx.cloud.database({ env: 'test' // 应为环境id})增db.collection('xianjian').add({ data: { name: this.data.user.name, age: this.data.user.age }}).then(res => { console.log('胜利', res)}).catch(err => { console.log('失败', err)})删db.collection('xianjian').doc('16db756f629f166a0633bd2b56c703f7').remove() .then(res => { console.log('胜利', res) }) .catch(err => { console.log('失败', err) })PS:删除不是本人创立的数据的时候,会失败 ...

June 9, 2022 · 3 min · jiezi

关于小程序:微信小程序-几种路由跳转方式

路由跳转wx.switchTab性能:跳转到指定的tabBar页面,并敞开其余所有非tabBar页面 只能跳转到在app.json的tabBar中注册的页面不能携带参数跳转时触发路由后页面的onShow生命周期跳转时触发路由前页面的onHide生命周期wx.reLaunch性能:敞开所有页面,关上到利用内的某个页面 门路后能够带参数能够关上任意页面跳转时触发路由后页面的onLoad和 onShow生命周期跳转时触发路由前页面(应该是全副页面?)的onUnload生命周期wx.redirectTo性能:敞开以后页面,跳转到利用内的某个页面 门路后能够带参数不容许跳转到 tabbar 页面跳转时触发路由后页面的onLoad和 onShow生命周期跳转时触发路由前页面的onUnload生命周期wx.navigateTo性能:保留以后页面,跳转到利用内的某个页面。 门路后能够带参数不容许跳转到 tabbar 页面调用navigateTo跳转的页面会被退出到页面栈中跳转时触发路由后页面的onLoad(首次)和 onShow生命周期跳转时触发路由前页面的onHide生命周期wx.navigateBack性能:敞开以后页面,返回上一页面或多级页面。 如果返回页数大于现有页面数,则返回到首页跳转时触发路由后页面的onLoad(首次)和 onShow生命周期跳转时触发路由前页面的onUnload生命周期

June 9, 2022 · 1 min · jiezi

关于小程序:借助小程序容器轻松打造自有App小程序生态

2022 年 1 月 17 日,阿拉丁研究院公布《2021 年度小程序互联网倒退白皮书》显示,2021 年全网小程序数量已超 700 万,其中微信小程序开发者冲破 300 万,DAU 超过 4.5 亿;日均应用次数同比增长 32%,沉闷小程序则增长 41%,小程序生态已塑造出新的增长空间。小程序作为挪动互联网的重要新基建之一也在焕发新的生机,在网民生存中的高度浸透使其成为日常生活“标配”,在各年龄段用户中成为网民生存“标配”,人生各阶段需要将来都可能在小程序上获取相应服务。并成为互联网商业的重要阵地。人们的生存、出行、购物各个方面越来越离不开小程序。 一、为什么要做小程序生态为什么企业都在关注小程序生态的建设,次要在于以下几点:1、小程序 DAU 超过 4.5 亿,成生存“标配”小程序的新增用户和沉闷用户的比例较2020年都有同步晋升,用户对小程序的接受度和动向应用度都更进一步;另一方面小程序的利用和应用覆盖面贯通咱们的生存起居,特地是服务类小程序拜访次数比重扩充,其中18 至 29 岁用户累计占比 35.4%,同比晋升 4 个百分点。小程序正在重塑以年老群体为外围的新生产时代。2、小程序成为互联网商业的重要阵地微信、支付宝、百度和字节等互联网平台鼎力搀扶小程序生态倒退,容许短信、H5、网页、APP 等跳转进入,造成以社交分享为基石、向“泛生态”扩散的推广链路,特地是随着小程序基础设施不断完善、小程序开发技术曾经成熟以及用户习惯逐渐加深,小程序成为传统批发企业转型降级、关上线上市场的先机。平台搀扶与协同进一步促成第三方 SaaS 服务延展,为企业品牌提供从获客、连贯到转化、维系的全链路解决方案与服务。3、小程序人造具备公域流量连贯能力在各大互联网平台都在做大做强"超级App"的同时,市场中客户的大部分碎片化工夫均被其“霸占”,对应的流量都把握在这些平台的手中,其余企业很难与之抗衡,而小程序正好具备人造的跨平台连贯能力,可能多端上架至这些“超级App”,在通过提供企业本身的服务,开掘更广大的公域流量,甚至逐渐将这部分公域流量导入企业的私域流量池,大幅升高企业本身的获客老本。4、小程序生态成为私域基建必选项在公域流量红利逐步殆尽,品牌开始从 “流量”思维向“留量”思维转型的时代,各个企业纷纷开启私域流量池建设。小程序、小程序直播等一系列小程序生态产品成为了“私域矩阵”中特地重要的一环。小程序与公众号、视频号、企业微信的互联互通将持续推动企业数字化转型和私域建设,扩大“闭环思维“至“组件化思维”,营销场景和营销办法由此爆发更多翻新与价值。 二、目前有哪些小程序生态目前大型互联网巨头简直全都投入到小程序生态的建设中,包含腾讯、阿里、百度、字节、快利用、美团、快手、网易、华为、360和京东这十系平台。如果将以后支流的小程序生态进行比照,也能发现一些差异化的特色,各大平台根本都是依据本身平台基因来定位小程序生态的使命。微信散发小程序的特点是基于社交关系的分享,重点放在社交服务的衍生与降级。支付宝侧重于特色的资金和信用服务。百度定位于搜寻与中转的转化。字节跳动则是要“连贯内容与服务”。美团显然是围绕“衣食住行”的生存场景。京东连贯“进驻”的商家与客户。 三、如何打造本人的小程序生态在整个智能手机销量下滑的现状和互联网流量红利殆尽的双重背景下,要减少一个App装置量和注册量的代价越来越贵,企业埋头本人开发各种服务App的时代已去。但针对银行、证券、政务、电商、车企等大型企业机构继续拓展本身的服务圈,以丰盛的服务去沉闷自有平台海量的存量用户又是必有动作,该怎么搞呢?过往运行小程序始终被认为是超级平台的“特权”,它是“超级App”为用户提供连贯所有服务的最佳延长载体,可能丰盛这些平台各自的用户生命周期。让本人的App具备运行小程序能力是打造自有小程序生态的首要前提,这个门槛对于很多企业机构来讲已是十分大的挑战,除了要思考开发的微小投入外还要保障运行的可靠性和兼容度。其实市场中也有十分成熟的解决方案能够间接便捷的应用,在《2021 年度小程序互联网倒退白皮书》就看到凡泰极客推出了 FinClip 去填补市场的空白,介绍中讲到正是基于企业数字化转型过程中构建数字生态连贯能力的需要,向市场提供了兼容互联网支流小程序技术的轻利用平台,帮忙企业打造本人的利用商店,开发、上架、治理与风控以小程序状态存在的碎片化业务场景,以乐高组件形式组装业务利用,赋能业务部门进行跨组织、跨机构、跨行业、跨终 端的数字生态经营。相当于他们把“App领有小程序运行能力”做成小程序容器技术,任何企业机构的App均能够通过简略嵌入 iOS、Android、MacOS、Windows、UOS、麒麟等零碎对应的FinClip 小程序运行时 SDK 而霎时取得运行小程序的能力,后续各个企业机构能够通过治理后盾以对立高低架的形式,治理本人以及合作伙伴们的业务场景。

June 8, 2022 · 1 min · jiezi

关于小程序:视频滑动切换组件

实用于微信小程序(H5的话改一改也能用)的视频滑动切换组件以前用过小程序提供的video-swiper组件, 其中的问题和bug也不做过多形容了。为了我的项目进度,过后也没过多思考,没用应用video-swiper,而是用swiper和swiper-item简略实现了性能,起初本人测进去了个问题,然而客户没有反馈,测试也没有提bug,所以这个问题就耽误,当初抽空从新写个demo,等当前遇到相似的我的项目,再拿进去批改。新写的这个demo就是参考了以前用过的轮播图组件的思维做的一个视频滑动切换组件,如果有其余问题,请大家不要悭吝,指导进去,谢谢! 还是间接上代码!!!//index.tsconst randomColor: string[] = ['a', 'b', 'c', 'd', 'e', 'f', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']interface BaseEvent extends WechatMiniprogram.BaseEvent { touches: Array<WechatMiniprogram.TouchDetail>}Page({ /** * 页面的初始数据 */ data: { distance: 0, list: <Array<string>>[], windowInfo: <WechatMiniprogram.WindowInfo>{}, }, loadMoreColor() { if (this.loading) return this.loading = true //视频汇合 let list = [ '' ] // for (let i = 0; i < 10; i++) { // let color = '#' // for (let n = 0; n < 6; n++) { // color += randomColor[Math.floor(Math.random() * randomColor.length)] // } // console.log(color); // list.push(color) // } setTimeout(() => { this.setData({ list: [...this.data.list, ...list] }, () => { this.currentIndex === 0 && this.createVideoContext() this.loading = false }) }, 2000); }, createVideoContext() { this.videoExample && this.videoExample.stop && this.videoExample.stop() this.videoExample = wx.createVideoContext(`video_${this.currentIndex}`) this.videoExample.play() }, videoExample: <Record<string, any> | null>null, //video实例 loading: false, //数据加载 currentIndex: 0, //以后swiper startLocation: <number>0, //手指摁下地位 endLocation: 0, //手指抬起地位 isTouchmove: false, //是否有滑动操作 inertiaRollState: true, //惯性滚动成果是否完结 true完结 false未完结 //触摸开始 touchstart(e: BaseEvent) { if (!this.inertiaRollState) return //记录滑动初始地位 this.startLocation = e.touches[0].clientY }, //触摸挪动 touchmove(e: BaseEvent) { //如果swiper以后地位是0且是下拉的动作 if ((this.currentIndex <= 0 && e.touches[0].clientY - this.startLocation > 0) || !this.inertiaRollState) return; console.log('touchmove'); this.isTouchmove = true this.endLocation = e.touches[0].clientY //e.touches[0].clientY - this.startLocation手指滑动的间隔 //this.currentIndex * this.data.windowInfo.screenHeight曾经卷下来的间隔 //distance一共卷下来的间隔 let distance = e.touches[0].clientY - this.startLocation - (this.currentIndex * this.data.windowInfo.screenHeight) this.setData({ distance: this.currentIndex < this.data.list.length - 1 ? distance : Math.abs(distance) > this.currentIndex * this.data.windowInfo.screenHeight + 50 ? -(this.currentIndex * this.data.windowInfo.screenHeight + 50) : distance }) }, //触摸完结 touchend() { //moveDistance手指滑动间隔 大于0(moveState为true)时是下拉, 小于0(moveState为false)时是上拉 let moveDistance = this.endLocation - this.startLocation let moveState = moveDistance > 0 this.endLocation = 0 this.startLocation = 0 //如果swiper以后地位是0且是下拉的动作 if ((this.currentIndex <= 0 && moveState) || !this.isTouchmove) return; this.isTouchmove = false this.inertiaRollState = false //手指滑动的间隔不小于1/4, swiper执行切换 if (Math.abs(moveDistance) >= this.data.windowInfo.screenHeight / 4) { let currentIndex = moveState ? this.currentIndex - 1 : this.currentIndex + 1 if (currentIndex < this.data.list.length) { //如果加载到最初一个视频, 去拉取新的列表 currentIndex === this.data.list.length - 1 && this.loadMoreColor() this.currentIndex = currentIndex this.inertiaRoll(moveState, -(this.currentIndex * this.data.windowInfo.screenHeight), true) return } } this.inertiaRoll(moveState, -(this.currentIndex * this.data.windowInfo.screenHeight)) }, touchcancel() { }, /** * moveState滑动状态 为true时是下拉, 为false时是上拉 * distance滑动间隔的起点地位 */ inertiaRoll(moveState: boolean, distance: number, swiper = false) { let baseNum = Math.abs(this.data.distance - distance) / 10 let intervalId = setInterval(() => { //下拉 值越来越大(从负无穷越来越靠近于0) 上拉 值越来越小(负无穷) let _d = moveState ? this.data.distance + baseNum : this.data.distance - baseNum if ((moveState && _d >= distance) || (!moveState && _d <= distance)) { //滑动切换实现 this.setData({ distance }, () => { swiper && this.createVideoContext() this.inertiaRollState = true }) clearInterval(intervalId) } else { this.setData({ distance: _d }) } }, 10) }, /** * 生命周期函数--监听页面加载 */ onLoad() { this.setData({ windowInfo: wx.getWindowInfo() }) this.loadMoreColor(); }})<!--index.wxml--><view class="container" style="height: {{windowInfo.screenHeight}}px;"> <view class="list-view" catchtouchstart="touchstart" catchtouchmove="touchmove" catchtouchend="touchend" catchtouchcancel="touchcancel" style="margin-top: {{distance}}px;"> <view wx:for="{{list}}" wx:key="index" style="height: {{windowInfo.screenHeight}}px; background-color: {{item}};" class="list-item"> <video id="{{'video_' + index}}" src="{{item}}" loop style="width: 100%; height: 100%;"></video> </view> <view style="height: 50px; line-height: 50px; text-align: center;">加载中...</view> </view></view>/**index.wxss**/.container { width: 100%; overflow: hidden; .list-view { .list-item { width: 100%; height: 100%; display: flex; align-items: center; } }}

May 30, 2022 · 3 min · jiezi

关于小程序:小程序商城开发究竟有何优势

随着互联网时代的倒退,各行各业的技术企业都在一直崛起,小程序商城正在逐步成为商家拓展社交电商的无利工具。因为微信用户流量高,经营成本低,带动了社交电商的倒退。小程序商城可能帮忙商家更加容易获取用户数量,也更进一步减速倒退。专一于小程序商城定制开发一站式互联网服务商至佳科技就带大家来看一下。 小程序商城开发的劣势介绍: 1、小程序商城更有利于中小企业倒退 这是许多中小企业抉择小程序商城开发的次要起因,因为对于这些中小企业来说,他们也想通过电子商务平台,将本人的产品推广进来,然而可能会受到各种条件的限度,而小程序就可能解决这一问题,可能帮忙他们实现线上销售,进步销量,并且对于商城平台来说,通过小程序还可能冲破流量瓶颈。 2、开发成本更低、周期短,不受手机利用限度 绝对于小程序商城开发的费用,小程序商城开发成本更低,能够帮忙运营者节俭开发成本,他们能够更多财力,人力,精力放在如何经营好产品,做好内容自身; 小程序商城要真正开发好上线应用周期长,还须要收不同手机利用的限度,例如安卓版本的APP在苹果利用的手机上就不能应用,二小程序商城就没有受到利用的限度。 3、弱小的平台入口,流量劣势显著 据统计微信使用者已超10亿,小程序商城背靠10亿用户的发平台,可分享转发流传更快、更易获取流量,而小程序商城须要独立宣传推广,更须要长时间资金人力投入来获取的用户积攒,对于初期倒退商城的商家是十分艰难的。 4、小程序商城是新物种,竞争小 APP的世界曾经趋于饱和,咱们简直能够在App Store 找到各种各样满足不同需要的APP,每个APP都在相互竞争用户的工夫,线上的竞争如此强烈,一个新网站或新APP,可能一年只能取得一个用户10秒的应用工夫。小程序商城的诞生给了企业新的商业契机。 5、小程序商城应用体验更不便 相比于小程序商城来说,在应用小程序商城的时候,只须要关上就能够了,没有必要下载安装,并且它所具备的性能和小程序商城的性能基本上是一样的,因为省去了下载安装的步骤,所以越来越多的人都更偏向于应用小程序商城,不仅可能防止下载安装的麻烦,还不必思考占内存的问题。 不要漠视小程序商城,是企业做好小程序的根底。理解商城小程序的劣势,并且抓住这部分劣势,对企业倒退是有很大益处的,也可能推动小程序的倒退。至佳科技能够帮忙企业进行小程序商城定制开发征询,获取专属计划,详情请点击在线客服征询或者拨打至佳科技全国对立服务热线0755-22675310。

May 30, 2022 · 1 min · jiezi

关于小程序:微信小程序四小程序生命周期

小程序的生命周期说白了就是指程序从创立、到开始、暂停、唤起、进行、卸载的过程。咱们大略从三个角度看一下小程序的生命周期。(1):利用生命周期(2):页面生命周期(3):利用生命周期影响页面生命周期一:利用生命周期放一张从网上找的图: 1:用户首次关上小程序,触发 onLaunch(全局只触发一次)。:2:小程序初始化实现后,触发onShow办法,监听小程序显示。3:小程序从前台进入后盾,触发 onHide办法。:4:小程序从后盾进入前台显示,触发 onShow办法。5:小程序后盾运行肯定工夫,或系统资源占用过高,会被销毁。前台、后盾定义: 当用户点击左上角敞开,或者按了设施 Home 键来到微信,小程序并没有间接销毁,而是进入了后盾;当再次进入微信或再次关上小程序,又会从后盾进入前台。最初的成果是这个样子的,微信开发者工具没有方法测试onHide办法 二:页面生命周期放一张从网上找来的图 1:小程序注册实现后,加载页面,触发onLoad办法。2:页面载入后触发onShow办法,显示页面。3:首次显示页面,会触发onReady办法,渲染页面元素和款式,一个页面只会调用一次。4:当小程序后盾运行或跳转到其余页面(应用wx.navigateTo)时,触发onHide办法。5:当小程序有后盾进入到前台运行或从新进入页面时,触发onShow办法。6:当应用重定向办法wx.redirectTo(OBJECT)或敞开当前页返回上一页wx.navigateBack(),触发onUnload具体成果如下图所示:留神看触发onHide和触发onunLoad的机会与形式 三:利用生命周期影响页面生命周期放一张从网上找来的图 1:小程序初始化实现后,页面首次加载触发onLoad,只会触发一次。2:当小程序进入到后盾,先执行页面onHide办法再执行利用onHide办法。3:当小程序从后盾进入到前台,先执行利用onShow办法再执行页面onShow办法。一个小程序的生命周期,从生成到最初销毁如下图所示:

May 28, 2022 · 1 min · jiezi

关于小程序:庆贺uniapp海外月活设备过亿

在刚过去的4月,uni-app 在中国以外的国家,无论以 uv 还是以 ip 口径统计,月沉闷设施均冲破 1亿 大关。 平台方面,这些沉闷设施次要来自于 App 和 web,也有小局部小程序。 国家散布方面,遍布寰球两百多个国家,各大洲、各种语言均有散布。 用户量排名靠前的前10个国家是:印度、美国、菲律宾、巴西、印度尼西亚、尼日利亚、土耳其、越南、马来西亚、英国。 这些利用有海内开发者开发的当地利用,但大部分利用是由中国开发者开发的出海利用。 作为世界工厂的中国,制作能力向海内溢出;而另一方面,中国的数字化开发能力也在向海内减速溢出。坦白讲,中国的开发工程师数量、数字利用制作能力,对寰球大多数国家而言不是一个级别的。 在过来一年里,DCloud在国际化方面做了很多事,不论是HBuilder、uni-app、还是uniCloud,均提供了国际化计划,帮忙中国开发者更便当的出海。 一、HBuilder推出英文版 除了中英文,HBuilder还凋谢制作各国语言包,反对双向文字流,即从右向左的文字。 庆祝:uni-app海内月活设施过亿uni-app全面反对国际化从前端到原生均反对国际化从利用到框架均反对国际化从vue到nvue均反对国际化双向文字流。从右向左的文字比方阿拉伯文也能够失常显示海内支流sdk反对:开发者出海不止须要多语言,海内的支流SDK适配也是必需品。uni-app 的map、pay、login、push均反对海内支流SDK。H5、App平台 Google地图App平台 领取反对 Paypal、Stripe、Google Pay、Apple IAPApp平台 登录反对 Google、Apple、FacebookApp平台 推送反对 Google FCM插件市场还有泛滥其余海内SDK的反对插件 DCloud提供了 hello i18n 示例来演示各种国际化的应用办法。 能够在 HBuilder 新建我的项目界面 获取 hello i18n 示例,也能够在插件市场下载: https://ext.dcloud.net.cn/plu... uniCloud终端用户可视数据国际化 uniCloud的 DB Schema 中波及字段的显示名称、谬误格局提醒语,这些也均反对国际化。 uniCloud阿里云版也反对海内减速。 配套开源生态的国际化uni ui、uni-starter、uni-admin等重要开源我的项目均反对国际化。 中国的数字利用数量,曾经是世界顶级。沉闷的app、小程序、web网站,数量上千万。宏大的需要孕育出宏大的生产能力。 中国依然有很多机会,但曾经内卷重大。与此同时,其余国家其实也迫切地须要数字化,他们须要中国的数字利用制作能力。 DCloud曾经为开发出海利用制作了大量轮子。往年的插件大赛,DCloud还将设立专门估算处分反对国际化的优良插件。 当初天时地利都具备,就等你来开发利用了! 2022,让咱们卷向海内吧。 点击浏览原文或下方链接,理解 uni-app 的 i18n标准技术文档:https://uniapp.dcloud.io/work...

May 26, 2022 · 1 min · jiezi

关于小程序:一个你想不到的小程序数组更新方式

首先这里不得不吐槽下小程序的数组更新,间接通过 setData 替换整个数组只在开发者工具上有成果,放到真机上就齐全失灵,这是一件很蛋疼的事件,不晓得小程序官网团队的更新机制是什么,也没有去细看,猜想可能与援用类型有关系。 看了网上大都是指定批改数组对象里的某个元素值,如这样: Page({ data: { list: [{name: 'tom'}] }, onLoad() { this.setData({[`list[0].name`]: 'jack'}) }})PS:感觉这样解决十分麻烦,须要一个个遍历去解决,而且新数组与旧数组的长度可能还不一至,还要比照,想想就放弃了,也没真正测试进去成果来。 因为要做的是一个简略的页面,只有地图和列表,所以就另辟蹊径通过 redirectTo 去解决了,其就是想通过刷新页面去实现视图更新的,因为小程序没有间接的刷新页面API,所以就想着通过 reLaunch 或 redirectTo 间接实现,不过 reLaunch 没成果,所以就确定了 redirectTo 加上参数实现的视图更新,说到这,其实这个和数组更新没有关系了,不过这的确是因为数组更新没成果引起的血案,只能通过其余形式来救场,相应的示例代码: Page({ data: { activeTab: '', list: [] }, onLoad(options) { if(options.tab) { this.setData({activeTab: options.tab}) } this.getList() }, changeTab(e) { wx.redirectTo({url: `/pages/index/index?tab=${e.currentTarget.dataset.tab}`}) }, getList() { wx.request({ url: 'xxx', data: { tab: this.data.activeTab }, success: res => { this.setData({list: res.data}) } }) }})最初尽管问题侧面解决了,但这不是正规的解决形式,而且有场景限度,所以还是心愿官网看看是否优化数组的更新机制。 更多前端常识,请关注小程序,不定期有惊喜! ...

May 18, 2022 · 1 min · jiezi

关于小程序:小程序音乐项目开发实战coderwhy源码齐全

小程序音乐我的项目开发实战-coderwhy源码齐全超清原画 残缺无密 资料齐全 获取ZY:百度网盘一个Java注解@Recover搞定俊俏的循环重试代码 使用背景在实际我的项目中其中一部分逻辑可能会因为调用了内部服务或者等待锁等情况下出现不可预料的异样,在这个时候咱们可能需要对调用这部分逻辑进行重试,代码外面次要就是使用for循环写一大坨重试的逻辑,各种硬编码,各种辣眼睛的补丁。 特地是针对重试的逻辑,到处都有。所以我决定用一个重试组件spring-retry优化一波。它的出现,解决掉这部分俊俏的代码! 2开始上代码首先引入依赖: org.springframework.retryspring-retry1.3.2复制代码因为该组件是依赖于 AOP 给你的,所以还需要引入这个依赖(如果你其余 jar 包中引用过了,当然也就不需要再次引用了): org.springframework.bootspring-boot-starter-aop2.6.1复制代码开启重试:@SpringBootApplication@EnableRetrypublic class ApplicationStarter { public static void main(String[] args) { SpringApplication.run(ApplicationStarter.class); }}复制代码Controller层@RestControllerpublic class TestController {@Autowiredprivate IRecursiveCallService recursiveCallService; @GetMapping("test2")public Object test2() { return recursiveCallService.testService();}}复制代码Service层public interface IRecursiveCallService { /** * 测试service * * @return */List testService();}复制代码Service层具体实现@Servicepublic class RecursiveCallServiceImpl implements IRecursiveCallService { @Override@Retryable(recover = "testService3")public List testService() { System.out.println("到此一游!"); System.out.println(1 / 0); return null;}@Recoverpublic List testService1() { System.out.println("谬误的返回"); return Collections.singletonList("S");}@Recoverpublic List testService2(String i) { System.out.println("正确的返回"); return Collections.singletonList(1);}@Recoverpublic List testService3() { System.out.println("正确的返回2"); return Collections.singletonList(2);}} ...

May 10, 2022 · 1 min · jiezi

关于小程序:小程序音乐项目开发实战coderwhy新课

小程序音乐我的项目开发实战-coderwhy新课download:网盘链接手把手教使用python实现人脸识别 什么是人脸识别人脸识别,是基于人的脸部特色信息进行身份识别的一种生物识别技术。用摄像机或摄像头采集含有人脸的图像或视频流,并主动在图像中检测和跟踪人脸,进而对检测到的人脸进行脸部识别的一系列相干技术,通常也叫做人像识别、面部识别。 目前的人脸识别技术已经非常成熟了,还发展成3D人脸识别。而且现在各大厂商也都提供了人脸识别的API接口供咱们调用,可能说几行代码就可能实现人脸识别。然而人脸识别的根本还是基于图像处理。在Python中最弱小的图像处理库就是OpenCV。 OpenCV简介OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可能运行在Linux、Windows、Android和Mac OS操作系统上。OpenCV可用于开发实时的图像处理、计算机视觉以及模式识别程序。它轻量级而且高效——由一系列 C 函数和大量 C++ 类形成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。 OpenCV基本使用安装pip install opencv-python # 基础库pip install opencv-contrib-python # 扩大库pip install opencv-python-headless复制代码读取图片读取和浮现图片是最基本的操作了,OpenCV当中使用imread和imshow实现该操作 import cv2 as cv 读取图片,路径不能含有中文名,否则图片读取不进去image = cv.imread('1111.jpg') 浮现图片cv.imshow('image', image) 等待键盘输入,单位是毫秒,0示意有限等待cv.waitKey(0) 因为最终调用的是C++对象,所以使用完要开释内存cv.destroyAllWindows()复制代码 将图片转为灰度图OpenCV中数百中对于不同色彩控件之间转换的方法。目前最罕用的有三种:灰度、BGR、HSV。 灰度色彩空间是通过去除黑白信息来讲图片转换成灰阶,灰度图会大量缩小图像处理中的色彩处理,对人脸识别很无效。BGR每个像素都由一个三元数组来示意,别离代码蓝、绿、红三种色彩。python中还有一个库PIL,读取的图片通道是RGB,其实是一样的,只是色彩次序不一样HSV,H是色调,S是饱和度,V是光明的程度将图片转换为灰度图import cv2 as cv 读取图片,路径不能含有中文名,否则图片读取不进去image = cv.imread('1111.jpg') cv2读取图片的通道是BGR,PIL读取图片的通道是RGBcode抉择COLOR_BGR2GRAY,就是BGR to GRAYgray_image = cv.cvtColor(image, code=cv.COLOR_BGR2GRAY) 浮现图片cv.imshow('image', gray_image) 等待键盘输入,单位是毫秒,0示意有限等待cv.waitKey(0) 因为最终调用的是C++对象,所以使用完要开释内存cv.destroyAllWindows()复制代码 绘制矩形image = cv.imread('1111.jpg')x, y, w, h = 50, 50, 80, 80 绘制矩形cv.rectangle(image, (x, y, x+w, y+h), color=(0, 255, 0), thickness=2) ...

May 5, 2022 · 2 min · jiezi

关于小程序:玩转小程序压测

简介:小程序是挪动互联网时代十分重要的流量入口。为了防止因零碎性能瓶颈导致用户在应用过程中呈现白屏、异样报错等问题影响用户体验,小程序在新性能上线前须要做好压力测试,评估出零碎的承载能力,并以压测后果配置限流。让零碎面对流量突增,也能稳如泰山。 作者:拂衣 小程序也是须要压测的小程序是挪动互联网时代十分重要的流量入口。为了防止因零碎性能瓶颈导致用户在应用过程中呈现白屏、异样报错等问题影响用户体验,小程序在新性能上线前须要做好压力测试,评估出零碎的承载能力,并以压测后果配置限流。让零碎面对流量突增,也能稳如泰山。 常见的小程序中须要做压测的 3 种场景新开发的零碎或性能上线前须要理解其性能水位状况。对系统进行技术调优、零碎扩容前后通过压测进行性能比对。加入小程序平台流动前对系统进行性能评估。小程序的压测计划如何设计依据压测场景不同,压测计划可简略可分为:单接口压测、混合压测、性能调优压测、长稳压测等。请依据须要抉择不同的计划。 单接口压测:针对外围业务场景波及的接口进行独自压测,剖析单接口链路的瓶颈。混合压测:针对业务场景进行混合压测,评估零碎综合并发解决能力。性能调优压测:测试利用零碎参数、JVM 参数、线程池参数等对系统性能的影响,并得出最佳实际的参数设置。长稳压测:长期维持一个绝对较高的并发量进行压力测试,察看零碎反馈状况。通过 24H * N 天的长稳压测,保证系统的稳定性,避免内存溢出、迟缓泄露,线程池、资源获取时的偶尔竞争造成死锁、排队等景象;长稳压测的工夫长度可依据具体情况适当缩小,比方依照 JVM GC、Full GC 产生次数决定稳定性压测工夫等。应用 PTS 对小程序进行压测的最佳实际不同于自建网站压测,针对小程序压测时,通常须要取得小程序所在的平台(如支付宝、微信)的 Token 信息,并在有效期内应用能力失常压测小程序业务接口。 举荐您通过以下两种形式获取平台受权的 Token: (举荐)编写接口主动获取 Token,并在有效期内刷新该 Token。压测中,您通过 PTS 压测该接口,能够主动取得 Token。压测前提前记录平台 Token,并以参数模式传入小程序业务接口中。然而请留神压测时长不能超过 Token 的有效期,防止因 Token 生效导致无奈进行业务压测。形式一:编写接口获取 Token假如须要压测微信平台上小程序的流动页面。您能够编写接口去获取微信的 Token 信息,将该接口编排进压测场景中,并提取出参,传递给前面理论的业务接口。具体操作步骤如下: 在本地编写接口,以便可能在压测过程中继续地获取微信的 Token 信息。登录 PTS 控制台[1],在左侧导航栏抉择创立场景 > 创立 PTS 场景。填写场景名,例如“myAPP”。在场景配置页签下,单击压测 API 名称一栏右侧的箭头开展更多具体设置,填写第一个压测 API,即自定义的获取微信 Token 的接口。抉择出参定义页签,配置示例如下: 出参名:access_token起源:Body:JSON解析表达式:access_token单击+增加压测 API,填写第二个 API,即小程序流动页面接口,申请形式抉择为 POST。小程序流动页面接口即小程序的 URL。 单击创立 PTS 场景页面下方的参数列表,在弹出的对话框中单击出参名的复制图标,复制该出参参数。 假如须要在 API 的 Body 中传入已复制的出参 access_token,单击 API 的 Body 定义页签。在 Key 中填写自定义的名称(例如 input_token),在 Value 中粘贴已复制的出参参数。 ...

April 29, 2022 · 1 min · jiezi

关于小程序:小程序成互联网商业重要阵地新生态建设近在眼前

2022 年 1 月 17 日,阿拉丁研究院公布《2021 年度小程序互联网倒退白皮书》显示,2021 年全网小程序数量已超 700 万,其中微信小程序开发者冲破 300 万,DAU 超过 4.5 亿;日均应用次数同比增长 32%,沉闷小程序则增长 41%,小程序生态已塑造出新的增长空间。 小程序作为挪动互联网的重要新基建之一也在焕发新的生机,在网民生存中的高度浸透使其成为日常生活“标配”,在各年龄段用户中成为网民生存“标配”,人生各阶段需要将来都可能在小程序上获取相应服务。并成为互联网商业的重要阵地。人们的生存、出行、购物各个方面越来越离不开小程序。 一、为什么要做小程序生态 为什么企业都在关注小程序生态的建设,次要在于以下几点: 1、小程序 DAU 超过 4.5 亿,成生存“标配” 小程序的新增用户和沉闷用户的比例较2020年都有同步晋升,用户对小程序的接受度和动向应用度都更进一步;另一方面小程序的利用和应用覆盖面贯通咱们的生存起居,特地是服务类小程序拜访次数比重扩充,其中18 至 29 岁用户累计占比 35.4%,同比晋升 4 个百分点。小程序正在重塑以年老群体为外围的新生产时代。 2、小程序成为互联网商业的重要阵地 微信、支付宝、百度和字节等互联网平台鼎力搀扶小程序生态倒退,容许短信、H5、网页、APP 等跳转进入,造成以社交分享为基石、向“泛生态”扩散的推广链路,特地是随着小程序基础设施不断完善、小程序开发技术曾经成熟以及用户习惯逐渐加深,小程序成为传统批发企业转型降级、关上线上市场的先机。平台搀扶与协同进一步促成第三方 SaaS 服务延展,为企业品牌提供从获客、连贯到转化、维系的全链路解决方案与服务。 3、小程序人造具备公域流量连贯能力 在各大互联网平台都在做大做强"超级App"的同时,市场中客户的大部分碎片化工夫均被其“霸占”,对应的流量都把握在这些平台的手中,其余企业很难与之抗衡,而小程序正好具备人造的跨平台连贯能力,可能多端上架至这些“超级App”,在通过提供企业本身的服务,开掘更广大的公域流量,甚至逐渐将这部分公域流量导入企业的私域流量池,大幅升高企业本身的获客老本。 4、小程序生态成为私域基建必选项 在公域流量红利逐步殆尽,品牌开始从 “流量”思维向“留量”思维转型的时代,各个企业纷纷开启私域流量池建设。小程序、小程序直播等一系列小程序生态产品成为了“私域矩阵”中特地重要的一环。小程序与公众号、视频号、企业微信的互联互通将持续推动企业数字化转型和私域建设,扩大“闭环思维“至“组件化思维”,营销场景和营销办法由此爆发更多翻新与价值。 二、目前有哪些小程序生态 目前大型互联网巨头简直全都投入到小程序生态的建设中,包含腾讯、阿里、百度、字节、快利用、美团、快手、网易、华为、360和京东这十系平台。 如果将以后支流的小程序生态进行比照,也能发现一些差异化的特色,各大平台根本都是依据本身平台基因来定位小程序生态的使命。 微信散发小程序的特点是基于社交关系的分享,重点放在社交服务的衍生与降级。支付宝侧重于特色的资金和信用服务。百度定位于搜寻与中转的转化。字节跳动则是要“连贯内容与服务”。美团显然是围绕“衣食住行”的生存场景。京东连贯“进驻”的商家与客户。三、如何打造本人的小程序生态 在整个智能手机销量下滑的现状和互联网流量红利殆尽的双重背景下,要减少一个App装置量和注册量的代价越来越贵,企业埋头本人开发各种服务App的时代已去。但针对银行、证券、政务、电商、车企等大型企业机构继续拓展本身的服务圈,以丰盛的服务去沉闷自有平台海量的存量用户又是必有动作,该怎么搞呢? 过往运行小程序始终被认为是超级平台的“特权”,它是“超级App”为用户提供连贯所有服务的最佳延长载体,可能丰盛这些平台各自的用户生命周期。让本人的App具备运行小程序能力是打造自有小程序生态的首要前提,这个门槛对于很多企业机构来讲已是十分大的挑战,除了要思考开发的微小投入外还要保障运行的可靠性和兼容度。 其实市场中也有十分成熟的解决方案能够间接便捷的应用,在《2021 年度小程序互联网倒退白皮书》就看到凡泰极客推出了 FinClip去填补市场的空白,介绍中讲到正是基于企业数字化转型过程中构建数字生态连贯能力的需要,向市场提供了兼容互联网支流小程序技术的轻利用平台,帮忙企业打造本人的利用商店,开发、上架、治理与风控以小程序状态存在的碎片化业务场景,以乐高组件形式组装业务利用,赋能业务部门进行跨组织、跨机构、跨行业、跨终 端的数字生态经营。 相当于他们把“App领有小程序运行能力”做成小程序容器技术,任何企业机构的App均能够通过简略嵌入 iOS、Android、MacOS、Windows、UOS、麒麟等零碎对应的FinClip 小程序运行时 SDK 而霎时取得运行小程序的能力,后续各个企业机构能够通过治理后盾以对立高低架的形式,治理本人以及合作伙伴们的业务场景。

April 28, 2022 · 1 min · jiezi

关于小程序:资源引流难度很大小程序说不

通过数年的倒退小程序未然成为一个普适性的工具。轻体量、低成本的特点,使得小程序有着人造的寄生属性。比方最早一批早退吃到螃蟹的人,拼多多借着小程序红利,在不到一年工夫里,把沉闷用户做到三亿!其社交裂变能力之快,使得寄生宿主“微信”也不得不忌惮,在去年敞开了“小程序跳转app”的服务。 “拼多多”们的高速倒退却早已证实小程序在社交引流上的优越能力!在当下流量市场饱和的状况下,小程序或者能成为跨平台引流的绝佳计划,想要吸引更多人的关注,就要把握正确的引流办法。 惯例调起小程序的形式往往是使用腾讯系资源,但小程序引流的解决方案不止使用腾讯系资源,以下为大家介绍3类非腾讯资源的引流形式: 1、全网资源引流(流量购买) 在全网资源中投放能调起小程序的广告,也可能跳出腾讯系媒体来为小程序引流。 点击广告进入落地页的用户将会收到一条跳转提醒——“行将关上XX小程序”。若用户抉择“容许”,则间接进入该小程序;若抉择“勾销”,则用户的手机页面停留在有小程序入口的H5中,再一次疏导用户进入小程序。 2、私域流量引流 对于小程序的引流来说,各个平台私域流量也是外围的流量起源。目前小程序反对在公众号、视频号绑定,也已实现在短信、邮件中调启。 短信/邮件引流 手机号与邮件作为目前最宽泛的私人联系方式,覆盖率仍旧是最高的,短信和邮件天然还是笼罩最广的被动音讯推送形式。 开发者生成微信 URL Link 链接后,能够间接调用小程序云开发短信接口发送短信与邮件,用户通过点击音讯中的URL即可调起小程序。还反对对不同的用户发送不同的链接,须要留神的是,可发短信数须要进行购买。 3、第三方单干引流 公域流量的竞争强烈,很多人不晓得的是与第三方平台进行单干也是十分无效的小程序引流形式。 此处以金融机构常见的异业单干举例说明,如券商常见的开户引流:券商通过与第三方平台单干,将服务小程序、开户小程序挂载在第三方平台,用户通过券商小程序能够在平台内间接实现开户操作实现用户引流。 除了在第三方平台实现服务外,还能够扩大小程序的服务场景,利用App关上小程序性能。用户在第三方平台获取服务之后,可通过小程序跳转回原APP 。这意味着,企业不仅仅能够通过第三方平台实现营销服务,也能够将内部用户无效引流至自有app进行积淀。 以上提到的第三方单干引流的模式须要肯定的技术支持,在这里为大家介绍一款小程序容器技术——FinClip小程序容器,任何企业或机构的App均能够嵌入该组件而霎时取得运行小程序的能力;同时也提供了“小程序开放平台”的解决方案,供任何机构、行业组织运行本人的小程序生态、对立高低架治理本人以及合作伙伴们的业务场景。 与互联网巨头小程序平台不同的中央在于,FinClip小程序平台更加凋谢(提供API接口,反对二次开发),也更聚焦不同组织在合规监管方面的非凡行业诉求。目前已在多家银行、保险、证券以及相干行业机构落地,并可能自有机房内独立部署运行。 不仅如此,“凡泰小程序技术”语法结构和微信小程序兼容,一次开发,多处上架,可升高开发成本,晋升研发效率。

April 28, 2022 · 1 min · jiezi

关于小程序:小程序自动化测试框架原理剖析

百度智能小程序,是 H5 和 Native 技术联合的产物,运行在百度 APP、爱奇艺等反对百度智能小程序运行的宿主 APP 上。因而,很难用既有的端自动化测试工具(如,Appium 等)、或者 H5 自动化测试工具(如,Selenium 等)进行百度智能小程序的自动化测试。 为了解决这个问题,百度智能小程序测试中台团队,出品了一款名为 smartapp-automator 的自动化测试框架,以便于业务发展智能小程序的自动化测试。 本文的主题,就是针对该自动化测试框架的架构原理进行深刻分析。 01智能小程序架构设计既然是对智能小程序自动化测试框架的分析,免不了先得聊聊智能小程序的架构设计。 如图所示便是智能小程序的一个简要的架构设计图: 运行设施指的是咱们平时应用的 android 或者 iOS 手机,宿主 APP 指的是 百度 APP 以及其它智能小程序开源联盟合作伙伴 APP,如爱奇艺、wifi 万能钥匙等。 当然智能小程序有一个独特的个性,能够为开发者主动生成一个 H5 状态的小程序,反对间接运行在浏览器上的,这时候运行设施指的就是咱们的个人电脑/手机,而宿主 APP 指的就是浏览器了。 当咱们用手机关上百度 APP 上的某个小程序的时候,百度 APP 会为这个小程序独自开启一个过程,并在这个过程里开启一个 Logic 线程和多个 View 线程。 小程序的所有业务逻辑都集中在 Logic 线程,而 View 线程就是咱们所看到的小程序的各个页面,Logic 线程和 View 线程通过宿主 APP 集成的小程序框架 SDK(swan sdk)提供的 eventBus 进行双向通信。 举个例子,咱们看到的小程序的首页(页面 A),其实是一个 View 线程(view1),当咱们点击下面的一个按钮的时候,点击事件会经 eventBus 由 swan sdk 传回到 Logic 线程,Logic 线程依据开发者绑定的解决函数调用 swan.navigateTo 办法触发跳转页面 B,页面调整指令由 Logic 线程传递到 swan sdk,swan sdk 创立一个新的 View 线程( view2)渲染页面 B 并将 view 推至前台展现在用户背后,最初通过 eventBus 告知 Logic 线程页面创立结束,实现一次点击事件的解决。 ...

April 27, 2022 · 2 min · jiezi

关于小程序:小程序商城系统源码完整开源版

 在本文中,咱们将应用PHP和MySQL构建一个跨平台反对的小程序商城源码。在这个源码中,咱们能够依据商品的名称、数量、状态(待定、已购买、不可购买)和日期增加它们。咱们能够查看、删除和更新这些条目,将有一个日期过滤性能,咱们能够依据日期查看货物。 技术条件:XAMPP服务器、HTML基本概念、CSS、Bootstrap、PHP、MySQL 残缺源码:xcxyms.top 咱们将依照以下步骤构建此应用程序。 步骤1:关上XAMPP控制面板,启动Apache和MySQL服务。在XAMPP文件夹中,转到htdocs文件夹并创立一个名为project1的文件夹。咱们将所有文件保留在project1文件夹中。在这个文件夹中,有五个文件(add.php, connect.php, delete.php, index.php, update.php)和一个名为css的文件夹,其中有一个名为style.css的文件。 步骤2:转到localhost/phpMyAdmin并创立一个名为grocerydb的数据库。在它上面,创立一个名为grocerytb的5列表。列是Id(主键)、Item_name、Item_Quantity、Item_status和日期。Id列的主动递增模式应该是开启的。最初,表构造应该如图所示。 步骤3:关上您抉择的编辑器。创立一个名为connect.php的文件,并编写以下代码行。 <?php$con=mysqli_connect("localhost","root","","grocerydb");if(!$con){ die("cannot connect to server");} ?> 这个页面用于将PHP页面与数据库“grocerydb”连接起来。连贯这个数据库之后,连贯对象被返回给$con变量。如果没有建设连贯,将显示“无奈连贯到服务器”的音讯。 步骤4:创立另一个名为add.php的文件,并编写以下代码行。 <html><head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Add List</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"> <link rel="stylesheet" href="css/style.css"></head><body> <div class="container mt-5"> <h1>Add Grocery List</h1> <form action="add.php" method="POST"> <div class="form-group"> <label>Item name</label> <input type="text" class="form-control" placeholder="Item name" name="iname" /> </div> <div class="form-group"> <label>Item quantity</label> <input type="text" class="form-control" placeholder="Item quantity" name="iqty" /> </div> <div class="form-group"> <label>Item status</label> <select class="form-control" name="istatus"> <option value="0"> PENDING </option> <option value="1"> BOUGHT </option> <option value="2"> NOT AVAILABLE </option> </select> </div> <div class="form-group"> <label>Date</label> <input type="date" class="form-control" placeholder="Date" name="idate"> </div> <div class="form-group"> <input type="submit" value="Add" class="btn btn-danger" name="btn"> </div> </form> </div> <?php if(isset($_POST["btn"])) { include("connect.php"); $item_name=$_POST['iname']; $item_qty=$_POST['iqty']; $item_status=$_POST['istatus']; $date=$_POST['idate']; $q="insert into grocerytb(Item_name, Item_Quantity,Item_status,Date) values('$item_name',$item_qty, '$item_status','$date')"; mysqli_query($con,$q); header("location:index.php"); } // if(!mysqli_query($con,$q)) // { // echo "Value Not Inserted"; // } // else // { // echo "Value Inserted"; // } ?></body></html> 这个页面用于将食品杂货数据从HTML表单插入到“grocerydb”数据库中的“grocerytb”表。html表单蕴含要由用户输出的项目名称、我的项目数量、我的项目状态和日期值。咱们曾经别离将Pending、Bought和Not Available(我的项目状态)的选项值设置为0、1和2。当单击按钮时,咱们将蕴含文件“connect.php”,以将页面连贯到数据库。而后,咱们获取用户输出的所有数据,并将它们插入到“grocerytb”表中。如果在表中胜利地输出了值,页面将挪动到“index.php”,它将容许用户查看到目前为止输出的项(或目前在表中)。在css文件夹中创立一个“style.css”文件,并编写如下代码。 ...

April 27, 2022 · 3 min · jiezi

关于小程序:SaaS版本上线小程序应用生态更进一步

2019年凡泰极客正式对外公布了FinClip小程序容器技术,由此凡泰极客也正式踏上了小程序生态建设之路。 通过近两年的服务实际与高速的产品性能迭代,FinClip的客群也在极速拓展。基于扎实的实际摸索累积,咱们惊喜的发现,尽管这款产品应金融行业的需要而生,然而服务与承接需要的能力却是没有行业限度的,具备真正的普适性,在不到两年的工夫里,FinClip也陆续取得了包含制造业、电信、互联网、医疗、物联网等简直全行业各类型客户的体验试用并胜利融入客户的日常业务提供赋能与服务。 随着意识与应用 FinClip 的用户越来越多,很多用户也提出了新的问题,比方心愿可能在线上环境中实现商业化应用,心愿可能自有地对已有的资源进行灵便拓展。基于种种原因,以及 FinClip 产研团队的合作配合,依照 2022 年产品 RoadMap 打算,FinClip SaaS 版曾经于近日上线至 FinClip.com 环境中。 咱们心愿邀请更多的开发者与生态从业者,一起退出 FinClip 来体验小程序利用的独特魅力。 从当初开始,任何用户不须要领取任何费用就能够应用 FinClip SaaS 版的绝大多数的软件性能,之前在官网注册应用体验版的用户也将主动迁徙至 SaaS 版环境。 咱们在 SaaS 版中提供了小程序必要的能力,也包含了付费版本中的大多数性能,能够满足小团队、项目组、小微企业等日常应用所需。 同时,咱们也为每位用户提供了每月 10,000 次的小程序收费公布调用与相干资源空间。心愿这样做可能进一步解决各位开发者与用户在应用时的门槛。 开发者敌人只须要关上 FinClip.com 进行注册,就能够体验 FinClip SaaS 版的相干性能了。如果您在此之前还没有体验过小程序的魔力,当初是时候了!咱们把用户门槛降到最低的“收费”,就是为了让更多的用户可能体验小程序利用平台的价值,同时也心愿助推更多的用户成为小程序开发专家,为更好地建设小程序生态做筹备。 提供 SaaS 版也与 FinClip 的另一个产品指标无关,咱们心愿可能建设大规模的小程序利用生态。在国内市场中因为不同行业,不同类型的限度,企业数量之多,需要背景之简单都可能意味着没有哪一款繁多的软件产品可能满足所有行业的须要。引入新的行业合作伙伴和曾经把握小程序利用设计的开发者就显得尤为重要,咱们心愿可能通过小程序生态的建设来解决这个问题,为小程序开发者们提供一个更好的舞台,他们所设计的不同小程序都能够通过 FinClip 的平台收费或免费的提供给更多企业与终端用户。 随同着SaaS版的上线,FIDE也配合做了性能的优化,目前FIDE反对 「小程序导出 App」性能,开发者在下载更新 IDE 版本后,就能够在工具的右上角看到有「导出」按钮的字样。 通过这个「生成 App」的性能,你就能够在本人的小程序根底之上,疾速生成 iOS 与 Android 的独立利用,之后则能够在 Xcode 或 Android Studio 中对相干资源进行配置优化,随后就能够编译出属于本人的独立 App 了! 相比于传统的 App,基于小程序所设计导出的 App 还具备如下长处: ...

April 21, 2022 · 1 min · jiezi

关于小程序:淘宝小程序体验优化数据分析和优化实践

作者:莫绪旻(向屿) 淘宝小程序曾经走过若干个双十一,淘宝凋谢业务有序铺开。体验优化是个陈词滥调的话题,如何让小程序跑得又稳又快,成了咱们最大的挑战之一。 写在后面如何定义好的体验过来咱们定义这个问题,更多的是从页面加载速度和晦涩度去解释,但这还远远不够。加载速度的晋升是否让用户更违心“玩”了,晦涩度晋升是否也晋升了模块曝光和成交。 为了有更平面的衡量标准,有了如下构想:页面加载速度和晦涩度晋升(技术视角)-> 用户跳失率降落(用户视角)-> 商品曝光和点击上涨(平台视角) 窘境上面是一些 TOP 二、三方业务的性能数据(数据取自2020年5月),能够说比拟蹩脚。(“跳失”的定义为:用户关上小程序后,页面渲染未实现或未达到产生交互的条件就退出页面) 简单的技术架构 小程序在逻辑/渲染拆散的架构下,保障了凋谢平安的同时,也引入了更大的性能挑战。 三方生态的品质和平安 小程序是淘宝凋谢体系中的重要一环,面向商家和内部开发者,给研发品质保障、数据安全带来了更大挑战。 掂量指标繁多 过来咱们定义这个问题,更多的是从页面加载速度和晦涩度去解释,但这远远不够。 破局通过运维数据标准化,贯通研发->公布->上线流程,造成数据闭环: 数据采集:定义采集算法、数据模型,造成一套标准化运维数据运维平台:连贯二/三方开发者,提供数据透出和回流能力,定义监控&卡口规定数据分析:迷信的数据分析方法论,有试验、有数据、有证据效力工具:买通研发基础设施,赋能开发者 数据采集T2(首屏算法)阿里团体小程序对齐了首屏加载掂量口径,采纳UC内核的T2首屏算法,T2指标定义为 从页面开始加载到页面首次渲染满屏内容的工夫。简略说,是在页面加载的过程中,记录所有的渲染帧,待页面加载完结之后,回溯查看每一帧,图片渲染面积首次达到最大值的一帧记为T2。 小程序性能模型为了把小程序启动性能进行分阶段拆解,定义了小程序性能模型,从小程序启动开始到首屏渲染实现完结,拆解成了:Downloading(资源申请:元信息申请和包下载)、Launch(容器启动和小程序Runtime启动)、Rending(业务逻辑执行和渲染) 同时,面向小程序开发者提供了规范的 Web API performance.mark(),反对开发者自定义打点。 通过剖析各阶段耗时,能够较为清晰的发现性能瓶颈。 数据分析和优化实际篇幅无限,仅分享几个经典案例。 页面性能与用户跳失的关系依据小程序加载性能和用户跳失的直方图,能更直观的剖析出小程序加载性能跟用户跳失的关系。如下图,能够看出当小程序加载耗时超过2s时,跳失率程指数级增长。也正是基于这个论断,咱们将小程序可交互时长的大盘指标定为了1.8s。(其中横轴示意可交互时长,纵轴示意跳失的用户散布在该工夫内的占比) 小程序启动漏斗小程序启动漏斗,能更直观的剖析出各阶段耗时和跳失率/白屏率等指标的关系。以下图为例: Downloading 申请阶段耗时过长,是白屏率/跳失率的重要因素a、旗舰店小程序接入 资源预热,Downloading 耗时缩短50%,阶段跳失/白屏收窄至0.08%内; 业务数据申请耗时长a、旗舰店小程序接入数据预取,店铺框架数据申请耗时根本降为0,阶段跳失/白屏根本降至0。 最佳实际之:小程序引擎实例复用和预启动 小程序过程启动后,在闲暇机会,会初始化并保留有且仅有一个通用的小程序 Engine 环境(与业务无关),直到小程序过程被杀死;在运行过程中,小程序 Engine 实例会在3个状态之间切换:a、可运行:小程序过程启动后,新创建的小程序Runtime环境为”可运行“状态; b、运行中:小程序业务启动时,将状态为”可运行“的实例取出应用,状态变为“运行中"; c、重置中:小程序业务敞开后,将应用过的实例取出,状态变为”重置中“;状态重置结束后,变为”可运行“状态,供下个小程序应用。 最佳实际之:数据预取2.0依据小程序性能模型剖析,在小程序启动过程中,Worker启动总是快于Render实现(Worker 处于闲暇状态),Worker 闲暇时长散布如下: 能够看出,线上有92.2%的概率会产生Worker闲置,闲置时长集中在300-500ms,能够实现1-2次网络申请;闲置 Worker 具备了齐备的小程序 JS 执行能力,可在受限范畴内执行小程序 JSAPI,发送网络申请获取定位信息/零碎信息等; 动静预取长处a、灵便:环境具备JS执行能力,更灵便 b、丰盛:提供受限的 JSAPI 调用能力= c、平安:反对权限管控,面向三方凋谢更平安 最佳实际之:基于模板的快照渲染快照渲染可能晋升页面二次关上性能,但在旗舰店场景下存在如下弊病:a、数据真实性:快照渲染应用了上次关上时的老数据,会先展现旧内容再刷新; b、磁盘占用和命中率:旗舰店属于模板类小程序,有百万数量级的实例化小程序,快照渲染会为每家店铺生成不同的快照文件;宏大的基数条件下,再思考磁盘占用建设的淘汰机制,使得快照命中率较低; c、长尾问题:拜访频次较低的长尾店铺,同一用户二次拜访的概率较低,无奈命中快照; 为解决上述问题,实现了”基于模板的快照渲染(Template Snapshot)“。基于模板小程序生成快照文件并将数据剔除,在快照渲染时,配合数据预取将实在数据插入模板中。既能保证数据真实性,同时可让所有店铺共享同一快照文件,最大限度的进步快照命中率和升高磁盘占用。 ...

April 20, 2022 · 1 min · jiezi

关于小程序:小程序自定义tabBar

主要用途:实现一些原生tabBar不能实现的货色,比方某个tabBar跳转别的小程序性能等所有非间接跳转本小程序页面的性能 核心思想:将整个底部的tabBar进行自定义,写一个本人的tabBar组件,绑定点击事件并传入下标,当传入的下标是你须要自定义办法的那个item项时执行自定义办法,其余下标执行失常的tabBar的页面跳转(switchtab) 具体实现参考博主:智慧大石https://www.imooc.com/article...

April 13, 2022 · 1 min · jiezi

关于小程序:微信-小程序-用户手机绑定表设计

这边文章是以本人的我的项目逻辑来整顿的文章,可能不合乎别人我的项目; 1、需要是通过用户受权获取微信绑定的手机号,来确定用户的身份权限;2、同时小程序端又有本人的wx.login 逻辑;尽管当初小程序改版后能够不通过wx.login来获取手机号,然而其余操作必须要session_key ,所以还是利用小程序的wx.login吧; 依据需要如果不论用户是否受权手机号,都须要统计用户信息、数量等,就须要增加额定一张小程序匿名用户的openid 的绑定表;如果仅仅是对受权手机号的用户辨认,仅须要一个手机号+openid 的联结表就行了; 留神: 微信换绑手机号,会对小程序用户受权绑定的手机号有影响,必须双重思考,每次登录都应该从新获取绑定手机号,以获取实在的绑定关系,而不是通过openid就单纯的确定手机号了。 以下两个需要都阐明一下: 一:须要记录每位微信小程序的用户数据,须要两张表,手机号主表+openid 附表 小程序用户表 mp_user appidopenidunionidsession_keyaccess_tokenexpire_timeuser_id小程序APPID微信用户openid微信用户unionid登录后session_key服务端token登录有效期(可不要)手机受权user用户手机号表: user_phone以手机号用户标记,不便用户业务脱离小程序 phonecountry_codenicknamehead手机号区号昵称头像流程阐明:1、小程序登录(静默登录无需界面体现),刷新小程序用户表session_key、access_token等信息2、受权手机号登录,查看openid+appid 和手机号是否和之前绑定的统一,如果不统一阐明用户换绑了手机号,则须要在小程序用户表解除旧的绑定,增加新的绑定关系; 二:仅仅有用户手机号表 user_phone一张表设计可能存在以下问题: 以openid为次要信息,手机号等为附加信息;所有设置以openid为主键;无奈扩大到小程序内部,如果要扩大,可能也须要将手机号表独立进去。如果用户换绑微信手机号,则从新登录受权手机号后,会刷掉之前的手机号;从而导致无奈找到之前的手机号;通过比照,倡议还是应用形式一的设计吧,这样数据离开保护;一张表也会关联session_key、openid等;依据以上解析,还是倡议应用第一种计划,不便拓展用户业务逻辑,独立以手机号为主用户标记的业务。

April 11, 2022 · 1 min · jiezi

关于小程序:微信-小程序-sessionkey-维护

这是 微信官网所说:session_key 阐明 以下三方服务端成为服务端微信服务端成为微信端小程序端成为小程序会话密钥 session_key 有效性开发者如果遇到因为 session_key 不正确而校验签名失败或解密失败,请关注上面几个与 session_key 无关的注意事项。 wx.login 调用时,用户的 session_key 可能会被更新而以致旧 session_key 生效(刷新机制存在最短周期,如果同一个用户短时间内屡次调用 wx.login,并非每次调用都导致 session_key 刷新)。开发者应该在明确须要从新登录时才调用 wx.login,及时通过 auth.code2Session 接口更新服务器存储的 session_key。 微信不会把 session_key 的有效期告知开发者。咱们会依据用户应用小程序的行为对 session_key 进行续期。用户越频繁应用小程序,session_key 有效期越长。 开发者在 session_key 生效时,能够通过从新执行登录流程获取无效的 session_key。应用接口 wx.checkSession能够校验 session_key 是否无效,从而防止小程序重复执行登录流程。 当开发者在实现自定义登录态时,能够思考以 session_key 有效期作为本身登录态有效期,也能够实现自定义的时效性策略。解释:wx.login 调用时,用户的 session_key 可能会被更新而以致旧 session_key 生效(刷新机制存在最短周期,如果同一个用户短时间内屡次调用 wx.login,并非每次调用都导致 session_key 刷新)。开发者应该在明确须要从新登录时才调用 wx.login,及时通过 auth.code2Session 接口更新服务器存储的 session_key。阐明:session_key 是微信端凋谢进去让服务端 保护小程序用户登录状态+用户数据的标识,wx.login 会刷新session_key(留神:频繁登录,微信端可能就懒得刷新重复使用之前的了);小程序 wx.checkSession 查看登录状态是否无效,刷新登录时服务端也依据code从新刷新session_key并且保留; 微信不会把 session_key 的有效期告知开发者。咱们会依据用户应用小程序的行为对 session_key 进行续期。用户越频繁应用小程序,session_key 有效期越长。阐明:session_key 有没无效代表以后登录状态有没无效,小程序端不停应用会提早有效期,这个和web的tokan、session 机制类相似;留神:小程序端wx.checkSession 查看,服务端可通过API auth.checkSessionKey 查看; 开发者在 session_key 生效时,能够通过从新执行登录流程获取无效的 session_key。应用接口 wx.checkSession能够校验 session_key 是否无效,从而防止小程序重复执行登录流程。当开发者在实现自定义登录态时,能够思考以 session_key 有效期作为本身登录态有效期,也能够实现自定义的时效性策略。阐明:通过 wx.checkSession 查看登录是否无效,有效就从新执行wx.login 并且 刷新服务端的session_key; ...

April 11, 2022 · 1 min · jiezi

关于小程序:题库小程序之技术点总结

题库小程序之技术点总结。有其中一些性能,过后我花了一些工夫精力推敲和尝试。当初回顾,总结一下。比方,解锁题库性能的设计与实现、一战到底的刷题性能的设计与实现(答对的主动删掉,答错的持续作答,直到全副答对为止)等等。 Q&A: 客户解锁某题库后,该题库是不是复制到另一表,我是不是删除该题库也不会影响客户持续做这个题库的题 Q&A: 客户遍历的是残余题,而不是总题 Q&A: 某题库只有解锁,就复制到客户的数据表,只有做对,从新更新表,记录会减1,客户表不会越来越大 Q&A: 该客户所有解锁后的题做完了,表就空了 Q&A: 或者是否将解锁题库下载到客户手机用于存取 Q&A: 或者是否将解锁后的题库对应id放到客户数据表 Q&A: 一套解锁后的题库作为一条记录,记录是数组,包含客户id,残余题id,等等 Q&A: 客户数据表: 客户id, 题库名, 总题数(由题库名就晓得总题数,该字段是不变的), 题库id(是题库数据库的惟一id,比如某题库有100题,则初始数组是100个) 每做完一题,如果题做错了,该记录内容不变,如果做对了,删除对应题库id,数组减1。 残余题数即题库数组大小 Q&A: 解锁一次,该表记录加1 Q&A: 数组为空后,删除该记录 Q&A: 这样的话,数据库就小多了 不用记录客户答题工夫

April 8, 2022 · 1 min · jiezi

关于小程序:基于-Serverless-架构的头像漫画风处理小程序

前言我始终都想要有一个漫画版的头像,奈何手太笨,用了很多软件 “捏不进去”,所以就在想着,是否能够基于 AI 实现这样一个性能,并部署到 Serverless 架构上让更多人来尝试应用呢? 后端我的项目后端我的项目采纳业界鼎鼎有名的动漫格调转化滤镜库 AnimeGAN 的 v2 版本,成果大略如下: 对于这个模型的具体的信息,在这里不做具体的介绍和阐明。通过与 Python Web 框架联合,将 AI 模型通过接口对外裸露: from PIL import Imageimport ioimport torchimport base64import bottleimport randomimport jsoncacheDir = '/tmp/'modelDir = './model/bryandlee_animegan2-pytorch_main'getModel = lambda modelName: torch.hub.load(modelDir, "generator", pretrained=modelName, source='local')models = { 'celeba_distill': getModel('celeba_distill'), 'face_paint_512_v1': getModel('face_paint_512_v1'), 'face_paint_512_v2': getModel('face_paint_512_v2'), 'paprika': getModel('paprika')}randomStr = lambda num=5: "".join(random.sample('abcdefghijklmnopqrstuvwxyz', num))face2paint = torch.hub.load(modelDir, "face2paint", size=512, source='local')@bottle.route('/images/comic_style', method='POST')def getComicStyle(): result = {} try: postData = json.loads(bottle.request.body.read().decode("utf-8")) style = postData.get("style", 'celeba_distill') image = postData.get("image") localName = randomStr(10) # 图片获取 imagePath = cacheDir + localName with open(imagePath, 'wb') as f: f.write(base64.b64decode(image)) # 内容预测 model = models[style] imgAttr = Image.open(imagePath).convert("RGB") outAttr = face2paint(model, imgAttr) img_buffer = io.BytesIO() outAttr.save(img_buffer, format='JPEG') byte_data = img_buffer.getvalue() img_buffer.close() result["photo"] = 'data:image/jpg;base64, %s' % base64.b64encode(byte_data).decode() except Exception as e: print("ERROR: ", e) result["error"] = True return resultapp = bottle.default_app()if __name__ == "__main__": bottle.run(host='localhost', port=8099)整个代码是基于 Serverless 架构进行了局部改进的: ...

April 8, 2022 · 5 min · jiezi

关于小程序:小程序测试

一、 微信小程序定义及特点1.1 定义简称Mini Program,依附于微信无需再次下载安装的挪动端应用程序1.2 特点用户的体验性(即用即走,清新体验)1.3 设计有余微信小程序包大小不超过20M(目前)微信小程序不适用于简单的业务解决微信小程序页面层级倡议理论设计不超过三级,官网要求不超过5级1.4 利用场景接口测试注意事项 微信小程序无奈间接和后盾服务器进行通信微信小程序必须依附于微信(客户端/微信接口服务器)进行和后盾失常通信 二、小程序和APP的比照2.1 入口小程序:进入小程序测试(扫码、搜寻、下拉进入、分享、卡包等进行受权即可)APP:通过网站进行下载(下载注册登录)2.2 部署小程序:无需下载安装即可应用APP :须要装置、卸载、降级2.3 兼容性小程序:微信的版本和手机的分辨率APP :不同的操作系统,同一操作系统的不同版本,屏幕分辨率

April 3, 2022 · 1 min · jiezi

关于小程序:uniapp小程序防止二次点击问题解决方案

背景:小程序有的中央点击 如果申请比较慢,就会关上两次新页面,所以这里对用户短时间双击进行了解决如果有更好的办法 请留言哦 我参考学习下我也是参考了他人的:https://blog.csdn.net/weixin_...1.封装公共办法 export function disableDoubleClick(fn, flag, data = {}) { let that = this;//这里flag 也是为了避免一个页面多个点击事件 if (that[flag]) { that[flag] = false; fn(data); setTimeout(function() { that[flag] = true; }, 1500) } else { //如果始终走else分支可能是你没有在页面的data上面挂载flag:true,不然始终都会走else console.log("请稍后点击") }}2.挂在在vue中 import { disableDoubleClick } from '../utils/utilsFn.js'Vue.prototype.$disableDoubleClick = disableDoubleClick;须要的页面应用 <view class="xf-act-btn" @click="$disableDoubleClick (handleLogin ,'onoff')" >开始提货</view> <view class="history-btn" @click="$disableDoubleClick(historyPage ,'onoff1')">历史提货</view>留神data定义一下,这里可能我解决的简单了,能够优化data(){ return { onoff:true, onoff1:true, } }

April 1, 2022 · 1 min · jiezi

关于小程序:慕慕到家家政小程序组件化进阶实战掌握小程序开发核心能力

前言:下载课程ZY:https://www.sisuoit.com/1999.html 简述ClickHouse 近两年在开源社区愈发炽热,不知从何开始大家争相用它来替换 ElasticSearch,大略因为 ElasticSearch 的开销太高,在不作为搜索引擎的场景下,肯定水平的暴力搜寻是能够容忍的。咱们在应用 Skywalking 后发现,它对后端存储要求太高了,应用 (32C + 64G + 2T) x8 的配置,在云平台上每月好几万的开销,性能仍然十分捉急,查问常常超时。前前后后优化了小半年后,最终下定决心替换成 ClickHouse。在应用为 ClickHouse 后,机器数量缩小了 50%; 查问链路列表从 5.53/s 进步到了 166/s,响应工夫从 3.52s 升高到了 166ms;查问链路详情从 5.31/s 进步到了 348/s,响应工夫从 3.63s 升高到了 348ms;链路数据存储工夫从 5 天进步到了 10 天,数据量达到数百亿;值得一提的是,在与 ES 的比照中常常会提到磁盘空间升高,其实 ClickHouse 的压缩率没有那么夸大,起码在我的理论体验两者相差不大。如果 ES 空间占用很高,那很可能是因为没在索引中开启 codec: best_compression。ClickHouse 也并不是没有毛病,本篇文章分享下如何用 ClickHouse 作为 Skywalking 的后端存储。本文不会赘述 ClickHouse 的基本原理,须要读者对 ClickHouse 有肯定理解的状况下浏览。(因为工作量微小,对 Skywalking 存储的革新仅限于存储链路数据,即 Segment,其余部分就抓大放小,仍应用 ElasticSearch 存储,没有进行革新) 表设计ClickHouse 根本只能建设一种索引,即 Order By 的索引。而链路表查问条件泛滥,简直每个字段都是查问条件,且蕴含多种排序,设计起来比拟辣手。查问条件:工夫、服务名称、服务实例、链路类型、链路 ID、链路名称、响应工夫、是否异样排序条件:工夫、响应工夫想要在一张表上设计出合乎所有查问模式,根本是不可能的(或齐全不可能),在参考了 jaeger-clickhouse 等泛滥设计后,更加动摇了这个论断。尝试了数次后,最终的建表语句如下: CREATE TABLE skywalking.segment( `segment_id` String, `trace_id` String, `service_id` LowCardinality(String), `service_instance_id` LowCardinality(String), `endpoint_name` String, `endpoint_component_id` LowCardinality(String), `start_time` DateTime64(3), `end_time` DateTime64(3), `latency` Int32, `is_error` Enum8('success' = 0, 'error' = 1), `data_binary` String, INDEX idx_endpoint_name endpoint_name TYPE tokenbf_v1(2048, 2, 0) GRANULARITY 1, PROJECTION p_trace_id ( SELECT trace_id, groupArrayDistinct(service_id), min(start_time) AS min_start_time, max(start_time) AS max_start_time GROUP BY trace_id ))ENGINE = MergeTreePARTITION BY toYYYYMMDD(start_time)ORDER BY (start_time, service_id, endpoint_name, is_error)TTL toDateTime(start_time) + toIntervalDay(10)首先,在 partition 上还是应用了天作为条件。在 Order By 时,应用 工夫 + 服务 + 链路名称 + 异样。为什么不是 服务 + 工夫,因为在很多查问中,工夫作为条件的状况比服务作为条件的频率更高,如果在服务放在前边,大部分时候 ClickHouse 须要在一个文件的不同局部去遍历,IO 会变得扩散。 ...

March 29, 2022 · 1 min · jiezi

关于小程序:基于微信小程序的大学校园实验预约平台的设计方案

业务背景实验室预约治理小程序,包含实验室动静,实验室规章制度,预约审批,用户治理,根底实验室预约,业余实验室预约等性能。目前局部高校实验室存在设施治理艰难的问题,要应用设施可能须要在微信群内重复询问,注销也麻烦。实验室预约助手目标就在用低成本的云开发实现对实验室的设施应用治理,从而达到有序试验,标准治理,晋升效率,无效溯源的作用 性能需要 数据库设计 技术攻关小程序隔离策略同一个微信小程序用户 storage 下限为 10MB。storage 以用户维度隔离, 同一台设施上,A 用户无奈读取到 B 用户的数据;不同小程序之间也无奈相互读写数据。 插件隔离策略同一小程序应用不同插件:不同插件之间,插件与小程序之间 storage 不互通。不同小程序应用同一插件:同一插件 storage 不互通。 清理策略本地缓存的清理机会跟代码包一样,只有在小程序代码包被清理的时候本地缓存才会被清理。 小程序缓存办法的类封装微信缓存二次封装,有设置时效性的封装 /** * 写小程序缓存 * k 键key * v 值value * t 秒(无效工夫) */function set(k, v, t = 86400 * 30) { if (!k) return null; wx.setStorageSync(k, v); let seconds = parseInt(t); if (seconds > 0) { let newtime = Date.parse(new Date()); newtime = newtime / 1000 + seconds; wx.setStorageSync(k + TIME_SUFFIX, newtime + ""); } else { wx.removeStorageSync(k + TIME_SUFFIX); }}/** * 获取小程序缓存 * k 键key * def 默认值 */function get(k, def = null) { if (!k) return null; let deadtime = parseInt(wx.getStorageSync(k + TIME_SUFFIX)); if (deadtime) { if (parseInt(deadtime) < Date.parse(new Date()) / 1000) { wx.removeStorageSync(k); wx.removeStorageSync(k + TIME_SUFFIX); return def; } } let res = wx.getStorageSync(k); if (res) { return res; } else { return def; }}前端界面设计 ...

March 29, 2022 · 1 min · jiezi