feat: TCP请求的相关交互和展示优化
接口定义TCP请求的交互和展示优化,TCP设置增加编码设置,TCP表头的请求类型改为协议方法,ESB报文增加Mock参数
This commit is contained in:
parent
3d0edb2e35
commit
214a6385fe
|
@ -20,6 +20,7 @@ import io.metersphere.commons.constants.DelimiterConstants;
|
||||||
import io.metersphere.commons.constants.MsTestElementConstants;
|
import io.metersphere.commons.constants.MsTestElementConstants;
|
||||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
import io.metersphere.commons.utils.LogUtil;
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
|
import io.metersphere.commons.utils.ScriptEngineUtils;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
|
@ -35,10 +36,13 @@ import org.apache.jmeter.testelement.property.StringProperty;
|
||||||
import org.apache.jorphan.collections.HashTree;
|
import org.apache.jorphan.collections.HashTree;
|
||||||
import org.apache.jorphan.collections.ListedHashTree;
|
import org.apache.jorphan.collections.ListedHashTree;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ -82,6 +86,9 @@ public class MsTCPSampler extends MsTestElement {
|
||||||
private String protocol = "TCP";
|
private String protocol = "TCP";
|
||||||
@JSONField(ordinal = 39)
|
@JSONField(ordinal = 39)
|
||||||
private String projectId;
|
private String projectId;
|
||||||
|
@JSONField(ordinal = 40)
|
||||||
|
private String connectEncoding;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新加两个参数,场景保存/修改时需要的参数。不会传递JMeter,只是用于最后的保留。
|
* 新加两个参数,场景保存/修改时需要的参数。不会传递JMeter,只是用于最后的保留。
|
||||||
|
@ -195,7 +202,21 @@ public class MsTCPSampler extends MsTestElement {
|
||||||
tcpSampler.setCloseConnection(String.valueOf(this.isCloseConnection()));
|
tcpSampler.setCloseConnection(String.valueOf(this.isCloseConnection()));
|
||||||
tcpSampler.setSoLinger(this.getSoLinger());
|
tcpSampler.setSoLinger(this.getSoLinger());
|
||||||
tcpSampler.setEolByte(this.getEolByte());
|
tcpSampler.setEolByte(this.getEolByte());
|
||||||
tcpSampler.setRequestData(this.getRequest());
|
|
||||||
|
String value = this.getRequest();
|
||||||
|
if(StringUtils.isNotEmpty(this.getConnectEncoding())){
|
||||||
|
if(StringUtils.equalsIgnoreCase("utf-8",this.getConnectEncoding())){
|
||||||
|
value = new String(value.getBytes(),StandardCharsets.UTF_8);
|
||||||
|
}else if(StringUtils.equalsIgnoreCase("gbk",this.getConnectEncoding())){
|
||||||
|
try {
|
||||||
|
value = new String(value.getBytes(),"GBK");
|
||||||
|
}catch (Exception e){
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tcpSampler.setRequestData(value);
|
||||||
|
|
||||||
tcpSampler.setProperty(ConfigTestElement.USERNAME, this.getUsername());
|
tcpSampler.setProperty(ConfigTestElement.USERNAME, this.getUsername());
|
||||||
tcpSampler.setProperty(ConfigTestElement.PASSWORD, this.getPassword());
|
tcpSampler.setProperty(ConfigTestElement.PASSWORD, this.getPassword());
|
||||||
return tcpSampler;
|
return tcpSampler;
|
||||||
|
@ -213,7 +234,19 @@ public class MsTCPSampler extends MsTestElement {
|
||||||
if (CollectionUtils.isNotEmpty(this.parameters)) {
|
if (CollectionUtils.isNotEmpty(this.parameters)) {
|
||||||
this.parameters.forEach(item -> {
|
this.parameters.forEach(item -> {
|
||||||
names.add(new StringProperty(new Integer(new Random().nextInt(1000000)).toString(), item.getName()));
|
names.add(new StringProperty(new Integer(new Random().nextInt(1000000)).toString(), item.getName()));
|
||||||
threadValues.add(new StringProperty(new Integer(new Random().nextInt(1000000)).toString(), item.getValue()));
|
String value = item.getValue();
|
||||||
|
value = this.formatMockValue(value);
|
||||||
|
if(StringUtils.isNotEmpty(this.getConnectEncoding())){
|
||||||
|
if(StringUtils.equalsIgnoreCase("utf-8",this.getConnectEncoding())){
|
||||||
|
value = new String(value.getBytes(),StandardCharsets.UTF_8);
|
||||||
|
}else if(StringUtils.equalsIgnoreCase("gbk",this.getConnectEncoding())){
|
||||||
|
try {
|
||||||
|
value = new String(value.getBytes(),"GBK");
|
||||||
|
}catch (Exception e){
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
threadValues.add(new StringProperty(new Integer(new Random().nextInt(1000000)).toString(), value));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
userParameters.setNames(new CollectionProperty(UserParameters.NAMES, names));
|
userParameters.setNames(new CollectionProperty(UserParameters.NAMES, names));
|
||||||
|
@ -222,7 +255,29 @@ public class MsTCPSampler extends MsTestElement {
|
||||||
userParameters.setThreadLists(new CollectionProperty(UserParameters.THREAD_VALUES, collectionPropertyList));
|
userParameters.setThreadLists(new CollectionProperty(UserParameters.THREAD_VALUES, collectionPropertyList));
|
||||||
tree.add(userParameters);
|
tree.add(userParameters);
|
||||||
}
|
}
|
||||||
|
private String formatMockValue(String value) {
|
||||||
|
|
||||||
|
String patten = ">@[^>@]+</?";
|
||||||
|
Pattern r = Pattern.compile(patten);
|
||||||
|
try{
|
||||||
|
Matcher m = r.matcher(value);
|
||||||
|
while (m.find()){
|
||||||
|
String findStr = m.group();
|
||||||
|
if(findStr.length() > 3){
|
||||||
|
findStr = findStr.substring(1,findStr.length()-2);
|
||||||
|
String replaceStr = ScriptEngineUtils.calculate(findStr);
|
||||||
|
if(StringUtils.equals(findStr,replaceStr)){
|
||||||
|
replaceStr = "";
|
||||||
|
}
|
||||||
|
value = value.replace(">"+findStr+"</",">"+replaceStr+"</");
|
||||||
|
m = r.matcher(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch (Exception e){
|
||||||
|
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
private ConfigTestElement tcpConfig() {
|
private ConfigTestElement tcpConfig() {
|
||||||
ConfigTestElement configTestElement = new ConfigTestElement();
|
ConfigTestElement configTestElement = new ConfigTestElement();
|
||||||
configTestElement.setEnabled(true);
|
configTestElement.setEnabled(true);
|
||||||
|
|
|
@ -39,11 +39,9 @@ public class EsbApiParamService {
|
||||||
|
|
||||||
public EsbApiParamsWithBLOBs createEsbApiParam(String resourceId, String esbDataStruct, String backedEsbDataStrcut, String backedScript) {
|
public EsbApiParamsWithBLOBs createEsbApiParam(String resourceId, String esbDataStruct, String backedEsbDataStrcut, String backedScript) {
|
||||||
EsbApiParamsWithBLOBs model = null;
|
EsbApiParamsWithBLOBs model = null;
|
||||||
|
|
||||||
EsbApiParamsExample example = new EsbApiParamsExample();
|
EsbApiParamsExample example = new EsbApiParamsExample();
|
||||||
example.createCriteria().andResourceIdEqualTo(resourceId);
|
example.createCriteria().andResourceIdEqualTo(resourceId);
|
||||||
List<EsbApiParamsWithBLOBs> list = esbApiParamsMapper.selectByExampleWithBLOBs(example);
|
List<EsbApiParamsWithBLOBs> list = esbApiParamsMapper.selectByExampleWithBLOBs(example);
|
||||||
|
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
String uuid = UUID.randomUUID().toString();
|
String uuid = UUID.randomUUID().toString();
|
||||||
model = new EsbApiParamsWithBLOBs();
|
model = new EsbApiParamsWithBLOBs();
|
||||||
|
|
|
@ -41,7 +41,7 @@
|
||||||
sortable="custom"
|
sortable="custom"
|
||||||
column-key="method"
|
column-key="method"
|
||||||
:filters="methodFilters"
|
:filters="methodFilters"
|
||||||
:label="$t('api_test.definition.api_type')"
|
:label="getApiRequestTypeName"
|
||||||
width="120px">
|
width="120px">
|
||||||
<template v-slot:default="scope">
|
<template v-slot:default="scope">
|
||||||
<el-tag size="mini"
|
<el-tag size="mini"
|
||||||
|
@ -228,6 +228,13 @@
|
||||||
} else {
|
} else {
|
||||||
return new Set();
|
return new Set();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
getApiRequestTypeName(){
|
||||||
|
if(this.currentProtocol === 'TCP'){
|
||||||
|
return this.$t('api_test.definition.api_agreement');
|
||||||
|
}else{
|
||||||
|
return this.$t('api_test.definition.api_type');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -69,7 +69,12 @@ export default {
|
||||||
return {
|
return {
|
||||||
validated: false,
|
validated: false,
|
||||||
apiProtocol: "TCP",
|
apiProtocol: "TCP",
|
||||||
methodTypes:["TCP"],
|
methodTypes:[
|
||||||
|
{
|
||||||
|
'key':"TCP",
|
||||||
|
'value':this.$t('api_test.request.tcp.general_format'),
|
||||||
|
}
|
||||||
|
],
|
||||||
showXpackCompnent:false,
|
showXpackCompnent:false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -85,7 +90,10 @@ export default {
|
||||||
this.showXpackCompnent = true;
|
this.showXpackCompnent = true;
|
||||||
if(hasLicense()){
|
if(hasLicense()){
|
||||||
if(this.methodTypes.length == 1){
|
if(this.methodTypes.length == 1){
|
||||||
this.methodTypes.push("ESB");
|
let esbMethodType = {};
|
||||||
|
esbMethodType.key = "ESB";
|
||||||
|
esbMethodType.value="ESB";
|
||||||
|
this.methodTypes.push(esbMethodType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<!-- <el-input class="ms-http-input" size="small" v-model="basicForm.name"/>-->
|
<!-- <el-input class="ms-http-input" size="small" v-model="basicForm.name"/>-->
|
||||||
<el-input v-model="basicForm.name" class="ms-http-input" size="small">
|
<el-input v-model="basicForm.name" class="ms-http-input" size="small">
|
||||||
<el-select v-model="basicForm.method" slot="prepend" style="width: 100px" size="small" @change="methodChange">
|
<el-select v-model="basicForm.method" slot="prepend" style="width: 100px" size="small" @change="methodChange">
|
||||||
<el-option v-for="item in methodTypes" :key="item" :label="item" :value="item"/>
|
<el-option v-for="item in methodTypes" :key="item.key" :label="item.value" :value="item.key"/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-input>
|
</el-input>
|
||||||
|
|
||||||
|
@ -16,20 +16,6 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item :label="$t('test_track.module.module')" prop="moduleId">
|
<el-form-item :label="$t('test_track.module.module')" prop="moduleId">
|
||||||
<!--<el-select class="ms-http-input" size="small" v-model="basicForm.moduleId" style="width: 100%" @change="reload">-->
|
|
||||||
<!--<div v-if="moduleOptions.length>0">-->
|
|
||||||
<!--<el-option v-for="item in moduleOptions" :key="item.id" :label="item.path" :value="item.id"/>-->
|
|
||||||
<!--</div>-->
|
|
||||||
<!--<div v-else>-->
|
|
||||||
<!--<el-option :key="0" :value="''">-->
|
|
||||||
<!--<div style="margin-left: 40px">-->
|
|
||||||
<!--<span style="font-size: 14px;color: #606266;font-weight: 48.93">{{ $t('api_test.definition.select_comp.no_data') }},-->
|
|
||||||
<!--</span>-->
|
|
||||||
<!--<el-link type="primary" @click="createModules">{{ $t('api_test.definition.select_comp.add_data') }}</el-link>-->
|
|
||||||
<!--</div>-->
|
|
||||||
<!--</el-option>-->
|
|
||||||
<!--</div>-->
|
|
||||||
<!--</el-select>-->
|
|
||||||
<ms-select-tree size="small" :data="moduleOptions" :defaultKey="basicForm.moduleId" @getValue="setModule" :obj="moduleObj" clearable checkStrictly/>
|
<ms-select-tree size="small" :data="moduleOptions" :defaultKey="basicForm.moduleId" @getValue="setModule" :obj="moduleObj" clearable checkStrictly/>
|
||||||
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
:filters="methodFilters"
|
:filters="methodFilters"
|
||||||
:fields-width="fieldsWidth"
|
:fields-width="fieldsWidth"
|
||||||
min-width="120px"
|
min-width="120px"
|
||||||
:label="$t('api_test.definition.api_type')">
|
:label="getApiRequestTypeName">
|
||||||
<template v-slot:default="scope" class="request-method">
|
<template v-slot:default="scope" class="request-method">
|
||||||
<el-tag size="mini"
|
<el-tag size="mini"
|
||||||
:style="{'background-color': getColor(true, scope.row.method), border: getColor(true, scope.row.method)}"
|
:style="{'background-color': getColor(true, scope.row.method), border: getColor(true, scope.row.method)}"
|
||||||
|
@ -398,6 +398,13 @@ export default {
|
||||||
selectRows() {
|
selectRows() {
|
||||||
return this.$refs.apiDefinitionTable.getSelectRows();
|
return this.$refs.apiDefinitionTable.getSelectRows();
|
||||||
},
|
},
|
||||||
|
getApiRequestTypeName(){
|
||||||
|
if(this.currentProtocol === 'TCP'){
|
||||||
|
return this.$t('api_test.definition.api_agreement');
|
||||||
|
}else{
|
||||||
|
return this.$t('api_test.definition.api_type');
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
created: function () {
|
created: function () {
|
||||||
if (this.trashEnable) {
|
if (this.trashEnable) {
|
||||||
|
@ -444,6 +451,12 @@ export default {
|
||||||
if (this.$refs.apiDefinitionTable) {
|
if (this.$refs.apiDefinitionTable) {
|
||||||
this.$refs.apiDefinitionTable.clearSelectRows();
|
this.$refs.apiDefinitionTable.clearSelectRows();
|
||||||
}
|
}
|
||||||
|
//关闭案例弹窗
|
||||||
|
if(this.$refs.caseList){
|
||||||
|
this.$refs.caseList.handleClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
initCondition(this.condition, this.condition.selectAll);
|
initCondition(this.condition, this.condition.selectAll);
|
||||||
this.selectDataCounts = 0;
|
this.selectDataCounts = 0;
|
||||||
this.condition.moduleIds = this.selectNodeIds;
|
this.condition.moduleIds = this.selectNodeIds;
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-link class="ms-el-link" @click="batchAdd" style="color: #783887"> {{$t("commons.batch_add")}}</el-link>
|
<el-link class="ms-el-link" @click="batchAdd" style="color: #783887"> {{$t("commons.batch_add")}}</el-link>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<ms-api-key-value :is-read-only="isReadOnly" :isShowEnable="isShowEnable" :suggestions="headerSuggestions" :items="headers" :need-mock="true"/>
|
<ms-api-key-value :is-read-only="isReadOnly" :isShowEnable="isShowEnable" :suggestions="headerSuggestions" :items="headers" :need-mock="true"/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
||||||
|
|
|
@ -73,12 +73,12 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="10" style="margin-left: 30px">
|
<el-row :gutter="10" style="margin-left: 30px">
|
||||||
<el-col :span="9">
|
<el-col :span="6">
|
||||||
<el-form-item :label="$t('api_test.request.tcp.re_use_connection')">
|
<el-form-item :label="$t('api_test.request.tcp.re_use_connection')">
|
||||||
<el-checkbox v-model="request.reUseConnection"/>
|
<el-checkbox v-model="request.reUseConnection"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="9">
|
<el-col :span="6">
|
||||||
<el-form-item :label="$t('api_test.request.tcp.close_connection')">
|
<el-form-item :label="$t('api_test.request.tcp.close_connection')">
|
||||||
<el-checkbox v-model="request.closeConnection"/>
|
<el-checkbox v-model="request.closeConnection"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
@ -88,6 +88,13 @@
|
||||||
<el-checkbox v-model="request.nodelay"/>
|
<el-checkbox v-model="request.nodelay"/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="6">
|
||||||
|
<el-form-item label="Connect encoding">
|
||||||
|
<el-select v-model="request.connectEncoding" style="width: 100px" size="small">
|
||||||
|
<el-option v-for="item in connectEncodingArr" :key="item.key" :label="item.value" :value="item.key"/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
@ -158,6 +165,16 @@
|
||||||
isReloadData: false,
|
isReloadData: false,
|
||||||
options: API_STATUS,
|
options: API_STATUS,
|
||||||
currentProjectId: "",
|
currentProjectId: "",
|
||||||
|
connectEncodingArr:[
|
||||||
|
{
|
||||||
|
'key':'UTF-8',
|
||||||
|
'value':'UTF-8',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'key':'GBK',
|
||||||
|
'value':'GBK',
|
||||||
|
},
|
||||||
|
],
|
||||||
rules: {
|
rules: {
|
||||||
classname: [{required: true, message: "请选择TCPClient", trigger: 'change'}],
|
classname: [{required: true, message: "请选择TCPClient", trigger: 'change'}],
|
||||||
server: [{required: true, message: this.$t('api_test.request.tcp.server_cannot_be_empty'), trigger: 'blur'}],
|
server: [{required: true, message: this.$t('api_test.request.tcp.server_cannot_be_empty'), trigger: 'blur'}],
|
||||||
|
@ -174,6 +191,9 @@
|
||||||
if (!this.request.tcpPreProcessor) {
|
if (!this.request.tcpPreProcessor) {
|
||||||
this.$set(this.request, 'tcpPreProcessor', new JSR223PreProcessor())
|
this.$set(this.request, 'tcpPreProcessor', new JSR223PreProcessor())
|
||||||
}
|
}
|
||||||
|
if(!this.request.connectEncoding){
|
||||||
|
this.request.connectEncoding = "UTF-8";
|
||||||
|
}
|
||||||
this.getEnvironments();
|
this.getEnvironments();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 1ac463ed7ef667d3f75c3ba64fab8331ecaa02c2
|
Subproject commit 34379f3a7e7d52b4a9c0194325b3ea02db5cc8eb
|
|
@ -682,6 +682,7 @@ export default {
|
||||||
api_name: "Api name",
|
api_name: "Api name",
|
||||||
api_status: "Api status",
|
api_status: "Api status",
|
||||||
api_type: "Api type",
|
api_type: "Api type",
|
||||||
|
api_agreement: "Method",
|
||||||
api_path: "Api path",
|
api_path: "Api path",
|
||||||
api_principal: "Api principal",
|
api_principal: "Api principal",
|
||||||
api_last_time: "Last update time",
|
api_last_time: "Last update time",
|
||||||
|
@ -1050,6 +1051,7 @@ export default {
|
||||||
variable_names: "Variable names",
|
variable_names: "Variable names",
|
||||||
},
|
},
|
||||||
tcp: {
|
tcp: {
|
||||||
|
general_format: "General",
|
||||||
server: "Server Name or IP",
|
server: "Server Name or IP",
|
||||||
port: "Port Number",
|
port: "Port Number",
|
||||||
connect: "Connect(ms)",
|
connect: "Connect(ms)",
|
||||||
|
|
|
@ -682,6 +682,7 @@ export default {
|
||||||
api_name: "接口名称",
|
api_name: "接口名称",
|
||||||
api_status: "接口状态",
|
api_status: "接口状态",
|
||||||
api_type: "请求类型",
|
api_type: "请求类型",
|
||||||
|
api_agreement: "协议/方法",
|
||||||
api_path: "路径",
|
api_path: "路径",
|
||||||
api_principal: "负责人",
|
api_principal: "负责人",
|
||||||
api_last_time: "最后更新时间",
|
api_last_time: "最后更新时间",
|
||||||
|
@ -1052,6 +1053,7 @@ export default {
|
||||||
variable_names: "按列存储",
|
variable_names: "按列存储",
|
||||||
},
|
},
|
||||||
tcp: {
|
tcp: {
|
||||||
|
general_format: "通用格式",
|
||||||
server: "服务器名或IP",
|
server: "服务器名或IP",
|
||||||
port: "端口",
|
port: "端口",
|
||||||
connect: "连接(ms)",
|
connect: "连接(ms)",
|
||||||
|
|
|
@ -682,6 +682,7 @@ export default {
|
||||||
api_name: "接口名稱",
|
api_name: "接口名稱",
|
||||||
api_status: "接口狀態",
|
api_status: "接口狀態",
|
||||||
api_type: "請求類型",
|
api_type: "請求類型",
|
||||||
|
api_agreement: "協議/方法",
|
||||||
api_path: "路徑",
|
api_path: "路徑",
|
||||||
api_principal: "負責人",
|
api_principal: "負責人",
|
||||||
api_last_time: "最後更新時間",
|
api_last_time: "最後更新時間",
|
||||||
|
@ -1052,6 +1053,7 @@ export default {
|
||||||
variable_names: "按列存儲",
|
variable_names: "按列存儲",
|
||||||
},
|
},
|
||||||
tcp: {
|
tcp: {
|
||||||
|
general_format: "通用格式",
|
||||||
server: "服務器名或IP",
|
server: "服務器名或IP",
|
||||||
port: "端口",
|
port: "端口",
|
||||||
connect: "連接(ms)",
|
connect: "連接(ms)",
|
||||||
|
|
Loading…
Reference in New Issue