图寻tips

需要特定地图才能提示,按1键可以提示plonkit中的知识,比如:plonkit新手向等等,或者带有tips关键词的题库才能使用

目前為 2023-12-07 提交的版本,檢視 最新版本

// ==UserScript==
// @name         图寻tips
// @namespace    https://tuxun.fun/
// @version      2.3
// @description  需要特定地图才能提示,按1键可以提示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';
const modalHTML = `
    <div id="customModal" style="
        cursor: move; /* 设置鼠标为可移动状态 */
        display: none; /* 初始设置为不显示,更改为block显示模态窗口 */
        position: fixed; /* 固定位置 */
        z-index: 1000; /* 设置堆叠顺序 */
        top: 10vh; /* 距离顶部10%的视口高度 */
        left: 10vw; /* 距离左侧10%的视口宽度 */
        background-color: #eee; /* 背景颜色 */
        padding: 5px; /* 内边距 */
        border-radius: 10px; /* 边框圆角 */
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); /* 盒子阴影 */
        width: 80vw; /* 宽度(这里可能是个错误,180vw可能过大) */
        max-width: 350px; /* 最大宽度 */
        transform: translate(0, 0); /* 移动转换(之前的负值已移除) */
        text-align: left; /* 文本对齐方式 */
        opacity: 0; /* 初始设置为透明,更改为1显示 */
        visibility: hidden; /* 初始设置为隐藏,更改为visible显示 */
    ">
    <div id="customModalHeader" style="cursor: move; padding: 10px; background-color: #eee;">
        <h2 style="cursor: move; user-select: none; margin-top: 0; margin-bottom: 20px; font-size: 1.5em; color: #333;">小技巧</h2>
    <!-- 图片模态窗口 -->
<div id="imageModal" style="display:none;">
    <button id="toggleButton">地图</button>
</div>
        <button id="pinModal" style="position: absolute; top: 3px; right: 30px; cursor: pointer;">📌</button>
        <div id="modalContent" style="user-select: text;">无提示</div>
        <!-- 新增文本输入框 -->
        <input type="text" id="customInputBox" placeholder="在此输入内容..." style="
            width: 90%; /* 输入框宽度 */
            padding: 5px; /* 内边距 */
            margin: 10px 5%; /* 外边距,水平居中 */
            border: 1px solid #ccc; /* 边框 */
            border-radius: 5px; /* 边框圆角 */
        ">
        <!-- 设置按钮 -->
          <div id="settingsPanel" style="display: none; padding: 10px; background-color: #f9f9f9; border-bottom: 1px solid #ccc;">
          <label for="countdownTime">设置倒计时(秒):</label>
          <input type="number" id="countdownTime" value="15" min="1" style="margin-right: 10px;">
          <button id="saveSettings">保存设置</button>
    </div>
        <!-- 新增按钮 -->
        <div style="text-align: center; margin-top: 10px;">
            <button id="addButton" style="padding: 5px 15px; border: none; border-radius: 5px; cursor: pointer;">新增</button>
        </div>
        <span id="modalClose" style="
            position: absolute;
            top: -4px;
            right: 8px;
            cursor: pointer;
            font-size: 1.5em;
            color: #333;
        ">&times;</span>
    </div>
`;
    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) {
    const tagContainer = document.createElement('div');
    tagContainer.classList.add('tag-container');
    const label = document.createElement('span');
    label.textContent = index !== undefined ? `${index + 1}. ` : '';
    label.classList.add('tag-label');
    const paragraph = document.createElement('p');
    paragraph.textContent = text;
    paragraph.contentEditable = "true";
    paragraph.id = index !== undefined ? `tag-${index}` : undefined;
    const placeholder = document.createElement('div');
    placeholder.style.display = 'none';
    const saveButton = document.createElement('button');
    saveButton.textContent = '保存';
    saveButton.classList.add('save-button');
    saveButton.onclick = index !== undefined ? () => saveTag(paragraph, index) : () => saveTag(paragraph);
    saveButton.style.display = 'none';
    applyButtonStyles(saveButton);
    paragraph.ondblclick = function() {
        makeEditable(paragraph, saveButton, placeholder);
    };
    tagContainer.appendChild(label);
    tagContainer.appendChild(paragraph);
    tagContainer.appendChild(placeholder);
    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) {
    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';
    };
}
    function addCustomStyles() {
        const style = document.createElement('style');
        style.type = 'text/css';
        style.innerHTML = `
        .tag-container {
            display: flex;
            align-items: flex-start;
            margin-bottom: 10px;
        }
        .tag-label {
            margin-right: 8px;
            font-weight: bold;
        }
        .tag-container p {
            margin: 0;
            flex-grow: 1;
            margin-right: 8px;
        }
        .save-button {
            display: none;
            align-self: center;
            flex-shrink: 0;
        }
        @media (max-width: 600px) {
            .save-button {
                min-width: 40px;
                min-height: 20px;
            }
        }
    `;
        document.head.appendChild(style);
    }
function preventKeyPropagation() {
    const modal = document.getElementById('customModal');
    modal.addEventListener('keydown', function(event) {
        event.stopPropagation();
    });
}
window.addEventListener('load', function() {
        addCustomStyles();
        preventKeyPropagation();
        localStorage.removeItem('imageUrls');
        localStorage.removeItem('imageUrl');
        document.getElementById('addButton').style.display = 'none';
        document.getElementById('customInputBox').style.display = 'none';
    });
let countdownInterval;
let shouldDisplayServerText = true;
function showModal(serverText) {
    const modal = document.getElementById('customModal');
    const modalContent = document.getElementById('modalContent');
    modalContent.innerHTML = '倒计时: 15秒';
    const storedAddress = localStorage.getItem('address') || localStorage.getItem('state') || '地址信息未找到';
    const storedModalPosition = JSON.parse(localStorage.getItem('modalPosition'));
    if (storedModalPosition) {
        modal.style.left = storedModalPosition.x + 'px';
        modal.style.top = storedModalPosition.y + 'px';
    }
    modalContent.innerHTML = `<p>倒计时: 15秒</p><p>地址信息: ${storedAddress}</p>`;
    if (countdownInterval) {
        clearInterval(countdownInterval);
    }
    let countdown = 3;
    countdownInterval = setInterval(function() {
        countdown--;
        modalContent.innerHTML = `<p>倒计时: ${countdown}秒</p>`;
        if (countdown <= 0) {
            clearInterval(countdownInterval);
            modalContent.innerHTML = `<p>省份:${storedAddress}</p>`;
            const tags = serverText.split('; ');
            tags.forEach((tag, index) => {
                const tagElement = createTagElement(tag, index);
                modalContent.appendChild(tagElement);
            });
        }
    }, 1000);
    modalContent.innerHTML = '倒计时: 15秒';
    if (modal.style.display !== 'none') {
        modal.style.display = 'block';
        modal.style.opacity = '1';
        modal.style.visibility = 'visible';
    }
}
    function closeModal() {
        const modal = document.getElementById('customModal');
        modal.style.opacity = '0';
        modal.style.visibility = 'hidden';
        setTimeout(() => modal.style.display = 'none', 100);
    }
function saveTag(paragraph, index) {
const editedText = paragraph.textContent.trim();
paragraph.contentEditable = "false";
let tags = [];
tags = localStorage.getItem('tagsText') ? localStorage.getItem('tagsText').split('; ') : [];
    if (index !== undefined) {
        if (editedText === '') {
            tags.splice(index, 1);
            const tagContainer = paragraph.parentElement;
            if (tagContainer) {
                tagContainer.remove();
            }
        } 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('coordinates'));
const dataToSend = {
    mapsId: localStorage.getItem('mapsId'),
    coordinates: storedCoordinates,
    tagsText: updatedTagsText
};
const saveButton = paragraph.parentElement.querySelector('.save-button');
if (saveButton) {
    saveButton.style.display = 'none';
}
    GM_xmlhttpRequest({
        method: "POST",
        url: 'http://knowledgetips.fun:3000/save-data',
        data: JSON.stringify(dataToSend),
        headers: {
            "Content-Type": "application/json"
        },
        onload: function(response) {
        }
    });
}
    //更新标签
function updateTagNumbers() {
    const tags = document.querySelectorAll('.tag-container');
    tags.forEach((tag, index) => {
        const label = tag.querySelector('.tag-label');
        if (label) {
            label.textContent = `${index + 1}. `;
        }
    });
}
function addNewTag() {
    const inputBox = document.getElementById('customInputBox');
    const newText = inputBox.value.trim();
    if (newText) {
        const newTagElement = createTagElement(newText);
        const modalContent = document.getElementById('modalContent');
        modalContent.appendChild(newTagElement);
        saveTag(newTagElement.querySelector('p'));
        inputBox.value = '';
        updateTagNumbers();
    }
}
const addButton = document.getElementById('addButton');
    if (addButton) {
} else {
}
addButton.addEventListener('click', addNewTag);
let isPinned = false;
function loadPinState() {
    const savedState = localStorage.getItem('isPinned');
    if (savedState !== null) {
        isPinned = savedState === 'true';
    }
    updatePinButton();
}
function updatePinButton() {
    const pinButton = document.getElementById('pinModal');
    pinButton.textContent = isPinned ? '📍' : '📌';
}
function togglePin() {
    isPinned = !isPinned;
    localStorage.setItem('isPinned', isPinned);
    updatePinButton();
}
document.getElementById('pinModal').addEventListener('click', function(event) {
    togglePin();
    event.stopPropagation();
});
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);
    }
});
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';
        }
    }
    document.addEventListener("keydown", function(evt) {
        const targetTagName = (evt.target || evt.srcElement).tagName;
        if (evt.key === '1' && targetTagName !== 'INPUT' && targetTagName !== 'TEXTAREA') {
            toggleModal();
        }
    });
    const mapsIdMatch = window.location.href.match(/maps-start\?mapsId=(\d+)/);
    const mapsId = mapsIdMatch ? mapsIdMatch[1] : localStorage.getItem('mapsId') || '未找到ID';
    if (mapsIdMatch) {
        localStorage.setItem('mapsId', mapsId);
    }
    const mapsIdPattern = /mapsId=(\d+)/;
const addressPattern = /\[\["(.*?)","zh"\]\]|\[\[.*?,\["(.*?)","zh"\]\]\]/;
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*\]/;
var realSend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(value) {
    let currentUrl = this._url;
    this.addEventListener("loadstart", function() {
        currentUrl = this._url;
    });
this.addEventListener("load", function() {
    let previousMapsId = localStorage.getItem('previousMapsId');
    let currentMapsId = localStorage.getItem('mapsId');
    if (!currentUrl.includes('mapsId=')) {
        const responseText = this.responseText;
        const mapsIdMatches = mapsIdPattern.exec(responseText);
        if (mapsIdMatches) {
            const newMapsId = mapsIdMatches[1];
            if (newMapsId !== currentMapsId) {
                localStorage.setItem('previousMapsId', currentMapsId);
                localStorage.setItem('mapsId', newMapsId);
            }
        }
    }
    if (this._url.includes('https://tuxun.fun/api/v0/tuxun/party/changeMaps')) {
        const newMapsIdMatch = this._url.match(mapsIdPattern);
        if (newMapsIdMatch) {
            const newMapsId = newMapsIdMatch[1];
            if (newMapsId !== currentMapsId) {
                localStorage.setItem('previousMapsId', currentMapsId);
                localStorage.setItem('mapsId', newMapsId);
            }
        }
    }
    currentMapsId = localStorage.getItem('mapsId');
    previousMapsId = localStorage.getItem('previousMapsId');
    if (currentMapsId !== previousMapsId) {
        //
    } else {
        //
    }
        if (currentUrl.includes('https://tuxun.fun/api/v0/tuxun/mapProxy/getGooglePanoInfoPost')) {
        //
const responseText = this.responseText;
let addressMatches;
let isAddressFound = false;
let loopCount = 0;
let dummyVar = Math.random();
function confuseFunction(data) {
    return data.split('').reverse().join('');
}
while ((addressMatches = addressPattern.exec(responseText)) !== null && loopCount < 3) {
    loopCount++;
    isAddressFound = true;
    const address = addressMatches[1] || addressMatches[2];
    const encryptedAddress = confuseFunction(address);
    const storedAddress = localStorage.getItem('address');
    if (address !== storedAddress) {
        localStorage.setItem('address', address);
    } else {
    }
    break;
}
if (!isAddressFound) {
    localStorage.removeItem('address');
}
if (coordinatePattern.test(responseText)) {
            //
let latitude, longitude;
const matches = coordinatePattern.exec(responseText);
if (matches) {
 //
  function confuse() {
    var seed = Math.random();
    return seed.toString(36).substring(2, 15);
  }
  var unused = confuse();
  var coordinateData = {lat: undefined, lon: undefined};
    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];
    }
    (function(){
        var fakeLat = Math.random() * 100;
        var fakeLon = Math.random() * 100;
        //
    })();
    if (latitude !== undefined && longitude !== undefined) {
                const storedCoordinatesString = localStorage.getItem('coordinates');
                let storedCoordinates = null;
                if (storedCoordinatesString) {
                    storedCoordinates = JSON.parse(storedCoordinatesString);
                }else {
}
                const tolerance = 0.008;
if (!storedCoordinates || !isCoordinateCloseEnough(storedCoordinates, latitude, longitude, tolerance)) {
    localStorage.removeItem('tagsText');
    const coordinates = { latitude, longitude };
    localStorage.setItem('coordinates', JSON.stringify(coordinates));

function getAddress(lat, lon) {
    return new Promise((resolve, reject) => {
        GM_xmlhttpRequest({
            method: "GET",
            url: `https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lon}&format=json`,
            onload: function(response) {
                //
                if (response.status === 200) {
                    //
                    resolve(JSON.parse(response.responseText));
                } else {
                    //
                    reject(`Failed to fetch address. Status: ${response.status}`);
                }
            },
            onerror: function(error) {
                reject("Error occurred while fetching address");
            }
        });
    });
}
getAddress(latitude, longitude)
    .then(addressData => {
        if (addressData && addressData.address && addressData.address.country) {
            const fullCountryString = addressData.address.country;
            //
            const country = fullCountryString.split('/')[0].trim();
            localStorage.setItem('country', country);
            const storedCountry = localStorage.getItem('country');
            if (storedCountry && storedCountry !== country) {
            }
            localStorage.setItem('country', country);
        } else {
        }
        if (addressData && addressData.address && addressData.address.state) {
            localStorage.setItem('state', addressData.address.state);
            const fullStateString = addressData.address.state;
            const state = fullStateString.split('/')[0].trim();
        } else {
        }
                    const country = localStorage.getItem('country');

                    const dataToSend = JSON.stringify({ mapsId, coordinates: `${latitude},${longitude}`,country });


                    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) {


                            const jsonResponse = JSON.parse(response.responseText);

                            if (jsonResponse.match && jsonResponse.tags) {


                                const tagsText = jsonResponse.tags.join('; ');

if (jsonResponse.images && jsonResponse.images.length > 0) {
    let isImageZoomed = false;
    let zoomedImg;
    function updateImage(url) {
        if (!zoomedImg) {
            zoomedImg = document.createElement('img');
            zoomedImg.id = 'myImage';
            document.body.appendChild(zoomedImg);
            zoomedImg.addEventListener('dblclick', function() {
                zoomedImg.style.display = "none";
                isImageZoomed = false;
            });
        }
        if (zoomedImg.src !== url) {
            zoomedImg.src = url;
        }
        zoomedImg.style.position = 'fixed';
        zoomedImg.style.top = '50%';
        zoomedImg.style.left = '50%';
        zoomedImg.style.transform = 'translate(-50%, -50%)';
        zoomedImg.style.width = "auto";
        zoomedImg.style.height = "80vh";
        zoomedImg.style.objectFit = "contain";
        zoomedImg.style.zIndex = 1000;
    }
    function toggleImageZoom() {
        let newImageUrl = jsonResponse.images[0];
        updateImage(newImageUrl);
        if (!isImageZoomed) {
            zoomedImg.style.display = "block";
            isImageZoomed = true;
        } else {
            zoomedImg.style.display = "none";
            isImageZoomed = false;
        }
    }
    document.addEventListener('keydown', function(event) {
        if (event.keyCode === 50) {
            toggleImageZoom();
            event.preventDefault();
        }
    });
}
                                localStorage.setItem('tagsText', tagsText);
                                 //
                                localStorage.setItem('coordinates', JSON.stringify(coordinates));

                                const modal = document.getElementById('customModal');
                                if (modal.style.display !== 'none') {
                                    const modalContent = document.getElementById('modalContent');

                                        modalContent.textContent = tagsText;
                                }


                                showModal(tagsText);
                            }else{

                                    modalContent.innerHTML = '无提示';
                            }
                        },
                    });
    })
    .catch(error => {
    });
                } else {
}
function isCoordinateCloseEnough(storedCoordinates, latitude, longitude, tolerance) {
    const latDifference = Math.abs(storedCoordinates.latitude - latitude);
    const lonDifference = Math.abs(storedCoordinates.longitude - longitude);
    return latDifference <= tolerance && lonDifference <= tolerance;
}
            }else {
}
                    } else {
    }
if (latitude !== undefined && longitude !== undefined) {
}
        }else {
    modalContent.innerHTML = '';
    }
            }
    }, false);
    realSend.call(this, value);
};
XMLHttpRequest.prototype.realOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
    this._url = url;
    this.realOpen(method, url, async, user, pass);
};
    if (XMLHttpRequest.prototype.send === XMLHttpRequest.prototype.realSend) {
    } else {
    }
})();

QingJ © 2025

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