1***@qq.com
1***@qq.com
  • 发布:2025-03-14 13:15
  • 更新:2025-03-14 13:57
  • 阅读:132

我的前端转背单词软件apk,在ipad ,ipad pro,nexus 7 可以显示完整,但如果在普通安卓手机上不会显示,是能指导一下啊

分类:HBuilder

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>记忆曲线单词学习</title>
<style>
body {
margin: 0;
padding: 20px;
font-family: Arial, sans-serif;
background: #f0f0f0;
}

    .container {  
        display: flex;  
        gap: 20px;  
        height: calc(100vh - 40px);  
    }  

    .grid-container {  
        flex: 1;  
        overflow: auto;  
        background: rgb(3, 77, 36);  
        border-radius: 8px;  
        box-shadow: 0 2px 4px rgba(0,0,0,0.1);  
        position: relative;  
    }  

    .grid {  
        position: absolute;  
        top: 0;  
        left: 0;  
        transform-origin: 0 0;  
        transition: transform 0.1s;  
    }  

    .cell {  
        position: absolute;  
        width: 20px;  
        height: 20px;  
        border: 1px solid #ddd;  
        cursor: pointer;  
        transition: background-color 0.3s;  
    }  

    .cell:hover {  
        border-color: #666;  
    }  

    .cell.gray { background-color: #ccc; }  
    .cell.green { background-color: #90EE90; }  
    .cell.yellow { background-color: #FFD700; }  
    .cell.red { background-color: #FF6B6B; }  

    .sidebar {  
        width: 300px;  
        background: rgb(13, 56, 8);  
        border-radius: 8px;  
        padding: 20px;  
        box-shadow: 0 2px 4px rgba(0,0,0,0.1);  
        display: flex;  
        flex-direction: column;  
        gap: 20px;  
        color: white;  
    }  

    .word-detail {  
        position: fixed;  
        top: 50%;  
        left: 50%;  
        transform: translate(-50%, -50%);  
        padding: 30px;  
        border: 1px solid #ddd;  
        border-radius: 8px;  
        display: none;  
        background: rgba(13, 56, 8, 0.95);  
        color: white;  
        z-index: 1000;  
        min-width: 300px;  
        max-width: 80%;  
        max-height: 80vh;  
        overflow-y: auto;  
        box-shadow: 0 4px 12px rgba(0,0,0,0.2);  
    }  

    .word-detail.active {  
        display: block;  
    }  

    .word-detail h3 {  
        margin-top: 0;  
        color: #4CAF50;  
    }  

    .word-detail p {  
        margin: 10px 0;  
        line-height: 1.6;  
    }  

    .word-detail textarea {  
        width: 100%;  
        padding: 10px;  
        border-radius: 4px;  
        border: 1px solid rgba(255,255,255,0.2);  
        background: rgba(255, 255, 255, 0.1);  
        color: white;  
        margin: 10px 0;  
        min-height: 100px;  
        resize: vertical;  
        font-family: inherit;  
    }  

    .word-detail textarea:focus {  
        outline: none;  
        border-color: #4CAF50;  
    }  

    .word-detail .button-group {  
        display: flex;  
        gap: 10px;  
        margin-top: 10px;  
    }  

    .word-detail .notes-display {  
        margin: 10px 0;  
        padding: 10px;  
        border-radius: 4px;  
        background: rgba(255, 255, 255, 0.05);  
        white-space: pre-wrap;  
        display: none;  
        min-height: 50px;  
        word-wrap: break-word;  
    }  

    .word-detail .notes-display.active {  
        display: block;  
    }  

    .overlay {  
        position: fixed;  
        top: 0;  
        left: 0;  
        right: 0;  
        bottom: 0;  
        background: rgba(0,0,0,0.5);  
        display: none;  
        z-index: 999;  
    }  

    .overlay.active {  
        display: block;  
    }  

    .controls {  
        display: flex;  
        gap: 10px;  
        margin-bottom: 20px;  
        flex-wrap: wrap;  
    }  

    button {  
        padding: 8px 16px;  
        border: none;  
        border-radius: 4px;  
        background: #4CAF50;  
        color: white;  
        cursor: pointer;  
    }  

    button:hover {  
        background: #45a049;  
    }  

    .zoom-controls {  
        position: fixed;  
        bottom: 20px;  
        right: 20px;  
        display: flex;  
        gap: 10px;  
    }  

    .zoom-controls button {  
        width: 40px;  
        height: 40px;  
        border-radius: 50%;  
        display: flex;  
        align-items: center;  
        justify-content: center;  
        font-size: 20px;  
    }  

    #notes {  
        width: 100%;  
        padding: 10px;  
        border-radius: 4px;  
        border: 1px solid #ddd;  
        background: rgba(255, 255, 255, 0.1);  
        color: white;  
    }  

    .settings {  
        margin-top: 20px;  
        padding: 10px;  
        border: 1px solid #ddd;  
        border-radius: 4px;  
        background: rgba(255, 255, 255, 0.1);  
    }  

    .settings label {  
        display: block;  
        margin-bottom: 10px;  
        color: white;  
    }  

    .sync-status {  
        display: none;  
    }  

    .sync-status.success {  
        display: none;  
    }  

    .sync-status.error {  
        display: none;  
    }  

    .sync-button {  
        display: none;  
    }  

    .sync-button:hover {  
        display: none;  
    }  

    .sync-button:disabled {  
        display: none;  
    }  
</style>  

</head>
<body>
<div class="container">
<div class="grid-container">
<div class="grid" id="grid"></div>
</div>
<div class="sidebar">
<div class="controls">
<button onclick="addNewWord()">添加新单词</button>
<button onclick="exportData()">导出JSON文件</button>
<button onclick="importData()">导入JSON文件</button>
<button onclick="exportToClipboard()">导出到剪切板</button>
<button onclick="importFromText()">从文本框导入</button>
<button onclick="showBatchImport()">批量导入</button>
</div>
</div>
<div class="settings">
<h3>设置</h3>
<label>
<input type="checkbox" id="requirePhonetic" checked> 要求输入音标
</label>
</div>
</div>
</div>
<div class="zoom-controls">
<button onclick="zoomIn()">+</button>
<button onclick="zoomOut()">-</button>
</div>
<div class="overlay" id="overlay"></div>
<div class="word-detail" id="wordDetail">
<h3>单词详情</h3>
<div class="display-toggle">
<label>
<input type="checkbox" id="displayToggle" onchange="toggleDisplayMode()"> 显示英文
</label>
</div>
<p id="wordText"></p>
<p id="wordMeaning"></p>
<p id="wordPhonetic"></p>
<textarea id="notes" placeholder="在这里添加学习笔记..."></textarea>
<div class="button-group">
<button onclick="saveNotes()">保存笔记</button>
<button onclick="deleteWord(parseInt(document.getElementById('wordDetail').dataset.currentIndex))">删除单词</button>
<button onclick="closeWordDetail()">关闭</button>
</div>
</div>
<textarea id="importTextArea" placeholder="在这里粘贴JSON数据以导入" style="width: 100%; height: 100px; margin-top: 20px;"></textarea>
<script>
// 修改存储单词数据的结构
let words = [];
let scale = 1;
let notes = {};
let lastViewTimes = {};
let viewHistory = {}; // 新增:存储每个单词的所有查看时间
let showEnglish = true; // 控制显示英文还是中文
let currentWordIndex = null; // 当前显示的单词索引

    // 初始化  
    function init() {  
        loadData();  
        createGrid();  
        updateColors();  
        initEventListeners();  
        setInterval(updateColors, 30000); // 每分钟更新一次颜色  
    }  

    // 创建网格  
    function createGrid() {  
        const grid = document.getElementById('grid');  
        const wordCount = words.length;  
        const gridSize = Math.ceil(Math.sqrt(wordCount));  

        grid.style.width = `${gridSize * 20}px`;  
        grid.style.height = `${gridSize * 20}px`;  

        for (let i = 0; i < wordCount; i++) {  
            const cell = document.createElement('div');  
            cell.className = 'cell';  
            cell.style.left = `${(i % gridSize) * 20}px`;  
            cell.style.top = `${Math.floor(i / gridSize) * 20}px`;  
            cell.onclick = () => showWordDetail(i);  
            grid.appendChild(cell);  
        }  
    }  

    // 修改 showWordDetail 函数  
    function showWordDetail(index) {  
        currentWordIndex = index;  
        const word = words[index];  
        const detail = document.getElementById('wordDetail');  
        const overlay = document.getElementById('overlay');  
        const wordText = document.getElementById('wordText');  
        const wordMeaning = document.getElementById('wordMeaning');  
        const wordPhonetic = document.getElementById('wordPhonetic');  
        const notesTextarea = document.getElementById('notes');  

        detail.dataset.currentIndex = index;  

        // 根据显示模式设置内容  
        if (showEnglish) {  
            wordText.textContent = word.text;  
            wordMeaning.textContent = '';  
        } else {  
            wordText.textContent = '';  
            wordMeaning.textContent = word.meaning;  
        }  
        wordPhonetic.textContent = word.phonetic;  
        notesTextarea.value = notes[index] || '';  

        detail.classList.add('active');  
        overlay.classList.add('active');  

        if (!viewHistory[index]) {  
            viewHistory[index] = [];  
        }  
        viewHistory[index].push(Date.now());  
        lastViewTimes[index] = Date.now();  
        saveData();  
        updateColors();  
    }  

    // 关闭单词详情  
    function closeWordDetail() {  
        const detail = document.getElementById('wordDetail');  
        const overlay = document.getElementById('overlay');  
        detail.classList.remove('active');  
        overlay.classList.remove('active');  
    }  

    // 修改 updateColors 函数来使用复习次数  
    function updateColors() {  
        const cells = document.querySelectorAll('.cell');  
        const now = Date.now();  

        cells.forEach((cell, index) => {  
            const history = viewHistory[index] || [];  
            const reviewCount = history.length;  
            const lastView = lastViewTimes[index] || 0;  
            const timeDiff = now - lastView;  

            // 根据复习次数和时间间隔设置不同的颜色  
            if (reviewCount >= 9) { // 9次以上复习  
                if (timeDiff < 5184000000) { // 30天内  
                    cell.className = 'cell green';  
                } else {  
                    cell.className = 'cell yellow';  
                }  

            } else if (reviewCount == 8) { // 8次复习  
                if (timeDiff < 2592000000) { // 15天内  
                    cell.className = 'cell green';  
                } else {  
                    cell.className = 'cell yellow';  
                }  

            } else if (reviewCount == 7) { // 7次复习  
                if (timeDiff < 1209600000) { // 7天内  
                    cell.className = 'cell green';  
                } else {  
                    cell.className = 'cell yellow';  
                }  
            } else if (reviewCount == 6) { // 6次复习  
                if (timeDiff < 518400000) { // 3天内  
                    cell.className = 'cell green';  
                } else {  
                    cell.className = 'cell yellow';  
                }  

            } else if (reviewCount == 5) { // 5次复习  
                if (timeDiff <172800000 ) { // 1天内  
                    cell.className = 'cell green';  
                } else {  
                    cell.className = 'cell yellow';  
                }  

            } else if (reviewCount == 4) { // 4次复习  
                if (timeDiff < 43200000) { // 12小时  
                    cell.className = 'cell green';  
                } else if (timeDiff < 50400000) { // 2小时内  
                    cell.className = 'cell yellow';  
                } else {  
                    cell.className = 'cell red';  
                }  

            } else if (reviewCount == 3) { // 3次复习  
                if (timeDiff < 7200000) { // 2小时  
                    cell.className = 'cell green';  
                } else if (timeDiff < 14400000) { // 2小时内  
                    cell.className = 'cell yellow';  
                } else {  
                    cell.className = 'cell red';  
                }  

            } else if (reviewCount == 2) { // 2次复习  
                if (timeDiff < 1800000) { // 30分钟  
                    cell.className = 'cell green';  
                } else if (timeDiff < 9000000) { // 2小时内  
                    cell.className = 'cell yellow';  
                } else {  
                    cell.className = 'cell red';  
                }  

            } else { // 原有的时间间隔逻辑 1次复习  
                if (timeDiff < 300000) { // 5分钟内  
                    cell.className = 'cell green';  
                } else if (timeDiff < 1800000) { // 30分钟内  
                    cell.className = 'cell yellow';  
                } else if (timeDiff < 7200000) { // 2小时内  
                    cell.className = 'cell red';  
                } else {  
                    cell.className = 'cell gray';  
                }  
            }  
        });  
    }  

    // 添加新单词  
    function addNewWord() {  
        const text = prompt('输入单词:');  
        if (!text) return;  

        const meaning = prompt('输入中文含义:');  
        if (!meaning) return;  

        let phonetic = '';  
        if (document.getElementById('requirePhonetic').checked) {  
            phonetic = prompt('输入音标(可选):');  
        }  

        const index = words.length;  
        words.push({ text, meaning, phonetic });  
        notes[index] = ''; // 初始化该单词的笔记  
        createGrid();  
        saveData();  
    }  

    // 批量导入单词  
    function showBatchImport() {  
        const text = prompt('请输入单词列表(格式: "单词": "含义"):');  
        if (!text) return;  

        try {  
            const lines = text.split('\n');  
            lines.forEach(line => {  
                const match = line.match(/"([^"]+)":\s*"([^"]+)"/);  
                if (match) {  
                    const [_, text, meaning] = match;  
                    const index = words.length;  
                    words.push({ text, meaning, phonetic: '' });  
                    notes[index] = ''; // 初始化该单词的笔记  
                }  
            });  
            createGrid();  
            saveData();  
            alert('批量导入成功!');  
        } catch (error) {  
            alert('导入失败,请检查格式是否正确');  
        }  
    }  

    // 修改 saveData 函数  
    function saveData() {  
        const data = {  
            words,  
            lastViewTimes,  
            notes,  
            viewHistory // 添加 viewHistory 到保存数据中  
        };  
        localStorage.setItem('memoryCurveData', JSON.stringify(data));  
    }  

    // 修改 loadData 函数,仅从本地加载数据  
    function loadData() {  
        const localData = localStorage.getItem('memoryCurveData');  
        if (localData) {  
            try {  
                const parsed = JSON.parse(localData);  
                words = parsed.words || [];  
                lastViewTimes = parsed.lastViewTimes || {};  
                notes = parsed.notes || {};  
                viewHistory = parsed.viewHistory || {}; // 加载历史记录  
            } catch (error) {  
                console.error('本地数据加载失败:', error);  
                words = [];  
                lastViewTimes = {};  
                notes = {};  
                viewHistory = {};  
            }  
        }  
    }  

    // 导出数据  
    function exportData() {  
        const data = {  
            words,  
            lastViewTimes,  
            notes,  
            viewHistory  
        };  
        const blob = new Blob([JSON.stringify(data)], { type: 'application/json' });  
        const url = URL.createObjectURL(blob);  
        const a = document.createElement('a');  
        a.href = url;  
        a.download = 'memory_curve_data.json';  
        a.click();  
        URL.revokeObjectURL(url);  
    }  

    // 导入数据  
    function importData() {  
        const input = document.createElement('input');  
        input.type = 'file';  
        input.accept = '.json';  
        input.onchange = (e) => {  
            const file = e.target.files[0];  
            const reader = new FileReader();  
            reader.onload = (event) => {  
                const data = JSON.parse(event.target.result);  
                words = data.words || [];  
                lastViewTimes = data.lastViewTimes || {};  
                notes = data.notes || {};  
                viewHistory = data.viewHistory || {};  
                createGrid();  
                updateColors();  
            };  
            reader.readAsText(file);  
        };  
        input.click();  
    }  

    // 保存笔记  
    function saveNotes() {  
        const detail = document.getElementById('wordDetail');  
        const index = parseInt(detail.dataset.currentIndex);  
        const noteContent = document.getElementById('notes').value;  

        if (!isNaN(index)) {  
            notes[index] = noteContent;  
            saveData();  
            alert('笔记已保存');  
        }  
    }  

    // 缩放控制  
    function zoomIn() {  
        scale *= 1.2;  
        updateZoom();  
    }  

    function zoomOut() {  
        scale /= 1.2;  
        updateZoom();  
    }  

    function updateZoom() {  
        const grid = document.getElementById('grid');  
        grid.style.transform = `scale(${scale})`;  
    }  

    // 鼠标滚轮缩放  
    document.querySelector('.grid-container').addEventListener('wheel', (e) => {  
        e.preventDefault();  
        if (e.deltaY < 0) {  
            zoomIn();  
        } else {  
            zoomOut();  
        }  
    });  

    // 初始化事件监听  
    function initEventListeners() {  
        // ESC键关闭  
        document.addEventListener('keydown', (e) => {  
            if (e.key === 'Escape') {  
                closeWordDetail();  
            } else if (e.key === 'z') {  
                selectRandomYellowWord();  
            } else if (e.key === 'v') {  
                selectRandomRedWord();  
            } else if (e.key === 'x') {  
                showEnglish = true;  
                toggleContent();  
            } else if (e.key === 'c') {  
                showEnglish = false;  
                toggleContent();  
            } else if (e.key === ' ' && document.querySelector('.word-detail.active')) {  
                e.preventDefault();  
                toggleContent();  
            }  
        });  

        // 点击遮罩层关闭  
        document.getElementById('overlay').addEventListener('click', closeWordDetail);  

        // 添加鼠标点击事件  
        document.querySelector('.word-detail').addEventListener('click', (e) => {  
            if (e.target.tagName !== 'BUTTON' && e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA') {  
                toggleContent();  
            }  
        });  
    }  

    // 添加显示模式切换函数  
    function toggleDisplayMode() {  
        showEnglish = document.getElementById('displayToggle').checked;  
        if (currentWordIndex !== null) {  
            showWordDetail(currentWordIndex);  
        }  
    }  

    // 修改 deleteWord 函数为全新的实现  
    function deleteWord(index) {  
        if (confirm('确定要删除这个单词吗?')) {  
            // 保存所有数据的临时备份 - 注意原始索引对应关系  
            const oldNotes = {...notes};  
            const oldLastViewTimes = {...lastViewTimes};  
            const oldViewHistory = {...viewHistory};  

            // 移除要删除的单词  
            words.splice(index, 1);  

            // 完全清空原有的对象  
            notes = {};  
            lastViewTimes = {};  
            viewHistory = {};  

            // 重建新的映射关系  
            words.forEach((word, newIndex) => {  
                // 如果当前索引小于被删除的索引,保持原来的数据  
                if (newIndex < index) {  
                    notes[newIndex] = oldNotes[newIndex] || '';  
                    lastViewTimes[newIndex] = oldLastViewTimes[newIndex] || null;  
                    viewHistory[newIndex] = oldViewHistory[newIndex] || [];  
                }   
                // 如果当前索引大于等于被删除的索引,则使用原来索引+1的数据  
                else {  
                    notes[newIndex] = oldNotes[newIndex + 1] || '';  
                    lastViewTimes[newIndex] = oldLastViewTimes[newIndex + 1] || null;  
                    viewHistory[newIndex] = oldViewHistory[newIndex + 1] || [];  
                }  
            });  

            createGrid();  
            updateColors();  
            saveData();  
            closeWordDetail();  
        }  
    }  

    // 添加切换显示内容函数  
    function toggleContent() {  
        if (currentWordIndex === null) return;  

        const word = words[currentWordIndex];  
        const wordText = document.getElementById('wordText');  
        const wordMeaning = document.getElementById('wordMeaning');  

        if (showEnglish) {  
            wordText.textContent = '';  
            wordMeaning.textContent = word.meaning;  
        } else {  
            wordText.textContent = word.text;  
            wordMeaning.textContent = '';  
        }  
    }  

    // 添加随机选择黄色单词功能  
    function selectRandomYellowWord() {  
        const yellowCells = Array.from(document.querySelectorAll('.cell.yellow'));  
        if (yellowCells.length > 0) {  
            const randomIndex = Math.floor(Math.random() * yellowCells.length);  
            const cellIndex = Array.from(document.querySelectorAll('.cell')).indexOf(yellowCells[randomIndex]);  
            showWordDetail(cellIndex);  
        }  
    }  

    // 添加随机选择红单词功能  
    function selectRandomRedWord() {  
        const redCells = Array.from(document.querySelectorAll('.cell.red'));  
        if (redCells.length > 0) {  
            const randomIndex = Math.floor(Math.random() * redCells.length);  
            const cellIndex = Array.from(document.querySelectorAll('.cell')).indexOf(redCells[randomIndex]);  
            showWordDetail(cellIndex);  
        }  
    }  

    // 初始化页面  
    init();  

    // 导出到剪切板  
    function exportToClipboard() {  
        const data = {  
            words,  
            lastViewTimes,  
            notes,  
            viewHistory  
        };  
        const jsonData = JSON.stringify(data);  
        navigator.clipboard.writeText(jsonData).then(() => {  
            alert('数据已复制到剪切板');  
        }).catch(err => {  
            console.error('复制到剪切板失败:', err);  
        });  
    }  

    // 从文本框导入  
    function importFromText() {  
        const textArea = document.getElementById('importTextArea');  
        const jsonData = textArea.value;  
        try {  
            const data = JSON.parse(jsonData);  
            words = data.words || [];  
            lastViewTimes = data.lastViewTimes || {};  
            notes = data.notes || {};  
            viewHistory = data.viewHistory || {};  
            createGrid();  
            updateColors();  
            alert('数据导入成功');  
        } catch (error) {  
            alert('导入失败,请检查JSON格式');  
            console.error('导入失败:', error);  
        }  
    }  

</script>  

</body>
</html>

2025-03-14 13:15 负责人:无 分享
已邀请:
iRainna

iRainna - 一个前端

没遇到过 不过之前我遇到过 弄vue在安卓低端机上不显示 你可以用ie浏览器 版本切换到(8 好像是 对标效果是 安卓4) 看看在控制台上有不有报错 有报错修改对应的报错试试 还有 如果是uniapp打包出来的安卓 好像是不能用web直接操作dom的

要回复问题请先登录注册