Skip to content

Commit cd69e92

Browse files
author
Taois
committed
feat:优化多选和单选
1 parent b122278 commit cd69e92

File tree

1 file changed

+200
-32
lines changed

1 file changed

+200
-32
lines changed

dashboard/src/components/actions/MultiInputAction.vue

Lines changed: 200 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@
6363

6464
<!-- 输入区域 -->
6565
<div class="input-group">
66-
<!-- 快速选择 - 在输入框上方,只显示非特殊选择器 -->
67-
<div v-if="input.selectData && hasNonSpecialOptions(input.selectData)" class="quick-select">
66+
<!-- 快速选择 - 在输入框上方,只显示非特殊选择器,且非多选模式 -->
67+
<div v-if="input.selectData && hasNonSpecialOptions(input.selectData) && !input.multiSelect" class="quick-select">
6868
<div class="quick-select-options">
6969
<button
7070
v-for="option in getNonSpecialOptions(input.selectData)"
@@ -429,34 +429,72 @@
429429
<!-- 选项弹窗 -->
430430
<ActionDialog
431431
:visible="showSelectOptions"
432-
title="请选择"
433-
:width="400"
432+
:title="isMultiSelectMode ? '请选择字母' : '请选择'"
433+
:width="isMultiSelectMode ? (currentSelectColumn * 160 + 200) : 400"
434434
@close="showSelectOptions = false"
435435
>
436436
<div class="select-options-content">
437-
<a-radio-group
438-
v-model="selectedRadioValue"
439-
@change="handleRadioChange"
440-
direction="vertical"
441-
class="radio-options-list"
442-
>
443-
<a-radio
444-
v-for="option in currentSelectOptions"
445-
:key="option.value"
446-
:value="option.value"
447-
class="radio-option-item"
437+
<!-- 单选模式 -->
438+
<div v-if="!isMultiSelectMode" class="radio-container">
439+
<a-radio-group
440+
v-model="selectedRadioValue"
441+
@change="handleRadioChange"
442+
direction="vertical"
443+
class="radio-options-list"
448444
>
449-
{{ option.name }}
450-
</a-radio>
451-
</a-radio-group>
445+
<a-radio
446+
v-for="option in currentSelectOptions"
447+
:key="option.value"
448+
:value="option.value"
449+
class="radio-option-item"
450+
>
451+
{{ option.name }}
452+
</a-radio>
453+
</a-radio-group>
454+
</div>
455+
456+
<!-- 多选模式 -->
457+
<div v-else class="multiselect-container">
458+
<div class="multiselect-main">
459+
<a-checkbox-group
460+
v-model="selectedCheckboxValues"
461+
class="checkbox-grid"
462+
:style="{ gridTemplateColumns: `repeat(${currentSelectColumn}, 1fr)` }"
463+
>
464+
<a-checkbox
465+
v-for="option in currentSelectOptions"
466+
:key="option.value"
467+
:value="option.value"
468+
class="checkbox-option-item"
469+
>
470+
{{ option.name }}
471+
</a-checkbox>
472+
</a-checkbox-group>
473+
</div>
474+
475+
<div class="multiselect-actions">
476+
<button class="btn-modern btn-secondary btn-small" @click="selectAll">
477+
全选
478+
</button>
479+
<button class="btn-modern btn-secondary btn-small" @click="clearSelection">
480+
全清
481+
</button>
482+
<button class="btn-modern btn-secondary btn-small" @click="invertSelection">
483+
反选
484+
</button>
485+
<button class="btn-modern btn-primary btn-small" @click="confirmMultiSelection">
486+
确定
487+
</button>
488+
</div>
489+
</div>
452490
</div>
453491

454-
<template #footer>
492+
<template #footer v-if="!isMultiSelectMode">
455493
<div class="modern-footer">
456494
<button class="btn-modern btn-secondary" @click="showSelectOptions = false">
457495
取消
458496
</button>
459-
<button class="btn-modern btn-primary" @click="confirmSelection">
497+
<button class="btn-modern btn-primary" @click="confirmRadioSelection">
460498
确认
461499
</button>
462500
</div>
@@ -477,15 +515,17 @@ import { executeAction } from '@/api/modules/module.js'
477515
import { showToast } from '@/stores/toast.js'
478516
import siteService from '@/api/services/site'
479517
import { useRouter } from 'vue-router'
480-
import { DatePicker, Radio, RadioGroup } from '@arco-design/web-vue'
518+
import { DatePicker, Radio, RadioGroup, Checkbox, CheckboxGroup } from '@arco-design/web-vue'
481519
482520
export default {
483521
name: 'MultiInputAction',
484522
components: {
485523
ActionDialog,
486524
DatePicker,
487525
'a-radio': Radio,
488-
'a-radio-group': RadioGroup
526+
'a-radio-group': RadioGroup,
527+
'a-checkbox': Checkbox,
528+
'a-checkbox-group': CheckboxGroup
489529
},
490530
props: {
491531
config: {
@@ -536,6 +576,11 @@ export default {
536576
const currentSelectIndex = ref(-1)
537577
const currentSelectOptions = ref([])
538578
const selectedRadioValue = ref('')
579+
580+
// 多选相关
581+
const selectedCheckboxValues = ref([])
582+
const isMultiSelectMode = ref(false)
583+
const currentSelectColumn = ref(4)
539584
540585
// 帮助弹窗相关
541586
const showHelpDialog = ref(false)
@@ -1036,8 +1081,20 @@ export default {
10361081
if (input.selectData) {
10371082
currentSelectIndex.value = index
10381083
currentSelectOptions.value = parseSelectData(input.selectData)
1039-
// 设置当前选中的值
1040-
selectedRadioValue.value = inputValues.value[index] || ''
1084+
1085+
// 判断是否为多选模式
1086+
isMultiSelectMode.value = input.multiSelect === true
1087+
currentSelectColumn.value = input.selectColumn || 4
1088+
1089+
if (isMultiSelectMode.value) {
1090+
// 多选模式:解析已选中的值
1091+
const currentValue = inputValues.value[index] || ''
1092+
selectedCheckboxValues.value = currentValue ? currentValue.split(',').map(v => v.trim()).filter(v => v) : []
1093+
} else {
1094+
// 单选模式:设置当前选中的值
1095+
selectedRadioValue.value = inputValues.value[index] || ''
1096+
}
1097+
10411098
showSelectOptions.value = true
10421099
}
10431100
}
@@ -1061,14 +1118,55 @@ export default {
10611118
}
10621119
}
10631120
1064-
// 确认选择
1065-
const confirmSelection = () => {
1121+
// 确认单选
1122+
const confirmRadioSelection = () => {
10661123
showSelectOptions.value = false
10671124
currentSelectIndex.value = -1
10681125
currentSelectOptions.value = []
10691126
selectedRadioValue.value = ''
10701127
}
10711128
1129+
1130+
1131+
1132+
1133+
1134+
1135+
// 全选
1136+
const selectAll = () => {
1137+
selectedCheckboxValues.value = currentSelectOptions.value.map(option => option.value)
1138+
}
1139+
1140+
// 全清选择
1141+
const clearSelection = () => {
1142+
selectedCheckboxValues.value = []
1143+
}
1144+
1145+
// 反选
1146+
const invertSelection = () => {
1147+
const allValues = currentSelectOptions.value.map(option => option.value)
1148+
selectedCheckboxValues.value = allValues.filter(value => !selectedCheckboxValues.value.includes(value))
1149+
}
1150+
1151+
// 确认选择(单选和多选)
1152+
const confirmMultiSelection = () => {
1153+
if (currentSelectIndex.value >= 0) {
1154+
if (isMultiSelectMode.value) {
1155+
// 多选模式:将选中的值用逗号连接
1156+
inputValues.value[currentSelectIndex.value] = selectedCheckboxValues.value.join(',')
1157+
} else {
1158+
// 单选模式:只取第一个值
1159+
inputValues.value[currentSelectIndex.value] = selectedCheckboxValues.value[0] || ''
1160+
}
1161+
validateInput(currentSelectIndex.value)
1162+
}
1163+
showSelectOptions.value = false
1164+
currentSelectIndex.value = -1
1165+
currentSelectOptions.value = []
1166+
selectedCheckboxValues.value = []
1167+
isMultiSelectMode.value = false
1168+
}
1169+
10721170
// 判断是否为特殊选择器
10731171
const isSpecialSelector = (value) => {
10741172
return value && value.startsWith('[') && value.endsWith(']')
@@ -1388,8 +1486,16 @@ export default {
13881486
openSelectOptions,
13891487
selectOption,
13901488
handleRadioChange,
1391-
confirmSelection,
1489+
confirmRadioSelection,
13921490
isOptionSelected,
1491+
// 多选相关
1492+
selectedCheckboxValues,
1493+
isMultiSelectMode,
1494+
currentSelectColumn,
1495+
selectAll,
1496+
clearSelection,
1497+
invertSelection,
1498+
confirmMultiSelection,
13931499
// 帮助弹窗
13941500
showHelpDialog,
13951501
helpContent,
@@ -2436,11 +2542,21 @@ export default {
24362542
padding: 16px;
24372543
}
24382544
2545+
/* 单选容器样式 */
2546+
.radio-container {
2547+
max-height: 400px;
2548+
overflow-y: auto;
2549+
border: 1px solid var(--ds-border, #d0d7de);
2550+
border-radius: 8px;
2551+
background: var(--ds-surface, #ffffff);
2552+
padding: 8px;
2553+
}
2554+
24392555
.radio-options-list {
24402556
width: 100%;
24412557
display: flex;
24422558
flex-direction: column;
2443-
gap: 8px;
2559+
gap: 4px;
24442560
}
24452561
24462562
.radio-option-item {
@@ -2475,11 +2591,11 @@ export default {
24752591
24762592
.radio-options-list :deep(.arco-radio .arco-radio-label) {
24772593
width: 100%;
2478-
padding: 12px 16px;
2594+
padding: 8px 12px;
24792595
margin: 0;
24802596
color: var(--ds-text, #24292f);
2481-
font-size: 14px;
2482-
line-height: 1.5;
2597+
font-size: 13px;
2598+
line-height: 1.4;
24832599
cursor: pointer;
24842600
}
24852601
@@ -2489,7 +2605,7 @@ export default {
24892605
}
24902606
24912607
.radio-options-list :deep(.arco-radio .arco-radio-button) {
2492-
margin: 8px 0 8px 12px;
2608+
margin: 6px 0 6px 10px;
24932609
}
24942610
24952611
.radio-options-list :deep(.arco-radio .arco-radio-button::after) {
@@ -2500,4 +2616,56 @@ export default {
25002616
border-color: var(--ds-border-accent, #3b82f6);
25012617
background-color: var(--ds-background-accent, #3b82f6);
25022618
}
2619+
2620+
/* 多选相关样式 */
2621+
.multiselect-container {
2622+
display: flex;
2623+
gap: 16px;
2624+
min-height: 300px;
2625+
}
2626+
2627+
.multiselect-main {
2628+
flex: 1;
2629+
}
2630+
2631+
.checkbox-grid {
2632+
display: grid;
2633+
gap: 12px 16px;
2634+
padding: 8px;
2635+
}
2636+
2637+
.checkbox-option-item {
2638+
padding: 8px 12px;
2639+
border: 1px solid var(--ds-border, #d1d5db);
2640+
border-radius: 6px;
2641+
background: var(--ds-background, #ffffff);
2642+
transition: all 0.2s ease;
2643+
cursor: pointer;
2644+
font-size: 14px;
2645+
}
2646+
2647+
.checkbox-option-item:hover {
2648+
border-color: var(--ds-border-accent, #3b82f6);
2649+
background: var(--ds-background-hover, #f8fafc);
2650+
}
2651+
2652+
.checkbox-option-item :deep(.arco-checkbox-checked .arco-checkbox-icon) {
2653+
background-color: var(--ds-background-accent, #3b82f6);
2654+
border-color: var(--ds-border-accent, #3b82f6);
2655+
}
2656+
2657+
.multiselect-actions {
2658+
display: flex;
2659+
flex-direction: column;
2660+
gap: 8px;
2661+
min-width: 80px;
2662+
padding: 8px;
2663+
}
2664+
2665+
.btn-small {
2666+
padding: 6px 12px;
2667+
font-size: 12px;
2668+
min-height: 32px;
2669+
white-space: nowrap;
2670+
}
25032671
</style>

0 commit comments

Comments
 (0)