feat(接口自动化): 场景变量处理

This commit is contained in:
fit2-zhao 2021-01-08 13:29:00 +08:00
parent f70e241602
commit c291de3292
11 changed files with 168 additions and 52 deletions

View File

@ -5,37 +5,26 @@ import com.github.pagehelper.PageHelper;
import io.metersphere.api.dto.JmxInfoDTO; import io.metersphere.api.dto.JmxInfoDTO;
import io.metersphere.api.dto.automation.*; import io.metersphere.api.dto.automation.*;
import io.metersphere.api.dto.definition.RunDefinitionRequest; import io.metersphere.api.dto.definition.RunDefinitionRequest;
import io.metersphere.api.dto.definition.request.*;
import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.service.ApiAutomationService; import io.metersphere.api.service.ApiAutomationService;
import io.metersphere.base.domain.ApiScenario; import io.metersphere.base.domain.ApiScenario;
import io.metersphere.base.domain.ApiScenarioWithBLOBs; import io.metersphere.base.domain.ApiScenarioWithBLOBs;
import io.metersphere.base.domain.Schedule; import io.metersphere.base.domain.Schedule;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.constants.RoleConstants; import io.metersphere.commons.constants.RoleConstants;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.LogUtil;
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.i18n.Translator;
import io.metersphere.performance.service.PerformanceTestService;
import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest; import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest;
import io.metersphere.track.request.testplan.SaveTestPlanRequest; import io.metersphere.track.request.testplan.FileOperationRequest;
import org.apache.commons.lang3.StringUtils;
import org.apache.jmeter.save.SaveService;
import org.apache.jorphan.collections.HashTree;
import org.apache.jorphan.collections.ListedHashTree;
import org.apache.shiro.authz.annotation.Logical; import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles; import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.UUID;
@RestController @RestController
@RequestMapping(value = "/api/automation") @RequestMapping(value = "/api/automation")
@ -44,9 +33,6 @@ public class ApiAutomationController {
@Resource @Resource
ApiAutomationService apiAutomationService; ApiAutomationService apiAutomationService;
@Resource
PerformanceTestService performanceTestService;
@PostMapping("/list/{goPage}/{pageSize}") @PostMapping("/list/{goPage}/{pageSize}")
@RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR) @RequiresRoles(value = {RoleConstants.TEST_MANAGER, RoleConstants.TEST_USER, RoleConstants.TEST_VIEWER}, logical = Logical.OR)
@ -145,5 +131,14 @@ public class ApiAutomationController {
runRequest.setExecuteType(ExecuteType.Completed.name()); runRequest.setExecuteType(ExecuteType.Completed.name());
return apiAutomationService.genPerformanceTestJmx(runRequest); return apiAutomationService.genPerformanceTestJmx(runRequest);
} }
@PostMapping("/file/download")
public ResponseEntity<byte[]> downloadJmx(@RequestBody FileOperationRequest fileOperationRequest) {
byte[] bytes = apiAutomationService.loadFileAsBytes(fileOperationRequest);
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType("application/octet-stream"))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileOperationRequest.getName() + "\"")
.body(bytes);
}
} }

View File

@ -7,6 +7,7 @@ import com.alibaba.fastjson.annotation.JSONType;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.scenario.KeyValue;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.service.ApiAutomationService; import io.metersphere.api.service.ApiAutomationService;
@ -42,7 +43,7 @@ public class MsScenario extends MsTestElement {
private String environmentId; private String environmentId;
@JSONField(ordinal = 23) @JSONField(ordinal = 23)
private List<KeyValue> variables; private List<ScenarioVariable> variables;
@JSONField(ordinal = 24) @JSONField(ordinal = 24)
private boolean enableCookieShare; private boolean enableCookieShare;
@ -60,7 +61,7 @@ public class MsScenario extends MsTestElement {
} }
} }
if (CollectionUtils.isNotEmpty(this.getVariables())) { if (CollectionUtils.isNotEmpty(this.getVariables())) {
config.setVariables(this.variables); //config.setVariables(this.variables);
} }
if (this.getReferenced() != null && this.getReferenced().equals("Deleted")) { if (this.getReferenced() != null && this.getReferenced().equals("Deleted")) {
return; return;
@ -92,17 +93,24 @@ public class MsScenario extends MsTestElement {
} }
} }
public void setOldVariables(List<KeyValue> oldVariables) {
if (CollectionUtils.isNotEmpty(oldVariables)) {
String json = JSON.toJSONString(oldVariables);
this.variables = JSON.parseArray(json, ScenarioVariable.class);
}
}
private Arguments arguments(ParameterConfig config) { private Arguments arguments(ParameterConfig config) {
Arguments arguments = new Arguments(); Arguments arguments = new Arguments();
arguments.setEnabled(true); arguments.setEnabled(true);
arguments.setName(name + "Variables"); arguments.setName(name + "Variables");
arguments.setProperty(TestElement.TEST_CLASS, Arguments.class.getName()); arguments.setProperty(TestElement.TEST_CLASS, Arguments.class.getName());
arguments.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ArgumentsPanel")); arguments.setProperty(TestElement.GUI_CLASS, SaveService.aliasToClass("ArgumentsPanel"));
if (CollectionUtils.isNotEmpty(this.getVariables())) { // if (CollectionUtils.isNotEmpty(this.getVariables())) {
variables.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> // variables.stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue ->
arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=") // arguments.addArgument(keyValue.getName(), keyValue.getValue(), "=")
); // );
} // }
if (config != null && config.getConfig() != null && config.getConfig().getCommonConfig() != null if (config != null && config.getConfig() != null && config.getConfig().getCommonConfig() != null
&& CollectionUtils.isNotEmpty(config.getConfig().getCommonConfig().getVariables())) { && CollectionUtils.isNotEmpty(config.getConfig().getCommonConfig().getVariables())) {
config.getConfig().getCommonConfig().getVariables().stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue -> config.getConfig().getCommonConfig().getVariables().stream().filter(KeyValue::isValid).filter(KeyValue::isEnable).forEach(keyValue ->

View File

@ -0,0 +1,29 @@
package io.metersphere.api.dto.definition.request.variable;
import io.metersphere.api.dto.scenario.request.BodyFile;
import lombok.Data;
import java.util.List;
@Data
public class ScenarioVariable {
// CONSTANT LIST CSV COUNTER RANDOM
private String type;
private String name;
// 常量值列表值[] ,计数器输出格式随机数输出格式
private String value;
private String description;
// csv
private List<BodyFile> files;
private String splits;
private String encoding;
// counter
private int startNumber;
private int endNumber;
private int increment;
// random
private int minNumber;
private int maxNumber;
}

View File

@ -11,7 +11,7 @@ import io.metersphere.api.dto.automation.*;
import io.metersphere.api.dto.datacount.ApiDataCountResult; import io.metersphere.api.dto.datacount.ApiDataCountResult;
import io.metersphere.api.dto.definition.RunDefinitionRequest; import io.metersphere.api.dto.definition.RunDefinitionRequest;
import io.metersphere.api.dto.definition.request.*; import io.metersphere.api.dto.definition.request.*;
import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
import io.metersphere.api.dto.scenario.environment.EnvironmentConfig; import io.metersphere.api.dto.scenario.environment.EnvironmentConfig;
import io.metersphere.api.jmeter.JMeterService; import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.base.domain.*; import io.metersphere.base.domain.*;
@ -30,18 +30,16 @@ import io.metersphere.commons.utils.ServiceUtils;
import io.metersphere.commons.utils.SessionUtils; import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.i18n.Translator; import io.metersphere.i18n.Translator;
import io.metersphere.job.sechedule.ApiScenarioTestJob; import io.metersphere.job.sechedule.ApiScenarioTestJob;
import io.metersphere.performance.service.PerformanceTestService;
import io.metersphere.service.ScheduleService; import io.metersphere.service.ScheduleService;
import io.metersphere.track.dto.TestPlanDTO; import io.metersphere.track.dto.TestPlanDTO;
import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest; import io.metersphere.track.request.testcase.ApiCaseRelevanceRequest;
import io.metersphere.track.request.testcase.QueryTestPlanRequest; import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import io.metersphere.track.request.testplan.SaveTestPlanRequest; import io.metersphere.track.request.testplan.FileOperationRequest;
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;
import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.jmeter.save.SaveService;
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 org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -50,6 +48,8 @@ import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -78,8 +78,6 @@ public class ApiAutomationService {
SqlSessionFactory sqlSessionFactory; SqlSessionFactory sqlSessionFactory;
@Resource @Resource
private ApiScenarioReportMapper apiScenarioReportMapper; private ApiScenarioReportMapper apiScenarioReportMapper;
@Resource
private PerformanceTestService performanceTestService;
public List<ApiScenarioDTO> list(ApiScenarioRequest request) { public List<ApiScenarioDTO> list(ApiScenarioRequest request) {
request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders())); request.setOrders(ServiceUtils.getDefaultOrder(request.getOrders()));
@ -285,6 +283,22 @@ public class ApiAutomationService {
return new ArrayList<>(); return new ArrayList<>();
} }
public byte[] loadFileAsBytes(FileOperationRequest fileOperationRequest) {
File file = new File("/opt/metersphere/data/body/" + fileOperationRequest.getId() + "_" + fileOperationRequest.getName());
try (FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);) {
byte[] b = new byte[1000];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
return bos.toByteArray();
} catch (Exception ex) {
LogUtil.error(ex.getMessage());
}
return null;
}
private void createScenarioReport(String id, String scenarioId, String scenarioName, String triggerMode, String execType, String projectId, String userID) { private void createScenarioReport(String id, String scenarioId, String scenarioName, String triggerMode, String execType, String projectId, String userID) {
APIScenarioReportResult report = new APIScenarioReportResult(); APIScenarioReportResult report = new APIScenarioReportResult();
report.setId(id); report.setId(id);
@ -354,12 +368,14 @@ public class ApiAutomationService {
// 多态JSON普通转换会丢失内容需要通过 ObjectMapper 获取 // 多态JSON普通转换会丢失内容需要通过 ObjectMapper 获取
if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) { if (element != null && StringUtils.isNotEmpty(element.getString("hashTree"))) {
LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"), LinkedList<MsTestElement> elements = mapper.readValue(element.getString("hashTree"),
new TypeReference<LinkedList<MsTestElement>>() {}); new TypeReference<LinkedList<MsTestElement>>() {
});
scenario.setHashTree(elements); scenario.setHashTree(elements);
} }
if (StringUtils.isNotEmpty(element.getString("variables"))) { if (StringUtils.isNotEmpty(element.getString("variables"))) {
LinkedList<KeyValue> variables = mapper.readValue(element.getString("variables"), LinkedList<ScenarioVariable> variables = mapper.readValue(element.getString("variables"),
new TypeReference<LinkedList<KeyValue>>() {}); new TypeReference<LinkedList<ScenarioVariable>>() {
});
scenario.setVariables(variables); scenario.setVariables(variables);
} }
group.setEnableCookieShare(scenario.isEnableCookieShare()); group.setEnableCookieShare(scenario.isEnableCookieShare());
@ -592,8 +608,8 @@ public class ApiAutomationService {
scenario.setHashTree(elements); scenario.setHashTree(elements);
} }
if (StringUtils.isNotEmpty(element.getString("variables"))) { if (StringUtils.isNotEmpty(element.getString("variables"))) {
LinkedList<KeyValue> variables = mapper.readValue(element.getString("variables"), LinkedList<ScenarioVariable> variables = mapper.readValue(element.getString("variables"),
new TypeReference<LinkedList<KeyValue>>() { new TypeReference<LinkedList<ScenarioVariable>>() {
}); });
scenario.setVariables(variables); scenario.setVariables(variables);
} }
@ -602,7 +618,6 @@ public class ApiAutomationService {
scenarios.add(scenario); scenarios.add(scenario);
group.setHashTree(scenarios); group.setHashTree(scenarios);
testPlan.getHashTree().add(group); testPlan.getHashTree().add(group);
} }
} catch (Exception ex) { } catch (Exception ex) {
MSException.throwException(ex.getMessage()); MSException.throwException(ex.getMessage());

View File

@ -13,7 +13,7 @@ import io.metersphere.api.dto.datacount.ApiDataCountResult;
import io.metersphere.api.dto.definition.*; import io.metersphere.api.dto.definition.*;
import io.metersphere.api.dto.definition.parse.ApiDefinitionImport; import io.metersphere.api.dto.definition.parse.ApiDefinitionImport;
import io.metersphere.api.dto.definition.request.*; import io.metersphere.api.dto.definition.request.*;
import io.metersphere.api.dto.scenario.KeyValue; import io.metersphere.api.dto.definition.request.variable.ScenarioVariable;
import io.metersphere.api.dto.scenario.request.RequestType; import io.metersphere.api.dto.scenario.request.RequestType;
import io.metersphere.api.jmeter.JMeterService; import io.metersphere.api.jmeter.JMeterService;
import io.metersphere.api.jmeter.TestResult; import io.metersphere.api.jmeter.TestResult;
@ -29,7 +29,6 @@ import io.metersphere.base.mapper.ext.ExtApiScenarioMapper;
import io.metersphere.base.mapper.ext.ExtTestPlanMapper; import io.metersphere.base.mapper.ext.ExtTestPlanMapper;
import io.metersphere.commons.constants.APITestStatus; import io.metersphere.commons.constants.APITestStatus;
import io.metersphere.commons.constants.ApiRunMode; import io.metersphere.commons.constants.ApiRunMode;
import io.metersphere.commons.constants.ReportTriggerMode;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.*; import io.metersphere.commons.utils.*;
import io.metersphere.i18n.Translator; import io.metersphere.i18n.Translator;
@ -366,8 +365,8 @@ public class ApiDefinitionService {
scenario.setHashTree(elements); scenario.setHashTree(elements);
} }
if (StringUtils.isNotEmpty(element.getString("variables"))) { if (StringUtils.isNotEmpty(element.getString("variables"))) {
LinkedList<KeyValue> variables = mapper.readValue(element.getString("variables"), LinkedList<ScenarioVariable> variables = mapper.readValue(element.getString("variables"),
new TypeReference<LinkedList<KeyValue>>() {}); new TypeReference<LinkedList<ScenarioVariable>>() {});
scenario.setVariables(variables); scenario.setVariables(variables);
} }
group.setEnableCookieShare(scenario.isEnableCookieShare()); group.setEnableCookieShare(scenario.isEnableCookieShare());

View File

@ -66,7 +66,7 @@ public class HistoricalDataUpgradeService {
private MsScenario createScenario(Scenario oldScenario) { private MsScenario createScenario(Scenario oldScenario) {
MsScenario scenario = new MsScenario(); MsScenario scenario = new MsScenario();
scenario.setVariables(oldScenario.getVariables()); scenario.setOldVariables(oldScenario.getVariables());
scenario.setName(oldScenario.getName()); scenario.setName(oldScenario.getName());
scenario.setEnableCookieShare(oldScenario.isEnableCookieShare()); scenario.setEnableCookieShare(oldScenario.isEnableCookieShare());
scenario.setEnvironmentId(oldScenario.getEnvironmentId()); scenario.setEnvironmentId(oldScenario.getEnvironmentId());

View File

@ -39,6 +39,7 @@
"vue-float-action-button": "^0.6.6", "vue-float-action-button": "^0.6.6",
"vue-i18n": "^8.15.3", "vue-i18n": "^8.15.3",
"vue-input-tag": "^2.0.7", "vue-input-tag": "^2.0.7",
"vue-papa-parse": "^2.0.0",
"vue-pdf": "^4.2.0", "vue-pdf": "^4.2.0",
"vue-router": "^3.1.3", "vue-router": "^3.1.3",
"vuedraggable": "^2.23.2", "vuedraggable": "^2.23.2",

View File

@ -803,6 +803,22 @@
this.recursiveFile(item.hashTree, bodyUploadFiles, obj); this.recursiveFile(item.hashTree, bodyUploadFiles, obj);
} }
}) })
// csv
this.currentScenario.variables.forEach(param => {
if (param.type === 'CSV' && param.files) {
param.files.forEach(item => {
if (item.file) {
if (!item.id) {
let fileId = getUUID().substring(0, 12);
item.name = item.file.name;
item.id = fileId;
}
obj.bodyUploadIds.push(item.id);
bodyUploadFiles.push(item.file);
}
})
}
})
return bodyUploadFiles; return bodyUploadFiles;
}, },
editScenario() { editScenario() {
@ -842,7 +858,7 @@
// //
if (item.name) { if (item.name) {
if (!item.type) { if (!item.type) {
item.type = "VARIABLE"; item.type = "CONSTANT";
item.id = getUUID(); item.id = getUUID();
} }
item.num = index; item.num = index;

View File

@ -21,7 +21,7 @@
<span>添加文件</span> <span>添加文件</span>
</el-col> </el-col>
<el-col :span="20"> <el-col :span="20">
<ms-csv-file-upload :parameter="form.files"/> <ms-csv-file-upload :parameter="form"/>
</el-col> </el-col>
</el-row> </el-row>
<el-row style="margin-top: 10px"> <el-row style="margin-top: 10px">
@ -42,7 +42,21 @@
</el-row> </el-row>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="$t('schema.preview')" name="preview">配置管理</el-tab-pane> <el-tab-pane :label="$t('schema.preview')" name="preview">
<el-table
:data="previewData"
style="width: 100%"
height="400px"
v-loading="loading">
<!-- 自定义列的遍历-->
<el-table-column v-for="(item, index) in columns" :key="index" :label="columns[index]" align="left" width="180">
<!-- 数据的遍历 scope.row就代表数据的每一个对象-->
<template slot-scope="scope">
<span>{{scope.row[index]}}</span>
</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs> </el-tabs>
</el-form> </el-form>
<template v-slot:footer> <template v-slot:footer>
@ -68,8 +82,11 @@
return { return {
activeName: "config", activeName: "config",
visible: false, visible: false,
form: {type: "CSV", files: {}}, loading: false,
form: {type: "CSV"},
editFlag: false, editFlag: false,
previewData: [],
columns: [],
rule: { rule: {
name: [ name: [
{required: true, message: this.$t('api_test.variable_name'), trigger: 'blur'}, {required: true, message: this.$t('api_test.variable_name'), trigger: 'blur'},
@ -84,17 +101,51 @@
this.form = v; this.form = v;
this.editFlag = true; this.editFlag = true;
} else { } else {
this.form = {files: {}}; this.form = {};
this.editFlag = false; this.editFlag = false;
} }
this.form.type = "CSV"; this.form.type = "CSV";
}, },
close() { close() {
this.visible = false; this.visible = false;
this.form = {files: {}}; this.form = {};
},
complete(results) {
if (results.errors && results.errors.length > 0) {
this.$error(results.errors);
return;
}
if (results.data) {
this.columns = results.data[0];
this.previewData = results.data;
}
}, },
handleClick() { handleClick() {
let config = {complete: this.complete};
//
if (this.form.files.length > 0 && this.form.files[0].file) {
this.$papa.parse(this.form.files[0].file, config);
}
//
if (this.form.files.length > 0 && !this.form.files[0].file) {
let file = this.form.files[0];
let config = {
url: "/api/automation/file/download",
method: 'post',
data: file,
responseType: 'blob'
};
this.result = this.$request(config).then(response => {
const content = response.data;
const blob = new Blob([content]);
console.log(blob)
console.log(content)
let data = new FormData();
data.append("file", blob, blob.name);
this.$papa.parse(data, config);
});
}
}, },
saveParameters() { saveParameters() {
this.$refs['form'].validate((valid) => { this.$refs['form'].validate((valid) => {

View File

@ -3,7 +3,7 @@
:visible.sync="visible" class="environment-dialog" width="60%" :visible.sync="visible" class="environment-dialog" width="60%"
@close="close"> @close="close">
<div> <div>
<el-table ref="scenarioTable" border :data="variables" class="adjust-table" @select-all="select" @select="select" <el-table ref="table" border :data="variables" class="adjust-table" @select-all="select" @select="select"
v-loading="loading"> v-loading="loading">
<el-table-column type="selection" width="38"/> <el-table-column type="selection" width="38"/>
<el-table-column prop="num" label="ID" sortable/> <el-table-column prop="num" label="ID" sortable/>

View File

@ -21,6 +21,8 @@ import VueFab from 'vue-float-action-button'
import {horizontalDrag} from "../common/js/directive"; import {horizontalDrag} from "../common/js/directive";
import JsonSchemaEditor from './components/common/json-schema/schema/index'; import JsonSchemaEditor from './components/common/json-schema/schema/index';
Vue.use(JsonSchemaEditor); Vue.use(JsonSchemaEditor);
import VuePapaParse from 'vue-papa-parse'
Vue.use(VuePapaParse)
Vue.config.productionTip = false; Vue.config.productionTip = false;
Vue.use(icon); Vue.use(icon);