缺陷管理
This commit is contained in:
51
test-ui/src/api/test/bug.js
Normal file
51
test-ui/src/api/test/bug.js
Normal file
@@ -0,0 +1,51 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
const api = {
|
||||
bugList: 'test/defect/list',
|
||||
addBug: 'test/defect/addBug',
|
||||
delBug: 'test/defect/delBug',
|
||||
getBugDetail: 'test/defect/bugDetail',
|
||||
updateBug: 'test/defect/editBug'
|
||||
}
|
||||
|
||||
export function getBugList(data) {
|
||||
return request({
|
||||
url: api.bugList,
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
export function addBug(data) {
|
||||
return request({
|
||||
url: api.addBug,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
export function delBug(id) {
|
||||
return request({
|
||||
url: api.delBug,
|
||||
method: 'post',
|
||||
data: {id}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function getBugDetail(id) {
|
||||
return request({
|
||||
url: api.getBugDetail,
|
||||
method: 'post',
|
||||
data: {id}
|
||||
})
|
||||
}
|
||||
|
||||
export function updateBug(data) {
|
||||
return request({
|
||||
url: api.updateBug,
|
||||
method: 'post',
|
||||
data:data
|
||||
})
|
||||
}
|
||||
|
||||
551
test-ui/src/views/test/bug/index.vue
Normal file
551
test-ui/src/views/test/bug/index.vue
Normal file
@@ -0,0 +1,551 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 顶部导航 -->
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="24">
|
||||
<el-header class="header">
|
||||
<div class="head1">
|
||||
<span style="font-size: 18px; font-weight: bold; margin-right: 20px;">缺陷列表</span>
|
||||
</div>
|
||||
<div class="head2">
|
||||
<el-input :placeholder="placeholderText" v-model="query" class="input-with-select" clearable>
|
||||
<el-select v-model="select" slot="prepend" placeholder="请选择" style="width: 80px;">
|
||||
<el-option label="概要" value="1"></el-option>
|
||||
<el-option label="ID" value="2"></el-option>
|
||||
</el-select>
|
||||
<el-button slot="append" icon="el-icon-search" @click="handleQuery"></el-button>
|
||||
</el-input>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="medium"
|
||||
style="margin-right: 10px;"
|
||||
@click="handleCollapse(!activeNames.includes('1'))"
|
||||
>高级筛选
|
||||
</el-button>
|
||||
<el-button icon="el-icon-plus" type="primary" size="medium" style="margin-left: 10px;" @click="addBugVue">新建缺陷</el-button>
|
||||
</div>
|
||||
</el-header>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-collapse v-model="activeNames">
|
||||
<el-collapse-item class="collapse-search" name="1">
|
||||
<el-form ref="queryForm" :model="queryParams" label-width="110px">
|
||||
<el-row :gutter="10" class="high-search">
|
||||
<el-form-item label="创建时间">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
type="daterange"
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
value-format="yyyy-MM-dd"
|
||||
></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="经办人">
|
||||
<el-select v-model="queryParams.manager" placeholder="请选择" clearable filterable>
|
||||
<simple-options :options="managerList"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="严重程度">
|
||||
<el-select v-model="queryParams.level" placeholder="请选择" clearable filterable>
|
||||
<simple-options :options="dict.type.severity_level"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" size="mini" icon="el-icon-search" @click="handleAdvancedSearch">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetAdvancedFilter">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
|
||||
<!-- 标签页 -->
|
||||
<el-Table v-loading="loading" :data="list" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection"/>
|
||||
<el-table-column prop="serialNumber" label="ID" align="center"/>
|
||||
<el-table-column prop="outline" label="概要" align="center"/>
|
||||
<el-table-column prop="status" label="状态" align="center">
|
||||
<template #default="{ row }">
|
||||
<dict-tag :options="dict.type.status" :value="row.status"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="manager" label="经办人" align="center"/>
|
||||
<el-table-column prop="level" label="严重程度" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="severityColor[scope.row.level]">{{ scope.row.level }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="createTime" label="创建时间" align="center"/>
|
||||
<el-table-column label="操作" align="left" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleEdit(scope.row.id)">编辑</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click.native.stop="handleDelete(scope.row.id)">删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-Table>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div style="margin-top: 10px; display: flex; justify-content: space-between; align-items: center;">
|
||||
<div>
|
||||
<el-button type="primary" size="small" @click="handleExport">全部导出</el-button>
|
||||
<el-button size="small" @click="handleSelectExport">批量导出</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-dialog title="新建缺陷" :visible.sync="addOpen" width="90%">
|
||||
<el-form ref="form" :rules="rules" :model="form" label-width="110px" label-position="right">
|
||||
<el-container>
|
||||
<el-main>
|
||||
<el-form-item label="缺陷概要" prop="outline">
|
||||
<el-input v-model="form.outline" placeholder="请输入"></el-input>
|
||||
</el-form-item>
|
||||
<!-- 描述 -->
|
||||
<el-form-item label="描述" prop="detail">
|
||||
<el-input type="textarea" v-model="form.detail" :rows="22"></el-input>
|
||||
</el-form-item>
|
||||
</el-main>
|
||||
<el-aside width="450px" class="basic-information">
|
||||
<h3>基础信息</h3>
|
||||
<el-form-item label="缺陷ID" prop="serialNumber">
|
||||
<el-input v-model="form.serialNumber" placeholder="请输入"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="缺陷名称" prop="name">
|
||||
<el-input v-model="form.name" placeholder="请输入"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="经办人" prop="manager">
|
||||
<el-select v-model="form.manager" placeholder="请选择经办人" clearable>
|
||||
<Simple-options :options="managerList"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="严重程度" prop="level">
|
||||
<el-select v-model="form.level" placeholder="未设置" clearable filterable>
|
||||
<simple-options :options="dict.type.severity_level"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="缺陷类型" prop="type">
|
||||
<el-select v-model="form.type" placeholder="未设置" clearable>
|
||||
<simple-options :options="dict.type.bug_type"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="缺陷状态" prop="status">
|
||||
<el-select v-model="form.status" placeholder="未设置" clearable>
|
||||
<simple-options :options="dict.type.bug_status"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="能否复现" prop="reappearance">
|
||||
<el-select v-model="form.reappearance" placeholder="未设置" clearable>
|
||||
<simple-options :options="reappearanceOptions"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="开发人" prop="dev">
|
||||
<el-select v-model="form.dev" placeholder="请选择开发人" clearable>
|
||||
<Simple-options :options="managerList"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="测试人" prop="test">
|
||||
<el-select v-model="form.test" placeholder="请选择测试人" clearable>
|
||||
<Simple-options :options="managerList"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="版本" prop="version">
|
||||
<el-input v-model="form.version" placeholder="请输入版本"></el-input>
|
||||
</el-form-item>
|
||||
</el-aside>
|
||||
</el-container>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="addOpen = false">取 消</el-button>
|
||||
<el-button type="primary" @click="submitForm">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog title="编辑缺陷" :visible.sync="editOpen" width="90%">
|
||||
<el-form ref="editForm" :rules="rules" :model="editForm" label-width="110px" label-position="right">
|
||||
<el-container>
|
||||
<el-main>
|
||||
<el-form-item label="缺陷概要" prop="outline">
|
||||
<el-input v-model="editForm.outline" placeholder="请输入"></el-input>
|
||||
</el-form-item>
|
||||
<!-- 描述 -->
|
||||
<el-form-item label="描述" prop="detail">
|
||||
<el-input type="textarea" v-model="editForm.detail" :rows="22"></el-input>
|
||||
</el-form-item>
|
||||
</el-main>
|
||||
<el-aside width="450px" class="basic-information">
|
||||
<h3>基础信息</h3>
|
||||
<el-form-item label="缺陷ID" prop="serialNumber">
|
||||
<el-input v-model="editForm.serialNumber" placeholder="请输入"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="缺陷名称" prop="name">
|
||||
<el-input v-model="editForm.name" placeholder="请输入"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="经办人" prop="manager">
|
||||
<el-select v-model="editForm.manager" placeholder="请选择经办人" clearable>
|
||||
<Simple-options :options="managerList"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="严重程度" prop="level">
|
||||
<el-select v-model="editForm.level" placeholder="未设置" clearable filterable>
|
||||
<simple-options :options="dict.type.severity_level"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="缺陷类型" prop="type">
|
||||
<el-select v-model="editForm.type" placeholder="未设置" clearable>
|
||||
<simple-options :options="dict.type.bug_type"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="缺陷状态" prop="status">
|
||||
<el-select v-model="editForm.status" placeholder="未设置" clearable>
|
||||
<simple-options :options="dict.type.bug_status"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="能否复现" prop="reappearance">
|
||||
<el-select v-model="editForm.reappearance" placeholder="未设置" clearable>
|
||||
<simple-options :options="reappearanceOptions"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="开发人" prop="dev">
|
||||
<el-select v-model="editForm.dev" placeholder="请选择开发人" clearable>
|
||||
<Simple-options :options="managerList"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="测试人" prop="test">
|
||||
<el-select v-model="editForm.test" placeholder="请选择测试人" clearable>
|
||||
<Simple-options :options="managerList"/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="版本" prop="version">
|
||||
<el-input v-model="editForm.version" placeholder="请输入版本"></el-input>
|
||||
</el-form-item>
|
||||
</el-aside>
|
||||
</el-container>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="editOpen = false">取 消</el-button>
|
||||
<el-button type="primary" @click="editSubmitForm">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {managerList} from "@/api/test/project";
|
||||
import {addBug, delBug, getBugDetail, getBugList, updateBug} from "@/api/test/bug";
|
||||
import SimpleOptions from "@/components/FormItem/option/SimpleOptions.vue";
|
||||
import {requestDownload} from "@/utils/request";
|
||||
|
||||
export default {
|
||||
name: 'defect',
|
||||
components: {SimpleOptions},
|
||||
dicts: ['severity_level', 'bug_type', 'bug_status'],
|
||||
data() {
|
||||
return {
|
||||
reappearanceOptions: [{
|
||||
value: '0',
|
||||
label: '必然复现'
|
||||
}, {
|
||||
value: '1',
|
||||
label: '偶发复现'
|
||||
}],
|
||||
severityColor: {
|
||||
P0: 'info',
|
||||
P1: 'warning',
|
||||
P2: 'warning',
|
||||
P3: 'danger',
|
||||
p4: 'danger'
|
||||
},
|
||||
query: '',
|
||||
rules: {
|
||||
serialNumber: [{required: true, message: '请输入缺陷ID', trigger: 'blur'}],
|
||||
detail: [{required: true, message: '请输入缺陷描述', trigger: 'blur'}],
|
||||
name: [{required: true, message: '请输入缺陷名称', trigger: 'blur'}],
|
||||
outline: [{required: true, message: '请输入缺陷概要', trigger: 'blur'}],
|
||||
manager: [{required: true, message: '请选择经办人', trigger: 'blur'}],
|
||||
dev: [{required: true, message: '请选择开发人员', trigger: 'blur'}],
|
||||
test: [{required: true, message: '请选择测试人员', trigger: 'blur'}],
|
||||
level: [{required: true, message: '请选择严重程度', trigger: 'blur'}],
|
||||
status: [{required: true, message: '请选择缺陷状态', trigger: 'blur'}],
|
||||
reappearance: [{required: true, message: '请选择是否复现', trigger: 'blur'}],
|
||||
type: [{required: true, message: '请选择缺陷类型', trigger: 'blur'}],
|
||||
version: [{required: true, message: '请输入版本', trigger: 'blur'}],
|
||||
},
|
||||
select: '1',
|
||||
searchKeyword: '',
|
||||
total: 0,
|
||||
list: [],
|
||||
title: '',
|
||||
// 遮罩层
|
||||
loading: false,
|
||||
editSubmitLoading: false,
|
||||
submitLoading: false,
|
||||
//新增弹窗
|
||||
addOpen: false,
|
||||
//编辑弹窗
|
||||
editOpen: false,
|
||||
selectedRows: [],
|
||||
selectedData: [],
|
||||
managerList: [],
|
||||
queryParams: {
|
||||
serialNumber: '',
|
||||
outline: '',
|
||||
manager: '',
|
||||
level: '',
|
||||
createTime: [],
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
activeNames: [], // 控制 collapse 的展开状态
|
||||
form: {
|
||||
serialNumber: '',
|
||||
name: '',
|
||||
outline: '',
|
||||
detail: '',
|
||||
status: '',
|
||||
manager: '',
|
||||
dev: '',
|
||||
test: '',
|
||||
level: '',
|
||||
type: '',
|
||||
reappearance: '',
|
||||
version: ''
|
||||
},
|
||||
editForm: {
|
||||
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.getManagerList();
|
||||
},
|
||||
computed: {
|
||||
placeholderText() {
|
||||
return this.select === '1' ? '请输入需求概要搜索' : '请输入需求ID搜索';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleSelectionChange(selection) {
|
||||
this.selectedRows = selection;
|
||||
},
|
||||
// 获取负责人列表
|
||||
getManagerList() {
|
||||
managerList()
|
||||
.then((list) => {
|
||||
this.managerList = (list.rows || []).map((e) => ({value: e.userId, label: e.userName}))
|
||||
})
|
||||
},
|
||||
// 搜索
|
||||
handleQuery() {
|
||||
if (this.select === '1') {
|
||||
this.queryParams.outline = this.query;
|
||||
this.queryParams.serialNumber = '';
|
||||
} else if (this.select === '2') {
|
||||
this.queryParams.serialNumber = this.query;
|
||||
this.queryParams.outline = '';
|
||||
}
|
||||
this.getList();
|
||||
},
|
||||
addBugVue() {
|
||||
this.addOpen = true;
|
||||
this.reset();
|
||||
},
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true
|
||||
const [startCreateTime, endCreateTime] = this.queryParams.createTime || []
|
||||
const queryParams = {
|
||||
...this.queryParams,
|
||||
startCreateTime,
|
||||
endCreateTime
|
||||
}
|
||||
getBugList(queryParams).then(list => {
|
||||
this.list = list.rows;
|
||||
this.total = list.total;
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
const form = {}
|
||||
Object.keys(this.form).forEach((key) => {
|
||||
form[key] = ''
|
||||
})
|
||||
this.form = form
|
||||
this.resetForm('form')
|
||||
},
|
||||
// 展开/折叠
|
||||
handleCollapse(val) {
|
||||
this.activeNames = val ? ['1'] : [];
|
||||
},
|
||||
handleAdvancedSearch() {
|
||||
// 高级筛选条件搜索
|
||||
this.queryParams.pageNum = 1
|
||||
this.getList()
|
||||
},
|
||||
resetAdvancedFilter() {
|
||||
// 重置高级筛选条件
|
||||
this.resetForm('queryFrom')
|
||||
this.handleAdvancedSearch()
|
||||
},
|
||||
submitForm() {
|
||||
const form = {
|
||||
...this.form,
|
||||
}
|
||||
console.log('submit', form)
|
||||
this.$refs?.form.validate((valid) => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
this.submitLoading = true
|
||||
addBug(form)
|
||||
.then(() => {
|
||||
this.$message.success('添加成功')
|
||||
this.addOpen = false
|
||||
this.getList()
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message.error('添加失败')
|
||||
})
|
||||
.finally(() => {
|
||||
this.submitLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
handleDelete(id) {
|
||||
this.$modal.confirm('是否确认删除缺陷?').then(function () {
|
||||
return delBug(id);
|
||||
}).then(() => {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
});
|
||||
},
|
||||
handleEdit(id) {
|
||||
this.title = '编辑缺陷'
|
||||
getBugDetail(id).then((res) => {
|
||||
this.editForm = res.data
|
||||
this.editForm.manager = parseInt(res.data.manager, 10);
|
||||
this.editOpen = true
|
||||
})
|
||||
},
|
||||
editSubmitForm() {
|
||||
const form = {
|
||||
...this.editForm,
|
||||
}
|
||||
this.$refs?.editForm.validate((valid) => {
|
||||
if (!valid) {
|
||||
return
|
||||
}
|
||||
})
|
||||
this.editSubmitLoading = true
|
||||
updateBug(form)
|
||||
.then(() => {
|
||||
this.$message.success('编辑成功')
|
||||
this.editSubmitLoading = false
|
||||
this.editOpen = false
|
||||
this.getList()
|
||||
})
|
||||
.catch(() => {
|
||||
this.$message.error('编辑失败')
|
||||
this.editSubmitLoading = false
|
||||
})
|
||||
},
|
||||
/** 全部导出按钮操作 */
|
||||
handleExport() {
|
||||
const [startCreateTime, endCreateTime] = this.queryParams.createTime || []
|
||||
this.queryParams.startCreateTime = startCreateTime
|
||||
this.queryParams.endCreateTime = endCreateTime
|
||||
const {pageNum, pageSize, ...rest} = this.queryParams
|
||||
requestDownload({
|
||||
url: '/test/defect/exportBug',
|
||||
fileName: `缺陷列表信息_${new Date().getTime()}.xlsx`,
|
||||
data: rest,
|
||||
})
|
||||
},
|
||||
/** 批量导出按钮操作 */
|
||||
handleSelectExport() {
|
||||
this.selectedData = this.selectedRows.map(row => ({
|
||||
serialNumber: row.serialNumber,
|
||||
outline: row.outline,
|
||||
manager: row.manager,
|
||||
level: row.level,
|
||||
createTime: row.createTime,
|
||||
status: row.status
|
||||
}));
|
||||
console.log('selectedData', this.selectedData)
|
||||
requestDownload({
|
||||
url: '/test/defect/batchExportBug',
|
||||
fileName: `缺陷列表信息_${new Date().getTime()}.xlsx`,
|
||||
data: this.selectedData,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.input-with-select {
|
||||
background-color: #ffffff;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.collapse-search {
|
||||
::v-deep .el-collapse-item__header {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.high-search {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-top: 40px;
|
||||
background-color: rgb(248, 248, 249);
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.head1 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.head2 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
justify-content: flex-end;
|
||||
column-gap: 10px;
|
||||
}
|
||||
|
||||
.el-dialog .el-form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.el-dialog .el-form-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.el-dialog .el-textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.basic-information {
|
||||
background-color: rgb(248, 248, 249) !important;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user