- Generazione della Raccolta dei Cataloghi (web e Stampa), e creazione del PDF Online.

- Lista Raccolta Cataloghi, aggiungi/togli catalogo.
This commit is contained in:
Surya Paolo
2025-05-14 15:02:14 +02:00
parent 85faf11d27
commit fc8a954eb0
39 changed files with 6149 additions and 4069 deletions

View File

@@ -1702,15 +1702,18 @@ export default defineComponent({
}
}
function addProductToList(element: IProduct) {
function addProductToList(element: IProduct, where: string) {
// console.log('addProductToList', element)
if (element) {
// add this record to lista_prodotti
if (getCatalogoByMyPage.value && !getCatalogoByMyPage.value.lista_prodotti.some((p) => p._id === element._id)) {
if (getCatalogoByMyPage.value && !getCatalogoByMyPage.value.lista_prodotti?.some((p) => p._id === element._id)) {
// inserire il record in cima
const arr = getCatalogoByMyPage.value.lista_prodotti;
arr.unshift(element);
const arr = getCatalogoByMyPage.value.lista_prodotti || [];
if (where === shared_consts.WHERE_INSERT.ONTOP)
arr.unshift(element);
else if (where === shared_consts.WHERE_INSERT.ONBOTTOM)
arr.push(element)
updateProducts(arr);
@@ -1944,9 +1947,9 @@ export default defineComponent({
const ris = await globalStore.execOnlinePDF({ id_catalog: catalog._id, stampa: false });
if (ris) {
if (ris.catalog?.pdf_online) {
catalog.pdf_online = ris.catalog.pdf_online;
catalog.data_online = ris.catalog.data_online;
if (ris.record?.pdf_online) {
catalog.pdf_online = ris.record.pdf_online;
catalog.data_online = ris.record.data_online;
}
$q.notify({
color: 'positive',
@@ -1969,9 +1972,9 @@ export default defineComponent({
const ris = await globalStore.execOnlinePDF({ id_catalog: catalog._id, stampa: true });
if (ris) {
if (ris.catalog.pdf_online_stampa) {
catalog.pdf_online_stampa = ris.catalog.pdf_online_stampa;
catalog.data_online_stampa = ris.catalog.data_online_stampa;
if (ris.record.pdf_online_stampa) {
catalog.pdf_online_stampa = ris.record.pdf_online_stampa;
catalog.data_online_stampa = ris.record.data_online_stampa;
}
$q.notify({
color: 'positive',

View File

@@ -231,6 +231,7 @@
:lista_prodotti="lista_prodotti"
@update:lista_prodotti="updateProducts"
:optcatalogo="optcatalogo"
table="products"
@rigenera="generaListaLibri()"
/>
</q-tab-panel>
@@ -1072,6 +1073,7 @@
@close="addnewProd = false"
nameLinkTemplate="SEARCH_Prima"
:empty="true"
table="catalogs"
>
</CSearchProduct>
</CMyDialog>

View File

@@ -0,0 +1 @@
export {default as RaccoltaCataloghi} from './raccoltacataloghi.vue'

View File

@@ -0,0 +1,166 @@
$heightBtn: 100%;
$colore_titolo_libro: rgb(210, 12, 12);
body {
line-height: 1.2 !important;
}
.card .product-image {
height: 300px;
}
.container {
margin-top: 4px;
margin-bottom: 4px;
}
.prod_trov {
font-style: italic;
color: grey;
}
.fixed-group {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: #ffffff;
/* Customize the background color as needed */
z-index: 1000;
/* Adjust the z-index to ensure it's above other elements */
transition: all 1s ease;
}
.category-title {
font-weight: bold;
font-size: 1.1rem;
margin-bottom: 0.5rem;
margin-top: 0.5rem;
color: black;
text-align: center;
}
.fixed-width {
width: var(--width) !important;
/* Usa una variabile CSS */
}
.fixed-height {
height: var(--height) !important;
/* Usa una variabile CSS */
}
.break {
flex-basis: 100%;
height: 0;
}
.book-title {
font-family: 'DINPro-Condensed-Bold', sans-serif;
color: $colore_titolo_libro;
text-transform: uppercase;
margin-top: calc(5 * var(--scalecatalog) * 1px);
margin-bottom: calc(5 * var(--scalecatalog) * 1px);
font-size: calc(18 * var(--scalecatalog) * 1px);
line-height: 100%;
font-weight: bold;
}
.book-author {
font-family: 'DINPro-Condensed-Regular', sans-serif;
font-size: calc(16 * var(--scalecatalog) * 1px);
}
.book-descr {
font-family: 'DINPro-Condensed-Bold-Italic', sans-serif;
font-size: calc(16 * var(--scalecatalog) * 1px);
}
.book-details {
font-family: 'DINPro-Condensed-Regular', sans-serif;
margin-bottom: calc(5 * var(--scalecatalog) * 1px);
font-size: calc(16 * var(--scalecatalog) * 1px);
text-align: left !important;
&.big {
font-size: calc(22 * var(--scalecatalog) * 1px);
}
}
.book-descr-estesa {
font-family: 'AGaramondPro-Regular', sans-serif;
font-size: calc(15 * var(--scalecatalog) * 1px);
text-align: justify;
word-wrap: break-word;
}
.book-link {
font-style: italic;
font-size: calc(14 * var(--scalecatalog) * 1px);
}
.book-novita {
font-size: calc(20 * var(--scalecatalog) * 1px);
}
.book-text-up {
font-family: 'DINPro', sans-serif;
margin-bottom: calc(5 * var(--scalecatalog) * 1px);
font-size: calc(20 * var(--scalecatalog) * 1px);
height: calc(380 * var(--scalecatalog) * 1px);
line-height: 130%;
}
.book-text-down {
font-family: 'DINPro', sans-serif;
margin-bottom: calc(5 * var(--scalecatalog) * 1px);
}
.book-pagina-title {
font-family: 'DINPro', sans-serif;
margin-top: calc(20 * var(--scalecatalog) * 1px);
margin-bottom: calc(5 * var(--scalecatalog) * 1px);
font-size: calc(35 * var(--scalecatalog) * 1px);
height: calc(100 * var(--scalecatalog) * 1px);
}
.categories {
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 8px;
padding: 12px;
border-radius: 24px;
background-color: #e6f0ff;
}
.category {
font-family: 'Segoe UI', Arial, sans-serif;
font-size: 0.95rem;
padding: 8px 16px;
background-color: white;
color: #2c3e50;
border: 1px solid #b0c4de;
border-radius: 20px;
cursor: pointer;
transition: all 0.2s ease-in-out;
user-select: none;
}
.category:hover {
background-color: #dbe9ff;
color: #1a3f8a;
border-color: #89aef0;
}
.category_sel {
background-color: #5c8ef4 !important;
color: white !important;
font-weight: 600;
border-color: #5c8ef4 !important;
box-shadow: 0 0 0 2px rgba(92, 142, 244, 0.3);
}

View File

@@ -0,0 +1,430 @@
import type { PropType } from 'vue';
import { defineComponent, onMounted, ref, watch, computed, onBeforeUnmount, nextTick } from 'vue';
import { tools } from '@tools';
import { useUserStore } from '@store/UserStore';
import { useRouter } from 'vue-router';
import { useGlobalStore } from '@store/globalStore';
import { useProducts } from '@store/Products';
import { useI18n } from 'vue-i18n';
import { toolsext } from '@store/Modules/toolsext';
import { useQuasar } from 'quasar';
import { costanti } from '@costanti';
import { shared_consts } from '@src/common/shared_vuejs';
import { CProductCard } from '@src/components/CProductCard';
import { CMyDialog } from '@src/components/CMyDialog';
import { CMySelect } from '@src/components/CMySelect';
import { CMyValueDb } from '@src/components/CMyValueDb';
import { CProductTable } from '@src/components/CProductTable';
import { CSearchProduct } from '@src/components/CSearchProduct';
import { CContainerCatalogoCard } from '@src/components/CContainerCatalogoCard';
import { CSelectUserActive } from '@src/components/CSelectUserActive';
import html2pdf from 'html2pdf.js';
import { PDFDocument } from 'pdf-lib';
import { saveAs } from 'file-saver';
import type {
IOptCatalogo,
IDimensioni,
IFilterCatalogo,
IProdView,
IProduct,
ISearchList,
ICatalog,
IImg,
IText,
ICollana,
IOptRigenera,
IOpAndOr,
} from 'model';
import { IMyPage } from 'model';
import { fieldsTable } from '@store/Modules/fieldsTable';
import { useCatalogStore } from '@src/store/CatalogStore';
export default defineComponent({
name: 'RaccoltaCataloghi',
components: {
CContainerCatalogoCard,
CProductCard,
CSelectUserActive,
CMySelect,
CProductTable,
CSearchProduct,
CMyDialog,
CMyValueDb,
},
emits: ['update:modelValue', 'updateCatalogo'],
props: {
modelValue: {
type: Object as PropType<IOptCatalogo>,
required: true,
},
idPage: {
type: String,
required: false,
default: '',
},
},
setup(props, { emit }) {
const userStore = useUserStore();
const globalStore = useGlobalStore();
const productStore = useProducts();
const router = useRouter();
const $q = useQuasar();
const { t } = useI18n();
const rigeneraLibri = ref(false);
const search = ref('');
const optauthors = ref(<any>[]);
const loadpage = ref(false)
const pdfContent = ref(null);
const addnewProd = ref(false);
const widthpdf = ref('8.88');
const heightpdf = ref('12.31');
const compressionepdf = ref('prepress');
const optcatalogo = ref(<IOptCatalogo>{ ...props.modelValue });
const getRaccoltaCataloghiByMyPage = computed(() => {
return catalogStore.raccoltacataloghis?.find((raccolta: IRaccoltaCatalogo) => raccolta.idPageAssigned === props.idPage);
});
const lista_cataloghi = computed(() => {
const arr = catalogStore.raccoltacataloghis?.find(
(raccolta: IRaccoltaCatalogo) => raccolta.idPageAssigned === props.idPage
);
return arr?.lista_cataloghi;
});
const ispageCatalogata = computed(() => {
return !!getRaccoltaCataloghiByMyPage.value;
});
const mycolumns = ref([]);
const catalogStore = useCatalogStore();
const tabraccolta = ref('lista');
const searchList = ref([] as ISearchList[]);
const numRecLoaded = ref(0);
// Create a ref for the component to fix
const componentToFixRef = ref(<any>null);
const isFixed = ref(false);
watch(
() => tabraccolta.value,
() => {
tools.setCookie('RACC_TAB_CAT', tabraccolta.value);
}
);
const labelcombo = computed(() => (item: any) => {
let lab = item.label;
if (item.showcount) lab += ' (' + valoriopt.value(item, false, false).length + ')';
return lab;
});
const arrLoaded = computed(() => {
if (arrCataloghi.value && numRecLoaded.value) return arrCataloghi.value.slice(0, numRecLoaded.value);
else {
return [];
}
});
function getTitoloRaccolta(): string {
const trovatoraccolta = getRaccoltaCataloghiByMyPage.value;
return trovatoraccolta ? trovatoraccolta.title : 'Raccolta';
}
function getSfondoImgCatalogo(scheda?: IMyScheda | null, mypage?: IDimensioni): IImg {
const trovatoraccolta = getRaccoltaCataloghiByMyPage.value;
let imagefile = '';
let fit = 'contain';
if (trovatoraccolta) {
// Poi cerca se c'è l'immagine di sfondo
const recimg = trovatoraccolta.img_bordata!;
if (!imagefile && recimg) {
imagefile = recimg.imagefile!;
fit = recimg.fit! || 'contain';
imagefile = imagefile
? `url(${tools.getDirUpload() + shared_consts.getDirectoryByTable(shared_consts.TABLES_CATALOG) + '/' + trovatoraccolta._id + '/' + imagefile})`
: '';
}
}
if (!imagefile) {
let myimg = costanti.CATALOGHI.PAG_SFONDO_DEFAULT;
// Se non c'è un immagine di sfondo, allora prende quella di default
imagefile = `url(${tools.getDirUpload() + shared_consts.getDirectoryByTable(shared_consts.TABLES_CATALOG) + '/' + myimg})`;
}
if (!imagefile && mypage) {
imagefile = mypage.imgsfondo!.imagefile!;
imagefile = imagefile ? `url(${tools.getDirUpload() + costanti.DIR_CATALOGO + imagefile})` : '';
fit = mypage.imgsfondo!.fit!;
}
return { imagefile, fit };
}
function salvaListaRaccolte(ricarica: boolean) {
// Estrai solo gli ID dei prodotti filtrati
const myarr = [...getRaccoltaCataloghiByMyPage.value.lista_cataloghi];
const catalogoIds = myarr.map((catalog) => (catalog._id ? catalog._id : null)).filter((id) => id !== null);
let mydata = {
lista_cataloghi: catalogoIds,
};
// Salva gli ID dei prodotti nel catalogo
tools.saveFieldToServer($q, 'raccoltacataloghis', getRaccoltaCataloghiByMyPage.value._id, mydata, true, false);
}
async function mounted() {
// console.log('mounted Catalogo')
if (getRaccoltaCataloghiByMyPage.value) {
tabraccolta.value = tools.getCookie('RACC_TAB_CAT', 'lista');
} else {
tabraccolta.value = 'lista';
}
loadpage.value = false;
// await productStore.loadProducts(true);
mycolumns.value = fieldsTable.getArrColsByTable('raccoltacataloghis');
// Inizializza
loadpage.value = true;
calcArrCataloghi();
}
function calcArrCataloghi() {}
function loaddata() {
numRecLoaded.value = 20;
}
function naviga(path: string) {
router.push(path);
}
function updateRaccolta(arr: any) {
if (getRaccoltaCataloghiByMyPage.value) {
getRaccoltaCataloghiByMyPage.value.lista_cataloghi = [...arr];
salvaListaRaccolte(true);
}
}
function addCatalogToList(element: ICatalog, where: string) {
// console.log('addCatalogToList', element)
if (element) {
// add this record to lista_cataloghi
if (
getRaccoltaCataloghiByMyPage.value &&
element._id && !getRaccoltaCataloghiByMyPage.value.lista_cataloghi?.some((p) => p?._id === element._id)
) {
// inserire il record in cima
const arr = getRaccoltaCataloghiByMyPage.value.lista_cataloghi || [];
if (where === shared_consts.WHERE_INSERT.ONTOP)
arr.unshift(element);
else if (where === shared_consts.WHERE_INSERT.ONBOTTOM)
arr.push(element)
updateRaccolta(arr);
addnewProd.value = false;
}
}
}
function clickaddNewBook() {
addnewProd.value = true;
}
function toggleDebug() {
optcatalogo.value.indebug = !optcatalogo.value.indebug;
}
const preparePDF = (stampa: boolean) => {
let addstr = stampa ? ' per la STAMPA' : ''
$q.dialog({
message: `Generare il PDF ${addstr}?`,
ok: {
label: t('dialog.yes'),
push: true,
},
cancel: {
label: t('dialog.cancel'),
},
title: 'Generazione PDF',
}).onOk(async () => {
generaPDF(stampa);
});
};
async function saveRaccolta() {
const raccolta = getRaccoltaCataloghiByMyPage.value
const mydata = {
table: 'raccoltacataloghis',
data: raccolta,
};
await globalStore.saveTable(mydata);
}
async function generaPDF(stampa: boolean) {
$q.loading.show({
message: 'Generazione della Raccolta Catalogo in PDF in corso ...',
});
try {
const options = {
id_raccolta: getRaccoltaCataloghiByMyPage.value._id,
stampa,
metti_online: false,
dir_out: '/upload/raccolte/',
}
const ris = await globalStore.execJoinPDF({options});
if (ris) {
const raccolta = getRaccoltaCataloghiByMyPage.value;
if (!stampa && ris.raccolta.pdf_generato) {
raccolta.pdf_generato = ris.raccolta.pdf_generato;
raccolta.data_generato = tools.getDateNow();
}
if (stampa && ris.raccolta.pdf_generato_stampa) {
raccolta.pdf_generato_stampa = ris.raccolta.pdf_generato_stampa;
raccolta.data_generato_stampa = tools.getDateNow();
}
await saveRaccolta();
}
$q.loading.hide();
$q.notify({
color: 'positive',
message: 'PDF generato con successo!',
icon: 'check',
});
} catch (error) {
$q.loading.hide();
$q.notify({
color: 'negative',
message: 'Errore nella generazione del PDF',
icon: 'error',
});
console.error('Errore nella generazione del PDF:', error);
}
}
const pubblicaPDF = async () => {
const raccolta = getRaccoltaCataloghiByMyPage.value;
const ris = await globalStore.execOnlinePDF({ id_raccolta: raccolta._id, stampa: false });
if (ris) {
if (ris.record?.pdf_online) {
raccolta.pdf_online = ris.record.pdf_online;
raccolta.data_online = ris.record.data_online;
}
$q.notify({
color: 'positive',
message: 'PDF inviato ONLINE!',
icon: 'check',
});
} else {
$q.loading.hide();
$q.notify({
color: 'negative',
message: "Errore nell'invio del PDF OnLine",
icon: 'error',
});
}
};
const pubblicaPDFStampa = async () => {
const raccolta = getRaccoltaCataloghiByMyPage.value;
const ris = await globalStore.execOnlinePDF({ id_raccolta: raccolta._id, stampa: true });
if (ris) {
if (ris.record.pdf_online_stampa) {
raccolta.pdf_online_stampa = ris.record.pdf_online_stampa;
raccolta.data_online_stampa = ris.record.data_online_stampa;
}
await saveRaccolta();
$q.notify({
color: 'positive',
message: 'PDF STAMPA inviato ONLINE!',
icon: 'check',
});
} else {
$q.loading.hide();
$q.notify({
color: 'negative',
message: "Errore nell'invio del PDF STAMPA OnLine",
icon: 'error',
});
}
}
onMounted(mounted);
return {
userStore,
costanti,
tools,
toolsext,
search,
shared_consts,
productStore,
t,
componentToFixRef,
isFixed,
numRecLoaded,
arrLoaded,
mycolumns,
tabraccolta,
naviga,
getTitoloRaccolta,
lista_cataloghi,
updateRaccolta,
clickaddNewBook,
addCatalogToList,
addnewProd,
rigeneraLibri,
getRaccoltaCataloghiByMyPage,
preparePDF,
pubblicaPDF,
pubblicaPDFStampa,
loadpage,
ispageCatalogata,
optcatalogo,
};
},
});

View File

@@ -0,0 +1,184 @@
<template>
<q-page>
<div>
<div
v-if="ispageCatalogata"
class="text-bold text-h6 text-center text-blue"
>
{{ getTitoloRaccolta() }}
</div>
<q-tabs
v-model="tabraccolta"
dense
class="bg-green text-white"
>
<q-tab
name="lista"
icon="fas fa-list"
label="Lista"
>
</q-tab>
<q-tab
v-if="!tools.isUtente()"
name="genera"
icon="fas fa-book"
label="Genera"
>
</q-tab>
</q-tabs>
<q-tab-panels
v-model="tabraccolta"
animated
class=""
keep-alive
>
<q-tab-panel
name="lista"
>
<q-btn
rounded
label="Aggiungi"
icon="fas fa-plus"
color="primary"
@click="clickaddNewBook()"
></q-btn>
<CProductTable
v-if="loadpage && lista_cataloghi?.length > 0"
:lista_prodotti="lista_cataloghi"
@update:lista_prodotti="updateRaccolta"
table="catalogs"
:optcatalogo="optcatalogo"
/>
</q-tab-panel>
<q-tab-panel name="genera">
<div
v-if="!tools.isUtente()"
class="row justify-center"
>
<q-btn
v-if="!optcatalogo.generazionePDFInCorso"
:label="`GENERA PDF per WEB`"
@click="preparePDF(false)"
></q-btn>
<q-btn
v-if="!optcatalogo.generazionePDFInCorso"
:label="`GENERA PDF per STAMPA`"
@click="preparePDF(true)"
></q-btn>
<q-btn
v-if="optcatalogo.generazionePDFInCorso"
:label="`Termina Generazione`"
@click="terminaPDF"
></q-btn>
</div>
<div
v-if="getRaccoltaCataloghiByMyPage?.pdf_generato"
class="bg-green-1 q-ma-sm q-pa-sm"
>
<div class="bg-blue-1 text-red text-bold text-h6 q-ma-sm q-pa-sm">
<strong>PDF generati Temporanei</strong>
</div>
<div v-if="getRaccoltaCataloghiByMyPage?.data_generato !== getRaccoltaCataloghiByMyPage?.data_online">
PDF Generato:
<a
:href="tools.getHost() + getRaccoltaCataloghiByMyPage?.pdf_generato"
target="_blank"
v-if="getRaccoltaCataloghiByMyPage?.pdf_generato"
class="text-bold"
>
{{ tools.getHost() + getRaccoltaCataloghiByMyPage?.pdf_generato }}
</a>
<span v-else>-</span>
<br />(del {{ tools.getstrDateTime(getRaccoltaCataloghiByMyPage?.data_generato) }})
<br />
<q-btn
v-if="getRaccoltaCataloghiByMyPage?.data_generato !== getRaccoltaCataloghiByMyPage?.data_online"
rounded
label="Pubblica PDF OnLine"
color="positive"
@click="pubblicaPDF()"
></q-btn>
</div>
<br />
<div v-if="getRaccoltaCataloghiByMyPage?.data_generato_stampa !== getRaccoltaCataloghiByMyPage?.data_online_stampa">
PDF Generato Stampa:
<a
:href="tools.getHost() + getRaccoltaCataloghiByMyPage?.pdf_generato_stampa"
target="_blank"
v-if="getRaccoltaCataloghiByMyPage?.pdf_generato_stampa"
class="text-bold"
>
{{ tools.getHost() + getRaccoltaCataloghiByMyPage?.pdf_generato_stampa }}
</a>
<span v-else>-</span>
<br />(del {{ tools.getstrDateTime(getRaccoltaCataloghiByMyPage?.data_generato_stampa) }})
<br />
<q-btn
v-if="getRaccoltaCataloghiByMyPage?.data_generato_stampa !== getRaccoltaCataloghiByMyPage?.data_online_stampa"
rounded
label="Pubblica PDF Stampa"
color="positive"
@click="pubblicaPDFStampa()"
></q-btn>
</div>
<div class="bg-green-1">
<div class="bg-blue-1 text-green text-bold text-h6 q-ma-sm q-pa-sm">
<strong>PDF Pubblicati OnLine</strong>
</div>
<div v-if="getRaccoltaCataloghiByMyPage?.data_online">
PDF OnLine:
<a
:href="tools.getHost() + getRaccoltaCataloghiByMyPage?.pdf_online"
target="_blank"
v-if="getRaccoltaCataloghiByMyPage?.pdf_online"
class="text-bold"
>
{{ tools.getHost() + getRaccoltaCataloghiByMyPage?.pdf_online }}
</a>
<span v-else>-</span>
<br />(del {{ tools.getstrDateTime(getRaccoltaCataloghiByMyPage?.data_online) }})
</div>
<br />
<div v-if="getRaccoltaCataloghiByMyPage?.data_online_stampa">>
PDF OnLine Stampa:
<a
:href="tools.getHost() + getRaccoltaCataloghiByMyPage?.pdf_online_stampa"
target="_blank"
v-if="getRaccoltaCataloghiByMyPage?.pdf_online_stampa"
class="text-bold"
>
{{ tools.getHost() + getRaccoltaCataloghiByMyPage?.pdf_online_stampa }}
</a>
<span v-else>-</span>
<br />(del {{ tools.getstrDateTime(getRaccoltaCataloghiByMyPage?.data_online_stampa) }})
</div>
</div>
</div>
</q-tab-panel>
</q-tab-panels>
</div>
</q-page>
<CMyDialog
v-model="addnewProd"
title="Aggiungi"
class="q-ma-md"
>
<CSearchProduct
:visu="shared_consts.VISU_SEARCHPROD_MODE.INSERT"
table="catalogs"
@insert="addCatalogToList"
@close="addnewProd = false"
nameLinkTemplate="SEARCH_Prima"
:empty="true"
>
</CSearchProduct>
</CMyDialog>
</template>
<script lang="ts" src="./raccoltacataloghi.ts"></script>
<style lang="scss" scoped>
@import './raccoltacataloghi.scss';
</style>