feat: 模板字段支持列表展示

This commit is contained in:
chenjianxing 2021-06-08 20:39:36 +08:00 committed by jianxing
parent b469bc5365
commit a5d7427fd9
12 changed files with 355 additions and 262 deletions

View File

@ -0,0 +1,2 @@
-- 自定义字段保存表头的key
ALTER TABLE custom_field_template ADD `key` varchar(1) NULL COMMENT 'Save Table Header Key';

View File

@ -33,6 +33,7 @@
</template>
</el-table-column>
<el-table-column width="1"/>
<slot></slot>
<el-table-column
@ -255,8 +256,8 @@ export default {
handleBatchMove() {
this.$refs.testBatchMove.open(this.treeNodes, Array.from(this.selectRows).map(row => row.id), this.moduleOptions);
},
handleRowClick() {
this.$emit("handleRowClick");
handleRowClick(row) {
this.$emit("handleRowClick", row);
},
handleRefresh() {
this.clear();

View File

@ -75,6 +75,7 @@ import CustomFieldFormList from "@/business/components/settings/workspace/templa
import CustomFieldRelateList from "@/business/components/settings/workspace/template/CustomFieldRelateList";
import {getCurrentWorkspaceId} from "@/common/js/utils";
import CustomFieldEdit from "@/business/components/settings/workspace/template/CustomFieldEdit";
import {generateTableHeaderKey, getCustomFieldsKeys} from "@/common/js/tableUtils";
export default {
name: "FieldTemplateEdit",
@ -147,7 +148,11 @@ export default {
param.workspaceId = getCurrentWorkspaceId();
let customFields = this.relateFields;
if (customFields) {
let keys = getCustomFieldsKeys(customFields);
customFields.forEach(item => {
if (!item.key) {
item.key = generateTableHeaderKey(keys, customFields);
}
item.defaultValue = JSON.stringify(item.defaultValue);
});
}

View File

@ -163,7 +163,14 @@ export default {
if (oldVal !== 'default' && newVal === 'default' && this.$refs.minder) {
this.$refs.minder.refresh();
}
}
},
activeDom(newVal, oldVal) {
this.$nextTick(() => {
if (oldVal !== 'left' && newVal === 'left' && this.$refs.testCaseList) {
this.$refs.testCaseList.getTemplateField();
}
});
},
},
computed: {
checkRedirectID: function () {

View File

@ -154,6 +154,7 @@
import TestCaseStepItem from "@/business/components/track/case/components/TestCaseStepItem";
import StepChangeItem from "@/business/components/track/case/components/StepChangeItem";
import MsChangeHistory from "../../../history/ChangeHistory";
import {getTestTemplate} from "@/network/custom-field-template";
export default {
name: "TestCaseEdit",
@ -311,7 +312,7 @@
created() {
this.projectId = this.projectIds;
let initAddFuc = this.initAddFuc;
getTemplate('field/template/case/get/relate/', this)
getTestTemplate()
.then((template) => {
this.testCaseTemplate = template;
initAddFuc();

View File

@ -1,165 +1,138 @@
<template>
<div class="card-container" v-loading="result.loading">
<div class="card-container">
<ms-table-header :condition.sync="condition" @search="initTableData"
:tip="$t('commons.search_by_name_or_id')" title="" :show-create="false"/>
<el-table
border
:data="tableData"
@sort-change="sort"
@filter-change="filter"
@select-all="handleSelectAll"
@select="handleSelect"
@header-dragend="headerDragend"
@cell-mouse-enter="showPopover"
:height="screenHeight"
row-key="id"
class="test-content adjust-table ms-select-all-fixed"
ref="table" @row-click="handleEdit">
<el-table-column
width="50"
type="selection"/>
<ms-table-header-select-popover v-show="total>0"
:page-size="pageSize > total ? total : pageSize"
:total="total"
:select-data-counts="selectDataCounts"
:table-data-count-in-page="tableData.length"
@selectPageAll="isSelectDataAll(false)"
@selectAll="isSelectDataAll(true)"/>
<ms-table
v-loading="page.result.loading"
:data="page.data"
:condition="condition"
:total="page.total"
:page-size.sync="page.pageSize"
:operators="operators"
:screen-height="screenHeight"
:batch-operators="buttons"
@handlePageChange="initTableData"
@handleRowClick="handleEdit"
:fields.sync="fields"
field-key="TRACK_TEST_CASE"
@refresh="initTableData"
ref="table">
<el-table-column width="30" :resizable="false" align="center">
<template v-slot:default="scope">
<show-more-btn :is-show="scope.row.showMore" :buttons="buttons" :size="selectDataCounts"/>
</template>
</el-table-column>
<template v-for="(item, index) in tableLabel">
<span v-for="item in fields" :key="item.key">
<el-table-column
v-if="item.id === 'num' && !customNum"
<ms-table-column
v-if="!customNum"
:field="item"
:fields-width="fieldsWidth"
prop="num"
sortable="custom"
:label="$t('commons.id')"
:key="index"
min-width="80"
show-overflow-tooltip>
</el-table-column>
<el-table-column
v-if="item.id === 'num' && customNum"
min-width="80"/>
<ms-table-column
v-if="customNum"
:field="item"
:fields-width="fieldsWidth"
prop="customNum"
sortable="custom"
:label="$t('commons.id')"
:key="index"
min-width="80"
show-overflow-tooltip>
</el-table-column>
<el-table-column
v-if="item.id == 'name'"
min-width="80"/>
<ms-table-column
prop="name"
:field="item"
:fields-width="fieldsWidth"
:label="$t('commons.name')"
show-overflow-tooltip
:key="index"
min-width="120"
>
</el-table-column>
<el-table-column
v-if="item.id == 'createUser'"
prop="createName"
/>
<ms-table-column
prop="createUser"
:field="item"
:fields-width="fieldsWidth"
:label="$t('commons.create_user')"
show-overflow-tooltip
:key="index"
min-width="120"
>
</el-table-column>
<el-table-column
v-if="item.id == 'maintainer'"
min-width="120"/>
<ms-table-column
prop="maintainer"
:field="item"
:fields-width="fieldsWidth"
:label="$t('custom_field.case_maintainer')"
show-overflow-tooltip
:key="index"
min-width="120"
>
</el-table-column>
<el-table-column
v-if="item.id == 'priority'"
min-width="120"/>
<ms-table-column
prop="priority"
:field="item"
:fields-width="fieldsWidth"
:filters="priorityFilters"
column-key="priority"
sortable="custom"
min-width="120px"
:label="$t('test_track.case.priority')"
show-overflow-tooltip
:key="index">
min-width="120px"
:label="$t('test_track.case.priority')">
<template v-slot:default="scope">
<priority-table-item :value="scope.row.priority"/>
</template>
</el-table-column>
<el-table-column
v-if="item.id=='reviewStatus'"
column-key="reviewStatus"
min-width="100px"
:label="$t('test_track.case.status')"
:key="index">
</ms-table-column>
<ms-table-column
prop="reviewStatus"
min-width="100px"
:field="item"
:fields-width="fieldsWidth"
:label="$t('test_track.case.status')">
<template v-slot:default="scope">
<span class="el-dropdown-link">
<review-status :value="scope.row.reviewStatus"/>
</span>
</template>
</el-table-column>
<el-table-column v-if="item.id=='tags'" prop="tags" :label="$t('commons.tag')" min-width="80" :key="index">
</ms-table-column>
<ms-table-column
prop="tags"
:field="item"
:fields-width="fieldsWidth"
:label="$t('commons.tag')"
min-width="80">
<template v-slot:default="scope">
<ms-tag v-for="(itemName,index) in scope.row.tags" :key="index" type="success" effect="plain"
:content="itemName" style="margin-left: 0px; margin-right: 2px"/>
</template>
</el-table-column>
</ms-table-column>
<el-table-column
v-if="item.id=='nodePath'"
<ms-table-column
prop="nodePath"
:field="item"
:fields-width="fieldsWidth"
:label="$t('test_track.case.module')"
min-width="150px"
show-overflow-tooltip
:key="index">
</el-table-column>
min-width="150px">
</ms-table-column>
<el-table-column
v-if="item.id=='updateTime'"
<ms-table-column
prop="updateTime"
sortable="custom"
:field="item"
:fields-width="fieldsWidth"
:label="$t('commons.update_time')"
min-width="150px"
show-overflow-tooltip
:key="index">
min-width="150px">
<template v-slot:default="scope">
<span>{{ scope.row.updateTime | timestampFormatDate }}</span>
</template>
</el-table-column>
</template>
<el-table-column fixed="right" min-width="150">
<template slot="header">
<header-label-operate @exec="customHeader"/>
</template>
<template v-slot:default="scope">
<ms-table-operator :edit-permission="['PROJECT_TRACK_CASE:READ+EDIT']"
:delete-permission="['PROJECT_TRACK_CASE:READ+DELETE']"
@editClick="handleEdit(scope.row)"
@deleteClick="handleDelete(scope.row)">
<template v-slot:middle>
<ms-table-operator-button v-permission="['PROJECT_TRACK_CASE:READ+COPY']"
:tip="$t('commons.copy')"
icon="el-icon-document-copy"
type="success" @exec="handleCopy(scope.row)"/>
</template>
</ms-table-operator>
</template>
</el-table-column>
<header-custom ref="headerCustom" :initTableData="initTableData" :optionalFields=headerItems
:type=type></header-custom>
</el-table>
</ms-table-column>
<ms-table-pagination :change="initTableData" :current-page.sync="currentPage" :page-size.sync="pageSize"
:total="total"/>
<ms-table-column v-for="field in testCaseTemplate.customFields" :key="field.id"
:field="item"
:fields-width="fieldsWidth"
:label="field.name"
:prop="field.name">
<template v-slot="scope">
{{getCustomFieldValue(scope.row, field)}}
</template>
</ms-table-column>
</span>
</ms-table>
<ms-table-pagination :change="initTableData" :current-page.sync="page.currentPage" :page-size.sync="page.pageSize"
:total="page.total"/>
<batch-edit ref="batchEdit" @batchEdit="batchEdit"
:typeArr="typeArr" :value-arr="valueArr" :dialog-title="$t('test_track.case.batch_edit_case')"/>
@ -185,39 +158,36 @@ import MsTableOperator from "../../../common/components/MsTableOperator";
import MsTableOperatorButton from "../../../common/components/MsTableOperatorButton";
import MsTableButton from "../../../common/components/MsTableButton";
import {TEST_CASE_CONFIGS} from "../../../common/components/search/search-components";
import ShowMoreBtn from "./ShowMoreBtn";
import BatchEdit from "./BatchEdit";
import {PROJECT_NAME, TEST_CASE_LIST, WORKSPACE_ID} from "@/common/js/constants";
import {PROJECT_NAME, TEST_CASE_LIST} from "@/common/js/constants";
import StatusTableItem from "@/business/components/track/common/tableItems/planview/StatusTableItem";
import TestCaseDetail from "./TestCaseDetail";
import ReviewStatus from "@/business/components/track/case/components/ReviewStatus";
import MsTag from "@/business/components/common/components/MsTag";
import {
_filter,
_handleSelect,
_handleSelectAll,
_sort,
buildBatchParam, deepClone,
getLabel,
getSelectDataCounts,
buildBatchParam, deepClone, getCustomFieldValue, getCustomTableWidth,
getPageInfo,
getTableHeaderWithCustomFields,
initCondition,
setUnSelectIds,
toggleAllSelection
} from "@/common/js/tableUtils";
import BatchMove from "./BatchMove";
import {Track_Test_Case} from "@/business/components/common/model/JsonData";
import HeaderCustom from "@/business/components/common/head/HeaderCustom";
import HeaderLabelOperate from "@/business/components/common/head/HeaderLabelOperate";
import PlanStatusTableItem from "@/business/components/track/common/tableItems/plan/PlanStatusTableItem";
import {getCurrentProjectID} from "@/common/js/utils";
import {getTestTemplate} from "@/network/custom-field-template";
import {getProjectMember} from "@/network/user";
import MsTable from "@/business/components/common/components/table/MsTable";
import MsTableColumn from "@/business/components/common/components/table/Ms-table-column";
import BatchMove from "@/business/components/track/case/components/BatchMove";
export default {
name: "TestCaseList",
components: {
BatchMove,
MsTableColumn,
MsTable,
PlanStatusTableItem,
HeaderLabelOperate,
HeaderCustom,
BatchMove,
MsTableHeaderSelectPopover,
MsTableButton,
MsTableOperatorButton,
@ -231,7 +201,6 @@ export default {
MsTablePagination,
NodeBreadcrumb,
MsTableHeader,
ShowMoreBtn,
BatchEdit,
StatusTableItem,
TestCaseDetail,
@ -244,16 +213,10 @@ export default {
screenHeight: 'calc(100vh - 310px)',
headerItems: Track_Test_Case,
tableLabel: [],
result: {},
deletePath: "/test/case/delete",
condition: {
components: TEST_CASE_CONFIGS
},
tableData: [],
currentPage: 1,
pageSize: 10,
total: 0,
selectRows: new Set(),
priorityFilters: [
{text: 'P0', value: 'P0'},
{text: 'P1', value: 'P1'},
@ -279,7 +242,6 @@ export default {
{text: '进行中', value: 'Underway'},
{text: '已完成', value: 'Completed'},
],
showMore: false,
buttons: [
{
name: this.$t('test_track.case.batch_edit_case'),
@ -295,6 +257,23 @@ export default {
permissions: ['PROJECT_TRACK_CASE:READ+DELETE']
}
],
operators: [
{
tip: this.$t('commons.edit'), icon: "el-icon-edit",
exec: this.handleEdit,
permissions: ['PROJECT_TRACK_CASE:READ+EDIT']
},
{
tip: this.$t('commons.copy'), icon: "el-icon-copy-document", type: "success",
exec: this.handleCopy,
permissions: ['PROJECT_TRACK_CASE:READ+EDIT']
},
{
tip: this.$t('commons.delete'), icon: "el-icon-delete", type: "danger",
exec: this.handleDelete,
permissions: ['PROJECT_TRACK_CASE:READ+DELETE']
}
],
typeArr: [
{id: 'priority', name: this.$t('test_track.case.priority')},
{id: 'maintainer', name: this.$t('test_track.case.maintainer')},
@ -317,9 +296,12 @@ export default {
],
maintainer: [],
},
currentCaseId: null,
selectDataCounts: 0,
selectDataRange: "all"
selectDataRange: "all",
testCaseTemplate: {},
members: [],
page: getPageInfo(),
fields: [],
fieldsWidth: getCustomTableWidth('TRACK_TEST_CASE'),
};
},
props: {
@ -345,8 +327,6 @@ export default {
moduleOptions() {
return this.$store.state.testCaseModuleOptions;
},
},
created: function () {
this.$emit('setCondition', this.condition);
@ -354,15 +334,15 @@ export default {
this.initTableData();
let redirectParam = this.$route.query.dataSelectRange;
this.checkRedirectEditPage(redirectParam);
},
activated() {
this.getTemplateField();
this.condition.filters = {reviewStatus: ["Prepare", "Pass", "UnPass"]};
this.initTableData();
},
watch: {
selectNodeIds() {
this.currentPage = 1;
this.page.currentPage = 1;
initCondition(this.condition, false);
this.initTableData();
},
@ -371,6 +351,22 @@ export default {
}
},
methods: {
getTemplateField() {
this.page.result.loading = false;
getProjectMember((data) => {
this.members = data;
});
getTestTemplate()
.then((template) => {
this.testCaseTemplate = template;
this.fields = getTableHeaderWithCustomFields('TRACK_TEST_CASE', this.testCaseTemplate.customFields);
this.page.result.loading = true;
this.$refs.table.reloadTable();
});
},
getCustomFieldValue(row, field) {
return getCustomFieldValue(row, field, this.members);
},
checkRedirectEditPage(redirectParam) {
if (redirectParam != null) {
this.$get('test/case/get/' + redirectParam, response => {
@ -394,7 +390,6 @@ export default {
this.condition.nodeIds = [];
//initCondition(this.condition);
initCondition(this.condition, this.condition.selectAll);
this.selectDataCounts = 0;
if (this.planId) {
// param.planId = this.planId;
this.condition.planId = this.planId;
@ -403,8 +398,6 @@ export default {
// param.nodeIds = this.selectNodeIds;
this.condition.nodeIds = this.selectNodeIds;
}
getLabel(this, TEST_CASE_LIST);
this.getData();
},
getData() {
@ -438,50 +431,20 @@ export default {
if (this.projectId) {
this.condition.projectId = this.projectId;
this.$emit('setCondition', this.condition);
this.result = this.$post(this.buildPagePath('/test/case/list'), this.condition, response => {
this.page.result = this.$post(this.buildPagePath('/test/case/list'), this.condition, response => {
let data = response.data;
this.total = data.itemCount;
this.tableData = data.listObject;
this.page.total = data.itemCount;
this.page.data = data.listObject;
// this.selectIds.clear();
this.selectRows.clear();
this.$refs.table.clear();
/*this.tableData.forEach(item => {
if (item.tags && item.tags.length > 0) {
item.tags = JSON.parse(item.tags);
}
})*/
this.tableData.forEach((item) => {
this.page.data.forEach((item) => {
item.tags = JSON.parse(item.tags);
});
this.$nextTick(() => {
if (this.$refs.table) {
setTimeout(this.$refs.table.doLayout, 200);
}
this.checkTableRowIsSelect();
});
});
}
},
checkTableRowIsSelect() {
//
if (this.condition.selectAll) {
let unSelectIds = this.condition.unSelectIds;
this.tableData.forEach(row => {
if (unSelectIds.indexOf(row.id) < 0) {
this.$refs.table.toggleRowSelection(row, true);
//selectRows
if (!this.selectRows.has(row)) {
this.$set(row, "showMore", true);
this.selectRows.add(row);
}
} else {
//selectRow
if (this.selectRows.has(row)) {
this.$set(row, "showMore", false);
this.selectRows.delete(row);
}
}
});
}
},
@ -489,7 +452,7 @@ export default {
this.initTableData();
},
buildPagePath(path) {
return path + "/" + this.currentPage + "/" + this.pageSize;
return path + "/" + this.page.currentPage + "/" + this.page.pageSize;
},
testCaseCreate() {
this.$emit('testCaseEdit');
@ -523,10 +486,8 @@ export default {
callback: (action) => {
if (action === 'confirm') {
let param = buildBatchParam(this);
// param.ids = Array.from(this.selectRows).map(row => row.id);
// param.condition = this.condition;
this.$post('/test/case/batch/delete', param, () => {
this.selectRows.clear();
this.$refs.table.clear();
this.$emit("refresh");
this.$success(this.$t('commons.delete_success'));
});
@ -543,28 +504,16 @@ export default {
});
},
refresh() {
// this.condition = {components: TEST_CASE_CONFIGS};
// this.selectIds.clear();
this.selectRows.clear();
this.$refs.table.clear();
this.$emit('refresh');
},
refreshAll() {
this.selectRows.clear();
this.$refs.table.clear();
this.$emit('refreshAll');
},
showDetail(row, event, column) {
this.$emit('testCaseDetail', row);
},
handleSelectAll(selection) {
_handleSelectAll(this, selection, this.tableData, this.selectRows, this.condition);
setUnSelectIds(this.tableData, this.condition, this.selectRows);
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
},
handleSelect(selection, row) {
_handleSelect(this, selection, row, this.selectRows);
setUnSelectIds(this.tableData, this.condition, this.selectRows);
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
},
importTestCase() {
if (!this.projectId) {
this.$warning(this.$t('commons.check_project_tip'));
@ -590,7 +539,7 @@ export default {
return;
}
this.result = this.$request(config).then(response => {
this.page.result = this.$request(config).then(response => {
const filename = "Metersphere_case_" + localStorage.getItem(PROJECT_NAME) + ".xlsx";
const blob = new Blob([response.data]);
if ("download" in document.createElement("a")) {
@ -605,7 +554,7 @@ export default {
});
},
handleBatch(type) {
if (this.selectRows.size < 1) {
if (this.$refs.selectRows.size < 1) {
if (type === 'export') {
this.exportTestCase();
return;
@ -615,7 +564,7 @@ export default {
}
}
if (type === 'move') {
let ids = Array.from(this.selectRows).map(row => row.id);
let ids = this.$refs.table.selectIds;
this.$emit('moveToNode', ids);
} else if (type === 'delete') {
this.handleDeleteBatch();
@ -624,8 +573,7 @@ export default {
}
},
batchEdit(form) {
let arr = Array.from(this.selectRows);
let ids = arr.map(row => row.id);
let ids = this.$refs.table.selectIds;
let param = {};
param[form.type] = form.value;
param.ids = ids;
@ -635,57 +583,21 @@ export default {
this.refresh();
});
},
filter(filters) {
_filter(filters, this.condition);
this.initTableData();
},
sort(column) {
//
if (this.condition.orders) {
this.condition.orders = [];
}
_sort(column, this.condition);
this.initTableData();
},
handleBatchEdit() {
this.getMaintainerOptions();
this.$refs.batchEdit.open();
},
handleBatchMove() {
this.$refs.testBatchMove.open(this.treeNodes, Array.from(this.selectRows).map(row => row.id), this.moduleOptions);
this.$refs.testBatchMove.open(this.treeNodes, this.$refs.table.selectIds, this.moduleOptions);
},
getMaintainerOptions() {
this.$post('/user/project/member/tester/list', {projectId: getCurrentProjectID()}, response => {
this.valueArr.maintainer = response.data;
});
},
showPopover(row, column, cell) {
if (column.property === 'name') {
this.currentCaseId = row.id;
}
},
isSelectDataAll(data) {
this.condition.selectAll = data;
//
toggleAllSelection(this.$refs.table, this.tableData, this.selectRows);
//
_handleSelectAll(this, this.tableData, this.tableData, this.selectRows);
//ID()
this.condition.unSelectIds = [];
//
this.selectDataCounts = getSelectDataCounts(this.condition, this.total, this.selectRows);
},
headerDragend(newWidth, oldWidth, column, event) {
let finalWidth = newWidth;
if (column.minWidth > finalWidth) {
finalWidth = column.minWidth;
}
column.width = finalWidth;
column.realWidth = finalWidth;
},
moveSave(param) {
param.condition = this.condition;
this.result = this.$post('/test/case/batch/edit', param, () => {
this.page.result = this.$post('/test/case/batch/edit', param, () => {
this.$success(this.$t('commons.save_success'));
this.$refs.testBatchMove.close();
this.refresh();
@ -725,7 +637,7 @@ export default {
margin-left: 10px;
}
/deep/ .el-table__fixed-body-wrapper {
top: 60px !important;
}
/*/deep/ .el-table__fixed-body-wrapper {*/
/* top: 60px !important;*/
/*}*/
</style>

View File

@ -77,6 +77,7 @@ import CustomFiledComponent from "@/business/components/settings/workspace/templ
import TestCaseIssueList from "@/business/components/track/issue/TestCaseIssueList";
import IssueEditDetail from "@/business/components/track/issue/IssueEditDetail";
import {getCurrentProjectID, getCurrentUserId} from "@/common/js/utils";
import {getIssueTemplate} from "@/network/custom-field-template";
export default {
name: "IssueEditDetail",
@ -146,7 +147,7 @@ export default {
methods: {
open(data) {
let initAddFuc = this.initEdit;
getTemplate('field/template/issue/get/relate/', this)
getIssueTemplate()
.then((template) => {
this.issueTemplate = template;
this.getThirdPartyInfo();

View File

@ -22,6 +22,7 @@
:fields.sync="fields"
field-key="ISSUE_LIST"
@refresh="getIssues"
ref="table"
>
<span v-for="(item) in fields" :key="item.key">
<!-- <ms-table-column
@ -87,6 +88,17 @@
</ms-table-column>
<issue-description-table-item :fields-width="fieldsWidth" :field="item"/>
<ms-table-column v-for="field in issueTemplate.customFields" :key="field.id"
:field="item"
:fields-width="fieldsWidth"
:label="field.name"
:prop="field.name">
<template v-slot="scope">
{{getCustomFieldValue(scope.row, field)}}
</template>
</ms-table-column>
</span>
</ms-table>
@ -117,13 +129,19 @@ import MsTableHeader from "@/business/components/common/components/MsTableHeader
import IssueDescriptionTableItem from "@/business/components/track/issue/IssueDescriptionTableItem";
import IssueEdit from "@/business/components/track/issue/IssueEdit";
import {getIssues} from "@/network/Issue";
import {getCustomTableHeader, getCustomTableWidth, getPageInfo} from "@/common/js/tableUtils";
import {
getCustomFieldValue,
getCustomTableWidth,
getPageInfo, getTableHeaderWithCustomFields,
} from "@/common/js/tableUtils";
import MsContainer from "@/business/components/common/components/MsContainer";
import MsMainContainer from "@/business/components/common/components/MsMainContainer";
import {getCurrentProjectID} from "@/common/js/utils";
import {getIssueTemplate} from "@/network/custom-field-template";
import {getProjectMember} from "@/network/user";
export default {
name: "CustomFieldList",
name: "IssueList",
components: {
MsMainContainer,
MsContainer,
@ -135,7 +153,7 @@ export default {
data() {
return {
page: getPageInfo(),
fields: getCustomTableHeader('ISSUE_LIST'),
fields: [],
fieldsWidth: getCustomTableWidth('ISSUE_LIST'),
screenHeight: 'calc(100vh - 290px)',
operators: [
@ -155,9 +173,20 @@ export default {
permissions: ['PROJECT_TRACK_ISSUE:READ+DELETE']
}
],
issueTemplate: {},
members: []
};
},
activated() {
getProjectMember((data) => {
this.members = data;
});
getIssueTemplate()
.then((template) => {
this.issueTemplate = template;
this.fields = getTableHeaderWithCustomFields('ISSUE_LIST', this.issueTemplate.customFields);
this.$refs.table.reloadTable();
});
this.getIssues();
},
computed: {
@ -181,6 +210,9 @@ export default {
}
},
methods: {
getCustomFieldValue(row, field) {
return getCustomFieldValue(row, field, this.members);
},
getIssues() {
this.page.condition.projectId = this.projectId;
this.page.result = getIssues(this.page);

View File

@ -1,5 +1,7 @@
import {getCurrentProjectID, getCurrentUser, humpToLine} from "@/common/js/utils";
import {CUSTOM_TABLE_HEADER} from "@/common/js/default-table-header";
import {updateCustomFieldTemplate} from "@/network/custom-field-template";
import i18n from "@/i18n/i18n";
export function _handleSelectAll(component, selection, tableData, selectRows, condition) {
if (selection.length > 0) {
@ -201,14 +203,14 @@ export function deepClone(source) {
return targetObj;
}
export function getPageInfo() {
export function getPageInfo(condition) {
return {
total: 0,
pageSize: 10,
currentPage: 1,
result: {},
data: [],
condition: {},
condition: condition ? condition : {},
}
}
@ -230,6 +232,10 @@ export function getPageDate(response, page) {
*/
export function getCustomTableHeader(key) {
let fieldSetting = CUSTOM_TABLE_HEADER[key];
return getCustomTableHeaderByFiledSetting(key, fieldSetting);
}
function getCustomTableHeaderByFiledSetting(key, fieldSetting) {
let fieldStr = localStorage.getItem(key);
if (fieldStr !== null) {
let fields = [];
@ -248,6 +254,55 @@ export function getCustomTableHeader(key) {
return fieldSetting;
}
/**
* 获取带自定义字段的表头
* @param key
* @param customFields
* @returns {[]|*}
*/
export function getTableHeaderWithCustomFields(key, customFields) {
let fieldSetting = CUSTOM_TABLE_HEADER[key];
let keys = getCustomFieldsKeys(customFields);
customFields.forEach(item => {
if (!item.key) {
// 兼容旧版更新key
item.key = generateTableHeaderKey(keys, customFields);
updateCustomFieldTemplate({id: item.id, key: item.key});
}
let field = {
id: item.name,
key: item.key,
label: item.name,
isCustom: true
}
fieldSetting.push(field);
});
return getCustomTableHeaderByFiledSetting(key, fieldSetting);
}
export function generateTableHeaderKey(keys) {
let customFieldKeys = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
for (let i = 0; i < customFieldKeys.length; i++) {
let key = customFieldKeys[i];
if (keys.has(key)) {
continue;
}
keys.add(key);
return key;
}
return '';
}
export function getCustomFieldsKeys(customFields) {
let keys = new Set();
customFields.forEach(item => {
if (item.key) {
keys.add(item.key);
}
});
return keys;
}
/**
* 将自定义表头存在 localStorage
* 格式简化减小占用
@ -289,3 +344,36 @@ export function saveCustomTableWidth(key, fieldKey, colWith) {
fields[fieldKey] = colWith + '';
localStorage.setItem(key + '_WITH', JSON.stringify(fields));
}
/**
* 获取列表的自定义字段的显示值
* @param row
* @param field
* @param members
* @returns {VueI18n.TranslateResult|*}
*/
export function getCustomFieldValue(row, field, members) {
if (row.customFields) {
for (let i = 0; i < row.customFields.length; i++) {
let item = row.customFields[i];
if (item.name === field.name) {
if (field.type === 'member' || field.type === 'multipleMember') {
for (let j = 0; j < members.length; j++) {
let member = members[j];
if (member.id === item.value) {
return member.name;
}
}
} else if (['radio', 'select', 'multipleSelect', 'checkbox'].indexOf(field.type) > -1) {
for (let j = 0; j < field.options.length; j++) {
let option = field.options[j];
if (option.value === item.value) {
return field.system ? i18n.t(option.text) : option.text;
}
}
}
return item.value;
}
}
}
}

View File

@ -5,6 +5,9 @@ export function buildIssues(page) {
let data = page.data;
for (let i = 0; i < data.length; i++) {
if (data[i]) {
if (data[i].customFields) {
data[i].customFields = JSON.parse(data[i].customFields);
}
if (data[i].platform !== 'Local') {
page.result = buildPlatformIssue(data[i]);
}

View File

@ -0,0 +1,31 @@
import {post, get} from "@/common/js/ajax";
import {getCurrentProjectID} from "@/common/js/utils";
export function getTemplate(baseUrl) {
return new Promise((resolve) => {
let template = {};
get(baseUrl + getCurrentProjectID(), (response) => {
template = response.data;
if (template.customFields) {
template.customFields.forEach(item => {
if (item.options) {
item.options = JSON.parse(item.options);
}
});
}
resolve(template);
});
});
}
export function getIssueTemplate() {
return getTemplate('field/template/issue/get/relate/');
}
export function getTestTemplate() {
return getTemplate('field/template/case/get/relate/');
}
export function updateCustomFieldTemplate(request) {
post('/custom/field/template/update', request);
}

View File

@ -0,0 +1,10 @@
import {getCurrentProjectID} from "@/common/js/utils";
import {post} from "@/common/js/ajax";
export function getProjectMember(callBack) {
return post('/user/project/member/tester/list', {projectId: getCurrentProjectID()}, response => {
if (callBack) {
callBack(response.data);
}
});
}