Informe sobre Solicitud de Autorización de Plantación
1. DATOS DE LA SOLICITUD
COORDENADAS ETRS89 / UTM
📍 PULSA AQUÍ PARA OBTENER LAS COORDENADAS
También puedes escribir o corregir X e Y manualmente.
2. ESPECIE Y SUPERFICIE CON LAS QUE SE PROYECTA REPOBLAR
3. USO ACTUAL DE LOS TERRENOS OBJETO DE LOS TRABAJOS
4. EN LA FINCA EXISTEN PIES DE
5. LA REPOBLACIÓN AFECTARÁ A
6. DESCRIPCIÓN GENERAL DE LA VEGETACIÓN EXISTENTE EN EL ÁREA
(1) Indicar el grado de presencia: P: Predominante; A: Abundante; E: Escasa; N: Nula
8. ANEXO CARTOGRÁFICO
🗺️ AÑADIR MAPA
Puedes seleccionar uno o varios mapas, planos, croquis o capturas cartográficas.
Añade aquí uno o varios mapas, planos, croquis o capturas cartográficas.
9. DOCUMENTACIÓN FOTOGRÁFICA
11. DOCUMENTACIÓN ADJUNTA — PDF
Puedes seleccionar uno o varios documentos PDF.
Los PDF quedan adjuntos en esta ficha y pueden abrirse desde la lista.
🟢 Guardado automático activo
💾 GUARDAR FICHA COMPLETA
Guarda una copia del informe con los datos, fotografías y documentación adjunta incorporados.
Esa copia se puede llevar del ordenador al móvil y volver al ordenador.
🖨️ GENERAR PDF
🗑️ BORRAR FORMULARIO
';
const bloqueFin='';
const bloque=
bloqueInicio+
'\n
', bloque+'\n');
}
const nombreSugerido=
'Ficha_Inspeccion_'+
new Date().toISOString().slice(0,10)+'_'+
new Date().toTimeString().slice(0,5).replace(':','-')+
'.html';
const blob=new Blob(['\n'+copia],{type:'text/html;charset=utf-8'});
const url=URL.createObjectURL(blob);
const a=document.createElement('a');
a.href=url;
a.download=nombreSugerido;
document.body.appendChild(a);
a.click();
a.remove();
setTimeout(()=>URL.revokeObjectURL(url),5000);
if(estado){
estado.textContent='🟢 Ficha completa guardada';
estado.className='autosave-status';
}
alert('Ficha guardada correctamente.\n\nLa copia descargada contiene los datos, fotografías y PDFs.');
}catch(e){
console.error(e);
alert('No se pudo guardar la ficha completa: '+e.message);
}
}
function aplicarDatosPortatiles(){
const bloque=document.getElementById('portableData');
if(!bloque) return;
try{
const datos=JSON.parse(bloque.textContent || '{}');
const elementos=document.querySelectorAll('input, textarea, select');
(datos.campos || []).forEach(item=>{
const el=elementos[item.i];
if(!el || el.type==='file') return;
if(el.type==='checkbox' || el.type==='radio'){
el.checked=!!item.checked;
}else{
el.value=item.value ?? '';
}
});
const fotos=datos.fotos || {};
Object.keys(fotos).forEach(id=>{
const img=document.getElementById(id);
if(!img || !fotos[id]) return;
img.src=fotos[id];
img.style.display='block';
});
if(typeof pdfAdjuntos !== 'undefined'){
(datos.pdfs || []).forEach(p=>{
if(!p.data) return;
try{
const byteString=atob(p.data.split(',')[1]);
const mime=p.data.split(',')[0].match(/:(.*?);/)[1];
const ab=new ArrayBuffer(byteString.length);
const ia=new Uint8Array(ab);
for(let i=0;i{
aplicarDatosPortatiles();
if(autosaveReady) programarGuardado();
},150);
}
});
document.addEventListener('visibilitychange',function(){
if(document.visibilityState==='hidden' && autosaveReady){
guardarBackupCamposLocal();
guardarEnDB();
}
});
window.addEventListener('pagehide',function(){
if(autosaveReady){
guardarBackupCamposLocal();
guardarEnDB();
}
});
/* ============================================================
ANEXO CARTOGRÁFICO — guardado independiente
============================================================ */
const CARTO_DB='FichaPlantacionCartografiaDB';
const CARTO_STORE='mapas';
let cartoDB=null;
function abrirDBCartografia(){
return new Promise((resolve,reject)=>{
if(cartoDB){resolve(cartoDB);return;}
const req=indexedDB.open(CARTO_DB,1);
req.onupgradeneeded=e=>{
const db=e.target.result;
if(!db.objectStoreNames.contains(CARTO_STORE)){
db.createObjectStore(CARTO_STORE,{keyPath:'id'});
}
};
req.onsuccess=e=>{cartoDB=e.target.result;resolve(cartoDB);};
req.onerror=()=>reject(req.error);
});
}
async function guardarMapaCartografico(registro){
try{
const db=await abrirDBCartografia();
await new Promise((resolve,reject)=>{
const tx=db.transaction(CARTO_STORE,'readwrite');
tx.objectStore(CARTO_STORE).put(registro);
tx.oncomplete=resolve;
tx.onerror=()=>reject(tx.error);
});
}catch(e){console.error('No se pudo guardar el mapa',e);}
}
async function borrarMapaCartografico(id){
try{
const db=await abrirDBCartografia();
await new Promise((resolve,reject)=>{
const tx=db.transaction(CARTO_STORE,'readwrite');
tx.objectStore(CARTO_STORE).delete(id);
tx.oncomplete=resolve;
tx.onerror=()=>reject(tx.error);
});
}catch(e){}
}
async function obtenerMapasCartograficos(){
try{
const db=await abrirDBCartografia();
return await new Promise((resolve,reject)=>{
const tx=db.transaction(CARTO_STORE,'readonly');
const req=tx.objectStore(CARTO_STORE).getAll();
req.onsuccess=()=>resolve(req.result||[]);
req.onerror=()=>reject(req.error);
});
}catch(e){return [];}
}
function comprimirMapaCartografico(file,maxDimension=1800,calidad=.88){
return new Promise((resolve,reject)=>{
const reader=new FileReader();
reader.onload=e=>{
const img=new Image();
img.onload=()=>{
let w=img.naturalWidth||img.width;
let h=img.naturalHeight||img.height;
if(w>maxDimension||h>maxDimension){
const escala=Math.min(maxDimension/w,maxDimension/h);
w=Math.round(w*escala);
h=Math.round(h*escala);
}
const canvas=document.createElement('canvas');
canvas.width=w;
canvas.height=h;
canvas.getContext('2d').drawImage(img,0,0,w,h);
resolve(canvas.toDataURL('image/jpeg',calidad));
};
img.onerror=reject;
img.src=e.target.result;
};
reader.onerror=reject;
reader.readAsDataURL(file);
});
}
function actualizarClaseCantidadMapas(){
const cont=document.getElementById('contenedorMapasCartograficos');
if(!cont) return;
const n=cont.querySelectorAll('.carto-item').length;
cont.classList.remove('map-count-0','map-count-1','map-count-2','map-count-many');
if(n===0) cont.classList.add('map-count-0');
else if(n===1) cont.classList.add('map-count-1');
else if(n===2) cont.classList.add('map-count-2');
else cont.classList.add('map-count-many');
}
function pintarMapaCartografico(registro){
const cont=document.getElementById('contenedorMapasCartograficos');
if(!cont)return;
const aviso=document.getElementById('avisoCartografico');
if(aviso)aviso.style.display='none';
const item=document.createElement('div');
item.className='carto-item';
item.dataset.cartoId=registro.id;
const borrar=document.createElement('button');
borrar.type='button';
borrar.className='carto-delete';
borrar.textContent='Eliminar mapa';
borrar.onclick=async()=>{
if(confirm('¿Eliminar este mapa del anexo cartográfico?')){
await borrarMapaCartografico(registro.id);
item.remove();
actualizarClaseCantidadMapas();
if(!cont.querySelector('.carto-item')&&aviso)aviso.style.display='block';
}
};
const img=document.createElement('img');
img.src=registro.data;
const pie=document.createElement('input');
pie.type='text';
pie.className='carto-caption';
pie.placeholder='Descripción del mapa (p. ej. plano de situación, detalle de la finca...)';
pie.value=registro.caption||'';
pie.addEventListener('input',()=>{
clearTimeout(pie._timer);
pie._timer=setTimeout(()=>{
registro.caption=pie.value;
guardarMapaCartografico(registro);
},350);
});
item.appendChild(borrar);
item.appendChild(img);
item.appendChild(pie);
cont.appendChild(item);
actualizarClaseCantidadMapas();
}
async function anadirMapasCartograficos(input){
const archivos=Array.from(input.files||[]);
for(const file of archivos){
try{
const data=await comprimirMapaCartografico(file);
const registro={
id:'mapa_'+Date.now()+'_'+Math.random().toString(36).slice(2),
data:data,
caption:'',
fecha:new Date().toISOString()
};
await guardarMapaCartografico(registro);
pintarMapaCartografico(registro);
}catch(e){
alert('No se pudo añadir uno de los mapas.');
}
}
input.value='';
}
async function recuperarMapasCartograficos(){
const mapas=await obtenerMapasCartograficos();
mapas.sort((a,b)=>(a.fecha||'').localeCompare(b.fecha||''));
mapas.forEach(pintarMapaCartografico);
actualizarClaseCantidadMapas();
}
window.addEventListener('load',()=>setTimeout(recuperarMapasCartograficos,300));