feat(UI自动化): 调试支持本地浏览器运行

This commit is contained in:
nathan.liu 2022-05-11 10:13:13 +08:00 committed by 刘瑞斌
parent d20957dbb1
commit f03367ecf3
21 changed files with 310 additions and 17 deletions

View File

@ -20,6 +20,8 @@ public class RunDefinitionRequest {
private boolean saved; private boolean saved;
private boolean runLocal;
private String requestId; private String requestId;
private String name; private String name;

View File

@ -80,6 +80,9 @@ public class ParameterConfig extends MsParameter {
private String scenarioId; private String scenarioId;
private String reportType; private String reportType;
private boolean runLocal;
/** /**
* 排除生成临界控制器的场景 * 排除生成临界控制器的场景
*/ */

View File

@ -33,5 +33,7 @@ public class User implements Serializable {
private String platformInfo; private String platformInfo;
private String seleniumServer;
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
} }

View File

@ -13,6 +13,7 @@
<result column="last_workspace_id" jdbcType="VARCHAR" property="lastWorkspaceId" /> <result column="last_workspace_id" jdbcType="VARCHAR" property="lastWorkspaceId" />
<result column="phone" jdbcType="VARCHAR" property="phone" /> <result column="phone" jdbcType="VARCHAR" property="phone" />
<result column="source" jdbcType="VARCHAR" property="source" /> <result column="source" jdbcType="VARCHAR" property="source" />
<result column="selenium_server" jdbcType="VARCHAR" property="seleniumServer" />
<result column="last_project_id" jdbcType="VARCHAR" property="lastProjectId" /> <result column="last_project_id" jdbcType="VARCHAR" property="lastProjectId" />
<result column="create_user" jdbcType="VARCHAR" property="createUser" /> <result column="create_user" jdbcType="VARCHAR" property="createUser" />
</resultMap> </resultMap>
@ -79,7 +80,7 @@
</sql> </sql>
<sql id="Base_Column_List"> <sql id="Base_Column_List">
id, `name`, email, `password`, `status`, create_time, update_time, `language`, last_workspace_id, id, `name`, email, `password`, `status`, create_time, update_time, `language`, last_workspace_id,
phone, `source`, last_project_id, create_user phone, `source`, selenium_server, last_project_id, create_user
</sql> </sql>
<sql id="Blob_Column_List"> <sql id="Blob_Column_List">
platform_info platform_info
@ -372,6 +373,9 @@
<if test="platformInfo != null"> <if test="platformInfo != null">
platform_info = #{platformInfo,jdbcType=LONGVARCHAR}, platform_info = #{platformInfo,jdbcType=LONGVARCHAR},
</if> </if>
<if test="seleniumServer != null">
`selenium_server` = #{seleniumServer,jdbcType=VARCHAR},
</if>
</set> </set>
where id = #{id,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR}
</update> </update>

View File

@ -9,10 +9,7 @@ import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.PageUtils; import io.metersphere.commons.utils.PageUtils;
import io.metersphere.commons.utils.Pager; import io.metersphere.commons.utils.Pager;
import io.metersphere.commons.utils.SessionUtils; import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.controller.request.member.AddMemberRequest; import io.metersphere.controller.request.member.*;
import io.metersphere.controller.request.member.EditPassWordRequest;
import io.metersphere.controller.request.member.QueryMemberRequest;
import io.metersphere.controller.request.member.UserRequest;
import io.metersphere.controller.request.resourcepool.UserBatchProcessRequest; import io.metersphere.controller.request.resourcepool.UserBatchProcessRequest;
import io.metersphere.dto.UserDTO; import io.metersphere.dto.UserDTO;
import io.metersphere.dto.UserGroupPermissionDTO; import io.metersphere.dto.UserGroupPermissionDTO;
@ -269,4 +266,18 @@ public class UserController {
public Map<Object, Object> getWSAndProjectByUserId(@PathVariable String userId) { public Map<Object, Object> getWSAndProjectByUserId(@PathVariable String userId) {
return userService.getWSAndProjectByUserId(userId); return userService.getWSAndProjectByUserId(userId);
} }
/**
* 配置 用户的selenium-server 地址 ip:port
*/
@PostMapping("/update/seleniumServer")
@MsAuditLog(module = OperLogModule.SYSTEM_USER, type = OperLogConstants.UPDATE, title = "selenium-server地址")
public int updateSeleniumServer(@RequestBody EditSeleniumServerRequest request) {
return userService.updateUserSeleniumServer(request);
}
@GetMapping("/verify/seleniumServer")
public String verifySeleniumServer() {
return userService.verifyUserSeleniumServer();
}
} }

View File

@ -0,0 +1,10 @@
package io.metersphere.controller.request.member;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class EditSeleniumServerRequest {
private String seleniumServer;
}

View File

@ -15,6 +15,7 @@ public class ProjectConfig {
private Boolean caseCustomNum = false; private Boolean caseCustomNum = false;
private Boolean scenarioCustomNum = false; private Boolean scenarioCustomNum = false;
private String apiQuickMenu; private String apiQuickMenu;
private String uiQuickMenu;
private Boolean casePublic = false; private Boolean casePublic = false;
private Integer mockTcpPort = 0; private Integer mockTcpPort = 0;
private Boolean mockTcpOpen = false; private Boolean mockTcpOpen = false;

View File

@ -19,10 +19,7 @@ import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.controller.ResultHolder; import io.metersphere.controller.ResultHolder;
import io.metersphere.controller.request.LoginRequest; import io.metersphere.controller.request.LoginRequest;
import io.metersphere.controller.request.WorkspaceRequest; import io.metersphere.controller.request.WorkspaceRequest;
import io.metersphere.controller.request.member.AddMemberRequest; import io.metersphere.controller.request.member.*;
import io.metersphere.controller.request.member.EditPassWordRequest;
import io.metersphere.controller.request.member.QueryMemberRequest;
import io.metersphere.controller.request.member.UserRequest;
import io.metersphere.controller.request.resourcepool.UserBatchProcessRequest; import io.metersphere.controller.request.resourcepool.UserBatchProcessRequest;
import io.metersphere.dto.GroupResourceDTO; import io.metersphere.dto.GroupResourceDTO;
import io.metersphere.dto.UserDTO; import io.metersphere.dto.UserDTO;
@ -39,6 +36,7 @@ import io.metersphere.log.vo.OperatingLogDetails;
import io.metersphere.log.vo.system.SystemReference; import io.metersphere.log.vo.system.SystemReference;
import io.metersphere.notice.domain.UserDetail; import io.metersphere.notice.domain.UserDetail;
import io.metersphere.security.MsUserToken; import io.metersphere.security.MsUserToken;
import okhttp3.*;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType; import org.apache.ibatis.session.ExecutorType;
@ -59,6 +57,7 @@ import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static io.metersphere.commons.constants.SessionConstants.ATTR_USER; import static io.metersphere.commons.constants.SessionConstants.ATTR_USER;
@ -102,7 +101,7 @@ public class UserService {
} }
public Map<String, User> queryNameByIds(List<String> userIds) { public Map<String, User> queryNameByIds(List<String> userIds) {
if(userIds.isEmpty()){ if (userIds.isEmpty()) {
return new HashMap<>(0); return new HashMap<>(0);
} }
return extUserMapper.queryNameByIds(userIds); return extUserMapper.queryNameByIds(userIds);
@ -171,7 +170,7 @@ public class UserService {
private void checkQuota(QuotaService quotaService, String type, List<String> sourceIds, int size) { private void checkQuota(QuotaService quotaService, String type, List<String> sourceIds, int size) {
if (quotaService != null) { if (quotaService != null) {
Map<String, Integer> addMemberMap = sourceIds.stream().collect(Collectors.toMap( id -> id, id -> size)); Map<String, Integer> addMemberMap = sourceIds.stream().collect(Collectors.toMap(id -> id, id -> size));
quotaService.checkMemberCount(addMemberMap, type); quotaService.checkMemberCount(addMemberMap, type);
} }
} }
@ -1346,4 +1345,64 @@ public class UserService {
return false; return false;
} }
public int updateUserSeleniumServer(EditSeleniumServerRequest request) {
UserExample userExample = new UserExample();
userExample.createCriteria().andIdEqualTo(SessionUtils.getUser().getId());
List<User> users = userMapper.selectByExample(userExample);
if (!CollectionUtils.isEmpty(users)) {
User user = users.get(0);
String seleniumServer = request.getSeleniumServer();
user.setSeleniumServer(StringUtils.isBlank(seleniumServer) ? "" : seleniumServer.trim());
user.setUpdateTime(System.currentTimeMillis());
//更新session seleniumServer 信息
SessionUser sessionUser = SessionUtils.getUser();
sessionUser.setSeleniumServer(seleniumServer);
SessionUtils.putUser(sessionUser);
return userMapper.updateByPrimaryKeySelective(user);
}
MSException.throwException("更新selenium-server地址失败");
return 0;
}
public String verifyUserSeleniumServer() {
UserExample userExample = new UserExample();
userExample.createCriteria().andIdEqualTo(SessionUtils.getUser().getId());
List<User> users = userMapper.selectByExample(userExample);
if (!CollectionUtils.isEmpty(users)) {
User user = users.get(0);
if (StringUtils.isBlank(user.getSeleniumServer())) {
return "configErr";
}
OkHttpClient client = new OkHttpClient().newBuilder()
.connectTimeout(5, TimeUnit.SECONDS)
.build();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType,
"{\"operationName\":\"\",\"variables\":{},\"query\":\"query Summary {\\n grid {\\n uri\\n totalSlots\\n nodeCount\\n maxSession\\n sessionCount\\n sessionQueueSize\\n version\\n __typename\\n }\\n}\"}");
Request req = new Request.Builder()
.url(user.getSeleniumServer() + "/graphql")
.method("POST", body)
.addHeader("Content-Type", "application/json")
.build();
Response response = null;
try {
response = client.newCall(req).execute();
if (!response.isSuccessful()) {
return "connectionErr";
}
} catch (Exception e) {
return "connectionErr";
} finally {
try {
if (response != null) {
response.close();
}
} catch (Exception e) {
}
}
}
return "ok";
}
} }

@ -1 +1 @@
Subproject commit 04012284cd9cd16dd6270f01e71ec4714d67babf Subproject commit bdab35b7a74d9a77ca74aa0e41e813d28067afaf

View File

@ -0,0 +1,2 @@
alter table user
add selenium_server varchar(255) default "";

View File

@ -1083,6 +1083,12 @@
"id": "PERSONAL_INFORMATION:READ+THIRD_ACCOUNT", "id": "PERSONAL_INFORMATION:READ+THIRD_ACCOUNT",
"name": "permission.personal_information.third_account", "name": "permission.personal_information.third_account",
"resourceId": "PERSONAL_INFORMATION" "resourceId": "PERSONAL_INFORMATION"
},
{
"id": "PERSONAL_INFORMATION:READ+UI_SETTING",
"name": "permission.personal_information.ui_setting",
"resourceId": "PERSONAL_INFORMATION",
"license": true
} }
], ],
"resource": [ "resource": [

View File

@ -74,6 +74,8 @@
"eslint-plugin-vue": "^5.0.0", "eslint-plugin-vue": "^5.0.0",
"file-writer": "^1.0.2", "file-writer": "^1.0.2",
"html-webpack-inline-source-plugin": "0.0.10", "html-webpack-inline-source-plugin": "0.0.10",
"less": "^3.9.0",
"less-loader": "^7.3.0",
"vue-template-compiler": "2.6.14" "vue-template-compiler": "2.6.14"
}, },
"eslintConfig": { "eslintConfig": {

View File

@ -17,6 +17,7 @@ export default {
debug: Boolean, debug: Boolean,
reportId: String, reportId: String,
runData: Object, runData: Object,
runLocal: Boolean,
saved: Boolean, saved: Boolean,
environmentType: String, environmentType: String,
environmentGroupId: String environmentGroupId: String
@ -78,6 +79,7 @@ export default {
if (this.runData.variables) { if (this.runData.variables) {
reqObj.variables = this.runData.variables; reqObj.variables = this.runData.variables;
} }
reqObj.runLocal = this.runLocal;
this.$emit('runRefresh', {}); this.$emit('runRefresh', {});
let url = '/api/automation/run/debug'; let url = '/api/automation/run/debug';

View File

@ -46,6 +46,12 @@ export default {
return getCurrentUser(); return getCurrentUser();
}, },
}, },
mounted() {
this.$EventBus.$on('showPersonInfo', this.handleCommand)
},
beforeDestroy(){
this.$EventBus.$off("showPersonInfo")
},
methods: { methods: {
logout: function () { logout: function () {
logout(); logout();

View File

@ -39,6 +39,28 @@
</el-row> </el-row>
</el-tab-pane> </el-tab-pane>
<!-- UI 测试 -->
<el-tab-pane v-if="isXpack" :label="$t('commons.ui_test')" name="ui_test" >
<el-row style="margin-top: 10px">
<span style="font-weight:bold">{{ $t('commons.view_settings') }}</span>
</el-row>
<el-row style="margin-top: 15px">
<app-manage-item :title="$t('ui.ui_debug_mode')"
:append-span="12" :prepend-span="12" :middle-span="0">
<template #append>
<el-radio-group v-model="config.uiQuickMenu" @change="switchChange('UI_QUICK_MENU', $event)">
<el-radio label="local" value="local">
{{ $t('ui.ui_local_debug') }}
</el-radio>
<el-radio label="server" value="server">
{{ $t('ui.ui_server_debug') }}
</el-radio>
</el-radio-group>
</template>
</app-manage-item>
</el-row>
</el-tab-pane>
<el-tab-pane :label="$t('commons.api')" name="api"> <el-tab-pane :label="$t('commons.api')" name="api">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="8"> <el-col :span="8">
@ -178,6 +200,7 @@ export default {
caseCustomNum: false, caseCustomNum: false,
scenarioCustomNum: false, scenarioCustomNum: false,
apiQuickMenu: "", apiQuickMenu: "",
uiQuickMenu: "server",
casePublic: false, casePublic: false,
mockTcpPort: 0, mockTcpPort: 0,
mockTcpOpen: false, mockTcpOpen: false,
@ -224,6 +247,9 @@ export default {
if (res.data) { if (res.data) {
this.config = res.data; this.config = res.data;
this.config.shareReport = true; this.config.shareReport = true;
if(!this.config.uiQuickMenu){
this.config.uiQuickMenu = "server";
}
} }
}); });
} }

View File

@ -5,11 +5,13 @@
<el-tab-pane v-if="hasPermission('PERSONAL_INFORMATION:READ+API_KEYS')" name="commons.api_keys" :label="$t('commons.api_keys')" class="setting-item" ></el-tab-pane> <el-tab-pane v-if="hasPermission('PERSONAL_INFORMATION:READ+API_KEYS')" name="commons.api_keys" :label="$t('commons.api_keys')" class="setting-item" ></el-tab-pane>
<el-tab-pane v-if="hasPermission('PERSONAL_INFORMATION:READ+EDIT_PASSWORD')" name="change_password" :label="$t('member.edit_password')" class="setting-item" ></el-tab-pane> <el-tab-pane v-if="hasPermission('PERSONAL_INFORMATION:READ+EDIT_PASSWORD')" name="change_password" :label="$t('member.edit_password')" class="setting-item" ></el-tab-pane>
<el-tab-pane v-if="hasPermission('PERSONAL_INFORMATION:READ+THIRD_ACCOUNT')&&(hasJira||hasTapd||hasZentao||hasAzure)&&hasPermission('WORKSPACE_SERVICE:READ')" name="third_account" :label="$t('commons.third_account')" class="setting-item" ></el-tab-pane> <el-tab-pane v-if="hasPermission('PERSONAL_INFORMATION:READ+THIRD_ACCOUNT')&&(hasJira||hasTapd||hasZentao||hasAzure)&&hasPermission('WORKSPACE_SERVICE:READ')" name="third_account" :label="$t('commons.third_account')" class="setting-item" ></el-tab-pane>
<el-tab-pane v-if="hasPermission('PERSONAL_INFORMATION:READ+UI_SETTING') && isXpack" name="commons.ui_setting" :label="$t('commons.ui_setting')" class="setting-item" ></el-tab-pane>
</el-tabs> </el-tabs>
<ms-main-container> <ms-main-container>
<ms-person-from-setting v-if="activeIndex==='commons.personal_setting'" :form = form @getPlatformInfo = "getPlatformInfo" @cancel = "cancel" /> <ms-person-from-setting v-if="activeIndex==='commons.personal_setting'" :form = form @getPlatformInfo = "getPlatformInfo" @cancel = "cancel" />
<ms-api-keys v-if="activeIndex==='commons.api_keys'" /> <ms-api-keys v-if="activeIndex==='commons.api_keys'" />
<password-info v-if="activeIndex==='change_password'" :rule-form = "ruleForm" @cancel="cancel" ></password-info> <password-info v-if="activeIndex==='change_password'" :rule-form = "ruleForm" @cancel="cancel" ></password-info>
<ui-setting v-if="activeIndex==='commons.ui_setting'" @cancel="cancel"></ui-setting>
<el-form v-if="activeIndex==='third_account'" > <el-form v-if="activeIndex==='third_account'" >
<jira-user-info @auth="handleAuth" v-if="hasJira" :data="currentPlatformInfo" /> <jira-user-info @auth="handleAuth" v-if="hasJira" :data="currentPlatformInfo" />
<tapd-user-info @auth="handleAuth" v-if="hasTapd" :data="currentPlatformInfo" /> <tapd-user-info @auth="handleAuth" v-if="hasTapd" :data="currentPlatformInfo" />
@ -32,7 +34,8 @@
import MsApiKeys from "@/business/components/settings/personal/ApiKeys"; import MsApiKeys from "@/business/components/settings/personal/ApiKeys";
import MsMainContainer from "@/business/components/common/components/MsMainContainer"; import MsMainContainer from "@/business/components/common/components/MsMainContainer";
import PasswordInfo from "@/business/components/settings/personal/PasswordInfo"; import PasswordInfo from "@/business/components/settings/personal/PasswordInfo";
import {getCurrentUser, getCurrentWorkspaceId, hasPermission} from "@/common/js/utils"; import UiSetting from "@/business/components/settings/personal/UiSetting";
import {getCurrentUser, getCurrentWorkspaceId, hasPermission, hasLicense} from "@/common/js/utils";
import ZentaoUserInfo from "@/business/components/settings/personal/ZentaoUserInfo"; import ZentaoUserInfo from "@/business/components/settings/personal/ZentaoUserInfo";
import TapdUserInfo from "@/business/components/settings/personal/TapdUserInfo"; import TapdUserInfo from "@/business/components/settings/personal/TapdUserInfo";
import JiraUserInfo from "@/business/components/settings/personal/JiraUserInfo"; import JiraUserInfo from "@/business/components/settings/personal/JiraUserInfo";
@ -42,7 +45,7 @@
export default { export default {
name: "MsPersonRouter", name: "MsPersonRouter",
components: {MsMainContainer,MsPersonFromSetting,MsApiKeys,PasswordInfo,ZentaoUserInfo, TapdUserInfo, JiraUserInfo, AzureDevopsUserInfo}, components: {MsMainContainer,MsPersonFromSetting,MsApiKeys,PasswordInfo,ZentaoUserInfo, TapdUserInfo, JiraUserInfo, AzureDevopsUserInfo, UiSetting},
inject: [ inject: [
'reload', 'reload',
], ],
@ -69,6 +72,7 @@
hasTapd: false, hasTapd: false,
hasZentao: false, hasZentao: false,
hasAzure: false, hasAzure: false,
isXpack: false,
updatePath: '/user/update/current', updatePath: '/user/update/current',
form: {platformInfo: {}}, form: {platformInfo: {}},
currentPlatformInfo: { currentPlatformInfo: {
@ -84,6 +88,17 @@
projectList:[] projectList:[]
} }
}, },
mounted() {
this.$EventBus.$on('siwtchActive', (item) => {
if(item){
this.activeIndex = item
}
})
this.isXpack = hasLicense();
},
beforeDestroy(){
this.$EventBus.$off("siwtchActive")
},
methods:{ methods:{
hasPermission, hasPermission,
currentUser: () => { currentUser: () => {
@ -201,7 +216,7 @@
this.activeIndex = 'third_account'; this.activeIndex = 'third_account';
return; return;
} }
} },
}, },
created() { created() {
this.getActiveIndex(); this.getActiveIndex();

View File

@ -0,0 +1,124 @@
<template>
<div class="setting-container">
<div class="server-setting-row">
<div class="server-label">本地 selenium-server 地址</div>
<div class="server-input">
<el-input
size="small"
type="text"
v-model="seleniumServer"
@input="change()"
/>
</div>
<div class="server-desc">(示例: http://192.168.1.101:4444)</div>
</div>
<div class="setting-opt-row">
<el-button size="small" @click="cancel">{{
$t("commons.cancel")
}}</el-button>
<el-button
size="small"
type="primary"
@click="updateSeleniumServer()"
@keydown.enter.native.prevent
>{{ $t("commons.confirm") }}</el-button
>
</div>
</div>
</template>
<script>
import { getCurrentUserId } from "@/common/js/utils";
export default {
name: "UiSetting",
data() {
return {
updateSeleniumServerPath: "/user/update/seleniumServer",
seleniumServer: "",
};
},
mounted() {
this.getUserSeleniumServer();
setTimeout(() => {
this.change();
}, 10);
},
methods: {
change() {
this.$forceUpdate();
},
cancel() {
this.$emit("cancel");
},
confirm() {
this.$emit("confirm");
},
async getUserSeleniumServer() {
let userId = getCurrentUserId();
let res = await this.$get(`/user/info/${userId}`);
if (res.data) {
this.seleniumServer = res.data.data.seleniumServer || "";
}
},
updateSeleniumServer() {
if (this.seleniumServer) {
if (!this.isURL(this.seleniumServer)) {
this.$error(this.$t("selenium-server 输入不合法!"));
return;
}
}
// seleniumServer
this.result = this.$post(
this.updateSeleniumServerPath,
{ seleniumServer: this.seleniumServer },
(response) => {
if (!response.data) {
this.$error(this.$t("selenium-server 配置失败!"));
} else {
this.$success(this.$t("commons.modify_success"));
}
}
);
},
isURL(url) {
let regEx =
/^(http|https):\/\/(([0-9]{1,3}\.){3}[0-9]{1,3}|([0-9a-z_!~*'()-]+\.)*([0-9a-z][0-9a-z-]{0,61})?[0-9a-z]\.[a-z]{2,6})(:[0-9]{1,5})?$/;
if (regEx.test(url)) {
return true;
} else {
return false;
}
},
},
};
</script>
<style scope lang="less">
.setting-container {
padding-left: 50px;
.server-setting-row {
margin: 10px 0px;
.server-label {
font-size: 15px;
color: #606266;
}
.server-input {
margin: 10px 0px 5px 0;
.el-input__inner {
width: 300px !important;
}
}
.server-desc {
color: #909399;
font-size: 11px;
}
}
.setting-opt-row {
margin-top: 18px;
el-button {
}
}
}
</style>

@ -1 +1 @@
Subproject commit e30c5a16d53a4cc551066b22598e43b2f5d3a6ce Subproject commit 4bfd301399124b83199c4a767f8c7f42a5f6b20a

View File

@ -109,6 +109,7 @@ export default {
personal_setting: 'Personal Setting', personal_setting: 'Personal Setting',
api_keys: 'API Keys', api_keys: 'API Keys',
third_account: 'Third Account', third_account: 'Third Account',
ui_setting: 'UI Setting',
quota: 'Quota', quota: 'Quota',
test_resource_pool: 'Resource Pool', test_resource_pool: 'Resource Pool',
system_setting: 'Settings', system_setting: 'Settings',
@ -118,6 +119,7 @@ export default {
follow_api: 'Follow API definition', follow_api: 'Follow API definition',
response_time_delay: 'Response delay time', response_time_delay: 'Response delay time',
my_workstation: 'MyWorkstation', my_workstation: 'MyWorkstation',
ui_test: 'UiTest',
performance: 'Performance', performance: 'Performance',
enable_settings: 'Enable Settings', enable_settings: 'Enable Settings',
view_settings: 'View Settings', view_settings: 'View Settings',
@ -3124,6 +3126,7 @@ export default {
api_keys: 'API Keys', api_keys: 'API Keys',
edit_password: "EDIT PASSWORD", edit_password: "EDIT PASSWORD",
third_account: 'Third Account', third_account: 'Third Account',
ui_setting: 'UI Setting',
}, },
other: { other: {
track: "Track", track: "Track",
@ -3162,5 +3165,8 @@ export default {
ui_automation: "UI Automation", ui_automation: "UI Automation",
ui_element: "UI Element Library", ui_element: "UI Element Library",
report: "Test Report", report: "Test Report",
ui_debug_mode: 'UI debugging mode',
ui_local_debug: 'local',
ui_server_debug: 'server',
} }
}; };

View File

@ -102,6 +102,7 @@ export default {
personal_info: '个人信息', personal_info: '个人信息',
api_keys: 'API Keys', api_keys: 'API Keys',
third_account: '第三方平台账号', third_account: '第三方平台账号',
ui_setting: 'UI设置',
quota: '配额管理', quota: '配额管理',
status: '状态', status: '状态',
show_all: '显示全部', show_all: '显示全部',
@ -123,6 +124,7 @@ export default {
view_settings: '显示设置', view_settings: '显示设置',
functional: '功能测试', functional: '功能测试',
my_workstation: '我的工作台', my_workstation: '我的工作台',
ui_test: 'UI测试',
input_content: '请输入内容', input_content: '请输入内容',
create: '新建', create: '新建',
edit: '编辑', edit: '编辑',
@ -3129,6 +3131,7 @@ export default {
api_keys: 'API Keys', api_keys: 'API Keys',
edit_password: "修改密码", edit_password: "修改密码",
third_account: '第三方平台账号', third_account: '第三方平台账号',
ui_setting: 'UI设置',
}, },
other: { other: {
track: "测试跟踪", track: "测试跟踪",
@ -3214,6 +3217,9 @@ export default {
cmdExtraction: "数据提取", cmdExtraction: "数据提取",
cmdExtractWindow: "提取窗口信息", cmdExtractWindow: "提取窗口信息",
cmdExtractElement: "提取元素信息", cmdExtractElement: "提取元素信息",
valiate_fail: "校验失败,请检查必填项" valiate_fail: "校验失败,请检查必填项",
ui_debug_mode: 'UI自动化调试方式',
ui_local_debug: '本地调试',
ui_server_debug: '后端调试',
} }
}; };

View File

@ -102,6 +102,7 @@ export default {
personal_info: '個人信息', personal_info: '個人信息',
api_keys: 'API Keys', api_keys: 'API Keys',
third_account: '第三方平臺賬號', third_account: '第三方平臺賬號',
ui_setting: 'UI 設置',
quota: '配額管理', quota: '配額管理',
status: '狀態', status: '狀態',
show_all: '顯示全部', show_all: '顯示全部',
@ -123,6 +124,7 @@ export default {
view_settings: '顯示設置', view_settings: '顯示設置',
functional: '功能測試', functional: '功能測試',
my_workstation: '我的工作臺', my_workstation: '我的工作臺',
ui_test: 'UI測試',
input_content: '請輸入內容', input_content: '請輸入內容',
create: '新建', create: '新建',
edit: '編輯', edit: '編輯',
@ -3128,6 +3130,7 @@ export default {
api_keys: 'API Keys', api_keys: 'API Keys',
edit_password: "修改密碼", edit_password: "修改密碼",
third_account: '第三方平臺賬號', third_account: '第三方平臺賬號',
ui_setting: 'UI 設置',
}, },
other: { other: {
track: "測試跟蹤", track: "測試跟蹤",
@ -3166,5 +3169,8 @@ export default {
ui_automation: "UI 自動化", ui_automation: "UI 自動化",
ui_element: "元素庫", ui_element: "元素庫",
report: "測試報告", report: "測試報告",
ui_debug_mode: 'UI自動化調試管道',
ui_local_debug: '本地調試',
ui_server_debug: '後端調試',
} }
}; };