Модуль отчетов
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
<script setup>
|
||||
import { NSelect, NInput, NTransfer, NDynamicInput, NFlex, NText, NEmpty, NFormItem, NForm } from 'naive-ui'
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
section: { type: Object, required: true },
|
||||
sources: { type: Array, default: () => [] },
|
||||
})
|
||||
|
||||
const sourceOptions = computed(() => props.sources.map(s => ({ label: s.label, value: s.key })))
|
||||
|
||||
const selectedSource = computed(() => props.sources.find(s => s.key === props.section.source) ?? null)
|
||||
|
||||
const columnTransferOptions = computed(() => Object.entries(selectedSource.value?.columns ?? {})
|
||||
.map(([value, label]) => ({ label, value })))
|
||||
|
||||
const filterableFieldOptions = computed(() => Object.entries(selectedSource.value?.filterableFields ?? {})
|
||||
.map(([value, def]) => ({ label: def.label, value })))
|
||||
|
||||
const filterValueOptions = (fieldKey) => {
|
||||
const options = selectedSource.value?.filterableFields?.[fieldKey]?.options
|
||||
return options ? Object.entries(options).map(([value, label]) => ({ label, value })) : null
|
||||
}
|
||||
|
||||
const createFilter = () => ({
|
||||
field: filterableFieldOptions.value[0]?.value ?? null,
|
||||
value: null,
|
||||
})
|
||||
|
||||
const onSourceChange = () => {
|
||||
// Колонки и фильтры принадлежат конкретному источнику — при смене источника они теряют смысл
|
||||
props.section.columns = []
|
||||
props.section.filters = []
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NFlex vertical :size="12" style="width: 100%;">
|
||||
<NForm label-placement="top">
|
||||
<NFlex :size="12" :wrap="true">
|
||||
<NFormItem label="Источник данных" style="min-width: 240px; margin-bottom: 0;">
|
||||
<NSelect v-model:value="section.source" :options="sourceOptions" @update:value="onSourceChange" />
|
||||
</NFormItem>
|
||||
<NFormItem label="Заголовок секции" style="min-width: 240px; flex: 1; margin-bottom: 0;">
|
||||
<NInput v-model:value="section.title" :placeholder="selectedSource?.label" />
|
||||
</NFormItem>
|
||||
</NFlex>
|
||||
</NForm>
|
||||
|
||||
<div>
|
||||
<NText depth="3" style="font-size: 12px; display: block; margin-bottom: 6px;">Колонки</NText>
|
||||
<NTransfer
|
||||
v-model:value="section.columns"
|
||||
:options="columnTransferOptions"
|
||||
source-filterable
|
||||
source-title="Доступные колонки"
|
||||
target-title="Колонки секции (в этом порядке)"
|
||||
style="height: 280px;"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-if="filterableFieldOptions.length">
|
||||
<NText depth="3" style="font-size: 12px; display: block; margin-bottom: 6px;">Фильтры (необязательно)</NText>
|
||||
<NDynamicInput v-model:value="section.filters" :on-create="createFilter">
|
||||
<template #default="{ value }">
|
||||
<NFlex align="center" :size="8" style="flex: 1;">
|
||||
<NSelect
|
||||
v-model:value="value.field"
|
||||
:options="filterableFieldOptions"
|
||||
style="width: 220px;"
|
||||
placeholder="Поле"
|
||||
/>
|
||||
<NSelect
|
||||
v-if="filterValueOptions(value.field)"
|
||||
v-model:value="value.value"
|
||||
:options="filterValueOptions(value.field)"
|
||||
style="width: 220px;"
|
||||
placeholder="Значение"
|
||||
/>
|
||||
<NInput
|
||||
v-else
|
||||
v-model:value="value.value"
|
||||
style="width: 220px;"
|
||||
placeholder="Значение"
|
||||
/>
|
||||
</NFlex>
|
||||
</template>
|
||||
</NDynamicInput>
|
||||
<NEmpty v-if="!section.filters.length" description="Без фильтров — попадут все записи" size="small" style="padding: 8px 0;" />
|
||||
</div>
|
||||
</NFlex>
|
||||
</template>
|
||||
Reference in New Issue
Block a user