代码优化

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 <el-table-column
v-if="showAction && hasActions" v-if="showAction && hasActions"
label="操作" label="操作"
:width="actionWidth" :width="dynamicActionWidth"
:fixed="actionFixed" :fixed="actionFixed"
align="center" align="center"
class-name="action-column" class-name="action-column"
@ -187,6 +187,7 @@
<template #default="{ row, $index }"> <template #default="{ row, $index }">
<slot name="action" :row="row" :index="$index"> <slot name="action" :row="row" :index="$index">
<!-- 前3个按钮直接显示 --> <!-- 前3个按钮直接显示 -->
<div class="action-column-container">
<template v-for="(action, idx) in visibleActions" :key="idx"> <template v-for="(action, idx) in visibleActions" :key="idx">
<!-- 有权限配置的按钮使用 v-hasPermi 指令 --> <!-- 有权限配置的按钮使用 v-hasPermi 指令 -->
<ComButton <ComButton
@ -236,8 +237,65 @@
{{ action.label }} {{ action.label }}
</ComButton> </ComButton>
</template> </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个按钮时使用弹出菜单 --> <!-- 超过3个按钮时使用弹出菜单 -->
<el-popover <!-- <el-popover
v-if="moreActions.length > 0" v-if="moreActions.length > 0"
trigger="click" trigger="click"
placement="bottom-end" placement="bottom-end"
@ -263,7 +321,7 @@
</template> </template>
<div class="popover-menu-list"> <div class="popover-menu-list">
<template v-for="(action, idx) in moreActions" :key="idx"> <template v-for="(action, idx) in moreActions" :key="idx">
<!-- 有权限配置的菜单项使用 v-hasPermi 指令 -->
<div <div
v-if="action.permission" v-if="action.permission"
v-hasPermi="action.permission" v-hasPermi="action.permission"
@ -283,7 +341,7 @@
> >
{{ action.label }} {{ action.label }}
</div> </div>
<!-- 没有权限配置的菜单项不使用 v-hasPermi 指令兼容旧代码 -->
<div <div
v-else v-else
class="popover-menu-item" class="popover-menu-item"
@ -304,7 +362,7 @@
</div> </div>
</template> </template>
</div> </div>
</el-popover> </el-popover> -->
</slot> </slot>
</template> </template>
</el-table-column> </el-table-column>
@ -411,6 +469,17 @@ const props = defineProps({
type: [String, Boolean], type: [String, Boolean],
default: 'right', default: 'right',
}, },
//
showMoreAction: {
type: Boolean,
default: false,
},
//
moreActionCount: {
type: Number,
default: 2,
},
// //
pagination: { pagination: {
type: Object, type: Object,
@ -502,12 +571,83 @@ const hasActions = computed(() => {
// 3 // 3
const visibleActions = computed(() => { 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 // 3
const moreActions = computed(() => { 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) { :deep(.el-table__fixed-right) {
box-shadow: -2px 0 4px rgba(0, 0, 0, 0.1); box-shadow: -2px 0 4px rgba(0, 0, 0, 0.1);
}
/* 操作列单元格样式 - 确保按钮水平对齐 */ /* 减小fixed right操作列的水平padding */
:deep(.el-table__body-wrapper .el-table__body tbody tr td.action-column .cell), .el-table__cell:last-child {
:deep(.el-table__fixed-right .el-table__fixed-body-wrapper tbody tr td.action-column .cell) { .cell {
display: flex; padding-left: 8px !important;
align-items: center; padding-right: 8px !important;
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;
} }
} }
/* Popover 菜单样式 */ /* 减小非fixed操作列的水平padding操作列通常是最后一列 */
.popover-menu-list { :deep(.el-table__body-wrapper),
padding: 0; :deep(.el-table__header-wrapper) {
margin: 0; .el-table__body,
list-style: none; .el-table__header {
.el-table__row {
.el-table__cell:last-child {
.cell {
padding-left: 8px !important;
padding-right: 8px !important;
}
}
}
}
} }
.popover-menu-item { .setting-icon {
padding: 8px 20px;
cursor: pointer; cursor: pointer;
font-size: 14px; font-size: 16px;
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;
} }
.column-setting-container { .column-setting-container {
@ -895,4 +985,106 @@ defineExpose({
:deep(.sortable-chosen) { :deep(.sortable-chosen) {
background-color: #e0f2fe !important; 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> </style>

View File

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

View File

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

View File

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