Merge branch 'master' of https://github.com/metersphere/metersphere
This commit is contained in:
commit
ce9d9c8c43
|
@ -256,7 +256,7 @@ public abstract class MsTestElement {
|
||||||
randomVariableConfig.setProperty("outputFormat", item.getValue());
|
randomVariableConfig.setProperty("outputFormat", item.getValue());
|
||||||
randomVariableConfig.setProperty("minimumValue", item.getMinNumber());
|
randomVariableConfig.setProperty("minimumValue", item.getMinNumber());
|
||||||
randomVariableConfig.setProperty("maximumValue", item.getMaxNumber());
|
randomVariableConfig.setProperty("maximumValue", item.getMaxNumber());
|
||||||
randomVariableConfig.setComment(item.getDescription());
|
randomVariableConfig.setComment(StringUtils.isEmpty(item.getDescription()) ? "" : item.getDescription());
|
||||||
tree.add(randomVariableConfig);
|
tree.add(randomVariableConfig);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -486,6 +486,7 @@ public class ApiTestCaseService {
|
||||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
MsTestElement element = mapper.readValue(testCaseWithBLOBs.getRequest(), new TypeReference<MsTestElement>() {
|
MsTestElement element = mapper.readValue(testCaseWithBLOBs.getRequest(), new TypeReference<MsTestElement>() {
|
||||||
});
|
});
|
||||||
|
element.setProjectId(testCaseWithBLOBs.getProjectId());
|
||||||
if (StringUtils.isBlank(request.getEnvironmentId())) {
|
if (StringUtils.isBlank(request.getEnvironmentId())) {
|
||||||
TestPlanApiCaseExample example = new TestPlanApiCaseExample();
|
TestPlanApiCaseExample example = new TestPlanApiCaseExample();
|
||||||
example.createCriteria().andTestPlanIdEqualTo(request.getTestPlanId()).andApiCaseIdEqualTo(request.getCaseId());
|
example.createCriteria().andTestPlanIdEqualTo(request.getTestPlanId()).andApiCaseIdEqualTo(request.getCaseId());
|
||||||
|
@ -513,9 +514,14 @@ public class ApiTestCaseService {
|
||||||
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
|
ApiTestEnvironmentService environmentService = CommonBeanFactory.getBean(ApiTestEnvironmentService.class);
|
||||||
ApiTestEnvironmentWithBLOBs environment = environmentService.get(request.getEnvironmentId());
|
ApiTestEnvironmentWithBLOBs environment = environmentService.get(request.getEnvironmentId());
|
||||||
ParameterConfig parameterConfig = new ParameterConfig();
|
ParameterConfig parameterConfig = new ParameterConfig();
|
||||||
// if (environment != null && environment.getConfig() != null) {
|
|
||||||
// parameterConfig.setConfig(JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class));
|
Map<String, EnvironmentConfig> envConfig = new HashMap<>(16);
|
||||||
// }
|
if (environment != null && environment.getConfig() != null) {
|
||||||
|
EnvironmentConfig environmentConfig = JSONObject.parseObject(environment.getConfig(), EnvironmentConfig.class);
|
||||||
|
envConfig.put(testCaseWithBLOBs.getProjectId(), environmentConfig);
|
||||||
|
parameterConfig.setConfig(envConfig);
|
||||||
|
}
|
||||||
|
|
||||||
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), parameterConfig);
|
testPlan.toHashTree(jmeterHashTree, testPlan.getHashTree(), parameterConfig);
|
||||||
return jmeterHashTree;
|
return jmeterHashTree;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
package io.metersphere.base.mapper.ext;
|
package io.metersphere.base.mapper.ext;
|
||||||
|
|
||||||
|
import io.metersphere.base.domain.Organization;
|
||||||
|
import io.metersphere.dto.OrganizationMemberDTO;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface ExtOrganizationMapper {
|
public interface ExtOrganizationMapper {
|
||||||
|
|
||||||
int checkSourceRole(@Param("sourceId") String sourceId,@Param("userId") String userId,@Param("roleId") String roleId);
|
int checkSourceRole(@Param("sourceId") String sourceId,@Param("userId") String userId,@Param("roleId") String roleId);
|
||||||
|
|
||||||
|
List<OrganizationMemberDTO> findAllIdAndName();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,4 +10,8 @@
|
||||||
and ur.role_id = #{roleId}
|
and ur.role_id = #{roleId}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
|
||||||
|
<select id="findAllIdAndName" resultType="io.metersphere.dto.OrganizationMemberDTO">
|
||||||
|
select id,name from Organization
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
|
@ -23,4 +23,6 @@ public interface ExtUserMapper {
|
||||||
|
|
||||||
@MapKey("id")
|
@MapKey("id")
|
||||||
Map<String, User> queryNameByIds(List<String> userIds);
|
Map<String, User> queryNameByIds(List<String> userIds);
|
||||||
|
|
||||||
|
List<String> selectAllId();
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,4 +72,8 @@
|
||||||
</foreach>
|
</foreach>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectAllId" resultType="java.lang.String">
|
||||||
|
select id from `user`
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
|
@ -10,4 +10,6 @@ public interface ExtWorkspaceMapper {
|
||||||
|
|
||||||
List<WorkspaceDTO> getWorkspaceWithOrg(@Param("request") WorkspaceRequest request);
|
List<WorkspaceDTO> getWorkspaceWithOrg(@Param("request") WorkspaceRequest request);
|
||||||
List<String> getWorkspaceIdsByOrgId(@Param("orgId") String orgId);
|
List<String> getWorkspaceIdsByOrgId(@Param("orgId") String orgId);
|
||||||
|
|
||||||
|
List<WorkspaceDTO> findAllIdAndName();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,4 +18,8 @@
|
||||||
where organization_id = #{orgId}
|
where organization_id = #{orgId}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="findAllIdAndName" resultType="io.metersphere.dto.WorkspaceDTO">
|
||||||
|
select id,name from workspace
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
|
@ -17,7 +17,9 @@ import io.metersphere.controller.request.organization.AddOrgMemberRequest;
|
||||||
import io.metersphere.controller.request.organization.QueryOrgMemberRequest;
|
import io.metersphere.controller.request.organization.QueryOrgMemberRequest;
|
||||||
import io.metersphere.dto.UserDTO;
|
import io.metersphere.dto.UserDTO;
|
||||||
import io.metersphere.dto.UserRoleDTO;
|
import io.metersphere.dto.UserRoleDTO;
|
||||||
|
import io.metersphere.excel.domain.ExcelResponse;
|
||||||
import io.metersphere.i18n.Translator;
|
import io.metersphere.i18n.Translator;
|
||||||
|
import io.metersphere.service.CheckPermissionService;
|
||||||
import io.metersphere.service.OrganizationService;
|
import io.metersphere.service.OrganizationService;
|
||||||
import io.metersphere.service.UserService;
|
import io.metersphere.service.UserService;
|
||||||
import io.metersphere.service.WorkspaceService;
|
import io.metersphere.service.WorkspaceService;
|
||||||
|
@ -25,8 +27,10 @@ import org.apache.commons.lang3.StringUtils;
|
||||||
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.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RequestMapping("user")
|
@RequestMapping("user")
|
||||||
|
@ -39,6 +43,8 @@ public class UserController {
|
||||||
private OrganizationService organizationService;
|
private OrganizationService organizationService;
|
||||||
@Resource
|
@Resource
|
||||||
private WorkspaceService workspaceService;
|
private WorkspaceService workspaceService;
|
||||||
|
@Resource
|
||||||
|
private CheckPermissionService checkPermissionService;
|
||||||
|
|
||||||
@PostMapping("/special/add")
|
@PostMapping("/special/add")
|
||||||
@RequiresRoles(RoleConstants.ADMIN)
|
@RequiresRoles(RoleConstants.ADMIN)
|
||||||
|
@ -298,4 +304,15 @@ public class UserController {
|
||||||
return userService.searchUser(condition);
|
return userService.searchUser(condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/export/template")
|
||||||
|
@RequiresRoles(value = {RoleConstants.ADMIN, RoleConstants.ORG_ADMIN, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||||
|
public void testCaseTemplateExport(HttpServletResponse response) {
|
||||||
|
userService.userTemplateExport(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/import/{userId}")
|
||||||
|
@RequiresRoles(value = {RoleConstants.TEST_USER, RoleConstants.TEST_MANAGER}, logical = Logical.OR)
|
||||||
|
public ExcelResponse testCaseImport(MultipartFile file, @PathVariable String userId) {
|
||||||
|
return userService.userImport(file, userId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
package io.metersphere.excel.domain;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelIgnore;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class UserExcelData {
|
||||||
|
|
||||||
|
@ExcelIgnore
|
||||||
|
private String id;
|
||||||
|
@ExcelIgnore
|
||||||
|
private String name;
|
||||||
|
@ExcelIgnore
|
||||||
|
private String email;
|
||||||
|
@ExcelIgnore
|
||||||
|
private String password;
|
||||||
|
@ExcelIgnore
|
||||||
|
private String phone;
|
||||||
|
@ExcelIgnore
|
||||||
|
private String userIsAdmin;
|
||||||
|
@ExcelIgnore
|
||||||
|
private String userIsOrgAdmin;
|
||||||
|
@ExcelIgnore
|
||||||
|
private String orgAdminOrganization;
|
||||||
|
@ExcelIgnore
|
||||||
|
private String userIsOrgMember;
|
||||||
|
@ExcelIgnore
|
||||||
|
private String orgMemberOrganization;
|
||||||
|
@ExcelIgnore
|
||||||
|
private String userIsTestManager;
|
||||||
|
@ExcelIgnore
|
||||||
|
private String testManagerWorkspace;
|
||||||
|
@ExcelIgnore
|
||||||
|
private String userIsTester;
|
||||||
|
@ExcelIgnore
|
||||||
|
private String testerWorkspace;
|
||||||
|
@ExcelIgnore
|
||||||
|
private String userIsViewer;
|
||||||
|
@ExcelIgnore
|
||||||
|
private String viewerWorkspace;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package io.metersphere.excel.domain;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.alibaba.excel.annotation.write.style.ColumnWidth;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.hibernate.validator.constraints.Length;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.Pattern;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@ColumnWidth(15)
|
||||||
|
public class UserExcelDataCn extends UserExcelData {
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@Length(max = 255)
|
||||||
|
@ExcelProperty("ID")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@Length(max = 255)
|
||||||
|
@ExcelProperty("姓名")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@Length(max = 255)
|
||||||
|
@ExcelProperty("电子邮箱")
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@Pattern(regexp = "^[a-zA-Z0-9_._-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$", message = "{user_import_format_wrong}")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@Length(max = 255)
|
||||||
|
@ExcelProperty("密码")
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@Pattern(regexp = "^(?![0-9]+$)(?![^0-9]+$)(?![a-zA-Z]+$)(?![^a-zA-Z]+$)(?![a-zA-Z0-9]+$)[a-zA-Z0-9\\S]{8,30}$", message = "{user_import_format_wrong}")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@ExcelProperty("电话")
|
||||||
|
@Length(max = 11)
|
||||||
|
@Pattern(regexp = "^1(3|4|5|6|7|8|9)\\d{9}$", message = "{user_import_format_wrong}")
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("是否是系统管理员(是/否)")
|
||||||
|
private String userIsAdmin;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("是否是组织管理员(是/否)")
|
||||||
|
private String userIsOrgAdmin;
|
||||||
|
|
||||||
|
@Length(max = 100)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@ExcelProperty("组织管理员工作空间")
|
||||||
|
private String orgAdminOrganization;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("是否是组织成员(是/否)")
|
||||||
|
private String userIsOrgMember;
|
||||||
|
|
||||||
|
@Length(max = 100)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@ExcelProperty("组织成员工作空间")
|
||||||
|
private String orgMemberOrganization;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("是否是测试经理(是/否)")
|
||||||
|
private String userIsTestManager;
|
||||||
|
|
||||||
|
@Length(max = 100)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@ExcelProperty("测试经理工作空间")
|
||||||
|
private String testManagerWorkspace;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("是否是测试成员(是/否)")
|
||||||
|
private String userIsTester;
|
||||||
|
|
||||||
|
@Length(max = 100)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@ExcelProperty("测试成员工作空间")
|
||||||
|
private String testerWorkspace;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("是否是只读用戶(是/否)")
|
||||||
|
private String userIsViewer;
|
||||||
|
|
||||||
|
@Length(max = 100)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@ExcelProperty("只读用户工作空间")
|
||||||
|
private String viewerWorkspace;
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package io.metersphere.excel.domain;
|
||||||
|
|
||||||
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class UserExcelDataFactory implements ExcelDataFactory {
|
||||||
|
@Override
|
||||||
|
public Class getExcelDataByLocal() {
|
||||||
|
Locale locale = LocaleContextHolder.getLocale();
|
||||||
|
if (Locale.US.toString().equalsIgnoreCase(locale.toString())) {
|
||||||
|
return UserExcelDataUs.class;
|
||||||
|
} else if (Locale.TRADITIONAL_CHINESE.toString().equalsIgnoreCase(locale.toString())) {
|
||||||
|
return UserExcelDataTw.class;
|
||||||
|
}
|
||||||
|
return UserExcelDataCn.class;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package io.metersphere.excel.domain;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.alibaba.excel.annotation.write.style.ColumnWidth;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.hibernate.validator.constraints.Length;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.Pattern;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@ColumnWidth(15)
|
||||||
|
public class UserExcelDataTw extends TestCaseExcelData {
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@Length(max = 255)
|
||||||
|
@ExcelProperty("ID")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@Length(max = 255)
|
||||||
|
@ExcelProperty("姓名")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@Length(max = 255)
|
||||||
|
@ExcelProperty("電子郵箱")
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@Pattern(regexp = "^[a-zA-Z0-9_._-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$", message = "{user_import_format_wrong}")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@Length(max = 255)
|
||||||
|
@ExcelProperty("密碼")
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@Pattern(regexp = "^(?![0-9]+$)(?![^0-9]+$)(?![a-zA-Z]+$)(?![^a-zA-Z]+$)(?![a-zA-Z0-9]+$)[a-zA-Z0-9\\S]{8,30}$", message = "{user_import_format_wrong}")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@ExcelProperty("電話")
|
||||||
|
@Length(max = 11)
|
||||||
|
@Pattern(regexp = "^1(3|4|5|6|7|8|9)\\d{9}$", message = "{user_import_format_wrong}")
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("是否是系統管理員(是/否)")
|
||||||
|
private String userIsAdmin;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("是否是組織管理員(是/否)")
|
||||||
|
private String userIsOrgAdmin;
|
||||||
|
|
||||||
|
@Length(max = 100)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@ExcelProperty("組織管理員工作空間")
|
||||||
|
private String orgAdminOrganization;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("是否是組織成員(是/否)")
|
||||||
|
private String userIsOrgMember;
|
||||||
|
|
||||||
|
@Length(max = 100)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@ExcelProperty("組織成員工作空間")
|
||||||
|
private String orgMemberOrganization;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("是否是測試經理(是/否)")
|
||||||
|
private String userIsTestManager;
|
||||||
|
|
||||||
|
@Length(max = 100)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@ExcelProperty("測試經理工作空間")
|
||||||
|
private String testManagerWorkspace;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("是否是測試成員(是/否)")
|
||||||
|
private String userIsTester;
|
||||||
|
|
||||||
|
@Length(max = 100)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@ExcelProperty("測試成員工作空間")
|
||||||
|
private String testerWorkspace;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("是否是只讀用戶(是/否)")
|
||||||
|
private String userIsViewer;
|
||||||
|
|
||||||
|
@Length(max = 100)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@ExcelProperty("只讀用戶工作空間")
|
||||||
|
private String viewerWorkspace;
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
package io.metersphere.excel.domain;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelIgnore;
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.alibaba.excel.annotation.write.style.ColumnWidth;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.hibernate.validator.constraints.Length;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.Pattern;
|
||||||
|
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@ColumnWidth(15)
|
||||||
|
public class UserExcelDataUs extends UserExcelData {
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@Length(max = 255)
|
||||||
|
@ExcelProperty("Id")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@Length(max = 255)
|
||||||
|
@ExcelProperty("Name")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@Length(max = 255)
|
||||||
|
@ExcelProperty("E-mail")
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@Pattern(regexp = "^[a-zA-Z0-9_._-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$", message = "{user_import_format_wrong}")
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@Length(max = 255)
|
||||||
|
@ExcelProperty("Password")
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@Pattern(regexp = "^(?![0-9]+$)(?![^0-9]+$)(?![a-zA-Z]+$)(?![^a-zA-Z]+$)(?![a-zA-Z0-9]+$)[a-zA-Z0-9\\S]{8,30}$", message = "{user_import_format_wrong}")
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@ExcelProperty("Phone")
|
||||||
|
@Length(max = 11)
|
||||||
|
@Pattern(regexp = "^1(3|4|5|6|7|8|9)\\d{9}$", message = "{user_import_format_wrong}")
|
||||||
|
private String phone;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("User is administrator(Yes/No)")
|
||||||
|
private String userIsAdmin;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("User is organization manager(Yes/No)")
|
||||||
|
private String userIsOrgAdmin;
|
||||||
|
|
||||||
|
@Length(max = 100)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@ExcelProperty("Manager in witch organization")
|
||||||
|
private String orgAdminOrganization;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("User is organization member(Yes/No)")
|
||||||
|
private String userIsOrgMember;
|
||||||
|
|
||||||
|
@Length(max = 100)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@ExcelProperty("Member in witch organization")
|
||||||
|
private String orgMemberOrganization;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("User is test manager(Yes/No)")
|
||||||
|
private String userIsTestManager;
|
||||||
|
|
||||||
|
@Length(max = 100)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@ExcelProperty("Workspace of test manager")
|
||||||
|
private String testManagerWorkspace;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("User is tester(Yes/No)")
|
||||||
|
private String userIsTester;
|
||||||
|
|
||||||
|
@Length(max = 100)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@ExcelProperty("Workspace of tester")
|
||||||
|
private String testerWorkspace;
|
||||||
|
|
||||||
|
@NotBlank(message = "{cannot_be_null}")
|
||||||
|
@ExcelProperty("User is read-only user(Yes/No)")
|
||||||
|
private String userIsViewer;
|
||||||
|
|
||||||
|
@Length(max = 100)
|
||||||
|
@ColumnWidth(30)
|
||||||
|
@ExcelProperty("Workspace of read-only user")
|
||||||
|
private String viewerWorkspace;
|
||||||
|
}
|
|
@ -8,6 +8,7 @@ import com.alibaba.excel.util.StringUtils;
|
||||||
import io.metersphere.commons.utils.LogUtil;
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
import io.metersphere.excel.domain.ExcelErrData;
|
import io.metersphere.excel.domain.ExcelErrData;
|
||||||
import io.metersphere.excel.domain.TestCaseExcelData;
|
import io.metersphere.excel.domain.TestCaseExcelData;
|
||||||
|
import io.metersphere.excel.domain.UserExcelData;
|
||||||
import io.metersphere.excel.utils.ExcelValidateHelper;
|
import io.metersphere.excel.utils.ExcelValidateHelper;
|
||||||
import io.metersphere.i18n.Translator;
|
import io.metersphere.i18n.Translator;
|
||||||
|
|
||||||
|
@ -139,5 +140,4 @@ public abstract class EasyExcelListener<T> extends AnalysisEventListener<T> {
|
||||||
public List<ExcelErrData<T>> getErrList() {
|
public List<ExcelErrData<T>> getErrList() {
|
||||||
return errList;
|
return errList;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -0,0 +1,277 @@
|
||||||
|
package io.metersphere.excel.listener;
|
||||||
|
|
||||||
|
import io.metersphere.commons.exception.MSException;
|
||||||
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
|
import io.metersphere.controller.request.member.UserRequest;
|
||||||
|
import io.metersphere.excel.domain.UserExcelData;
|
||||||
|
import io.metersphere.i18n.Translator;
|
||||||
|
import io.metersphere.service.UserService;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class UserDataListener extends EasyExcelListener<UserExcelData> {
|
||||||
|
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
//key:workspace.name value:id
|
||||||
|
Map<String, String> workspaceNameMap;
|
||||||
|
//key:Organization.name value:id
|
||||||
|
Map<String, String> orgNameMap;
|
||||||
|
//已经保存的用户ID
|
||||||
|
List<String> savedUserId;
|
||||||
|
|
||||||
|
public UserDataListener(Class clazz,Map<String, String> workspaceNameMap,Map<String, String> orgNameMap) {
|
||||||
|
this.clazz = clazz;
|
||||||
|
this.workspaceNameMap = workspaceNameMap;
|
||||||
|
this.orgNameMap = orgNameMap;
|
||||||
|
this.userService = (UserService) CommonBeanFactory.getBean("userService");
|
||||||
|
savedUserId = userService.selectAllId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String validate(UserExcelData data, String errMsg) {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder(errMsg);
|
||||||
|
|
||||||
|
//判断组织管理员组织
|
||||||
|
String orgManagerOrgCheck = this.checkOrganization(data.getUserIsOrgAdmin(), data.getOrgAdminOrganization());
|
||||||
|
if (orgManagerOrgCheck != null) {
|
||||||
|
stringBuilder.append(orgManagerOrgCheck);
|
||||||
|
}
|
||||||
|
//判断组织成员组织
|
||||||
|
String orgMemberOrgCheck = this.checkOrganization(data.getUserIsOrgMember(), data.getOrgMemberOrganization());
|
||||||
|
if (orgMemberOrgCheck != null) {
|
||||||
|
stringBuilder.append(orgMemberOrgCheck);
|
||||||
|
}
|
||||||
|
//判断测试经理工作空间
|
||||||
|
String testManagerWorkspaceCheck = this.checkWorkSpace(data.getUserIsTestManager(), data.getTestManagerWorkspace());
|
||||||
|
if (testManagerWorkspaceCheck != null) {
|
||||||
|
stringBuilder.append(testManagerWorkspaceCheck);
|
||||||
|
}
|
||||||
|
//判断测试人员工作空间
|
||||||
|
String testerWorkspaceCheck = this.checkWorkSpace(data.getUserIsTester(), data.getTesterWorkspace());
|
||||||
|
if (testerWorkspaceCheck != null) {
|
||||||
|
stringBuilder.append(testerWorkspaceCheck);
|
||||||
|
}
|
||||||
|
//判断只读用户工作空间
|
||||||
|
String viewerWorkspaceCheck = this.checkWorkSpace(data.getUserIsViewer(), data.getViewerWorkspace());
|
||||||
|
if (viewerWorkspaceCheck != null) {
|
||||||
|
stringBuilder.append(viewerWorkspaceCheck);
|
||||||
|
}
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveData() {
|
||||||
|
//检查有无重复数据
|
||||||
|
String checkRepeatDataResult = this.checkRepeatIdAndEmail(list);
|
||||||
|
if(!StringUtils.isEmpty(checkRepeatDataResult)){
|
||||||
|
MSException.throwException(checkRepeatDataResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
//无错误数据才插入数据
|
||||||
|
if (!errList.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Collections.reverse(list);
|
||||||
|
List<UserRequest> result = list.stream().map(item -> this.convert2UserRequest(item)).collect(Collectors.toList());
|
||||||
|
|
||||||
|
for (UserRequest userRequest : result) {
|
||||||
|
String id = userRequest.getId();
|
||||||
|
if (savedUserId.contains(id)) {
|
||||||
|
//已经在数据库内的,走更新逻辑
|
||||||
|
userService.updateUserRole(userRequest);
|
||||||
|
} else {
|
||||||
|
//不再数据库中的走新建逻辑
|
||||||
|
userService.insert(userRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查工作空间
|
||||||
|
*
|
||||||
|
* @param userRoleInExcel excel表里的用户权限填写信息
|
||||||
|
* @param workspaceInfoInExcel excel表中用户的工作空间填写信息
|
||||||
|
* @return 报错信息
|
||||||
|
*/
|
||||||
|
private String checkWorkSpace(String userRoleInExcel, String workspaceInfoInExcel) {
|
||||||
|
String result = null;
|
||||||
|
if (StringUtils.equalsIgnoreCase(Translator.get("options_yes"), userRoleInExcel)) {
|
||||||
|
String[] workspaceArr = workspaceInfoInExcel.split("\n");
|
||||||
|
for (String workspace :
|
||||||
|
workspaceArr) {
|
||||||
|
if (!workspaceNameMap.containsKey(workspace)) {
|
||||||
|
if (result == null) {
|
||||||
|
result = new String(Translator.get("user_import_workspace_not_fond") + ":" + workspace + "; ");
|
||||||
|
} else {
|
||||||
|
result += Translator.get("user_import_workspace_not_fond") + ":" + workspace + "; ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查组织
|
||||||
|
*
|
||||||
|
* @param userRoleInExcel excel表里的用户权限填写信息
|
||||||
|
* @param organizationInfoInExcel excel表中用户组织填写信息
|
||||||
|
* @return 报错信息
|
||||||
|
*/
|
||||||
|
private String checkOrganization(String userRoleInExcel, String organizationInfoInExcel) {
|
||||||
|
String result = null;
|
||||||
|
if (StringUtils.equalsIgnoreCase(Translator.get("options_yes"), userRoleInExcel)) {
|
||||||
|
String[] organizationArr = organizationInfoInExcel.split("\n");
|
||||||
|
for (String organization :
|
||||||
|
organizationArr) {
|
||||||
|
if (!orgNameMap.containsKey(organization)) {
|
||||||
|
if (result == null) {
|
||||||
|
result = new String(Translator.get("user_import_organization_not_fond") + ":" + organization + "; ");
|
||||||
|
} else {
|
||||||
|
result += Translator.get("user_import_organization_not_fond") + ":" + organization + "; ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过excel的信息,以及id字典对象,获取相对应的ID
|
||||||
|
*
|
||||||
|
* @param userRoleInExcel excel中的信息,是否进行工作空间或者组织的id转化
|
||||||
|
* @param nameStringInExce excel中的信息,组织或者工作空间的名称
|
||||||
|
* @param idDic id字典对象,传入组织或者工作空间的<name:id>类
|
||||||
|
* @return 转化后的id集合
|
||||||
|
*/
|
||||||
|
private List<String> getIdByExcelInfoAndIdDic(String userRoleInExcel, String nameStringInExce, Map<String, String> idDic) {
|
||||||
|
List<String> resultList = new ArrayList<>();
|
||||||
|
if (StringUtils.equalsIgnoreCase(Translator.get("options_yes"), userRoleInExcel)) {
|
||||||
|
String[] nameArr = nameStringInExce.split("\n");
|
||||||
|
for (String name : nameArr) {
|
||||||
|
if (idDic.containsKey(name)) {
|
||||||
|
resultList.add(idDic.get(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resultList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private UserRequest convert2UserRequest(UserExcelData data) {
|
||||||
|
UserRequest request = new UserRequest();
|
||||||
|
request.setId(data.getId());
|
||||||
|
request.setStatus("1");
|
||||||
|
request.setSource("LOCAL");
|
||||||
|
request.setName(data.getName());
|
||||||
|
request.setEmail(data.getEmail());
|
||||||
|
request.setPhone(data.getPhone());
|
||||||
|
//这里的password要加密
|
||||||
|
request.setPassword(data.getPassword());
|
||||||
|
|
||||||
|
List<Map<String, Object>> roleMapList = new ArrayList<>();
|
||||||
|
//判断是否是Admin
|
||||||
|
if (StringUtils.equalsIgnoreCase(Translator.get("options_yes"), data.getUserIsAdmin())) {
|
||||||
|
List<String> adminIdList = new ArrayList<>();
|
||||||
|
adminIdList.add("adminSourceId");
|
||||||
|
Map<String, Object> adminRoleMap = this.genRoleMap("admin", adminIdList);
|
||||||
|
roleMapList.add(adminRoleMap);
|
||||||
|
}
|
||||||
|
//判断组织管理员
|
||||||
|
List<String> orgManagerOrdIdList = this.getIdByExcelInfoAndIdDic(data.getUserIsOrgAdmin(), data.getOrgAdminOrganization(), orgNameMap);
|
||||||
|
if (!orgManagerOrdIdList.isEmpty()) {
|
||||||
|
Map<String, Object> orgAdminRoleMap = this.genRoleMap("org_admin", orgManagerOrdIdList);
|
||||||
|
roleMapList.add(orgAdminRoleMap);
|
||||||
|
}
|
||||||
|
//判断组织成员
|
||||||
|
List<String> orgMemberOrdIdList = this.getIdByExcelInfoAndIdDic(data.getUserIsOrgMember(), data.getOrgMemberOrganization(), orgNameMap);
|
||||||
|
if (!orgMemberOrdIdList.isEmpty()) {
|
||||||
|
Map<String, Object> orgMemberRoleMap = this.genRoleMap("org_member", orgMemberOrdIdList);
|
||||||
|
roleMapList.add(orgMemberRoleMap);
|
||||||
|
}
|
||||||
|
//判断测试经理
|
||||||
|
List<String> testManagerWorkspaceIdList = this.getIdByExcelInfoAndIdDic(data.getUserIsTestManager(), data.getTestManagerWorkspace(), workspaceNameMap);
|
||||||
|
if (!testManagerWorkspaceIdList.isEmpty()) {
|
||||||
|
Map<String, Object> testManagerRoleMap = this.genRoleMap("test_manager", testManagerWorkspaceIdList);
|
||||||
|
roleMapList.add(testManagerRoleMap);
|
||||||
|
}
|
||||||
|
//判断测试人员
|
||||||
|
List<String> testgerWorkspaceIdList = this.getIdByExcelInfoAndIdDic(data.getUserIsTester(), data.getTesterWorkspace(), workspaceNameMap);
|
||||||
|
if (!testgerWorkspaceIdList.isEmpty()) {
|
||||||
|
Map<String, Object> testerRoleMap = this.genRoleMap("test_user", testgerWorkspaceIdList);
|
||||||
|
roleMapList.add(testerRoleMap);
|
||||||
|
}
|
||||||
|
//判断只读用户
|
||||||
|
List<String> viewerWorkspaceIdList = this.getIdByExcelInfoAndIdDic(data.getUserIsViewer(), data.getViewerWorkspace(), workspaceNameMap);
|
||||||
|
if (!viewerWorkspaceIdList.isEmpty()) {
|
||||||
|
Map<String, Object> testViewerRoleMap = this.genRoleMap("test_viewer", viewerWorkspaceIdList);
|
||||||
|
roleMapList.add(testViewerRoleMap);
|
||||||
|
}
|
||||||
|
request.setRoles(roleMapList);
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 封装用户权限数据格式
|
||||||
|
* @param roleName 权限名称
|
||||||
|
* @param roleIdList 对应的权限ID
|
||||||
|
* @return 保存用户时,对应的数据权限的数据格式
|
||||||
|
*/
|
||||||
|
private Map<String, Object> genRoleMap(String roleName, List<String> roleIdList) {
|
||||||
|
Map<String, Object> roleMap = new HashMap<>();
|
||||||
|
if (roleName == null || roleIdList == null) {
|
||||||
|
return roleMap;
|
||||||
|
}
|
||||||
|
roleMap.put("id", roleName);
|
||||||
|
roleMap.put("ids", roleIdList);
|
||||||
|
return roleMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否有重复的ID和Email
|
||||||
|
* @param list
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String checkRepeatIdAndEmail(List<UserExcelData> list){
|
||||||
|
String checkRepeatIdResult = new String();
|
||||||
|
|
||||||
|
List<String> allIdList = new ArrayList<>();
|
||||||
|
List<String> allEmailList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (UserExcelData data: list) {
|
||||||
|
allIdList.add(data.getId());
|
||||||
|
allEmailList.add(data.getEmail());
|
||||||
|
}
|
||||||
|
List<String> repeatIdList = allIdList.stream()
|
||||||
|
.collect(Collectors.toMap(e -> e, e -> 1, (a, b) -> a + b)) // 获得元素出现频率的 Map,键为元素,值为元素出现的次数
|
||||||
|
.entrySet().stream() // Set<Entry>转换为Stream<Entry>
|
||||||
|
.filter(entry -> entry.getValue() > 1) // 过滤出元素出现次数大于 1 的 entry
|
||||||
|
.map(entry -> entry.getKey()) // 获得 entry 的键(重复元素)对应的 Stream
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if(!repeatIdList.isEmpty()){
|
||||||
|
checkRepeatIdResult += Translator.get("user_import_id_is_repeat") + ":";
|
||||||
|
for (String repeatID:repeatIdList) {
|
||||||
|
checkRepeatIdResult += repeatID+";";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> repeatEmailList = allEmailList.stream()
|
||||||
|
.collect(Collectors.toMap(e -> e, e -> 1, (a, b) -> a + b)) // 获得元素出现频率的 Map,键为元素,值为元素出现的次数
|
||||||
|
.entrySet().stream() // Set<Entry>转换为Stream<Entry>
|
||||||
|
.filter(entry -> entry.getValue() > 1) // 过滤出元素出现次数大于 1 的 entry
|
||||||
|
.map(entry -> entry.getKey()) // 获得 entry 的键(重复元素)对应的 Stream
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if(!repeatEmailList.isEmpty()){
|
||||||
|
checkRepeatIdResult += Translator.get("user_import_email_is_repeat") + ":";
|
||||||
|
for (String repeatEmail:repeatEmailList) {
|
||||||
|
checkRepeatIdResult += repeatEmail+";";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return checkRepeatIdResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -178,4 +178,8 @@ public class OrganizationService {
|
||||||
MSException.throwException(Translator.get("organization_does_not_belong_to_user"));
|
MSException.throwException(Translator.get("organization_does_not_belong_to_user"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<OrganizationMemberDTO> findAllIdAndName(){
|
||||||
|
return extOrganizationMapper.findAllIdAndName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,20 @@
|
||||||
package io.metersphere.service;
|
package io.metersphere.service;
|
||||||
|
|
||||||
|
import com.alibaba.excel.EasyExcelFactory;
|
||||||
import io.metersphere.base.domain.*;
|
import io.metersphere.base.domain.*;
|
||||||
import io.metersphere.base.mapper.*;
|
import io.metersphere.base.mapper.*;
|
||||||
|
import io.metersphere.base.mapper.ext.ExtOrganizationMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtUserMapper;
|
import io.metersphere.base.mapper.ext.ExtUserMapper;
|
||||||
import io.metersphere.base.mapper.ext.ExtUserRoleMapper;
|
import io.metersphere.base.mapper.ext.ExtUserRoleMapper;
|
||||||
import io.metersphere.commons.constants.RoleConstants;
|
import io.metersphere.commons.constants.RoleConstants;
|
||||||
|
import io.metersphere.commons.constants.TestCaseConstants;
|
||||||
import io.metersphere.commons.constants.UserSource;
|
import io.metersphere.commons.constants.UserSource;
|
||||||
import io.metersphere.commons.constants.UserStatus;
|
import io.metersphere.commons.constants.UserStatus;
|
||||||
import io.metersphere.commons.exception.MSException;
|
import io.metersphere.commons.exception.MSException;
|
||||||
import io.metersphere.commons.user.SessionUser;
|
import io.metersphere.commons.user.SessionUser;
|
||||||
import io.metersphere.commons.utils.CodingUtil;
|
import io.metersphere.commons.utils.CodingUtil;
|
||||||
import io.metersphere.commons.utils.CommonBeanFactory;
|
import io.metersphere.commons.utils.CommonBeanFactory;
|
||||||
|
import io.metersphere.commons.utils.LogUtil;
|
||||||
import io.metersphere.commons.utils.SessionUtils;
|
import io.metersphere.commons.utils.SessionUtils;
|
||||||
import io.metersphere.controller.ResultHolder;
|
import io.metersphere.controller.ResultHolder;
|
||||||
import io.metersphere.controller.request.LoginRequest;
|
import io.metersphere.controller.request.LoginRequest;
|
||||||
|
@ -20,11 +24,20 @@ import io.metersphere.controller.request.member.QueryMemberRequest;
|
||||||
import io.metersphere.controller.request.member.UserRequest;
|
import io.metersphere.controller.request.member.UserRequest;
|
||||||
import io.metersphere.controller.request.organization.AddOrgMemberRequest;
|
import io.metersphere.controller.request.organization.AddOrgMemberRequest;
|
||||||
import io.metersphere.controller.request.organization.QueryOrgMemberRequest;
|
import io.metersphere.controller.request.organization.QueryOrgMemberRequest;
|
||||||
|
import io.metersphere.dto.OrganizationMemberDTO;
|
||||||
import io.metersphere.dto.UserDTO;
|
import io.metersphere.dto.UserDTO;
|
||||||
import io.metersphere.dto.UserRoleDTO;
|
import io.metersphere.dto.UserRoleDTO;
|
||||||
|
import io.metersphere.dto.WorkspaceDTO;
|
||||||
|
import io.metersphere.excel.domain.*;
|
||||||
|
import io.metersphere.excel.listener.EasyExcelListener;
|
||||||
|
import io.metersphere.excel.listener.TestCaseDataListener;
|
||||||
|
import io.metersphere.excel.listener.UserDataListener;
|
||||||
|
import io.metersphere.excel.utils.EasyExcelExporter;
|
||||||
import io.metersphere.i18n.Translator;
|
import io.metersphere.i18n.Translator;
|
||||||
import io.metersphere.notice.domain.UserDetail;
|
import io.metersphere.notice.domain.UserDetail;
|
||||||
import io.metersphere.security.MsUserToken;
|
import io.metersphere.security.MsUserToken;
|
||||||
|
import io.metersphere.track.request.testcase.QueryTestCaseRequest;
|
||||||
|
import io.metersphere.xmind.XmindCaseParser;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.apache.shiro.authc.*;
|
import org.apache.shiro.authc.*;
|
||||||
|
@ -35,8 +48,10 @@ import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ -63,6 +78,8 @@ public class UserService {
|
||||||
@Lazy
|
@Lazy
|
||||||
@Resource
|
@Resource
|
||||||
private WorkspaceService workspaceService;
|
private WorkspaceService workspaceService;
|
||||||
|
@Resource
|
||||||
|
private ExtOrganizationMapper extOrganizationMapper;
|
||||||
|
|
||||||
public List<UserDetail> queryTypeByIds(List<String> userIds) {
|
public List<UserDetail> queryTypeByIds(List<String> userIds) {
|
||||||
return extUserMapper.queryTypeByIds(userIds);
|
return extUserMapper.queryTypeByIds(userIds);
|
||||||
|
@ -616,4 +633,93 @@ public class UserService {
|
||||||
ssoService.logout();
|
ssoService.logout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void userTemplateExport(HttpServletResponse response) {
|
||||||
|
try {
|
||||||
|
EasyExcelExporter easyExcelExporter = new EasyExcelExporter(new UserExcelDataFactory().getExcelDataByLocal());
|
||||||
|
easyExcelExporter.export(response, generateExportTemplate(),
|
||||||
|
Translator.get("user_import_template_name"), Translator.get("user_import_template_sheet"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
MSException.throwException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<UserExcelData> generateExportTemplate() {
|
||||||
|
List<UserExcelData> list = new ArrayList<>();
|
||||||
|
List<String> types = TestCaseConstants.Type.getValues();
|
||||||
|
List<String> methods = TestCaseConstants.Method.getValues();
|
||||||
|
SessionUser user = SessionUtils.getUser();
|
||||||
|
for (int i = 1; i <= 2; i++) {
|
||||||
|
UserExcelData data = new UserExcelData();
|
||||||
|
data.setId("user_id_"+i);
|
||||||
|
data.setName(Translator.get("user") + i);
|
||||||
|
String workspace = "";
|
||||||
|
for (int workspaceIndex = 1; workspaceIndex <= i; workspaceIndex++) {
|
||||||
|
if (workspaceIndex == 1) {
|
||||||
|
workspace = "workspace" + workspaceIndex;
|
||||||
|
} else {
|
||||||
|
workspace = workspace + "\n" + "workspace" + workspaceIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data.setUserIsAdmin(Translator.get("options_no"));
|
||||||
|
data.setUserIsTester(Translator.get("options_no"));
|
||||||
|
data.setUserIsOrgMember(Translator.get("options_no"));
|
||||||
|
data.setUserIsViewer(Translator.get("options_no"));
|
||||||
|
data.setUserIsTestManager(Translator.get("options_no"));
|
||||||
|
data.setUserIsOrgAdmin(Translator.get("options_yes"));
|
||||||
|
data.setOrgAdminOrganization(workspace);
|
||||||
|
list.add(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
list.add(new UserExcelData());
|
||||||
|
UserExcelData explain = new UserExcelData();
|
||||||
|
explain.setName(Translator.get("do_not_modify_header_order"));
|
||||||
|
explain.setOrgAdminOrganization("多个工作空间请换行展示");
|
||||||
|
list.add(explain);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExcelResponse userImport(MultipartFile multipartFile, String userId) {
|
||||||
|
|
||||||
|
ExcelResponse excelResponse = new ExcelResponse();
|
||||||
|
String currentWorkspaceId = SessionUtils.getCurrentWorkspaceId();
|
||||||
|
List<ExcelErrData<TestCaseExcelData>> errList = null;
|
||||||
|
if (multipartFile == null) {
|
||||||
|
MSException.throwException(Translator.get("upload_fail"));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Class clazz = new UserExcelDataFactory().getExcelDataByLocal();
|
||||||
|
|
||||||
|
Map<String,String> orgNameMap = new HashMap<>();
|
||||||
|
Map<String,String> workspaceNameMap = new HashMap<>();
|
||||||
|
|
||||||
|
List<OrganizationMemberDTO> organizationList = extOrganizationMapper.findAllIdAndName();
|
||||||
|
for (OrganizationMemberDTO model : organizationList) {
|
||||||
|
orgNameMap.put(model.getName(),model.getId());
|
||||||
|
}
|
||||||
|
List<WorkspaceDTO> workspaceList = workspaceService.findAllIdAndName();
|
||||||
|
for (WorkspaceDTO model : workspaceList) {
|
||||||
|
workspaceNameMap.put(model.getName(),model.getId());
|
||||||
|
}
|
||||||
|
EasyExcelListener easyExcelListener = new UserDataListener(clazz,workspaceNameMap,orgNameMap);
|
||||||
|
EasyExcelFactory.read(multipartFile.getInputStream(), clazz, easyExcelListener).sheet().doRead();
|
||||||
|
errList = easyExcelListener.getErrList();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LogUtil.error(e.getMessage(), e);
|
||||||
|
MSException.throwException(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
//如果包含错误信息就导出错误信息
|
||||||
|
if (!errList.isEmpty()) {
|
||||||
|
excelResponse.setSuccess(false);
|
||||||
|
excelResponse.setErrList(errList);
|
||||||
|
} else {
|
||||||
|
excelResponse.setSuccess(true);
|
||||||
|
}
|
||||||
|
return excelResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> selectAllId() {
|
||||||
|
return extUserMapper.selectAllId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package io.metersphere.service;
|
package io.metersphere.service;
|
||||||
|
|
||||||
|
import com.sun.corba.se.spi.orbutil.threadpool.Work;
|
||||||
import io.metersphere.base.domain.*;
|
import io.metersphere.base.domain.*;
|
||||||
import io.metersphere.base.mapper.ProjectMapper;
|
import io.metersphere.base.mapper.ProjectMapper;
|
||||||
import io.metersphere.base.mapper.UserMapper;
|
import io.metersphere.base.mapper.UserMapper;
|
||||||
|
@ -284,4 +285,8 @@ public class WorkspaceService {
|
||||||
projectExample.createCriteria().andWorkspaceIdEqualTo(workspaceId);
|
projectExample.createCriteria().andWorkspaceIdEqualTo(workspaceId);
|
||||||
return projectMapper.selectByExample(projectExample);
|
return projectMapper.selectByExample(projectExample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<WorkspaceDTO> findAllIdAndName(){
|
||||||
|
return extWorkspaceMapper.findAllIdAndName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,17 @@ test_case_remark=
|
||||||
test_case_step_desc=
|
test_case_step_desc=
|
||||||
test_case_step_result=
|
test_case_step_result=
|
||||||
test_case=
|
test_case=
|
||||||
|
user=
|
||||||
|
user_import_template_name=
|
||||||
|
user_import_template_sheet=
|
||||||
|
user_import_format_wrong=
|
||||||
|
user_import_id_is_repeat=
|
||||||
|
user_import_email_is_repeat=
|
||||||
|
user_import_password_format_wrong=
|
||||||
|
user_import_phone_format_wrong=
|
||||||
|
user_import_email_format_wrong=
|
||||||
|
user_import_organization_not_fond=
|
||||||
|
user_import_workspace_not_fond=
|
||||||
module=
|
module=
|
||||||
preconditions_optional=
|
preconditions_optional=
|
||||||
step_tip_separate=
|
step_tip_separate=
|
||||||
|
@ -41,5 +52,7 @@ remark_optional=
|
||||||
do_not_modify_header_order=
|
do_not_modify_header_order=
|
||||||
module_created_automatically=
|
module_created_automatically=
|
||||||
options=
|
options=
|
||||||
|
options_yes=
|
||||||
|
options_no=
|
||||||
please_input_workspace_member=
|
please_input_workspace_member=
|
||||||
test_case_report_template_repeat=
|
test_case_report_template_repeat=
|
|
@ -105,6 +105,17 @@ test_case_step_desc=Step description
|
||||||
test_case_step_result=Step result
|
test_case_step_result=Step result
|
||||||
test_case_module=Module
|
test_case_module=Module
|
||||||
test_case=Test case
|
test_case=Test case
|
||||||
|
user=User
|
||||||
|
user_import_template_name=User import templates
|
||||||
|
user_import_template_sheet=templates
|
||||||
|
user_import_format_wrong=input error
|
||||||
|
user_import_id_is_repeat=Id repeat
|
||||||
|
user_import_email_is_repeat=E-mail repeat
|
||||||
|
user_import_password_format_wrong=Wrong password format
|
||||||
|
user_import_phone_format_wrong=Wrong phone format
|
||||||
|
user_import_email_format_wrong=Wrong email format
|
||||||
|
user_import_organization_not_fond=Organization is not found
|
||||||
|
user_import_workspace_not_fond=Workspace is not found
|
||||||
module=Module
|
module=Module
|
||||||
preconditions_optional=Preconditions optional
|
preconditions_optional=Preconditions optional
|
||||||
step_tip_separate=Each step is separated by a new line
|
step_tip_separate=Each step is separated by a new line
|
||||||
|
@ -117,6 +128,8 @@ remark_optional=Remark optional
|
||||||
do_not_modify_header_order=Do not modify the header order
|
do_not_modify_header_order=Do not modify the header order
|
||||||
module_created_automatically=If there is no such module, will be created automatically
|
module_created_automatically=If there is no such module, will be created automatically
|
||||||
options=options
|
options=options
|
||||||
|
options_yes=Yes
|
||||||
|
options_no=No
|
||||||
please_input_workspace_member=Please input workspace merber
|
please_input_workspace_member=Please input workspace merber
|
||||||
test_case_report_template_repeat=The workspace has the same name template
|
test_case_report_template_repeat=The workspace has the same name template
|
||||||
plan_name_already_exists=Test plan name already exists
|
plan_name_already_exists=Test plan name already exists
|
||||||
|
|
|
@ -105,6 +105,17 @@ test_case_step_desc=步骤描述
|
||||||
test_case_step_result=预期结果
|
test_case_step_result=预期结果
|
||||||
test_case_module=所属模块
|
test_case_module=所属模块
|
||||||
test_case=测试用例
|
test_case=测试用例
|
||||||
|
user=用户
|
||||||
|
user_import_template_name=用户导入模板
|
||||||
|
user_import_template_sheet=模版
|
||||||
|
user_import_format_wrong=格式错误
|
||||||
|
user_import_id_is_repeat=ID重复
|
||||||
|
user_import_email_is_repeat=E-mail重复
|
||||||
|
user_import_password_format_wrong=密码格式错误
|
||||||
|
user_import_phone_format_wrong=手机号码格式错误
|
||||||
|
user_import_email_format_wrong=电子邮箱格式错误
|
||||||
|
user_import_organization_not_fond=组织未找到
|
||||||
|
user_import_workspace_not_fond=工作空间未找到
|
||||||
module=模块
|
module=模块
|
||||||
preconditions_optional=前置条件选填
|
preconditions_optional=前置条件选填
|
||||||
step_tip_separate=每个步骤以换行分隔
|
step_tip_separate=每个步骤以换行分隔
|
||||||
|
@ -117,6 +128,8 @@ remark_optional=备注选填
|
||||||
do_not_modify_header_order=请勿修改表头顺序
|
do_not_modify_header_order=请勿修改表头顺序
|
||||||
module_created_automatically=若无该模块将自动创建
|
module_created_automatically=若无该模块将自动创建
|
||||||
options=选项
|
options=选项
|
||||||
|
options_yes=是
|
||||||
|
options_no=否
|
||||||
please_input_workspace_member=请填写该工作空间相关人员
|
please_input_workspace_member=请填写该工作空间相关人员
|
||||||
test_case_report_template_repeat=同一工作空间下不能存在同名模版
|
test_case_report_template_repeat=同一工作空间下不能存在同名模版
|
||||||
plan_name_already_exists=测试计划名称已存在
|
plan_name_already_exists=测试计划名称已存在
|
||||||
|
|
|
@ -105,6 +105,17 @@ test_case_step_desc=步驟描述
|
||||||
test_case_step_result=預期結果
|
test_case_step_result=預期結果
|
||||||
test_case_module=所屬模塊
|
test_case_module=所屬模塊
|
||||||
test_case=測試用例
|
test_case=測試用例
|
||||||
|
user=用戶
|
||||||
|
user_import_template_name=用戶導入模板
|
||||||
|
user_import_template_sheet=模板
|
||||||
|
user_import_format_wrong=格式錯誤
|
||||||
|
user_import_id_is_repeat=ID重複
|
||||||
|
user_import_email_is_repeat=E-mail重複
|
||||||
|
user_import_password_format_wrong=密碼格式錯誤
|
||||||
|
user_import_phone_format_wrong=手機號碼格式錯誤
|
||||||
|
user_import_email_format_wrong=電子郵箱格式錯誤
|
||||||
|
user_import_organization_not_fond=組織未找到
|
||||||
|
user_import_workspace_not_fond=工作空間未找到
|
||||||
module=模塊
|
module=模塊
|
||||||
preconditions_optional=前置條件選填
|
preconditions_optional=前置條件選填
|
||||||
step_tip_separate=每個步驟以換行分隔
|
step_tip_separate=每個步驟以換行分隔
|
||||||
|
@ -117,6 +128,8 @@ remark_optional=備註選填
|
||||||
do_not_modify_header_order=請勿修改表頭順序
|
do_not_modify_header_order=請勿修改表頭順序
|
||||||
module_created_automatically=若無該模塊將自動創建
|
module_created_automatically=若無該模塊將自動創建
|
||||||
options=選項
|
options=選項
|
||||||
|
options_yes=是
|
||||||
|
options_no=否
|
||||||
please_input_workspace_member=請填寫該工作空間相關人員
|
please_input_workspace_member=請填寫該工作空間相關人員
|
||||||
test_case_report_template_repeat=同壹工作空間下不能存在同名模版
|
test_case_report_template_repeat=同壹工作空間下不能存在同名模版
|
||||||
plan_name_already_exists=測試計劃名稱已存在
|
plan_name_already_exists=測試計劃名稱已存在
|
||||||
|
|
|
@ -111,26 +111,9 @@
|
||||||
<el-col :span="3" class="ms-col-one ms-font">
|
<el-col :span="3" class="ms-col-one ms-font">
|
||||||
<el-checkbox v-model="enableCookieShare">共享cookie</el-checkbox>
|
<el-checkbox v-model="enableCookieShare">共享cookie</el-checkbox>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="7" class="ms-col-one ms-font">
|
<el-col :span="7">
|
||||||
<el-link type="primary" @click="handleEnv">环境配置</el-link>
|
<env-popover :env-map="projectEnvMap" :project-ids="projectIds" @setProjectEnvMap="setProjectEnvMap"
|
||||||
<!-- <el-select v-model="currentEnvironmentId" size="small" class="ms-htt-width"-->
|
:project-list="projectList" ref="envPopover"/>
|
||||||
<!-- :placeholder="$t('api_test.definition.request.run_env')"-->
|
|
||||||
<!-- clearable>-->
|
|
||||||
<!-- <el-option v-for="(environment, index) in environments" :key="index"-->
|
|
||||||
<!-- :label="environment.name + (environment.config.httpConfig.socket ? (': ' + environment.config.httpConfig.protocol + '://' + environment.config.httpConfig.socket) : '')"-->
|
|
||||||
<!-- :value="environment.id"/>-->
|
|
||||||
<!-- <el-button class="ms-scenario-button" size="mini" type="primary" @click="openEnvironmentConfig">-->
|
|
||||||
<!-- {{ $t('api_test.environment.environment_config') }}-->
|
|
||||||
<!-- </el-button>-->
|
|
||||||
<!-- <template v-slot:empty>-->
|
|
||||||
<!-- <div class="empty-environment">-->
|
|
||||||
<!-- <el-button class="ms-scenario-button" size="mini" type="primary" @click="openEnvironmentConfig">-->
|
|
||||||
<!-- {{ $t('api_test.environment.environment_config') }}-->
|
|
||||||
<!-- </el-button>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </template>-->
|
|
||||||
<!-- </el-select>-->
|
|
||||||
|
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="2">
|
<el-col :span="2">
|
||||||
<el-button :disabled="scenarioDefinition.length < 1" size="small" type="primary" @click="runDebug">{{$t('api_test.request.debug')}}</el-button>
|
<el-button :disabled="scenarioDefinition.length < 1" size="small" type="primary" @click="runDebug">{{$t('api_test.request.debug')}}</el-button>
|
||||||
|
@ -186,9 +169,6 @@
|
||||||
<!--场景导入 -->
|
<!--场景导入 -->
|
||||||
<scenario-relevance @save="addScenario" ref="scenarioRelevance"/>
|
<scenario-relevance @save="addScenario" ref="scenarioRelevance"/>
|
||||||
|
|
||||||
<api-scenario-env :project-ids="projectIds" :env-map="projectEnvMap"
|
|
||||||
ref="apiScenarioEnv" @setProjectEnvMap="setProjectEnvMap" :project-list="projectList"/>
|
|
||||||
|
|
||||||
<!-- 环境 -->
|
<!-- 环境 -->
|
||||||
<api-environment-config ref="environmentConfig" @close="environmentConfigClose"/>
|
<api-environment-config ref="environmentConfig" @close="environmentConfigClose"/>
|
||||||
|
|
||||||
|
@ -236,8 +216,7 @@
|
||||||
import MsComponentConfig from "./component/ComponentConfig";
|
import MsComponentConfig from "./component/ComponentConfig";
|
||||||
import {handleCtrlSEvent} from "../../../../../common/js/utils";
|
import {handleCtrlSEvent} from "../../../../../common/js/utils";
|
||||||
import {getProject} from "@/business/components/api/automation/scenario/event";
|
import {getProject} from "@/business/components/api/automation/scenario/event";
|
||||||
import ApiScenarioEnv from "@/business/components/api/automation/scenario/ApiScenarioEnv";
|
import EnvPopover from "@/business/components/api/automation/scenario/EnvPopover";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "EditApiScenario",
|
name: "EditApiScenario",
|
||||||
props: {
|
props: {
|
||||||
|
@ -245,7 +224,6 @@
|
||||||
currentScenario: {},
|
currentScenario: {},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
ApiScenarioEnv,
|
|
||||||
MsVariableList,
|
MsVariableList,
|
||||||
ScenarioRelevance,
|
ScenarioRelevance,
|
||||||
ScenarioApiRelevance,
|
ScenarioApiRelevance,
|
||||||
|
@ -255,6 +233,7 @@
|
||||||
MsApiCustomize,
|
MsApiCustomize,
|
||||||
ApiImport,
|
ApiImport,
|
||||||
MsComponentConfig,
|
MsComponentConfig,
|
||||||
|
EnvPopover
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -712,7 +691,7 @@
|
||||||
// this.$error(this.$t('api_test.environment.select_environment'));
|
// this.$error(this.$t('api_test.environment.select_environment'));
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
let sign = this.$refs.apiScenarioEnv.checkEnv();
|
let sign = this.$refs.envPopover.checkEnv();
|
||||||
if (!sign) {
|
if (!sign) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
<template>
|
||||||
|
<el-popover
|
||||||
|
v-model="visible"
|
||||||
|
placement="bottom"
|
||||||
|
width="400"
|
||||||
|
@show="showPopover"
|
||||||
|
trigger="click">
|
||||||
|
<env-select :project-ids="projectIds" :env-map="envMap" @close="visible = false"
|
||||||
|
ref="envSelect" @setProjectEnvMap="setProjectEnvMap" :project-list="projectList"/>
|
||||||
|
<el-button type="primary" slot="reference" size="mini" style="margin-top: 2px;">
|
||||||
|
环境配置<i class="el-icon-caret-bottom el-icon--right"></i>
|
||||||
|
</el-button>
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import EnvSelect from "@/business/components/api/automation/scenario/EnvSelect";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "EnvPopover",
|
||||||
|
components: {EnvSelect},
|
||||||
|
props: {
|
||||||
|
envMap: Map,
|
||||||
|
projectIds: Set,
|
||||||
|
projectList: Array,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showPopover() {
|
||||||
|
this.$refs.envSelect.open();
|
||||||
|
},
|
||||||
|
setProjectEnvMap(map) {
|
||||||
|
this.$emit("setProjectEnvMap", map);
|
||||||
|
},
|
||||||
|
checkEnv() {
|
||||||
|
return this.$refs.envSelect.checkEnv();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,149 @@
|
||||||
|
<template>
|
||||||
|
<div v-loading="result.loading">
|
||||||
|
<div v-for="pe in data" :key="pe.id" style="margin-left: 20px;">
|
||||||
|
<el-select v-model="pe['selectEnv']" placeholder="请选择环境" style="margin-top: 8px;width: 200px;" size="small">
|
||||||
|
<el-option v-for="(environment, index) in pe.envs" :key="index"
|
||||||
|
:label="environment.name + (environment.config.httpConfig.socket ? (': ' + environment.config.httpConfig.protocol + '://' + environment.config.httpConfig.socket) : '')"
|
||||||
|
:value="environment.id"/>
|
||||||
|
<el-button class="ms-scenario-button" size="mini" type="primary" @click="openEnvironmentConfig(pe.id)">
|
||||||
|
{{ $t('api_test.environment.environment_config') }}
|
||||||
|
</el-button>
|
||||||
|
<template v-slot:empty>
|
||||||
|
<div class="empty-environment">
|
||||||
|
<el-button class="ms-scenario-button" size="mini" type="primary" @click="openEnvironmentConfig(pe.id)">
|
||||||
|
{{ $t('api_test.environment.environment_config') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-select>
|
||||||
|
<span class="project-name" :title="getProjectName(pe.id)">
|
||||||
|
{{ getProjectName(pe.id) }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-button type="primary" @click="handleConfirm" size="small" class="env-confirm">确 定</el-button>
|
||||||
|
|
||||||
|
<!-- 环境配置 -->
|
||||||
|
<api-environment-config ref="environmentConfig" @close="environmentConfigClose"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {parseEnvironment} from "@/business/components/api/test/model/EnvironmentModel";
|
||||||
|
import ApiEnvironmentConfig from "@/business/components/api/definition/components/environment/ApiEnvironmentConfig";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "EnvironmentSelect",
|
||||||
|
components: {ApiEnvironmentConfig},
|
||||||
|
props: {
|
||||||
|
envMap: Map,
|
||||||
|
projectIds: Set,
|
||||||
|
projectList: Array
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
data: [],
|
||||||
|
result: {},
|
||||||
|
projects: [],
|
||||||
|
environments: [],
|
||||||
|
dialogVisible: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
init() {
|
||||||
|
this.projectIds.forEach(id => {
|
||||||
|
let item = {id: id, envs: [], selectEnv: ""};
|
||||||
|
this.data.push(item);
|
||||||
|
this.result = this.$get('/api/environment/list/' + id, res => {
|
||||||
|
let envs = res.data;
|
||||||
|
envs.forEach(environment => {
|
||||||
|
parseEnvironment(environment);
|
||||||
|
});
|
||||||
|
// 固定环境列表渲染顺序
|
||||||
|
let temp = this.data.find(dt => dt.id === id);
|
||||||
|
temp.envs = envs;
|
||||||
|
temp.selectEnv = this.envMap.get(id);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
open() {
|
||||||
|
this.data = [];
|
||||||
|
if (this.projectIds.size > 0) {
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getProjectName(id) {
|
||||||
|
const project = this.projectList.find(p => p.id === id);
|
||||||
|
return project ? project.name : "";
|
||||||
|
},
|
||||||
|
openEnvironmentConfig(projectId) {
|
||||||
|
if (!projectId) {
|
||||||
|
this.$error(this.$t('api_test.select_project'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$refs.environmentConfig.open(projectId);
|
||||||
|
},
|
||||||
|
handleConfirm() {
|
||||||
|
let map = new Map();
|
||||||
|
let sign = true;
|
||||||
|
this.data.forEach(dt => {
|
||||||
|
if (!dt.selectEnv) {
|
||||||
|
sign = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
map.set(dt.id, dt.selectEnv);
|
||||||
|
})
|
||||||
|
if (!sign) {
|
||||||
|
this.$warning("请为每个项目选择一个运行环境!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$emit('setProjectEnvMap', map);
|
||||||
|
this.$emit('close');
|
||||||
|
},
|
||||||
|
checkEnv() {
|
||||||
|
let sign = true;
|
||||||
|
if (this.data.length > 0) {
|
||||||
|
this.data.forEach(dt => {
|
||||||
|
if (!dt.selectEnv) {
|
||||||
|
sign = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
sign = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sign) {
|
||||||
|
this.$warning("请为每个项目选择一个运行环境!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
environmentConfigClose() {
|
||||||
|
// todo 关闭处理
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.ms-scenario-button {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.env-confirm {
|
||||||
|
margin-left: 20px;
|
||||||
|
width: 360px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.project-name {
|
||||||
|
display:inline-block;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 150px;
|
||||||
|
margin-left: 8px;
|
||||||
|
vertical-align:middle;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -10,6 +10,8 @@
|
||||||
<span class="operate-button">
|
<span class="operate-button">
|
||||||
<ms-table-button :is-tester-permission="isTesterPermission" v-if="showCreate" icon="el-icon-circle-plus-outline"
|
<ms-table-button :is-tester-permission="isTesterPermission" v-if="showCreate" icon="el-icon-circle-plus-outline"
|
||||||
:content="createTip" @click="create"/>
|
:content="createTip" @click="create"/>
|
||||||
|
<ms-table-button :is-tester-permission="true" icon="el-icon-download" v-if="showImport"
|
||||||
|
:content="importTip" @click="importData"/>
|
||||||
<ms-table-button :is-tester-permission="isTesterPermission" v-if="showRun" icon="el-icon-video-play"
|
<ms-table-button :is-tester-permission="isTesterPermission" v-if="showRun" icon="el-icon-video-play"
|
||||||
type="primary"
|
type="primary"
|
||||||
:content="runTip" @click="runTest"/>
|
:content="runTip" @click="runTest"/>
|
||||||
|
@ -47,6 +49,10 @@
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
|
showImport: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
showRun: {
|
showRun: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
@ -60,6 +66,12 @@
|
||||||
return this.$t('commons.create');
|
return this.$t('commons.create');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
importTip: {
|
||||||
|
type: String,
|
||||||
|
default() {
|
||||||
|
return this.$t('commons.import');
|
||||||
|
}
|
||||||
|
},
|
||||||
runTip: {
|
runTip: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|
||||||
|
@ -84,6 +96,9 @@
|
||||||
create() {
|
create() {
|
||||||
this.$emit('create');
|
this.$emit('create');
|
||||||
},
|
},
|
||||||
|
importData() {
|
||||||
|
this.$emit('import');
|
||||||
|
},
|
||||||
runTest() {
|
runTest() {
|
||||||
this.$emit('runTest')
|
this.$emit('runTest')
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
|
|
||||||
<el-card class="table-card">
|
<el-card class="table-card">
|
||||||
<template v-slot:header>
|
<template v-slot:header>
|
||||||
<ms-table-header :condition.sync="condition" @search="search" @create="create"
|
<ms-table-header :condition.sync="condition" @search="search" @create="create" @import="importUserDialogOpen"
|
||||||
:create-tip="$t('user.create')" :title="$t('commons.user')"/>
|
:create-tip="$t('user.create')" :show-import="true" :import-tip="$t('commons.import_user')" :title="$t('commons.user')"/>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table border class="adjust-table" :data="tableData" style="width: 100%">
|
<el-table border class="adjust-table" :data="tableData" style="width: 100%">
|
||||||
|
@ -323,7 +324,7 @@
|
||||||
@confirm="editUserPassword('editPasswordForm')"/>
|
@confirm="editUserPassword('editPasswordForm')"/>
|
||||||
</span>
|
</span>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<user-import ref="userImportDialog" @refreshAll="search"></user-import>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -339,6 +340,7 @@ import MsRolesTag from "../../common/components/MsRolesTag";
|
||||||
import {ROLE_ADMIN} from "@/common/js/constants";
|
import {ROLE_ADMIN} from "@/common/js/constants";
|
||||||
import {getCurrentUser} from "../../../../common/js/utils";
|
import {getCurrentUser} from "../../../../common/js/utils";
|
||||||
import {PHONE_REGEX} from "@/common/js/regex";
|
import {PHONE_REGEX} from "@/common/js/regex";
|
||||||
|
import UserImport from "@/business/components/settings/system/components/UserImport";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "MsUser",
|
name: "MsUser",
|
||||||
|
@ -349,7 +351,8 @@ export default {
|
||||||
MsTableOperator,
|
MsTableOperator,
|
||||||
MsDialogFooter,
|
MsDialogFooter,
|
||||||
MsTableOperatorButton,
|
MsTableOperatorButton,
|
||||||
MsRolesTag
|
MsRolesTag,
|
||||||
|
UserImport
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -579,6 +582,9 @@ export default {
|
||||||
this.userRole = response.data;
|
this.userRole = response.data;
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
importUserDialogOpen(){
|
||||||
|
this.$refs.userImportDialog.open();
|
||||||
|
},
|
||||||
addRole(validForm) {
|
addRole(validForm) {
|
||||||
this.$refs[validForm].validate(valid => {
|
this.$refs[validForm].validate(valid => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
<template>
|
||||||
|
<el-dialog class="user-import" :title="$t('commons.import_user')" :visible.sync="dialogVisible"
|
||||||
|
@close="close">
|
||||||
|
<el-row>
|
||||||
|
<el-link type="primary" class="download-template"
|
||||||
|
@click="downloadTemplate"
|
||||||
|
>{{$t('test_track.case.import.download_template')}}
|
||||||
|
</el-link>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<el-upload
|
||||||
|
style="width: 100%"
|
||||||
|
v-loading="result.loading"
|
||||||
|
:element-loading-text="$t('test_track.case.import.importing')"
|
||||||
|
element-loading-spinner="el-icon-loading"
|
||||||
|
class="upload-demo"
|
||||||
|
multiple
|
||||||
|
drag
|
||||||
|
:limit="1"
|
||||||
|
action=""
|
||||||
|
:on-exceed="handleExceed"
|
||||||
|
:beforeUpload="uploadValidate"
|
||||||
|
:on-error="handleError"
|
||||||
|
:show-file-list="false"
|
||||||
|
:http-request="upload"
|
||||||
|
:file-list="fileList">
|
||||||
|
<i class="el-icon-upload"></i>
|
||||||
|
<div class="el-upload__text" v-html="$t('load_test.upload_tips')"></div>
|
||||||
|
<div class="el-upload__tip" slot="tip">{{ $t('api_test.api_import.file_size_limit') }}</div>
|
||||||
|
</el-upload>
|
||||||
|
</el-row>
|
||||||
|
<el-row>
|
||||||
|
<ul>
|
||||||
|
<li v-for="errFile in errList" :key="errFile.rowNum">
|
||||||
|
{{errFile.errMsg}}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</el-row>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ElUploadList from "element-ui/packages/upload/src/upload-list";
|
||||||
|
import MsTableButton from '../../../../components/common/components/MsTableButton';
|
||||||
|
import {getCurrentProjectID, listenGoBack, removeGoBackListener} from "../../../../../common/js/utils";
|
||||||
|
import {TokenKey} from '../../../../../common/js/constants';
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "UserImport",
|
||||||
|
components: {ElUploadList, MsTableButton},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
result: {},
|
||||||
|
activeName: 'excelImport',
|
||||||
|
dialogVisible: false,
|
||||||
|
fileList: [],
|
||||||
|
errList: [],
|
||||||
|
isLoading: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleExceed(files, fileList) {
|
||||||
|
this.$warning(this.$t('test_track.case.import.upload_limit_count'));
|
||||||
|
},
|
||||||
|
uploadValidate(file) {
|
||||||
|
let suffix = file.name.substring(file.name.lastIndexOf('.') + 1);
|
||||||
|
if (suffix != 'xls' && suffix != 'xlsx') {
|
||||||
|
this.$warning(this.$t('test_track.case.import.upload_limit_format'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (file.size / 1024 / 1024 > 20) {
|
||||||
|
this.$warning(this.$t('test_track.case.import.upload_limit_size'));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.isLoading = true;
|
||||||
|
this.errList = [];
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
handleError(err, file, fileList) {
|
||||||
|
this.isLoading = false;
|
||||||
|
this.$error(err.message);
|
||||||
|
},
|
||||||
|
open() {
|
||||||
|
listenGoBack(this.close);
|
||||||
|
this.projectId = getCurrentProjectID();
|
||||||
|
this.dialogVisible = true;
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
removeGoBackListener(this.close);
|
||||||
|
this.dialogVisible = false;
|
||||||
|
this.fileList = [];
|
||||||
|
this.errList = [];
|
||||||
|
},
|
||||||
|
downloadTemplate() {
|
||||||
|
this.$fileDownload('/user/export/template');
|
||||||
|
},
|
||||||
|
upload(file) {
|
||||||
|
this.isLoading = false;
|
||||||
|
this.fileList.push(file.file);
|
||||||
|
let user = JSON.parse(localStorage.getItem(TokenKey));
|
||||||
|
|
||||||
|
this.result = this.$fileUpload('/user/import/' + user.id, file.file, null, {}, response => {
|
||||||
|
let res = response.data;
|
||||||
|
if (res.success) {
|
||||||
|
this.$success(this.$t('commons.import_success'));
|
||||||
|
this.dialogVisible = false;
|
||||||
|
this.$emit("refreshAll");
|
||||||
|
} else {
|
||||||
|
this.errList = res.errList;
|
||||||
|
}
|
||||||
|
this.fileList = [];
|
||||||
|
}, erro => {
|
||||||
|
this.fileList = [];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.download-template {
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-import >>> .el-dialog {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
|
@ -83,13 +83,13 @@
|
||||||
<el-progress :percentage="scope.row.testRate"></el-progress>
|
<el-progress :percentage="scope.row.testRate"></el-progress>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-colum
|
<el-table-column
|
||||||
v-if="item.id == 'projectName'"
|
v-if="item.id == 'projectName'"
|
||||||
prop="projectName"
|
prop="projectName"
|
||||||
:label="$t('test_track.plan.plan_project')"
|
:label="$t('test_track.plan.plan_project')"
|
||||||
show-overflow-tooltip
|
show-overflow-tooltip
|
||||||
:key="index">
|
:key="index">
|
||||||
</el-table-colum>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column
|
||||||
v-if="item.id == 'plannedStartTime'"
|
v-if="item.id == 'plannedStartTime'"
|
||||||
sortable
|
sortable
|
||||||
|
|
|
@ -85,6 +85,9 @@
|
||||||
<el-button type="primary" @click="saveReview">
|
<el-button type="primary" @click="saveReview">
|
||||||
{{ $t('test_track.confirm') }}
|
{{ $t('test_track.confirm') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button type="primary" @click="reviewInfo('form')">
|
||||||
|
{{ $t('test_track.planning_execution') }}
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -134,6 +137,34 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
reviewInfo(form) {
|
||||||
|
this.$refs['reviewForm'].validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
let param = {};
|
||||||
|
Object.assign(param, this.form);
|
||||||
|
param.name = param.name.trim();
|
||||||
|
if (this.form.tags instanceof Array) {
|
||||||
|
this.form.tags = JSON.stringify(this.form.tags);
|
||||||
|
}
|
||||||
|
param.tags = this.form.tags;
|
||||||
|
if (param.name === '') {
|
||||||
|
this.$warning(this.$t('test_track.plan.input_plan_name'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.compareTime(new Date().getTime(), this.form.endTime)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.result = this.$post('/test/case/review/' + this.operationType, param, response => {
|
||||||
|
this.dialogFormVisible = false;
|
||||||
|
this.$router.push('/track/review/view/' + response.data);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
openCaseReviewEditDialog(caseReview) {
|
openCaseReviewEditDialog(caseReview) {
|
||||||
this.resetForm();
|
this.resetForm();
|
||||||
this.setReviewerOptions();
|
this.setReviewerOptions();
|
||||||
|
|
|
@ -2,8 +2,11 @@ export default {
|
||||||
commons: {
|
commons: {
|
||||||
cover: 'Cover',
|
cover: 'Cover',
|
||||||
not_cover: 'Not Cover',
|
not_cover: 'Not Cover',
|
||||||
|
import: 'Import',
|
||||||
|
import_success: 'Import success',
|
||||||
import_mode: 'Import mode',
|
import_mode: 'Import mode',
|
||||||
import_module: 'Import module',
|
import_module: 'Import module',
|
||||||
|
import_user: 'Import user',
|
||||||
please_fill_in_the_template: 'Please fill in the template',
|
please_fill_in_the_template: 'Please fill in the template',
|
||||||
cut_back_old_version: 'Cut back to old version',
|
cut_back_old_version: 'Cut back to old version',
|
||||||
cut_back_new_version: 'Switch back to new version',
|
cut_back_new_version: 'Switch back to new version',
|
||||||
|
@ -1039,6 +1042,7 @@ export default {
|
||||||
test_track: "Track",
|
test_track: "Track",
|
||||||
confirm: "Confirm",
|
confirm: "Confirm",
|
||||||
cancel: "Cancel",
|
cancel: "Cancel",
|
||||||
|
planning_execution: "Planning&Execution",
|
||||||
project: "Project",
|
project: "Project",
|
||||||
save: "Save",
|
save: "Save",
|
||||||
return: "Return",
|
return: "Return",
|
||||||
|
|
|
@ -2,8 +2,11 @@ export default {
|
||||||
commons: {
|
commons: {
|
||||||
cover: '覆盖',
|
cover: '覆盖',
|
||||||
not_cover: '不覆盖',
|
not_cover: '不覆盖',
|
||||||
|
import: '导入',
|
||||||
|
import_success: '导入成功',
|
||||||
import_mode: '导入模式',
|
import_mode: '导入模式',
|
||||||
import_module: '导入模块',
|
import_module: '导入模块',
|
||||||
|
import_user: '导入用户',
|
||||||
please_fill_in_the_template: '请填写模版内容',
|
please_fill_in_the_template: '请填写模版内容',
|
||||||
cut_back_old_version: '切回旧版',
|
cut_back_old_version: '切回旧版',
|
||||||
cut_back_new_version: '切回新版',
|
cut_back_new_version: '切回新版',
|
||||||
|
@ -1044,6 +1047,7 @@ export default {
|
||||||
},
|
},
|
||||||
test_track: {
|
test_track: {
|
||||||
test_track: "测试跟踪",
|
test_track: "测试跟踪",
|
||||||
|
planning_execution: "规划&执行",
|
||||||
confirm: "确 定",
|
confirm: "确 定",
|
||||||
cancel: "取 消",
|
cancel: "取 消",
|
||||||
project: "项目",
|
project: "项目",
|
||||||
|
|
|
@ -2,8 +2,11 @@ export default {
|
||||||
commons: {
|
commons: {
|
||||||
cover: '覆蓋',
|
cover: '覆蓋',
|
||||||
not_cover: '不覆蓋',
|
not_cover: '不覆蓋',
|
||||||
|
import: '導入',
|
||||||
|
import_success: '導入成功',
|
||||||
import_mode: '導入模式',
|
import_mode: '導入模式',
|
||||||
import_module: '導入模塊',
|
import_module: '導入模塊',
|
||||||
|
import_user: '導入用戶',
|
||||||
please_fill_in_the_template: '請填寫模版內容',
|
please_fill_in_the_template: '請填寫模版內容',
|
||||||
cut_back_old_version: '切回舊版',
|
cut_back_old_version: '切回舊版',
|
||||||
cut_back_new_version: '切回新版',
|
cut_back_new_version: '切回新版',
|
||||||
|
@ -1041,6 +1044,7 @@ export default {
|
||||||
test_track: "測試跟蹤",
|
test_track: "測試跟蹤",
|
||||||
confirm: "確 定",
|
confirm: "確 定",
|
||||||
cancel: "取 消",
|
cancel: "取 消",
|
||||||
|
planning_execution: "規劃&執行",
|
||||||
project: "項目",
|
project: "項目",
|
||||||
save: "保 存",
|
save: "保 存",
|
||||||
return: "返 回",
|
return: "返 回",
|
||||||
|
|
|
@ -10,7 +10,7 @@ module.exports = {
|
||||||
port: 8080,
|
port: 8080,
|
||||||
proxy: {
|
proxy: {
|
||||||
//1.8需求:增加分享功能,不登陆即可看到文档页面。所以代理设置增加了(?!/document)文档页面的相关信息
|
//1.8需求:增加分享功能,不登陆即可看到文档页面。所以代理设置增加了(?!/document)文档页面的相关信息
|
||||||
// ['^((?!/login)']: {
|
// ['^(?!/login)']: {
|
||||||
['^((?!/login)(?!/document))']: {
|
['^((?!/login)(?!/document))']: {
|
||||||
target: 'http://localhost:8081',
|
target: 'http://localhost:8081',
|
||||||
ws: true,
|
ws: true,
|
||||||
|
|
Loading…
Reference in New Issue