excel导入导出国际化

This commit is contained in:
chenjianxing 2020-05-22 16:08:22 +08:00
parent f415a121a5
commit 6977ee496b
11 changed files with 121 additions and 42 deletions

View File

@ -2,14 +2,18 @@ package io.metersphere.config;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.i18n.Translator;
import org.hibernate.validator.HibernateValidator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import javax.validation.Validator;
@Configuration
public class I18nConfig {
@ -33,7 +37,14 @@ public class I18nConfig {
@Bean
public LocalValidatorFactoryBean localValidatorFactoryBean(MessageSource messageSource) {
LocalValidatorFactoryBean localValidatorFactoryBean = new LocalValidatorFactoryBean();
localValidatorFactoryBean.setProviderClass(HibernateValidator.class);
localValidatorFactoryBean.setValidationMessageSource(messageSource);
return localValidatorFactoryBean;
}
@Bean
public Validator validator(LocalValidatorFactoryBean localValidatorFactoryBean){
return localValidatorFactoryBean.getValidator();
}
}

View File

@ -12,33 +12,33 @@ import javax.validation.constraints.Pattern;
@ColumnWidth(15)
public class TestCaseExcelData {
@NotBlank
@NotBlank(message = "{cannot_be_null}")
@Length(max=50)
@ExcelProperty("{test_case_name}")
private String name;
@NotBlank
@NotBlank(message = "{cannot_be_null}")
@Length(max=1000)
@ExcelProperty("{test_case_module}")
@ColumnWidth(30)
@Pattern(regexp = "^(?!.*//).*$", message = "{incorrect_format}")
private String nodePath;
@NotBlank
@NotBlank(message = "{cannot_be_null}")
@ExcelProperty("{test_case_type}")
@Pattern(regexp = "(^functional$)|(^performance$)|(^api$)", message = "{test_case_type_validate}")
private String type;
@NotBlank
@NotBlank(message = "{cannot_be_null}")
@ExcelProperty("{test_case_maintainer}")
private String maintainer;
@NotBlank
@NotBlank(message = "{cannot_be_null}")
@ExcelProperty("{test_case_priority}")
@Pattern(regexp = "(^P0$)|(^P1$)|(^P2$)|(^P3$)", message = "{test_case_priority_validate}")
private String priority;
@NotBlank
@NotBlank(message = "{cannot_be_null}")
@ExcelProperty("{test_case_method}")
@Pattern(regexp = "(^manual$)|(^auto$)", message = "{test_case_method_validate}")
private String method;

View File

@ -61,7 +61,7 @@ public abstract class EasyExcelListener <T> extends AnalysisEventListener<T> {
if (!StringUtils.isEmpty(errMsg)) {
ExcelErrData excelErrData = new ExcelErrData(t, rowIndex,
Translator.get("number") + rowIndex + Translator.get("row") + Translator.get("error")
Translator.get("number")+ " " + rowIndex + " " + Translator.get("row") + Translator.get("error")
+ "" + errMsg);
errList.add(excelErrData);
} else {

View File

@ -7,6 +7,7 @@ import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.groups.Default;
import java.lang.reflect.Field;
import java.util.Set;
@ -17,11 +18,11 @@ public class ExcelValidateHelper {
private static ExcelValidateHelper excelValidateHelper;
@Resource
LocalValidatorFactoryBean localValidatorFactoryBean;
Validator validator;
public static <T> String validateEntity(T obj) throws NoSuchFieldException {
StringBuilder result = new StringBuilder();
Set<ConstraintViolation<T>> set = excelValidateHelper.localValidatorFactoryBean.getValidator().validate(obj, Default.class);
Set<ConstraintViolation<T>> set = excelValidateHelper.validator.validate(obj, Default.class);
if (set != null && !set.isEmpty()) {
for (ConstraintViolation<T> cv : set) {
Field declaredField = obj.getClass().getDeclaredField(cv.getPropertyPath().toString());
@ -33,9 +34,12 @@ public class ExcelValidateHelper {
return result.toString();
}
/**
* 在静态方法中调用
*/
@PostConstruct
public void initialize() {
excelValidateHelper = this;
excelValidateHelper.localValidatorFactoryBean = this.localValidatorFactoryBean;
excelValidateHelper.validator = this.validator;
}
}

View File

@ -9,6 +9,7 @@ import io.metersphere.base.mapper.ext.ExtTestCaseMapper;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.user.SessionUser;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.excel.domain.ExcelErrData;
import io.metersphere.excel.domain.ExcelResponse;
@ -190,6 +191,7 @@ public class TestCaseService {
EasyExcelFactory.read(file.getInputStream(), TestCaseExcelData.class, easyExcelListener).sheet().doRead();
errList = easyExcelListener.getErrList();
} catch (Exception e) {
LogUtil.error(e.getMessage(), e);
MSException.throwException(e.getMessage());
} finally {
easyExcelListener.close();

View File

@ -1,6 +1,10 @@
#commons
error_lang_invalid=Invalid language parameter
file_cannot_be_null=File cannot be empty!
cannot_be_null=\tCannot be empty
number=Number
row=row
error=error
#user related
user_email_already_exists=User email already exists
user_name_is_null=User name cannot be null
@ -43,23 +47,20 @@ test_case_node_level=level
test_case_node_level_tip=The node tree maximum depth is
test_case_module_not_null=The owned module cannot be empty
test_case_create_module_fail=Failed to create module
test_case_import_template_name=Test case templates
test_case_import_template_name=Test_case_templates
test_case_import_template_sheet=Template
module_not_null=The module must not be blank
user_not_exists=The user in this workspace is not exists
test_case_already_exists=The test case in this project is exists
parse_data_error=Parse data error
missing_header_information=Missing header information
number=Number
row=row
error=error
test_case_exist=A test case already exists under this project:
node_deep_limit=The node depth does not exceed 5 layers!
before_delete_plan=There is an associated test case under this plan, please unlink it first!
incorrect_format=Incorrect format
test_case_type_validate=must be functional, performance, api
test_case_priority_validate=must be P0, P1, P2, P3
test_case_method_validate=must be manual, auto
incorrect_format=\tincorrect format
test_case_type_validate=\tmust be functional, performance, api
test_case_priority_validate=\tmust be P0, P1, P2, P3
test_case_method_validate=\tmust be manual, auto
test_case_name=Name
test_case_type=Type
test_case_maintainer=Maintainer

View File

@ -1,6 +1,10 @@
#commons
error_lang_invalid=语言参数错误
file_cannot_be_null=文件不能为空!
cannot_be_null=不能为空
number=
row=
error=出错
#user related
user_email_already_exists=用户邮箱已存在
user_name_is_null=用户名不能为空
@ -50,9 +54,6 @@ user_not_exists=该工作空间下无该用户
test_case_already_exists=该项目下已存在该测试用例
parse_data_error=解析数据出错
missing_header_information=缺少头部信息
number=
row=
error=出错
test_case_exist=该项目下已存在用例:
node_deep_limit=节点深度不超过5层
before_delete_plan=该计划下存在关联测试用例,请先取消关联!

View File

@ -1,6 +1,10 @@
#commons
error_lang_invalid=語言參數錯誤
file_cannot_be_null=文件不能為空!
cannot_be_null=不能為空
number=
row=
error=出錯
#user related
user_email_already_exists=用戶郵箱已存在
user_name_is_null=用戶名不能為空
@ -50,9 +54,6 @@ user_not_exists=該工作空間下無該用戶
test_case_already_exists=該項目下已存在該測試用例
parse_data_error=解析數據出錯
missing_header_information=缺少頭部信息
number=
row=
error=出錯
test_case_exist=該項目下已存在用例:
node_deep_limit=節點深度不超過5層
before_delete_plan=該計劃下存在關聯測試用例,請先取消關聯!

View File

@ -135,9 +135,9 @@
});
},
saveAndRun() {
if (!this.validTestPlan()) {
return;
}
// if (!this.validTestPlan()) {
// return;
// }
let options = this.getSaveOption();

View File

@ -4,21 +4,23 @@
<el-row>
<el-link type="primary" class="download-template"
href="/test/case/export/template">{{$t('test_track.case.import.download_template')}}</el-link></el-row>
@click="downloadTemplate"
>{{$t('test_track.case.import.download_template')}}</el-link></el-row>
<el-row>
<el-upload
v-loading="isLoading"
v-loading="result.loading"
:element-loading-text="$t('test_track.case.import.importing')"
element-loading-spinner="el-icon-loading"
class="upload-demo"
:action="'/test/case/import/' + projectId"
multiple
:limit="1"
action=""
:on-exceed="handleExceed"
:beforeUpload="UploadValidate"
:on-success="handleSuccess"
:on-error="handleError"
:show-file-list="false"
:http-request="upload"
:file-list="fileList">
<template v-slot:trigger>
<el-button size="mini" type="success" plain>{{$t('test_track.case.import.click_upload')}}</el-button>
@ -49,6 +51,7 @@
components: {ElUploadList, MsTableButton},
data() {
return {
result: {},
dialogVisible: false,
fileList: [],
errList: [],
@ -80,16 +83,16 @@
return true;
},
handleSuccess(response) {
this.isLoading = false;
let res = response.data;
if (res.success) {
this.$success(this.$t('test_track.case.import.success'));
this.dialogVisible = false;
this.$emit("refresh");
} else {
this.errList = res.errList;
}
this.fileList = [];
// let res = response.data;
// if (res.success) {
// this.$success(this.$t('test_track.case.import.success'));
// this.dialogVisible = false;
// this.$emit("refresh");
// } else {
// this.errList = res.errList;
// }
// this.fileList = [];
},
handleError(err, file, fileList) {
this.isLoading = false;
@ -102,6 +105,28 @@
open() {
this.dialogVisible = true;
},
downloadTemplate() {
// this.$get('/test/case/export/template');
// fileDownload('/test/case/export/template', {});
this.$fileDownload('/test/case/export/template');
},
upload(file) {
this.isLoading = false;
this.fileList.push(file.file);
this.result = this.$fileUpload('/test/case/import/' + this.projectId, this.fileList,response => {
let res = response.data;
if (res.success) {
this.$success(this.$t('test_track.case.import.success'));
this.dialogVisible = false;
this.$emit("refresh");
} else {
this.errList = res.errList;
}
this.fileList = [];
}, erro => {
this.fileList = [];
});
}
}
}
</script>

View File

@ -35,8 +35,7 @@ export default {
function then(success, response, result) {
if (!response.data) {
success(response);
}
if (response.data.success) {
} else if (response.data.success) {
success(response.data);
} else {
window.console.warn(response.data);
@ -108,5 +107,40 @@ export default {
if (array.length < 1) return;
axios.all(array).then(axios.spread(callback));
};
Vue.prototype.$fileDownload = function(url) {
axios({
method: 'get',
url: url,
responseType: 'blob',
}).then(response => {
let fileName = window.decodeURI(response.headers['content-disposition'].split('=')[1]);
let link = document.createElement("a");
link.href = window.URL.createObjectURL(new Blob([response.data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"}));
link.download = fileName;
link.click();
})
};
Vue.prototype.$fileUpload = function(url, fileList, success, failure) {
let result = {loading: true};
let formData = new FormData();
if (fileList.length > 0) {
fileList.forEach(f => {
formData.append("file", f);
});
}
axios.post(url, formData, { headers: { "Content-Type": "multipart/form-data" }})
.then(response => {
then(success, response, result);
}).catch(error => {
exception(error, result);
if (failure) {
then(failure, error, result);
}
});
return result;
}
}
}