测试开发【提测平台】分享12-掌握日期组件&列表状态格式化最终实现提测管理多条件搜索展示功能
微信搜索【大奇测试开】,关注这个坚持分享测试开发干货的家伙。
本章内容思维导图如下,由于需要各种状态下的菜单操作,所以需要先实现提测信息的列表基础页面,然后再推进其他需求开发
基本知识点学习
DatePicker 日期组件
Element ui 组件中有两个时间相关的控件,一个是 TimePicker 组件,以十分秒维度,另一个是 DatePicker 组件,以年月日时分秒维度,两者用法基本相同,本篇开发用到的是DatePicker,它的基本使用方法为
<el-date-picker
v-model="绑定变量值"
align="right"
type="date"
placeholder="选择日期">
</el-date-picker>
其中v-model一如即往的是指绑定的变量参数,align是对其的方向,placeholder标题没有值的时候提示信息,最重要的type是指日期的样式和类型,本例子选中时间后将展示如:2021-10-10 的格式时间,其他类型还报告年、月、星期、时间范围月范围等,实战开发还会用到带快捷选项 picker-options 属性,即可以日期选项左侧可以设定和快捷选项一个范围,比如近一个月,近三个月等,样式如,更多内容参考官方例子 [注解-1]
Select 选择器
这个组件在之前的文章是讲过的,当时直接举例没有讲清楚具体使用场景,这里举例说明下:
场景1: 如果是少量比较固定的,可以直接前端写<el-option key="",value="",label=""/>
场景2: 如果是动态固定数据,则用v-for的语法绑定一个list选项(用到之前请求接口赋予)
场景3: 如果是动态大量数据,可以使用远程搜索模式,即数据关键词后时时请求接口后台查询后显示,如公司用户查询选择。
选项中key关键词、value表示选择后的值,lebel为实际展示的值
SQL联合表查询
依稀记得在上学的时候设计数据表的时候,尤其是关系型数据库表,有很多的关联表,也很规范的使用外键等,不过目前从工作后,尤其是近几年很少看到这么严谨了,基本上如果查询少就在新表中多个相同字段,否则也是简单关联查询,语法格式为 select A.*,B.字段 from A, B where A.id=B.aid
在项目编写后端多条件查询语句的时候,最好是设计相关表后,插入几条关联数据,在数据库工具里先写好关联查询语句,测试通过后在去拼写后端请求代码,千万不要自信满满,笔记就是直接上代码,可以由于空格,语法等就要浪费好多时间去一点点debug,就本文带有时间范围的联合表查询,可以先完全先写sql语句,进行测试,然后再粘贴到代码里实现,比如是我先实现的语句验证OK。
需求功能实现
提测列表的搜索和展示需求其实和之前分享的应用列表管理非常类似,这里就不再贴需求原型,直接给出实现部分和注意点,最后看下整体实现。
服务查询接口
1. 查询接口的数据字典
直接给出如下,方便大家直接调试
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; -- ----------------------------
-- Table structure for request
-- ----------------------------
DROP TABLE IF EXISTS `request`;
CREATE TABLE `request` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`title` varchar(200) DEFAULT NULL COMMENT '提测标题',
`appId` varchar(50) DEFAULT NULL COMMENT '应用服务',
`developer` varchar(255) DEFAULT NULL COMMENT '提测RD',
`tester` varchar(255) DEFAULT NULL COMMENT '测试QA',
`CcMail` varchar(500) DEFAULT NULL COMMENT '关系人',
`verison` varchar(100) DEFAULT NULL COMMENT '提测版本',
`type` tinyint(1) DEFAULT NULL COMMENT '提测类型 1.功能 2.性能 3.安全',
`scope` text COMMENT '测试说明',
`gitCode` varchar(200) DEFAULT NULL COMMENT '项目代码',
`wiki` varchar(200) DEFAULT NULL COMMENT '产品文档',
`more` text COMMENT '是否发送邮件,0未操作,1成功,2失败',
`status` tinyint(1) DEFAULT NULL COMMENT '测试状态 1-已提测 2-测试中 3-通过 4-失败 9-废弃',
`sendEmail` tinyint(1) DEFAULT NULL COMMENT '是否发送消息,0未操作,1成功,2失败',
`isDel` tinyint(1) DEFAULT '0' COMMENT '状态0正常1删除',
`createUser` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '创建人',
`createDate` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updateUser` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '修改人',
`updateDate` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; SET FOREIGN_KEY_CHECKS = 1;
2. 后端提测数据查询接口
新建文件testmanager.py,沿用数据链接池不变,这里主要注意代码里的拼接,按照知识点里说最好现在把测试语句在数据库查询命令行中测试通过,注意需要支持分页。
# -*- coding:utf-8 -*-
# testmanager.py from flask import Blueprint
from dbutils.pooled_db import PooledDB
from configs import config, format from flask import request
import pymysql.cursors
import json # 使用数据库连接池的方式链接数据库,提高资源利用率
pool = PooledDB(pymysql, mincached=2, maxcached=5,host=config.MYSQL_HOST, port=config.MYSQL_PORT,
user=config.MYSQL_USER, passwd= config.MYSQL_PASSWORD, database=config.MYSQL_DATABASE,
cursorclass=pymysql.cursors.DictCursor) test_manager = Blueprint("test_manager", __name__) @test_manager.route("/api/test/search",methods=['POST'])
def searchBykey():
body = request.get_data()
body = json.loads(body) # 基础语句定义
sql = "" # 获取pageSize和
pageSize = 10 if 'pageSize' not in body or body['pageSize'] is None else body['pageSize']
currentPage = 1 if 'currentPage' not in body or body['currentPage'] is None else body['currentPage'] # 拼接查询条件
if 'productId' in body and body['productId'] != '':
sql = sql + " AND A.productId LIKE '%{}%'".format(body['productId'])
if 'appId' in body and body['appId'] != '':
sql = sql + " AND A.appId LIKE '%{}%'".format(body['appId'])
if 'tester' in body and body['tester'] != '':
sql = sql + " AND R.tester LIKE '%{}%'".format(body['tester'])
if 'developer' in body and body['developer'] != '':
sql = sql + " AND R.developer LIKE '%{}%'".format(body['developer'])
if 'status' in body and body['status'] != '':
sql = sql + " AND R.status = '{}'".format(body['status'])
if 'pickTime' in body and body['pickTime'] != '':
sql = sql + " AND R.updateDate >= '{}' and R.updateDate <= '{}' ".format(body['pickTime'][0],body['pickTime'][1]) # 排序和页数拼接
sql = sql + ' ORDER BY R.updateDate DESC LIMIT {},{}'.format((currentPage - 1) * pageSize, pageSize)
print(sql) # 使用连接池链接数据库
connection = pool.connection() with connection:
# 先查询总数
with connection.cursor() as cursor:
count_select = 'SELECT COUNT(*) as `count` FROM request as R , apps as A where R.appId = A.id AND R.isDel=0' + sql
print(count_select)
cursor.execute(count_select)
total = cursor.fetchall() # 执行查询
with connection.cursor() as cursor:
# 按照条件进行查询
cursor.execute('SELECT A.appId,R.* FROM request as R , apps as A where R.appId = A.id AND R.isDel=0' + sql)
data = cursor.fetchall() # 按分页模版返回查询数据
response = format.resp_format_success
response['data'] = data
response['total'] = total[0]['count']
return response
前端多条件搜索
此区域位于提测vue页面的顶部,有两个下拉选择框,分别是“归属分类” 数据从服务接口获,“测试状态” 所有选项只有几个前端写了就行,点击查询按钮进行接口请求和查询,其中一个“新建提测”按钮为预留,下一篇新页面路由跳转的逻辑。
1. HTML部分代码参考
<div class="filter-container">
<el-form :inline="true" :model="search">
<el-form-item label="归属分类">
<el-select v-model="search.productId">
<el-option value="" label="所有" />
<el-option
v-for="item in optsProduct"
:key="item.id"
:label="item.title"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="应用ID">
<el-input v-model="search.appId" placeholder="服务ID关键词" style="width: 200px;" clearable />
</el-form-item>
<el-form-item label="测试人">
<el-input v-model="search.tester" placeholder="默认测试" style="width: 210px;" clearable />
</el-form-item>
<el-form-item label="提测人">
<el-input v-model="search.developer" placeholder="默认测试" style="width: 210px;" clearable />
</el-form-item>
<el-form-item label="时间范围">
<el-date-picker
v-model="search.pickTime"
type="datetimerange"
:picker-options="pickerOptions"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
align="right">
</el-date-picker>
</el-form-item>
<el-form-item label="测试状态">
<el-select v-model="search.status" placeholder="请选择">
<el-option value="" label="所有" />
<el-option key=1 label="已提测" value=1></el-option>
<el-option key=2 label="测试中" value=2></el-option>
<el-option key=3 label="通过" value=3></el-option>
<el-option key=4 label="失败" value=4></el-option>
<el-option key=9 label="废弃" value=9></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" plain @click="searchClick()">查询</el-button>
</el-form-item>
</el-form>
<el-button type="primary" icon="el-icon-plus" style="float:right" @click="doCommit()">新建提测</el-button>
</div>
2. JS部分所涉及代码参考
所属分类的接口请求不需要新写,沿用应用管理那部分实现
1)data() 变量定义
主要是绑定的搜索条件、日期快捷,顺便定义table存储变量
import { apiAppsProduct } from '@/api/apps'
// 新定义的提测api js文件
import { apiTestSearch } from '@/api/test.js' data() {
return {
// 条件查询变量定义
search: {
productId: '',
appId: '',
developer: '',
tester: '',
status: '',
pickTime: ''
},
// 范围日期组件的快捷选项配置
pickerOptions: {
shortcuts: [{
text: '最近一周',
onClick(picker) {
const end = new Date()
const start = new Date() // 当前时间
start.setTime(start.getTime() - 3600 * 1000 * 24 * 7) //单位毫秒加减计算
picker.$emit('pick', [start, end])
}
}, {
text: '最近一个月',
onClick(picker) {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
picker.$emit('pick', [start, end])
}
}]
},
// 所属分类选项-沿用应用管理
optsProduct: [],
// 数据表格展示和分页变量数据定义
testData: [],
pageValues: {
pageSize: 10,
currentPage: 1,
total: 0
}
}
}
2. methods方法相关实现
默认归类数据的请求与赋值,以及点击搜索按钮后的查询接口请求和表格数据回填,页码数据回填。
// 所属归类选项数据查询
productList() {
apiAppsProduct().then(resp => {
this.optsProduct = resp.data
})
},
// 按照条件查询,如果某个控件为空,则不会此字段请求
searchClick() {
const body = {
pageSize: this.pageValues.pageSize,
currentPage: this.pageValues.currentPage,
productId: this.search.productId,
appId: this.search.appId,
tester: this.search.tester,
developer: this.search.developer,
pickTime: this.search.pickTime,
status: this.search.status
}
apiTestSearch(body).then(response => {
// 将返回的结果赋值给表格自动匹配
this.testData = response.data
this.pageValues.total = response.total
})
},
数据展示和操作逻辑
上边已经完成了所有数据绑定部分,接着就是进行展示
1. 分别定义 table 和 pagination 元素
这里特别要关注实现就是操作的功能的按钮要根据每条数据的状态数值判断是否给予显示。之前需求文档给出来的逻辑如下(测试中状态有更正)
测试状态 |
状态码 |
操作菜单 |
已提测 |
1(新建默认) |
开始测试 / 编辑提测 / 提测详细 |
测试中 |
2 |
添加结果 / 编辑提测 / 提测详细 |
通过 |
3 |
查看报告 / 编辑结果 / 提测详细 |
失败 |
4 |
查看报告 / 编辑结果 / 提测详细 |
废弃 |
9 |
删除提测 / 编辑结果 / 提测详细 |
html代码参考
<div>
<el-table :data="testData">
<!--:data prop绑定{}中的key,label为自定义显示的列表头-->
<el-table-column prop="appId" label="应用ID" />
<el-table-column prop="title" label="提测标题" show-overflow-tooltip />
<el-table-column :formatter="formatStatus" prop="status" label="测试状态"/>
<el-table-column :formatter="formatType" prop="type" label="类型" />
<el-table-column prop="developer" label="提测人" />
<el-table-column prop="tester" label="测试人" />
<el-table-column prop="updateUser" label="更新人" />
<el-table-column :formatter="formatDate" prop="updateDate" label="更新时间" />
<el-table-column label="操作" width="300">
<template slot-scope="scope">
<!--<label>菜单逻辑判断一列</label>-->
<el-link type="primary" v-if="scope.row.status===1" @click="startTest(scope.row)">开始测试</el-link>
<el-link type="primary" v-if="scope.row.status===2" >添加结果</el-link>
<el-link type="primary" v-if="scope.row.status===3 || scope.row.status == 4" >查看报告</el-link>
<el-link type="primary" v-if="scope.row.status===9" >删除结果</el-link>
<!--<label>菜单逻辑判断二列</label>-->
<el-divider direction="vertical"></el-divider>
<el-link type="primary" v-if="[1,2].includes(scope.row.status)">编辑提测</el-link>
<el-link type="primary" v-if="[3,4,9].includes(scope.row.status)">编辑结果</el-link>
<el-divider direction="vertical"></el-divider>
<el-link type="primary" >提测详情</el-link>
</template>
</el-table-column>
</el-table>
</div>
<div>
<br>
<el-pagination
background
:current-page.sync="pageValues.currentPage"
:page-size="pageValues.pageSize"
layout="total, sizes, prev, pager, next"
:page-sizes="[5, 10, 20, 30, 50]"
:total="pageValues.total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
2. 对应元素JS代码
分别要对时间格式化(之前有案例),状态和类型列也要格式化,使用javascript 中的swith case 语法语句进行判断,实现将本来的不可辨别的数字翻译成对应的文字展示。
formatDate(row, column) {
const date = row[column.property]
if (date === undefined) {
return ''
}
// 使用moment格式化时间,由于我的数据库是默认时区,偏移量设置0,各自根据情况进行配置
return moment(date).utcOffset(0).format('YYYY-MM-DD HH:mm')
},
formatStatus(row, column) {
const status = row[column.property]
switch (status) {
case 1:
return '已提测'
case 2:
return '测试中'
case 3:
return '通过'
case 4:
return '失败'
case 9:
return '已废弃'
default:
return '未知状态'
}
},
formatType(row, column) {
const type = row[column.property]
switch (type) {
case 1:
return '功能测试'
case 2:
return '性能测试'
case 3:
return '安全测试'
default:
return '未知状态'
}
},
另外一部分js代码是对分页的实现,请自行实现或参考git上源码。
至此前后的逻辑代码部分已经全部给出来了,没有给出部分是api请求request 和本页的菜单配置,相信如果你是一步步跟着之前文章实战下来的,这些已经太轻车熟路了,启动前后端最终实现页面如下,最后再想想需要写哪些CASE对本功能进行一个全面的测试。
学习交流群已经开放,可以关注公众号【大奇测试开发】发送 “测试开发” 获取最新二维码入群。
【代码更新】
地址:https://github.com/mrzcode/TestProjectManagement
TAG:TPMShare12
【注解&参考】
[注解-1] : https://element.eleme.io/#/zh-CN/component/date-picker
坚持原创,坚持实践,坚持干货,如果你觉得有用,请点击推荐,也欢迎关注我博客园和微信公众号。
测试开发【提测平台】分享12-掌握日期组件&列表状态格式化最终实现提测管理多条件搜索展示功能的更多相关文章
- 2020年第二期《python接口自动化+测试开发》课程,已开学!
2020年第二期<python接口自动化+python测试开发>课程,12月15号开学! 主讲老师:上海-悠悠 上课方式:QQ群视频在线教学,方便交流 本期上课时间:12月15号-3月29 ...
- 测试开发【提测平台】分享3-正式开发产品需求&项目初始化
上两个分享主要是介绍和演示基本前后端所要使用的框架,接下来我们将正式进入到[提测平台的开发] 提要先给出依赖和内容点: 提测平台定义和产品原型需求说明 使用github创建代码仓库进行项目管理 Fla ...
- 测试开发【提测平台】分享9-DBUntils优化数据连接&实现应用搜索和分页功能
微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 从本期开始知识点讲以思维导图的形式给出,内容点会按照讲解-应用-展示的形式体现,这样会更清晰些. DBUntils连接池 在项目中链接数据 ...
- 测试开发【提测平台】分享11-Python实现邮件发送的两种方法实践
微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 按照开发安排,本篇本应该是关于提测页面的搜索和显示实现,怕相似内容疲劳,这期改下内容顺序,将邮件服务的相关的提前,在之前的产品需求和原型中 ...
- 测试开发【提测平台】分享13-远程搜索和路由$route使用实现新建提测需求
微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 本篇继续提测平台开发,按惯例先给出学习的思维导图,以便快速了解学习知识和平台功能实现的重点. 基本知识点学习 远程搜索 显示的数据通过输入 ...
- 测试开发【提测平台】分享14-Vue图标Icon几种用法并利用其一优化菜单
微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 回归主线更新,由于本次知识点只有一个,就不给思维导图了,在上系列测试平台开发实践中主要学习了页面直接的转跳方法和远程搜索的如何做,最终实现 ...
- 测试开发【提测平台】分享10-Element UI抽屉和表单校验&增改接口合并实现应用管理
微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 开篇说个小讨论,一个群里聊天聊到关于更新篇章的长度,是小篇幅多次,还是每次按照一个小完整的功能,我个人的是按照后种来的,主要的思考就是希望 ...
- 测试开发实战[提测平台]19-Echarts图表在项目的应用
微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 在图表统计展示方面,笔者目前使用过的两种开源,分别是 Echats 和 G2Plot 组件,从个人使用上来讲前者应用更广.自定义开发更灵活 ...
- 测试开发实战[提测平台]20-图表G2Plot在项目的实践实录
微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. G2Plot项目应用 上一篇<提测平台19-Echarts图表在项目的实践>讲解了Echarts的图表应用,此篇来看下开箱即用 ...
随机推荐
- spring-data-redis 连接泄漏,我 TM 人傻了
本系列是 我TM人傻了 系列第四期[捂脸],往期精彩回顾: 升级到Spring 5.3.x之后,GC次数急剧增加,我TM人傻了 这个大表走索引字段查询的 SQL 怎么就成全扫描了,我TM人傻了 获取异 ...
- Vue.JS快速上手(Vue-router 实现SPA 开发)
一.什么是路由 URL -> 映射 -> 组件 Hash+onhashchange History.pushstate+replaceState+onpopstate 二.准备工作 组件 ...
- 基于SigalR实现的奥运会实时金牌榜
系统架构 三端 winform 后台数据管理 + Asp.Net Mvc 前台数据展示 + Xamarin.Forms 移动端跨平台APP 因为本人的代码水平一般,期间遇到了一些问题,如signalR ...
- android http get
Executors.newSingleThreadExecutor().execute{ val uri = "https://www.cnblogs.com/hangj" val ...
- uniapp 封装 request 并 配置跨域,( 本地 + 线上 + 封装 )
找到上面这个 文件,不管是用 命令创建 还是 用 HBX 创建,都一样会有这个文件的,然后跟着截图复制粘贴就好了. // 这是配置本地能跨域的,或者你可以直接让后端给你设置请求头,避免了跨域. &qu ...
- NOIP模拟50
过分的神圣,往往比恶魔更加恶质. 前言 最大的一个收获就是不要动不动就码线段树,一定要审清楚题目之后再码!! T1 一开始理解错题了,以为答案是就是 \(\dfrac{\operatorname{le ...
- Configuration对象和SessionFactory会话池
一.加载核心配置文件方式 二.加载映射文件方式 三.SessionFactory相当于连接池 四.获取session会话 同一个线程中获取的session两种方法获取的是同一个session对象: 不 ...
- Storm近年的发展
storm作为第一款大数据领域的流式计算引擎,在2013年推出之后风头一时无二.后续虽然有spark streaming也作为流式计算的引擎,但storm依然在流式计算的江湖占有稳定的地位.直到201 ...
- 洛谷P1060——开心的金明
https://www.luogu.org/problem/show?pid=1060 题目描述 金明今天很开心,家里购置的新房就要领钥匙了,新房里有一间他自己专用的很宽敞的房间.更让他高兴的是,妈妈 ...
- 简单学习PHP中的层次性能分析器
在 PHP 中,我们需要进行调试的时候,一般都会使用 memory_get_usage() 看下内存的使用情况.但如果想看当前的脚本 CPU 的占用情况就没有什么现成的函数了.不过,PHP 也为我们提 ...