增加导出功能
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="visible"
|
||||
:title="title"
|
||||
width="560px"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
@closed="onClosed"
|
||||
>
|
||||
<div class="export-field-toolbar">
|
||||
<el-checkbox
|
||||
:model-value="allChecked"
|
||||
:indeterminate="indeterminate"
|
||||
@change="toggleAll"
|
||||
>全选</el-checkbox>
|
||||
<el-button link type="primary" @click="resetDefault">恢复默认</el-button>
|
||||
</div>
|
||||
<el-checkbox-group v-model="checked" class="export-field-grid">
|
||||
<el-checkbox
|
||||
v-for="f in fields"
|
||||
:key="f.prop"
|
||||
:value="f.prop"
|
||||
>{{ f.label }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<template #footer>
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" :disabled="!checked.length" @click="confirm">确定导出</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const props = defineProps({
|
||||
title: { type: String, default: '选择导出字段' },
|
||||
fields: { type: Array, default: () => [] },
|
||||
/** localStorage key to remember last selection */
|
||||
storageKey: { type: String, default: '' }
|
||||
})
|
||||
|
||||
const visible = ref(false)
|
||||
const checked = ref([])
|
||||
let resolveFn = null
|
||||
|
||||
const allProps = computed(() => (props.fields || []).map(f => f.prop).filter(Boolean))
|
||||
const allChecked = computed(() => allProps.value.length > 0 && checked.value.length === allProps.value.length)
|
||||
const indeterminate = computed(() => checked.value.length > 0 && checked.value.length < allProps.value.length)
|
||||
|
||||
function defaultChecked() {
|
||||
return allProps.value.slice()
|
||||
}
|
||||
|
||||
function loadStored() {
|
||||
if (!props.storageKey) return null
|
||||
try {
|
||||
const raw = localStorage.getItem(props.storageKey)
|
||||
if (!raw) return null
|
||||
const arr = JSON.parse(raw)
|
||||
if (!Array.isArray(arr)) return null
|
||||
const allow = new Set(allProps.value)
|
||||
return arr.map(String).filter(p => allow.has(p))
|
||||
} catch (e) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function saveStored(list) {
|
||||
if (!props.storageKey) return
|
||||
try {
|
||||
localStorage.setItem(props.storageKey, JSON.stringify(list || []))
|
||||
} catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
function toggleAll(val) {
|
||||
checked.value = val ? defaultChecked() : []
|
||||
}
|
||||
|
||||
function resetDefault() {
|
||||
checked.value = defaultChecked()
|
||||
}
|
||||
|
||||
function open() {
|
||||
const stored = loadStored()
|
||||
checked.value = (stored && stored.length) ? stored : defaultChecked()
|
||||
visible.value = true
|
||||
return new Promise(resolve => {
|
||||
resolveFn = resolve
|
||||
})
|
||||
}
|
||||
|
||||
function confirm() {
|
||||
if (!checked.value.length) {
|
||||
ElMessage.warning('请至少选择一个导出字段')
|
||||
return
|
||||
}
|
||||
// keep declaration order
|
||||
const allow = new Set(checked.value)
|
||||
const ordered = allProps.value.filter(p => allow.has(p))
|
||||
saveStored(ordered)
|
||||
visible.value = false
|
||||
if (resolveFn) {
|
||||
resolveFn(ordered)
|
||||
resolveFn = null
|
||||
}
|
||||
}
|
||||
|
||||
function onClosed() {
|
||||
if (resolveFn) {
|
||||
resolveFn(null)
|
||||
resolveFn = null
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.export-field-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.export-field-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 8px 12px;
|
||||
max-height: 360px;
|
||||
overflow: auto;
|
||||
}
|
||||
.export-field-grid :deep(.el-checkbox) {
|
||||
margin-right: 0;
|
||||
height: auto;
|
||||
white-space: normal;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user