图寻tips

由于会被系统误判为作弊,目前已经违法使用,以后更新。需要特定地图才能提示,按Q键可以提示plonkit中的知识,比如:plonkit新手向等等,或者带有tips关键词的题库才能使用

// ==UserScript==
// @name         图寻tips
// @namespace    https://tuxun.fun/
// @version      4.8
// @description  由于会被系统误判为作弊,目前已经违法使用,以后更新。需要特定地图才能提示,按Q键可以提示plonkit中的知识,比如:plonkit新手向等等,或者带有tips关键词的题库才能使用
// @supportURL   https://sleazyfork.org/en/scripts/480332-图寻tips
// @author       yukejun
// @match        https://tuxun.fun/*
// @grant        GM_xmlhttpRequest
// @connect      knowledgetips.fun
// @connect      nominatim.openstreetmap.org
// @license MIT
// ==/UserScript==
(function() {
    'use strict';
    // 在闭包中初始化 isMatch
let isMatch = true;
   //
// CSS样式
const modalStyles = `
#customModal {
    cursor: move;
    display: none;
    position: fixed;
    z-index: 1000;
    top: 10vh;
    left: 10vw;
    background-color: #fff;
    padding: 5px;
    border-radius: 10px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    width: 80vw;
    max-width: 350px;
    transform: translate(0, 0);
    text-align: left;
    opacity: 0;
    visibility: hidden;
    border: 0.5px solid #000;
    transition: opacity 0.4s ease, visibility 0.4s ease, transform 0.4s ease; /* 添加 max-height 到过渡效果中 */
}
/* 添加显示时的样式 */
#customModal.show {
    opacity: 1;
    visibility: visible;
    transform: translate(0, 10px); /* 添加轻微的向下移动效果以增强动态感 */
}
/* 鼠标悬停时的按钮样式 */
.modalButton {
    padding: 2px 5px;
    border: 1px solid #ccc;
    border-radius: 2px;
    cursor: pointer;
    transition: box-shadow 0.3s ease; /* 添加过渡效果 */
}
.modalButton:hover {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); /* 鼠标悬停时的阴影效果 */
}
#customModal * {
    user-select: text; /* 允许文本选择 */
    cursor: auto; /* 设置鼠标为默认样式 */
}
/* 特定元素,如按钮,可能需要重写这些样式 */
#customModal button {
    user-select: none; /* 防止按钮文本被选择 */
    cursor: pointer; /* 为按钮设置手型鼠标样式 */
}
#setTimeButton {
    background-image: url('https://pic1.zhimg.com/80/v2-7c700be8d7b319f5845121926faaae37_1440w.png');
    background-size: contain;
    background-repeat: no-repeat;
    border: none; /* 移除边框 */
    width: 18px; /* 根据需要调整尺寸 */
    height: 18px; /* 根据需要调整尺寸 */
    cursor: pointer; /* 鼠标悬停时显示手型光标 */
    position: absolute;
    top: 3px;
    right: 50px;
    background-color: #ffffff;
}
#customModalHeader {
    cursor: pointer;
    padding: 7px;
    background-color: #fff;
}
#customModalHeader h2 {
    font-size: 1.5em;
    margin: 0;
    color: #333;
    text-align: left;
}
#pinModal {
    background-image: url('https://pic1.zhimg.com/80/v2-0b6c9fb7436ac72d00ccc1f49a3919c0_1440w.webp'); /* 默认图钉图片 */
    background-size: cover;
    background-repeat: no-repeat;
    background-position: center;
    color: transparent; /* 隐藏文本 */
    width: 21px; /* 设置合适的宽度 */
    height: 21px; /* 设置合适的高度 */
    position: absolute;
    top: 3px;
    right: 27px;
    background-color: #ffffff;
}
#modalContent {
    user-select: text;
    font-size: 16px;
    color: black;
    margin-top: 5px; /* 调整位置高度 */
    /* 根据需要,您也可以添加 margin-bottom */
}
#customInputBox {
    width: 90%;
    padding: 5px;
    margin: 10px 5%;
    border: 1px solid #ccc;
    border-radius: 5px;
    overflow-y: hidden;
    resize: none;
}
#modalClose {
    position: absolute;
    top: -4px;
    right: 8px;
    cursor: pointer;
    font-size: 1.5em;
    color: #333;
}
/* 响应式设计 */
@media (max-width: 600px) {
    #customModal {
        width: 95vw;
        left: 2.5vw;
        font-size: 14px;
    }
    #imageDisplay {
        width: 90%;
    }
    #customModalHeader {
        padding: 5px;
    }
}
@media (min-width: 601px) and (max-width: 800px) {
    #customModal {
        width: 70vw;
        left: 15vw;
        font-size: 16px;
    }
    #imageDisplay {
        width: 70%;
    }
}
/* 可以继续添加更多样式... */
/* 响应式设计 */
@media (max-width: 600px) {
    #customModal {
        width: 95vw;
        left: 2.5vw;
    }
}
#buttonGroup {
    display: flex;
    justify-content: center;
    gap: 5px;
    font-size: 14px;
}
.modalButton {
    padding: 5px 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
    cursor: pointer;
}
.centered-content {
    text-align: center;
    margin-bottom: 10px;
}
.locationSymbol {
    width: 20px;
    height: 25px;
    position: relative; /* 或者 'absolute',取决于您的需要 */
    top: 5px;  /* 向下移动5像素 */
    bottom: 5px; /* 向上移动5像素 */
    left: -5px; /* 向右移动10像素 */
}
#imageDisplay {
    width: 100%; /* 根据需要调整宽度 */
    margin-top: 10px;
    border-radius: 10px; /* 添加圆角 */
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); /* 添加阴影以增加深度感 */
    padding: 5px; /* 添加内边距 */
    background-color: #ffffff; /* 设定背景颜色 */
    transition: all 0.3s ease; /* 平滑过渡效果 */
}
.blankSpace {
    height: 5px; /* 您可以根据需要调整这个高度 */
    width: 100%;
}
.blankSpace1 {
    height: 5px; /* 您可以根据需要调整这个高度 */
    width: 100%;
}
.blankSpace2 {
    height: 5px; /* 您可以根据需要调整这个高度 */
    width: 100%;
}
.buttonActive {
    background-color: rgb(19, 206, 102); /* 浅绿色 */
    color: white;
}
.loader {
    border: 4px solid #3498db; /* 边框更细,整体为蓝色边框 */
    border-top: 3px solid #f3f3f3; /* 边框更细,顶部为轻色边框 */
    border-radius: 50%;
    width: 50px; /* 增大半径 */
    height: 50px; /* 增大半径 */
    animation: spin 2s linear infinite;
    margin: 0 auto; /* 水平居中 */
    display: block; /* 确保能够应用margin auto */
    margin-top: 25px; /* 增加顶部边距 */
}
@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}
`;
// HTML结构
const modalHTML = `
    <div id="customModal">
        <div id="customModalHeader">
            <h2>小技巧</h2>
            <div class="blankSpace1"></div> <!-- 新增的空白区域 -->
            <div id="buttonGroup" class="centered-content">
            <button class="modalButton" data-function="imagetip">Tips</button>
            <button class="modalButton" data-function="nationalflag">国旗</button>
            <button class="modalButton" data-function="areanumber">区编</button>
            <button class="modalButton" data-function="licensePlate">车牌</button>
            <button class="modalButton" data-function="text">文字</button>
            <button class="modalButton" data-function="tellphone">电话</button>
            </div>
            <div id="imageDisplayContainer">
            <img id="imageDisplay" src="" alt="显示图片" style="display:none;">
            </div>
            <div class="blankSpace"></div> <!-- 新增的空白区域 -->
            <button id="setTimeButton"></button>
            <button id="pinModal"></button>
            <div id="modalContent"></div>
            <textarea id="customInputBox" placeholder="在此输入内容..."></textarea>
        </div>
        <div style="text-align: center; margin-top: 10px;">
            <button id="addButton">新增</button>
        </div>
        <span id="modalClose">&times;</span>
    </div>
`;
    // 将CSS添加到页面
const styleSheet = document.createElement("style");
styleSheet.type = "text/css";
styleSheet.innerText = modalStyles;
document.head.appendChild(styleSheet);
    // 插入模态窗口到<body>的末尾
    document.body.insertAdjacentHTML('beforeend', modalHTML);
function updateModalPosition(x, y) {
    const modal = document.getElementById('customModal');
    modal.style.left = `${x}px`;
    modal.style.top = `${y}px`;
    localStorage.setItem('modalPosition', JSON.stringify({ x, y }));
}
function restoreModalPosition() {
    const modal = document.getElementById('customModal');
    const position = JSON.parse(localStorage.getItem('modalPosition'));
    if (position) {
        modal.style.left = `${position.x}px`;
        modal.style.top = `${position.y}px`;
    }
}
// 函数用于创建标签元素(段落和保存按钮)
function createTagElement(text, index) {
    // 创建一个 div 元素作为标签的外层容器
    const tagContainer = document.createElement('div');
    tagContainer.classList.add('tag-container'); // 添加类名以便应用CSS样式
    // 创建一个 div 元素来容纳标签的内容(编号和文本)
    const tagContentContainer = document.createElement('div');
    tagContentContainer.classList.add('tag-content-container'); // 添加类名
    // 创建一个 span 元素作为标签编号的容器
    const label = document.createElement('span');
    label.textContent = index !== undefined ? `${index + 1}. ` : ''; // 如果提供了 index,则显示编号
    label.classList.add('tag-label'); // 添加类名
    // 创建一个段落元素用于显示传入的文本
    const paragraph = document.createElement('p');
    paragraph.textContent = text; // 设置段落文本
    paragraph.contentEditable = false; // 设置为不可编辑
    paragraph.id = index !== undefined ? `tag-${index}` : undefined; // 如果提供了 index,则设置ID
    // 创建一个占位元素,用于在需要时占据保存按钮的空间
    const placeholder = document.createElement('div');
    placeholder.style.display = 'none'; // 初始状态隐藏
// 创建一个新的按钮元素
const saveButton = document.createElement('button');
// 设置按钮的文本内容为'保存'
saveButton.textContent = '保存';
// 给按钮添加一个CSS类名'save-button'
saveButton.classList.add('save-button');
// 根据index变量的值设置按钮的点击事件处理函数
saveButton.onclick = index !== undefined ?
    () => {
        saveTag(paragraph, index); // 如果index已定义,调用saveTag函数并传递paragraph和index参数
        saveButton.style.display = 'none'; // 点击后使按钮消失
    } :
    () => {
        saveTag(paragraph); // 如果index未定义,只调用saveTag函数并传递paragraph参数
        saveButton.style.display = 'none'; // 点击后使按钮消失
    };
// 设置按钮的初始显示状态为隐藏
saveButton.style.display = 'none';
    // 应用保存按钮的样式
    applyButtonStyles(saveButton);
    // 设置段落的双击事件处理函数
    // 使段落在双击时变为可编辑,并显示保存按钮和占位元素
    let isEditable = false; // 发布时需要更改的代码
    paragraph.ondblclick = function() {
        if (isEditable) {
            makeEditable(paragraph, saveButton, placeholder);
        }
        // 如果 isEditable 为 false,则不执行任何操作
    };
    // 从本地存储中获取创建者名称
    const creatorName = localStorage.getItem('creatorName');
    // 创建一个新段落来显示创建者信息
    const creatorParagraph = document.createElement('p');
    creatorParagraph.textContent = `${creatorName}`;
    creatorParagraph.classList.add('creator-info'); // 添加类名
    creatorParagraph.style.fontSize = '10px'; // 设置字体大小
    creatorParagraph.style.color = 'black'; // 设置字体颜色
    creatorParagraph.style.marginLeft = '60px'; // 设置左边距
    // 在段落旁边添加标签元素
    tagContentContainer.appendChild(label);
    tagContentContainer.appendChild(paragraph);
    tagContainer.appendChild(placeholder);
    tagContainer.appendChild(tagContentContainer);
    tagContainer.appendChild(creatorParagraph);
    tagContainer.appendChild(saveButton);
    return tagContainer;
}
// 函数使段落变为可编辑并显示保存按钮
function makeEditable(paragraph, saveButton, placeholder) {
    paragraph.contentEditable = "true";
    paragraph.focus(); // 立即聚焦到段落,方便编辑
    saveButton.style.display = 'inline-block'; // 显示保存按钮
    placeholder.style.display = 'block'; // 显示占位元素
}
// 应用按钮样式的函数
function applyButtonStyles(button) {
        // 使用响应式设计,例如min-width和min-height,以适应不同屏幕尺寸
    button.style.minWidth = '50px';
    button.style.minHeight = '25px';
    button.style.overflow = 'hidden'; // 防止内容溢出
    button.style.backgroundColor = '#4CAF50'; // 绿色背景
    button.style.color = 'white'; // 白色文字
    button.style.border = 'none'; // 无边框
    button.style.borderRadius = '5px'; // 圆角
    button.style.padding = '5px 5px'; // 内边距
    button.style.cursor = 'text'; // 鼠标悬停时的手指图标
    // 悬浮效果
    button.onmouseover = function() {
        button.style.backgroundColor = '#45a049'; // 深绿色
    };
    button.onmouseout = function() {
        button.style.backgroundColor = '#4CAF50'; // 原绿色
    };
}
    // 创建一个style元素并添加CSS
    function addCustomStyles() {
        const style = document.createElement('style');
        style.type = 'text/css';
        style.innerHTML = `
        .tag-container {
            display: flex;
            flex-direction: column;
            align-items: flex-end; // 所有子元素向右对齐
            margin-bottom: 10px;
            high: 110%
        }
        .tag-content-container {
            cursor: auto;
            display: flex;
            align-items: center; // 内部元素水平对齐
            flex-grow: 1;
            width: 100%; // 占满整个容器宽度
        }
        .tag-label {
            cursor: auto;
            margin-right: 8px;
            font-weight: bold;
            align-self: flex-start; // 标签向左上角对齐
        }
        .tag-container p {
            cursor: auto;
            margin: 0;
            margin-right: 8px;
            flex-grow: 1; // 让段落填满剩余空间
        }
        .save-button {
            display: none;
        }
        .creator-info {
            cursor: auto;
            align-self: flex-end; // 向右对齐
        }
        @media (max-width: 600px) {
            .save-button {
                // 小屏幕上的特定样式
                min-width: 30px;
                min-height: 10px;
                align-self: flex-end; // 向右对齐
            }
        }
    `;
        document.head.appendChild(style);
    }
window.onload = function() {
    // 获取所有的 .creator-info 元素
    var creatorInfoElements = document.querySelectorAll('.creator-info');
    let isPageFirstLoad = localStorage.getItem('isPageFirstLoad') !== 'false';
    if (isPageFirstLoad) {
        // 这里是第一次加载页面时需要执行的代码
        const storedTagsText = localStorage.getItem('tagsText');
        const storedImageUrls = JSON.parse(localStorage.getItem('imageUrls') || '[]');
        if (storedTagsText) {
            let modalContent = storedTagsText;
            showModal(modalContent); // 显示模态窗口
        }
        localStorage.setItem('isPageFirstLoad', 'false');
    }
    // 遍历所有元素并直接设置其样式
    creatorInfoElements.forEach(function(elem) {
        elem.style.fontSize = '14px'; // 设置字体大小
        elem.style.color = '#333333'; // 设置字体颜色
    });
};
const customInputBox = document.getElementById('customInputBox');
customInputBox.addEventListener('keyup', function(event) {
    adjustTextareaHeight(this);
});
    function adjustTextareaHeight(textarea) {
        textarea.style.height = 'auto'; // 重置高度
        textarea.style.height = textarea.scrollHeight + 'px'; // 根据内容调整高度
    }
// 函数用于激活模态窗口时阻止键盘事件传播
function preventKeyPropagation() {
    const modal = document.getElementById('customModal');
    modal.addEventListener('keydown', function(event) {
        event.stopPropagation(); // 阻止事件冒泡到父元素
        // 如果需要,也可以根据需求阻止默认行为
        // event.preventDefault();
    });
}
        // 在页面加载时调用函数以添加样式
window.addEventListener('load', function() {
        addCustomStyles(); // 添加自定义样式
        preventKeyPropagation(); // 防止键盘事件传播
        // 尝试从 localStorage 中获取模态窗口的位置
        const savedPosition = localStorage.getItem('modalPosition');
        if (savedPosition) {
        const { x, y } = JSON.parse(savedPosition);
        const modal = document.getElementById('customModal');
        if (modal) {
            // 设置模态窗口的位置
            modal.style.left = x + 'px';
            modal.style.top = y + 'px';
        }
    }
    //发布时需要添加的代码
    document.getElementById('addButton').style.display = 'none';
    document.getElementById('customInputBox').style.display = 'none';
    });
// 为 setTimeButton 按钮添加点击事件监听器
document.getElementById('setTimeButton').addEventListener('click', function() {
    event.stopPropagation()
    // 弹出一个对话框让用户输入新的倒计时时间
    let newTime = prompt("请输入新的倒计时时间(秒),时间必须是 3 秒或以上的正整数:");
    // 如果用户点击取消,newTime 将是 null,不执行任何操作
    if (newTime === null) {
        return;
    }
    // 验证输入是否为正整数且大于等于 3
    if (!isNaN(newTime) && Number.isInteger(parseFloat(newTime)) && parseInt(newTime) >= 3) {
        // 更新倒计时时间
        countdownTime = parseInt(newTime);
        // 将新的倒计时时间存储在 localStorage 中
        localStorage.setItem('countdownTime', countdownTime);
        // 可以在这里重新开始倒计时或者进行其他操作
    } else {
        alert("请输入有效的正整数(3秒或以上)!");
    }
});
// 全局变量,控制是否显示图片
let shouldDisplayImage = false;
let countdownTime = 30; // 默认倒计时时间为3秒
let countdownInterval; // 将倒计时定时器声明为全局变量
let immediateDisplay = false; // 新增一个全局变量来控制是否立即显示文本内容
// 从localStorage获取倒计时时间
function getStoredCountdownTime() {
    const storedCountdown = localStorage.getItem('countdownTime');
    if (storedCountdown !== null) {
        countdownTime = parseInt(storedCountdown, 10);
    }
}
// 显示模态窗口并在15秒内进行倒计时
function showModal(serverText) {
 //
    // 重置immediateDisplay为false
    immediateDisplay = false;
    // 获取存储的倒计时时间
    getStoredCountdownTime();
    const modal = document.getElementById('customModal');
    const modalContent = document.getElementById('modalContent');
    // 清空modalContent的内容
    modalContent.innerHTML = '倒计时: 15秒';
// 获取存储在 localStorage 中的各个地址组件
const storedAddress = localStorage.getItem('address');
const storedState = localStorage.getItem('state');
const storedRegion = localStorage.getItem('region');
const storedCity = localStorage.getItem('city');
const displayAddress = storedAddress || storedState || storedRegion || storedCity || '地址信息未找到';
//
const storedModalPosition = JSON.parse(localStorage.getItem('modalPosition'));
const storedImageUrl = localStorage.getItem('savedImageUrl');
if (storedModalPosition) {
    modal.style.left = storedModalPosition.x + 'px';
    modal.style.top = storedModalPosition.y + 'px';
}
    // 如果之前的倒计时仍在运行,则清除它
    if (countdownInterval) {
        clearInterval(countdownInterval);
    }
    // 初始化倒计时
    let countdown = countdownTime;
    // 设置一个每秒更新一次的定时器
    countdownInterval = setInterval(function() {
        if (immediateDisplay) {
            // 如果需要立即显示文本内容
            clearInterval(countdownInterval);
            displayContent(serverText, displayAddress);
            shouldDisplayImage = true;
        } else {
            countdown--;
           modalContent.innerHTML = `<p style="text-align: center; font-size: 18px; margin-top: 48px; position: relative; top: -20px;">倒计时: ${countdown}秒</p>`;
            // 当倒计时结束时
        if (countdown <= 0) {
            clearInterval(countdownInterval);
            displayContent(serverText, displayAddress);
            shouldDisplayImage = true;
        }
        }
    }, 1000);
    // 清空modalContent的内容
    modalContent.innerHTML = '<div class="loader"></div><p></p>';
   // 显示模态窗口
if (modal.style.display === 'none') {
    modal.style.display = 'block';
    modal.style.opacity = '1';
    modal.style.visibility = 'visible';
}
const wrapperElement = document.querySelector('.wrapper___NMMQn');
    if (wrapperElement) {
    const observer = new MutationObserver(function(mutations, obs) {
    const canvasElement = wrapperElement.querySelector('.mapConfirm___Q8fp1');
    if (canvasElement) {
    } else {
        skipCountdown();
        obs.disconnect();

    }
});
        observer.observe(wrapperElement, { childList: true, subtree: true });
    }else {
        console.log('wei找到选择器wrapper');
    }

}
// 显示最终内容的函数
function displayContent(serverText, displayAddress) {
    const locationSymbolHtml = `<img
    src="https://pic1.zhimg.com/80/v2-b5108764f32666bde67f8e7340b3350c_r.jpg"
alt="Location" class="locationSymbol" />`;
    modalContent.innerHTML = `<p>${locationSymbolHtml} ${displayAddress}</p>`;
    // 显示解析后的serverText内容
    const tags = serverText.split('; ');
    tags.forEach((tag, index) => {
        const tagElement = createTagElement(tag, index);
        modalContent.appendChild(tagElement);
    });
}
// 在需要的时候可以调用这个函数来立即显示文本内容
function skipCountdown() {
    immediateDisplay = true;
}
    // 关闭模态窗口的函数
    function closeModal() {
        const modal = document.getElementById('customModal');
        modal.style.opacity = '0';
        modal.style.visibility = 'hidden';
        setTimeout(() => modal.style.display = 'none', 100); // 确保过渡效果结束后再隐藏
    }
    //更新标签
function updateTagNumbers() {
    const tags = document.querySelectorAll('.tag-container');
    tags.forEach((tag, index) => {
        const label = tag.querySelector('.tag-label');
        if (label) {
            label.textContent = `${index + 1}. `;
        }
    });
}
// 全局变量
let isSaveTagActive = true; // 控制函数是否激活
// 函数保存编辑后的标签并发送数据到服务器
function saveTag(paragraph, index) {
    // 如果全局变量为 false,则函数不执行任何操作
    if (!isSaveTagActive) {
        return;
    }
    // 获取并处理编辑后的文本
    const editedText = paragraph.textContent.trim();
    paragraph.contentEditable = "false"; // 关闭可编辑状态
    // 从localStorage获取当前标签列表
    let tags = localStorage.getItem('tagsText') ? localStorage.getItem('tagsText').split('; ') : [];
    // 更新或移除标签
    if (index !== undefined) {
        if (editedText === '') {
            // 用户删除了所有文本,从标签数组中移除该标签
            tags.splice(index, 1);
if (editedText === '') {
    tags.splice(index, 1); // 从标签数组中移除该标签
    // 从 DOM 中移除标签元素及其内部元素
    const tagContainer = paragraph.parentElement.parentElement;
    if (tagContainer) {
        tagContainer.remove();
        updateTagNumbers(); // 更新标签编号
    }
}
        } else {
            // 更新指定索引的标签
            tags[index] = editedText;
        }
    } else if (editedText !== '') {
        // 添加新标签时,追加到标签数组的末尾
        tags.push(editedText);
    }
    // 过滤和更新标签列表
    tags = tags.filter(tag => tag && tag.trim());
    const updatedTagsText = tags.join('; ');
    localStorage.setItem('tagsText', updatedTagsText);
const storedCoordinates = JSON.parse(localStorage.getItem('newCoordinateName'));
    // 准备发送的数据
    const dataToSendtext = {
        mapsId: localStorage.getItem('mapsId'),
        coordinates: storedCoordinates,
        tagsText: updatedTagsText
    };
    // 隐藏保存按钮
    const saveButton = paragraph.parentElement.querySelector('.save-button');
    if (saveButton) {
        saveButton.style.display = 'none';
    }
}
//发布时添加
isSaveTagActive = false; // 关闭
isSaveTagActive = true;  // 开启
// 验证输入内容的函数
function isValidInput(input) {
    const maxLength = 300; // 最大字符长度设置为300
    // 检查长度
    if (input.length > maxLength) {
        alert(`输入的文本太长,请输入不超过 ${maxLength} 个字符的文本。`);
        return false;
    }
    return true;
}
// 新增标签的函数
function addNewTag() {
    //
    const inputBox = document.getElementById('customInputBox');
    const newText = inputBox.value.trim();
    if (newText && isValidInput(newText)) {
        const newTagElement = createTagElement(newText);
        const modalContent = document.getElementById('modalContent');
        modalContent.appendChild(newTagElement);
        // 保存新标签并发送到服务器
        saveTag(newTagElement.querySelector('p'));
        inputBox.value = '';
        // 更新所有标签的序号
        updateTagNumbers();
    }
    inputBox.value = ''; // 清空输入框
    // 重置文本框的高度
    const customInputBox = document.getElementById('customInputBox');
    customInputBox.style.height = '30px'; // 设置为初始高度或任意合适的固定高度
}
// 给新增按钮添加点击事件监听器
const addButton = document.getElementById('addButton');
    if (addButton) {
   //
} else {
  //
}
addButton.addEventListener('click', addNewTag);
// 置顶状态追踪变量
let isPinned = false;
// 从localStorage读取置顶状态
function loadPinState() {
    // 尝试从localStorage获取之前保存的状态
    const savedState = localStorage.getItem('isPinned');
    if (savedState !== null) {
        // 更新isPinned变量为保存的状态(需要将字符串转换为布尔值)
        isPinned = savedState === 'true';
    }
    // 更新按钮的显示
    updatePinButton();
}
// 更新置顶按钮的显示
function updatePinButton() {
    const pinButton = document.getElementById('pinModal');
    if (isPinned) {
        pinButton.style.backgroundImage = "url('https://pic1.zhimg.com/80/v2-0b6c9fb7436ac72d00ccc1f49a3919c0_1440w.webp')";
    } else {
        pinButton.style.backgroundImage = "url('https://pic2.zhimg.com/80/v2-893d2c6777c1205430e5fa2cc4019ae9_1440w.webp')";
    }
}
// 切换置顶状态的函数
function togglePin() {
    isPinned = !isPinned;
    // 保存当前状态到localStorage
    localStorage.setItem('isPinned', isPinned);
    // 更新按钮的显示
    updatePinButton();
}
// 添加置顶按钮的事件监听器
document.getElementById('pinModal').addEventListener('click', function(event) {
    togglePin();
    event.stopPropagation(); // 阻止事件冒泡到document,防止触发关闭模态窗口的逻辑
});
// 当页面加载时,读取并显示之前保存的置顶状态
window.addEventListener('load', loadPinState);
//以上是置顶函数变量
let isDragging = false;
let dragStartX, dragStartY;
let originalX, originalY;
document.getElementById('customModalHeader').addEventListener('mousedown', function(e) {
    if (e.target !== this && e.target !== document.querySelector('#customModalHeader h2')) {
        return;
    }
    isDragging = true;
    dragStartX = e.clientX;
    dragStartY = e.clientY;
    const modal = document.getElementById('customModal');
    originalX = parseInt(window.getComputedStyle(modal).left, 10);
    originalY = parseInt(window.getComputedStyle(modal).top, 10);
    e.preventDefault();
});
document.addEventListener('mousemove', function(e) {
    if (!isDragging) return;
    let newX = originalX + e.clientX - dragStartX;
    let newY = originalY + e.clientY - dragStartY;
    updateModalPosition(newX, newY);
});
document.addEventListener('mouseup', function(e) {
    if (isDragging) {
        isDragging = false;
        let newX = originalX + e.clientX - dragStartX;
        let newY = originalY + e.clientY - dragStartY;
        updateModalPosition(newX, newY);
                // 存储新位置到 localStorage
        localStorage.setItem('modalPosition', JSON.stringify({ x: newX, y: newY }));
    }
});
    // 点击模态窗口以外的区域关闭模态窗口
// 修改点击模态窗口以外区域关闭模态窗口的逻辑,加入置顶状态判断
document.addEventListener('click', function(event) {
    const modal = document.getElementById('customModal');
    // 如果模态窗口未被置顶,并且点击的不是模态窗口也不是模态窗口的子元素,则关闭模态窗口
    if (!isPinned && !modal.contains(event.target)) {
        closeModal();
    }
});

    document.getElementById('modalClose').addEventListener('click', closeModal);

    function toggleModal() {
        const modal = document.getElementById('customModal');
        if (modal.style.opacity === '1' || modal.style.visibility === 'visible') {
            modal.style.opacity = '0';
            modal.style.visibility = 'hidden';
            modal.style.display = 'none';
        } else {
            modal.style.opacity = '1';
            modal.style.visibility = 'visible';
            modal.style.display = 'block';
        }
    }
var shouldSend = true; 

    document.addEventListener("keyup", function(evt) {
        const targetTagName = (evt.target || evt.srcElement).tagName;
        if (evt.key === 'q' && targetTagName !== 'INPUT' && targetTagName !== 'TEXTAREA') {
            toggleModal();
       // 改变发送状态 shouldSend = !shouldSend;
        }
    });

    const mapsIdPattern = /mapsId=(\d+)|\/map\/(\d+)/;

const addressPattern = /\[\s*null,\s*null,\s*\[\s*(\[\s*"([^"]*)",\s*"([^"]*)"\s*\])(,\s*\[\s*"([^"]*)",\s*"([^"]*)"\s*\])?\s*\]\s*\]/;
    // 合并的正则表达式,用于匹配两种不同类型的坐标
const coordinatePattern = /\[\[null,null,(-?\d+\.\d+),(-?\d+\.\d+)\],\[\d+\.\d+\],\[\d+\.\d+,\d+\.\d+,\d+\.\d+\]\]|\[\s*null,\s*null,\s*(-?\d+\.\d+),\s*(-?\d+\.\d+)\s*\]|"lat":\s*(-?\d+\.\d+),\s*"lng":\s*(-?\d+\.\d+)/;
  // 保存原始的send方法
try {
    // 检查shouldSend变量
    if (shouldSend) {
        // 在发送请求之前保存请求的URL
    let currentUrl = this._url;
    // 初始化mapsIdChanged变量为false
    // 添加一个事件监听器来处理请求加载完成后的逻辑
    this.addEventListener("loadstart", function() {
        currentUrl = this._url; // 保存实际发送时的URL
// 当请求完成时检查URL
this.addEventListener("load", function() {
    // 从localStorage获取当前和之前的mapsId
    let previousMapsId = localStorage.getItem('previousMapsId');
    let currentMapsId = localStorage.getItem('mapsId');
    // 检查URL是否包含mapsId,如果不包含则从响应中获取
   if (this._url.includes('https://tuxun.fun/api/v0/tuxun/solo/get?gameId')) {
        var response = JSON.parse(this.responseText);
                    try {
    // 提取并打印 mapsId 字段
    if (response && response.data && response.data.mapsId !== undefined) {
        const newMapsId = response.data.mapsId;
        if (newMapsId !== currentMapsId) {
                localStorage.setItem('previousMapsId', currentMapsId);
                localStorage.setItem('mapsId', newMapsId);
        }

    } else {
        console.error("没找到");
    }
            } catch (error) {
                console.error("Error parsing JSON response:", error);
            }
    }

            // 在发布时需要删除这段代码,从URL中提取新的mapsId
if (currentUrl.includes('https://tuxun.fun/api/v0/tuxun/mapProxy/getGooglePanoInfoPost') ||
    currentUrl.includes('https://tuxun.fun/api/v0/tuxun/mapProxy/getPanoInfo?pano=')) {
        //
// 定义isCountryCode函数
function isCountryCode(str) {
    return /^[A-Za-z]{2}$/.test(str);
}
const responseText = this.responseText;
let addressMatches;
let isAddressFound = false;
let loopCount = 0;
let address;
while ((addressMatches = addressPattern.exec(responseText)) !== null && loopCount < 3) {
    loopCount++;

    if (addressMatches[5] && !isCountryCode(addressMatches[5])) {
        address = addressMatches[5];
        isAddressFound = true;

    }

    else if (addressMatches[2] && !isCountryCode(addressMatches[2])) {
        address = addressMatches[2];
        isAddressFound = true;
      //
    }
    if (isAddressFound) {

        break; 
    } else {
      //
    }
}
if (!isAddressFound) {
 //
}

if (isAddressFound) {
    const storedAddress = localStorage.getItem('address');
    if (address !== storedAddress) {
        localStorage.setItem('address', address);
    } else {
    }
} else {
    localStorage.removeItem('address');
}

if (coordinatePattern.test(responseText)) {

let latitude, longitude;
const matches = coordinatePattern.exec(responseText);
if (matches) {

    if (matches[1] !== undefined && matches[2] !== undefined) {
        latitude = matches[1];
        longitude = matches[2];
          }

    else if (matches[3] !== undefined && matches[4] !== undefined) {
        latitude = matches[3];
        longitude = matches[4];
      //
    }

    else if (matches[5] !== undefined && matches[6] !== undefined) {
        latitude = matches[5];
        longitude = matches[6];
            }
    if (latitude !== undefined && longitude !== undefined) {
let storedCoordinates = null 
const storedCoordinatesString = localStorage.getItem('newCoordinateName');
if (storedCoordinatesString) {

    try {
        if (storedCoordinatesString !== "null") {
            storedCoordinates = JSON.parse(storedCoordinatesString);

        }
    } catch (e) {
        console.error('解析存储的坐标时发生错误,使用默认坐标: ', e);
    }
}
const tolerance = 0.005;
let isWithinTolerance = true;
function isCoordinateCloseEnough(storedCoordinates, latitude, longitude, tolerance) {
    if (!storedCoordinates) {
        return true;
    }
    const latDifference = Math.abs(storedCoordinates.latitude - latitude);
    const lonDifference = Math.abs(storedCoordinates.longitude - longitude);
    if (latDifference > tolerance || lonDifference > tolerance) {
        isWithinTolerance = true; // 坐标不在容差范围内,设置isMatch为true
    } else {
        isWithinTolerance = false; // 坐标在容差范围内,设置isMatch为false
    }
    return isMatch;
}
function processIfCoordinateChanged(storedCoordinates, latitude, longitude) {
    if (isCoordinateCloseEnough(storedCoordinates, latitude, longitude, tolerance)) {
        const newCoordinates = { latitude: latitude, longitude: longitude };
        localStorage.setItem('newCoordinateName', JSON.stringify(newCoordinates));
        localStorage.removeItem('tagsText');
        localStorage.removeItem('state');
        localStorage.removeItem('address');
        getAddressAndProcessData(latitude, longitude);
        shouldDisplayImage = false;
        clearImageDisplay()
    } else {

    }
}
processIfCoordinateChanged(storedCoordinates, latitude, longitude)

function getAddress(lat, lon) {
    return new Promise((resolve) => {
        try {
            GM_xmlhttpRequest({
                method: "GET",
                url: `https://www.123.com`,
                onload: function(response) {
                   //
                    if (response.status === 200) {
                       //
                        resolve(JSON.parse(response.responseText));
                    } else {
                        resolve({ error: `无法获取地址。状态码: ${response.status}`, lat, lon }); // 使用 resolve 代替 reject
                    }
                },
                onerror: function(error) {

                    resolve({ error: "在获取地址时发生错误", lat, lon }); // 使用 resolve 代替 reject
                }
            });
        } catch (error) {

            resolve({ error: "在获取地址时发生异常", lat, lon }); // 使用 resolve 代替 reject
        }
    });
}

function checkAndSendRequest() {

    if (isMatch && isWithinTolerance) {
        sendRequest();
    }
}
function getAddressAndProcessData(latitude, longitude) {

    getAddress(latitude, longitude)
        .then(addressData => {
            if (addressData) {
                ['country', 'state', 'region', 'city'].forEach(key => {
                    processAddressData(addressData, key);
                });
            } else {
            }

checkAndSendRequest();

window.checkAndSendRequest = checkAndSendRequest;
    })
    .catch(errorData => {
        // 此处可以继续使用 errorData.lat 和 errorData.lon
    });
}

function processAddressData(data, key) {
    if (data && data.address && data.address[key]) {
        const value = data.address[key].split('/')[0].trim();
        const storedValue = localStorage.getItem(key);
        localStorage.setItem(key, value);
        // 如果 country 信息相同,则清除 localStorage 中的 country 信息
/*        if (key === 'country' && storedValue === value) {
            localStorage.removeItem(key);
        } else if (storedValue !== value) {
            // 对于 country 以外的信息,或者 country 信息不同,更新 localStorage
          //
            localStorage.setItem(key, value);
        }
*/
    } else {
    }
}
// 初始化一个变量来跟踪重试次数
let retryCount = 0;
    function sendRequest() {
                    const mapsId = localStorage.getItem('mapsId');
                    const country = localStorage.getItem('country');
                    // 定义将要发送的数据
                    const dataToSend = JSON.stringify({ mapsId, coordinates: `${latitude},${longitude}`,country });
                    // 使用GM_xmlhttpRequest发送坐标和mapsId到指定的服务器地址
                    GM_xmlhttpRequest({
                        method: "POST",
                        url: 'http://knowledgetips.fun:3000/receive-data',
                        data: JSON.stringify({ mapsId, coordinates: `${latitude},${longitude}`,country }),
                        headers: {
                            "Content-Type": "application/json"
                        },
onload: function(response) {
   //
    if (response && response.responseText) {
        try {
            const jsonResponse = JSON.parse(response.responseText);
            handleResponse(response);
        } catch (error) {
            console.error('解析响应时出错:', error);
            console.error('原始响应文本:', response.responseText);
        }
    } else {
        console.error('响应文本不存在或为空');
    }
},
    onerror: function(error) {
        // 检查是否已达到最大重试次数
        if (retryCount < 3) {
            retryCount++;
            setTimeout(sendRequest, 1000); // 1秒后重新发送请求
        } else {
        }
    },
                    });
}
function handleResponse(response) {
    try {
        const jsonResponse = JSON.parse(response.responseText);
        // 处理 jsonResponse
        processResponseData(jsonResponse);
        storeResponseData(jsonResponse);
        updateIsMatch(jsonResponse);
        updateButtonStates(jsonResponse);
    } catch (error) {
        console.error("解析JSON失败:", error);
    }
}
function storeResponseData(jsonResponse) {
    // 检查响应中是否包含 creator 字段
    if (jsonResponse.hasOwnProperty('creator')) {
        const creatorName = jsonResponse.creator;
        localStorage.setItem('creatorName', creatorName); // 将 creator 字段的内容存储在 localStorage 中
      //
    }
    // 检查响应中是否包含 images 字段
    if (jsonResponse.hasOwnProperty('images')) {
        const images = jsonResponse.images;
        localStorage.setItem('images', JSON.stringify(images)); // 将 images 字段的内容以字符串形式存储在 localStorage 中
      //
        // 检查是否存在 imagetip 键,并单独存储
        if (images.hasOwnProperty('imagetip')) {
            const imagetip = images.imagetip;
            localStorage.setItem('imagetip', imagetip); // 单独存储 imagetip 字段的内容
          //
        }
    }
}
function updateIsMatch(jsonResponse) {
        // 根据响应中的 mymapsid 值更新 isMatch 变量
        if (jsonResponse.hasOwnProperty('mymapsid')) {
            isMatch = jsonResponse.mymapsid;
        }
}
// ***********************控制按钮的颜色***********************  //
function updateButtonStates(jsonResponse) {
    const buttonContainer = document.getElementById('buttonGroup');
    const buttons = buttonContainer.querySelectorAll('button');
    // 首先,从所有按钮中移除 'buttonActive' 类
    buttons.forEach(button => button.classList.remove('buttonActive'));
    for (const key in jsonResponse.images) {
      //
        if (jsonResponse.images[key]) {
            const button = buttonContainer.querySelector(`button[data-function="${key}"]`);
            if (button) {
                button.classList.add('buttonActive');
               //
            } else {
             //
            }
        } else {
          //
        }
    }
}
// ***********************控制按钮的颜色***********************  //
function processResponseData(jsonResponse, coordinates) {
    if (jsonResponse.match === false) {
        return;
    }
    if (jsonResponse.match && jsonResponse.tags && jsonResponse.tags.join('; ').length >= 6) {
        // 将标签数组转换为文本并存储在localStorage中
        const tagsText = jsonResponse.tags.join('; ');
        // 更新模态窗口内容
        const modal = document.getElementById('customModal');
        if (modal.style.display !== 'none') {
            const modalContent = document.getElementById('modalContent');
            modalContent.textContent = tagsText; // 更新模态窗口内容
        }
        // 显示模态窗口
        localStorage.setItem('tagsText', tagsText);
        localStorage.setItem('coordinates', JSON.stringify(coordinates));
        showModal(tagsText);
    } else {
        skipCountdown()
        showModal('无提示');
    }
}
const customInputBox = document.getElementById('customInputBox');
function updateImagesDict() {
        // 检查是否在customInputBox中
    if (document.activeElement === customInputBox) {
       //
        return;
    }
        // 如果shouldDisplayImage为false,则不执行任何操作
    if (!shouldDisplayImage) {
       //
        return;
    }
    // 尝试从localStorage获取images字段
    const storedImages = localStorage.getItem('images');
 //
    let imagesDict = {};
    if (storedImages) {
        try {
            // 将存储的字符串转换为对象
            imagesDict = JSON.parse(storedImages);
        } catch (error) {
            console.error("解析images失败:", error);
        }
    }
    return imagesDict;
}
// 创建或获取img标签的函数
function getOrCreateImageTag() {
    let imgTag = document.getElementById('uniqueImageId');
    if (!imgTag) {
        imgTag = document.createElement('img');
        imgTag.id = 'uniqueImageId';
        // 设置样式
        Object.assign(imgTag.style, {
            height: "80vh", // 高度为视口高度的80%
            width: 'auto',
            backgroundColor: 'white',
            position: 'absolute',  // 绝对定位
            left: '30%',  // 水平居中
            top: '46%',  // 垂直居中
            transform: 'translate(-50%, -50%)',  // 用于确保准确居中
            zIndex: 1200, // 高层级
            display: 'none'  // 默认不显示图片
        });
        document.body.appendChild(imgTag);
    }
    return imgTag;
}
// 用于显示或隐藏图片的函数
function displayImage(fieldName, fieldKey) {
        // 如果shouldDisplayImage为false,则不执行任何操作
    // 每次调用时都从localStorage获取最新的imagesDict
    const imagesDict = updateImagesDict();
        // 在适当的时机调用 setupModalListener
    // 当imagesDict为空时,不执行任何操作
 try {
    if (Object.keys(imagesDict).length === 0) {
        return;
    }
        let imgTag;
        if (['1', '2', '3', '4', '5', '6'].includes(fieldKey)) {
            imgTag = document.getElementById('imageDisplay');
        } else {
            imgTag = getOrCreateImageTag();
        }
        // 检查imagesDict是否包含fieldName对应的项
        if (imgTag && imagesDict.hasOwnProperty(fieldName)) {
            if (imgTag.style.display === 'none' || imgTag.src !== imagesDict[fieldName]) {
                imgTag.src = imagesDict[fieldName];
                imgTag.style.display = 'block';
            } else {
                imgTag.style.display = 'none';
            }
        } else {
        }
    } catch (error) {
       // console.error(`显示图片时发生错误: ${error.message}`);
    }
}
function clearImageDisplay() {
    const imgTag = document.getElementById('imageDisplay');
    if (imgTag) {
        imgTag.style.display = 'none';  // 隐藏图片容器
      //
    } else {
    }
}
// 仅在必要时添加事件监听器
function setupEventListener() {
    const imagesDict = updateImagesDict();
    const existingListener = document.getElementById('imageDisplayListener');
    if (!existingListener) {
        const listenerTag = document.createElement('span');
        listenerTag.id = 'imageDisplayListener';
        document.body.appendChild(listenerTag);
        document.addEventListener('keyup', function(event) {
            const fieldKeyMap = {
                '1': 'imagetip',
                '2': 'nationalflag',
                '3': 'areanumber',
                '4': 'licensePlate',
                '5': 'text',
                '6': 'tellphone',
                'e': 'mapjpg',
                'r': '3dmap',
                't': 'climateimg'
            };
            const fieldKey = event.key;
            const fieldName = fieldKeyMap[fieldKey];
            if (fieldName) {
             //
                displayImage(fieldName, fieldKey, imagesDict);
            } else {
              //
            }
        });
    }
}
/****************************以下这段代码有bug不知道怎么解决,
就是在点击事件中,总会被重复执行,随着游戏轮次增加
每次点击按钮显示图片,都会被重复执行
当点击一次按钮时,会输出三次点击效果,如果是第四轮游戏,就会同时输出四次点击效果,以此类推。。。
*/
// 假设 setupEventListener 是在这个函数内定义的
function outerFunction(callback) {
function setupModalListener() {
    const buttonGroup = document.getElementById('buttonGroup');
    if (buttonGroup) {
        buttonGroup.addEventListener('click', function(event) {
            if (event.target && event.target.classList.contains('modalButton')) {
                // 根据按钮的 data-function 属性确定要显示的图片
                const fieldName = event.target.getAttribute('data-function');
                const fakeEvent = { key: '1' };
                displayImage(fieldName, fakeEvent.key);
            }
        });
    } else {
    }
}
// displayImage 函数保持不变
setupModalListener();
}
//*********上面这段代码
// 执行事件监听器设置
setupEventListener();
        // ... 其他需要坐标的函数
    } else {
    }
                    } else {
    }
            // 确保在这一点之后使用 latitude 和 longitude
if (latitude !== undefined && longitude !== undefined) {
    // 使用 latitude 和 longitude 的代码
    // ...
}
        }else {
    // 清空modalContent的内容
    modalContent.innerHTML = '';
//
    }
            }
    }, false);
// 括号被移动到最后了
});
        }
        realSend.call(this, value); // 使用正确的上下文调用原始send方法
    } catch (error) {
        console.error("send方法替换中发生错误:", error);
        // 可以选择在出错时调用原始send方法或者处理错误
        realSend.call(this, value);
    }

// 重写open方法以捕获请求URL
XMLHttpRequest.prototype.realOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
    this._url = url; // 保存请求的URL
    this.realOpen(method, url, async, user, pass);
};
    if (XMLHttpRequest.prototype.send === XMLHttpRequest.prototype.realSend) {
      //  console.error('Tampermonkey script failed to override XMLHttpRequest.send.');
    } else {
    }
})();

QingJ © 2025

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