在线取号排队的魅力所在与实用性 - 教你构建在线取号排队小程序 - 飞书官网
解决方案

在线取号排队的魅力所在与实用性-教你构建在线取号排队小程序

飞书

2024-12-23

推荐理由​
一、关于我​
二、需求分析​
三、方案调研​
四、开发流程​
五、更多相关开发心得​
作者:潘龙(phiron.pan)​
推荐理由​
超好用的取号排队小程序,能够在线实时看到自己的号码和排队进度,不但方便你先忙其他的事情,而且不需要花太多的时间在排队上面,等快排到时再去现场,大大节省了时间!​
​
​
一、关于我​
大家好,我是一位热衷于全栈开发的工程师,一直对折腾和学习新技术充满热情。很高兴今天有机会与大家分享一下我在飞书上打造的一款在线取号排队小程序。通过这个小程序,我们可以轻松享受到更为便捷的服务体验和创新的排队方式。让我们一同探索这个在线取号排队小程序,为未来的服务体验带来更多可能性。​
​
二、需求分析​
随着生活节奏的加快,人们对于服务效率的需求日益增长。在线取号排队小程序旨在通过数字化的方式提高服务行业的效率,降低用户等待时间,实现更便捷的服务体验。​
​
三、方案调研​
随着飞书等即时通讯工具的普及,将在线取号排队系统与飞书集成,可以为用户提供更便捷的服务体验。通过扫码免登录的方式,用户可以轻松取号,同时通过飞书机器人提供实时的排队通知。​
​
四、开发流程​
1.小程序整体功能比较简洁大方,取号页面和排队页面,并且添加了一个管理员页面,方便管理员过号和销号。​
2.取号页面,我们提供了三种类型的服务一个是电脑清灰,和手机贴膜,还有现场问诊服务,这样分开来方便大家细化自己的需求,考虑到号码队列更新的比较快,在首页实时展示剩余号码,所以我使用了redis缓存三个键值对,然后取号时触发-1,过号或者取消排队则+1,这样很方便而且读取更快:​
​
​
mredis.incr("queue_type_1") #自增+1​
mredis.decr("queue_type_1") #自减-1​
​
3.手机贴膜取号需要弹窗让用户选择已知的贴膜和问诊取号需要弹窗让用户填写问诊的问题,如下图所示:​
取号代码如下:​
​
​
# 生成清灰手机贴膜问诊排队号​
def generate_clear_film_number(user_id, queue_type, queue_number, model,​
mold):​
# 清灰​
if queue_type == 1:​
# 创建游标对象​
cursor = conn.cursor()​
try:​
# 开始事务​
conn.begin()​
​
# 重新取号 把号改成取消​
if queue_number is not None:​
update_sql = "UPDATE h_queue_clear SET status = 4 WHERE id = %s"​
cursor.execute(update_sql, queue_number)​
mredis.incr("queue_type_1")​
​
# 判断是否已经有号 有号则不需要取号 要先把这个号改成取消状态​
select_sql = "SELECT * FROM h_queue_clear WHERE status = 1 AND user_id = %s"​
cursor.execute(select_sql,​
(user_id))​
one = cursor.fetchone()​
​
if one is not None:​
return {'error': True, 'msg': "您已经有在排队中的号码,请点击底部排队按钮查看", 'data': None}​
​
# 先校验是否有号​
queue_type_1 = mredis.str_get("queue_type_1")​
if int(queue_type_1.decode('utf-8')) <= 0:​
return {'error': True, 'msg': "可预约号码不足,请耐心等待放号", 'data': None}​
​
insert_sql = "INSERT INTO h_queue_clear (user_id,create_date,status) VALUES (%s, %s, 1)"​
cursor.execute(insert_sql,​
(user_id, datetime.now(tz)))​
​
mredis.decr("queue_type_1")​
​
return {'error': False, 'msg': "success", 'data': None}​
​
except Exception as e:​
print("e", e)​
conn.rollback() # 出现异常时回滚事务​
return {'error': True, 'msg': "An error occurred while processing the request", 'data': None}​
finally:​
cursor.close()​
conn.commit() # 提交事务​
elif queue_type == 2:​
# 贴膜​
# 创建游标对象​
cursor = conn.cursor()​
try:​
# 开始事务​
conn.begin()​
​
# 重新取号 把号改成取消​
if queue_number is not None:​
update_sql = "UPDATE h_queue_film SET status = 4 WHERE id = %s"​
cursor.execute(update_sql, queue_number)​
mredis.incr("queue_type_2")​
​
# 判断是否已经有号 有号则重新取号 要先把这个号改成取消状态​
select_sql = "SELECT * FROM h_queue_film WHERE status = 1 AND user_id = %s"​
cursor.execute(select_sql,​
(user_id))​
one = cursor.fetchone()​
​
if one is not None:​
return {'error': True, 'msg': "您已经有在排队中的号码,请点击底部排队按钮查看", 'data': None}​
​
# 先校验是否有号​
queue_type_2 = mredis.str_get("queue_type_2")​
if int(queue_type_2.decode('utf-8')) <= 0:​
return {'error': True, 'msg': "可预约号码不足,请耐心等待放号", 'data': None}​
​
insert_sql = "INSERT INTO h_queue_film (user_id,create_date,status,model) VALUES (%s, %s, 1,%s)"​
cursor.execute(insert_sql,​
(user_id, datetime.now(tz), model))​
mredis.decr("queue_type_2")​
​
return {'error': False, 'msg': "success", 'data': None}​
​
except Exception as e:​
print("e", e)​
conn.rollback() # 出现异常时回滚事务​
return {'error': True, 'msg': "An error occurred while processing the request", 'data': None}​
finally:​
cursor.close()​
conn.commit() # 提交事务​
​
else:​
# 问诊​
# 创建游标对象​
cursor = conn.cursor()​
try:​
# 开始事务​
conn.begin()​
​
# 重新取号 把号改成取消​
if queue_number is not None:​
update_sql = "UPDATE h_queue_ig SET status = 4 WHERE id = %s"​
cursor.execute(update_sql, queue_number)​
mredis.incr("queue_type_3")​
​
# 判断是否已经有号 有号则重新取号 要先把这个号改成取消状态​
select_sql = "SELECT * FROM h_queue_ig WHERE status = 1 AND user_id = %s"​
cursor.execute(select_sql,​
(user_id))​
one = cursor.fetchone()​
​
if one is not None:​
return {'error': True, 'msg': "您已经有在排队中的号码,请点击底部排队按钮查看", 'data': None}​
​
# 先校验是否有号​
queue_type_3 = mredis.str_get("queue_type_3")​
if int(queue_type_3.decode('utf-8')) <= 0:​
return {'error': True, 'msg': "可预约号码不足,请耐心等待放号", 'data': None}​
​
insert_sql = "INSERT INTO h_queue_ig (user_id,create_date,status,mold) VALUES (%s, %s, 1,%s)"​
cursor.execute(insert_sql,​
(user_id, datetime.now(tz), mold))​
​
mredis.decr("queue_type_3")​
​
return {'error': False, 'msg': "success", 'data': None}​
​
except Exception as e:​
print("e", e)​
conn.rollback() # 出现异常时回滚事务​
return {'error': True, 'msg': "An error occurred while processing the request", 'data': None}​
finally:​
cursor.close()​
conn.commit() # 提交事务​
4.然后是排队页面,可以实时看到自己的号码和排队的进度,这样就可以方便你可以先忙其他的事情,不需要花太多的时间在排队上面,等快到你的时候再去现场,大大节省了时间:​
排队的代码有一点复杂,可以参考如下:​
​
​
# 查询 清灰和贴膜 问诊 当前用户的状态​
def query_status(user_id, queue_type):​
# 清灰​
if queue_type == 1:​
# 创建游标对象​
cursor = conn.cursor()​
​
# 查询自己的号​
select_sql = "SELECT * FROM h_queue_clear WHERE status in(1,2) AND user_id = %s Order By create_date DESC LIMIT 1"​
cursor.execute(select_sql, user_id)​
your_number = cursor.fetchone()​
​
if your_number is None:​
return None​
​
# 查询当前第一位的号码​
select_sql = "SELECT * FROM h_queue_clear WHERE status = 1 ORDER BY id ASC LIMIT 1"​
cursor.execute(select_sql)​
one = cursor.fetchone()​
​
# 查询你的号前面排了多少位​
# 查询第一位到我的位置(我前面还有多少位)​
cursor.execute("SELECT COUNT(*) as number FROM h_queue_clear WHERE status = 1 AND id < %s",​
(your_number["id"]))​
before_number = cursor.fetchone()​
​
# 关闭链接对象​
cursor.close()​
​
data = {​
"first_number": one["id"] if one is not None else 0,​
"before_number": before_number["number"],​
"queue_number": your_number["id"],​
"status": your_number["status"]​
}​
​
return data​
elif queue_type == 2:​
# 创建游标对象​
cursor = conn.cursor()​
​
# 查询自己的号​
select_sql = "SELECT * FROM h_queue_film WHERE status in(1,2) AND user_id = %s Order By create_date DESC LIMIT 1"​
cursor.execute(select_sql, user_id)​
your_number = cursor.fetchone()​
​
if your_number is None:​
return None​
​
# 查询当前第一位的号码​
select_sql = "SELECT * FROM h_queue_film WHERE status = 1 ORDER BY id ASC LIMIT 1"​
cursor.execute(select_sql)​
one = cursor.fetchone()​
​
# 查询你的号前面排了多少位​
# 查询第一位到我的位置(我前面还有多少位)​
cursor.execute("SELECT COUNT(*) as number FROM h_queue_film WHERE status = 1 AND id < %s",​
(your_number["id"]))​
before_number = cursor.fetchone()​
​
# 关闭链接对象​
cursor.close()​
​
data = {​
"first_number": one["id"] if one is not None else 0,​
"before_number": before_number["number"],​
"queue_number": your_number["id"],​
"status": your_number["status"]​
}​
​
return data​
else:​
# 创建游标对象​
cursor = conn.cursor()​
​
# 查询自己的号​
select_sql = "SELECT * FROM h_queue_ig WHERE status in(1,2) AND user_id = %s Order By create_date DESC LIMIT 1"​
cursor.execute(select_sql, user_id)​
your_number = cursor.fetchone()​
​
if your_number is None:​
return None​
​
# 查询当前第一位的号码​
select_sql = "SELECT * FROM h_queue_ig WHERE status = 1 ORDER BY id ASC LIMIT 1"​
cursor.execute(select_sql)​
one = cursor.fetchone()​
​
# 查询你的号前面排了多少位​
# 查询第一位到我的位置(我前面还有多少位)​
cursor.execute("SELECT COUNT(*) as number FROM h_queue_ig WHERE status = 1 AND id < %s",​
(your_number["id"]))​
before_number = cursor.fetchone()​
​
# 关闭链接对象​
cursor.close()​
​
data = {​
"first_number": one["id"] if one is not None else 0,​
"before_number": before_number["number"],​
"queue_number": your_number["id"],​
"status": your_number["status"]​
}​
​
return data​
​
5.管理员页面,方便管理员过号和销号等其他操作,当管理员销号或者过号的时候,我们会异步发出飞书机器人卡片通知消息给队伍前10位,这样就能方便用户及时赶到现场排队:​
​
五、更多相关开发心得​
在开发过程中,我们确实面临了许多挑战,但通过灵活运用思维,积极搜索解决方案,以及请教身边经验丰富的大佬,成功克服了许多难题。在遇到不懂的问题时,我发现网络搜索和向ChatGPT提问是获取信息的高效途径,而对于一些特定的飞书开发问题,官方文档和热情耐心的客服都是不可或缺的资源。​
特别值得一提的是,团队的协作和沟通对项目的推进起到了至关重要的作用。我们经常进行短而高效的站会,及时发现和解决问题,保持团队的合作默契。​
关于飞书开发的更多细节,我建议查阅官方文档,并积极与客服进行沟通。客服团队的热情和耐心为我们提供了很大的支持。​
​
​
预约飞书企业效能顾问 深度诊断企业痛点,定制专属 AI 办公方案

先进团队,先用飞书

欢迎联系我们,飞书效能顾问将为您提供全力支持
分享先进工作方式
输送行业最佳实践
全面协助组织提效
标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题标题

字节跳动旗下 AI 工作平台

联系我们立即试用