This commit is contained in:
2025-03-03 16:44:15 +08:00
parent 379cf19425
commit cbf60d042c
18 changed files with 422 additions and 891 deletions

View File

@@ -0,0 +1,47 @@
package com.test.test.controller;
import com.test.common.annotation.Log;
import com.test.common.core.controller.BaseController;
import com.test.common.core.domain.AjaxResult;
import com.test.common.core.page.TableDataInfo;
import com.test.common.enums.BusinessType;
import com.test.common.utils.DateUtils;
import com.test.test.domain.TestTask;
import com.test.test.domain.TestTaskCase;
import com.test.test.domain.qo.GroupIdQO;
import com.test.test.domain.qo.IDQO;
import com.test.test.service.ITestTaskCaseService;
import com.test.test.service.ITestTaskService;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 定时任务用例关联Controller
*/
@RestController
@RequestMapping("/test/taskCase")
public class TestTaskCaseController extends BaseController {
@Resource
private ITestTaskCaseService testTaskCaseService;
/**
* 新增定时任务用例关联
*/
@Log(title = "定时任务用例关联", businessType = BusinessType.INSERT)
@PostMapping("/add")
public AjaxResult add(@RequestBody TestTaskCase testTaskCase) {
return toAjax(testTaskCaseService.insertTestTaskCase(testTaskCase));
}
/**
* 删除定时任务用例关联
*/
@Log(title = "定时任务用例关联", businessType = BusinessType.DELETE)
@PostMapping("/del")
public AjaxResult remove(@RequestBody TestTaskCase testTaskCase) {
return toAjax(testTaskCaseService.deleteTestTaskCase(testTaskCase));
}
}

View File

@@ -0,0 +1,77 @@
package com.test.test.controller;
import com.test.common.annotation.Log;
import com.test.common.core.controller.BaseController;
import com.test.common.core.domain.AjaxResult;
import com.test.common.core.page.TableDataInfo;
import com.test.common.enums.BusinessType;
import com.test.common.utils.DateUtils;
import com.test.test.domain.TestCase;
import com.test.test.domain.TestTask;
import com.test.test.domain.qo.GroupIdQO;
import com.test.test.domain.qo.IDQO;
import com.test.test.service.ITestTaskService;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 定时任务Controller
*/
@RestController
@RequestMapping("/test/task")
public class TestTaskController extends BaseController {
@Resource
private ITestTaskService testTaskService;
/**
* 查询定时任务列表
*/
@GetMapping("/list")
public TableDataInfo list(@Validated GroupIdQO qo) {
startPage();
List<TestTask> list = testTaskService.selectTestTaskList(qo);
return getDataTable(list);
}
/**
* 获取定时任务详细信息
*/
@PostMapping(value = "/detail")
public AjaxResult getInfo(@RequestBody IDQO qo) {
return success(testTaskService.selectTestTaskById(qo.getId()));
}
/**
* 新增定时任务
*/
@Log(title = "定时任务", businessType = BusinessType.INSERT)
@PostMapping("/add")
public AjaxResult add(@RequestBody TestTask testTask) {
testTask.setCreateBy(getLoginUser().getUsername());
testTask.setCreateTime(DateUtils.getNowDate());
return toAjax(testTaskService.insertTestTask(testTask));
}
/**
* 修改定时任务
*/
@Log(title = "定时任务", businessType = BusinessType.UPDATE)
@PostMapping("/edit")
public AjaxResult edit(@RequestBody TestTask testTask) {
return toAjax(testTaskService.updateTestTask(testTask));
}
/**
* 删除定时任务
*/
@Log(title = "定时任务", businessType = BusinessType.DELETE)
@PostMapping("/del")
public AjaxResult remove(@RequestBody IDQO qo) {
return toAjax(testTaskService.deleteTestTaskById(qo.getId()));
}
}

View File

@@ -0,0 +1,19 @@
package com.test.test.domain.vo;
import com.test.test.domain.TestCase;
import com.test.test.domain.TestTask;
import lombok.Data;
import java.util.List;
@Data
public class TestTaskDetailVO {
private TestTask task;
private List<TestCaseVo> caseList;
@Data
public static class TestCaseVo {
private TestCase testCase;
private Long sort;
}
}

View File

@@ -66,4 +66,8 @@ public interface TestTaskCaseMapper
* @return * @return
*/ */
public List<TestTaskCase> selectTestTaskCaseListByTaskId(Long taskId); public List<TestTaskCase> selectTestTaskCaseListByTaskId(Long taskId);
Long max(Long taskId);
int deleteTestTaskCase(TestTaskCase testTaskCase);
} }

View File

@@ -59,4 +59,6 @@ public interface ITestTaskCaseService
* @return 结果 * @return 结果
*/ */
public int deleteTestTaskCaseByTaskId(Long taskId); public int deleteTestTaskCaseByTaskId(Long taskId);
int deleteTestTaskCase(TestTaskCase testTaskCase);
} }

View File

@@ -2,6 +2,7 @@ package com.test.test.service;
import com.test.test.domain.TestTask; import com.test.test.domain.TestTask;
import com.test.test.domain.qo.GroupIdQO; import com.test.test.domain.qo.GroupIdQO;
import com.test.test.domain.vo.TestTaskDetailVO;
import java.util.List; import java.util.List;
@@ -12,7 +13,7 @@ public interface ITestTaskService {
/** /**
* 查询自动化测试 * 查询自动化测试
*/ */
TestTask selectTestTaskById(Long id); TestTaskDetailVO selectTestTaskById(Long id);
/** /**
* 查询自动化测试列表 * 查询自动化测试列表

View File

@@ -15,8 +15,7 @@ import java.util.List;
* @date 2025-02-21 * @date 2025-02-21
*/ */
@Service @Service
public class TestTaskCaseServiceImpl implements ITestTaskCaseService public class TestTaskCaseServiceImpl implements ITestTaskCaseService {
{
@Resource @Resource
private TestTaskCaseMapper testTaskCaseMapper; private TestTaskCaseMapper testTaskCaseMapper;
@@ -27,8 +26,7 @@ public class TestTaskCaseServiceImpl implements ITestTaskCaseService
* @return 自动化测试和用例关联 * @return 自动化测试和用例关联
*/ */
@Override @Override
public TestTaskCase selectTestTaskCaseByTaskId(Long taskId) public TestTaskCase selectTestTaskCaseByTaskId(Long taskId) {
{
return testTaskCaseMapper.selectTestTaskCaseByTaskId(taskId); return testTaskCaseMapper.selectTestTaskCaseByTaskId(taskId);
} }
@@ -39,8 +37,7 @@ public class TestTaskCaseServiceImpl implements ITestTaskCaseService
* @return 自动化测试和用例关联 * @return 自动化测试和用例关联
*/ */
@Override @Override
public List<TestTaskCase> selectTestTaskCaseList(TestTaskCase testTaskCase) public List<TestTaskCase> selectTestTaskCaseList(TestTaskCase testTaskCase) {
{
return testTaskCaseMapper.selectTestTaskCaseList(testTaskCase); return testTaskCaseMapper.selectTestTaskCaseList(testTaskCase);
} }
@@ -51,8 +48,8 @@ public class TestTaskCaseServiceImpl implements ITestTaskCaseService
* @return 结果 * @return 结果
*/ */
@Override @Override
public int insertTestTaskCase(TestTaskCase testTaskCase) public int insertTestTaskCase(TestTaskCase testTaskCase) {
{ testTaskCase.setSort(testTaskCaseMapper.max(testTaskCase.getTaskId()) + 1);
return testTaskCaseMapper.insertTestTaskCase(testTaskCase); return testTaskCaseMapper.insertTestTaskCase(testTaskCase);
} }
@@ -63,8 +60,7 @@ public class TestTaskCaseServiceImpl implements ITestTaskCaseService
* @return 结果 * @return 结果
*/ */
@Override @Override
public int updateTestTaskCase(TestTaskCase testTaskCase) public int updateTestTaskCase(TestTaskCase testTaskCase) {
{
return testTaskCaseMapper.updateTestTaskCase(testTaskCase); return testTaskCaseMapper.updateTestTaskCase(testTaskCase);
} }
@@ -75,8 +71,7 @@ public class TestTaskCaseServiceImpl implements ITestTaskCaseService
* @return 结果 * @return 结果
*/ */
@Override @Override
public int deleteTestTaskCaseByTaskIds(Long[] taskIds) public int deleteTestTaskCaseByTaskIds(Long[] taskIds) {
{
return testTaskCaseMapper.deleteTestTaskCaseByTaskIds(taskIds); return testTaskCaseMapper.deleteTestTaskCaseByTaskIds(taskIds);
} }
@@ -87,8 +82,12 @@ public class TestTaskCaseServiceImpl implements ITestTaskCaseService
* @return 结果 * @return 结果
*/ */
@Override @Override
public int deleteTestTaskCaseByTaskId(Long taskId) public int deleteTestTaskCaseByTaskId(Long taskId) {
{
return testTaskCaseMapper.deleteTestTaskCaseByTaskId(taskId); return testTaskCaseMapper.deleteTestTaskCaseByTaskId(taskId);
} }
@Override
public int deleteTestTaskCase(TestTaskCase testTaskCase) {
return testTaskCaseMapper.deleteTestTaskCase(testTaskCase);
}
} }

View File

@@ -3,6 +3,7 @@ package com.test.test.service.impl;
import com.test.common.utils.DateUtils; import com.test.common.utils.DateUtils;
import com.test.test.domain.*; import com.test.test.domain.*;
import com.test.test.domain.qo.GroupIdQO; import com.test.test.domain.qo.GroupIdQO;
import com.test.test.domain.vo.TestTaskDetailVO;
import com.test.test.mapper.*; import com.test.test.mapper.*;
import com.test.test.service.ITestTaskService; import com.test.test.service.ITestTaskService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@@ -42,8 +43,18 @@ public class TestTaskServiceImpl implements ITestTaskService {
* 查询自动化测试 * 查询自动化测试
*/ */
@Override @Override
public TestTask selectTestTaskById(Long id) { public TestTaskDetailVO selectTestTaskById(Long id) {
return testTaskMapper.selectTestTaskById(id); TestTaskDetailVO testTaskDetailVO = new TestTaskDetailVO();
testTaskDetailVO.setTask(testTaskMapper.selectTestTaskById(id));
List<TestTaskDetailVO.TestCaseVo> caseList = new ArrayList<>();
testTaskCaseMapper.selectTestTaskCaseListByTaskId(id).forEach(testTaskCase -> {
TestTaskDetailVO.TestCaseVo testCase = new TestTaskDetailVO.TestCaseVo();
testCase.setSort(testTaskCase.getSort());
testCase.setTestCase(testCaseMapper.selectTestCaseById(testTaskCase.getCaseId()));
caseList.add(testCase);
});
testTaskDetailVO.setCaseList(caseList);
return testTaskDetailVO;
} }
/** /**
@@ -98,7 +109,7 @@ public class TestTaskServiceImpl implements ITestTaskService {
*/ */
@Override @Override
public boolean executeTestTaskById(Long id, Integer triggerType, String environment, String jmeterHomePath, String operUser) { public boolean executeTestTaskById(Long id, Integer triggerType, String environment, String jmeterHomePath, String operUser) {
TestTask testTask = this.selectTestTaskById(id); TestTask testTask = testTaskMapper.selectTestTaskById(id);
if (testTask == null || testTask.getStatus() == null if (testTask == null || testTask.getStatus() == null
|| testTask.getStatus() > 0 || "2".equals(testTask.getDelFlag())) { || testTask.getStatus() > 0 || "2".equals(testTask.getDelFlag())) {
log.error("定时任务已删除或未启用,不能执行!"); log.error("定时任务已删除或未启用,不能执行!");

View File

@@ -60,9 +60,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach> </foreach>
</delete> </delete>
<delete id="deleteTestTaskCase" parameterType="TestTaskCase">
delete from test_task_case where case_id = #{caseId} and task_id = #{taskId}
</delete>
<select id="selectTestTaskCaseListByTaskId" parameterType="Long" resultMap="TestTaskCaseResult"> <select id="selectTestTaskCaseListByTaskId" parameterType="Long" resultMap="TestTaskCaseResult">
<include refid="selectTestTaskCaseVo"/> <include refid="selectTestTaskCaseVo"/>
where task_id = #{taskId} where task_id = #{taskId}
ORDER BY sort ORDER BY sort
</select> </select>
<select id="max" parameterType="Long" resultType="Long">
select max(sort) from test_task_case where task_id = #{taskId}
</select>
</mapper> </mapper>

View File

@@ -0,0 +1,19 @@
import request from '@/utils/request'
// 新增用例
export function addTaskCase(data) {
return request({
url: '/test/taskCase/add',
method: 'post',
data: data
})
}
// 删除用例
export function delTaskCase(data) {
return request({
url: '/test/taskCase/del',
method: 'post',
data: data
})
}

View File

@@ -0,0 +1,82 @@
<template>
<folder-page type="case" @click="folderHandleSelected">
<div v-if="queryParams.groupId && queryParams.groupId !== 0">
<el-table v-loading="loading" :data="dataList" ref="multipleTable">
<el-table-column label="用例名称" align="center" prop="name"/>
<el-table-column label="创建人" align="center" prop="createBy"/>
<el-table-column label="用例状态" align="center" prop="status" :formatter="row => ['','草稿', '通过', '不通过'][row.status]"/>
<el-table-column label="创建时间" align="center" prop="createTime"/>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<span v-if="caseList.findIndex(item => item.id === scope.row.id) > -1">已添加</span>
<el-button v-else size="mini" type="text" icon="el-icon-delete" @click="handleAdd(scope.row.id)">添加</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
</div>
<el-empty v-else/>
</folder-page>
</template>
<script>
import FolderPage from "@/components/FolderPage/index.vue";
import {listCase} from "@/api/test/case";
import {addTaskCase} from "@/api/test/taskCase";
export default {
components: {FolderPage},
props: {
caseList: {
type: Array,
},
taskId: {
type: Number,
}
},
data() {
return {
loading: false,
total: 0,
dataList: [],
queryParams: {
pageNum: 1,
pageSize: 10,
groupId: null,
},
};
},
methods: {
folderHandleSelected(id) {
if (id) {
this.queryParams.groupId = id;
this.getList();
} else {
this.dataList = [];
}
},
getList() {
this.loading = true;
listCase(this.queryParams).then(response => {
this.dataList = response.rows;
this.total = response.total;
this.loading = false;
});
},
handleAdd(id) {
this.loading = true;
addTaskCase({
taskId: this.taskId,
caseId: id,
}).then(res => {
this.loading = false;
this.$emit("success");
})
},
},
};
</script>
<style lang="scss" scoped>
::v-deep .el-container {
height: unset;
}
</style>

View File

@@ -1,18 +0,0 @@
// clickOutside.js
export default {
bind(el, binding, vnode) {
el.clickOutsideEvent = function (event) {
// 检查点击事件的目标元素是否是绑定指令的元素或其子元素
if (!(el === event.target || el.contains(event.target))) {
// 如果不是,则调用传递给指令的方法
vnode.context[binding.expression](event);
}
};
// 添加事件监听器
document.body.addEventListener("click", el.clickOutsideEvent);
},
unbind(el) {
// 移除事件监听器
document.body.removeEventListener("click", el.clickOutsideEvent);
},
};

View File

@@ -1,41 +1,17 @@
<template> <template>
<div> <div>
<div class="row">
<div class="button">
<el-button type="primary" icon="el-icon-video-play">搜索</el-button>
<i class="el-icon-setting"></i>
</div>
</div>
<div class="refresh"> <div class="refresh">
<div class="refresh-icon"> <div class="refresh-icon">
<i class="el-icon-refresh"></i> <i class="el-icon-refresh"></i>
<span>刷新</span> <span>刷新</span>
</div> </div>
</div> </div>
<div class="chart-container"> <!-- <div class="chart-container">-->
<div class="chart-instance"> <!-- <div class="chart-instance">-->
<div>定时任务执行记录</div> <!-- <div>定时任务执行记录</div>-->
<lineChart /> <!-- <lineChart />-->
</div> <!-- </div>-->
<div class="chart-instance"> <!-- </div>-->
<div class="trend-chart">
<span>覆盖率趋势图</span>
<div>
<span class="select">选择应用</span>
<el-select v-model="value" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</div>
</div>
<lineChartCover />
</div>
</div>
<div class="table-content"> <div class="table-content">
<el-table :data="tableData" border style="width: 100%"> <el-table :data="tableData" border style="width: 100%">
<el-table-column prop="triggerTime" label="触发时间"> </el-table-column> <el-table-column prop="triggerTime" label="触发时间"> </el-table-column>
@@ -63,10 +39,7 @@
</el-table-column> </el-table-column>
<el-table-column fixed="right" label="操作"> <el-table-column fixed="right" label="操作">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button @click="handleClick(scope.row)" type="text" size="small" <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button>
>查看</el-button
>
<el-button type="text" size="small">编辑</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -89,69 +62,14 @@
<script> <script>
import lineChart from "./lineChart.vue"; import lineChart from "./lineChart.vue";
import lineChartCover from "./lineChartCover.vue";
// import executiveReport from "./executiveReport.vue";
export default { export default {
components: { components: {
lineChart, lineChart,
lineChartCover,
// executiveReport,
}, },
data() { data() {
return { return {
value: "", value: "",
options: [ tableData: [],
{
value: "选项1",
label: "黄金糕",
},
{
value: "选项2",
label: "双皮奶",
},
{
value: "选项3",
label: "蚵仔煎",
},
{
value: "选项4",
label: "龙须面",
},
{
value: "选项5",
label: "北京烤鸭",
},
],
tableData: [
{
triggerTime: "2025-02-19 10:00:00",
startTime: "2025-02-29 10:00:00",
triggerMethod: "定时",
environment: "中移商业保理平台",
status: "成功",
sendStatus: "未发送",
executionTime: "111s",
},
{
triggerTime: "2025-02-19 10:00:00",
startTime: "2025-02-29 10:00:00",
triggerMethod: "定时",
environment: "中移商业保理平台",
status: "成功",
sendStatus: "未发送",
executionTime: "111s",
},
{
triggerTime: "2025-02-19 10:00:00",
startTime: "2025-02-29 10:00:00",
triggerMethod: "定时",
environment: "中移商业保理平台",
status: "成功",
sendStatus: "未发送",
executionTime: "111s",
},
// 可以添加更多数据
],
currentPage: 1, currentPage: 1,
}; };
}, },
@@ -209,7 +127,7 @@ export default {
display: flex; display: flex;
.chart-instance { .chart-instance {
width: 50%; width: 100%;
padding: 16px; padding: 16px;
border: 1px solid #e9f3fb; border: 1px solid #e9f3fb;
margin-right: 16px; margin-right: 16px;

View File

@@ -1,19 +1,19 @@
<template> <template>
<div class="content"> <div class="content">
<div class="header" @click="handleOutClick"> <div class="header">
<div class="back"> <div class="back" @click="backList">
<span><i class="el-icon-arrow-left"></i></span> <span><i class="el-icon-arrow-left"></i></span>
<span>返回列表</span> <span>返回列表</span>
</div> </div>
<div class="task"> <div class="task">
<span class="collect"><i class="el-icon-star-off"></i></span> <span class="collect"><i class="el-icon-star-off"></i></span>
<span class="name">任务名称</span> <span class="name">任务名称</span>
<el-input :class="isEdit ? 'black' : 'red'" type="text" placeholder="请输入内容" v-model="text" maxlength="64" show-word-limit @click.native.stop="isEdit = true"/> <el-input v-model="form.name" size="mini"/>
</div> </div>
</div> </div>
<el-tabs v-model="activeName" @tab-click="handleClick"> <el-tabs v-model="activeName">
<el-tab-pane label="任务详情" name="first"> <el-tab-pane label="任务详情" name="first">
<taskDetails /> <taskDetails :task="form" :caseList="caseList" @submit="submit" @getData="getData"/>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="执行记录" name="second"> <el-tab-pane label="执行记录" name="second">
<executionRecord /> <executionRecord />
@@ -29,26 +29,48 @@
import taskDetails from "./taskDetails.vue"; import taskDetails from "./taskDetails.vue";
import executionRecord from "./executionRecord.vue"; import executionRecord from "./executionRecord.vue";
import operationRecords from "./operationRecords.vue"; import operationRecords from "./operationRecords.vue";
import {getTask, updateTask} from "@/api/test/task";
export default { export default {
components: { components: { taskDetails, executionRecord, operationRecords },
taskDetails,
executionRecord,
operationRecords,
},
data() { data() {
return { return {
text: "111", // 输入框内容 form: {},
isEdit: false, // 是否禁用 caseList: [],
activeName: "first", activeName: "first",
}; };
}, },
created() {
this.getData();
},
methods: { methods: {
handleOutClick() { getData() {
this.isEdit = false; // 聚焦时设置为 true this.caseList=[]
getTask(this.$route.query.id).then(res => {
this.form = res.data.task;
if (res.data.caseList && res.data.caseList.length) {
res.data.caseList.forEach(item => {
this.caseList.push({
...item.testCase,
sort: item.sort,
});
})
}
})
}, },
handleClick(tab, event) { backList() {
console.log(tab, event); this.$tab.closeOpenPage({path: "/task"});
}, },
submit(data) {
updateTask({
...data,
status: data.status ? 0 : 2,
retry: data.retry ? 0 : 2
}).then(res => {
this.$message.success("修改成功");
this.backList();
})
}
}, },
}; };
</script> </script>
@@ -65,6 +87,9 @@ export default {
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
padding: 16px 100px 16px 24px; padding: 16px 100px 16px 24px;
.back {
cursor: pointer;
}
} }
.back span { .back span {
color: rgb(50, 114, 254); color: rgb(50, 114, 254);
@@ -74,9 +99,9 @@ export default {
.task { .task {
color: #4f597f; color: #4f597f;
font-size: 12px; font-size: 12px;
margin: 0 8px 0 0px;
display: flex; display: flex;
align-items: center; align-items: center;
margin: 8px 8px 0 0;
.collect { .collect {
margin-right: 10px; margin-right: 10px;
} }

View File

@@ -1,168 +0,0 @@
<template>
<!-- 修改为正确的闭合标签 -->
<div :class="className" :style="{ height: height, width: width }"></div>
</template>
<script>
import * as echarts from "echarts";
require("echarts/theme/macarons"); // echarts theme
import resize from "@/views/dashboard/mixins/resize";
export default {
mixins: [resize],
props: {
className: {
type: String,
default: "chart",
},
width: {
type: String,
default: "680px",
},
height: {
type: String,
default: "350px",
},
autoResize: {
type: Boolean,
default: true,
},
chartData: {
type: Object,
required: false,
},
},
data() {
return {
chart: null,
};
},
watch: {
chartData: {
deep: true,
handler(val) {
this.setOptions(val);
},
},
},
mounted() {
this.$nextTick(() => {
this.initChart();
});
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
initChart() {
this.chart = echarts.init(this.$el, "macarons");
this.setOptions();
},
setOptions() {
const option = {
tooltip: {
trigger: "axis",
},
legend: {
data: ["分支覆盖率", "方法覆盖率", "行覆盖率"],
// 修改图例颜色
textStyle: {
color: "#686868",
},
},
grid: {
left: "3%",
right: "4%",
bottom: "3%",
containLabel: true,
// 去掉背景保留背景线条
backgroundColor: "transparent",
},
xAxis: {
type: "category",
boundaryGap: false,
axisLabel: {
textStyle: {
color: "#686868",
},
},
data: [
"2025-01-21 10:00:00",
"2025-01-25 10:00:00",
"2025-01-29 10:00:00",
"2025-02-02 10:00:00",
"2025-02-06 10:00:00",
"2025-02-10 10:00:00",
"2025-02-14 10:00:00",
"2025-02-18 10:00:00",
],
},
yAxis: [
{
type: "value",
// 去掉坐标轴名称
name: "",
min: 0,
max: 2,
interval: 0.5,
axisLabel: {
formatter: "{value}",
textStyle: {
color: "#686868",
},
},
},
{
type: "value",
// 去掉坐标轴名称
name: "",
min: 0,
max: 100,
interval: 25,
axisLabel: {
formatter: "{value}%",
textStyle: {
color: "#686868",
},
},
},
],
series: [
{
name: "分支覆盖率",
type: "line",
yAxisIndex: 0, // 使用左边的纵坐标
data: [0.5, 1.2, 1.8, 1.5, 1.0, 0.8, 1.3, 1.7],
itemStyle: {
color: "red", // 设置为蓝色
},
},
{
name: "方法覆盖率",
type: "line",
yAxisIndex: 1, // 使用右边的纵坐标
data: [25, 50, 75, 90, 40, 30, 70, 90],
itemStyle: {
color: "green", // 设置为绿色
},
},
{
name: "行覆盖率",
type: "line",
yAxisIndex: 1, // 使用右边的纵坐标
data: [25, 50, 75, 60, 40, 30, 70, 90],
itemStyle: {
color: "gray", // 设置为绿色
},
},
],
};
this.chart.setOption(option);
},
},
};
</script>

View File

@@ -5,7 +5,6 @@
<span>任务信息</span> <span>任务信息</span>
<i class="el-icon-arrow-down"></i> <i class="el-icon-arrow-down"></i>
</span> </span>
<div class="mission" v-show="collapse"> <div class="mission" v-show="collapse">
<div class="mission_left"> <div class="mission_left">
<div class="min"> <div class="min">
@@ -15,19 +14,14 @@
<!-- --> <!-- -->
<div class="expression-top"> <div class="expression-top">
<span>crontab表达式</span> <span>crontab表达式</span>
<i class="el-icon-warning-outline"></i>
</div> </div>
<!-- --> <!-- -->
<div class="expression-centre"> <div class="expression-centre">
<div class="time"> <div class="time">
<el-input <!-- <el-input style="width: 100px" v-model="inputItem.value" v-for="(inputItem, index) in inputGroup" :key="index">-->
style="width: 100px" <!-- <template slot="suffix">{{ inputItem.label }}</template>-->
v-model="inputItem.value" <!-- </el-input>-->
v-for="(inputItem, index) in inputGroup" <el-input v-model="form.crontab"/>
:key="index"
>
<template slot="suffix">{{ inputItem.label }}</template>
</el-input>
</div> </div>
</div> </div>
<!-- --> <!-- -->
@@ -44,45 +38,23 @@
</div> </div>
</div> </div>
<div class="footer"> <div class="footer">
<div> <span>用例执行方式</span>
<span>所在分组</span> <template>
<el-select v-model="value" placeholder="请选择"> <el-radio v-model="form.async" :label="2">串行</el-radio>
<el-option <el-radio v-model="form.async" :label="0">并行</el-radio>
v-for="item in options" </template>
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</div>
<span class="way">
<span>用例执行方式</span>
<template>
<el-radio v-model="radio" label="1">备选项</el-radio>
<el-radio v-model="radio" label="2">备选项</el-radio>
</template>
</span>
<div class="avatar">
<span>创建人</span>
<el-avatar
:size="14"
src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
></el-avatar>
<span>涂卫军</span>
</div>
</div> </div>
</div> </div>
<div class="mission_right"> <div class="mission_right">
<el-form ref="form" :model="form" label-width="120px"> <el-form ref="form" :model="form" label-width="120px">
<el-form-item label="启动定时任务"> <el-form-item label="启动定时任务">
<el-switch v-model="form.delivery1"></el-switch> <el-switch v-model="form.status"></el-switch>
</el-form-item> </el-form-item>
<el-form-item label="失败用例重试"> <el-form-item label="失败用例重试">
<el-switch v-model="form.delivery2"></el-switch> <el-switch v-model="form.retry"></el-switch>
</el-form-item> </el-form-item>
<el-form-item label="最大重试次数"> <el-form-item label="最大重试次数">
<el-input v-model="form.name" style="width: 100px"></el-input> <el-input v-model="form.retryCount" style="width: 100px"></el-input>
<span class="restrict">最小1次最大10次</span> <span class="restrict">最小1次最大10次</span>
</el-form-item> </el-form-item>
</el-form> </el-form>
@@ -95,185 +67,74 @@
<span>已选用例列表</span> <span>已选用例列表</span>
<i class="el-icon-arrow-down"></i> <i class="el-icon-arrow-down"></i>
</span> </span>
<el-row>
<el-button type="primary" class="append-bt" @click="usecase"
>添加用例</el-button
>
</el-row>
</div> </div>
<div class="form-container" v-show="collapse1"> <div class="form-container" v-show="collapse1">
<div class="form-container-left"> <el-row :gutter="10" class="mb8">
<div class="menu-list-item"> <el-col :span="1.5">
<div class="menu-itme-left"> <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="addCase">添加用例</el-button>
<i class="el-icon-menu" style="font-size: 14px"></i> </el-col>
<div class="menu-itme-text"> <right-toolbar @queryTable="getCaseList"></right-toolbar>
<span class="text-top">全部用例</span> </el-row>
</div> <el-table :data="caseList">
</div> <el-table-column label="用例名称" align="center" prop="name"/>
</div> <el-table-column label="执行顺序" sortable align="center" prop="sort"/>
<div class="menu-list-item"> <el-table-column label="创建人" align="center" prop="createBy"/>
<div class="menu-itme-left"> <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<i class="el-icon-menu" style="font-size: 14px"></i> <template slot-scope="scope">
<div class="menu-itme-text"> <el-button size="mini" type="text" icon="el-icon-delete" @click="delCase(scope.row.id)">删除</el-button>
<span class="text-top">中移商业保理平台</span> </template>
<span class="text-bottom">指定接口用例</span> </el-table-column>
</div> </el-table>
</div>
<span>
<span class="num">2</span>
<i
class="el-icon-edit icon"
style="margin-right: 12px; color: #343434"
></i>
<i class="el-icon-delete icon"></i>
</span>
</div>
</div>
<div class="table">
<div class="table-header">
<span>中移商业保理平台</span>
<el-input
placeholder="请输入内容"
v-model="input3"
style="width: 400px"
>
<el-select v-model="select" slot="prepend" placeholder="请选择">
<el-option label="餐厅名" value="1"></el-option>
<el-option label="订单号" value="2"></el-option>
<el-option label="用户电话" value="3"></el-option>
</el-select>
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
</div>
<el-table ref="filterTable" :data="tableData" style="width: 100%">
<el-table-column prop="name" label="ID" width="180">
</el-table-column>
<el-table-column prop="example" label="用例名称">
<template slot-scope="scope">
<span class="icon--edit">A</span>
<span class="icon__pencil"></span>
<span>{{ scope.row.example }}</span>
</template>
</el-table-column>
<el-table-column prop="address" label="用例状态">
<template slot-scope="scope">
<i class="el-icon-success"></i>
<span>{{ scope.row.address }}</span>
</template>
</el-table-column>
<el-table-column prop="tag" label="创建人" width="100">
<template slot-scope="scope">
<el-avatar
:size="14"
src="https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png"
></el-avatar>
<span>{{ scope.row.tag }}</span>
</template>
</el-table-column>
<el-table-column prop="date" width="180" sortable>
<template #header>
<span>用例执行优先级</span>
<i class="el-icon-warning-outline"></i>
</template>
<template slot-scope="scope">
<span
v-if="!scope.row.isInput"
class="table-input-text"
@click="handleTableInputClick(scope.row)"
>
<span>{{ scope.row.date || "未设置,点击输入" }}</span>
<i class="el-icon-warning-outline icon"></i>
</span>
<el-input-number
v-if="scope.row.isInput"
style="width: 140px"
v-model="scope.row.date"
controls-position="right"
:min="1"
:max="10"
placeholder="未设置,点击输入"
class="table-input"
></el-input-number>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[100, 200, 300, 400]"
:page-size="100"
layout="total, sizes, prev, pager, next, jumper"
:total="400"
>
</el-pagination>
</div>
</div>
</div> </div>
</div> </div>
<div> <el-dialog :visible.sync="dialogFormVisible" title="添加用例" width="80%">
<div> <caseTable :caseList="caseList" :taskId="form.id" @success="getCaseList"/>
<div class="selected"> <div slot="footer" class="dialog-footer">
<span class="headline" @click="handlecollapse2"> <el-button type="primary" @click="dialogFormVisible = false"> </el-button>
<span>关联应用</span>
<i class="el-icon-warning-outline"></i>
<i class="el-icon-arrow-down"></i>
</span>
<el-row>
<el-button type="primary" class="append-bt">关联应用</el-button>
</el-row>
</div>
<div v-show="collapse2">
<el-table ref="filterTable" :data="tableData2" style="width: 100%">
<el-table-column prop="name" label="应用名称" align="center">
</el-table-column>
<el-table-column prop="address" label="实例数" align="center">
</el-table-column>
</el-table>
</div>
</div>
</div>
<el-dialog :visible.sync="dialogFormVisible">
<template #title>
<div class="tab-line">
<span style="margin-right: 20px">添加用例</span>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="手动选择" name="first"> </el-tab-pane>
<el-tab-pane label="提升覆盖率推荐" name="second"> </el-tab-pane>
</el-tabs>
</div>
<test1 v-if="activeName == 'first'" />
<test2 v-if="activeName == 'second'" />
</template>
<div slot="footer" class="dialog-footer" v-if="activeName == 'first'">
<el-button @click="dialogFormVisible = false"> </el-button>
<el-button type="primary" @click="dialogFormVisible = false"
> </el-button
>
</div> </div>
</el-dialog> </el-dialog>
<div class="footer">
<el-button type="primary" @click="submit"> </el-button>
</div>
</div> </div>
</template> </template>
<script> <script>
import clickOutside from "./clickOutside.js"; import caseTable from "./caseTable.vue";
import test1 from "./test1.vue"; import {delTaskCase} from "@/api/test/taskCase";
import Test2 from "./test2.vue";
import test2 from "./test2.vue";
export default { export default {
directives: {
clickoutside: clickOutside, // 注册指令
},
components: { components: {
test1, caseTable,
test2, },
props: {
task: {
type: Object,
},
caseList: {
type: Array,
}
},
watch: {
task: {
handler(val) {
if (val !== this.form) {
this.form = val;
this.form.status = val.status === 0;
this.form.retry = val.retry === 0;
}
},
},
}, },
data() { data() {
return { return {
activeName: "first", loading: false,
total: 0,
queryParams: {
pageNum: 1,
pageSize: 10,
groupId: null,
},
collapse: true, collapse: true,
collapse1: true, collapse1: true,
collapse2: true, collapse2: true,
@@ -318,117 +179,39 @@ export default {
}, },
], ],
value: "", value: "",
options: [
{
value: "选项1",
label: "黄金糕",
},
{
value: "选项2",
label: "双皮奶",
},
{
value: "选项3",
label: "蚵仔煎",
},
{
value: "选项4",
label: "龙须面",
},
{
value: "选项5",
label: "北京烤鸭",
},
],
form: { form: {
delivery1: false, delivery1: false,
delivery2: false, delivery2: false,
name: "", name: "",
}, },
input3: "",
tableData: [
{
date: "",
name: "王小虎",
example: "授信信息管理",
address: "通过",
tag: "家",
isInput: false,
},
{
date: "",
name: "王小虎",
example: "授信信息管理",
address: "通过",
tag: "公司",
isInput: false,
},
{
date: "",
name: "王小虎",
example: "授信信息管理",
address: "通过",
tag: "家",
isInput: false,
},
{
date: "",
name: "王小虎",
example: "授信信息管理",
address: "通过",
tag: "公司",
isInput: false,
},
],
tableData2: [
{
name: "cmcf-scfp",
address: "0",
},
{
name: "cmcf-scfp",
address: "0",
},
],
currentPage: 4,
select: "",
}; };
}, },
methods: { methods: {
usecase() { getCaseList() {
this.$emit("getData");
},
addCase() {
this.dialogFormVisible = !this.dialogFormVisible; this.dialogFormVisible = !this.dialogFormVisible;
}, },
delCase(id) {
console.log(id)
delTaskCase({
taskId: this.task.id,
caseId: id,
}).then(res => {
this.$modal.msgSuccess("删除成功");
this.getCaseList();
})
},
handlecollapse() { handlecollapse() {
this.collapse = !this.collapse; this.collapse = !this.collapse;
}, },
handlecollapse1() { handlecollapse1() {
this.collapse1 = !this.collapse1; this.collapse1 = !this.collapse1;
}, },
handlecollapse2() { submit() {
this.collapse2 = !this.collapse2; this.$emit("submit", this.form);
}, }
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
},
handleSizeChange(val) {
console.log(`每页 ${val}`);
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`);
},
handleTableInputClick(row) {
// this.tableData.forEach((item) => (item.isInput = false)); // 关闭其他输入框
row.isInput = true; // 打开当前输入框
},
handleClickOutside() {
this.tableData.forEach((item) => (item.isInput = false));
},
handleClick(tab, event) {
console.log(tab, event);
},
}, },
}; };
</script> </script>
@@ -451,20 +234,17 @@ export default {
border: 1px solid #ebf0fa; border: 1px solid #ebf0fa;
border-radius: 4px; border-radius: 4px;
display: flex; display: flex;
justify-content: space-between;
padding: 16px 8px; padding: 16px 8px;
margin: 16px 0; margin: 16px 0;
} }
.mission_left { .mission_left {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
margin-right: 32px;
} }
.min { .min {
display: flex; display: flex;
border: 1px solid transparent; border: 1px solid transparent;
border-radius: 4px; border-radius: 4px;
display: flex;
padding: 0 12px; padding: 0 12px;
position: relative; position: relative;
} }
@@ -475,9 +255,9 @@ export default {
font-size: 12px; font-size: 12px;
line-height: 20px; line-height: 20px;
margin-right: 16px; margin-right: 16px;
min-width: 60px;
} }
.wrapper { .wrapper {
width: 948px;
background-color: #f3f4f9; background-color: #f3f4f9;
border-radius: 4px; border-radius: 4px;
display: flex; display: flex;
@@ -536,6 +316,7 @@ export default {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 12px 12px 0 12px; padding: 12px 12px 0 12px;
margin-top: 12px;
span { span {
align-items: center; align-items: center;
color: #8e9eb1; color: #8e9eb1;
@@ -588,19 +369,6 @@ export default {
border-radius: 4px; border-radius: 4px;
height: 32px; height: 32px;
} }
.form-container {
display: flex;
border: 1px solid #ebf0fa;
border-radius: 4px;
padding-bottom: 16px;
margin-bottom: 16px;
.form-container-left {
border-right: 1px solid #e3e8f2;
display: flex;
flex-direction: column;
// width: 280px;
}
}
.menu-list-item { .menu-list-item {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;

View File

@@ -1,47 +0,0 @@
<template>
<div>
<el-form ref="form" :model="form" label-width="80px" class="content">
<el-form-item label="选择用例库">
<el-select v-model="form.region" placeholder="请选择用例库">
<el-option label="中移商业保理平台" value="shanghai"></el-option>
<el-option label="中移商业保理平台" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item label="选择用例">
<el-radio-group v-model="form.resource">
<el-radio label="全部接口用例"></el-radio>
<el-radio label="目录下全部用例"></el-radio>
<el-radio label="指定接口用例"></el-radio>
</el-radio-group>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
data() {
return {
form: {
name: "",
region: "",
date1: "",
date2: "",
delivery: false,
type: [],
resource: "",
desc: "",
},
};
},
methods: {
onSubmit() {
console.log("submit!");
},
},
};
</script>
<style lang="scss" scoped>
.content {
padding: 16px;
}
</style>

View File

@@ -1,217 +0,0 @@
<template>
<div>
<div class="title">
根据未覆盖代码提供与其关联的用例和无用例覆盖的接口补充用例并执行重新观察全量覆盖率数值变化
</div>
<div class="container">
<div class="example-container">
<div class="example-title">
<span class="use">应用</span>
<span class="real">实例</span>
</div>
<div
class="example-item"
v-for="example in exampleList"
:key="example.label"
>
<span class="data-name1">
<i class="el-icon-s-order"></i>
<span>{{ example.label }}</span>
</span>
<span class="data-name2">{{ example.value }}</span>
</div>
</div>
<div class="content-container">
<div class="form-container">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="覆盖范围">
<el-radio-group v-model="form.resource">
<el-radio label="应用"></el-radio>
<el-radio label="用例集"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="活动区域">
<el-select v-model="form.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item label="活动时间">
<el-col :span="11">
<el-date-picker
v-model="form.date"
type="datetimerange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="['12:00:00']"
>
</el-date-picker>
</el-col>
</el-form-item>
<el-form-item label="活动名称">
<el-input v-model="form.name" :disabled="true"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">生成</el-button>
</el-form-item>
</el-form>
</div>
<div class="table-container">
<el-table :data="tableData" border style="width: 100%">
<el-table-column fixed prop="date" label="日期"> </el-table-column>
<el-table-column prop="name" label="姓名"> </el-table-column>
<el-table-column prop="province" label="省份"> </el-table-column>
<el-table-column fixed="right" label="操作">
<template slot-scope="scope">
<el-button
@click="handleClick(scope.row)"
type="text"
size="small"
>查看</el-button
>
<el-button type="text" size="small">编辑</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
exampleList: [
{
label: "cmcf-scfp",
value: "0",
},
],
form: {
name: "985e1a832f5317923eccf1a0caa8b6c6",
region: "",
date: "",
delivery: false,
type: [],
resource: "",
desc: "",
},
tableData: [
{
date: "2016-05-02",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1518 弄",
zip: 200333,
},
{
date: "2016-05-04",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1517 弄",
zip: 200333,
},
{
date: "2016-05-01",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1519 弄",
zip: 200333,
},
{
date: "2016-05-03",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1516 弄",
zip: 200333,
},
],
};
},
methods: {
onSubmit() {
console.log("submit!");
},
},
};
</script>
<style lang="scss" scoped>
.title {
display: flex;
background-color: #f0f7ff;
border: 1px solid #84b4ff;
border-radius: 6px;
color: #343434;
font-size: 12px;
padding: 8px;
margin: 16px 0;
}
// 内容
.container {
background-color: #fff;
border-radius: 2px;
display: flex;
flex: 1;
overflow: hidden;
width: 100%;
}
.content-container {
width: 100%;
height: 450px;
overflow-y: scroll;
padding-left: 16px;
}
.example-container {
border-right: 1px solid #e3e8f2;
display: flex;
flex-direction: column;
overflow: hidden;
}
.example-title {
align-items: center;
background-color: #fafafa;
display: flex;
font-weight: 500;
height: 40px;
padding: 0 24px;
color: #343434;
font-size: 12px;
font-weight: 500;
.use {
width: 172px;
}
.real {
width: 50px;
}
}
// 应用下面的内容
.example-item {
display: flex;
height: 40px;
line-height: 40px;
padding: 0 20px;
.data-name1 {
width: 172px;
color: #343434;
font-size: 12px;
.el-icon-s-order {
color: #84b4ff;
margin-right: 10px;
font-size: 18px;
}
}
.data-name2 {
width: 50px;
color: #343434;
font-size: 12px;
}
}
</style>