您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
KING OF TIME 打刻画面を色と巨大文字でわかりやすく
// ==UserScript== // @name KING OF TIME Timerecorder status Enhancer // @namespace https://example.com/ // @version 2025-05-28 // @description KING OF TIME 打刻画面を色と巨大文字でわかりやすく // @match https://s4.ta.kingoftime.jp/independent/recorder2/personal/* // @grant none // @run-at document-end // @license MIT // ==/UserScript== (() => { console.log('[TM] timerecorder helper started'); /* ---------------- 1. 直近ステータスを取得 ---------------- */ function getLatestStatus () { const key = Object.keys(localStorage) .find(k => k.startsWith('PARSONAL_BROWSER_RECORDER@RECORD_HISTORY_')); if (!key) return null; let logs; try { logs = JSON.parse(localStorage[key]); } catch { return null; } if (!Array.isArray(logs) || !logs.length) return null; const latest = logs.find(r => r.status === 1) || logs[0]; switch (latest.name) { case '出勤': return 'working';// 勤務中 case '休始': return 'break';// 休憩中 case '休終': return 'working';// 休憩→勤務 case '退勤': return 'checkedOut'; // 退勤済 default:return 'unknown'; } } /* ---------------- 2. 画面を更新 ---------------- */ const COLORS = { working:'#C8E6C9', break:'#FFE0B2', checkedOut:'#E0E0E0', unknown:'#FFCDD2' }; const FONTCOL = { working:'#2E7D32', break:'#EF6C00', checkedOut:'#616161', unknown:'#C62828' }; const LABELS = { working:'勤務中', break:'休憩中', checkedOut:'退勤済', unknown:'状態不明' }; function updateUI () { const state = getLatestStatus(); if (!state) return; /* 2-1 背景色変更 */ document.body.style.backgroundColor = COLORS[state]; /* 2-2 デカ文字ラベル(位置情報取得済みの直下)*/ let label = document.getElementById('tm-status-label'); if (!label) { label = document.createElement('div'); label.id = 'tm-status-label'; label.style.cssText = ` margin-top:20px; text-align:center; font-size:48px; font-weight:900; `; // #location_area が常にある想定。無い場合は .wrapper-all に append でも可 const anchor = document.getElementById('location_area'); (anchor ? anchor : document.body).after(label); } label.style.color = FONTCOL[state]; label.textContent = LABELS[state]; /* 2-3 打刻ボタンの enable/disable */ const buttons = document.querySelectorAll('#buttons input[type="button"], #buttons button'); buttons.forEach(btn => { const text = (btn.value || btn.textContent).trim(); const disable = (state === 'working' && /出勤/.test(text)) || (state === 'break' && /退勤/.test(text)) || (state === 'checkedOut' && /休始|休終/.test(text)); btn.disabled = disable; btn.style.opacity = disable ? '0.35' : '1'; btn.style.cursor = disable ? 'not-allowed' : ''; }); } /* ---------------- 3. 監視 & トリガ ---------------- */ window.addEventListener('load', () => { updateUI(); // 初回 /* 1 秒ポーリング */ setInterval(updateUI, 1_000); /* 他タブで localStorage が変わった時 */ window.addEventListener('storage', updateUI); /* 同じタブでボタンを押した瞬間にも即反映 */ const btnArea = document.getElementById('buttons'); if (btnArea) { btnArea.addEventListener('click', (e) => { if (e.target.matches('input[type="button"], button')) { // localStorage の書き込み完了は非同期なので 100 ms 待つ setTimeout(updateUI, 100); } }); } }); })();