代码优化

This commit is contained in:
BianLzhaoMin 2026-02-03 09:00:38 +08:00
parent 110dea3969
commit 169d50e945
4 changed files with 357 additions and 137 deletions

View File

@ -179,7 +179,7 @@
<el-table-column
v-if="showAction && hasActions"
label="操作"
:width="actionWidth"
:width="dynamicActionWidth"
:fixed="actionFixed"
align="center"
class-name="action-column"
@ -187,6 +187,7 @@
<template #default="{ row, $index }">
<slot name="action" :row="row" :index="$index">
<!-- 前3个按钮直接显示 -->
<div class="action-column-container">
<template v-for="(action, idx) in visibleActions" :key="idx">
<!-- 有权限配置的按钮使用 v-hasPermi 指令 -->
<ComButton
@ -236,8 +237,65 @@
{{ action.label }}
</ComButton>
</template>
<el-dropdown
v-if="moreActions.length > 0"
@command="(cmd) => handleDropdownAction(cmd, row, $index)"
>
<el-button type="primary" link size="small">
更多<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<template
v-for="(action, idx) in moreActions"
:key="idx"
>
<el-dropdown-item
v-if="action.permission"
:command="{ action, row, index: $index }"
:disabled="
typeof action.disabled === 'function'
? action.disabled(row)
: action.disabled
"
v-hasPermi="action.permission"
>
{{ action.label }}
</el-dropdown-item>
<el-dropdown-item
v-else
:command="{ action, row, index: $index }"
:disabled="
typeof action.disabled === 'function'
? action.disabled(row)
: action.disabled
"
>
<!-- {{ action.label }} -->
<ComButton
:type="action.type || 'primary'"
:size="
computedSize === 'large'
? 'default'
: 'small'
"
:link="action.link !== false"
:plain="action.plain"
:disabled="action.disabled"
>
{{ action.label }}
</ComButton>
</el-dropdown-item>
</template>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
<!-- 超过3个按钮时使用弹出菜单 -->
<el-popover
<!-- <el-popover
v-if="moreActions.length > 0"
trigger="click"
placement="bottom-end"
@ -263,7 +321,7 @@
</template>
<div class="popover-menu-list">
<template v-for="(action, idx) in moreActions" :key="idx">
<!-- 有权限配置的菜单项使用 v-hasPermi 指令 -->
<div
v-if="action.permission"
v-hasPermi="action.permission"
@ -283,7 +341,7 @@
>
{{ action.label }}
</div>
<!-- 没有权限配置的菜单项不使用 v-hasPermi 指令兼容旧代码 -->
<div
v-else
class="popover-menu-item"
@ -304,7 +362,7 @@
</div>
</template>
</div>
</el-popover>
</el-popover> -->
</slot>
</template>
</el-table-column>
@ -411,6 +469,17 @@ const props = defineProps({
type: [String, Boolean],
default: 'right',
},
//
showMoreAction: {
type: Boolean,
default: false,
},
//
moreActionCount: {
type: Number,
default: 2,
},
//
pagination: {
type: Object,
@ -502,12 +571,83 @@ const hasActions = computed(() => {
// 3
const visibleActions = computed(() => {
return props.actionColumns.slice(0, 2)
if (props.showMoreAction) {
return props.actionColumns.slice(0, props.moreActionCount)
}
return props.actionColumns
// return props.actionColumns.slice(0, 2)
})
// 3
const moreActions = computed(() => {
return props.actionColumns.slice(2)
if (props.showMoreAction) {
return props.actionColumns.slice(props.moreActionCount)
}
return []
})
//
const dynamicActionWidth = computed(() => {
if (props.actionColumns.length === 0) {
return 120 //
}
// padding
// link14px7pxpadding16px
const getButtonWidth = (label) => {
if (!label) return 50 //
// 14px7px
let textWidth = 0
for (let i = 0; i < label.length; i++) {
const char = label[i]
//
if (/[\u4e00-\u9fa5\u3000-\u303f\uff00-\uffef]/.test(char)) {
textWidth += 18
} else {
textWidth += 7
}
}
const padding = 4 // padding
return Math.max(textWidth + padding) // 50px
}
//
const buttonGap = 0
// paddingpadding
const columnPadding = 0
if (props.showMoreAction) {
// moreActionCount + 1
const visibleCount = props.moreActionCount
const moreButtonLabel = '更多'
let totalWidth = columnPadding
//
for (let i = 0; i < Math.min(visibleCount, props.actionColumns.length); i++) {
const action = props.actionColumns[i]
totalWidth += getButtonWidth(action.label) + buttonGap
}
//
totalWidth += getButtonWidth(moreButtonLabel)
return Math.max(totalWidth, 120) // 120px
} else {
//
let totalWidth = columnPadding
props.actionColumns.forEach((action) => {
totalWidth += getButtonWidth(action.label) + buttonGap
})
//
if (props.actionColumns.length > 0) {
totalWidth -= buttonGap
}
return Math.max(totalWidth, 100) // 100px
}
})
//
@ -744,85 +884,35 @@ defineExpose({
/* 操作列按钮样式 */
:deep(.el-table__fixed-right) {
box-shadow: -2px 0 4px rgba(0, 0, 0, 0.1);
}
/* 操作列单元格样式 - 确保按钮水平对齐 */
:deep(.el-table__body-wrapper .el-table__body tbody tr td.action-column .cell),
:deep(.el-table__fixed-right .el-table__fixed-body-wrapper tbody tr td.action-column .cell) {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: nowrap;
gap: 8px;
white-space: nowrap;
}
.action-button-item {
flex-shrink: 0;
display: inline-flex;
align-items: center;
}
.more-action-button {
:deep(.el-icon--right) {
margin-left: 4px;
font-size: 12px;
vertical-align: middle;
/* 减小fixed right操作列的水平padding */
.el-table__cell:last-child {
.cell {
padding-left: 8px !important;
padding-right: 8px !important;
}
}
}
/* Popover 菜单样式 */
.popover-menu-list {
padding: 0;
margin: 0;
list-style: none;
/* 减小非fixed操作列的水平padding操作列通常是最后一列 */
:deep(.el-table__body-wrapper),
:deep(.el-table__header-wrapper) {
.el-table__body,
.el-table__header {
.el-table__row {
.el-table__cell:last-child {
.cell {
padding-left: 8px !important;
padding-right: 8px !important;
}
}
}
}
}
.popover-menu-item {
padding: 8px 20px;
.setting-icon {
cursor: pointer;
font-size: 14px;
color: #606266;
transition: all 0.2s;
line-height: 1.5;
white-space: nowrap;
user-select: none;
&:hover:not(.is-disabled) {
background-color: #ecf5ff;
color: #409eff;
}
&:active:not(.is-disabled) {
background-color: #d9ecff;
}
&.is-disabled {
color: #c0c4cc;
cursor: not-allowed;
opacity: 0.6;
}
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
}
:deep(.action-popover-menu) {
padding: 4px 0;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
border: 1px solid #e4e7ed;
background-color: #fff;
min-width: 120px;
}
:deep(.action-popover-menu .el-popover__title) {
display: none;
font-size: 16px;
}
.column-setting-container {
@ -895,4 +985,106 @@ defineExpose({
:deep(.sortable-chosen) {
background-color: #e0f2fe !important;
}
.action-column-container {
display: flex;
align-items: center;
justify-content: space-around;
position: relative;
.el-button {
margin-left: 0;
}
/* 修复el-dropdown悬停时的边框问题 */
:deep(.el-dropdown) {
display: inline-block;
.el-button {
border: none !important;
outline: none !important;
box-shadow: none !important;
&:hover,
&:focus,
&:active {
border: none !important;
outline: none !important;
box-shadow: none !important;
}
}
}
}
/* 隐藏el-dropdown的popper定位参考线和边框 */
:deep(.el-dropdown__popper) {
&::before,
&::after {
display: none !important;
content: none !important;
}
.el-popper__arrow {
display: none !important;
&::before,
&::after {
display: none !important;
content: none !important;
}
}
}
/* 修复下拉菜单的边框 */
:deep(.el-dropdown-menu) {
&::before,
&::after {
display: none !important;
content: none !important;
}
}
/* 确保操作列中的下拉按钮没有额外的边框或伪元素 */
.action-column-container :deep(.el-dropdown) {
position: relative;
&::before,
&::after {
display: none !important;
content: none !important;
}
.el-button {
position: relative;
border: none !important;
outline: none !important;
&::before,
&::after {
display: none !important;
content: none !important;
}
&:hover::before,
&:hover::after,
&:focus::before,
&:focus::after {
display: none !important;
content: none !important;
}
}
}
/* 修复表格单元格hover时可能显示的边框 */
:deep(.el-table__body-wrapper .el-table__row:hover) {
.el-table__cell:last-child {
.action-column-container {
&::before,
&::after {
display: none !important;
content: none !important;
}
}
}
}
</style>

View File

@ -24,6 +24,8 @@
:show-toolbar="showToolbar"
:show-action="showAction"
:action-columns="actionColumns"
:show-more-action="showMoreAction"
:more-action-count="moreActionCount"
@selection-change="handleSelectionChange"
@refresh="handleRefresh"
@pagination-change="handlePaginationChange"
@ -117,6 +119,16 @@ const props = defineProps({
type: Function,
default: null,
},
//
showMoreAction: {
type: Boolean,
default: false,
},
//
moreActionCount: {
type: Number,
default: 2,
},
//
defaultQueryParams: {
type: Object,

View File

@ -8,6 +8,8 @@
:load-data="listLoopSendAPI"
:show-toolbar="true"
:show-action="true"
:show-more-action="true"
:more-action-count="2"
:action-columns="actionColumns"
>
<template #toolbar>
@ -102,7 +104,7 @@ const actionColumns = [
{
label: '立即执行一次',
type: 'primary',
type: 'success',
link: true,
handler: (row) => {
runOneLoopMsgAPI({ id: row.id, jobId: row.jobId })
@ -119,7 +121,7 @@ const actionColumns = [
},
{
label: '编辑',
type: 'primary',
type: 'success',
link: true,
handler: (row) => {
router.push({
@ -138,13 +140,16 @@ const actionColumns = [
link: true,
handler: (row) => {
proxy.$modal.confirm('是否确认删除该循环发送任务?').then(async () => {
proxy.$modal
.confirm('是否确认删除该循环发送任务?')
.then(async () => {
const result = await delLoopSendAPI({ id: row.id, jobId: row.jobId })
if (result.code === 200) {
proxy.$modal.msgSuccess('删除成功')
comTableRef.value?.refresh()
}
})
.catch(() => {})
},
},
{

View File

@ -29,9 +29,16 @@
prop="orgName"
label="部门"
align="center"
width="180"
show-overflow-tooltip
/>
<el-table-column prop="phone" label="电话" align="center" width="130" />
<el-table-column
prop="updateTime"
label="提交时间"
align="center"
width="180"
/>
<el-table-column prop="sendTime" label="发送时间" align="center" width="180" />
<el-table-column prop="submitStatus" label="提交状态" align="center" />
<el-table-column label="发送状态" align="center" width="120">
@ -110,6 +117,10 @@ const tableColumns = [
prop: 'taskName',
label: '任务名称',
},
{
prop: 'loopTime',
label: '时间',
},
{
prop: 'msgType',
label: '短信类型',
@ -144,7 +155,7 @@ const actionColumns = [
const detailDialogConfig = reactive({
outerVisible: false,
outerTitle: '发送记录详情',
outerWidth: '1000px',
outerWidth: '80%',
minHeight: '400px',
maxHeight: '80vh',
})