Flask搭建APP统一管理平台
主页效果:
1.从数据库中获取所有APP的信息,每个卡片上展示APP名称、bundle id、版本构建历史记录,系统类型等构建信息
2.支持查询筛选,模糊查询
3.点击历史记录跳转APP历史记录详情页面
历史详情页面效果:
页面包含APP名称,对应构建次数的二维码,APP的系统类型及版本信息、扫码、下载
flashk的框架架构:
和常见的分层差不多类似:
1.主要用到的数据、模板、路由
2.数据是用的DBUtils数据库连接池
通用app下载页面:
单次构建版本下载:
贴几个主要的代码:
css文件,js文件,感兴趣的可以留言交流。
app_main.py:
from app.dao import read_sql as sql
from flask import Flask, render_template app = Flask('app') @app.route('/')
def get_index():
mysql_l = sql.deal_mysql('get_app_new.sql')
return render_template('/post/app_main_detail.html', data=mysql_l, len_data=len(mysql_l)) @app.route('/<app_name>')
def get_index_app(app_name):
if app_name:
na_app = list([app_name])
mysql_l = sql.deal_mysql('get_app_new_search.sql', na_app)
else:
mysql_l = sql.deal_mysql('get_app_new.sql')
return render_template('/post/app_main_detail.html', data=mysql_l, len_data=len(mysql_l)) @app.route('/app_detail/<app_name>/<path:qr_name>')
def get_app_detail(app_name, qr_name):
name_app = list([app_name])
app_detail = []
android_qa = sql.deal_mysql('get_android_qa.sql', name_app)
android_online = sql.deal_mysql('get_android_online.sql', name_app)
ios_test = sql.deal_mysql('get_ios_test.sql', name_app)
ios_product = sql.deal_mysql('get_ios_product.sql', name_app)
app_detail.append(android_qa)
app_detail.append(android_online)
app_detail.append(ios_test)
app_detail.append(ios_product) return render_template('/post/app_detail.html', data=app_detail, q_name=qr_name, name=app_name) if __name__ == '__main__':
app.run(host='0.0.0.0', port='9000', debug=True)
app_detail.html【含3d效果的css】
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="https://pkgcdn.thecover.cn/pkg/cover/css/app_manger/1.5.0/3d.css">
<link rel="stylesheet" type="text/css" href="https://pkgcdn.thecover.cn/pkg/cover/css/app_manger/1.5.0/htmleaf-demo.css">
<link rel="stylesheet" type="text/css" href="https://pkgcdn.thecover.cn/pkg/cover/css/app_manger/1.5.0/tabs-basic.css">
</head> <body>
<div class="container">
<div class="card">
<div class="img" align="center" >
<div style="color: #1183fb;">
<h3>{{name}}</h3>
</div>
<img id="show_img" width="255", height="255" src="{{q_name}}"/>
<div style="color: #32a3b1;">
<h4> 扫描二维码下载[浏览器扫码]</h4>
</div> </div>
<div class="contentBx" align="right">
</div>
<div class="htmleaf-container">
<div class="tabs-basic">
<ul>
<li>
<a class="tab-active" data-index="0" href="#">Android(测)</a>
</li>
<li>
<a data-index="1" href="#">Android(正)</a>
</li>
<li>
<a data-index="2" href="#">iOS(测)</a>
</li>
<li>
<a data-index="3" href="#">iOS(正)</a>
</li>
</ul> <div class="tabs-content-placeholder">
<div class="tab-content-active">
<table border="0" cellpadding="2" style="border-collapse:collapse;margin-top:1px" align="center">
<tr height="28px">
<td align="center"><font size="1"><strong>版本号</strong></font></td>
<td align="center"><font size="1"><strong>次数</strong></font></td>
<td align="center"><font size="1"><strong>类型</strong></font></td>
<td align="center"><font size="1"><strong>构建时间</strong></font></td>
<td colspan="100" align="center"><font size="1"><strong>操作</strong></font></td>
</tr>
{% for i in data[0] %}
<tr>
<td align="center"><font size="1">{{i[1]}}</font></td>
<td align="center"><font size="1">{{i[2]}}</font></td>
<td align="center"><font size="1">{{i[3]}}</font></td>
<td align="center"><font size="1">{{i[6]}}</font></td>
<td><a class="ercode-img" data-img="{{i[4]}}"><font size="1" >扫码</font></a></td>
<td><a href="{{i[5]}}"><font size="1">下载</font></a></td>
</tr>
{% endfor %}
</table>
</div> <div>
<table border="0" cellpadding="2" style="border-collapse:collapse;margin-top:1px" align="center">
<tr height="28px">
<td align="center"><font size="1"><strong>版本号</strong></font></td>
<td align="center"><font size="1"><strong>次数</strong></font></td>
<td align="center"><font size="1"><strong>类型</strong></font></td>
<td align="center"><font size="1"><strong>构建时间</strong></font></td>
<td colspan="2" align="center"><font size="1"><strong>操作</strong></font></td>
</tr>
{% for i in data[1] %}
<tr>
<td align="center"><font size="1">{{i[1]}}</font></td>
<td align="center"><font size="1">{{i[2]}}</font></td>
<td align="center"><font size="1">{{i[3]}}</font></td>
<td align="center"><font size="1">{{i[6]}}</font></td>
<td align="right"><a class="ercode-img" data-img="{{i[4]}}"><font size="1">扫码</font></a></td>
<td align="left"><a href="{{i[5]}}"><font size="1">下载</font></a></td>
</tr>
{% endfor %}
</table>
</div> <div>
<table border="0" cellpadding="2" style="border-collapse:collapse;margin-top:1px" align="center">
<tr height="28px">
<td width="50" height="5" align="center"><font size="1"><strong>版本号</strong></font></td>
<td width="80" height="5" align="center"><font size="1"><strong>次数</strong></font></td>
<td width="40" height="5" align="center"><font size="1"><strong>类型</strong></font></td>
<td width="160" height="5" align="center"><font size="1"><strong>构建时间</strong></font></td>
<td width="80" height="5" align="center"><font size="1"><strong>操作</strong></font></td>
</tr>
{% for i in data[2] %}
<tr>
<td align="center"><font size="1">{{i[1]}}</font></td>
<td align="center"><font size="1">{{i[2]}}</font></td>
<td align="center"><font size="1">{{i[3]}}</font></td>
<td align="center"><font size="1">{{i[6]}}</font></td>
<td align="center"><a class="ercode-img" data-img="{{i[4]}}"><font size="1">扫码</font></a></td>
</tr>
{% endfor %}
</table>
</div> <div>
<table border="0" cellpadding="2" style="border-collapse:collapse;margin-top:1px" align="center">
<tr height="28px">
<td width="50" height="5" align="center"><font size="1"><strong>版本号</strong></font></td>
<td width="80" height="5" align="center"><font size="1"><strong>次数</strong></font></td>
<td width="40" height="5" align="center"><font size="1"><strong>类型</strong></font></td>
<td width="160" height="5" align="center"><font size="1"><strong>构建时间</strong></font></td>
<td width="80" height="5" align="center"><font size="1"><strong>操作</strong></font></td>
</tr>
{% for i in data[3] %}
<tr>
<td align="center"><font size="1">{{i[1]}}</font></td>
<td align="center"><font size="1">{{i[2]}}</font></td>
<td align="center"><font size="1">{{i[3]}}</font></td>
<td align="center"><font size="1">{{i[6]}}</font></td>
<td align="center"><a class="ercode-img" data-img="{{i[4]}}"><font size="1">扫码</font></a></td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
</div>
<script src="https://pkgcdn.thecover.cn/pkg/cover/js/app_manger/1.5.0/jquery.js"></script>
<script type="text/javascript"> $(document).ready(function() { var widget = $('.tabs-basic'); var tabs = widget.find('ul a'),
content = widget.find('.tabs-content-placeholder > div'); tabs.on('click', function (e) { e.preventDefault(); // Get the data-index attribute, and show the matching content div var index = $(this).data('index'); tabs.removeClass('tab-active');
content.removeClass('tab-content-active'); $(this).addClass('tab-active');
content.eq(index).addClass('tab-content-active'); }); });
$('.ercode-img').on('click', function(){
var img = $(this).attr('data-img');
$('#show_img').attr('src', img);
})
</script>
</div>
</div>
</body> </html>
app_main_detail.html【css含搜索动画效果、卡片浮动效果】
<!DOCTYPE html>
<html lang="zn">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="initial-scale=1, maximum-scale=3, minimum-scale=1, user-scalable=no">
<link rel="stylesheet" href="https://pkgcdn.thecover.cn/pkg/cover/css/app_manger/1.5.0/zui.min.css">
<script src="https://pkgcdn.thecover.cn/pkg/cover/js/app_manger/1.5.0/jquery.js"></script>
<link rel="stylesheet" href="https://pkgcdn.thecover.cn/pkg/cover/css/app_manger/1.5.0/source_end.css" type="text/css" media="screen">
<link rel="stylesheet" href="https://pkgcdn.thecover.cn/pkg/cover/css/app_manger/1.0.0/normalize.css" type="text/css" media="screen">
<link rel="stylesheet" href="https://pkgcdn.thecover.cn/pkg/cover/css/app_manger/1.2.0/search-form.css" type="text/css" media="screen"> <title>Cover-App Testing Platform</title> </head>
<body>
<div class="title">
<h1> 封面APP统一管理平台 </h1>
<p> 封面传媒融媒体APP、内部APP、封巢、直播等应用统一管理平台</p>
</div>
<div>
<section class="htmleaf-container">
<form onsubmit="submitFn(this, event); " method = "post">
<div class="search-wrapper">
<div class="input-holder">
<input type="text" class="search-input" placeholder="请输入APP名称,支持模糊查询" />
<button class="search-icon" onclick="searchToggle(this, event);"><span></span></button>
</div>
<span class="close" onclick="searchToggle(this, event);"></span>
<div class="result-container">
</div>
</div> </form>
</section>
</div> <script type="text/javascript">
function searchToggle(obj, evt){
var container = $(obj).closest('.search-wrapper'); if(!container.hasClass('active')){
container.addClass('active');
evt.preventDefault();
}
else if(container.hasClass('active') && $(obj).closest('.input-holder').length == 0){
container.removeClass('active');
// clear input
container.find('.search-input').val('');
// clear and hide result container when we press close
container.find('.result-container').fadeOut(100, function(){$(this).empty();});
}
} function submitFn(obj, evt){
value = $(obj).find('.search-input').val().trim();
if(!value.length){
window.location.href = "/";
}
else{
window.location.href = "/" + value;
}
evt.preventDefault();
}
</script> <div class="col col-12" data-grid="12" data-row="4" style="top: 95px">
<div id="block1261" class="block" >
{% for i in range(len_data) %}
{% if i % 4 == 0 %}
<div class="see-wrap">
<div class="container">
<div class="row">
<div class="col-md-3">
<div class="see-box see">
<div class="see-top">
<h4> {{data[i][0]}} </h4>
<p> bundle id:<br>{{data[i][3]}} </p>
<a href="/app_detail/{{data[i][0]}}/{{data[i][9]}}" target="_blank">历史记录</a>
</div>
<div class="see-bottom">
<p><em>•</em><span>For Build {{data[i][1]}} ({{data[i][2]}})</span> </p>
<p><em>•</em><span>构建版本: {{data[i][4]}}(id-{{data[i][5]}})</span> </p>
<p><em>•</em><span>构建时间: {{data[i][6]}}</span> </p>
<p><em>•</em><span>更新环境: {{data[i][8]}}</span> </p>
</div>
</div>
</div>
{% elif i% 4 == 3 %}
<div class="col-md-3">
<div class="see-box see">
<div class="see-top">
<h4> {{data[i][0]}} </h4>
<p> bundle id:<br>{{data[i][3]}} </p>
<a href="/app_detail/{{data[i][0]}}/{{data[i][9]}}" target="_blank">历史记录</a>
</div>
<div class="see-bottom">
<p><em>•</em><span>For Build {{data[i][1]}} ({{data[i][2]}})</span> </p>
<p><em>•</em><span>构建版本: {{data[i][4]}}(id-{{data[i][5]}})</span> </p>
<p><em>•</em><span>构建时间: {{data[i][6]}}</span> </p>
<p><em>•</em><span>更新环境: {{data[i][8]}}</span> </p>
</div>
</div>
</div>
</div>
</div>
</div>
{% else %}
<div class="col-md-3">
<div class="see-box see">
<div class="see-top">
<h4> {{data[i][0]}} </h4>
<p> bundle id:<br>{{data[i][3]}} </p>
<a href="/app_detail/{{data[i][0]}}/{{data[i][9]}}" target="_blank">历史记录</a>
</div>
<div class="see-bottom">
<p><em>•</em><span>For Build {{data[i][1]}} ({{data[i][2]}})</span> </p>
<p><em>•</em><span>构建版本: {{data[i][4]}}(id-{{data[i][5]}})</span> </p>
<p><em>•</em><span>构建时间: {{data[i][6]}}</span> </p>
<p><em>•</em><span>更新环境: {{data[i][8]}}</span> </p>
</div>
</div>
</div>
{% endif %}
{% endfor %}
</div>
</div>
</body>
</html>
flask_mysql.py
import pymysql
from DBUtils.PooledDB import PooledDB
from app.dao import db_config as config class Database:
def __init__(self, *db):
# mysql数据库
self.host = config.mysqlInfo['host']
self.port = config.mysqlInfo['port']
self.user = config.mysqlInfo['user']
self.pwd = config.mysqlInfo['passwd']
self.db = config.mysqlInfo['db']
self.charset = config.mysqlInfo['charset']
self.create_pool() def create_pool(self):
self.Pool = PooledDB(creator=pymysql, mincached=2, maxcached=5, maxshared=3, maxconnections=6, blocking=True, host=self.host, port=self.port,
user=self.user, password=self.pwd, database=self.db, charset=self.charset) def get_connect(self):
self.conn = self.Pool.connection()
cur = self.conn.cursor()
if not cur:
raise NameError("数据库连接不上")
else:
return cur # 查询sql
def exec_query(self, sql):
cur = self.get_connect()
cur.execute(sql)
re_list = cur.fetchall()
cur.close()
self.conn.close()
return re_list # 非查询的sql,增删改
def exec_no_query(self, sql):
cur = self.get_connect()
cur.execute(sql)
self.conn.commit()
cur.close()
self.conn.close() # 显示查询中的第一条记录
def show_first(self, sql):
cur = self.get_connect()
cur.execute(sql)
result_first = cur.fetchone()
cur.close()
self.conn.close()
return result_first # 显示查询出的所有结果
def show_all(self, sql):
cur = self.get_connect()
cur.execute(sql)
result_all = cur.fetchall()
cur.close()
self.conn.close()
return result_all if __name__ == "__main__":
d = Database()
sql = """
"""
for i in range(100):
a = d.show_all(sql)
print(a)
read_sql.py
# coding = utf-8
# 禅道项目度量--读取sql脚本 import os
from app.dao import flask_mysql as mysql pl = os.getcwd().split('cover_app_platform')
path_pl = pl[0] + "cover_app_platform\\app\\dao\\sql_scripts\\" # 读取sql脚本
def read_sql(f):
"""
:param f: 需要读取sql脚本的文件
:return: 返回读取后的sql语句
"""
f_path = path_pl + f try:
fi = open(f_path, "r", encoding='UTF-8')
fp = fi.readlines()
fi.close()
sql_script = ''
for i in fp:
sql_script += i
return sql_script
except FileNotFoundError as ep:
return ep def deal_mysql(f, pa=''):
"""
:param f:
:param pa:
:return:
"""
d = mysql.Database()
sql = read_sql(f)
print(pa)
if len(pa) != 0:
for i in pa:
sql = sql.replace('@@@@', i)
results = d.show_all(sql)
tl = list(results)
return tl
欢迎题留言交流
Flask搭建APP统一管理平台的更多相关文章
- 如何用Baas快速在腾讯云上开发小程序-系列2:搭建Phabricator开发管理平台
版权声明:本文由贺嘉 原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/905333001487424158 来源:腾云阁 h ...
- API统一管理平台-YApi
前言:开发过程中,会产生很多接口对接操作,这个时候可能需要一个接口管理平台管理已经开发好的接口方便业务对接. 一.概述 YApi 是高效.易用.功能强大的 api 管理平台,旨在为开发.产品.测试人员 ...
- 搭建用例管理平台phpstudy+testlink代替Apache+MySQL+PHP环境,以及testlink搭建环境报错修复
公司需要搭建一个用例管理平台,环境搭建Apache+MySQL+PHP环境 哇一看就是需要花很长时间去搭建环境,本来我也在用这样的笨方法,不小心被公司开发看到,经人家一提点,哎呀妈呀发现自己以前的方法 ...
- Kingbase数据库web统一管理平台
1.安装Kingbase金仓数据库后,通过打开web管理平台,可以方便的进行远程维护. 示例地址:https://192.168.0.1:54328/webstudio 2.输入用户名密码登 ...
- 从零开始搭建gitea代码管理平台
Gitea,一款极易搭建的Git自助服务.如其名,Git with a cup of tea.跨平台的开源服务,支持Linux.Windows.macOS和ARM平台.配置要求低,甚至可以运行在树莓派 ...
- python实例编写(6)--引入unittest测试框架,构造测试集批量测试(以微信统一管理平台为例)
---恢复内容开始--- 一.python单元测试实例介绍 unittest框架又叫PyUnit框架,是python的单元测试框架. 先介绍一个普通的单元测试(不用unittest框架)的实例: 首先 ...
- 利用RAP搭建可视化接口管理平台
环境:CentOS7 jdk:1.7.0_51 redis:3.2.8 mysql:5.6 tomcat:8.0 安装过程: 依赖组件安装: 安装jdk.redis.mysql.tomcat过程省略. ...
- Docker搭建Gitlab代码管理平台
一.Gitlab的安装 宿主机环境: CentOS 7 docker docker-compose 1.查找镜像 docker search gitlab 2.拉取镜像 docker pull git ...
- vue-element-admin改造接入后台,搭建有来商城youlai-mall后台前端管理平台
一. 前言 本篇基于有来商城youlai-mall微服务项目,搭建后台前端管理平台,技术选型希望通过本篇文章你可以,技术解决方案选择了vue-element-admin.希望通过本篇文章你可以vue- ...
- Mobox 知识管理平台助推市长质量奖
Mobox 知识管理平台助推市长质量奖 引言: 在过去的十多年中,国际上在管理领域出现两股浪潮:一是许多国家和地区采取设立政府质量奖的方式,来改善企业管理绩效,提升区域整体竞争力:二是这些国家和地区的 ...
随机推荐
- MySQL学习之初识数据库
•数据库的相关概念 DB : 数据库,保存一组有组织的数据的容器 DBMS : 数据库管理系统,又称为数据库软件(产品),用于管理 DB 中的数据 SQL : 结构化查询语言,用于和 DBMS 通信的 ...
- Java中枚举配合switch语句用法-2022新项目
一.业务场景 项目开发中经常会遇到多条件判断的情况,如果判断条件少的话使用if/elseif/else还比较好处理,如果判断条件多的话,则在使用这种语句就不太合适. 如果是自定义的一些内容,比如不同的 ...
- KEIL5新建工程0810
在保存各种项目的文件夹内创建一个项目文件夹1新建工程到文件夹1 选择芯片添加工程的必要文件(固件库) STM32程序是从启动文件开始,复制这些文件到文件夹A的新建Start文件夹下 stm32f10x ...
- history = his + story 男性史 = 历史 学单词
history = his + story 男性史 = 历史 早先还有 herstory 由于女性地位底下,就由 history 代表历史了. 然后 history 由拉丁文过来 story 从法语过 ...
- LeNet-5 论文及原理分析(笨鸟角度)
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明 本文作为本人csdn blog的主站的备份.(Bl ...
- 3DCAT亮相WAIC 2022浦东分会场——元宇宙博览会暨数字光影大会
以"智联世界 元生无界"为主题的2022世界人工智能大会于9月3日下午圆满闭幕.与此同时,由上海市多媒体行业协会.深圳市数字创意与多媒体行业协会主办,上海天盛会展有限公司承办的WA ...
- 记录--HTML问题:如何实现分享URL预览?
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 1. 需求分析 为了提高用户对页面链接分享的体验,需要对分享链接做一些处理. 以 Telegram(国外某一通讯软件) 为例,当在 Tel ...
- 从静态到动态化,Python数据可视化中的Matplotlib和Seaborn
本文分享自华为云社区<Python数据可视化大揭秘:Matplotlib和Seaborn高效应用指南>,作者: 柠檬味拥抱. 安装Matplotlib和Seaborn 首先,确保你已经安装 ...
- Linux修改账户密码
打开终端并登录到要修改密码的账户 输入 passwd 命令,然后 Enter 系统会提示你输入 Current password. 如果是第一次登录或者忘记密码,使用 passwd -d userna ...
- SpringBoot2使用hikari报 Failed to validate connection com.mysql.cj.jdbc.ConnectionImpl
SpringBoot2配置文件有变化,需要更改配置 #datasource spring.datasource.driver-class-name=com.mysql.jdbc.Driver spri ...