DealerNotificaFluxo

Notifica o usuário sobre novos fluxos no DealerNet.

当前为 2024-11-27 提交的版本,查看 最新版本

// ==UserScript==
// @name         DealerNotificaFluxo
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Notifica o usuário sobre novos fluxos no DealerNet.
// @author       Igor Lima
// @match        http*://*.dealernetworkflow.com.br/Portal/default.html
// @match        http*://*.dealernetworkflow.com.br/WP_Fluxo.aspx
// @grant        none
// @license      MIT
// ==/UserScript==

/*
    Este código foi gerado por um modelo de IA. Embora tenha sido projetado para ser funcional,
    pode ser necessário realizar uma revisão, testes ou modificações para atender às suas necessidades específicas.
    Verifique o código quanto à correção e adequação antes de utilizá-lo em ambientes de produção.
*/                                                                                                                                                                                           

(function() {
    'use strict';

    // Configuração do script
    const configuracao = {

        //Fluxos a serem procurados e notificados, em formato regex, sempre seguindo o padrão: /^nomedofluxo\(\d+\)$/,
        procurarFluxos: [
            /^Duplicar E-mail \(\d+\)$/,
            /^Recebimento de Garantia da Oficina \(\d+\)$/,
            /^Requisição da Oficina \(\d+\)$/,
        ],

        notificacaoHabilitada: true, //Ativa/desativa a notificação, mantendo o realçamento do botão de Administração

        margemTopo: 60, //Margem em pixels do topo da página, usado para notificações,

        notificacaoTempo: 5000, //Tempo (em ms) que a notificação permanece na tela

        intervaloAtualizacaoFluxos: 60000, // Intervalo (em ms) para atualizar os fluxos
        intervaloVerificacaoNotificacao: 10000, // Intervalo que o script procura novos fluxos para notificar

        idBotao: 'ext-gen26', //Botão da barra superior que será realçado ao encontrar fluxos, deixar em branco caso queira somente a notificação.
        textoBotao: 'Administração', //Texto do botão, redundância pro script não alterar o botão errado caso mudarem o id do botão de Administração pra outra coisa
        classeIframe: 'W5Portal_Window_Frame', //Classe do iframe contendo a página inicial
        idTabelaFluxo: 'W0038GridfluxoContainerTbl', //Tablea contendo os fluxos
        intervaloVerificacaoIframe: 1000 // Intervalo para verificar se o iframe foi carregado, por padrão verifica a cada 1 segundo (1000 ms)
    };

    let botaoModificado = false;
    let fluxosNotificados = new Set();
    let contagemFluxos = new Map(); // Para rastrear as contagens de cada fluxo

    // Função auxiliar para modificar o botão de administração e atualizar o tooltip
    const modificarBotao = (fluxos) => {
        const botao = document.getElementById(configuracao.idBotao);
        if (botao && botao.textContent.includes(configuracao.textoBotao)) {
            // Adicionar ícone de sino, se não estiver presente
            if (!botao.querySelector('.icone-sino')) {
                const iconeSino = document.createElement('span');
                iconeSino.innerHTML = '📢';
                iconeSino.style.marginRight = '5px';
                iconeSino.classList.add('icone-sino');
                botao.prepend(iconeSino);
                botao.style.fontWeight = 'bold';
                botao.style.color = 'red';
                botaoModificado = true;
            }

            // Atualizar tooltip com fluxos encontrados e suas contagens
            const tooltipFluxos = Array.from(contagemFluxos.entries())
                .map(([fluxo, count]) => `${fluxo}`)
                .join('\n');
            botao.title = tooltipFluxos;
        }
    };

    // Reverter o botão de administração para o estado original
    const reverterBotao = () => {
        const botao = document.getElementById(configuracao.idBotao);
        if (botao && botao.querySelector('.icone-sino')) {
            botao.querySelector('.icone-sino').remove();
            botao.style.fontWeight = 'normal';
            botao.style.color = '';
            botao.title = '';
            botaoModificado = false;
        }
    };

    // Notificar o usuário sobre os fluxos encontrados
    const mostrarNotificacao = (fluxos) => {
        const notificacao = document.createElement('div');
        notificacao.style = `
            position: fixed; right: 0; top: ${configuracao.margemTopo}px;
            background: #FFF;
            color: black; padding: 15px 20px;
            border-radius: 8px 0px 0px 8px;
            max-width: 350px; z-index: 9999; font-family: 'Arial', sans-serif;
            box-shadow: 0 8px 15px rgba(0, 0, 0, 0.2);
            transform: translateX(100%); transition: transform 0.5s ease-in-out, opacity 0.3s ease-in-out;
            opacity: 0;
            border: 1px solid #999;
            cursor: pointer;
        `;

        // Fechar a notificação ao clicar
        notificacao.onclick = () => {
            notificacao.style.transform = 'translateX(100%)';
            notificacao.style.opacity = '0';
            setTimeout(() => notificacao.remove(), 500); // Remover notificação após animação de saída
        };

        // Título
        const titulo = document.createElement('strong');
        titulo.style = 'font-size: 18px; display: block; font-weight: bold; margin-bottom: 5px;';
        titulo.textContent = '🔔 Novos fluxos encontrados';
        notificacao.appendChild(titulo);

        // Corpo
        const corpo = document.createElement('div');
        corpo.style = 'font-size: 14px; white-space: pre-wrap; line-height: 1.4;';
        corpo.textContent = Array.from(fluxos).join('\n');
        notificacao.appendChild(corpo);

        document.body.appendChild(notificacao);

        // Animação de entrada
        setTimeout(() => {
            notificacao.style.transform = 'translateX(0)';
            notificacao.style.opacity = '1';
        }, 100);

        // Animação de saída após tempo configurado
        setTimeout(() => {
            notificacao.style.transform = 'translateX(100%)';
            notificacao.style.opacity = '0';
        }, configuracao.notificacaoTempo);
    };

    // Verificar a tabela de fluxos e aplicar lógica
    const verificarFluxos = (iframe) => {
        const docIframe = iframe.contentDocument || iframe.contentWindow.document;
        if (!docIframe) return;

        const tabela = docIframe.getElementById(configuracao.idTabelaFluxo);
        const fluxosEncontrados = new Set();

        if (tabela) {
            const celulas = tabela.getElementsByTagName('td');
            const contagemAtualFluxos = new Map(); // Rastrear as contagens atuais

            // Iterar sobre as células da tabela e encontrar fluxos correspondentes
            for (let celula of celulas) {
                const textoCelula = celula.textContent.trim();
                configuracao.procurarFluxos.forEach(padrao => {
                    const correspondencia = textoCelula.match(padrao);
                    if (correspondencia) {
                        const nomeFluxo = correspondencia[0]; // O nome do fluxo correspondente
                        const correspondenciaContagem = textoCelula.match(/\((\d+)\)/); // Extrair a contagem
                        const contagem = correspondenciaContagem ? parseInt(correspondenciaContagem[1]) : 1;

                        contagemAtualFluxos.set(nomeFluxo, contagem);
                        fluxosEncontrados.add(`${nomeFluxo}`);
                    }
                });
            }

            // Comparar contagens atuais com contagens anteriores e notificar se aumentarem
            let notificarNovamente = false;
            contagemAtualFluxos.forEach((contagem, nomeFluxo) => {
                const contagemAnterior = contagemFluxos.get(nomeFluxo) || 0;
                if (contagem > contagemAnterior) {
                    notificarNovamente = true; // Acionar nova notificação se alguma contagem aumentar
                }
            });

            if (fluxosEncontrados.size > 0) {
                contagemFluxos = new Map(contagemAtualFluxos); // Atualizar contagens
                modificarBotao(fluxosEncontrados);

                // Acionar notificação se as contagens aumentarem ou se for a primeira notificação
                if (notificarNovamente || configuracao.notificacaoHabilitada && fluxosEncontrados.size > fluxosNotificados.size) {
                    mostrarNotificacao(fluxosEncontrados);
                    fluxosNotificados = new Set([...fluxosEncontrados]); // Atualizar fluxos notificados
                }
            } else if (botaoModificado) {
                reverterBotao();
                contagemFluxos.clear(); // Limpar contagens, já que nenhum fluxo está presente
                fluxosNotificados.clear(); // Limpar o conjunto de notificações, já que nenhum fluxo está presente
            }
        }
    };

    // Detectar quando o iframe foi totalmente carregado
    const esperarCarregamentoIframe = () => {
        const iframe = document.querySelector(`.${configuracao.classeIframe}`);
        if (iframe) {
            iframe.onload = () => verificarFluxos(iframe); // Executar verificação quando o iframe estiver totalmente carregado
            verificarFluxos(iframe); // Verificação imediata se o iframe já estiver carregado
        }
    };

    // Verificar continuamente a presença do iframe e monitorar fluxos
    const verificarContinuamenteIframe = () => {
        const intervaloId = setInterval(() => {
            const iframe = document.querySelector(`.${configuracao.classeIframe}`);
            if (iframe) {
                clearInterval(intervaloId); // Parar de verificar quando o iframe for encontrado
                esperarCarregamentoIframe(); // Agora, esperar o carregamento do conteúdo do iframe
            }
        }, configuracao.intervaloVerificacaoIframe);
    };

    // Lógica principal do script baseada na página atual
    const site = window.location.pathname;
    if (site === '/Portal/default.html') {
        verificarContinuamenteIframe(); // Continuar verificando o iframe até que seja carregado
        setInterval(verificarContinuamenteIframe, configuracao.intervaloVerificacaoNotificacao); // Re-verificar o iframe e fluxos a cada 10 segundos
    } else if (site === '/WP_Fluxo.aspx') {
        setInterval(() => gx.evt.execEvt('W0038E\'DOATUALIZAR\'.', this), configuracao.intervaloAtualizacaoFluxos); // Acionar atualização da página periodicamente
    }

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址