UI коструктора отчетов

This commit is contained in:
brusnitsyn
2026-06-22 17:02:36 +09:00
parent bdb16dac54
commit 13dfcc3e05
11 changed files with 1664 additions and 0 deletions

View File

@@ -0,0 +1,104 @@
<script setup>
import { ref, computed } from 'vue'
import { NModal, NInput, NScrollbar, NGrid, NGi, NText } from 'naive-ui'
import { TbSearch } from 'vue-icons-plus/tb'
import PresetCard from './PresetCard.vue'
const props = defineProps({
show: { type: Boolean, default: false },
presets: { type: Array, default: () => [] },
categories: { type: Array, default: () => [] },
})
const emit = defineEmits(['update:show', 'select'])
const search = ref('')
const activeCategory = ref('Все')
const filtered = computed(() => props.presets.filter((p) => {
const byCat = activeCategory.value === 'Все' || p.category === activeCategory.value || p.key === 'blank'
const byText = !search.value || p.label.toLowerCase().includes(search.value.toLowerCase())
return byCat && byText
}))
const pick = (preset) => {
emit('select', preset)
emit('update:show', false)
}
</script>
<template>
<NModal
:show="show"
preset="card"
title="Шаблоны для отчёта"
style="width: 860px; max-width: 94vw;"
class="h-[580px]"
@update:show="emit('update:show', $event)"
>
<template #header-extra>
<NText depth="3" style="font-size: 13px;">Создавайте отчёт по шаблонам</NText>
</template>
<div class="picker">
<div class="picker-side">
<NInput v-model:value="search" placeholder="Поиск" clearable size="small">
<template #prefix><TbSearch :size="14" /></template>
</NInput>
<div class="cat-list">
<div
v-for="cat in categories"
:key="cat"
class="cat-item"
:class="{ active: cat === activeCategory }"
@click="activeCategory = cat"
>
{{ cat }}
</div>
</div>
</div>
<NScrollbar style="max-height: 60vh;" class="picker-main">
<NGrid responsive="screen" cols="2 s:3" :x-gap="12" :y-gap="12" class="pt-0.5">
<NGi v-for="preset in filtered" :key="preset.key">
<PresetCard :preset="preset" @click="pick(preset)" />
</NGi>
</NGrid>
</NScrollbar>
</div>
</NModal>
</template>
<style scoped>
.picker {
display: flex;
gap: 16px;
}
.picker-side {
width: 180px;
flex-shrink: 0;
}
.cat-list {
margin-top: 12px;
display: flex;
flex-direction: column;
gap: 2px;
}
.cat-item {
padding: 7px 10px;
border-radius: 8px;
cursor: pointer;
font-size: 13px;
}
.cat-item:hover {
background: color-mix(in srgb, var(--primary-color) 8%, transparent);
}
.cat-item.active {
background: color-mix(in srgb, var(--primary-color) 14%, transparent);
color: var(--primary-color);
font-weight: 600;
}
.picker-main {
flex: 1;
}
</style>