feat(UI自动化): 新增自定义指令及UI列表支持查看引用关系

--story=1009459 --user=刘瑶 【UI测试】支持自定义指令 https://www.tapd.cn/55049933/s/1244269
--story=1009531 --user=刘瑶 【UI测试】支持查看引用关系 https://www.tapd.cn/55049933/s/1244270
This commit is contained in:
nathan.liu 2022-09-06 16:02:53 +08:00 committed by nathanliu2022
parent ec07e6f5e1
commit 0e19f0a408
24 changed files with 256 additions and 13 deletions

View File

@ -540,8 +540,11 @@ public class ApiScenarioReportService {
}
scenario.setExecuteTimes(executeTimes + 1);
// 针对 UI 调试类型的不需要更新
String custom = "customCommand";
if (report.getExecuteType().equals(ExecuteType.Debug.name()) &&
report.getReportType().equals(ReportTypeConstants.UI_INDEPENDENT.name())) {
report.getReportType().equals(ReportTypeConstants.UI_INDEPENDENT.name()) &&
!StringUtils.equalsIgnoreCase(scenario.getScenarioType(), custom)
) {
return false;
}
uiScenarioMapper.updateByPrimaryKey(scenario);

View File

@ -10,4 +10,5 @@ public class ModuleNode extends TestCaseNode {
private Integer caseNum;
private String protocol;
private String modulePath;
private String scenarioType;
}

View File

@ -259,6 +259,11 @@ public class TestCaseNodeExample {
return (Criteria) this;
}
public Criteria andScenarioTypeEqualTo(String value) {
addCriterion("`scenario_type` =", value, "scenarioType");
return (Criteria) this;
}
public Criteria andNameNotEqualTo(String value) {
addCriterion("`name` <>", value, "name");
return (Criteria) this;

View File

@ -19,6 +19,8 @@ public class UiScenario implements Serializable {
private String name;
private String scenarioType;
private String level;
private String status;

View File

@ -19,5 +19,7 @@ public class UiScenarioReference implements Serializable {
private String dataType;
private Integer customId;
private static final long serialVersionUID = 1L;
}

View File

@ -10,6 +10,7 @@
<result column="module_path" jdbcType="VARCHAR" property="modulePath" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="level" jdbcType="VARCHAR" property="level" />
<result column="scenario_type" jdbcType="VARCHAR" property="scenarioType" />
<result column="status" jdbcType="VARCHAR" property="status" />
<result column="principal" jdbcType="VARCHAR" property="principal" />
<result column="step_total" jdbcType="INTEGER" property="stepTotal" />
@ -99,7 +100,7 @@
</where>
</sql>
<sql id="Base_Column_List">
id, project_id, tags, user_id, module_id, module_path, `name`, `level`, `status`,
id, project_id, tags, user_id, module_id, module_path, `name`, `level`, scenario_type,`status`,
principal, step_total, schedule, create_time, update_time, pass_rate, last_result,
report_id, num, original_state, custom_num, create_user, version, delete_time, delete_user_id,
execute_times, `order`, environment_type, environment_group_id, version_id, ref_id,
@ -159,7 +160,7 @@
<insert id="insert" parameterType="io.metersphere.base.domain.UiScenarioWithBLOBs">
insert into ui_scenario (id, project_id, tags,
user_id, module_id, module_path,
`name`, `level`, `status`,
`name`, `level`, scenario_type, `status`,
principal, step_total,
create_time, update_time, pass_rate,
last_result, report_id, num,
@ -170,7 +171,7 @@
latest, scenario_definition, description)
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{tags,jdbcType=VARCHAR},
#{userId,jdbcType=VARCHAR}, #{moduleId,jdbcType=VARCHAR}, #{modulePath,jdbcType=VARCHAR},
#{name,jdbcType=VARCHAR}, #{level,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
#{name,jdbcType=VARCHAR}, #{level,jdbcType=VARCHAR}, #{scenarioType,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
#{principal,jdbcType=VARCHAR}, #{stepTotal,jdbcType=INTEGER},
#{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{passRate,jdbcType=VARCHAR},
#{lastResult,jdbcType=VARCHAR}, #{reportId,jdbcType=VARCHAR}, #{num,jdbcType=INTEGER},
@ -207,6 +208,9 @@
<if test="level != null">
`level`,
</if>
<if test="scenarioType != null">
`scenario_type`,
</if>
<if test="status != null">
`status`,
</if>
@ -314,6 +318,9 @@
<if test="level != null">
#{level,jdbcType=VARCHAR},
</if>
<if test="scenarioType != null">
#{scenarioType,jdbcType=VARCHAR},
</if>
<if test="status != null">
#{status,jdbcType=VARCHAR},
</if>
@ -430,6 +437,9 @@
<if test="record.level != null">
`level` = #{record.level,jdbcType=VARCHAR},
</if>
<if test="record.scenarioType != null">
`scenario_type` = #{record.scenarioType,jdbcType=VARCHAR},
</if>
<if test="record.status != null">
`status` = #{record.status,jdbcType=VARCHAR},
</if>
@ -526,6 +536,7 @@
module_path = #{record.modulePath,jdbcType=VARCHAR},
`name` = #{record.name,jdbcType=VARCHAR},
`level` = #{record.level,jdbcType=VARCHAR},
scenario_type = #{record.scenarioType,jdbcType=VARCHAR},
`status` = #{record.status,jdbcType=VARCHAR},
principal = #{record.principal,jdbcType=VARCHAR},
step_total = #{record.stepTotal,jdbcType=INTEGER},
@ -567,6 +578,7 @@
module_path = #{record.modulePath,jdbcType=VARCHAR},
`name` = #{record.name,jdbcType=VARCHAR},
`level` = #{record.level,jdbcType=VARCHAR},
scenario_type = #{record.scenarioType,jdbcType=VARCHAR},
`status` = #{record.status,jdbcType=VARCHAR},
principal = #{record.principal,jdbcType=VARCHAR},
step_total = #{record.stepTotal,jdbcType=INTEGER},
@ -618,6 +630,9 @@
<if test="level != null">
`level` = #{level,jdbcType=VARCHAR},
</if>
<if test="scenarioType != null">
`scenario_type` = #{scenarioType,jdbcType=VARCHAR},
</if>
<if test="status != null">
`status` = #{status,jdbcType=VARCHAR},
</if>
@ -711,6 +726,7 @@
module_path = #{modulePath,jdbcType=VARCHAR},
`name` = #{name,jdbcType=VARCHAR},
`level` = #{level,jdbcType=VARCHAR},
scenario_type = #{scenarioType,jdbcType=VARCHAR},
`status` = #{status,jdbcType=VARCHAR},
principal = #{principal,jdbcType=VARCHAR},
step_total = #{stepTotal,jdbcType=INTEGER},
@ -744,6 +760,7 @@
module_path = #{modulePath,jdbcType=VARCHAR},
`name` = #{name,jdbcType=VARCHAR},
`level` = #{level,jdbcType=VARCHAR},
scenario_type = #{scenarioType,jdbcType=VARCHAR},
`status` = #{status,jdbcType=VARCHAR},
principal = #{principal,jdbcType=VARCHAR},
step_total = #{stepTotal,jdbcType=INTEGER},

View File

@ -3,6 +3,11 @@ package io.metersphere.base.mapper;
import io.metersphere.base.domain.UiScenarioReference;
import io.metersphere.base.domain.UiScenarioReferenceExample;
import java.util.List;
import io.metersphere.xpack.ui.dto.RefReq;
import io.metersphere.xpack.ui.dto.RefResp;
import io.metersphere.xpack.ui.dto.UiCheckRefDTO;
import io.metersphere.xpack.ui.dto.UiCheckRefReq;
import org.apache.ibatis.annotations.Param;
public interface UiScenarioReferenceMapper {
@ -27,4 +32,13 @@ public interface UiScenarioReferenceMapper {
int updateByPrimaryKeySelective(UiScenarioReference record);
int updateByPrimaryKey(UiScenarioReference record);
/**
* 获取引用信息
*/
List<RefResp> refList(@Param("request") RefReq request);
List<RefResp> getTestPlanRef(@Param("request") RefReq request);
List<UiCheckRefDTO> checkRef(@Param("request")UiCheckRefReq request);
}

View File

@ -240,4 +240,72 @@
data_type = #{dataType,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
<select id="refList" parameterType="io.metersphere.xpack.ui.dto.RefReq" resultType="io.metersphere.xpack.ui.dto.RefResp">
SELECT us.id AS targetId, us.name AS scenarioName , us.num AS id, p.name AS project, usf.create_time AS dateStr , w.name AS workspace FROM `ui_scenario_reference` usf
LEFT JOIN ui_scenario us ON usf.ui_scenario_id = us.id
LEFT JOIN project p ON us.project_id = p.id
LEFT JOIN `workspace` w ON p.workspace_id = w.id
WHERE usf.reference_id = #{request.scenarioId}
AND usf.reference_type = "REF"
AND us.scenario_type = #{request.scenarioType}
<if test="request.workspace != null">
AND w.id in
<foreach close=")" collection="request.workspace" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</if>
<if test="request.project != null">
AND p.id in
<foreach close=")" collection="request.project" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</if>
<if test="request.timeOrder != null and request.timeOrder == 1">
ORDER by usf.create_time DESC
</if>
<if test="request.timeOrder != null and request.timeOrder == 0">
ORDER by usf.create_time ASC
</if>
</select>
<select id="getTestPlanRef" parameterType="io.metersphere.xpack.ui.dto.RefReq" resultType="io.metersphere.xpack.ui.dto.RefResp">
SELECT tp.name AS scenarioName , us.id AS id, p.name AS project, us.create_time AS dateStr , w.name AS workspace, tp.id AS targetId
FROM
`test_plan_ui_scenario` us LEFT JOIN `test_plan` tp ON us.test_plan_id = tp.id
LEFT JOIN project p ON tp.project_id = p.id
LEFT JOIN `workspace` w ON p.workspace_id = w.id
WHERE
us.ui_scenario_id = #{request.scenarioId}
<if test="request.workspace != null">
AND w.id in
<foreach close=")" collection="request.workspace" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</if>
<if test="request.project != null">
AND p.id in
<foreach close=")" collection="request.project" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</if>
<if test="request.timeOrder != null and request.timeOrder == 1">
ORDER by us.create_time DESC
</if>
<if test="request.timeOrder != null and request.timeOrder == 0">
ORDER by us.create_time ASC
</if>
</select>
<select id="checkRef" parameterType="io.metersphere.xpack.ui.dto.UiCheckRefReq" resultType="io.metersphere.xpack.ui.dto.UiCheckRefDTO">
SELECT us.scenario_type AS scenarioType, us.name AS scenarioName, usf.reference_id AS scenarioId
FROM `ui_scenario_reference` usf left join ui_scenario us on usf.ui_scenario_id = us.id
WHERE usf.reference_id in
<foreach close=")" collection="request.scenarioIds" item="item" open="(" separator=",">
#{item}
</foreach>
AND usf.reference_type = "REF" ORDER BY usf.create_time DESC LIMIT 3;
</select>
</mapper>

View File

@ -17,6 +17,8 @@ public interface ExtModuleNodeMapper {
List<ModuleNodeDTO> getNodeTreeByProjectId(@Param("tableName") String tableName, @Param("projectId") String projectId);
List<ModuleNodeDTO> getNodeTreeByProjectIdWithType(@Param("tableName") String tableName, @Param("scenarioType") String scenarioType, @Param("projectId") String projectId);
List<ModuleNode> getAllNodeTree(@Param("tableName") String tableName);
int updateByPrimaryKeySelective(@Param("tableName") String tableName, @Param("record") ModuleNode record);
@ -27,6 +29,8 @@ public interface ExtModuleNodeMapper {
void insertWithModulePath(@Param("tableName") String tableName, @Param("record") ModuleNode record);
void insertWithModulePathAndType(@Param("tableName") String tableName, @Param("record") ModuleNode record);
ModuleNodeDTO get(@Param("tableName") String tableName, @Param("id") String id);
void updatePos(@Param("tableName") String tableName, @Param("id") String id, @Param("pos") Double pos);

View File

@ -17,6 +17,9 @@
<if test="record.modulePath != null">
`module_path`,
</if>
<if test="record.scenarioType != null">
`scenario_type`,
</if>
<if test="record.parentId != null">
parent_id,
</if>
@ -49,6 +52,9 @@
<if test="record.modulePath != null">
#{record.modulePath,jdbcType=VARCHAR},
</if>
<if test="record.scenarioType != null">
#{record.scenarioType,jdbcType=VARCHAR},
</if>
<if test="record.parentId != null">
#{record.parentId,jdbcType=VARCHAR},
</if>
@ -90,6 +96,17 @@
#{record.updateTime,jdbcType=BIGINT}, #{record.pos,jdbcType=DOUBLE},
#{record.createUser,jdbcType=VARCHAR})
</insert>
<insert id="insertWithModulePathAndType">
insert into ${tableName} (id, project_id, `name`, module_path, `scenario_type`,
parent_id, `level`, create_time,
update_time, pos, create_user)
values (#{record.id,jdbcType=VARCHAR}, #{record.projectId,jdbcType=VARCHAR}, #{record.name,jdbcType=VARCHAR},
#{record.modulePath,jdbcType=VARCHAR}, #{record.scenarioType,jdbcType=VARCHAR},
#{record.parentId,jdbcType=VARCHAR}, #{record.level,jdbcType=INTEGER},
#{record.createTime,jdbcType=BIGINT},
#{record.updateTime,jdbcType=BIGINT}, #{record.pos,jdbcType=DOUBLE},
#{record.createUser,jdbcType=VARCHAR})
</insert>
<update id="updateByPrimaryKeySelective">
update ${tableName}
<set>
@ -180,6 +197,13 @@
where project_id = #{projectId}
order by pos asc
</select>
<select id="getNodeTreeByProjectIdWithType" resultType="io.metersphere.track.dto.ModuleNodeDTO">
select
<include refid="io.metersphere.base.mapper.TestCaseNodeMapper.Base_Column_List"/>
from ${tableName}
where project_id = #{projectId} and `scenario_type` = #{scenarioType}
order by pos asc
</select>
<select id="selectByIds" resultType="io.metersphere.track.dto.ModuleNodeDTO">
select
<include refid="io.metersphere.base.mapper.TestCaseNodeMapper.Base_Column_List"/>

View File

@ -68,6 +68,10 @@ public enum ProjectApplicationType {
* 接口分享链接有效期
*/
API_SHARE_REPORT_TIME,
/**
* UI报告分享链接有效期
*/
UI_SHARE_REPORT_TIME,
/**
* 我的工作台-是否开启待更新时间限制

View File

@ -90,6 +90,8 @@ public class BaseQueryRequest {
*/
private boolean hasStep;
private String scenarioType;
public Map<String, List<String>> getFilters() {
if (MapUtils.isEmpty(filters) || filters.containsKey("isHandleCustomMultiple")) {
return filters;

View File

@ -118,6 +118,11 @@ public class BaseModuleService extends NodeTreeService<ModuleNodeDTO> {
if (StringUtils.isNotBlank(node.getId())) {
criteria.andIdNotEqualTo(node.getId());
}
if(StringUtils.isNotBlank(node.getScenarioType())){
criteria.andScenarioTypeEqualTo(node.getScenarioType());
}
if (extModuleNodeMapper.selectByExample(tableName, example).size() > 0) {
MSException.throwException(Translator.get("test_case_module_already_exists"));
}
@ -146,6 +151,29 @@ public class BaseModuleService extends NodeTreeService<ModuleNodeDTO> {
}
}
public ModuleNode getDefaultNodeWithType(String projectId, String type, String defaultName) {
TestCaseNodeExample example = new TestCaseNodeExample();
example.createCriteria().andProjectIdEqualTo(projectId).andScenarioTypeEqualTo(type).andNameEqualTo(Optional.ofNullable(defaultName).orElse("未规划用例")).andParentIdIsNull();
List<ModuleNode> list = extModuleNodeMapper.selectByExample(tableName, example);
if (CollectionUtils.isEmpty(list)) {
ModuleNode record = new ModuleNode();
record.setId(UUID.randomUUID().toString());
record.setCreateUser(SessionUtils.getUserId());
record.setName(Optional.ofNullable(defaultName).orElse("未规划用例"));
record.setPos(1.0);
record.setLevel(1);
record.setCreateTime(System.currentTimeMillis());
record.setUpdateTime(System.currentTimeMillis());
record.setProjectId(projectId);
record.setScenarioType(type);
extModuleNodeMapper.insertWithModulePathAndType(tableName, record);
record.setCaseNum(0);
return record;
} else {
return list.get(0);
}
}
public List<ModuleNodeDTO> getNodeTreeByProjectIdWithCount(String projectId, Function<QueryNodeRequest, List<Map<String, Object>>> getModuleCountFunc, String defaultName) {
// 判断当前项目下是否有默认模块没有添加默认模块
this.getDefaultNode(projectId, defaultName);

View File

@ -246,6 +246,8 @@ public class ProjectService {
projectApplicationMapper.insert(projectApplication);
projectApplication.setType(ProjectApplicationType.API_SHARE_REPORT_TIME.toString());
projectApplicationMapper.insert(projectApplication);
projectApplication.setType(ProjectApplicationType.UI_SHARE_REPORT_TIME.toString());
projectApplicationMapper.insert(projectApplication);
projectApplication.setType(ProjectApplicationType.CASE_CUSTOM_NUM.toString());
projectApplication.setTypeValue(Boolean.FALSE.toString());
projectApplicationMapper.insert(projectApplication);

@ -1 +1 @@
Subproject commit f30234a4342e77b32a7af1a2c8a94d27423fa54a
Subproject commit c6cd95f777577f8f1d478b13261021cc68d4079a

View File

@ -52,6 +52,7 @@ export const ELEMENT_TYPE = {
export const TYPE_TO_C = new Map([
['scenario', 'io.metersphere.api.dto.definition.request.MsScenario'],
['customCommand', 'io.metersphere.xpack.ui.hashtree.MsUiCustomCommand'],
['UiScenario', 'io.metersphere.xpack.ui.hashtree.MsUiScenario'],
['HTTPSamplerProxy', 'io.metersphere.api.dto.definition.request.sampler.MsHTTPSamplerProxy'],
['DubboSampler', 'io.metersphere.api.dto.definition.request.sampler.MsDubboSampler'],

View File

@ -1,7 +1,7 @@
<template>
<div>
<p>
<el-select v-model="operateModel" size="small" class="ms-select-step">
<el-select v-model="operateModel" size="small" class="ms-select-step" :disabled="isReadonly">
<el-option
v-for="item in operates"
:key="item.id"
@ -10,7 +10,7 @@
</el-option>
</el-select>
<el-select v-model="operateSubModel" size="small" class="ms-select-step" v-if="subOperates">
<el-select v-model="operateSubModel" size="small" class="ms-select-step" v-if="subOperates" :disabled="isReadonly">
<el-option
v-for="item in subOperates"
:key="item.value"
@ -20,6 +20,7 @@
</el-select>
<el-button
:disabled="isReadonly"
size="small"
type="primary"
@click="add">
@ -41,6 +42,10 @@ export default {
name: "addStepContainer",
components: {},
props: {
isReadonly:{
type: Boolean,
default: false,
},
showButton: {
type: Boolean,
default: true,

View File

@ -770,6 +770,18 @@ export const UI_TRASH_MODULE_TREE = _getModuleTree({
params: {}
})
export const UI_CUSTOM_COMMAND_MODULE_TREE = _getModuleTree({
url: "/ui/scenario/module/custom/list",
type: "GET",
params: {}
})
export const UI_CUSTOM_COMMAND_TRASH_MODULE_TREE = _getModuleTree({
url: "/ui/scenario/module/custom/trash/list",
type: "GET",
params: {}
})
export const TEST_CONFIGS = [ID, NAME, UPDATE_TIME, CREATE_TIME, STATUS, CREATOR, FOLLOW_PEOPLE];
export const PROJECT_CONFIGS = [NAME, UPDATE_TIME, CREATE_TIME, CREATOR];
@ -783,6 +795,9 @@ export const UI_REPORT_CONFIGS = [NAME, TEST_NAME, CREATE_TIME, UI_REPORT_STATUS
export const UI_SCENARIO_CONFIGS = [NAME, CREATE_TIME, API_STATUS, PROJECT_CREATOR, UI_MODULE_TREE];
export const UI_SCENARIO_CONFIGS_TRASH = [NAME, CREATE_TIME, API_STATUS_TRASH, PROJECT_CREATOR, UI_TRASH_MODULE_TREE];
export const UI_CUSTOM_COMMAND_CONFIGS = [NAME, CREATE_TIME, PROJECT_CREATOR, UI_CUSTOM_COMMAND_MODULE_TREE];
export const UI_CUSTOM_COMMAND_CONFIGS_TRASH = [NAME, CREATE_TIME, PROJECT_CREATOR, UI_CUSTOM_COMMAND_TRASH_MODULE_TREE];
// 测试跟踪-测试用例 列表
export const TEST_CASE_CONFIGS = [ID, NAME, TAGS, TEST_CASE_MODULE_TREE, CREATE_TIME, UPDATE_TIME, CREATOR, CASE_REVIEW_STATUS, FOLLOW_PEOPLE, CASE_DEMAND];

View File

@ -1,6 +1,7 @@
<template>
<div>
<el-table
:id="msTableKey"
v-if="tableActive"
border
class="test-content adjust-table ms-table"
@ -139,6 +140,7 @@ import HeaderLabelOperate from "@/business/components/common/head/HeaderLabelOpe
import HeaderCustom from "@/business/components/common/head/HeaderCustom";
import MsCustomTableHeader from "@/business/components/common/components/table/MsCustomTableHeader";
import {lineToHump} from "@/common/js/utils";
import {getUUID} from "@/common/js/utils";
/**
* 参考 ApiList
@ -166,7 +168,8 @@ export default {
selectIds: [],
hasBatchTipShow: false,
defaultSort: {},
tableActive: true
tableActive: true,
msTableKey: "msTableKey_" + getUUID(),
};
},
props: {
@ -343,7 +346,7 @@ export default {
if (this.rowOrderFunc) {
this.rowOrderFunc(param);
}
});
}, this.msTableKey);
}
},
isScrollShow(column, tableTop) { //

@ -1 +1 @@
Subproject commit 1fa61cb98c337a84b779e7a0f660f78e794db3ad
Subproject commit 6c12de172275146ff2bd666ccc93a6f59b95b709

View File

@ -629,9 +629,9 @@ export function clearShareDragParam() {
shareDragParam.data = null;
}
export function handleRowDrop(data, callback) {
export function handleRowDrop(data, callback, msTableKey) {
setTimeout(() => {
const tbody = document.querySelector('.el-table__body-wrapper tbody');
const tbody = document.querySelector(`#${msTableKey} .el-table__body-wrapper tbody`);
if (!tbody) {
return;
}

View File

@ -2918,6 +2918,20 @@ export default {
error_step_screenshot: "Screenshot of exception",
downloadScreenshot: "Download screenshot file",
description: "remark",
scenario_title: "Scenario",
custom_command_title: "Command",
custom_command_label: "Custom command",
automation_list: "Automation list",
create_custom_command: "Create command",
create_custom_command_label: "Create custom command",
import_by_list_label: "UI list import",
open_custom_command_label: "Open command",
debug_result_label: "Debug result",
scenario_ref_label: "Scenario reference",
command_ref_label: "Command reference",
test_plan_ref_label: "Test plan reference",
delete_scenario_lable: "Delete scenario",
delete_command_lable: "Delete command",
},
project_application: {
workstation: {

View File

@ -475,7 +475,8 @@ export default {
api_definition: '未规划接口',
api_scenario: '未规划场景',
ui_element: '未规划元素',
ui_scenario: '未规划场景'
ui_scenario: '未规划场景',
ui_module: "未规划模块",
},
template_delete: "模版删除",
executing: "正在执行...",
@ -2927,6 +2928,20 @@ export default {
error_step_screenshot: "出现异常截图",
downloadScreenshot: "下载截图文件",
description: "描述",
scenario_title: "场景",
custom_command_title: "指令",
custom_command_label: "自定义指令",
automation_list: "自动化列表",
create_custom_command: "创建指令",
create_custom_command_label: "创建自定义指令",
import_by_list_label: "UI列表导入",
open_custom_command_label: "打开指令",
debug_result_label: "调试结果",
scenario_ref_label: "场景引用",
command_ref_label: "指令引用",
test_plan_ref_label: "测试计划引用",
delete_scenario_lable: "删除场景",
delete_command_lable: "删除指令",
},
project_application: {
workstation: {

View File

@ -2907,6 +2907,20 @@ export default {
error_step_screenshot: "出現異常截圖",
downloadScreenshot: "下載截圖文件",
description: "備注",
scenario_title: "場景",
custom_command_title: "指令",
custom_command_label: "自定義指令",
automation_list: "自動化列錶",
create_custom_command: "創建指令",
create_custom_command_label: "創建自定義指令",
import_by_list_label: "UI列錶導入",
open_custom_command_label: "打開指令",
debug_result_label: "調試結果",
scenario_ref_label: "場景引用",
command_ref_label: "指令引用",
test_plan_ref_label: "測試計劃引用",
delete_scenario_lable: "刪除場景",
delete_command_lable: "刪除指令",
},
project_application: {
workstation: {