From d6c0bcf879d3f1f3f4a95777c8778cfc0d0beb49 Mon Sep 17 00:00:00 2001 From: Surya Paolo Date: Sat, 27 Sep 2025 17:24:40 +0200 Subject: [PATCH] - corretto gruppomacro catalogo, info prodotti, estrazione dati da amazon corretto. --- .env.production | 18 +- src/components/CCart/CCart.ts | 2 +- src/components/CCatalogoCard/CCatalogoCard.ts | 3 +- .../CCatalogoCard/CCatalogoCard.vue | 58 +++- .../CModifTrafiletto/CModifTrafiletto.ts | 46 +-- src/components/CMyChipList/CMyChipList.ts | 284 +++++++++--------- src/components/CMyPopupEdit/CMyPopupEdit.vue | 1 + src/components/CProductCard/CProductCard.vue | 13 - .../CProductTable/CProductTable.vue | 3 +- .../CSchedaProdotto/CSchedaProdotto.ts | 102 ++++--- src/components/LandingFooter/LandingFooter.ts | 40 ++- src/mixins/mixin-base.ts | 7 - .../admin/importaprodotti/importaprodotti.vue | 5 +- 13 files changed, 330 insertions(+), 252 deletions(-) diff --git a/.env.production b/.env.production index 806a4a4b..2a577413 100644 --- a/.env.production +++ b/.env.production @@ -1,13 +1,11 @@ VITE_APP_ID="18" -VITE_APP_URL="https://gruppomacro.app" -VITE_MONGODB_HOST="https://api.gruppomacro.app" -VITE_LOGO_REG='gruppomacro-logo-full.png' +VITE_APP_URL="https://test.gruppomacro.app" +VITE_MONGODB_HOST="https://testapi.gruppomacro.app" +VITE_LOGO_REG="gruppomacro-logo-full.png" VITE_PUBLICKEY_PUSH="BJgo8XR_upbnbMLWgCAUELo6DK7dRXffYAnFOxbaMMz5favBgcQBKT-eISqouO-jRad4Sw8l5nd2wCF6KorGiTc" -VITE_DEBUG="0" -VITE_VUE_APP_ISTEST="0" +VITE_DEBUG="1" +VITE_VUE_APP_ISTEST="1" DIRECTORY_LOCAL="myprojplanet_vite" -DIRECTORY_SERVER="/var/www/nodejs_piuchebuono_server" -SERVERDIR_WEBSITE="/var/www/gruppomacro.app" -SERVERPW_WEBSITE="pwdadmin@1AOK" -PORT_SPA="8089" -PORT_PWA="8099" \ No newline at end of file +DIRECTORY_SERVER="/var/www/nodejs_test.piuchebuono_server" +SERVERDIR_WEBSITE="/var/www/test.gruppomacro.app" +SERVERPW_WEBSITE="pwdadmin@1AOK" \ No newline at end of file diff --git a/src/components/CCart/CCart.ts b/src/components/CCart/CCart.ts index 5814395e..c12cae1f 100755 --- a/src/components/CCart/CCart.ts +++ b/src/components/CCart/CCart.ts @@ -208,7 +208,7 @@ export default defineComponent({ function completeOrder() { $q.dialog({ - message: t('ecomm.conferma_acq', { qty: myTotalQty }), + message: t('ecomm.conferma_acq', { qty: myTotalQty.value }), ok: { label: t('dialog.yes'), push: true, diff --git a/src/components/CCatalogoCard/CCatalogoCard.ts b/src/components/CCatalogoCard/CCatalogoCard.ts index 2da58b05..81c2842e 100755 --- a/src/components/CCatalogoCard/CCatalogoCard.ts +++ b/src/components/CCatalogoCard/CCatalogoCard.ts @@ -789,7 +789,7 @@ export default defineComponent({ dataextractedWeb.value = '... caricamento in corso...'; try { - const data = await scrapingBook(false); + const data = await scrapingBook(false, false); const html = tools.generateHtmlTableFromObject(data); dataextractedWeb.value = html; } catch (error) { @@ -885,6 +885,7 @@ export default defineComponent({ heightoggetto, mywidthogg, myheightogg, + scrapingBook, }; }, }); diff --git a/src/components/CCatalogoCard/CCatalogoCard.vue b/src/components/CCatalogoCard/CCatalogoCard.vue index c924d22d..a58c3bdd 100755 --- a/src/components/CCatalogoCard/CCatalogoCard.vue +++ b/src/components/CCatalogoCard/CCatalogoCard.vue @@ -76,7 +76,7 @@ scheda, true ) ?? '100%', - 'height': tools.adjustSize( + height: tools.adjustSize( optcatalogo, scheda.dimensioni?.scheda_prodotto?.size?.height, scheda, @@ -84,13 +84,17 @@ ), }" > -
+
@@ -158,18 +166,35 @@ z-index: 10; " > -
+
-
+
({ ...props.modelValue }); - const id = computed(() => myproduct.value.productInfo._id); + const id = computed(() => myproduct.value._id); const myvalue = computed(() => { - return myproduct.value.productInfo[props.mykey]; + if (props.mysubkey) { + return myproduct.value[props.mykey][props.mysubkey]; + } else { + return myproduct.value[props.mykey]; + } }); watch( @@ -105,7 +102,8 @@ export default defineComponent({ loading.value = true; try { const myscrapingbookrec = await products.loadMyScrapingBook( - myproduct.value.isbn, false + myproduct.value.isbn, + false ); myscrapingbook.value = myscrapingbookrec; } catch (error) { @@ -152,10 +150,7 @@ export default defineComponent({ } async function updateproduct(load?: boolean) { - myproduct.value = await products.getProductById( - myproduct.value._id, - load - ); + myproduct.value = await products.getProductById(myproduct.value._id, load); } const copyToClipboard = (text) => { @@ -187,8 +182,9 @@ export default defineComponent({ function getPrompt() { // Prompt: - let mydescr = 'Scrivimi la sinossi del libro che ti indicherò, che andrà in un catalogo libri, la lunghezza del testo finale dev\'essere compresa tra 760 e 780 caratteri, senza spiegazione, senza titolo iniziale, solo la sinossi. Togli eventuali riferimenti a chi ha fatto la prefazione. Rendilo un po\' accattivante, ma non troppo. Senza immagine. Non inserire nessun link o riferimenti esterni o citazioni esterne. L\'output è solo la sinossi, senza altre spiegazioni. \n\n'; - return mydescr + let mydescr = + "Scrivimi la sinossi del libro che ti indicherò, che andrà in un catalogo libri, la lunghezza del testo finale dev'essere compresa tra 760 e 780 caratteri, senza spiegazione, senza titolo iniziale, solo la sinossi. Togli eventuali riferimenti a chi ha fatto la prefazione. Rendilo un po' accattivante, ma non troppo. Senza immagine. Non inserire nessun link o riferimenti esterni o citazioni esterne. L'output è solo la sinossi, senza altre spiegazioni. \n\n"; + return mydescr; } function copyDescrizioneFromScrapingData() { @@ -197,9 +193,14 @@ export default defineComponent({ const data = myscrapingbook.value; if (!data) return false; - mydescr = getPrompt() + mydescr = getPrompt(); mydescr += 'Titolo Libro: ' + data.titolo + '\n'; - mydescr += 'Autore Libro: ' + (data?.autore.trim() ? data?.autore.trim() : products.getAutoriByArrayAuthors(myproduct?.value.productInfo?.authors)) + '\n'; + mydescr += + 'Autore Libro: ' + + (data?.autore.trim() + ? data?.autore.trim() + : products.getAutoriByArrayAuthors(myproduct?.value.productInfo?.authors)) + + '\n'; mydescr += 'DESCRIZIONE LIBRO: \n'; mydescr += data.descrizione_lunga; @@ -210,9 +211,12 @@ export default defineComponent({ function copyDescrizioneFromGruppoMacro() { let mydescr = ''; - mydescr = getPrompt() + mydescr = getPrompt(); mydescr += 'Titolo Libro: ' + myproduct?.value.productInfo?.name + '\n'; - mydescr += 'Autore Libro: ' + products.getAutoriByArrayAuthors(myproduct?.value.productInfo?.authors) + '\n'; + mydescr += + 'Autore Libro: ' + + products.getAutoriByArrayAuthors(myproduct?.value.productInfo?.authors) + + '\n'; mydescr += 'DESCRIZIONE LIBRO: \n'; mydescr += myproduct?.value.productInfo?.descrizione_completa_macro; diff --git a/src/components/CMyChipList/CMyChipList.ts b/src/components/CMyChipList/CMyChipList.ts index d4303f05..0d93712d 100755 --- a/src/components/CMyChipList/CMyChipList.ts +++ b/src/components/CMyChipList/CMyChipList.ts @@ -1,8 +1,8 @@ -import { defineComponent, ref, watch, toRef, onMounted } from 'vue' -import { useI18n } from 'vue-i18n' -import { useQuasar } from 'quasar' -import { tools } from '@tools' -import { costanti } from '@costanti' +import { defineComponent, ref, watch, toRef, onMounted } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { useQuasar } from 'quasar'; +import { tools } from '@tools'; +import { costanti } from '@costanti'; export default defineComponent({ name: 'CMyChipList', @@ -36,22 +36,22 @@ export default defineComponent({ myclass: { type: String, required: false, - default: '' + default: '', }, opticon: { type: String, required: false, - default: '' + default: '', }, optcolor: { type: String, required: false, - default: '' + default: '', }, labelifblank: { type: String, required: false, - default: '' + default: '', }, rec: { type: Object, @@ -62,173 +62,185 @@ export default defineComponent({ type: String, required: false, default: '', - } + }, }, components: {}, setup(props, { emit }) { - const { t } = useI18n() + const { t } = useI18n(); - const myval = toRef(props, 'value') - const myarrvalues = ref([]) + const myval = toRef(props, 'value'); + const myarrvalues = ref([]); - watch(() => myval.value, (newval, oldval) => { - refreshval() - }) + watch( + () => myval.value, + (newval, oldval) => { + refreshval(); + } + ); function refreshval() { - // console.log('refreshval') - myarrvalues.value = [] + // azzero l'array di uscita + myarrvalues.value = []; - // console.log('options', props.options) - if (props.options.length > 0) { - props.options.forEach((rec: any, index) => { - // console.log('rec', rec) - if (props.type === costanti.FieldType.multiselect) { - if (!!myval.value) { + // --- MULTISELECT: itera sulle selezioni, non sulle options --- + if (props.type === costanti.FieldType.multiselect) { + if (Array.isArray(myval.value) && myval.value.length) { + myval.value.forEach((recout, idx) => { + // valore "chiave" della selezione + const value = + props.type_out === costanti.FieldType.object + ? recout?.[props.optval] + : recout && typeof recout === 'object' + ? recout._id + : recout; - /* - console.log('rec', rec) - console.log('optval', props.optval) - console.log('optlab', props.optlab) - console.log('myval.value', myval.value) - console.log('rec[props.optval]', rec[props.optval]) - */ + if (value == null) return; // skip selezioni non valide - let trovato = false + // provo a trovare il record corrispondente tra le options (se presenti) + const recFromOptions = Array.isArray(props.options) + ? props.options.find((o) => o && o[props.optval] === value) + : null; - if (props.type_out === costanti.FieldType.object) { - // @ts-ignore - trovato = myval.value.find((recout) => recout[props.optval] === rec[props.optval]) - } else { - // @ts-ignore - trovato = myval.value.includes(rec[props.optval]) - } + const baseRec = + recFromOptions || (typeof recout === 'object' ? recout : null); - if (trovato) { - const mydata: any = { - label: null, - value: rec[props.optval], - // myris = mylist.filter((myrec) => arrval.includes(myrec[key])) - valbool: true, - icon: '', - color: tools.getColorByIndexBest(index) - } + const mydata = { + label: null, + value, + valbool: true, + icon: '', + // priorità: optcolor -> color su record -> fallback colore + color: + (props.optcolor && baseRec?.[props.optcolor]) || + baseRec?.color || + tools.getColorByIndexBest(idx), + }; - if (rec['color']) { - mydata.color = rec['color'] - } - - /* - if (rec['theme']) { - mydata.class = rec['theme'] - } - */ - - // console.log('mydata', mydata) - - if (tools.isObject(props.optlab)) { - // @ts-ignore - mydata.label = props.options.filter((myrec: any) => myrec[props.optval] === mydata.value).map(props.optlab) - if (mydata.label) - mydata.label = mydata.label[0] - } else { - mydata.label = tools.getValueByFunzOrVal(rec, props.optlab) - } - - // console.log('mydata.label', mydata.label) - - if (props.opticon) - mydata.icon = rec[props.opticon] - if (props.optcolor) - mydata.color = rec[props.optcolor] - - myarrvalues.value.push(mydata) - } + // icon (se disponibile) + if (props.opticon && baseRec?.[props.opticon]) { + mydata.icon = baseRec[props.opticon]; } - } else if (props.type === costanti.FieldType.select) { - if (myval.value === rec[props.optval]) { - const mydata: any = { + + // label + if (tools.isObject(props.optlab)) { + // se optlab è funzione/mapper, applico al record trovato in options + if (recFromOptions) { + mydata.label = + typeof props.optlab === 'function' + ? props.optlab(recFromOptions) + : tools.getValueByFunzOrVal(recFromOptions, props.optlab); + } else { + // fallback: provo su recout se è un oggetto + mydata.label = tools.getValueByFunzOrVal(baseRec || {}, props.optlab); + } + } else { + // optlab è chiave o funzione gestita dalla utility + mydata.label = tools.getValueByFunzOrVal(baseRec || {}, props.optlab); + } + + myarrvalues.value.push(mydata); + }); + } + + // se multiselect non ha prodotto nulla, gestisco eventuale fallback sotto + } else if (props.type === costanti.FieldType.select) { + // --- SELECT: itera sulle options e trova la corrispondenza --- + if (Array.isArray(props.options) && props.options.length) { + props.options.forEach((rec, index) => { + if (myval.value === rec?.[props.optval]) { + const mydata = { value: myval.value, valbool: true, icon: '', - color: tools.getColorByIndexBest(index) - } + color: + (props.optcolor && rec?.[props.optcolor]) || + rec?.color || + tools.getColorByIndexBest(index), + label: null, + }; - // console.log('mydata', mydata, 'optlab', optlab, 'myval.value', myval.value) + if (props.opticon && rec?.[props.opticon]) mydata.icon = rec[props.opticon]; if (tools.isObject(props.optlab)) { - // @ts-ignore - mydata.label = props.options.filter((myrec: any) => myrec[props.optval] === mydata.value).map(props.optlab) - if (mydata.label) - mydata.label = mydata.label[0] + // cerco l'option corrispondente e la mappo + const opt = props.options.find( + (o) => o && o[props.optval] === mydata.value + ); + mydata.label = opt + ? typeof props.optlab === 'function' + ? props.optlab(opt) + : tools.getValueByFunzOrVal(opt, props.optlab) + : null; } else { - mydata.label = tools.getValueByFunzOrVal(rec, props.optlab) + mydata.label = tools.getValueByFunzOrVal(rec, props.optlab); } - if (props.opticon) - mydata.icon = rec[props.opticon] - if (props.optcolor) - mydata.color = rec[props.optcolor] - - myarrvalues.value.push(mydata) + myarrvalues.value.push(mydata); } + }); + } + } else { + // --- BITMASK (o altro tipo legacy): itera sulle options e verifica i bit attivi --- + if (Array.isArray(props.options) && props.options.length) { + props.options.forEach((rec, index) => { + const optVal = rec?.[props.optval]; + if (optVal == null) return; - } else { - if (tools.isBitActive(myval.value, rec[props.optval])) { - // console.log('rec', rec, 'props.optlab', props.optlab) + if (tools.isBitActive(myval.value, optVal)) { const mydata = { label: t(tools.getValueByFunzOrVal(rec, props.optlab)), - value: rec[props.optval], - valbool: tools.isBitActive(myval.value, rec[props.optval]), + value: optVal, + valbool: true, icon: '', - color: tools.getColorByIndexBest(index) - } + color: + (props.optcolor && rec?.[props.optcolor]) || + rec?.color || + tools.getColorByIndexBest(index), + }; - if (props.opticon) - mydata.icon = rec[props.opticon] - if (props.optcolor) - mydata.color = rec[props.optcolor] + if (props.opticon && rec?.[props.opticon]) mydata.icon = rec[props.opticon]; - myarrvalues.value.push(mydata) + myarrvalues.value.push(mydata); } - } - }) - } else { - if (props.type === costanti.FieldType.select_by_server) { - - const mydata: any = { - // @ts-ignore - label: props.rec[props.optlab], - value: 0, - valbool: true, - icon: '', - color: tools.getColorByIndexBest(0) - } - - if (!mydata.label && props.labelifblank) { - mydata.label = props.labelifblank - mydata.color = 'grey' - } - - myarrvalues.value.push(mydata) + }); } } - if (myarrvalues.value.length === 0) - myarrvalues.value.push({ label: t('otherpages.manage.nessuno'), color: 'gray' }) + // --- FALLBACK quando non ci sono options ma select_by_server --- + if ( + (!Array.isArray(props.options) || props.options.length === 0) && + props.type === costanti.FieldType.select_by_server + ) { + const mydata = { + label: props.rec?.[props.optlab], + value: 0, + valbool: true, + icon: '', + color: tools.getColorByIndexBest(0), + }; - // console.log('arrvalues=', myarrvalues) + if (!mydata.label && props.labelifblank) { + mydata.label = props.labelifblank; + mydata.color = 'grey'; + } + + myarrvalues.value.push(mydata); + } + + // --- Nessuna selezione: placeholder "nessuno" --- + if (!Array.isArray(myarrvalues.value) || myarrvalues.value.length === 0) { + myarrvalues.value = [{ label: t('otherpages.manage.nessuno'), color: 'gray' }]; + } } function mounted() { - refreshval() + refreshval(); } - onMounted(mounted) + onMounted(mounted); return { myarrvalues, - } - } -}) - + }; + }, +}); diff --git a/src/components/CMyPopupEdit/CMyPopupEdit.vue b/src/components/CMyPopupEdit/CMyPopupEdit.vue index 12ecf3ea..dc8ddef6 100755 --- a/src/components/CMyPopupEdit/CMyPopupEdit.vue +++ b/src/components/CMyPopupEdit/CMyPopupEdit.vue @@ -1068,6 +1068,7 @@
+
{{ myproduct.productInfo.imagefile }}
- - { + // Try to read a globally exposed product store value if present + try { + const gp: any = (globalStore as any).myproduct + if (gp && gp.value !== undefined) return gp.value + } catch { + // ignore + } + + // Fallback: try to read from site.productInfo if available + try { + const s: any = site.value + if (s && s.productInfo) return s.productInfo + } catch { + // ignore + } + + // Final fallback + return {} + }) + + const nestedProductValue = computed(() => { + const key = props.mykey + if (!key) return undefined + const base = (productSource.value as any)?.[key] + if (props.mysubkey && base && typeof base === 'object') { + return base[props.mysubkey] + } + return base + }) function TelegramSupport() { return globalStore.getValueSettingsByKey('TELEGRAM_SUPPORT', false) @@ -90,6 +123,7 @@ export default defineComponent({ site, getBackColorText, t, + nestedProductValue, } }, }) diff --git a/src/mixins/mixin-base.ts b/src/mixins/mixin-base.ts index 28e670f7..ba21803e 100755 --- a/src/mixins/mixin-base.ts +++ b/src/mixins/mixin-base.ts @@ -256,13 +256,6 @@ export default function () { if (idprod >= 0 && key) { productStore.products[idprod][key as keyof IProduct] = value; } - /*} else if (table === 'productinfos') { - const productStore = useProducts() - const idprod = productStore.products.findIndex((rec: IProduct) => rec.productInfo._id === id) - if (idprod >= 0 && key) { - const myfield = key as keyof IProductInfo - productStore.products[idprod].productInfo[myfield] = value - }*/ } else if (table === 'arrvariazioni') { const productStore = useProducts(); const idprod = productStore.products.findIndex((rec: IProduct) => rec._id === id); diff --git a/src/rootgen/admin/importaprodotti/importaprodotti.vue b/src/rootgen/admin/importaprodotti/importaprodotti.vue index 93926181..6b5966ab 100755 --- a/src/rootgen/admin/importaprodotti/importaprodotti.vue +++ b/src/rootgen/admin/importaprodotti/importaprodotti.vue @@ -14,12 +14,13 @@ v-model="checkAggiornaQta" label="Aggiorna Quantità in Magazzino" > -