167 lines
4.9 KiB
Vue
167 lines
4.9 KiB
Vue
<template>
|
|
<Popover
|
|
v-model:open="popoverOpen"
|
|
trigger="click"
|
|
placement="bottomRight"
|
|
:overlayClassName="`${prefixCls}__popover`"
|
|
@open-change="handleOpenChange"
|
|
>
|
|
<template #title>
|
|
<div :class="`${prefixCls}__title`">
|
|
<Checkbox :indeterminate="indeterminate" :checked="checkAll" @change="onCheckAllChange">列展示</Checkbox>
|
|
</div>
|
|
</template>
|
|
<template #content>
|
|
<div :class="`${prefixCls}__list`">
|
|
<CheckboxGroup v-model:value="draftCheckedList" :options="columnOptions" />
|
|
</div>
|
|
<div :class="`${prefixCls}__footer`">
|
|
<a-button size="small" @click="handleReset">重置</a-button>
|
|
<a-button size="small" type="primary" @click="handleSave">保存</a-button>
|
|
</div>
|
|
</template>
|
|
<a-tooltip title="列设置">
|
|
<a-button size="small" class="mixing-material-column-setting-btn" @click.stop>
|
|
<Icon icon="ant-design:setting-outlined" />
|
|
</a-button>
|
|
</a-tooltip>
|
|
</Popover>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { computed, ref, type PropType } from 'vue';
|
|
import { Popover, Checkbox } from 'ant-design-vue';
|
|
import type { CheckboxChangeEvent } from 'ant-design-vue/lib/checkbox/interface';
|
|
import { Icon } from '/@/components/Icon';
|
|
import { useMessage } from '/@/hooks/web/useMessage';
|
|
import {
|
|
MIXING_MATERIAL_LOCKED_COLUMN_KEYS,
|
|
getMixingMaterialColumnSettingItems,
|
|
saveMixingMaterialHiddenColumnKeys,
|
|
type MixingMaterialColumnSettingItem,
|
|
} from '../MesXslMixingSpec.data';
|
|
|
|
const CheckboxGroup = Checkbox.Group;
|
|
const prefixCls = 'mixing-material-column-setting';
|
|
const { createMessage } = useMessage();
|
|
|
|
const props = defineProps({
|
|
hiddenKeys: {
|
|
type: Array as PropType<string[]>,
|
|
default: () => [],
|
|
},
|
|
});
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'update:hiddenKeys', value: string[]): void;
|
|
(e: 'change', value: string[]): void;
|
|
}>();
|
|
|
|
const popoverOpen = ref(false);
|
|
const columnItems = ref<MixingMaterialColumnSettingItem[]>(getMixingMaterialColumnSettingItems());
|
|
const allKeys = computed(() => columnItems.value.map((item) => item.key));
|
|
const lockableKeys = computed(() => columnItems.value.filter((item) => !item.locked).map((item) => item.key));
|
|
const draftCheckedList = ref<string[]>([]);
|
|
|
|
const columnOptions = computed(() =>
|
|
columnItems.value.map((item) => ({
|
|
label: item.title,
|
|
value: item.key,
|
|
disabled: item.locked,
|
|
})),
|
|
);
|
|
|
|
const checkAll = computed(() => {
|
|
const keys = lockableKeys.value;
|
|
return keys.length > 0 && keys.every((key) => draftCheckedList.value.includes(key));
|
|
});
|
|
|
|
const indeterminate = computed(() => {
|
|
const keys = lockableKeys.value;
|
|
const checkedCount = keys.filter((key) => draftCheckedList.value.includes(key)).length;
|
|
return checkedCount > 0 && checkedCount < keys.length;
|
|
});
|
|
|
|
function ensureLockedChecked() {
|
|
const next = new Set(draftCheckedList.value);
|
|
MIXING_MATERIAL_LOCKED_COLUMN_KEYS.forEach((key) => next.add(key));
|
|
draftCheckedList.value = Array.from(next);
|
|
}
|
|
|
|
function syncDraftFromHidden(hiddenKeys: string[]) {
|
|
const hiddenSet = new Set(hiddenKeys || []);
|
|
draftCheckedList.value = allKeys.value.filter((key) => !hiddenSet.has(key));
|
|
ensureLockedChecked();
|
|
}
|
|
|
|
function buildHiddenKeysFromDraft() {
|
|
ensureLockedChecked();
|
|
return allKeys.value.filter((key) => !draftCheckedList.value.includes(key));
|
|
}
|
|
|
|
function handleOpenChange(open: boolean) {
|
|
if (open) {
|
|
syncDraftFromHidden(props.hiddenKeys);
|
|
}
|
|
}
|
|
|
|
function onCheckAllChange(e: CheckboxChangeEvent) {
|
|
draftCheckedList.value = e.target.checked ? [...allKeys.value] : [...MIXING_MATERIAL_LOCKED_COLUMN_KEYS];
|
|
}
|
|
|
|
function handleReset() {
|
|
draftCheckedList.value = [...allKeys.value];
|
|
}
|
|
|
|
function handleSave() {
|
|
const hiddenKeys = buildHiddenKeysFromDraft();
|
|
saveMixingMaterialHiddenColumnKeys(hiddenKeys);
|
|
emit('update:hiddenKeys', hiddenKeys);
|
|
emit('change', hiddenKeys);
|
|
createMessage.success('保存成功');
|
|
popoverOpen.value = false;
|
|
}
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.mixing-material-column-setting-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding-inline: 8px;
|
|
}
|
|
</style>
|
|
|
|
<style lang="less">
|
|
.mixing-material-column-setting__popover {
|
|
.mixing-material-column-setting__title {
|
|
min-width: 180px;
|
|
}
|
|
|
|
.mixing-material-column-setting__list {
|
|
max-height: 320px;
|
|
overflow-y: auto;
|
|
margin-bottom: 8px;
|
|
|
|
.ant-checkbox-group {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
}
|
|
|
|
.ant-checkbox-group-item {
|
|
margin-inline-start: 0;
|
|
white-space: nowrap;
|
|
}
|
|
}
|
|
|
|
.mixing-material-column-setting__footer {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 8px;
|
|
padding-top: 4px;
|
|
border-top: 1px solid #f0f0f0;
|
|
}
|
|
}
|
|
</style>
|