Merge branch 'master' of github.com:fit2cloudrd/metersphere-server into master

This commit is contained in:
Captain.B 2020-09-14 16:17:41 +08:00
commit 4f4cef3feb
25 changed files with 664 additions and 144 deletions

View File

@ -312,7 +312,7 @@
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
<include>**/*</include>
</includes>
<filtering>false</filtering>
</resource>

View File

@ -14,6 +14,7 @@ import io.metersphere.track.dto.TestPlanDTOWithMetric;
import io.metersphere.track.request.testcase.PlanCaseRelevanceRequest;
import io.metersphere.track.request.testcase.QueryTestPlanRequest;
import io.metersphere.track.request.testplan.AddTestPlanRequest;
import io.metersphere.track.request.testplancase.TestCaseRelevanceRequest;
import io.metersphere.track.service.TestPlanProjectService;
import io.metersphere.track.service.TestPlanService;
import org.apache.shiro.authz.annotation.Logical;
@ -111,8 +112,18 @@ public class TestPlanController {
return testPlanService.getProjectNameByPlanId(planId);
}
@GetMapping("/project/{planId}")
public List<Project> getProjectByPlanId(@PathVariable String planId) {
return testPlanProjectService.getProjectByPlanId(planId);
@PostMapping("/project")
public List<Project> getProjectByPlanId(@RequestBody TestCaseRelevanceRequest request) {
List<String> projectIds = testPlanProjectService.getProjectIdsByPlanId(request.getPlanId());
request.setProjectIds(projectIds);
return testPlanProjectService.getProjectByPlanId(request);
}
@PostMapping("/project/{goPage}/{pageSize}")
public Pager<List<Project>> getProjectByPlanId(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody TestCaseRelevanceRequest request) {
List<String> projectIds = testPlanProjectService.getProjectIdsByPlanId(request.getPlanId());
request.setProjectIds(projectIds);
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, testPlanProjectService.getProjectByPlanId(request));
}
}

View File

@ -0,0 +1,14 @@
package io.metersphere.track.request.testplancase;
import lombok.Getter;
import lombok.Setter;
import java.util.List;
@Getter
@Setter
public class TestCaseRelevanceRequest {
private String planId;
private String name;
private List<String> projectIds;
}

View File

@ -6,26 +6,25 @@ import io.metersphere.base.domain.TestPlanProject;
import io.metersphere.base.domain.TestPlanProjectExample;
import io.metersphere.base.mapper.ProjectMapper;
import io.metersphere.base.mapper.TestPlanProjectMapper;
import org.python.antlr.ast.Str;
import io.metersphere.track.request.testplancase.TestCaseRelevanceRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class TestPlanProjectService {
@Resource
TestPlanProjectMapper testPlanProjectMapper;
@Resource
ProjectMapper projectMapper;
public List<String> getProjectIdsByPlanId(String planId) {
TestPlanProjectExample example = new TestPlanProjectExample();
example.createCriteria().andTestPlanIdEqualTo(planId);
@ -41,12 +40,14 @@ public class TestPlanProjectService {
return projectIds;
}
public List<Project> getProjectByPlanId(String planId) {
List<String> projectIds = getProjectIdsByPlanId(planId);
public List<Project> getProjectByPlanId(TestCaseRelevanceRequest request) {
ProjectExample projectExample = new ProjectExample();
projectExample.createCriteria().andIdIn(projectIds);
List<Project> projects = projectMapper.selectByExample(projectExample);
return Optional.ofNullable(projects).orElse(new ArrayList<>());
ProjectExample.Criteria criteria = projectExample.createCriteria();
criteria.andIdIn(request.getProjectIds());
if (StringUtils.isNotBlank(request.getName())) {
criteria.andNameLike(StringUtils.wrapIfMissing(request.getName(), "%"));
}
return projectMapper.selectByExample(projectExample);
}
public void deleteTestPlanProjectByPlanId(String planId) {

View File

@ -0,0 +1,13 @@
CREATE TABLE `license` (
`id` varchar(50) NOT NULL COMMENT 'ID',
`create_time` bigint(13) NOT NULL COMMENT 'Create timestamp',
`update_time` bigint(13) NOT NULL COMMENT 'Update timestamp',
`corporation` varchar(500) NOT NULL COMMENT 'corporation ',
`expired` varchar(255) NOT NULL COMMENT 'expired ',
`product` varchar(500) DEFAULT NULL COMMENT 'product name',
`edition` varchar(255) COMMENT 'edition ',
`license_version` varchar(255) NOT NULL COMMENT 'licenseVersion',
`license_count` INT COMMENT 'license_count',
`license_code` longtext DEFAULT NULL COMMENT 'license_code',
PRIMARY KEY (`id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

View File

@ -150,4 +150,6 @@ quota_performance_excess_organization=The number of performance tests exceeds th
quota_max_threads_excess_workspace=The maximum number of concurrent threads exceeds the workspace quota
quota_max_threads_excess_organization=The maximum number of concurrent threads exceeds the organization quota
quota_duration_excess_workspace=The stress test duration exceeds the work space quota
quota_duration_excess_organization=The stress test duration exceeds the organization quota
quota_duration_excess_organization=The stress test duration exceeds the organization quota
license_valid_license_error=valid license error
license_valid_license_code=The authorization code already exists

View File

@ -151,6 +151,7 @@ quota_max_threads_excess_workspace=最大并发数超过工作空间限额
quota_max_threads_excess_organization=最大并发数超过组织限额
quota_duration_excess_workspace=压测时长超过工作空间限额
quota_duration_excess_organization=压测时长超过组织限额
license_valid_license_error=授权验证失败
license_valid_license_code=授权码已经存在

View File

@ -150,4 +150,7 @@ quota_performance_excess_organization=性能測試數量超過組織限額
quota_max_threads_excess_workspace=最大並發數超過工作空間限額
quota_max_threads_excess_organization=最大並發數超過組織限額
quota_duration_excess_workspace=壓測時長超過工作空間限額
quota_duration_excess_organization=壓測時長超過組織限額
quota_duration_excess_organization=壓測時長超過組織限額
license_valid_license_error=授權驗證失敗
license_valid_license_code=授權碼已經存在

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -37,6 +37,9 @@
:environment="scenario.environment"
:description="$t('api_test.scenario.kv_description')"/>
</el-tab-pane>
<el-tab-pane :label="'数据库配置'" name="database">
<ms-database-config :configs="scenario.databaseConfigs"/>
</el-tab-pane>
<el-tab-pane :label="$t('api_test.scenario.dubbo')" name="dubbo">
<div class="dubbo-config-title">Config Center</div>
<ms-dubbo-config-center :config="scenario.dubboConfig.configCenter" :is-read-only="isReadOnly"/>
@ -62,10 +65,12 @@ import {REQUEST_HEADERS} from "@/common/js/constants";
import MsDubboRegistryCenter from "@/business/components/api/test/components/request/dubbo/RegistryCenter";
import MsDubboConfigCenter from "@/business/components/api/test/components/request/dubbo/ConfigCenter";
import MsDubboConsumerService from "@/business/components/api/test/components/request/dubbo/ConsumerAndService";
import MsDatabaseConfig from "./request/database/DatabaseConfig";
export default {
name: "MsApiScenarioForm",
components: {
MsDatabaseConfig,
MsDubboConsumerService,
MsDubboConfigCenter, MsDubboRegistryCenter, ApiEnvironmentConfig, MsApiScenarioVariables, MsApiKeyValue
},

View File

@ -0,0 +1,59 @@
<template>
<div>
<ms-database-from :config="currentConfig" @save="addConfig" ref="databaseFrom"/>
<ms-database-config-list v-if="configs.length > 0" :table-data="configs"/>
</div>
</template>
<script>
import MsDatabaseConfigList from "./DatabaseConfigList";
import {DatabaseConfig} from "../../../model/ScenarioModel";
import MsDatabaseFrom from "./DatabaseFrom";
import {getUUID} from "../../../../../../../common/js/utils";
export default {
name: "MsDatabaseConfig",
components: {MsDatabaseFrom, MsDatabaseConfigList},
props: {
configs: Array,
isReadOnly: {
type: Boolean,
default: false
},
},
data() {
return {
drivers: DatabaseConfig.DRIVER_CLASS,
currentConfig: new DatabaseConfig()
}
},
methods: {
addConfig(config) {
for (let item of this.configs) {
if (item.name === config.name) {
this.$warning("名称重复");
return;
}
}
config.id = getUUID();
this.configs.push(config);
this.currentConfig = new DatabaseConfig();
}
}
}
</script>
<style scoped>
.addButton {
float: right;
}
.database-from {
padding: 10px;
border: #DCDFE6 solid 1px;
margin: 5px 0;
border-radius: 5px;
}
</style>

View File

@ -0,0 +1,58 @@
<template>
<el-dialog :title="'数据库配置'" :visible.sync="visible">
<ms-database-from :config="config" @save="editConfig"/>
</el-dialog>
</template>
<script>
import MsDatabaseConfigList from "./DatabaseConfigList";
import MsDatabaseFrom from "./DatabaseFrom";
import {DatabaseConfig} from "../../../model/ScenarioModel";
export default {
name: "MsDatabaseConfigDialog",
components: {MsDatabaseFrom, MsDatabaseConfigList},
props: {
configs: Array,
isReadOnly: {
type: Boolean,
default: false
},
},
data() {
return {
visible: false,
config: new DatabaseConfig(),
}
},
methods: {
open(config) {
this.visible = true;
Object.assign(this.config, config);
},
editConfig(config) {
let currentConfig = undefined;
for (let item of this.configs) {
if (item.name === config.name && item.id != config.id) {
this.$warning("名称重复");
return;
}
if (item.id === config.id) {
currentConfig = item;
}
}
if (currentConfig) {
Object.assign(currentConfig, config)
} else {
//copy
this.configs.push(config);
}
this.visible = false;
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,92 @@
<template>
<ms-main-container>
<el-table border :data="tableData" class="adjust-table table-content"
@row-click="handleView">
<el-table-column prop="name" :label="'连接池名称'" show-overflow-tooltip/>
<el-table-column prop="driver" :label="'数据库驱动'" show-overflow-tooltip/>
<el-table-column prop="dbUrl" :label="'数据库连接URL'" show-overflow-tooltip/>
<el-table-column prop="username" :label="'用户名'" show-overflow-tooltip/>
<el-table-column prop="poolMax" :label="'最大连接数'" show-overflow-tooltip/>
<el-table-column prop="timeout" :label="'最大等待时间'" show-overflow-tooltip/>
<el-table-column
:label="$t('commons.operating')" min-width="100">
<template v-slot:default="scope">
<ms-table-operator :is-tester-permission="true" @editClick="handleEdit(scope.row)"
@deleteClick="handleDelete(scope.$index)">
<template v-slot:middle>
<ms-table-operator-button :is-tester-permission="true" :tip="$t('commons.copy')"
icon="el-icon-document-copy"
type="success" @exec="handleCopy(scope.row)"/>
</template>
</ms-table-operator>
</template>
</el-table-column>
</el-table>
<ms-database-config-dialog :configs="tableData" ref="databaseConfigEdit"/>
</ms-main-container>
</template>
<script>
import {DatabaseConfig} from "../../../model/ScenarioModel";
import MsMainContainer from "../../../../../common/components/MsMainContainer";
import MsTableOperator from "../../../../../common/components/MsTableOperator";
import MsTableOperatorButton from "../../../../../common/components/MsTableOperatorButton";
import MsDatabaseConfigDialog from "./DatabaseConfigDialog";
import {getUUID} from "../../../../../../../common/js/utils";
export default {
name: "MsDatabaseConfigList",
components: {MsDatabaseConfigDialog, MsTableOperatorButton, MsTableOperator, MsMainContainer},
props: {
tableData: Array,
isReadOnly: {
type: Boolean,
default: false
}
},
data() {
return {
drivers: DatabaseConfig.DRIVER_CLASS,
result: {},
}
},
methods: {
handleView() {
},
handleEdit(config) {
this.$refs.databaseConfigEdit.open(config);
},
handleDelete(index) {
this.tableData.splice(index, 1);
},
handleCopy(config) {
let copy = {};
Object.assign(copy, config);
copy.id = getUUID();
this.$refs.databaseConfigEdit.open(copy);
}
}
}
</script>
<style scoped>
.addButton {
float: right;
}
.database-from {
padding: 10px;
border: #DCDFE6 solid 1px;
margin: 5px 0;
border-radius: 5px;
}
</style>

View File

@ -0,0 +1,121 @@
<template>
<div>
<el-form :model="config" :rules="rules" label-width="150px" size="small" :disabled="isReadOnly" class="database-from" ref="databaseFrom">
<el-form-item :label="'连接池名称'" prop="name">
<el-input v-model="config.name" maxlength="300" show-word-limit
:placeholder="$t('commons.input_content')"/>
</el-form-item>
<el-form-item :label="'数据库连接URL'" prop="dbUrl">
<el-input v-model="config.dbUrl" maxlength="300" show-word-limit
:placeholder="$t('commons.input_content')"/>
</el-form-item>
<el-form-item :label="'数据库驱动'" prop="driver">
<el-select v-model="config.driver" class="select-100" clearable>
<el-option v-for="p in drivers" :key="p" :label="p" :value="p"/>
</el-select>
</el-form-item>
<el-form-item :label="'用户名'" prop="username">
<el-input v-model="config.username" maxlength="300" show-word-limit
:placeholder="$t('commons.input_content')"/>
</el-form-item>
<el-form-item :label="'密码'" prop="password">
<el-input v-model="config.password" maxlength="300" show-word-limit
:placeholder="$t('commons.input_content')"/>
</el-form-item>
<el-form-item :label="'最大连接数'" prop="poolMax">
<el-input-number size="small" :disabled="isReadOnly" v-model="config.poolMax" :placeholder="$t('commons.millisecond')" :max="1000*10000000" :min="0"/>
</el-form-item>
<el-form-item :label="'最大等待时间(ms)'" prop="timeout">
<el-input-number size="small" :disabled="isReadOnly" v-model="config.timeout" :placeholder="$t('commons.millisecond')" :max="1000*10000000" :min="0"/>
</el-form-item>
<el-form-item>
<el-button type="primary" size="small" class="addButton" @click="save">添加</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import {DatabaseConfig} from "../../../model/ScenarioModel";
export default {
name: "MsDatabaseFrom",
components: {},
props: {
isReadOnly: {
type: Boolean,
default: false
},
config: {
type: Object,
default() {
return new DatabaseConfig();
}
},
},
data() {
return {
drivers: DatabaseConfig.DRIVER_CLASS,
// config: new DatabaseConfig(),
rules: {
name: [
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
{max: 300, message: this.$t('commons.input_limit', [0, 300]), trigger: 'blur'}
],
driver: [
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
],
password: [
{max: 200, message: this.$t('commons.input_limit', [0, 200]), trigger: 'blur'}
],
dbUrl: [
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
{max: 500, message: this.$t('commons.input_limit', [0, 500]), trigger: 'blur'}
],
username: [
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
{max: 200, message: this.$t('commons.input_limit', [0, 200]), trigger: 'blur'}
]
}
}
},
methods: {
save() {
this.$refs['databaseFrom'].validate((valid) => {
if (valid) {
this.$emit('save', this.config);
// this.config = new DatabaseConfig();
} else {
return false;
}
});
}
}
}
</script>
<style scoped>
.addButton {
float: right;
}
.database-from {
padding: 10px;
border: #DCDFE6 solid 1px;
margin: 5px 0;
border-radius: 5px;
}
</style>

View File

@ -211,14 +211,16 @@ export class Scenario extends BaseConfig {
this.environment = undefined;
this.enableCookieShare = false;
this.enable = true;
this.databaseConfigs = undefined;
this.set(options);
this.sets({variables: KeyValue, headers: KeyValue, requests: RequestFactory}, options);
this.sets({variables: KeyValue, headers: KeyValue, requests: RequestFactory, databaseConfigs: DatabaseConfig}, options);
}
initOptions(options = {}) {
options.id = options.id || uuid();
options.requests = options.requests || [new RequestFactory()];
options.databaseConfigs = options.databaseConfigs || [];
options.dubboConfig = new DubboConfig(options.dubboConfig);
return options;
}
@ -479,6 +481,51 @@ export class ConfigCenter extends BaseConfig {
}
}
export class DatabaseConfig extends BaseConfig {
static DRIVER_CLASS = ["com.mysql.jdbc.Driver"];
constructor(options) {
super();
this.id = undefined;
this.name = undefined;
this.poolMax = undefined;
this.timeout = undefined;
this.driver = undefined;
this.dbUrl = undefined;
this.username = undefined;
this.password = undefined;
this.set(options);
}
initOptions(options = {}) {
// options.id = options.id || uuid();
return options;
}
// <JDBCDataSource guiclass="TestBeanGUI" testclass="JDBCDataSource" testname="JDBC Connection Configurationqqq" enabled="true">
// <boolProp name="autocommit">true</boolProp>
// <stringProp name="checkQuery"></stringProp>
// <stringProp name="connectionAge">5000</stringProp>
// <stringProp name="connectionProperties"></stringProp>
// <stringProp name="dataSource">test</stringProp>
// <stringProp name="dbUrl">jdbc:mysql://localhost:3306/metersphere?autoReconnect=false&amp;useUnicode=true&amp;characterEncoding=UTF-8&amp;characterSetResults=UTF-8&amp;zeroDateTimeBehavior=convertToNull&amp;allowMultiQueries=true</stringProp>
// <stringProp name="driver">com.mysql.jdbc.Driver</stringProp>
// <stringProp name="initQuery"></stringProp>
// <boolProp name="keepAlive">true</boolProp>
// <stringProp name="password">root</stringProp>
// <stringProp name="poolMax">10</stringProp>
// <boolProp name="preinit">false</boolProp>
// <stringProp name="timeout">10000</stringProp>
// <stringProp name="transactionIsolation">DEFAULT</stringProp>
// <stringProp name="trimInterval">60000</stringProp>
// <stringProp name="username">root</stringProp>
// </JDBCDataSource>
isValid() {
return !!this.name || !!this.poolMax || !!this.timeout || !!this.driver || !!this.dbUrl || !!this.username || !!this.password;
}
}
export class RegistryCenter extends BaseConfig {
static PROTOCOLS = ["none", "zookeeper", "nacos", "apollo", "multicast", "redis", "simple"];

View File

@ -45,64 +45,99 @@
</template>
<script>
import {checkoutCurrentOrganization, checkoutCurrentWorkspace} from "@/common/js/utils";
import Setting from "@/business/components/settings/router";
import {checkoutCurrentOrganization, checkoutCurrentWorkspace} from "@/common/js/utils";
import Setting from "@/business/components/settings/router";
export default {
name: "MsSettingMenu",
data() {
let getMenus = function (group) {
let menus = [];
Setting.children.forEach(child => {
if (child.meta[group] === true) {
let menu = {index: Setting.path + "/" + child.path}
menu.title = child.meta.title;
menu.roles = child.meta.roles;
menus.push(menu);
}
})
return menus;
export default {
name: "MsSettingMenu",
data() {
let getMenus = function (group) {
let menus = [];
Setting.children.forEach(child => {
if (child.meta[group] === true) {
let menu = {index: Setting.path + "/" + child.path}
menu.title = child.meta.title;
menu.roles = child.meta.roles;
menu.valid = child.meta.valid;
menus.push(menu);
}
})
return menus;
}
return {
systems: getMenus('system'),
organizations: getMenus('organization'),
workspaces: getMenus('workspace'),
persons: getMenus('person'),
isCurrentOrganizationAdmin: false,
isCurrentWorkspaceUser: false,
}
},
mounted() {
this.valid();
this.isCurrentOrganizationAdmin = checkoutCurrentOrganization();
this.isCurrentWorkspaceUser = checkoutCurrentWorkspace();
},
methods: {
valid() {
let _this = this;
this.result = this.$get("/license/valid", response => {
let data = response.data;
if (data === undefined || data != true) {
this.systems.forEach(item => {
if (item.valid != undefined && item.valid === true) {
_this.systems.splice(this.systems.indexOf(item), 1);
}
})
this.organizations.forEach(item => {
if (item.valid != undefined && item.valid === true) {
_this.organizations.splice(this.organizations.indexOf(item), 1);
}
})
this.workspaces.forEach(item => {
if (item.valid != undefined && item.valid === true) {
_this.workspaces.splice(this.workspaces.indexOf(item), 1);
}
})
this.persons.forEach(item => {
if (item.valid != undefined && item.valid === true) {
_this.persons.splice(this.persons.indexOf(item), 1);
}
})
}
})
}
}
return {
systems: getMenus('system'),
organizations: getMenus('organization'),
workspaces: getMenus('workspace'),
persons: getMenus('person'),
isCurrentOrganizationAdmin: false,
isCurrentWorkspaceUser: false,
}
},
mounted() {
this.isCurrentOrganizationAdmin = checkoutCurrentOrganization();
this.isCurrentWorkspaceUser = checkoutCurrentWorkspace();
}
}
</script>
<style scoped>
.setting {
border-right: 0;
}
.setting {
border-right: 0;
}
.setting .setting-item {
height: 40px;
line-height: 40px;
}
.setting .setting-item {
height: 40px;
line-height: 40px;
}
.icon {
width: 24px;
margin-right: 10px;
}
.icon {
width: 24px;
margin-right: 10px;
}
.account {
color: #5a78f0;
}
.account {
color: #5a78f0;
}
.organization {
color: #b33a5b;
}
.organization {
color: #b33a5b;
}
.workspace {
color: #44b349;
}
.workspace {
color: #44b349;
}
</style>

View File

@ -32,7 +32,7 @@ export default {
component: () => import(/* webpackChunkName: "setting" */ '@/business/components/settings/system/SystemParameterSetting'),
meta: {system: true, title: 'commons.system_parameter_setting'}
},
...requireContext.keys().map(key => requireContext(key).system),
...requireContext.keys().map(key => requireContext(key).system),...requireContext.keys().map(key => requireContext(key).license),
{
path: 'organizationmember',
component: () => import(/* webpackChunkName: "setting" */ '@/business/components/settings/organization/OrganizationMember'),

View File

@ -1,86 +1,101 @@
<template>
<el-dialog v-loading="result.loading"
:visible.sync="dialogVisible"
:close-on-click-modal="false"
>
<el-table
:data="tableData"
highlight-current-row
@current-change="handleCurrentChange"
style="width: 100%">
<el-table-column prop="name" :label="$t('commons.name')" show-overflow-tooltip/>
<el-table-column prop="description" :label="$t('commons.description')" show-overflow-tooltip>
<template v-slot:default="scope">
{{ scope.row.description }}
</template>
</el-table-column>
<el-table-column
sortable
prop="createTime"
:label="$t('commons.create_time')"
show-overflow-tooltip>
<template v-slot:default="scope">
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<el-table-column
sortable
prop="updateTime"
:label="$t('commons.update_time')"
show-overflow-tooltip>
<template v-slot:default="scope">
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
</template>
</el-table-column>
</el-table>
<template v-slot:footer>
<div class="dialog-footer">
<ms-dialog-footer
@cancel="dialogVisible = false"
@confirm="submit()"/>
</div>
</template>
</el-dialog>
<el-dialog v-loading="result.loading"
:visible.sync="dialogVisible"
:close-on-click-modal="false"
class="ms-switch-project"
>
<ms-table-header :condition.sync="condition" @search="initData" title="" :show-create="false"/>
<el-table
:data="tableData"
highlight-current-row
@current-change="handleCurrentChange"
style="width: 100%">
<el-table-column prop="name" :label="$t('commons.name')" show-overflow-tooltip/>
<el-table-column prop="description" :label="$t('commons.description')" show-overflow-tooltip>
<template v-slot:default="scope">
{{ scope.row.description }}
</template>
</el-table-column>
<el-table-column
prop="createTime"
:label="$t('commons.create_time')"
show-overflow-tooltip>
<template v-slot:default="scope">
<span>{{ scope.row.createTime | timestampFormatDate }}</span>
</template>
</el-table-column>
<el-table-column
prop="updateTime"
:label="$t('commons.update_time')"
show-overflow-tooltip>
<template v-slot:default="scope">
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
</template>
</el-table-column>
</el-table>
<ms-table-pagination :change="initData" :current-page.sync="currentPage" :page-size.sync="pageSize"
:total="total"/>
<template v-slot:footer>
<div class="dialog-footer">
<ms-dialog-footer
@cancel="dialogVisible = false"
@confirm="submit()"/>
</div>
</template>
</el-dialog>
</template>
<script>
import MsDialogFooter from "../../../common/components/MsDialogFooter";
import MsDialogFooter from "../../../common/components/MsDialogFooter";
import MsTableHeader from "../../../common/components/MsTableHeader";
import MsTablePagination from "../../../common/pagination/TablePagination";
export default {
name: "SwitchProject",
components: {MsDialogFooter},
data() {
return {
tableData: [],
result: {},
dialogVisible: false,
projectId: ''
export default {
name: "SwitchProject",
components: {MsDialogFooter, MsTableHeader, MsTablePagination},
data() {
return {
tableData: [],
result: {},
dialogVisible: false,
projectId: '',
planId: '',
condition: {},
currentPage: 1,
pageSize: 5,
total: 0,
}
},
methods: {
open(planId) {
this.dialogVisible = true;
this.planId = planId;
this.initData();
},
initData() {
this.condition.planId = this.planId;
this.result = this.$post("/test/plan/project/" + this.currentPage + "/" + this.pageSize, this.condition, res => {
const data = res.data;
this.total = data.itemCount;
this.tableData = data.listObject;
})
},
handleCurrentChange(currentRow) {
// initData
if (currentRow) {
this.projectId = currentRow.id;
}
},
methods: {
open(planId) {
this.dialogVisible = true;
this.initData(planId);
},
initData(planId) {
this.result = this.$get("/test/plan/project/" + planId,res => {
this.tableData = res.data;
})
},
handleCurrentChange(currentRow) {
// initData
if (currentRow) {
this.projectId = currentRow.id;
}
},
submit() {
this.$emit('getProjectNode', this.projectId);
this.dialogVisible = false;
}
submit() {
this.$emit('getProjectNode', this.projectId);
this.dialogVisible = false;
}
}
}
</script>
<style scoped>
.ms-switch-project >>> .el-dialog__body {
padding: 0 15px !important;
}
</style>

View File

@ -192,8 +192,8 @@ export default {
this.total = data.itemCount;
this.tableData = data.listObject;
for (let i = 0; i < this.tableData.length; i++) {
let path = "/test/plan/project/" + this.tableData[i].id;
this.$get(path, res => {
let path = "/test/plan/project";
this.$post(path,{planId: this.tableData[i].id}, res => {
let arr = res.data;
let projectName = arr.map(data => data.name).join("、");
let projectIds = arr.map(data => data.id);

View File

@ -256,7 +256,7 @@
},
getProject() {
if (this.planId) {
this.$get("/test/plan/project/" + this.planId,res => {
this.$post("/test/plan/project/", {planId: this.planId},res => {
let data = res.data;
if (data) {
this.projects = data;

View File

@ -110,6 +110,7 @@ export default {
please_save: 'Please save first',
formatErr: 'Format Error',
id: 'ID',
cannot_be_null: 'not null ',
millisecond: 'ms',
please_upload: 'Please upload file',
reference_documentation: "Reference documentation",
@ -153,6 +154,18 @@ export default {
}
}
},
license:{
title: 'Authorization management',
corporation: 'corporation',
expired: 'expired',
product: 'product',
edition: 'edition',
licenseVersion: 'licenseVersion',
count: 'count',
valid_license: 'valid license',
show_license: 'show license',
valid_license_error: 'validate license error',
},
workspace: {
create: 'Create Workspace',
update: 'Update Workspace',
@ -639,6 +652,7 @@ export default {
upload_limit_count: "Only one file can be uploaded at a time",
upload_limit_format: "Upload files can only be XLS, XLSX format!",
upload_limit_size: "Upload file size cannot exceed 20MB!",
upload_limit_other_size: "Upload file size cannot exceed",
success: "Import success",
importing: "Importing...",
},

View File

@ -113,6 +113,7 @@ export default {
reference_documentation: "参考文档",
id: 'ID',
millisecond: '毫秒',
cannot_be_null: '不能为空',
date: {
select_date: '选择日期',
start_date: '开始日期',
@ -153,6 +154,18 @@ export default {
}
}
},
license:{
title: '授权管理',
corporation: '客户名称',
expired: '授权时间',
product: '产品名称',
edition: '产品版本',
licenseVersion: '授权版本',
count: '授权数量',
valid_license: '授权验证',
show_license: '查看授权',
valid_license_error: '授权验证失败',
},
workspace: {
create: '创建工作空间',
update: '修改工作空间',
@ -639,6 +652,7 @@ export default {
download_template: "下载模版",
click_upload: "点击上传",
upload_limit: "只能上传xls/xlsx文件且不超过20M",
upload_limit_other_size: "上传文件大小不能超过",
upload_limit_count: "一次只能上传一个文件",
upload_limit_format: "上传文件只能是 xls、xlsx格式!",
upload_limit_size: "上传文件大小不能超过 20MB!",

View File

@ -108,6 +108,7 @@ export default {
formatErr: '格式錯誤',
please_save: '請先保存',
id: 'ID',
cannot_be_null: '不能为空',
millisecond: '毫秒',
reference_documentation: "參考文檔",
please_upload: '請上傳文件',
@ -151,6 +152,19 @@ export default {
}
}
},
license:{
title: '授權管理',
corporation: '客戶名稱',
expired: '授權時間',
product: '產品名稱',
edition: '產品版本',
licenseVersion: '授權版本',
count: '授權數量',
valid_license: '授權验证',
show_license: '查看授權',
valid_license_error: '授權验证失败',
},
workspace: {
create: '創建工作空間',
update: '修改工作空間',
@ -638,6 +652,7 @@ export default {
upload_limit_count: "一次只能上傳一個文件",
upload_limit_format: "上傳文件只能是 xls、xlsx格式!",
upload_limit_size: "上傳文件大小不能超過 20MB!",
upload_limit_other_size: "上傳文件大小不能超過",
success: "導入成功!",
importing: "導入中...",
},