feat: table标签列快捷编辑内容空/宽度编辑优化
This commit is contained in:
parent
85d098646e
commit
359bfa96f4
|
@ -29,8 +29,7 @@
|
|||
{{ t(item.locale) }}
|
||||
</div>
|
||||
<div v-if="Array.isArray(item.value)" class="pr-[24px]">
|
||||
<MsTagGroup v-if="item.value.length > 0" :tag-list="item.value" size="small" is-string-tag />
|
||||
<div v-else>-</div>
|
||||
<MsTagGroup :tag-list="item.value" size="small" is-string-tag />
|
||||
</div>
|
||||
<slot v-else :name="item.key" :value="item.value">
|
||||
<a-tooltip :content="item.value" :disabled="isEmpty(item.value)" :position="item.tooltipPosition">
|
||||
|
|
|
@ -67,12 +67,12 @@
|
|||
<a-table-column
|
||||
v-for="(item, idx) in currentColumns"
|
||||
:key="idx"
|
||||
:width="item.isTag || item.isStringTag ? columnLastWidthMap[item.dataIndex as string] : item.width"
|
||||
:width="item.isTag || item.isStringTag ? getColumnTagLastWidthMap(item) : item.width"
|
||||
:align="item.align"
|
||||
:fixed="item.fixed"
|
||||
:sortable="item.sortable"
|
||||
:filterable="item.filterable"
|
||||
:cell-class="item.cellClass"
|
||||
:cell-class="item.isTag || item.isStringTag ? `ms-tag-cell-class ${item.cellClass || ''}` : item.cellClass"
|
||||
:header-cell-class="`${item.filterConfig && hasSelectedFilter(item) ? 'header-cell-filter' : ''} ${
|
||||
item.headerCellClass
|
||||
}`"
|
||||
|
@ -143,20 +143,13 @@
|
|||
</template>
|
||||
<template v-else-if="item.isTag || item.isStringTag">
|
||||
<slot :name="item.slotName" v-bind="{ record, rowIndex, column, columnConfig: item }">
|
||||
<template
|
||||
v-if="!record[item.dataIndex as string] || (Array.isArray(record[item.dataIndex as string]) && record[item.dataIndex as string].length === 0)"
|
||||
>
|
||||
-
|
||||
</template>
|
||||
<template v-else>
|
||||
<MsTagGroup
|
||||
:is-string-tag="item.isStringTag"
|
||||
:tag-list="record[item.dataIndex as string]"
|
||||
type="primary"
|
||||
theme="outline"
|
||||
:tag-position="item.tagPosition"
|
||||
/>
|
||||
</template>
|
||||
<MsTagGroup
|
||||
:is-string-tag="item.isStringTag"
|
||||
:tag-list="record[item.dataIndex as string]"
|
||||
type="primary"
|
||||
theme="outline"
|
||||
:tag-position="item.tagPosition"
|
||||
/>
|
||||
</slot>
|
||||
</template>
|
||||
<template v-else-if="item.slotName === SpecialColumnEnum.OPERATION">
|
||||
|
@ -523,12 +516,25 @@
|
|||
|
||||
const columnLastWidthMap = ref<Record<string, any>>({});
|
||||
|
||||
function getColumnTagLastWidthMap(column: MsTableColumnData) {
|
||||
const editTgaMinColumnWidth = 200;
|
||||
// 如果是编辑列标签则最小宽度保留200
|
||||
if (column?.allowEditTag) {
|
||||
if (columnLastWidthMap.value[column.dataIndex as string] < editTgaMinColumnWidth) {
|
||||
return editTgaMinColumnWidth;
|
||||
}
|
||||
return columnLastWidthMap.value[column.dataIndex as string];
|
||||
}
|
||||
return columnLastWidthMap.value[column.dataIndex as string];
|
||||
}
|
||||
|
||||
// 获取单个标签的宽度
|
||||
const getTagWidth = (tag: Record<string, any>, lastText: string) => {
|
||||
const maxTagWidth = 144; // 单个标签最大宽度
|
||||
const spanPadding = 8; // 标签内边距
|
||||
const spanBorder = 2; // 标签边框
|
||||
const marginRight = 4; // 标签之间的间距
|
||||
const fillWidth = 8; // 填充宽度
|
||||
|
||||
const el = document.createElement('div');
|
||||
el.style.visibility = 'hidden';
|
||||
|
@ -542,7 +548,7 @@
|
|||
|
||||
// 衡量宽度后将元素移除
|
||||
document.body.removeChild(el);
|
||||
width = width > maxTagWidth ? maxTagWidth + marginRight : width + marginRight;
|
||||
width = width > maxTagWidth ? maxTagWidth + marginRight + fillWidth : width + marginRight + fillWidth;
|
||||
return width;
|
||||
};
|
||||
|
||||
|
@ -1163,6 +1169,13 @@
|
|||
color: var(--color-text-3);
|
||||
}
|
||||
}
|
||||
:deep(.arco-table-td.ms-tag-cell-class) {
|
||||
.arco-table-td-content {
|
||||
> div {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
|
|
|
@ -70,6 +70,8 @@ export interface MsTableColumnData extends TableColumnData {
|
|||
isCustomParam?: boolean;
|
||||
// 插槽表格过滤筛选数据item
|
||||
filterItem?: any;
|
||||
// 是否标签编辑列
|
||||
allowEditTag?: boolean;
|
||||
// 自定义属性
|
||||
[key: string]: any;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
<template>
|
||||
<div class="flex max-w-[440px] flex-row" @click="emit('click')">
|
||||
<div
|
||||
v-if="showTagList.length"
|
||||
:class="`tag-group-class ${props.allowEdit ? 'cursor-pointer' : ''}`"
|
||||
@click="emit('click')"
|
||||
>
|
||||
<MsTag v-for="tag of showTagList" :key="tag.id" :width="getTagWidth(tag)" :size="props.size" v-bind="attrs">
|
||||
{{ props.isStringTag ? tag : tag[props.nameKey] }}
|
||||
</MsTag>
|
||||
|
@ -15,6 +19,10 @@
|
|||
</MsTag>
|
||||
</a-tooltip>
|
||||
</div>
|
||||
<!-- 避免在标签为空时,增大点击区域快速编辑 -->
|
||||
<div v-else :class="`tag-group-class ${props.allowEdit ? 'min-h-[24px] cursor-pointer' : ''}`" @click="emit('click')">
|
||||
-
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -29,6 +37,7 @@
|
|||
nameKey?: string;
|
||||
isStringTag?: boolean; // 是否是字符串数组的标签
|
||||
size?: Size;
|
||||
allowEdit?: boolean;
|
||||
tagPosition?:
|
||||
| 'top'
|
||||
| 'tl'
|
||||
|
@ -83,4 +92,9 @@
|
|||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="less"></style>
|
||||
<style scoped lang="less">
|
||||
.tag-group-class {
|
||||
max-width: 440px;
|
||||
@apply flex w-full flex-row;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -428,13 +428,9 @@
|
|||
});
|
||||
}
|
||||
|
||||
watch(
|
||||
[() => props.activeModule, () => props.selectedProtocols],
|
||||
() => {
|
||||
loadMockList();
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
watch([() => props.activeModule, () => props.selectedProtocols], () => {
|
||||
loadMockList();
|
||||
});
|
||||
|
||||
const isActivated = computed(() => cacheStore.cacheViews.includes(CacheTabTypeEnum.API_TEST_MOCK_TABLE));
|
||||
|
||||
|
|
|
@ -92,6 +92,7 @@
|
|||
:tag-list="record.reviewNames"
|
||||
is-string-tag
|
||||
:show-num="1"
|
||||
allow-edit
|
||||
theme="outline"
|
||||
@click="record.showModuleTree = false"
|
||||
/>
|
||||
|
|
|
@ -44,19 +44,31 @@
|
|||
:tag-list="record.userRoles || []"
|
||||
type="primary"
|
||||
theme="outline"
|
||||
allow-edit
|
||||
@click="changeUser(record)"
|
||||
/>
|
||||
<a-select
|
||||
<MsSelect
|
||||
v-else
|
||||
v-model="record.selectUserList"
|
||||
:popup-visible="record.showUserSelect"
|
||||
multiple
|
||||
class="w-full max-w-[300px]"
|
||||
:max-tag-count="2"
|
||||
@popup-visible-change="(value) => userGroupChange(value, record)"
|
||||
>
|
||||
<a-option v-for="item of userGroupOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
||||
</a-select>
|
||||
v-model:model-value="record.selectUserList"
|
||||
v-model:loading="dialogLoading"
|
||||
:max-tag-count="1"
|
||||
class="w-full"
|
||||
:options="userGroupOptions"
|
||||
:search-keys="['name']"
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
allow-search
|
||||
:multiple="true"
|
||||
:placeholder="t('common.pleaseSelect')"
|
||||
:at-least-one="true"
|
||||
:fallback-option="
|
||||
(val:any) => ({
|
||||
label: userGroupOptions.find((e) => e.id === val)?.name || (val as string),
|
||||
value: val,
|
||||
})
|
||||
"
|
||||
@popup-visible-change="(value:boolean) => userGroupChange(value as boolean, record)"
|
||||
/>
|
||||
</template>
|
||||
<template #enable="{ record }">
|
||||
<div v-if="record.enable" class="flex items-center">
|
||||
|
@ -106,6 +118,7 @@
|
|||
import MsTagGroup from '@/components/pure/ms-tag/ms-tag-group.vue';
|
||||
import MsBatchModal from '@/components/business/ms-batch-modal/index.vue';
|
||||
import MsRemoveButton from '@/components/business/ms-remove-button/MsRemoveButton.vue';
|
||||
import MsSelect from '@/components/business/ms-select';
|
||||
import AddMemberModal from './addMemberModal.vue';
|
||||
import inviteModal from '@/views/setting/system/components/inviteModal.vue';
|
||||
|
||||
|
@ -173,6 +186,7 @@
|
|||
dataIndex: 'userRoles',
|
||||
showDrag: true,
|
||||
isTag: true,
|
||||
allowEditTag: true,
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
|
@ -345,24 +359,24 @@
|
|||
const batchModalRef = ref();
|
||||
// 添加到用户组
|
||||
const addUserGroup = async (target: string[]) => {
|
||||
const { selectedIds, excludeIds, selectAll } = batchParams.value;
|
||||
const params = {
|
||||
projectId: lastProjectId.value,
|
||||
userIds: batchParams.value.selectedIds || [],
|
||||
selectAll: !!selectAll,
|
||||
excludeIds: excludeIds || [],
|
||||
selectIds: selectedIds || [],
|
||||
roleIds: target,
|
||||
condition: {
|
||||
keyword: keyword.value,
|
||||
filter: {
|
||||
...propsRes.value.filter,
|
||||
roleIds: roleIds.value ? [roleIds.value] : [],
|
||||
},
|
||||
combine: batchParams.value.condition,
|
||||
},
|
||||
};
|
||||
try {
|
||||
const { selectedIds, excludeIds, selectAll } = batchParams.value;
|
||||
const params = {
|
||||
projectId: lastProjectId.value,
|
||||
userIds: batchParams.value.selectedIds || [],
|
||||
selectAll: !!selectAll,
|
||||
excludeIds: excludeIds || [],
|
||||
selectIds: selectedIds || [],
|
||||
roleIds: target,
|
||||
condition: {
|
||||
keyword: keyword.value,
|
||||
filter: {
|
||||
...propsRes.value.filter,
|
||||
roleIds: roleIds.value ? [roleIds.value] : [],
|
||||
},
|
||||
combine: batchParams.value.condition,
|
||||
},
|
||||
};
|
||||
await batchModalRef.value.batchRequestFun(addProjectUserGroup, params);
|
||||
resetSelector();
|
||||
initData();
|
||||
|
@ -393,15 +407,17 @@
|
|||
addMemberVisible.value = true;
|
||||
projectMemberRef.value.initProjectMemberOptions();
|
||||
};
|
||||
const dialogLoading = ref(false);
|
||||
|
||||
// 编辑项目成员
|
||||
const editProjectMember = async (record: ProjectMemberItem) => {
|
||||
const params: ActionProjectMember = {
|
||||
projectId: lastProjectId.value,
|
||||
userId: record.id,
|
||||
roleIds: record.selectUserList,
|
||||
};
|
||||
try {
|
||||
dialogLoading.value = true;
|
||||
const params: ActionProjectMember = {
|
||||
projectId: lastProjectId.value,
|
||||
userId: record.id,
|
||||
roleIds: record.selectUserList,
|
||||
};
|
||||
await addOrUpdateProjectMember(params);
|
||||
Message.success(t('project.member.batchUpdateSuccess'));
|
||||
record.showUserSelect = false;
|
||||
|
@ -409,6 +425,8 @@
|
|||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
} finally {
|
||||
dialogLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -42,23 +42,31 @@
|
|||
v-if="!record.showProjectSelect"
|
||||
:tag-list="record.projectIdNameMap || []"
|
||||
theme="outline"
|
||||
allow-edit
|
||||
@click="changeUserOrProject(record, 'project')"
|
||||
>
|
||||
</MsTagGroup>
|
||||
<a-select
|
||||
<MsSelect
|
||||
v-else
|
||||
v-model="record.selectProjectList"
|
||||
multiple
|
||||
:max-tag-count="2"
|
||||
size="small"
|
||||
class="w-full max-w-[300px]"
|
||||
:popup-visible="record.showProjectSelect"
|
||||
@change="(value) => selectUserOrProject(value, record, 'project')"
|
||||
@popup-visible-change="visibleChange($event, record, 'project')"
|
||||
>
|
||||
<a-option v-for="item of projectOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
||||
</a-select>
|
||||
<span v-if="(record.projectIdNameMap || []).length === 0">-</span>
|
||||
v-model:model-value="record.selectProjectList"
|
||||
v-model:loading="dialogLoading"
|
||||
:max-tag-count="1"
|
||||
class="w-full"
|
||||
:options="projectOptions"
|
||||
:search-keys="['name']"
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
allow-search
|
||||
:multiple="true"
|
||||
:placeholder="t('common.pleaseSelect')"
|
||||
:fallback-option="
|
||||
(val) => ({
|
||||
label: projectOptions.find((e) => e.id === val)?.name || (val as string),
|
||||
value: val,
|
||||
})
|
||||
"
|
||||
@popup-visible-change="(value) => visibleChange(value, record, 'project')"
|
||||
/>
|
||||
</template>
|
||||
<template #userRoleIdNameMap="{ record }">
|
||||
<MsTagGroup
|
||||
|
@ -66,22 +74,32 @@
|
|||
:tag-list="record.userRoleIdNameMap || []"
|
||||
type="primary"
|
||||
theme="outline"
|
||||
allow-edit
|
||||
@click="changeUserOrProject(record, 'user')"
|
||||
>
|
||||
</MsTagGroup>
|
||||
<a-select
|
||||
<MsSelect
|
||||
v-else
|
||||
v-model="record.selectUserList"
|
||||
multiple
|
||||
:max-tag-count="2"
|
||||
class="w-full max-w-[300px]"
|
||||
:popup-visible="record.showUserSelect"
|
||||
@change="(value) => selectUserOrProject(value, record, 'user')"
|
||||
v-model:model-value="record.selectUserList"
|
||||
v-model:loading="dialogLoading"
|
||||
:max-tag-count="1"
|
||||
class="w-full"
|
||||
:options="userGroupOptions"
|
||||
:search-keys="['name']"
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
allow-search
|
||||
:multiple="true"
|
||||
:placeholder="t('common.pleaseSelect')"
|
||||
:at-least-one="true"
|
||||
:fallback-option="
|
||||
(val) => ({
|
||||
label: userGroupOptions.find((e) => e.id === val)?.name || (val as string),
|
||||
value: val,
|
||||
})
|
||||
"
|
||||
@popup-visible-change="(value) => visibleChange(value, record, 'user')"
|
||||
>
|
||||
<a-option v-for="item of userGroupOptions" :key="item.id" :value="item.id">{{ item.name }}</a-option>
|
||||
</a-select>
|
||||
<span v-if="(record.userRoleIdNameMap || []).length === 0">-</span>
|
||||
/>
|
||||
</template>
|
||||
<template #enable="{ record }">
|
||||
<div v-if="record.enable" class="flex items-center">
|
||||
|
@ -94,9 +112,9 @@
|
|||
</div>
|
||||
</template>
|
||||
<template #action="{ record }">
|
||||
<MsButton v-permission="['ORGANIZATION_MEMBER:READ+UPDATE']" @click="addOrEditMember('edit', record)">{{
|
||||
t('organization.member.edit')
|
||||
}}</MsButton>
|
||||
<MsButton v-permission="['ORGANIZATION_MEMBER:READ+UPDATE']" @click="addOrEditMember('edit', record)">
|
||||
{{ t('organization.member.edit') }}
|
||||
</MsButton>
|
||||
<MsRemoveButton
|
||||
v-permission="['ORGANIZATION_MEMBER:READ+DELETE']"
|
||||
position="br"
|
||||
|
@ -146,6 +164,7 @@
|
|||
import MsTagGroup from '@/components/pure/ms-tag/ms-tag-group.vue';
|
||||
import MSBatchModal from '@/components/business/ms-batch-modal/index.vue';
|
||||
import MsRemoveButton from '@/components/business/ms-remove-button/MsRemoveButton.vue';
|
||||
import MsSelect from '@/components/business/ms-select';
|
||||
import AddMemberModal from './components/addMemberModal.vue';
|
||||
import inviteModal from '@/views/setting/system/components/inviteModal.vue';
|
||||
|
||||
|
@ -216,6 +235,7 @@
|
|||
showInTable: true,
|
||||
showDrag: true,
|
||||
isTag: true,
|
||||
allowEditTag: true,
|
||||
},
|
||||
{
|
||||
title: 'organization.member.tableColunmUsergroup',
|
||||
|
@ -224,6 +244,7 @@
|
|||
showInTable: true,
|
||||
isTag: true,
|
||||
showDrag: true,
|
||||
allowEditTag: true,
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
|
@ -278,6 +299,7 @@
|
|||
}
|
||||
);
|
||||
const keyword = ref('');
|
||||
const dialogLoading = ref(false);
|
||||
const tableSelected = ref<(string | number)[]>([]);
|
||||
// 跨页多选
|
||||
const selectedData = ref<string[] | undefined>([]);
|
||||
|
@ -387,6 +409,7 @@
|
|||
// 列表编辑更新用户组和项目
|
||||
const updateUserOrProject = async (record: MemberItem) => {
|
||||
try {
|
||||
dialogLoading.value = true;
|
||||
const params = {
|
||||
organizationId: lastOrganizationId.value,
|
||||
projectIds: [...record.selectProjectList],
|
||||
|
@ -403,6 +426,7 @@
|
|||
} finally {
|
||||
record.showUserSelect = false;
|
||||
record.showProjectSelect = false;
|
||||
dialogLoading.value = false;
|
||||
}
|
||||
};
|
||||
// 编辑模式和下拉选择切换
|
||||
|
@ -423,17 +447,6 @@
|
|||
record.selectProjectList = (record.projectIdNameMap || []).map((item) => item.id);
|
||||
record.selectUserList = (record.userRoleIdNameMap || []).map((item) => item.id);
|
||||
};
|
||||
// 用户和项目选择改变的回调
|
||||
const selectUserOrProject = (value: any, record: MemberItem, type: string) => {
|
||||
if (!hasAnyPermission(['ORGANIZATION_MEMBER:READ+UPDATE'])) {
|
||||
return;
|
||||
}
|
||||
if (type === 'project') {
|
||||
record.selectProjectList = value;
|
||||
} else {
|
||||
record.selectUserList = value;
|
||||
}
|
||||
};
|
||||
// 面板切换的回调
|
||||
const visibleChange = (visible: boolean, record: MemberItem, type: string) => {
|
||||
const originMapIds =
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
:tag-list="record.userRoleList"
|
||||
type="primary"
|
||||
theme="outline"
|
||||
allow-edit
|
||||
@click="handleTagClick(record)"
|
||||
/>
|
||||
<MsSelect
|
||||
|
@ -132,6 +133,7 @@
|
|||
label: (val as Record<string, any>).name,
|
||||
value: val,
|
||||
})"
|
||||
class="w-full"
|
||||
:object-value="true"
|
||||
value-key="id"
|
||||
label-key="name"
|
||||
|
@ -379,6 +381,7 @@
|
|||
slotName: 'userGroup',
|
||||
isTag: true,
|
||||
showDrag: true,
|
||||
allowEditTag: true,
|
||||
width: 300,
|
||||
},
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue