【Flask】测试平台开发,重构提测管理页面-第二十篇
概述:
我们在前面已经将提测功能界面的功能都已经开发完成了,但是你有没有发现,此时的UI界面看起来很low,不是很高级,提测后的扭转状态也没有颜色区分,不直观
UI看着是不是很low,测试类型和测试的状态没有颜色,看着不是很直观
重构后的完整前端代码如下
<template><div class="app-container"><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-optionv-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-pickerv-model="search.timeRange"type="datetimerange":picker-options="pickerOptions"range-separator="至"start-placeholder="开始日期"end-placeholder="结束日期"align="right"value-format="yyyy-MM-dd HH:mm:ss"format="yyyy-MM-dd HH:mm:ss"/></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 key="2" label="测试中" value="2" /><el-option key="3" label="通过" value="3" /><el-option key="4" label="失败" value="4" /><el-option key="9" label="废弃" value="9" /></el-select></el-form-item><el-form-item><el-button type="primary" plain @click="searchClick()">查询</el-button><el-button @click="resetSearch">重置</el-button></el-form-item></el-form><el-button type="primary" icon="el-icon-plus" style="float:right" @click="doCommit()">新建提测</el-button></div><div><el-table :data="testData" v-loading="loading"><el-table-column prop="appId" label="服务应用ID" /><el-table-column prop="title" label="提测标题" show-overflow-tooltip /><el-table-column prop="status" label="测试状态"><template slot-scope="scope"><el-tag :type="getStatusType(scope.row.status)" effect="dark">{{ formatStatus(scope.row) }}</el-tag></template></el-table-column><el-table-column prop="type" label="类型" align="center"><template slot-scope="scope"><el-tag :type="getTypeType(scope.row.type)" effect="light">{{ formatType(scope.row) }}</el-tag></template></el-table-column><el-table-column prop="developer" label="提测人" align="center" /><el-table-column prop="tester" label="测试人" align="center" /><el-table-column prop="updateUser" label="更新人" align="center"/><el-table-column :formatter="formatDate" prop="updateDate" label="更新时间" align="center" /><el-table-column :formatter="formatDate" prop="start_time" label="测试开始时间" align="center" /><el-table-column :formatter="formatDate" prop="end_time" label="测试结束时间" align="center" /><el-table-column label="操作" align="center" width="270"><template slot-scope="scope"><el-link v-if="scope.row.status===1" type="primary" @click="startTest(scope.row)">开始测试</el-link><el-link v-if="scope.row.status===2" type="primary" @click="doReport(scope.row)">添加结果</el-link><el-link v-if="scope.row.status===3 || scope.row.status == 4" type="primary" @click="showReportInfo(scope.row)">查看报告</el-link><el-link v-if="scope.row.status===9" type="primary" @click="deleteTest(scope.row)">删除结果</el-link><el-divider direction="vertical" /><el-link v-if="[1,2].includes(scope.row.status)" type="primary" @click="doUpdate(scope.row)">编辑提测</el-link><el-link v-if="[3,4,9].includes(scope.row.status)" type="primary" @click="updateReport(scope.row)">编辑结果</el-link><el-divider direction="vertical" /><el-link type="primary" @click="showRequestInfo(scope.row)">提测详情</el-link></template></el-table-column></el-table></div><div><br><el-paginationbackground: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><div><el-dialog :title="requestInfo.title" :visible.sync="requestInfoVisible"><el-descriptions :column="2" border><el-descriptions-item label="提测人">{{requestInfo.developer}}</el-descriptions-item><el-descriptions-item label="测试人">{{requestInfo.tester}}</el-descriptions-item><el-descriptions-item label="提测版本">{{requestInfo.version}}</el-descriptions-item><el-descriptions-item label="提测类型">{{formatInfoType(requestInfo.type)}}</el-descriptions-item><el-descriptions-item label="服务应用ID" :span="2">{{requestInfo.appId}}</el-descriptions-item><el-descriptions-item label="提测说明" :span="2">{{requestInfo.scope}}</el-descriptions-item><el-descriptions-item label="代码地址" :span="2">{{requestInfo.gitCode}}</el-descriptions-item><el-descriptions-item label="测试文档" :span="2">{{requestInfo.wiki}}</el-descriptions-item><el-descriptions-item label="更多信息" :span="2">{{requestInfo.more}}</el-descriptions-item><el-descriptions-item label="测试开始时间" :formatter="formatDate">{{requestInfo.start_time}}</el-descriptions-item><el-descriptions-item label="测试结束时间" :formatter="formatDate">{{requestInfo.end_time}}</el-descriptions-item></el-descriptions></el-dialog></div><div><el-dialog :title="'[测试报告]' + reportInfo.title" :visible.sync="reportInfoVisible"><el-descriptions :column="1" border><el-descriptions-item label="测试结果">{{formatReportInfoStatus(reportInfo.status)}}</el-descriptions-item><el-descriptions-item label="测试结论">{{reportInfo.test_desc}}</el-descriptions-item><el-descriptions-item label="风险提示">{{reportInfo.test_risks}}</el-descriptions-item><el-descriptions-item label="测试内容">{{reportInfo.test_cases}}</el-descriptions-item><el-descriptions-item label="发现缺陷">{{reportInfo.test_bugs}}</el-descriptions-item><el-descriptions-item v-if="reportInfo.test_file !==''" label="附件"><a :href="'http://172.16.60.60:5000/api/file/download?name='+reportInfo.test_file">{{reportInfo.test_file}}</a></el-descriptions-item><el-descriptions-item label="备注">{{reportInfo.test_note}}</el-descriptions-item><el-descriptions-item label="已发邮件">{{reportInfo.test_email===1?'已发送':'未发送或失败'}}</el-descriptions-item></el-descriptions></el-dialog></div></div>
</template>
<script>
import { apiAppsProduct } from '@/api/apps'
import { apiTestSearch, changeStatus } from '@/api/test.js'export default {name: 'Test',data() {return {// 条件查询变量定义search: {productId: '',appId: '',developer: '',tester: '',status: '',timeRange: [] // 统一的时间范围搜索},// 范围日期组件的快捷选项配置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])}}, {text: '最近三个月',onClick(picker) {const end = new Date()const start = new Date()start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)picker.$emit('pick', [start, end])}}]},optsProduct: [],testData: [],pageValues: {pageSize: 10,currentPage: 1,total: 0},loading: false,requestInfoVisible: false,requestInfo: {},reportInfoVisible: false,reportInfo: {},currentSearchParams: {}, // 当前搜索参数showDebug: true // 是否显示调试信息}},mounted() {if (this.$route.params.needUp && this.$route.params.needUp.needUp === 'true') {this.searchClick()}},created() {this.productList()this.searchClick()},methods: {formatDate(row, column) {const date = row[column.property]if (date === undefined) {return ''}return date},getStatusType(status) {const statusMap = {1: 'primary',2: 'warning',3: 'success',4: 'danger',9: 'info'}return statusMap[status] || 'info'},getTypeType(type) {const typeMap = {1: '',2: 'warning',3: 'danger',4: 'warning',5: 'warning',6: 'warning'}return typeMap[type] || ''},formatStatus(row) {const status = row.statusswitch (status) {case 1:return '已提测'case 2:return '测试中'case 3:return '测试通过'case 4:return '测试不通过'case 9:return '已废弃'default:return '未知状态'}},formatType(row) {const type = row.typeswitch (type) {case 1:return '功能测试'case 2:return '性能测试'case 3:return '安全测试'case 4:return '固件测试'case 5:return '外采类测试'case 6:return '整机测试'default:return '未知类型'}},productList() {apiAppsProduct().then(resp => {this.optsProduct = resp.data})},searchClick() {this.loading = true// 构建请求体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 || '',status: this.search.status || '',// 使用 pickTime 参数名pickTime: this.search.timeRange || []}// 移除空字符串参数Object.keys(body).forEach(key => {if (body[key] === '') {delete body[key]}})console.log('发送到API的参数:', body)// 检查是否有搜索条件(除了分页参数)const hasSearchConditions = Object.keys(body).some(key =>key !== 'pageSize' &&key !== 'currentPage' &&body[key] !== undefined &&body[key] !== '' &&!(Array.isArray(body[key]) && body[key].length === 0))apiTestSearch(body).then(response => {this.testData = response.datathis.pageValues.total = response.totalthis.loading = false// 只在有搜索条件时才显示提示if (hasSearchConditions) {if (response.data && response.data.length === 0) {this.$message.warning('未找到符合条件的记录')} else {this.$message.success(`找到 ${response.data.length} 条记录`)}}}).catch(error => {console.error('查询失败:', error)this.loading = false// 错误提示仍然显示this.$message.error('查询失败: ' + (error.message || '请检查网络或参数'))})},resetSearch() {this.search = {productId: '',appId: '',developer: '',tester: '',status: '',timeRange: []}this.$message({message: '已重置搜索条件',type: 'success'})this.searchClick()},handleSizeChange(val) {this.pageValues.pageSize = valthis.searchClick()},handleCurrentChange(val) {this.pageValues.currentPage = valthis.searchClick()},doCommit(row) {this.$router.push({ path: '/commit?action=ADD' })},doUpdate(row) {this.$router.push({ path: '/commit?action=UPDATE&id=' + row.id })},startTest(row) {const reqBody = {id: row.id,status: 'start'}changeStatus(reqBody).then(resp => {this.$message({message: resp.message,type: 'success'})this.searchClick()})},deleteTest(row) {const reqBody = {id: row.id,status: 'delete'}changeStatus(reqBody).then(resp => {this.$message({message: resp.message,type: 'success'})this.searchClick()})},showRequestInfo(row) {this.requestInfo = rowthis.requestInfoVisible = true},formatInfoType(type) {switch (type) {case 1:return '功能测试'case 2:return '性能测试'case 3:return '安全测试'default:return '未知状态'}},doReport(row) {this.$router.push({ name: 'report', params: { action: 'ADD', id: row.id }})},updateReport(row) {this.$router.push({ name: 'report', params: { action: 'UPDATE', id: row.id }})},showReportInfo(row) {this.reportInfo = rowthis.reportInfoVisible = true},formatReportInfoStatus(status) {if (status === 3) {return '测试通过'} else if (status === 4) {return '测试失败'} else if (status === 9) {return '测试废弃'}}}
}
</script><style scoped>.el-pagination {text-align: right;}.el-tag {font-weight: bold;}.time-tips {font-size: 12px;color: #909399;margin-top: 5px;}.debug-panel {background: #f9f9f9;border-left: 4px solid #409EFF;padding: 10px 15px;margin: 15px 0;border-radius: 4px;font-size: 13px;}.debug-title {font-weight: bold;color: #409EFF;margin-bottom: 5px;}
</style>
重新启动前端服务,此时查看页面上的状态展示
每个状态我们都添加了颜色区分,这样使用上更加的直观
接着我们在原有提测管理的基础上,分别拓展几个功能菜单页面,分别为我的提测,我的测试,测试通过,测试失败的菜单,这样每个状态在对应的菜单栏里面只能看对应的状态,提测管理这个页面默认存储所有状态的数据
我们已经实现总的页面,要拓展这几个菜单出来,就很简单了,例如我的测试页面代码如下
<template><div class="app-container"><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-optionv-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-pickerv-model="search.timeRange"type="datetimerange":picker-options="pickerOptions"range-separator="至"start-placeholder="开始日期"end-placeholder="结束日期"align="right"value-format="yyyy-MM-dd HH:mm:ss"format="yyyy-MM-dd HH:mm:ss"/></el-form-item><el-form-item label="测试状态"><el-select v-model="search.status" placeholder="请选择"><el-option value="1" label="已提测" /><el-option value="" label="所有" /></el-select></el-form-item><el-form-item><el-button type="primary" plain @click="searchClick()">查询</el-button><el-button @click="resetSearch">重置</el-button></el-form-item></el-form><el-button type="primary" icon="el-icon-plus" style="float:right" @click="doCommit()">新建提测</el-button></div><div><el-table :data="testData" v-loading="loading"><el-table-column prop="appId" label="服务应用ID" /><el-table-column prop="title" label="提测标题" show-overflow-tooltip /><el-table-column prop="status" label="测试状态"><template slot-scope="scope"><el-tag :type="getStatusType(scope.row.status)" effect="dark">{{ formatStatus(scope.row) }}</el-tag></template></el-table-column><el-table-column prop="type" label="类型" align="center"><template slot-scope="scope"><el-tag :type="getTypeType(scope.row.type)" effect="light">{{ formatType(scope.row) }}</el-tag></template></el-table-column><el-table-column prop="developer" label="提测人" align="center" /><el-table-column prop="tester" label="测试人" align="center" /><el-table-column prop="updateUser" label="更新人" align="center"/><el-table-column :formatter="formatDate" prop="updateDate" label="更新时间" align="center" /><el-table-column :formatter="formatDate" prop="start_time" label="测试开始时间" align="center" /><el-table-column :formatter="formatDate" prop="end_time" label="测试结束时间" align="center" /><el-table-column label="操作" align="center" width="270"><template slot-scope="scope"><el-link v-if="scope.row.status===1" type="primary" @click="startTest(scope.row)">开始测试</el-link><el-link v-if="scope.row.status===2" type="primary" @click="doReport(scope.row)">添加结果</el-link><el-link v-if="scope.row.status===3 || scope.row.status == 4" type="primary" @click="showReportInfo(scope.row)">查看报告</el-link><el-link v-if="scope.row.status===9" type="primary" @click="deleteTest(scope.row)">删除结果</el-link><el-divider direction="vertical" /><el-link v-if="[1,2].includes(scope.row.status)" type="primary" @click="doUpdate(scope.row)">编辑提测</el-link><el-link v-if="[3,4,9].includes(scope.row.status)" type="primary" @click="updateReport(scope.row)">编辑结果</el-link><el-divider direction="vertical" /><el-link type="primary" @click="showRequestInfo(scope.row)">提测详情</el-link></template></el-table-column></el-table></div><div><br><el-paginationbackground: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><div><el-dialog :title="requestInfo.title" :visible.sync="requestInfoVisible"><el-descriptions :column="2" border><el-descriptions-item label="提测人">{{requestInfo.developer}}</el-descriptions-item><el-descriptions-item label="测试人">{{requestInfo.tester}}</el-descriptions-item><el-descriptions-item label="提测版本">{{requestInfo.version}}</el-descriptions-item><el-descriptions-item label="提测类型">{{formatInfoType(requestInfo.type)}}</el-descriptions-item><el-descriptions-item label="服务应用ID" :span="2">{{requestInfo.appId}}</el-descriptions-item><el-descriptions-item label="提测说明" :span="2">{{requestInfo.scope}}</el-descriptions-item><el-descriptions-item label="代码地址" :span="2">{{requestInfo.gitCode}}</el-descriptions-item><el-descriptions-item label="测试文档" :span="2">{{requestInfo.wiki}}</el-descriptions-item><el-descriptions-item label="更多信息" :span="2">{{requestInfo.more}}</el-descriptions-item><el-descriptions-item label="测试开始时间" :formatter="formatDate">{{requestInfo.start_time}}</el-descriptions-item><el-descriptions-item label="测试结束时间" :formatter="formatDate">{{requestInfo.end_time}}</el-descriptions-item></el-descriptions></el-dialog></div><div><el-dialog :title="'[测试报告]' + reportInfo.title" :visible.sync="reportInfoVisible"><el-descriptions :column="1" border><el-descriptions-item label="测试结果">{{formatReportInfoStatus(reportInfo.status)}}</el-descriptions-item><el-descriptions-item label="测试结论">{{reportInfo.test_desc}}</el-descriptions-item><el-descriptions-item label="风险提示">{{reportInfo.test_risks}}</el-descriptions-item><el-descriptions-item label="测试内容">{{reportInfo.test_cases}}</el-descriptions-item><el-descriptions-item label="发现缺陷">{{reportInfo.test_bugs}}</el-descriptions-item><el-descriptions-item v-if="reportInfo.test_file !==''" label="附件"><a :href="'http://172.16.60.60:5000/api/file/download?name='+reportInfo.test_file">{{reportInfo.test_file}}</a></el-descriptions-item><el-descriptions-item label="备注">{{reportInfo.test_note}}</el-descriptions-item><el-descriptions-item label="已发邮件">{{reportInfo.test_email===1?'已发送':'未发送或失败'}}</el-descriptions-item></el-descriptions></el-dialog></div></div>
</template><script>
import { apiAppsProduct } from '@/api/apps'
import { apiTestSearch, changeStatus } from '@/api/test.js'
import { getToken } from '@/utils/auth'export default {name: 'MyCommit',data() {return {search: {productId: '',appId: '',developer: getToken('username') || '', // 默认当前用户tester: '',status: '1', // 默认只显示已提测状态timeRange: []},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])}}, {text: '最近三个月',onClick(picker) {const end = new Date()const start = new Date()start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)picker.$emit('pick', [start, end])}}]},optsProduct: [],testData: [],pageValues: {pageSize: 10,currentPage: 1,total: 0},loading: false,requestInfoVisible: false,requestInfo: {},reportInfoVisible: false,reportInfo: {}}},mounted() {if (this.$route.params.needUp && this.$route.params.needUp.needUp === 'true') {this.searchClick()}},created() {this.productList()this.searchClick()},methods: {formatDate(row, column) {const date = row[column.property]if (date === undefined) {return ''}return date},getStatusType(status) {const statusMap = {1: 'primary',2: 'warning',3: 'success',4: 'danger',9: 'info'}return statusMap[status] || 'info'},getTypeType(type) {const typeMap = {1: '',2: 'warning',3: 'danger',4: 'warning',5: 'warning',6: 'warning'}return typeMap[type] || ''},formatStatus(row) {const status = row.statusswitch (status) {case 1:return '已提测'case 2:return '测试中'case 3:return '测试通过'case 4:return '测试不通过'case 9:return '已废弃'default:return '未知状态'}},formatType(row) {const type = row.typeswitch (type) {case 1:return '功能测试'case 2:return '性能测试'case 3:return '安全测试'case 4:return '固件测试'case 5:return '外采类测试'case 6:return '整机测试'default:return '未知类型'}},productList() {apiAppsProduct().then(resp => {this.optsProduct = resp.data})},searchClick() {this.loading = trueconst 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 || '',status: this.search.status || '',pickTime: this.search.timeRange || []}// 强制过滤状态为已提测(1),即使选择了"所有"if (this.search.status === '') {body.status = '1'}apiTestSearch(body).then(response => {this.testData = response.datathis.pageValues.total = response.totalthis.loading = falseif (response.data && response.data.length === 0) {this.$message.warning('未找到符合条件的记录')}}).catch(error => {console.error('查询失败:', error)this.loading = falsethis.$message.error('查询失败: ' + (error.message || '请检查网络或参数'))})},resetSearch() {this.search = {productId: '',appId: '',developer: getToken('username') || '', // 重置后仍保持当前用户tester: '',status: '1', // 重置后仍保持已提测状态timeRange: []}this.$message({message: '已重置搜索条件',type: 'success'})this.searchClick()},handleSizeChange(val) {this.pageValues.pageSize = valthis.searchClick()},handleCurrentChange(val) {this.pageValues.currentPage = valthis.searchClick()},doCommit(row) {this.$router.push({ path: '/commit?action=ADD' })},doUpdate(row) {this.$router.push({ path: '/commit?action=UPDATE&id=' + row.id })},startTest(row) {const reqBody = {id: row.id,status: 'start'}changeStatus(reqBody).then(resp => {this.$message({message: resp.message,type: 'success'})this.searchClick()})},deleteTest(row) {const reqBody = {id: row.id,status: 'delete'}changeStatus(reqBody).then(resp => {this.$message({message: resp.message,type: 'success'})this.searchClick()})},showRequestInfo(row) {this.requestInfo = rowthis.requestInfoVisible = true},formatInfoType(type) {switch (type) {case 1:return '功能测试'case 2:return '性能测试'case 3:return '安全测试'default:return '未知状态'}},doReport(row) {this.$router.push({ name: 'report', params: { action: 'ADD', id: row.id }})},updateReport(row) {this.$router.push({ name: 'report', params: { action: 'UPDATE', id: row.id }})},showReportInfo(row) {this.reportInfo = rowthis.reportInfoVisible = true},formatReportInfoStatus(status) {if (status === 3) {return '测试通过'} else if (status === 4) {return '测试失败'} else if (status === 9) {return '测试废弃'}}}
}
</script><style scoped>.el-pagination {text-align: right;}.el-tag {font-weight: bold;}.time-tips {font-size: 12px;color: #909399;margin-top: 5px;}
</style>
其他页面也是相同的操作,只是对于过滤条件进行了筛选过滤,可以动手自己试试