fix(接口测试): 接口自动化场景步骤较多时,展开步骤和步骤的响应内容后上下滑动,页面会不受控制滑动并且自动收起响应内容

--bug=1028739 --user=白奇 【接口测试】github#26158,接口自动化场景步骤较多时,展开步骤和步骤的响应内容后上下滑动,页面会不受控制滑动并且自动收起响应内容 https://www.tapd.cn/55049933/s/1408426
This commit is contained in:
baiqi 2023-08-25 14:53:09 +08:00 committed by fit2-zhao
parent 747ca01483
commit 025c9eed41
8 changed files with 276 additions and 211 deletions

View File

@ -9,9 +9,9 @@
"report": "NODE_ENV=analyze vue-cli-service build" "report": "NODE_ENV=analyze vue-cli-service build"
}, },
"dependencies": { "dependencies": {
"@ba1q1/vue-easy-tree": "^1.1.0",
"@ckeditor/ckeditor5-build-classic": "^18.0.0", "@ckeditor/ckeditor5-build-classic": "^18.0.0",
"@ckeditor/ckeditor5-vue": "^1.0.1", "@ckeditor/ckeditor5-vue": "^1.0.1",
"@fit2cloud-ui/vue-virtual-tree": "^1.0.0",
"@form-create/element-ui": "^2.5.8", "@form-create/element-ui": "^2.5.8",
"@fortawesome/fontawesome-svg-core": "^1.2.26", "@fortawesome/fontawesome-svg-core": "^1.2.26",
"@fortawesome/free-brands-svg-icons": "^5.13.0", "@fortawesome/free-brands-svg-icons": "^5.13.0",

View File

@ -9,7 +9,7 @@
</el-tooltip> </el-tooltip>
</div> </div>
<div style="height: calc(100vh - 400px)"> <div style="height: calc(100vh - 400px)">
<vue-easy-tree <vue-virtual-tree
:data="treeData" :data="treeData"
node-key="resourceId" node-key="resourceId"
:sizeDependencies="['expanded']" :sizeDependencies="['expanded']"
@ -33,7 +33,7 @@
:is-share="isShare" :is-share="isShare"
:share-id="shareId" /> :share-id="shareId" />
</template> </template>
</vue-easy-tree> </vue-virtual-tree>
</div> </div>
</el-card> </el-card>
</template> </template>

View File

@ -9,7 +9,7 @@
</el-tooltip> </el-tooltip>
</div> </div>
<div style="height: calc(100vh - 400px)"> <div style="height: calc(100vh - 400px)">
<vue-easy-tree <vue-virtual-tree
:data="treeData" :data="treeData"
node-key="resourceId" node-key="resourceId"
:sizeDependencies="['expanded']" :sizeDependencies="['expanded']"
@ -33,7 +33,7 @@
:is-share="isShare" :is-share="isShare"
:share-id="shareId" /> :share-id="shareId" />
</span> </span>
</vue-easy-tree> </vue-virtual-tree>
</div> </div>
</el-card> </el-card>
</template> </template>

View File

@ -271,7 +271,7 @@
<el-row> <el-row>
<!-- 场景步骤内容 --> <!-- 场景步骤内容 -->
<div ref="stepInfo" style="height: calc(100vh - 170px)"> <div ref="stepInfo" style="height: calc(100vh - 170px)">
<vue-easy-tree <vue-virtual-tree
node-key="id" node-key="id"
height="calc(100vh - 170px)" height="calc(100vh - 170px)"
:minItemSize="43" :minItemSize="43"
@ -353,7 +353,7 @@
{{ hideNode(node) }} {{ hideNode(node) }}
</div> </div>
</el-row> </el-row>
</vue-easy-tree> </vue-virtual-tree>
</div> </div>
</el-row> </el-row>
<el-row> <el-row>
@ -1464,7 +1464,7 @@ export default {
} }
this.selectedTreeNode = data; this.selectedTreeNode = data;
this.selectedNode = node; this.selectedNode = node;
store.selectStep = data; store.selectStep = node.data;
this.buttonData = buttons(this); this.buttonData = buttons(this);
this.initPlugins(); this.initPlugins();
if (this.buttonData.length === 0 && this.$refs.refFab && this.$refs.refFab.active) { if (this.buttonData.length === 0 && this.$refs.refFab && this.$refs.refFab.active) {

View File

@ -62,26 +62,24 @@
</slot> </slot>
</span> </span>
<div <div v-if="!ifFromVariableAdvance" class="header-right" @click.stop>
v-if="!ifFromVariableAdvance" <div v-show="!isMax">
class="header-right" <slot name="message"></slot>
@click.stop> </div>
<slot name="message" v-show="!isMax"></slot>
<slot name="debugStepCode"></slot> <slot name="debugStepCode"></slot>
<slot name="button" v-if="showVersion"></slot> <slot name="button" v-if="showVersion"></slot>
<el-tooltip :content="$t('test_resource_pool.enable_disable')" placement="top" v-if="showBtn" <el-tooltip
:content="$t('test_resource_pool.enable_disable')"
placement="top"
v-if="showBtn"
v-permission="[ v-permission="[
'PROJECT_API_SCENARIO:READ+EDIT', 'PROJECT_API_SCENARIO:READ+EDIT',
'PROJECT_API_SCENARIO:READ+CREATE', 'PROJECT_API_SCENARIO:READ+CREATE',
'PROJECT_API_SCENARIO:READ+COPY', 'PROJECT_API_SCENARIO:READ+COPY',
]"> ]">
<el-switch <el-switch v-model="data.enable" class="enable-switch" size="mini" :disabled="isEnabled()" />
v-model="data.enable"
class="enable-switch"
size="mini"
:disabled="isEnabled()" />
</el-tooltip> </el-tooltip>
<el-button <el-button
@ -111,7 +109,7 @@
'PROJECT_API_SCENARIO:READ+EDIT', 'PROJECT_API_SCENARIO:READ+EDIT',
'PROJECT_API_SCENARIO:READ+CREATE', 'PROJECT_API_SCENARIO:READ+CREATE',
'PROJECT_API_SCENARIO:READ+COPY', 'PROJECT_API_SCENARIO:READ+COPY',
]"/> ]" />
<step-extend-btns <step-extend-btns
style="display: contents" style="display: contents"
@ -165,7 +163,6 @@ export default {
data() { data() {
return { return {
isShowInput: false, isShowInput: false,
colorStyle: '',
stepFilter: new STEP(), stepFilter: new STEP(),
}; };
}, },
@ -238,21 +235,12 @@ export default {
default: false, default: false,
}, },
}, },
watch: {
selectStep() {
if (store.selectStep && store.selectStep.resourceId === this.data.resourceId) {
this.colorStyle = this.color;
} else {
this.colorStyle = '';
}
},
},
created() { created() {
let typeArray = ["LoopController", "IfController","TransactionController"]; let typeArray = ['LoopController', 'IfController', 'TransactionController'];
if (typeArray.includes(this.data.type) && !this.data.disabled) { if (typeArray.includes(this.data.type) && !this.data.disabled) {
this.data.hashTree.forEach(item => { this.data.hashTree.forEach((item) => {
item.isCopy = true; item.isCopy = true;
}) });
} }
if (!this.data.name) { if (!this.data.name) {
this.isShowInput = true; this.isShowInput = true;
@ -272,6 +260,13 @@ export default {
selectStep() { selectStep() {
return store.selectStep; return store.selectStep;
}, },
colorStyle() {
if (this.selectStep?.resourceId === this.data.resourceId) {
return this.color;
} else {
return '';
}
},
forceRerenderIndex() { forceRerenderIndex() {
return store.forceRerenderIndex; return store.forceRerenderIndex;
}, },
@ -285,12 +280,13 @@ export default {
}, },
isMoreButton() { isMoreButton() {
if (this.data.type === 'ConstantTimer' || this.data.type === 'Assertions') { if (this.data.type === 'ConstantTimer' || this.data.type === 'Assertions') {
return !this.data.caseEnable && ( return (
!this.innerStep || !this.data.caseEnable &&
(!this.innerStep ||
(this.showBtn && (this.showBtn &&
(!this.data.disabled || this.data.root || this.data.isCopy || this.data.showExtend) && (!this.data.disabled || this.data.root || this.data.isCopy || this.data.showExtend) &&
this.showVersion && this.showVersion &&
this.stepFilter.get('ALlSamplerStep').indexOf(this.data.type) === -1) this.stepFilter.get('ALlSamplerStep').indexOf(this.data.type) === -1))
); );
} }
return ( return (

View File

@ -20,8 +20,8 @@ import VueClipboard from 'vue-clipboard2';
import VuePapaParse from 'vue-papa-parse'; import VuePapaParse from 'vue-papa-parse';
import VueShepherd from 'vue-shepherd'; // 新手引导 import VueShepherd from 'vue-shepherd'; // 新手引导
import 'metersphere-frontend/src/assets/shepherd/shepherd-theme.css'; import 'metersphere-frontend/src/assets/shepherd/shepherd-theme.css';
import { gotoCancel, gotoNext } from "metersphere-frontend/src/utils"; import { gotoCancel, gotoNext } from 'metersphere-frontend/src/utils';
import VueEasyTree from "@ba1q1/vue-easy-tree"; import VueVirtualTree from '@fit2cloud-ui/vue-virtual-tree';
Vue.config.productionTip = false; Vue.config.productionTip = false;
@ -45,7 +45,7 @@ Vue.use(VueFab);
// Vue.use(formCreate); // Vue.use(formCreate);
Vue.use(VuePapaParse); Vue.use(VuePapaParse);
Vue.use(VueShepherd); Vue.use(VueShepherd);
Vue.use(VueEasyTree); Vue.use(VueVirtualTree);
Vue.prototype.gotoCancel = gotoCancel; Vue.prototype.gotoCancel = gotoCancel;
Vue.prototype.gotoNext = gotoNext; Vue.prototype.gotoNext = gotoNext;
@ -66,9 +66,9 @@ function render(props = {}) {
// 解决qiankun下vue-devtools不显示的问题 // 解决qiankun下vue-devtools不显示的问题
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
const instanceDiv = document.createElement('div') const instanceDiv = document.createElement('div');
instanceDiv.__vue__ = instance instanceDiv.__vue__ = instance;
document.body.appendChild(instanceDiv) document.body.appendChild(instanceDiv);
} }
// 微服务过来的路由 // 微服务过来的路由
if (defaultPath || routeName) { if (defaultPath || routeName) {
@ -110,7 +110,7 @@ export async function unmount(props) {
/** /**
* 更新钩子目前只有routeParams更新后续有其他属性更新再添加 * 更新钩子目前只有routeParams更新后续有其他属性更新再添加
*/ */
export async function update (props) { export async function update(props) {
const { defaultPath, routeParams, routeName } = props; const { defaultPath, routeParams, routeName } = props;
// 微服务过来的路由 // 微服务过来的路由
if (defaultPath || routeName) { if (defaultPath || routeName) {

View File

@ -21,13 +21,13 @@ import chart from 'metersphere-frontend/src/chart';
import filters from 'metersphere-frontend/src/filters'; import filters from 'metersphere-frontend/src/filters';
import icons from 'metersphere-frontend/src/icons'; import icons from 'metersphere-frontend/src/icons';
import plugins from 'metersphere-frontend/src/plugins'; import plugins from 'metersphere-frontend/src/plugins';
import VueEasyTree from "@ba1q1/vue-easy-tree"; import VueVirtualTree from '@fit2cloud-ui/vue-virtual-tree';
function apiReportUse(id, template) { function apiReportUse(id, template) {
Vue.use(ElementUI, { Vue.use(ElementUI, {
i18n: (key, value) => i18n.t(key, value), i18n: (key, value) => i18n.t(key, value),
}); });
Vue.use(VueEasyTree); Vue.use(VueVirtualTree);
Vue.use(Row); Vue.use(Row);
Vue.use(Col); Vue.use(Col);
Vue.use(Form); Vue.use(Form);

View File

@ -1,15 +1,24 @@
import {getCurrentProjectID, getCurrentUser} from "./token"; import { getCurrentProjectID, getCurrentUser } from "./token";
import {CUSTOM_TABLE_HEADER} from "./default-table-header"; import { CUSTOM_TABLE_HEADER } from "./default-table-header";
import {updateCustomFieldTemplate} from "../api/custom-field-template"; import { updateCustomFieldTemplate } from "../api/custom-field-template";
import i18n from "../i18n"; import i18n from "../i18n";
import Sortable from 'sortablejs' import Sortable from "sortablejs";
import {dateFormat, datetimeFormat} from "fit2cloud-ui/src/filters/time"; import { dateFormat, datetimeFormat } from "fit2cloud-ui/src/filters/time";
import {hasLicense} from "../utils/permission"; import { hasLicense } from "../utils/permission";
import {getUUID, humpToLine} from "./index"; import { getUUID, humpToLine } from "./index";
import {CUSTOM_FIELD_TYPE_OPTION, SYSTEM_FIELD_NAME_MAP} from "./table-constants"; import {
import {generateColumnKey} from "../components/search/custom-component"; CUSTOM_FIELD_TYPE_OPTION,
SYSTEM_FIELD_NAME_MAP,
} from "./table-constants";
import { generateColumnKey } from "../components/search/custom-component";
export function _handleSelectAll(component, selection, tableData, selectRows, condition) { export function _handleSelectAll(
component,
selection,
tableData,
selectRows,
condition
) {
selectRows.clear(); selectRows.clear();
if (selection.length > 0) { if (selection.length > 0) {
selection.forEach((item) => { selection.forEach((item) => {
@ -28,7 +37,7 @@ export function _handleSelectAll(component, selection, tableData, selectRows, co
} }
} else { } else {
selectRows.clear(); selectRows.clear();
tableData.forEach(item => { tableData.forEach((item) => {
component.$set(item, "showMore", false); component.$set(item, "showMore", false);
}); });
} }
@ -47,15 +56,15 @@ export function _handleSelect(component, selection, row, selectRowMap) {
selectRowMap.set(row.id, row); selectRowMap.set(row.id, row);
} }
let arr = Array.from(selectRowMap.values()); let arr = Array.from(selectRowMap.values());
arr.forEach(row => { arr.forEach((row) => {
component.$set(row, "showMore", true); component.$set(row, "showMore", true);
}); });
} }
// 设置 unSelectIds 查询条件,返回当前选中的条数 // 设置 unSelectIds 查询条件,返回当前选中的条数
export function setUnSelectIds(tableData, condition, selectRows) { export function setUnSelectIds(tableData, condition, selectRows) {
let ids = Array.from(selectRows).map(o => o.id); let ids = Array.from(selectRows).map((o) => o.id);
let allIDs = tableData.map(o => o.id); let allIDs = tableData.map((o) => o.id);
let thisUnSelectIds = allIDs.filter(function (val) { let thisUnSelectIds = allIDs.filter(function (val) {
return ids.indexOf(val) === -1; return ids.indexOf(val) === -1;
}); });
@ -68,7 +77,7 @@ export function setUnSelectIds(tableData, condition, selectRows) {
let needPushIds = thisUnSelectIds.filter(function (val) { let needPushIds = thisUnSelectIds.filter(function (val) {
return condition.unSelectIds.indexOf(val) === -1; return condition.unSelectIds.indexOf(val) === -1;
}); });
needPushIds.forEach(id => { needPushIds.forEach((id) => {
condition.unSelectIds.push(id); condition.unSelectIds.push(id);
}); });
} }
@ -91,11 +100,17 @@ export function toggleAllSelection(table, tableData, selectRows) {
} }
//检查表格每一行是否应该选择(使用场景:全选数据时进行翻页操作) //检查表格每一行是否应该选择(使用场景:全选数据时进行翻页操作)
export function checkTableRowIsSelect(component, condition, tableData, table, selectRows) { export function checkTableRowIsSelect(
component,
condition,
tableData,
table,
selectRows
) {
//如果默认全选的话,则选中应该选中的行 //如果默认全选的话,则选中应该选中的行
if (condition.selectAll) { if (condition.selectAll) {
let unSelectIds = condition.unSelectIds; let unSelectIds = condition.unSelectIds;
tableData.forEach(row => { tableData.forEach((row) => {
if (unSelectIds.indexOf(row.id) < 0) { if (unSelectIds.indexOf(row.id) < 0) {
table.toggleRowSelection(row, true); table.toggleRowSelection(row, true);
@ -116,19 +131,24 @@ export function checkTableRowIsSelect(component, condition, tableData, table, se
} }
//删除不需要的row(使用场景点击表格下拉框全选时在翻页的时候会把翻页的数据也加勾选如果勾选了table认为已经选中当点击只选此页数据时前几页的数据不会消失) //删除不需要的row(使用场景点击表格下拉框全选时在翻页的时候会把翻页的数据也加勾选如果勾选了table认为已经选中当点击只选此页数据时前几页的数据不会消失)
export function deleteTableRow(component, condition, tableData, table, selectRows) { export function deleteTableRow(
component,
condition,
tableData,
table,
selectRows
) {
//所有以选中的数据 //所有以选中的数据
let selectRowMap = new Map(); let selectRowMap = new Map();
for (let selectRow of selectRows) { for (let selectRow of selectRows) {
selectRowMap.set(selectRow.id, selectRow); selectRowMap.set(selectRow.id, selectRow);
} }
//表格标为选中的数据 //表格标为选中的数据
table.selection.forEach(t => { table.selection.forEach((t) => {
if (!selectRowMap.get(t.id)) { if (!selectRowMap.get(t.id)) {
table.toggleRowSelection(t, false); table.toggleRowSelection(t, false);
} }
}) });
} }
// nexttick:表格加载完成之后触发。判断是否需要勾选行 // nexttick:表格加载完成之后触发。判断是否需要勾选行
@ -148,7 +168,9 @@ export function _filter(filters, condition) {
} }
for (let filter in filters) { for (let filter in filters) {
if (filters.hasOwnProperty(filter)) { if (filters.hasOwnProperty(filter)) {
let filterName = filter.startsWith('custom') ? filter : humpToLine(filter); let filterName = filter.startsWith("custom")
? filter
: humpToLine(filter);
if (filters[filter] && filters[filter].length > 0) { if (filters[filter] && filters[filter].length > 0) {
condition.filters[filterName] = filters[filter]; condition.filters[filterName] = filters[filter];
} else { } else {
@ -160,11 +182,13 @@ export function _filter(filters, condition) {
//表格数据排序 //表格数据排序
export function _sort(column, condition) { export function _sort(column, condition) {
let field = humpToLine(column.column.columnKey ? column.column.columnKey : column.prop); let field = humpToLine(
if (column.order === 'descending') { column.column.columnKey ? column.column.columnKey : column.prop
column.order = 'desc'; );
} else if (column.order === 'ascending') { if (column.order === "descending") {
column.order = 'asc'; column.order = "desc";
} else if (column.order === "ascending") {
column.order = "asc";
} }
if (!condition.orders) { if (!condition.orders) {
condition.orders = []; condition.orders = [];
@ -173,7 +197,7 @@ export function _sort(column, condition) {
return; return;
} }
let hasProp = false; let hasProp = false;
condition.orders.forEach(order => { condition.orders.forEach((order) => {
if (order.name === field) { if (order.name === field) {
order.type = column.order; order.type = column.order;
hasProp = true; hasProp = true;
@ -183,7 +207,7 @@ export function _sort(column, condition) {
hasProp = true; hasProp = true;
}*/ }*/
if (!hasProp) { if (!hasProp) {
condition.orders.push({name: field, type: column.order}); condition.orders.push({ name: field, type: column.order });
} }
} }
@ -198,26 +222,31 @@ export function getLabel(vueObj, type) {
let param = {}; let param = {};
param.userId = getCurrentUser().id; param.userId = getCurrentUser().id;
param.type = type; param.type = type;
vueObj.result = vueObj.$post('/system/header/info', param, response => { vueObj.result = vueObj.$post("/system/header/info", param, (response) => {
if (response.data != null) { if (response.data != null) {
vueObj.tableLabel = eval(response.data.props); vueObj.tableLabel = eval(response.data.props);
} else { } else {
let param = {}; let param = {};
param.type = type; param.type = type;
vueObj.result = vueObj.$post('/system/system/header', param, response => { vueObj.result = vueObj.$post(
"/system/system/header",
param,
(response) => {
if (response.data != null) { if (response.data != null) {
vueObj.tableLabel = eval(response.data.props); vueObj.tableLabel = eval(response.data.props);
} }
}); }
);
} }
}); });
} }
export function buildBatchParam(vueObj, selectIds, projectId) { export function buildBatchParam(vueObj, selectIds, projectId) {
let param = {}; let param = {};
if (vueObj.selectRows) { if (vueObj.selectRows) {
param.ids = selectIds ? selectIds : Array.from(vueObj.selectRows).map(row => row.id); param.ids = selectIds
? selectIds
: Array.from(vueObj.selectRows).map((row) => row.id);
} else { } else {
param.ids = selectIds; param.ids = selectIds;
} }
@ -228,12 +257,12 @@ export function buildBatchParam(vueObj, selectIds, projectId) {
// 深拷贝 // 深拷贝
export function deepClone(source) { export function deepClone(source) {
if (!source && typeof source !== 'object') { if (!source && typeof source !== "object") {
throw new Error('error arguments', 'deepClone'); throw new Error("error arguments", "deepClone");
} }
const targetObj = source.constructor === Array ? [] : {}; const targetObj = source.constructor === Array ? [] : {};
Object.keys(source).forEach(keys => { Object.keys(source).forEach((keys) => {
if (source[keys] && typeof source[keys] === 'object') { if (source[keys] && typeof source[keys] === "object") {
targetObj[keys] = deepClone(source[keys]); targetObj[keys] = deepClone(source[keys]);
} else { } else {
targetObj[keys] = source[keys]; targetObj[keys] = source[keys];
@ -250,8 +279,8 @@ export function getPageInfo(condition) {
result: {}, result: {},
data: [], data: [],
condition: condition ? condition : {}, condition: condition ? condition : {},
loading: false loading: false,
} };
} }
export function buildPagePath(path, page) { export function buildPagePath(path, page) {
@ -306,23 +335,27 @@ function getCustomTableHeaderByFiledSetting(key, fieldSetting) {
* @param customFields * @param customFields
* @returns {[]|*} * @returns {[]|*}
*/ */
export function getTableHeaderWithCustomFields(key, customFields, projectMembers = []) { export function getTableHeaderWithCustomFields(
key,
customFields,
projectMembers = []
) {
let fieldSetting = [...CUSTOM_TABLE_HEADER[key]]; let fieldSetting = [...CUSTOM_TABLE_HEADER[key]];
fieldSetting = JSON.parse(JSON.stringify(fieldSetting)); // 复制,国际化 fieldSetting = JSON.parse(JSON.stringify(fieldSetting)); // 复制,国际化
translateLabel(fieldSetting); translateLabel(fieldSetting);
let keys = getCustomFieldsKeys(customFields); let keys = getCustomFieldsKeys(customFields);
projectMembers.forEach(member => { projectMembers.forEach((member) => {
member['text'] = member.name; member["text"] = member.name;
// 高级搜索使用 // 高级搜索使用
member['label'] = member.name; member["label"] = member.name;
member['value'] = member.id; member["value"] = member.id;
member['showLabel'] = member.name + "(" + member.id + ")"; member["showLabel"] = member.name + "(" + member.id + ")";
}) });
customFields.forEach(item => { customFields.forEach((item) => {
if (!item.key) { if (!item.key) {
// 兼容旧版更新key // 兼容旧版更新key
item.key = generateTableHeaderKey(keys, customFields); item.key = generateTableHeaderKey(keys, customFields);
updateCustomFieldTemplate({id: item.id, key: item.key}); updateCustomFieldTemplate({ id: item.id, key: item.key });
} }
let field = { let field = {
id: item.name, id: item.name,
@ -330,10 +363,10 @@ export function getTableHeaderWithCustomFields(key, customFields, projectMembers
label: item.system ? i18n.t(SYSTEM_FIELD_NAME_MAP[item.name]) : item.name, label: item.system ? i18n.t(SYSTEM_FIELD_NAME_MAP[item.name]) : item.name,
type: item.type, type: item.type,
isCustom: true, isCustom: true,
sortable: ['richText', 'textarea'].indexOf(item.type) > -1 ? false : true, sortable: ["richText", "textarea"].indexOf(item.type) > -1 ? false : true,
columnKey: generateColumnKey(item), columnKey: generateColumnKey(item),
filters: getCustomFieldFilter(item) filters: getCustomFieldFilter(item),
} };
// 设置宽度 // 设置宽度
if (!field.minWidth) { if (!field.minWidth) {
field.minWidth = 25 + field.label.length * 16; field.minWidth = 25 + field.label.length * 16;
@ -345,7 +378,11 @@ export function getTableHeaderWithCustomFields(key, customFields, projectMembers
} }
} }
fieldSetting.push(field); fieldSetting.push(field);
if ((item.type === 'member' || item.type === 'multipleMember') && projectMembers && projectMembers.length > 0) { if (
(item.type === "member" || item.type === "multipleMember") &&
projectMembers &&
projectMembers.length > 0
) {
item.options = projectMembers; item.options = projectMembers;
} }
}); });
@ -354,8 +391,8 @@ export function getTableHeaderWithCustomFields(key, customFields, projectMembers
export function translateLabel(fieldSetting) { export function translateLabel(fieldSetting) {
if (fieldSetting) { if (fieldSetting) {
fieldSetting.forEach(item => { fieldSetting.forEach((item) => {
if (item.label) { if (item.label && !/^[A-Za-z]+$/.test(item.label)) {
item.label = i18n.t(item.label); item.label = i18n.t(item.label);
} }
}); });
@ -372,18 +409,18 @@ export function getAllFieldWithCustomFields(key, customFields) {
let fieldSetting = [...CUSTOM_TABLE_HEADER[key]]; let fieldSetting = [...CUSTOM_TABLE_HEADER[key]];
// 如果没有 license, 排除 xpack // 如果没有 license, 排除 xpack
if (!hasLicense()) { if (!hasLicense()) {
fieldSetting = fieldSetting.filter(v => !v.xpack); fieldSetting = fieldSetting.filter((v) => !v.xpack);
} }
fieldSetting = JSON.parse(JSON.stringify(fieldSetting)); fieldSetting = JSON.parse(JSON.stringify(fieldSetting));
translateLabel(fieldSetting); translateLabel(fieldSetting);
if (customFields) { if (customFields) {
customFields.forEach(item => { customFields.forEach((item) => {
let field = { let field = {
id: item.name, id: item.name,
key: item.key, key: item.key,
label: item.name, label: item.name,
isCustom: true isCustom: true,
} };
fieldSetting.push(field); fieldSetting.push(field);
}); });
} }
@ -396,22 +433,26 @@ export function getAllFieldWithCustomFields(key, customFields) {
* @param customFields * @param customFields
* @returns {*[]} * @returns {*[]}
*/ */
export function getAllDragOrCheckFieldWithCustomFields(fieldKey, fieldDragKey, customFields) { export function getAllDragOrCheckFieldWithCustomFields(
fieldKey,
fieldDragKey,
customFields
) {
let fieldSetting = [...CUSTOM_TABLE_HEADER[fieldKey]]; let fieldSetting = [...CUSTOM_TABLE_HEADER[fieldKey]];
// 如果没有 license, 排除 xpack // 如果没有 license, 排除 xpack
if (!hasLicense()) { if (!hasLicense()) {
fieldSetting = fieldSetting.filter(v => !v.xpack); fieldSetting = fieldSetting.filter((v) => !v.xpack);
} }
fieldSetting = JSON.parse(JSON.stringify(fieldSetting)); fieldSetting = JSON.parse(JSON.stringify(fieldSetting));
translateLabel(fieldSetting); translateLabel(fieldSetting);
if (customFields) { if (customFields) {
customFields.forEach(item => { customFields.forEach((item) => {
let field = { let field = {
id: item.name, id: item.name,
key: item.key, key: item.key,
label: item.name, label: item.name,
isCustom: true isCustom: true,
} };
fieldSetting.push(field); fieldSetting.push(field);
}); });
} }
@ -434,7 +475,7 @@ export function getAllDragOrCheckFieldWithCustomFields(fieldKey, fieldDragKey, c
} }
export function generateTableHeaderKey(keys) { export function generateTableHeaderKey(keys) {
let customFieldKeys = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; let customFieldKeys = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (let i = 0; i < customFieldKeys.length; i++) { for (let i = 0; i < customFieldKeys.length; i++) {
let key = customFieldKeys[i]; let key = customFieldKeys[i];
if (keys.has(key)) { if (keys.has(key)) {
@ -443,12 +484,12 @@ export function generateTableHeaderKey(keys) {
keys.add(key); keys.add(key);
return key; return key;
} }
return ''; return "";
} }
export function getCustomFieldsKeys(customFields) { export function getCustomFieldsKeys(customFields) {
let keys = new Set(); let keys = new Set();
customFields.forEach(item => { customFields.forEach((item) => {
if (item.key) { if (item.key) {
keys.add(item.key); keys.add(item.key);
} }
@ -463,9 +504,9 @@ export function getCustomFieldsKeys(customFields) {
* @param fields * @param fields
*/ */
export function saveCustomTableHeader(key, fields) { export function saveCustomTableHeader(key, fields) {
let result = ''; let result = "";
if (fields) { if (fields) {
fields.forEach(item => { fields.forEach((item) => {
result += item.key; result += item.key;
}); });
} }
@ -494,14 +535,13 @@ export function getLastTableSortField(key) {
return []; return [];
} }
/** /**
* 获取对应表格的列宽 * 获取对应表格的列宽
* @param key * @param key
* @returns {{}|any} * @returns {{}|any}
*/ */
export function getCustomTableWidth(key) { export function getCustomTableWidth(key) {
let fieldStr = localStorage.getItem(key + '_WITH'); let fieldStr = localStorage.getItem(key + "_WITH");
if (fieldStr !== null) { if (fieldStr !== null) {
let fields = JSON.parse(fieldStr); let fields = JSON.parse(fieldStr);
return fields; return fields;
@ -517,8 +557,8 @@ export function getCustomTableWidth(key) {
*/ */
export function saveCustomTableWidth(key, fieldKey, colWith) { export function saveCustomTableWidth(key, fieldKey, colWith) {
let fields = getCustomTableWidth(key); let fields = getCustomTableWidth(key);
fields[fieldKey] = colWith + ''; fields[fieldKey] = colWith + "";
localStorage.setItem(key + '_WITH', JSON.stringify(fields)); localStorage.setItem(key + "_WITH", JSON.stringify(fields));
} }
export const OPTION_LABEL_PREFIX = "optionLabel:"; export const OPTION_LABEL_PREFIX = "optionLabel:";
@ -536,28 +576,37 @@ export function getCustomFieldValue(row, field, members) {
let item = row.fields[i]; let item = row.fields[i];
if (item.id === field.id) { if (item.id === field.id) {
if (item.value === 0) { if (item.value === 0) {
return '0'; return "0";
} }
if (!item.value) { if (!item.value) {
return ''; return "";
} }
if (item.textValue && item.textValue.startsWith(OPTION_LABEL_PREFIX) && field.options) { if (
item.textValue &&
item.textValue.startsWith(OPTION_LABEL_PREFIX) &&
field.options
) {
// 处理 jira 远程搜索字段 // 处理 jira 远程搜索字段
if (item.value instanceof Array) { if (item.value instanceof Array) {
// 多选 // 多选
try { try {
let optionLabel = item.textValue.substring(OPTION_LABEL_PREFIX.length); let optionLabel = item.textValue.substring(
OPTION_LABEL_PREFIX.length
);
if (optionLabel) { if (optionLabel) {
let optionLabelMap = JSON.parse(optionLabel); let optionLabelMap = JSON.parse(optionLabel);
let label = ''; let label = "";
for (let j = 0; j < item.value.length; j++) { for (let j = 0; j < item.value.length; j++) {
let val = item.value[j]; let val = item.value[j];
let option = field.options.find(i => i.value === val); let option = field.options.find((i) => i.value === val);
if (option) { if (option) {
label += option.text + (j === item.value.length - 1 ? '' : ' , '); label +=
option.text + (j === item.value.length - 1 ? "" : " , ");
} else { } else {
label += optionLabelMap[val] + (j === item.value.length - 1 ? '' : ' , '); label +=
optionLabelMap[val] +
(j === item.value.length - 1 ? "" : " , ");
} }
} }
return label; return label;
@ -565,23 +614,25 @@ export function getCustomFieldValue(row, field, members) {
} catch (e) { } catch (e) {
console.error("getCustomFieldValue error ", e); console.error("getCustomFieldValue error ", e);
} }
} else if (field.options.filter(i => i.value === item.value).length < 1) { } else if (
field.options.filter((i) => i.value === item.value).length < 1
) {
// 单选 // 单选
return item.textValue.substring(OPTION_LABEL_PREFIX.length); return item.textValue.substring(OPTION_LABEL_PREFIX.length);
} }
} }
if (field.type === 'member') { if (field.type === "member") {
for (let j = 0; j < members.length; j++) { for (let j = 0; j < members.length; j++) {
let member = members[j]; let member = members[j];
if (member.id === item.value) { if (member.id === item.value) {
return member.name; return member.name;
} }
} }
} else if (field.type === 'multipleMember') { } else if (field.type === "multipleMember") {
let values = ''; let values = "";
if (item.value.length > 0) { if (item.value.length > 0) {
item.value.forEach(v => { item.value.forEach((v) => {
for (let j = 0; j < members.length; j++) { for (let j = 0; j < members.length; j++) {
let member = members[j]; let member = members[j];
if (member.id === v) { if (member.id === v) {
@ -593,7 +644,7 @@ export function getCustomFieldValue(row, field, members) {
}); });
} }
return values; return values;
} else if (['radio', 'select'].indexOf(field.type) > -1) { } else if (["radio", "select"].indexOf(field.type) > -1) {
if (field.options) { if (field.options) {
for (let j = 0; j < field.options.length; j++) { for (let j = 0; j < field.options.length; j++) {
let option = field.options[j]; let option = field.options[j];
@ -602,30 +653,33 @@ export function getCustomFieldValue(row, field, members) {
} }
} }
} }
} else if (['multipleSelect', 'checkbox'].indexOf(field.type) > -1) { } else if (["multipleSelect", "checkbox"].indexOf(field.type) > -1) {
let values = ''; let values = "";
try { try {
if (field.type === 'multipleSelect') { if (field.type === "multipleSelect") {
if (typeof (item.value) === 'string' || item.value instanceof String) { if (
typeof item.value === "string" ||
item.value instanceof String
) {
item.value = JSON.parse(item.value); item.value = JSON.parse(item.value);
} }
} }
item.value.forEach(v => { item.value.forEach((v) => {
for (let j = 0; j < field.options.length; j++) { for (let j = 0; j < field.options.length; j++) {
let option = field.options[j]; let option = field.options[j];
if (option.value === v) { if (option.value === v) {
values += (field.system ? i18n.t(option.text) : option.text); values += field.system ? i18n.t(option.text) : option.text;
values += " "; values += " ";
break; break;
} }
} }
}); });
} catch (e) { } catch (e) {
values = ''; values = "";
} }
return values; return values;
} else if (field.type === 'cascadingSelect') { } else if (field.type === "cascadingSelect") {
let val = ''; let val = "";
let options = field.options; let options = field.options;
for (const v of item.value) { for (const v of item.value) {
if (!options) break; if (!options) break;
@ -638,21 +692,21 @@ export function getCustomFieldValue(row, field, members) {
} }
} }
return val; return val;
} else if (field.type === 'multipleInput') { } else if (field.type === "multipleInput") {
let val = ''; let val = "";
if (!item.value || item.value === '') { if (!item.value || item.value === "") {
return val; return val;
} }
let mulArr = parseMultipleInputToArray(item.value) let mulArr = parseMultipleInputToArray(item.value);
mulArr.forEach(i => { mulArr.forEach((i) => {
val += i + ' '; val += i + " ";
}); });
return val; return val;
} else if (field.type === 'datetime') { } else if (field.type === "datetime") {
return datetimeFormat(item.value); return datetimeFormat(item.value);
} else if (field.type === 'date') { } else if (field.type === "date") {
return dateFormat(item.value); return dateFormat(item.value);
} else if (['richText', 'textarea'].indexOf(field.type) > -1) { } else if (["richText", "textarea"].indexOf(field.type) > -1) {
return item.textValue; return item.textValue;
} }
return item.value; return item.value;
@ -670,18 +724,18 @@ export function parseMultipleInputToArray(mulInputStr) {
if (mulInputStr instanceof Array) { if (mulInputStr instanceof Array) {
return mulInputStr; return mulInputStr;
} else if (mulInputStr.indexOf(",")) { } else if (mulInputStr.indexOf(",")) {
return mulInputStr.split(",") return mulInputStr.split(",");
} else if (mulInputStr.indexOf(";")) { } else if (mulInputStr.indexOf(";")) {
return mulInputStr.split(";") return mulInputStr.split(";");
} else if (mulInputStr.indexOf("")) { } else if (mulInputStr.indexOf("")) {
return mulInputStr.split("") return mulInputStr.split("");
} else if (mulInputStr.indexOf("")) { } else if (mulInputStr.indexOf("")) {
return mulInputStr.split("") return mulInputStr.split("");
} else if (mulInputStr.indexOf("|")) { } else if (mulInputStr.indexOf("|")) {
return mulInputStr.split("|") return mulInputStr.split("|");
} else { } else {
let mulArr = []; let mulArr = [];
mulArr.push(mulInputStr) mulArr.push(mulInputStr);
return mulArr; return mulArr;
} }
} }
@ -693,30 +747,34 @@ export function parseMultipleInputToArray(mulInputStr) {
* @param valueArr * @param valueArr
* @param members * @param members
*/ */
export function getCustomFieldBatchEditOption(customFields, typeArr, valueArr, members) { export function getCustomFieldBatchEditOption(
customFields,
customFields.forEach(item => { typeArr,
valueArr,
members
) {
customFields.forEach((item) => {
if (item.options) { if (item.options) {
typeArr.push({ typeArr.push({
id: item.id, id: item.id,
name: item.name, name: item.name,
uuid: item.id, uuid: item.id,
custom: "custom" + item.id custom: "custom" + item.id,
}); });
let options = []; let options = [];
if (['multipleMember', 'member'].indexOf(item.type) > -1) { if (["multipleMember", "member"].indexOf(item.type) > -1) {
members.forEach(member => { members.forEach((member) => {
options.push({ options.push({
id: member.id, id: member.id,
name: member.name name: member.name,
}); });
}); });
} else { } else {
item.options.forEach((option) => { item.options.forEach((option) => {
options.push({ options.push({
id: option.value, id: option.value,
name: option.system ? i18n.t(option.text) : option.text name: option.system ? i18n.t(option.text) : option.text,
}); });
}); });
} }
@ -726,9 +784,9 @@ export function getCustomFieldBatchEditOption(customFields, typeArr, valueArr, m
} }
export function parseCustomFilesForList(data) { export function parseCustomFilesForList(data) {
data.forEach(item => { data.forEach((item) => {
if (item.fields) { if (item.fields) {
item.fields.forEach(i => { item.fields.forEach((i) => {
parseCustomFilesForItem(i); parseCustomFilesForItem(i);
}); });
} }
@ -738,7 +796,9 @@ export function parseCustomFilesForList(data) {
export function parseCustomFilesForItem(data) { export function parseCustomFilesForItem(data) {
if (data.value) { if (data.value) {
// 自定义字段内容存在回车,换行符, 需转义. // 自定义字段内容存在回车,换行符, 需转义.
data.value = JSON.parse(data.value.replace(/\n/g,"\\n").replace(/\r/g,"\\r")); data.value = JSON.parse(
data.value.replace(/\n/g, "\\n").replace(/\r/g, "\\r")
);
} }
if (data.textValue && !data.textValue.startsWith(OPTION_LABEL_PREFIX)) { if (data.textValue && !data.textValue.startsWith(OPTION_LABEL_PREFIX)) {
data.value = data.textValue; data.value = data.textValue;
@ -756,17 +816,19 @@ export function clearShareDragParam() {
export function handleRowDrop(data, callback, msTableKey) { export function handleRowDrop(data, callback, msTableKey) {
setTimeout(() => { setTimeout(() => {
const tbody = document.querySelector(`#${msTableKey} .el-table__body-wrapper tbody`); const tbody = document.querySelector(
`#${msTableKey} .el-table__body-wrapper tbody`
);
if (!tbody) { if (!tbody) {
return; return;
} }
const dropBars = tbody.getElementsByClassName('table-row-drop-bar'); const dropBars = tbody.getElementsByClassName("table-row-drop-bar");
const msTable = document.getElementsByClassName('ms-table'); const msTable = document.getElementsByClassName("ms-table");
// 每次调用生成一个class // 每次调用生成一个class
// 避免增删列表数据时,回调函数中的 data 与实际 data 不一致 // 避免增删列表数据时,回调函数中的 data 与实际 data 不一致
let dropClass = 'table-row-drop-bar-random' + '_' + getUUID(); let dropClass = "table-row-drop-bar-random" + "_" + getUUID();
for (let i = 0; i < dropBars.length; i++) { for (let i = 0; i < dropBars.length; i++) {
dropBars[i].classList.add(dropClass); dropBars[i].classList.add(dropClass);
@ -777,23 +839,23 @@ export function handleRowDrop(data, callback, msTableKey) {
Sortable.create(tbody, { Sortable.create(tbody, {
handle: "." + dropClass, handle: "." + dropClass,
animation: 100, animation: 100,
onStart: function (/**Event*/evt) { onStart: function (/**Event*/ evt) {
// 解决拖拽时高亮阴影停留在原位置的问题 // 解决拖拽时高亮阴影停留在原位置的问题
if (msTable) { if (msTable) {
for (let i = 0; i < msTable.length; i++) { for (let i = 0; i < msTable.length; i++) {
msTable[i].classList.add('disable-hover'); msTable[i].classList.add("disable-hover");
} }
} }
}, },
onEnd({newIndex, oldIndex}) { onEnd({ newIndex, oldIndex }) {
let param = {}; let param = {};
param.moveId = shareDragParam.data[oldIndex].id; param.moveId = shareDragParam.data[oldIndex].id;
if (newIndex === 0) { if (newIndex === 0) {
param.moveMode = 'BEFORE'; param.moveMode = "BEFORE";
param.targetId = shareDragParam.data[0].id; param.targetId = shareDragParam.data[0].id;
} else { } else {
// 默认从后面添加 // 默认从后面添加
param.moveMode = 'AFTER'; param.moveMode = "AFTER";
if (newIndex < oldIndex) { if (newIndex < oldIndex) {
// 如果往前拖拽,则添加到当前下标的前一个元素后面 // 如果往前拖拽,则添加到当前下标的前一个元素后面
param.targetId = shareDragParam.data[newIndex - 1].id; param.targetId = shareDragParam.data[newIndex - 1].id;
@ -802,7 +864,11 @@ export function handleRowDrop(data, callback, msTableKey) {
param.targetId = shareDragParam.data[newIndex].id; param.targetId = shareDragParam.data[newIndex].id;
} }
} }
if (shareDragParam.data && shareDragParam.data.length > 1 && newIndex !== oldIndex) { if (
shareDragParam.data &&
shareDragParam.data.length > 1 &&
newIndex !== oldIndex
) {
const currRow = shareDragParam.data.splice(oldIndex, 1)[0]; const currRow = shareDragParam.data.splice(oldIndex, 1)[0];
shareDragParam.data.splice(newIndex, 0, currRow); shareDragParam.data.splice(newIndex, 0, currRow);
if (callback) { if (callback) {
@ -811,27 +877,31 @@ export function handleRowDrop(data, callback, msTableKey) {
} }
for (let i = 0; i < msTable.length; i++) { for (let i = 0; i < msTable.length; i++) {
msTable[i].classList.remove('disable-hover'); msTable[i].classList.remove("disable-hover");
}
} }
},
}); });
}, 100); }, 100);
} }
export function getCustomFieldFilter(field, userFilter) { export function getCustomFieldFilter(field, userFilter) {
if (field.type === 'multipleMember') { if (field.type === "multipleMember") {
return null; return null;
} }
if (field.type === 'member' && userFilter) { if (field.type === "member" && userFilter) {
return userFilter; return userFilter;
} }
let optionTypes = CUSTOM_FIELD_TYPE_OPTION let optionTypes = CUSTOM_FIELD_TYPE_OPTION.filter((x) => x.hasOption).map(
.filter(x => x.hasOption) (x) => x.value
.map(x => x.value); );
if (optionTypes.indexOf(field.type) > -1 && Array.isArray(field.options) && field.options.length > 0) { if (
field.options.forEach(item => { optionTypes.indexOf(field.type) > -1 &&
Array.isArray(field.options) &&
field.options.length > 0
) {
field.options.forEach((item) => {
if (item.system && i18n.t(item.text)) { if (item.system && i18n.t(item.text)) {
item.text = i18n.t(item.text); item.text = i18n.t(item.text);
} }
@ -840,4 +910,3 @@ export function getCustomFieldFilter(field, userFilter) {
} }
return null; return null;
} }