Merge remote-tracking branch 'origin/master'

This commit is contained in:
wenyann 2021-01-26 17:39:43 +08:00
commit ff0d8665f6
37 changed files with 215 additions and 133 deletions

View File

@ -59,6 +59,20 @@ public class MsScenario extends MsTestElement {
if (!this.isEnable()) {
return;
}
if (this.getReferenced() != null && this.getReferenced().equals("Deleted")) {
return;
} else if (this.getReferenced() != null && this.getReferenced().equals("REF")) {
try {
ApiAutomationService apiAutomationService = CommonBeanFactory.getBean(ApiAutomationService.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
ApiScenarioWithBLOBs scenario = apiAutomationService.getApiScenario(this.getId());
JSONObject element = JSON.parseObject(scenario.getScenarioDefinition());
hashTree = mapper.readValue(element.getString("hashTree"), new TypeReference<LinkedList<MsTestElement>>() {});
} catch (Exception ex) {
ex.printStackTrace();
}
}
config.setStep(this.name);
config.setStepType("SCENARIO");
config.setEnableCookieShare(enableCookieShare);
@ -72,26 +86,6 @@ public class MsScenario extends MsTestElement {
if (CollectionUtils.isNotEmpty(this.getVariables())) {
config.setVariables(this.variables);
}
if (this.getReferenced() != null && this.getReferenced().equals("Deleted")) {
return;
} else if (this.getReferenced() != null && this.getReferenced().equals("REF")) {
try {
ApiAutomationService apiAutomationService = CommonBeanFactory.getBean(ApiAutomationService.class);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
ApiScenarioWithBLOBs scenario = apiAutomationService.getApiScenario(this.getId());
JSONObject element = JSON.parseObject(scenario.getScenarioDefinition());
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"), new TypeReference<LinkedList<MsTestElement>>() {
});
if (hashTree == null) {
hashTree = elements;
} else {
hashTree.addAll(elements);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
// 场景变量和环境变量
tree.add(arguments(config));
addCsvDataSet(tree);

View File

@ -124,6 +124,12 @@ public class ApiAutomationService {
apiScenarioMapper.deleteByExample(example);
}
public void removeToGcByIds(List<String> nodeIds) {
ApiScenarioExample example = new ApiScenarioExample();
example.createCriteria().andApiScenarioModuleIdIn(nodeIds);
extApiScenarioMapper.removeToGcByExample(example);
}
public ApiScenario create(SaveApiScenarioRequest request, List<MultipartFile> bodyFiles) {
request.setId(UUID.randomUUID().toString());
checkNameExist(request);

View File

@ -174,6 +174,11 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
ApiModuleExample.Criteria criteria = example.createCriteria();
criteria.andNameEqualTo(node.getName())
.andProjectIdEqualTo(node.getProjectId());
if (StringUtils.isNotBlank(node.getProtocol())) {
criteria.andProtocolEqualTo(node.getProtocol());
}
if (StringUtils.isNotBlank(node.getParentId())) {
criteria.andParentIdEqualTo(node.getParentId());
} else {
@ -235,7 +240,7 @@ public class ApiModuleService extends NodeTreeService<ApiModuleDTO> {
public int deleteNode(List<String> nodeIds) {
ApiDefinitionExample apiDefinitionExample = new ApiDefinitionExample();
apiDefinitionExample.createCriteria().andModuleIdIn(nodeIds);
apiDefinitionMapper.deleteByExample(apiDefinitionExample);
extApiDefinitionMapper.removeToGcByExample(apiDefinitionExample); // 删除模块则模块下的接口放入回收站
ApiModuleExample apiDefinitionNodeExample = new ApiModuleExample();
apiDefinitionNodeExample.createCriteria().andIdIn(nodeIds);

View File

@ -194,7 +194,7 @@ public class ApiScenarioModuleService extends NodeTreeService<ApiScenarioModuleD
}
public int deleteNode(List<String> nodeIds) {
apiAutomationService.deleteByIds(nodeIds);
apiAutomationService.removeToGcByIds(nodeIds);
ApiScenarioModuleExample apiScenarioModuleExample = new ApiScenarioModuleExample();
apiScenarioModuleExample.createCriteria().andIdIn(nodeIds);

View File

@ -39,8 +39,11 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.URL;
import java.nio.channels.FileChannel;
import java.util.*;
@Service
@ -276,45 +279,12 @@ public class HistoricalDataUpgradeService {
private static final String BODY_FILE_DIR = "/opt/metersphere/data/body";
//文件的拷贝
private static void copyFile(String sourcePath, String newPath) {
File readfile = new File(sourcePath);
File newFile = new File(newPath);
BufferedWriter bufferedWriter = null;
Writer writer = null;
FileOutputStream fileOutputStream = null;
BufferedReader bufferedReader = null;
try {
fileOutputStream = new FileOutputStream(newFile, true);
writer = new OutputStreamWriter(fileOutputStream, "UTF-8");
bufferedWriter = new BufferedWriter(writer);
bufferedReader = new BufferedReader(new FileReader(readfile));
String line = null;
while ((line = bufferedReader.readLine()) != null) {
bufferedWriter.write(line);
bufferedWriter.newLine();
bufferedWriter.flush();
}
} catch (IOException e) {
public static void copyFile(String sourcePath, String newPath) {
try (FileChannel inChannel = new FileInputStream(new File(sourcePath)).getChannel();
FileChannel outChannel = new FileOutputStream(new File(newPath)).getChannel();) {
inChannel.transferTo(0, inChannel.size(), outChannel);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (bufferedWriter != null) {
bufferedWriter.close();
}
if (bufferedReader != null) {
bufferedReader.close();
}
if (writer != null) {
writer.close();
}
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

View File

@ -6,6 +6,8 @@ import io.metersphere.api.dto.definition.ApiDefinitionRequest;
import io.metersphere.api.dto.definition.ApiDefinitionResult;
import io.metersphere.api.dto.definition.ApiSwaggerUrlDTO;
import io.metersphere.base.domain.ApiDefinition;
import io.metersphere.base.domain.ApiDefinitionExample;
import io.metersphere.base.domain.ApiModuleExample;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@ -19,6 +21,8 @@ public interface ExtApiDefinitionMapper {
int removeToGc(@Param("ids") List<String> ids);
int removeToGcByExample(ApiDefinitionExample example);
int reduction(@Param("ids") List<String> ids);
List<ApiDataCountResult> countProtocolByProjectID(String projectId);

View File

@ -311,6 +311,15 @@
</foreach>
</update>
<update id="removeToGcByExample" parameterType="io.metersphere.base.domain.ApiDefinitionExample">
update api_definition
set
status = 'Trash', module_path = null, module_id = null
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</update>
<update id="reduction">
update api_definition
set

View File

@ -4,6 +4,7 @@ import io.metersphere.api.dto.automation.ApiScenarioDTO;
import io.metersphere.api.dto.automation.ApiScenarioRequest;
import io.metersphere.api.dto.datacount.ApiDataCountResult;
import io.metersphere.base.domain.ApiScenario;
import io.metersphere.base.domain.ApiScenarioExample;
import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import org.apache.ibatis.annotations.Param;
@ -20,6 +21,8 @@ public interface ExtApiScenarioMapper {
int removeToGc(@Param("ids") List<String> ids);
int removeToGcByExample(ApiScenarioExample example);
int reduction(@Param("ids") List<String> ids);
long countByProjectID(String projectId);

View File

@ -7,6 +7,35 @@
<result column="project_name" property="projectName"/>
<result column="user_name" property="userName"/>
</resultMap>
<sql id="Example_Where_Clause">
<where>
<foreach collection="oredCriteria" item="criteria" separator="or">
<if test="criteria.valid">
<trim prefix="(" prefixOverrides="and" suffix=")">
<foreach collection="criteria.criteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="condition">
<choose>
<when test='${object}.operator == "like"'>
@ -243,6 +272,15 @@
</foreach>
</update>
<update id="removeToGcByExample" parameterType="io.metersphere.base.domain.ApiScenarioExample">
update api_scenario
set
status = 'Trash', module_path = null, api_scenario_module_id = null
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</update>
<update id="reduction">
update api_scenario
set

View File

@ -1,5 +1,5 @@
package io.metersphere.commons.constants;
public enum UserSource {
LOCAL, LDAP
LOCAL, LDAP, CAS, OIDC
}

View File

@ -28,6 +28,7 @@ public class ShiroUtils {
filterChainDefinitionMap.put("/authsource/list/allenable", "anon");
filterChainDefinitionMap.put("/sso/signin", "anon");
filterChainDefinitionMap.put("/sso/callback", "anon");
// for swagger
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
filterChainDefinitionMap.put("/swagger-ui/**", "anon");

View File

@ -56,13 +56,9 @@ public class LoginController {
}
@GetMapping(value = "/signout")
public ResultHolder logout() {
String ssoMode = env.getProperty("sso.mode");
if (ssoMode != null && StringUtils.equalsIgnoreCase(SsoMode.CAS.name(), ssoMode)) {
return ResultHolder.error("sso");
} else {
SecurityUtils.getSubject().logout();
}
public ResultHolder logout() throws Exception {
userService.logout();
SecurityUtils.getSubject().logout();
return ResultHolder.success("");
}

View File

@ -389,8 +389,6 @@ public class JmeterDocumentParser implements DocumentParser {
element.appendChild(createStringProp(document, "HTTPSampler.concurrentPool", "6"));
element.appendChild(createStringProp(document, "HTTPSampler.connect_timeout", ""));
element.appendChild(createStringProp(document, "HTTPSampler.response_timeout", ""));
element.appendChild(createBoolProp(document, "HTTPSampler.image_parser", true));
element.appendChild(createBoolProp(document, "HTTPSampler.concurrentDwn", true));
hashTree.appendChild(element);
// 空的 hashTree
hashTree.appendChild(document.createElement(HASH_TREE_ELEMENT));

View File

@ -10,6 +10,7 @@ import io.metersphere.commons.utils.LogUtil;
import io.metersphere.dto.NodeDTO;
import io.metersphere.dto.TestResourcePoolDTO;
import io.metersphere.i18n.Translator;
import javafx.util.Pair;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
@ -39,29 +40,16 @@ public class NodeResourcePoolService {
}
deleteTestResource(testResourcePool.getId());
List<String> nodeIps = testResourcePool.getResources().stream()
List Ip_Port = testResourcePool.getResources().stream()
.map(resource -> {
NodeDTO nodeDTO = JSON.parseObject(resource.getConfiguration(), NodeDTO.class);
return nodeDTO.getIp();
return new Pair(nodeDTO.getIp(), nodeDTO.getPort());
})
.distinct()
.collect(Collectors.toList());
List<Integer> nodePorts = testResourcePool.getResources().stream()
.map(resource -> {
NodeDTO nodeDTO = JSON.parseObject(resource.getConfiguration(), NodeDTO.class);
return nodeDTO.getPort();
})
.distinct()
.collect(Collectors.toList());
if (nodeIps.size() < testResourcePool.getResources().size() && nodePorts.size() < testResourcePool.getResources().size()) {
if (Ip_Port.size() < testResourcePool.getResources().size()) {
MSException.throwException(Translator.get("duplicate_node_ip_port"));
}
else if (nodeIps.size() < testResourcePool.getResources().size()) {
MSException.throwException(Translator.get("duplicate_node_ip"));
}
else if (nodePorts.size() < testResourcePool.getResources().size()) {
MSException.throwException(Translator.get("duplicate_node_port"));
}
testResourcePool.setStatus(VALID.name());
boolean isValid = true;
for (TestResource resource : testResourcePool.getResources()) {

View File

@ -0,0 +1,5 @@
package io.metersphere.service;
public interface SSOService {
void logout() throws Exception;
}

View File

@ -10,6 +10,7 @@ import io.metersphere.commons.constants.UserStatus;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.user.SessionUser;
import io.metersphere.commons.utils.CodingUtil;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.controller.ResultHolder;
import io.metersphere.controller.request.LoginRequest;
@ -608,4 +609,11 @@ public class UserService {
public List<User> searchUser(String condition) {
return extUserMapper.searchUser(condition);
}
public void logout() throws Exception {
SSOService ssoService = CommonBeanFactory.getBean(SSOService.class);
if (ssoService != null) {
ssoService.logout();
}
}
}

@ -1 +1 @@
Subproject commit a18f543c2be6bcd8521a22094bb11aacc920ece4
Subproject commit ed891ee7503cc1ca4679b4779a5c12e2ffee986d

View File

@ -22,6 +22,7 @@
:trash-enable="trashEnable"
:checkRedirectID="checkRedirectID"
:isRedirectEdit="isRedirectEdit"
@openScenario="editScenario"
@edit="editScenario"
@changeSelectDataRangeAll="changeSelectDataRangeAll"
ref="apiScenarioList"/>

View File

@ -28,7 +28,13 @@
<el-table-column prop="num" label="ID"
sortable="custom"
show-overflow-tooltip/>
show-overflow-tooltip>
<template slot-scope="scope">
<el-tooltip content="编辑">
<a style="cursor:pointer" @click="edit(scope.row)"> {{ scope.row.num }} </a>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="name"
sortable="custom"
:label="$t('api_test.automation.scenario_name')"
@ -100,7 +106,7 @@
<ms-table-operator-button :tip="$t('api_test.automation.copy')" icon="el-icon-document-copy" type=""
@exec="copy(row)"/>
<ms-table-operator-button :tip="$t('api_test.automation.remove')" icon="el-icon-delete" @exec="remove(row)" type="danger" v-tester/>
<ms-scenario-extend-buttons :row="row"/>
<ms-scenario-extend-buttons @openScenario="openScenario" :row="row"/>
</div>
</template>
</el-table-column>
@ -589,6 +595,9 @@ export default {
_filter(filters, this.condition);
this.search();
},
openScenario (item) {
this.$emit('openScenario', item)
},
}
}
</script>

View File

@ -3,12 +3,20 @@
width="45%" :destroy-on-close="true" >
<span>{{ $t('api_test.automation.scenario_ref') }}</span>
<div class="refs" v-loading="scenarioLoading">
<div v-for="(item, index) in scenarioRefs" :key="index" class="el-button--text">{{ item.name }}</div>
<div v-for="(item, index) in scenarioRefs" :key="index" class="el-button--text">
<el-link @click="openScenario(item)">
{{ item.name }}
</el-link>
</div>
</div>
<span>{{ $t('api_test.automation.plan_ref') }}</span>
<div class="refs">
<div v-for="(item, index) in planRefs" :key="index" class="el-button--text">{{ item.name }}</div>
<div v-for="(item, index) in planRefs" :key="index" class="el-button--text">
<router-link :to="'/track/plan/view/' + item.id">
{{ item.name }}
</router-link>
</div>
</div>
<template v-slot:footer>
@ -47,6 +55,10 @@
open(row) {
this.getReferenceData(row);
this.visible = true
},
openScenario(item) {
this.$emit('openScenario', item);
this.visible = false;
}
}
}

View File

@ -10,7 +10,7 @@
<el-dropdown-item command="create_performance" v-tester>{{ $t('api_test.create_performance_test') }}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<ms-reference-view ref="viewRef"/>
<ms-reference-view @openScenario="openScenario" ref="viewRef"/>
<ms-schedule-maintain ref="scheduleMaintain" @refreshTable="refreshTable"/>
</div>
@ -64,6 +64,9 @@
})
});
},
openScenario (item) {
this.$emit('openScenario', item)
},
refreshTable() {
}

View File

@ -227,7 +227,7 @@
}); // tab ctrl + s
let tabs = this.apiTabs;
let index = tabs.findIndex(item => item.name === tab.name); // tabindex
if (index != -1) {
if (index != -1 && this.$refs.apiConfig[index - 1]) {
this.$refs.apiConfig[index - 1].addListener(); // tab ctrl + s index-1tab
}
}

View File

@ -234,6 +234,9 @@
} else {
request = JSON.parse(this.api.request);
}
if (!request.hashTree) {
request.hashTree = [];
}
let obj = {apiDefinitionId: this.api.id, name: '', priority: 'P0', active: true, tags: []};
obj.request = request;
this.apiCaseList.unshift(obj);

View File

@ -31,7 +31,13 @@
</template>
</el-table-column>
<el-table-column prop="num" label="ID" show-overflow-tooltip/>
<el-table-column prop="num" label="ID" show-overflow-tooltip>
<template slot-scope="scope">
<el-tooltip content="编辑">
<a style="cursor:pointer" @click="handleTestCase(scope.row)"> {{ scope.row.num }} </a>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="name" :label="$t('test_track.case.name')" show-overflow-tooltip/>
<el-table-column
@ -469,7 +475,10 @@ export default {
return ids;
},
showCaseRef(row) {
this.$refs.viewRef.open(row);
let param = {};
Object.assign(param, row);
param.moduleId = undefined;
this.$refs.viewRef.open(param);
},
showEnvironment(row) {

View File

@ -31,7 +31,13 @@
</el-table-column>
<el-table-column prop="num" label="ID" show-overflow-tooltip
sortable="custom"/>
sortable="custom">
<template slot-scope="scope">
<el-tooltip content="编辑">
<a style="cursor:pointer" @click="editApi(scope.row)"> {{ scope.row.num }} </a>
</el-tooltip>
</template>
</el-table-column>
<el-table-column prop="name" :label="$t('api_test.definition.api_name')"
show-overflow-tooltip
sortable="custom" min-width="120px"/>

View File

@ -5,14 +5,9 @@
</el-link>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="ref">{{ $t('api_test.automation.view_ref') }}</el-dropdown-item>
<!-- <el-dropdown-item :disabled="isCaseEdit" command="add_plan">{{ $t('api_test.automation.batch_add_plan') }}</el-dropdown-item>-->
<el-dropdown-item :disabled="isCaseEdit" command="create_performance">{{ $t('api_test.create_performance_test') }}</el-dropdown-item>
</el-dropdown-menu>
<ms-reference-view ref="viewRef"/>
<!--测试计划-->
<el-drawer :visible.sync="planVisible" :destroy-on-close="true" direction="ltr" :withHeader="false" :title="$t('test_track.plan_view.test_result')" :modal="false" size="90%">
<ms-test-plan-list @addTestPlan="addTestPlan"/>
</el-drawer>
</el-dropdown>
</template>
@ -36,7 +31,6 @@
planVisible: false,
}
},
methods: {
handleCommand(cmd) {
if (this.row.id) {
@ -44,9 +38,6 @@
case "ref":
this.$refs.viewRef.open(this.row);
break;
case "add_plan":
this.addCaseToPlan();
break;
case "create_performance":
this.createPerformance(this.row);
break;
@ -113,16 +104,6 @@
this.$emit('runRefresh', {});
});
},
addCaseToPlan() {
this.planVisible = true;
},
addTestPlan(plans) {
let obj = {planIds: plans, apiIds: [this.row.id]};
this.planVisible = false;
this.$post("/api/automation/scenario/plan", obj, response => {
this.$success(this.$t("commons.save_success"));
});
}
}
}

View File

@ -27,18 +27,30 @@
methods: {
addPre() {
let jsr223PreProcessor = createComponent("JSR223PreProcessor");
if (!this.request.hashTree) {
this.request.hashTree = [];
}
this.request.hashTree.push(jsr223PreProcessor);
},
addPost() {
let jsr223PostProcessor = createComponent("JSR223PostProcessor");
if (!this.request.hashTree) {
this.request.hashTree = [];
}
this.request.hashTree.push(jsr223PostProcessor);
},
addAssertions() {
let assertions = new Assertions();
if (!this.request.hashTree) {
this.request.hashTree = [];
}
this.request.hashTree.push(assertions);
},
addExtract() {
let jsonPostProcessor = new Extract();
if (!this.request.hashTree) {
this.request.hashTree = [];
}
this.request.hashTree.push(jsonPostProcessor);
},
}

View File

@ -105,21 +105,33 @@
methods: {
addPre() {
let jsr223PreProcessor = createComponent("JSR223PreProcessor");
if (!this.request.hashTree) {
this.request.hashTree = [];
}
this.request.hashTree.push(jsr223PreProcessor);
this.reload();
},
addPost() {
let jsr223PostProcessor = createComponent("JSR223PostProcessor");
if (!this.request.hashTree) {
this.request.hashTree = [];
}
this.request.hashTree.push(jsr223PostProcessor);
this.reload();
},
addAssertions() {
let assertions = new Assertions();
if (!this.request.hashTree) {
this.request.hashTree = [];
}
this.request.hashTree.push(assertions);
this.reload();
},
addExtract() {
let jsonPostProcessor = new Extract();
if (!this.request.hashTree) {
this.request.hashTree = [];
}
this.request.hashTree.push(jsonPostProcessor);
this.reload();
},

View File

@ -116,7 +116,7 @@
}
.search-bar {
width: 200px
width: 240px
}
</style>

View File

@ -28,6 +28,9 @@ import {getCurrentUser} from "@/common/js/utils";
import AboutUs from "./AboutUs";
import axios from "axios";
const requireComponent = require.context('@/business/components/xpack/', true, /\.vue$/);
const auth = requireComponent.keys().length > 0 ? requireComponent("./auth/Auth.vue") : {};
export default {
name: "MsUser",
components: {AboutUs},
@ -42,6 +45,17 @@ export default {
}
},
methods: {
logout: function () {
axios.get("/signout").then(response => {
if (response.data.success) {
localStorage.clear();
window.location.href = "/login";
}
}).catch(error => {
localStorage.clear();
window.location.href = "/login";
});
},
handleCommand(command) {
switch (command) {
case "personal":
@ -49,15 +63,7 @@ export default {
this.$router.push('/setting/personsetting').catch(error => error);
break;
case "logout":
axios.get("/signout").then(response => {
if (response.data.success) {
localStorage.clear();
window.location.href = "/login";
}
}).catch(error => {
localStorage.clear();
window.location.href = "/login";
});
this.logout();
break;
case "about":
this.$refs.aboutUs.open();

View File

@ -32,7 +32,7 @@
@cell-mouse-enter="showPopover"
row-key="id"
class="test-content adjust-table ms-select-all"
ref="table">
ref="table" @row-click="handleEdit">
<el-table-column
width="50"

View File

@ -3,7 +3,7 @@
:condition="condition"
@search="$emit('refresh')"
:show-create="false"
:tip="$t('commons.search_by_name_or_id')">
:tip="$t('commons.search_by_id_name_tag')">
<template v-slot:title>
接口用例
</template>

View File

@ -3,7 +3,7 @@
<el-card class="card-content" v-loading="result.loading">
<template v-slot:header>
<ms-table-header :is-tester-permission="true" :condition.sync="condition" @search="initTableData"
:show-create="false" :tip="$t('commons.search_by_name_or_id')">
:show-create="false" :tip="$t('commons.search_by_id_name_tag')">
<template v-slot:title>
<node-breadcrumb class="table-title" :nodes="selectParentNodes" @refresh="breadcrumbRefresh"/>
</template>

@ -1 +1 @@
Subproject commit 5abe43dc1f65b529ad59c17bfdc58aea33d23cad
Subproject commit 6d6ed5226849337876ecf55312aa6b5f13ba6472

View File

@ -71,7 +71,8 @@ export default {
not_filled: 'Not filled',
please_select: 'Please select',
search_by_name: 'Search by name',
search_by_name_or_id: 'Search by name or id',
search_by_name_or_id: 'Search by ID/NAME',
search_by_id_name_tag: 'Search by ID/NAME/TAG',
personal_information: 'Personal Information',
exit_system: 'Exit System',
verification: 'Verification',

View File

@ -72,7 +72,8 @@ export default {
not_filled: '未填写',
please_select: '请选择',
search_by_name: '根据名称搜索',
search_by_name_or_id: '根据ID或名称搜索',
search_by_name_or_id: '根据 ID/名称 搜索',
search_by_id_name_tag: '根据 ID/名称/标签 搜索',
personal_information: '个人信息',
exit_system: '退出系统',
verification: '验证',

View File

@ -72,7 +72,8 @@ export default {
not_filled: '未填寫',
please_select: '請選擇',
search_by_name: '根據名稱搜索',
search_by_name_or_id: '根據ID或名稱搜索',
search_by_name_or_id: '根據 ID/名稱 搜索',
search_by_id_name_tag: '根據 ID/名稱/標籤 搜索',
personal_information: '個人信息',
exit_system: '退出系統',
verification: '驗證',