mirror of
https://gitee.com/fit2cloud-feizhiyun/MeterSphere.git
synced 2024-12-05 05:29:29 +08:00
feat(接口自动化): 内置函数构造器优化,增加 mock 数据说明示例及场景变量
--story=1004200 --user=周骏弘 内置函数构造器优化 https://www.tapd.cn/55049933/s/1082243
This commit is contained in:
parent
1ae3ebdfeb
commit
406482ca41
@ -1371,6 +1371,8 @@ export default {
|
||||
this.resetResourceId(this.scenarioDefinition);
|
||||
}
|
||||
this.$store.state.scenarioMap.set(this.currentScenario.id, 0);
|
||||
// 让接口自动化参数设置的地方,可以拿到场景变量
|
||||
this.$store.state.scenarioMap.set("currentScenarioId", this.currentScenario.variables);
|
||||
})
|
||||
}
|
||||
},
|
||||
|
@ -223,7 +223,7 @@
|
||||
},
|
||||
created() {
|
||||
if (this.items.length === 0 || this.items[this.items.length - 1].name) {
|
||||
this.items.push(new KeyValue({enable: true}));
|
||||
this.items.push(new KeyValue({enable: true, name: '', value: ''}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,13 @@
|
||||
:visible.sync="itemValueVisible"
|
||||
:append-to-body="appendToBody"
|
||||
class="advanced-item-value"
|
||||
width="70%">
|
||||
width="100%"
|
||||
:fullscreen="dialogVisible">
|
||||
|
||||
<el-tabs tab-position="top" style="height: 50vh;" @tab-click="selectTab">
|
||||
<el-tab-pane :label="$t('api_test.request.parameters_advance_mock')">
|
||||
<el-row type="flex" :gutter="20">
|
||||
<el-col :span="6" class="col-height">
|
||||
<el-col :span="10" class="col-height">
|
||||
<div>
|
||||
<el-input size="small" v-model="filterText"
|
||||
:placeholder="$t('api_test.request.parameters_mock_filter_tips')"/>
|
||||
@ -34,6 +36,52 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
|
||||
<!--场景自定义变量-->
|
||||
<el-tab-pane :label="$t('api_test.automation.scenario_total')" name="variable">
|
||||
<div>
|
||||
<el-row style="margin-bottom: 10px">
|
||||
<div style="float: left">
|
||||
<el-input :placeholder="$t('commons.search_by_name')" v-model="defineVariable" size="small"
|
||||
@change="filter"
|
||||
@keyup.enter="filter">
|
||||
<el-select v-model="searchType" slot="prepend" :placeholder="$t('test_resource_pool.type')"
|
||||
style="width: 90px" @change="filter">
|
||||
<el-option value="CONSTANT" :label="$t('api_test.automation.constant')"></el-option>
|
||||
<el-option value="LIST" :label="$t('test_track.case.list')"></el-option>
|
||||
<el-option value="CSV" label="CSV"></el-option>
|
||||
<el-option value="COUNTER" :label="$t('api_test.automation.counter')"></el-option>
|
||||
<el-option value="RANDOM" :label="$t('api_test.automation.random')"></el-option>
|
||||
</el-select>
|
||||
</el-input>
|
||||
</div>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<div style="border:1px #DCDFE6 solid; min-height: 325px;border-radius: 4px ;width: 100% ;">
|
||||
<el-table ref="table" border :data="variables" class="adjust-table"
|
||||
:row-class-name="tableRowClassName"
|
||||
@select-all="select"
|
||||
@select="select"
|
||||
@row-click="edit"
|
||||
v-loading="loading" height="325px">
|
||||
<el-table-column type="selection" width="38"/>
|
||||
<el-table-column prop="num" label="ID" sortable width="60"/>
|
||||
<el-table-column prop="name" :label="$t('api_test.variable_name')" sortable
|
||||
show-overflow-tooltip/>
|
||||
<el-table-column prop="type" :label="$t('test_track.case.type')" width="70">
|
||||
<template v-slot:default="scope">
|
||||
<span>{{ types.get(scope.row.type) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="value" :label="$t('api_test.value')" show-overflow-tooltip/>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane :label="$t('api_test.variable')">
|
||||
<el-row>
|
||||
<el-col :span="6" class="col-height">
|
||||
@ -62,6 +110,12 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</el-tabs>
|
||||
<el-form>
|
||||
<el-form-item>
|
||||
@ -93,6 +147,8 @@
|
||||
<script>
|
||||
import {calculate, Scenario} from "../model/ApiTestModel";
|
||||
import {JMETER_FUNC, MOCKJS_FUNC} from "@/common/js/constants";
|
||||
import {buttons} from "../../automation/scenario/menu/Menu";
|
||||
import {ENV_TYPE} from "@/common/js/constants";
|
||||
|
||||
export default {
|
||||
name: "MsApiVariableAdvance",
|
||||
@ -144,11 +200,26 @@
|
||||
{name: "number"}
|
||||
],
|
||||
mockFuncs: MOCKJS_FUNC.map(f => {
|
||||
return {name: f.name, value: f.name}
|
||||
return {name: f.name + " " + f.des + " " + this.$t('api_test.request.parameters_filter_example') + ":" + f.ex, value: f.name}
|
||||
}),
|
||||
jmeterFuncs: JMETER_FUNC,
|
||||
mockVariableFuncs: [],
|
||||
jmeterVariableFuncs: [],
|
||||
dialogVisible: true,
|
||||
|
||||
// 自定义变量相关
|
||||
defineVariable: "",
|
||||
searchType: "",
|
||||
variables: [],
|
||||
selection: [],
|
||||
loading: false,
|
||||
types: new Map([
|
||||
['CONSTANT', this.$t('api_test.automation.constant')],
|
||||
['LIST', this.$t('test_track.case.list')],
|
||||
['CSV', 'CSV'],
|
||||
['COUNTER', this.$t('api_test.automation.counter')],
|
||||
['RANDOM', this.$t('api_test.automation.random')]
|
||||
])
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -162,11 +233,15 @@
|
||||
watch: {
|
||||
filterText(val) {
|
||||
this.$refs.tree.filter(val);
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.itemValueVisible = true;
|
||||
if(this.$store.state.scenarioMap.get != undefined
|
||||
&& this.$store.state.scenarioMap.get("currentScenarioId") != undefined){
|
||||
this.variables = this.$store.state.scenarioMap.get("currentScenarioId");
|
||||
}
|
||||
},
|
||||
prepareData() {
|
||||
if (this.scenario) {
|
||||
@ -278,7 +353,9 @@
|
||||
this.mockVariableFuncs.push({name: '', params: []});
|
||||
},
|
||||
saveAdvanced() {
|
||||
if(this.itemValue.indexOf('@') == -1){
|
||||
if(this.itemValue != null && this.itemValue != undefined
|
||||
&& this.itemValue.indexOf('@') == -1
|
||||
&& this.itemValue.indexOf('$') == -1){
|
||||
this.currentItem.value = '@' + this.itemValue;
|
||||
} else {
|
||||
this.currentItem.value = this.itemValue;
|
||||
@ -286,6 +363,49 @@
|
||||
this.itemValueVisible = false;
|
||||
this.mockVariableFuncs = [];
|
||||
this.$emit('advancedRefresh', this.itemValue);
|
||||
},
|
||||
|
||||
// 自定义变量
|
||||
filter() {
|
||||
let datas = [];
|
||||
this.variables.forEach(item => {
|
||||
if (this.searchType && this.searchType != "" && this.defineVariable && this.defineVariable != "") {
|
||||
if ((item.type && item.type.toLowerCase().indexOf(this.searchType.toLowerCase()) == -1) || (item.name && item.name.toLowerCase().indexOf(this.defineVariable.toLowerCase()) == -1)) {
|
||||
item.hidden = true;
|
||||
} else {
|
||||
item.hidden = undefined;
|
||||
}
|
||||
} else if (this.defineVariable && this.defineVariable != "") {
|
||||
if (item.name && item.name.toLowerCase().indexOf(this.defineVariable.toLowerCase()) == -1) {
|
||||
item.hidden = true;
|
||||
} else {
|
||||
item.hidden = undefined;
|
||||
}
|
||||
} else if (this.searchType && this.searchType != "") {
|
||||
if (item.type && item.type.toLowerCase().indexOf(this.searchType.toLowerCase()) == -1) {
|
||||
item.hidden = true;
|
||||
} else {
|
||||
item.hidden = undefined;
|
||||
}
|
||||
} else {
|
||||
item.hidden = undefined;
|
||||
}
|
||||
datas.push(item);
|
||||
});
|
||||
this.variables = datas;
|
||||
},
|
||||
tableRowClassName(row) {
|
||||
if (row.row.hidden) {
|
||||
return 'ms-variable-hidden-row';
|
||||
}
|
||||
return '';
|
||||
},
|
||||
select(selection) {
|
||||
this.selection = selection.map(s => s.id);
|
||||
},
|
||||
edit(row) {
|
||||
this.selection = [row.id];
|
||||
this.itemValue = '${' + row.name + '}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
import i18n from "@/i18n/i18n";
|
||||
|
||||
export const TEST_CASE_LIST = 'test_case_list'
|
||||
export const TEST_CASE_REVIEW_LIST = 'test_case_review_list'
|
||||
export const API_LIST = 'api_list'
|
||||
@ -85,57 +87,57 @@ export const REQUEST_HEADERS = [
|
||||
]
|
||||
|
||||
export const MOCKJS_FUNC = [
|
||||
{name: '@boolean'},
|
||||
{name: '@natural'},
|
||||
{name: '@integer'},
|
||||
{name: '@float'},
|
||||
{name: '@character'},
|
||||
{name: '@string'},
|
||||
{name: '@range'},
|
||||
{name: '@date'},
|
||||
{name: '@time'},
|
||||
{name: '@datetime'},
|
||||
{name: '@now'},
|
||||
{name: '@img'},
|
||||
{name: '@dataImage'},
|
||||
{name: '@color'},
|
||||
{name: '@hex'},
|
||||
{name: '@rgb'},
|
||||
{name: '@rgba'},
|
||||
{name: '@hsl'},
|
||||
{name: '@paragraph'},
|
||||
{name: '@sentence'},
|
||||
{name: '@word'},
|
||||
{name: '@title'},
|
||||
{name: '@cparagraph'},
|
||||
{name: '@csentence'},
|
||||
{name: '@cword'},
|
||||
{name: '@ctitle'},
|
||||
{name: '@first'},
|
||||
{name: '@last'},
|
||||
{name: '@name'},
|
||||
{name: '@cfirst'},
|
||||
{name: '@clast'},
|
||||
{name: '@cname'},
|
||||
{name: '@url'},
|
||||
{name: '@domain'},
|
||||
{name: '@protocol'},
|
||||
{name: '@tld'},
|
||||
{name: '@email'},
|
||||
{name: '@ip'},
|
||||
{name: '@region'},
|
||||
{name: '@province'},
|
||||
{name: '@city'},
|
||||
{name: '@county'},
|
||||
{name: '@zip'},
|
||||
{name: '@capitalize'},
|
||||
{name: '@upper'},
|
||||
{name: '@lower'},
|
||||
{name: '@pick'},
|
||||
{name: '@shuffle'},
|
||||
{name: '@guid'},
|
||||
{name: '@id'},
|
||||
{name: '@increment'}
|
||||
{name: '@boolean', des: i18n.t('api_test.request.boolean'), ex: true},
|
||||
{name: '@natural', des: i18n.t('api_test.request.natural'), ex: 72834},
|
||||
{name: '@integer', des: i18n.t('api_test.request.integer'), ex: 79750},
|
||||
{name: '@float', des: i18n.t('api_test.request.float'), ex: 24.2},
|
||||
{name: '@character', des: i18n.t('api_test.request.character'), ex: "k"},
|
||||
{name: '@string', des: i18n.t('api_test.request.string'), ex: "hello"},
|
||||
{name: '@range', des: i18n.t('api_test.request.range'), ex: "org.mozilla.javascript.NavicatArray@1739f809"},
|
||||
{name: '@date', des: i18n.t('api_test.request.date'), ex: "1973-01-08"},
|
||||
{name: '@time', des: i18n.t('api_test.request.time'), ex: "06:15:27"},
|
||||
{name: '@datetime', des: i18n.t('api_test.request.datetime'), ex: "1975-10-12 02:32:04"},
|
||||
{name: '@now', des: i18n.t('api_test.request.now'), ex: (new Date()).toLocaleTimeString().toLocaleString()},
|
||||
{name: '@img', des: i18n.t('api_test.request.img'), ex: "http://dummyimage.com/120x60"},
|
||||
{name: '@dataImage', des: i18n.t('api_test.request.dataImage'), ex: "data:image/png;base64,iVBORw0KG=="},
|
||||
{name: '@color', des: i18n.t('api_test.request.color'), ex: "#b479f2"},
|
||||
{name: '@hex', des: i18n.t('api_test.request.hex'), ex: "#f27984"},
|
||||
{name: '@rgb', des: i18n.t('api_test.request.rgb'), ex: "rgb(203, 242, 121)"},
|
||||
{name: '@rgba', des: i18n.t('api_test.request.rgba'), ex: "rgba(242, 121, 238, 0.66)"},
|
||||
{name: '@hsl', des: i18n.t('api_test.request.hsl'), ex: "hsl(164, 82, 71)"},
|
||||
{name: '@paragraph', des: i18n.t('api_test.request.paragraph'), ex: "Iwvh qxuvn uigzjw xijvntv dfidxtof"},
|
||||
{name: '@sentence', des: i18n.t('api_test.request.sentence'), ex: "Hfi fpqnqerrs sghxldx oqpghvnmy"},
|
||||
{name: '@word', des: i18n.t('api_test.request.word'), ex: "shnjlyazvi"},
|
||||
{name: '@title', des: i18n.t('api_test.request.title'), ex: "Tefsdc Vhs Ujx"},
|
||||
{name: '@cparagraph', des: i18n.t('api_test.request.cparagraph'), ex: "色青元处才不米拉律消叫别金如上。"},
|
||||
{name: '@csentence', des: i18n.t('api_test.request.csentence'), ex: "与形府部速她运改织图集料进完。"},
|
||||
{name: '@cword', des: i18n.t('api_test.request.cword'), ex: "满"},
|
||||
{name: '@ctitle', des: i18n.t('api_test.request.ctitle'), ex: "运满前省快"},
|
||||
{name: '@first', des: i18n.t('api_test.request.first'), ex: "Mary"},
|
||||
{name: '@last', des: i18n.t('api_test.request.last'), ex: "Miller"},
|
||||
{name: '@name', des: i18n.t('api_test.request.name'), ex: "Robert Lee"},
|
||||
{name: '@cfirst', des: i18n.t('api_test.request.cfirst'), ex: "龚"},
|
||||
{name: '@clast', des: i18n.t('api_test.request.clast'), ex: "刚"},
|
||||
{name: '@cname', des: i18n.t('api_test.request.cname'), ex: "江娟"},
|
||||
{name: '@url', des: i18n.t('api_test.request.url'), ex: "wais://jopnwwj.bh/lqnhn"},
|
||||
{name: '@domain', des: i18n.t('api_test.request.domain'), ex: "rsh.bt"},
|
||||
{name: '@protocol', des: i18n.t('api_test.request.protocol'), ex: "rlogin"},
|
||||
{name: '@tld', des: i18n.t('api_test.request.tld'), ex: "sa"},
|
||||
{name: '@email', des: i18n.t('api_test.request.email'), ex: "d.somdg@edntlm.cd"},
|
||||
{name: '@ip', des: i18n.t('api_test.request.ip'), ex: "22.151.93.255"},
|
||||
{name: '@region', des: i18n.t('api_test.request.region'), ex: "东北"},
|
||||
{name: '@province', des: i18n.t('api_test.request.province'), ex: "陕西省"},
|
||||
{name: '@city', des: i18n.t('api_test.request.city'), ex: "珠海市"},
|
||||
{name: '@county', des: i18n.t('api_test.request.county'), ex: "正宁县"},
|
||||
{name: '@zip', des: i18n.t('api_test.request.zip'), ex: 873247},
|
||||
{name: '@capitalize', des: i18n.t('api_test.request.capitalize'), ex: "Undefined"},
|
||||
{name: '@upper', des: i18n.t('api_test.request.upper'), ex: "UNDEFINED"},
|
||||
{name: '@lower', des: i18n.t('api_test.request.lower'), ex: "undefined"},
|
||||
{name: '@pick', des: i18n.t('api_test.request.pick'), ex: "None example"},
|
||||
{name: '@shuffle', des: i18n.t('api_test.request.shuffle'), ex: "org.mozilla.javascript.NavicatArray@2264545d"},
|
||||
{name: '@guid', des: i18n.t('api_test.request.guid'), ex: "4f9CeC2c-8d59-40f6-ec4F-2Abbc5C94Ddf"},
|
||||
{name: '@id', des: i18n.t('api_test.request.id'), ex: "450000197511051762"},
|
||||
{name: '@increment', des: i18n.t('api_test.request.increment'), ex: 1}
|
||||
]
|
||||
|
||||
export const JMETER_FUNC = [
|
||||
|
@ -1129,6 +1129,7 @@ export default {
|
||||
post_script: "Postscript",
|
||||
all_post_script: "Postscript",
|
||||
pre_sql: "JDBC Preprocessor",
|
||||
pre_return: "pre return",
|
||||
post_sql: "JDBC Postprocessor",
|
||||
extract_param: "Extract parameters",
|
||||
add_module: "Add module",
|
||||
@ -1370,6 +1371,56 @@ export default {
|
||||
condition: "condition",
|
||||
condition_variable: "Variable, e.g: ${var}",
|
||||
wait: "wait",
|
||||
|
||||
all_name:"name",
|
||||
all_url:"url",
|
||||
boolean:"Boolean value",
|
||||
capitalize:"Start with a capital letter",
|
||||
cfirst:"Last name (Chinese)",
|
||||
character:"character",
|
||||
city:"city",
|
||||
clast:"First name (Chinese)",
|
||||
cname:"Chinese name",
|
||||
color:"colour",
|
||||
county:"county",
|
||||
ctitle:"Chinese title",
|
||||
dataImage:"Data image",
|
||||
date:"date",
|
||||
datetime:"Date time",
|
||||
domain:"field",
|
||||
email:"E-mail",
|
||||
first:"surname",
|
||||
float:"Floating point number",
|
||||
guid:"guid",
|
||||
hex:"hexadecimal",
|
||||
hsl:"hsl",
|
||||
id:"id",
|
||||
img:"Picture address",
|
||||
increment:"increment",
|
||||
integer:"integer",
|
||||
ip:"intellectual property right",
|
||||
last:"name",
|
||||
lower:"Lowercase letters",
|
||||
natural:"Natural number",
|
||||
now:"current time ",
|
||||
paragraph:"paragraph",
|
||||
pick:"choice",
|
||||
protocol:"agreement",
|
||||
province:"province",
|
||||
range:"Range",
|
||||
region:"region",
|
||||
rgb:"rgb",
|
||||
rgba:"rgba",
|
||||
sentence:"sentence",
|
||||
shuffle:"shuffle the cards",
|
||||
string:"character string",
|
||||
time:"time",
|
||||
title:"title",
|
||||
tld:"tld",
|
||||
upper:"capital",
|
||||
word:"Words",
|
||||
zip:"Postal Code",
|
||||
|
||||
assertions: {
|
||||
label: "Assertion",
|
||||
text: "Text",
|
||||
|
@ -1136,6 +1136,7 @@ export default {
|
||||
post_script: "后置脚本",
|
||||
all_post_script: "全局后置脚本",
|
||||
pre_sql: "前置SQL",
|
||||
pre_return: "前置返回",
|
||||
post_sql: "后置SQL",
|
||||
extract_param: "提取参数",
|
||||
add_module: "创建模块",
|
||||
@ -1376,6 +1377,56 @@ export default {
|
||||
condition: "条件",
|
||||
condition_variable: "变量,例如: ${var}",
|
||||
wait: "等待",
|
||||
|
||||
all_name: "名字",
|
||||
all_url: "url",
|
||||
boolean: "布尔值",
|
||||
capitalize: "大写字母开头",
|
||||
cfirst: "姓(中文)",
|
||||
character: "字符",
|
||||
city: "城市",
|
||||
clast: "名(中文)",
|
||||
cname: "中文名",
|
||||
color: "颜色",
|
||||
county: "县",
|
||||
ctitle: "中文标题",
|
||||
dataImage: "数据图像",
|
||||
date: "日期",
|
||||
datetime: "日期时间",
|
||||
domain: "域",
|
||||
email: "电子邮件",
|
||||
first: "姓",
|
||||
float: "浮点数",
|
||||
guid: "guid",
|
||||
hex: "十六进制",
|
||||
hsl: "hsl",
|
||||
id: "id",
|
||||
img: "图片地址",
|
||||
increment: "增量",
|
||||
integer: "整数",
|
||||
ip: "知识产权",
|
||||
last: "名",
|
||||
lower: "小写字母",
|
||||
natural: "自然数",
|
||||
now: "当前时间",
|
||||
paragraph: "段",
|
||||
pick: "选择",
|
||||
protocol: "协议",
|
||||
province: "省",
|
||||
range: "范围",
|
||||
region: "地区",
|
||||
rgb: "rgb",
|
||||
rgba: "rgba",
|
||||
sentence: "句子",
|
||||
shuffle: "洗牌",
|
||||
string: "字符串",
|
||||
time: "时间",
|
||||
title: "标题",
|
||||
tld: "tld",
|
||||
upper: "大写字母",
|
||||
word: "词",
|
||||
zip: "邮政编码",
|
||||
|
||||
assertions: {
|
||||
label: "断言",
|
||||
text: "文本",
|
||||
|
@ -1136,6 +1136,7 @@ export default {
|
||||
post_script: "後置腳本",
|
||||
all_post_script: "全局後置腳本",
|
||||
pre_sql: "前置SQL",
|
||||
pre_return: "前置返回",
|
||||
post_sql: "後置SQL",
|
||||
extract_param: "提取參數",
|
||||
add_module: "創建模塊",
|
||||
@ -1376,6 +1377,56 @@ export default {
|
||||
condition: "條件",
|
||||
condition_variable: "變量,例如: ${var}",
|
||||
wait: "等待",
|
||||
|
||||
all_name:"名字",
|
||||
all_url:"網址",
|
||||
boolean:"布林值",
|
||||
capitalize:"大寫字母開頭",
|
||||
cfirst:"姓(中文)",
|
||||
character:"字元",
|
||||
city:"都市",
|
||||
clast:"名(中文)",
|
||||
cname:"中文名",
|
||||
color:"顏色",
|
||||
county:"縣",
|
||||
ctitle:"中文標題",
|
||||
dataImage:"數據影像",
|
||||
date:"日期",
|
||||
datetime:"日期時間",
|
||||
domain:"域",
|
||||
email:"電子郵件",
|
||||
first:"姓",
|
||||
float:"浮點數",
|
||||
guid:"指南",
|
||||
hex:"十六進位",
|
||||
hsl:"hsl",
|
||||
id:"身份證件",
|
||||
img:"圖片地址",
|
||||
increment:"增量",
|
||||
integer:"整數",
|
||||
ip:"知識產權",
|
||||
last:"名",
|
||||
lower:"小寫字母",
|
||||
natural:"自然數",
|
||||
now:"當前時間",
|
||||
paragraph:"段",
|
||||
pick:"選擇",
|
||||
protocol:"協定",
|
||||
province:"省",
|
||||
range:"範圍",
|
||||
region:"地區",
|
||||
rgb:"rgb",
|
||||
rgba:"rgba",
|
||||
sentence:"句子",
|
||||
shuffle:"洗牌",
|
||||
string:"字串",
|
||||
time:"時間",
|
||||
title:"標題",
|
||||
tld:"tld",
|
||||
upper:"大寫字母",
|
||||
word:"詞",
|
||||
zip:"郵遞區號",
|
||||
|
||||
assertions: {
|
||||
label: "斷言",
|
||||
text: "文本",
|
||||
|
Loading…
Reference in New Issue
Block a user