如何设计一个ToC的弹窗

2023-10-15 19:15
文章标签 设计 弹窗 toc

本文主要是介绍如何设计一个ToC的弹窗,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本文主要分享了如何设计一个具有高可扩展性的弹窗功能。

本设计参考了优惠券功能的设计思路,有兴趣的朋友可以看看优惠券的分享:如何设计一个可扩展的优惠券功能_java优惠券系统设计-CSDN博客

一、需求介绍

假如你的项目需要实现以下弹窗,你会怎么去实现?

需求:

1.展示1张图片,点击图片后跳转到另外1个页面(支持H5、小程序、其他小程序),有个关闭按钮,点击关闭按钮停留在当前页面

2.该弹窗功能提供给运营通过管理后台进行配置

3.弹窗频率需要有所控制,比如1天1次,有优先级,比如运营配置了3个弹窗,不能同时弹,需要按优先级每次进入页面的时候才弹(参考某团的体验)

4.支持灵活配置弹窗条件,比如地域属性、平台属性、时间属性、指定某些用户、用户来源等

5.在配置弹窗过程中有些变量属性,需要运行时才能确定,比如跳转链接中增加当前登录用户ID或者token作为参数

二、数据库设计(存储设计好坏往往决定一个功能日后的可维护、可扩展)

1.错误的表设计(按需求一一列举各种条件作为表结构的字段)

id

有效期

图片url

H5链接

小程序链接频率控制

优先级

条件1

条件2

...

条件n

1

2023-09-24

https://image.com/aa/bb.jpg

/page/mini

1次/天

99

ios

深圳市

相信很多朋友都是这样设计弹窗表的,这种表设计非常大的问题就是每次需要增加1个新的弹窗条件的话就要新增1个字段,非常不利于功能扩展。

2.正确的表设计(抽象区分‘配置数据’和‘弹窗条件’)

配置数据:使用1个字段,以json结构进行存储,可以做到灵活增加数据或改变数据,配置数据不涉及数据过滤,所以不涉及性能问题

id

有效期

优先级

背景图json

1

2023-09-24

99

{"imgUrl":"https://image.com/aa/bb.jpg","type":"redirct_mini","value":"/page/mini"}

弹窗条件:由列式转化为行式存储,增加条件不需要增加字段,而是加1行数据

id

popup_id

条件

条件值

1

1

条件1

1次/天

2

1

条件2

ios

3

1

条件3

深圳市

核心设计思想:

1.把数据库表的列式条件转化为行式条件,比如 where a=? and b=?,转化为2行数据作为条件(当然转化后不再是sql能表达的)

2.运用设计模式(类似责任链模式)把1中的行式条件转化为一段代码,可简单可复杂,通过关联关系来做到可插拔

3.完整的表结构设计(remark、create_time、update_time是固定字段)
CREATE TABLE `mk_popup_pop_condition` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',`bean_name` varchar(32) NOT NULL DEFAULT '' COMMENT 'bean名称(PopCondition的实现类)',`descrpition` varchar(255) DEFAULT NULL COMMENT '描述',`remark` varchar(255) DEFAULT NULL COMMENT '备注',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,UNIQUE KEY `uniq_beanname` (`bean_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='弹窗条件';CREATE TABLE `mk_popup` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',`begin_time` datetime NOT NULL COMMENT '有效期开始时间',`end_time` datetime NOT NULL COMMENT '有效期结束时间',`status` varchar(8) NOT NULL DEFAULT '' COMMENT '状态(off:下架,on:上架)',`priority` int(11) NOT NULL DEFAULT '0' COMMENT '优先级(值越大,优先级越高)',`title` varchar(32) NOT NULL DEFAULT '' COMMENT '标题',`text` varchar(128) NOT NULL DEFAULT '' COMMENT '文案',`bg_img` varchar(255) NOT NULL DEFAULT '' COMMENT '背景图json数据',`close_btn` varchar(255) NOT NULL DEFAULT '' COMMENT '关闭按钮json数据',`remark` varchar(255) DEFAULT NULL COMMENT '备注',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,KEY `idx_begintime` (`begin_time`),KEY `idx_endtime` (`end_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='弹窗';CREATE TABLE `mk_popup_condition` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',`popup_id` int(11) NOT NULL COMMENT 'mk_popup.id',`pop_condition` varchar(32) NOT NULL DEFAULT '' COMMENT '弹窗条件(bean名称,mk_popup_pop_condition.bean_name)',`pop_condition_value` varchar(255) DEFAULT '' COMMENT '弹窗条件值',`remark` varchar(255) DEFAULT NULL COMMENT '备注',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`),KEY `idx_popupid` (`popup_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='弹窗-弹窗条件';CREATE TABLE `mk_popup_log` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',`business_type` varchar(64) NOT NULL DEFAULT '' COMMENT '业务类型(popup:mk_popup,user_popup:mk_user_popup)',`business_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '业务ID',`user_id` int(11) NOT NULL DEFAULT '0' COMMENT 'bu_user_info.id',`deviceid` varchar(64) NOT NULL DEFAULT '' COMMENT '设备号',`remark` varchar(255) DEFAULT NULL COMMENT '备注',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,KEY `idx_userid` (`user_id`),KEY `idx_deviceid` (`deviceid`),KEY `idx_businessid_businesstype` (`business_id`,`business_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户弹窗记录';

表说明:

mk_popup_pop_condition:主要是记录有哪些弹窗条件,管理后台中配置弹窗时有用

mk_popup:弹窗配置,运营配置数据就往这里写数据

mk_popup_condition:某个弹窗的弹窗条件(1对多),条件组合配置就是利用该表

mk_popup_log:用户弹窗记录,用于控制弹窗频率

数据样例说明:

弹窗配置

弹窗条件

1) 弹窗1只有1个条件FrequencyCondition,可以理解为只控制弹窗频率为2次/天

2) 弹窗2有3个条件,需要符合场景为小程序首页,地域属性为深圳才弹,并且控制弹窗频率为1次/天

三、代码设计

1.抽象弹窗条件,定义一个接口,其子类对应mk_popup_pop_condition的数据

PopParam说明:

2.核心代码(PopService)中提供1个方法‘用户最优的弹窗’(此处代码过多,只贴核心部分,完整的可以通过gitee查看源码)

设计思想:

1.查询有效期内上架的所有弹窗(按优先级倒排,找到第1个就是最优的了),遍历每个弹窗的多个弹窗条件,判断有1个条件不满足就放弃该弹窗,进入下一个判断

2.运行时替换一些配置的参数,简单的如{userId},复杂的参数就实现ReplaceParam接口,下文有响应结果demo

tips:此处利用CompletableFuture优化性能,实现了多线程并发判断每个弹窗条件,只要有1个条件不满足就立马返回。

3.如何新增1种弹窗条件?

实现接口PopCondition,重写canPop方法,以下为‘场景’弹窗条件的代码

把Bean名称配置到弹窗条件表mk_popup_condition即可使用该条件,无需新增其他代码,也不改动主流程代码。

4.Controller固定入口

5.API定义

前端将弹窗封装成1个公共组件,只需请求固定接口/popup/best即可,在需要弹窗的页面直接引用该组件

入参:

字段

说明

sence

前端每个页面定义1个唯一值

经纬度

非固定参数,可不传

地域信息

非固定参数,可不传

渠道信息

非固定参数,可不传

...

非固定参数,可不传

响应:

字段

说明

model

前端渲染模板定义,需要与前端协商,不同的值代表不同的渲染模板

title

标题,本来想用于背景图的标题,但其实可以把标题设计到背景图中

text

文案,同标题

bgImg

背景图JSON,存储背景图位置的数据和动作

bgImg.imgUrl

背景图

bgImg.type

点击背景图做什么?(close:关闭,api:请求API,subscribe:订阅消息,redirect_http:跳转http链接,redirect_mini:跳转小程序链接,redirect_other_mini:跳转其他小程序链接)

bgImg.value

点击背景图做什么携带的信息

closeBtn

关闭按钮JSON,存储关闭按钮位置的动作(一般都是关闭,也可以做一些骚操作,比如点击关闭按钮跳转到某个页面,或者没有关闭按钮,一定要点击背景图)

popupLogId

弹窗记录ID,本设计中查询到弹窗就会往mk_popup_log插入记录,而不是用户看到弹窗才记录,如果需要了解用户是否有真正看到弹窗,需要与前端协商一起实现,这个ID可以作为下个api的传参

示例:

https://domain.com/popup/best?sence=mini_home&cityCode=440300

四、需求升级

1.点击图片后不跳转到另外1个页面,而是实现特殊逻辑(如拉起小程序订阅消息)

解:需要前端协作实现,增加bgImg.type的定义值,数据通过bgImg.value返回给前端

2.点击图片后不跳转到另外1个页面,而是切换到下一张图片,点击后下一张图片后才跳转页面(比如发优惠券,第一张图片展示立即领取,点击后请求api进行发券,随后切换至去使用的图片,点击后再跳转到对应用券页面)

解:增加下一步操作设计,next结构与最外层的响应一样,类似递归结构

3.图片位置除了背景图,还需要展示其他的信息,比如新人礼包弹窗展示优惠券(需要实现ReplaceParam来完成)

1)实现接口ReplaceParam,bean名称为参数名,重写replace方法,以下为‘新人券包’的demo代码

2)配置demo(即bg_img字段值),{newUserCoupon}是一个动态参数,运行过程中替换掉:

{"imgUrl": "{\"imgUrl\":\"https://img.domain.com/aaa.png\",\"newUserCoupon\":{newUserCoupon}}","type": "api","value": "https://domain.com/api/coupon/recive?id=8"
}

问:imgUrl为什么要配置为json字符串?

答:灵活运用固定字段响应数据给到前端,不同业务场景可定义不同的字段返回,只要跟前端约定好即可

数据响应示例:

4.在运行时给用户做一些弹窗埋点,比如完成某个事件后给用户埋一个弹窗,用户下次进入应用就给他弹

解:增加1张表mk_user_popup,字段与mk_popup差不多,但是不需要配置mk_popup_condition,因为这种弹窗只弹1次已经能满足需求,如有特殊需求也可以特殊设计

CREATE TABLE `mk_user_popup` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',`user_id` int(11) NOT NULL COMMENT 'bu_user_info.id',`begin_time` datetime NOT NULL COMMENT '有效期开始时间',`end_time` datetime NOT NULL COMMENT '有效期结束时间',`status` varchar(8) NOT NULL DEFAULT '' COMMENT '状态(off:下架,on:上架)',`priority` int(11) NOT NULL DEFAULT '0' COMMENT '优先级(值越大,优先级越高)',`title` varchar(32) NOT NULL DEFAULT '' COMMENT '标题',`text` varchar(128) NOT NULL DEFAULT '' COMMENT '文案',`bg_img` varchar(255) NOT NULL DEFAULT '' COMMENT '背景图json数据',`close_btn` varchar(255) NOT NULL DEFAULT '' COMMENT '关闭按钮json数据',`remark` varchar(255) DEFAULT NULL COMMENT '备注',`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`) USING BTREE,KEY `idx_userid` (`user_id`),KEY `idx_userid_begintime` (`user_id`,`begin_time`),KEY `idx_userid_endtime` (`user_id`,`end_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户弹窗';

PopService中增加以下代码

tips:还有些步骤型的逻辑,每步骤都有1个弹窗,比如进行到第1步,给用户埋了1个弹窗,但用户一直没有进入应用,后面流转到第2步了,又埋了1个弹窗。此时如果用户进入应用,就会先后看到2个弹窗,其实第1步的弹窗对于用户来说已经没有意义了(造成不好的用户体验),直接给用户弹第2步的弹窗即可。所以可以设计取消弹窗的操作,在埋第2步弹窗的同时把第1步弹窗取消掉。

扩展思考:

1.弹窗做成不同的表现形式,比如提示框效果,过一段时间自动消失

2.弹窗自动关闭,比如倒计时n秒后自动关闭

怎么样?如果你觉得有用的话,还不快快收藏起来!!!

附:涉及的代码目录

github:https://github.com/897665787/springcloud-template

gitee:springcloud-template: 一个基于springcloud netflix微服务框架,记录了关于微服务开发的一些最佳应用,欢迎大家学习指导。

springcloud-template

└── template-tool

     └──controller

          └── PopupController -- 最优弹窗查询API

     └── popup

          └── PopCondition -- 抽象定义使用条件

          └── PopParam -- 弹窗条件参数

          └── PopService -- 弹窗查询的核心代码

          └── ReplaceParam -- 参数替换接口

          └── condition -- 弹窗条件实现类(条件就新增到这下面)

               └── FrequencyCondition -- 弹窗频率

               └── PushAreaCondition -- 推送地区

               └── ... -- 其他弹窗条件

          └── param -- 参数替换实现类(复杂条件就新增到这下面)

               └──NewUserCouponReplaceParam  -- 新人券包

               └── ... -- 其他参数替换

这篇关于如何设计一个ToC的弹窗的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/218418

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

怎么让1台电脑共享给7人同时流畅设计

在当今的创意设计与数字内容生产领域,图形工作站以其强大的计算能力、专业的图形处理能力和稳定的系统性能,成为了众多设计师、动画师、视频编辑师等创意工作者的必备工具。 设计团队面临资源有限,比如只有一台高性能电脑时,如何高效地让七人同时流畅地进行设计工作,便成为了一个亟待解决的问题。 一、硬件升级与配置 1.高性能处理器(CPU):选择多核、高线程的处理器,例如Intel的至强系列或AMD的Ry

基于51单片机的自动转向修复系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机

SprinBoot+Vue网络商城海鲜市场的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优质创作者,全网30w+

单片机毕业设计基于单片机的智能门禁系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍程序代码部分参考 设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订

Spring的设计⽬标——《Spring技术内幕》

读《Spring技术内幕》第二版,计文柯著。 如果我们要简要地描述Spring的设计⽬标,可以这么说,Spring为开发者提供的是⼀个⼀站式的轻量级应⽤开发框架(平台)。 作为平台,Spring抽象了我们在 许多应⽤开发中遇到的共性问题;同时,作为⼀个轻量级的应⽤开发框架,Spring和传统的J2EE开发相⽐,有其⾃⾝的特点。 通过这些⾃⾝的特点,Spring充分体现了它的设计理念:在

开题报告中的研究方法设计:AI能帮你做什么?

AIPaperGPT,论文写作神器~ https://www.aipapergpt.com/ 大家都准备开题报告了吗?研究方法部分是不是已经让你头疼到抓狂? 别急,这可是大多数人都会遇到的难题!尤其是研究方法设计这一块,选定性还是定量,怎么搞才能符合老师的要求? 每次到这儿,头脑一片空白。 好消息是,现在AI工具火得一塌糊涂,比如ChatGPT,居然能帮你在研究方法这块儿上出点主意。是不

创业者该如何设计公司的股权架构

本文来自七八点联合IT橘子和车库咖啡的一系列关于设计公司股权结构的讲座。 主讲人何德文: 在公司发展的不同阶段,创业者都会面临公司股权架构设计问题: 1.合伙人合伙创业第一天,就会面临股权架构设计问题(合伙人股权设计); 2.公司早期要引入天使资金,会面临股权架构设计问题(天使融资); 3.公司有三五十号人,要激励中层管理与重要技术人员和公司长期走下去,会面临股权架构设计问题(员工股权激

分布式文件系统设计

分布式文件系统是分布式领域的一个基础应用,其中最著名的毫无疑问是 HDFS/GFS。如今该领域已经趋向于成熟,但了解它的设计要点和思想,对我们将来面临类似场景 / 问题时,具有借鉴意义。并且,分布式文件系统并非只有 HDFS/GFS 这一种形态,在它之外,还有其他形态各异、各有千秋的产品形态,对它们的了解,也对扩展我们的视野有所俾益。本文试图分析和思考,在分布式文件系统领域,我们要解决哪些问题、有

(入门篇)JavaScript 网页设计案例浅析-简单的交互式图片轮播

网页设计已经成为了每个前端开发者的必备技能,而 JavaScript 作为前端三大基础之一,更是为网页赋予了互动性和动态效果。本篇文章将通过一个简单的 JavaScript 案例,带你了解网页设计中的一些常见技巧和技术原理。今天就说一说一个常见的图片轮播效果。相信大家在各类电商网站、个人博客或者展示页面中,都看到过这种轮播图。它的核心功能是展示多张图片,并且用户可以通过点击按钮,左右切换图片。