Greasy Fork

Greasy Fork is available in English.

保存个人说明历史

保存幼儿园个人说明历史

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         保存个人说明历史
// @namespace    https://github.com/lifegpc/userscript
// @version      0.0.1
// @description  保存幼儿园个人说明历史
// @author       lifegpc
// @match        https://u2.dmhy.org/usercp.php?action=personal*
// @icon         https://u2.dmhy.org/favicon.ico
// @license      MIT
// ==/UserScript==
/**@type {IDBDatabase} */
let db = undefined;
let need_reinit = false;
let storage = navigator.storage || globalThis['WorkerNavigator']['storage'];
async function make_storage_persist() {
    let persisted = await storage.persisted();
    if (!persisted) {
        persisted = await storage.persist();
    }
    return persisted;
}
function init() {
    return new Promise((resolve, reject) => {
        make_storage_persist().then(() => {
            if (db !== undefined && !need_reinit) {
                resolve();
                return;
            }
            let indexedReq = indexedDB.open('u2_history', 1);
            /**@param {IDBVersionChangeEvent} event*/
            indexedReq.onupgradeneeded = function (event) {
                let db = this.result;
                console.log(`upgrade u2_history from ${event.oldVersion} to ${event.newVersion}`);
                /*No version or version < 1 -> v1 */
                if (isNaN(event.oldVersion) || event.oldVersion < 1) {
                    db.createObjectStore('info', { keyPath: 'time' });
                }
            }
            indexedReq.onsuccess = () => {
                db = indexedReq.result;
                resolve();
            }
            indexedReq.onerror = () => {
                need_reinit = true;
                reject(indexedReq.error);
            }
        }).catch(reject);
    })
}
/**
 * @template T
 * @param {(tx: IDBDatabase) => IDBRequest<T>} callback
 * @returns {Promise<T>}
 */
function db_handle(callback) {
    return new Promise((resolve, reject) => {
        init().then(() => {
            let req = callback(db);
            req.onsuccess = () => {
                let re = req.result;
                resolve(re);
            }
            req.onerror = () => {
                need_reinit = true;
                reject(req.error);
            }
        }).catch(reject);
    })
}
async function get_all_info_keys() {
    return await db_handle(db => db.transaction('info').objectStore('info').getAllKeys());
}
async function get_info(time) {
    let info = await db_handle(db => db.transaction('info').objectStore('info').get(time));
    return info ? info.info : undefined;
}
async function delete_info(time) {
    await db_handle(db => db.transaction('info', 'readwrite').objectStore('info').delete(time));
}
async function save_info(time, info) {
    return await db_handle(db => db.transaction('info', 'readwrite').objectStore('info').put({ time, info }));
}
async function render_page() {}
(async function() {
let times = await get_all_info_keys();
let textarea = document.querySelector('textarea[name="info"]');
let submit = document.querySelector('input[type="submit"]');
if (!times.length) {
    let info = textarea.value;
    if (info) {
        times.push(await save_info(new Date, info));
    }
}
console.log(times)
if (times.length) {
    times.sort((a, b) => b.getTime() - a.getTime())
    let details = document.createElement('details');
    let summary = document.createElement('summary');
    summary.innerText = '历史记录';
    details.append(summary);
    let body = document.createElement('div');
    details.append(body);
    textarea.parentElement.append(details);
    let page = 0;
    const count_per_page = 10;
    /**
     * @param {Date} time
     * @param {string} info
     */
    function render_info(time, info) {
        const details = document.createElement('details');
        const summary = document.createElement('summary');
        summary.innerText = time.toLocaleString();
        details.append(summary);
        const form = document.createElement('form');
        form.target = '_blank';
        form.action = "/tags.php";
        form.method = "post";
        details.append(form);
        const ntextarea = document.createElement('textarea');
        ntextarea.readOnly = true;
        ntextarea.name = "test";
        ntextarea.value = info;
        ntextarea.style.width = textarea.style.width;
        ntextarea.rows = textarea.rows;
        form.append(ntextarea);
        const line = document.createElement('div');
        form.append(line);
        const use = document.createElement('input');
        use.type = "button";
        use.value = "使用";
        use.addEventListener('click', () => {
            textarea.value = info;
        })
        line.append(use);
        const preview = document.createElement('input');
        preview.type = "submit";
        preview.value = "预览";
        line.append(preview);
        const del = document.createElement('input');
        del.type = "button";
        del.value = "删除";
        del.addEventListener('click', async () => {
            await delete_info(time);
            times = await get_all_info_keys();
            times.sort((a, b) => b.getTime() - a.getTime());
            await render_page();
        })
        line.append(del);
        body.append(details);
    }
    async function render_page() {
        body.innerHTML = '';
        const total_page = Math.ceil(times.length / count_per_page);
        if (page < 0) page = 0;
        if (page >= total_page) page = total_page - 1;
        const max = Math.min((page + 1) * count_per_page, times.length);
        for (let i = page * count_per_page; i < max; i++) {
            const time = times[i];
            const info = await get_info(time);
            render_info(time, info);
        }
        const line = document.createElement('div');
        body.append(line);
        const pagei = document.createElement('input');
        pagei.type = 'number';
        pagei.min = '1';
        pagei.max = `${total_page}`;
        pagei.value = `${page + 1}`;
        pagei.addEventListener('change', () => {
            page = pagei.valueAsNumber - 1;
            render_page();
        })
        line.append(pagei);
        line.append(`/${total_page}页`);
        if (page > 0) {
            const first = document.createElement('input');
            first.type = 'button';
            first.value = '首页';
            first.addEventListener('click', () => {
                page = 0;
                render_page();
            })
            line.append(first);
            const prev = document.createElement('input');
            prev.type = 'button';
            prev.value = '上一页';
            prev.addEventListener('click', () => {
                page--;
                render_page();
            })
            line.append(prev);
        }
        if (page < total_page - 1) {
            const next = document.createElement('input');
            next.type = 'button';
            next.value = '下一页';
            next.addEventListener('click', () => {
                page++;
                render_page();
            })
            line.append(next);
            const last = document.createElement('input');
            last.type = 'button';
            last.value = '尾页';
            last.addEventListener('click', () => {
                page = total_page - 1;
                render_page();
            })
            line.append(last);
        }
    }
    await render_page();
} else {
    let div = document.createElement('div');
    div.innerText = "无历史记录";
    textarea.parentElement.append(div);
}
submit.addEventListener('click', async () => {
    const last_time = new Date(Math.max(...times));
    const info_db = await get_info(last_time);
    const info = textarea.value;
    if (info != info_db) {
        await save_info(new Date, info);
    }
})
})();