您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Überprüft das Personalsoll und die Werbephasen in allen Gebäuden
当前为
// ==UserScript== // @name * Personaler // @namespace bos-ernie.leitstellenspiel.de // @version 1.0.0 // @license BSD-3-Clause // @author BOS-Ernie // @description Überprüft das Personalsoll und die Werbephasen in allen Gebäuden // @match https://www.leitstellenspiel.de/ // @icon https://www.google.com/s2/favicons?sz=64&domain=leitstellenspiel.de // @run-at document-idle // @grant none // ==/UserScript== /* global $ */ (function () { "use strict"; const buildingsWithPersonal = [0, 2, 6, 9, 11, 12, 13, 18, 19, 20]; const buildingTypePersonalCountTarget = { 0: 250, 2: 80, 6: 300, 9: 140, 11: 215, 12: 34, 13: 400, 18: 250, 19: 300, 20: 80, }; function addStyle() { const style = ".loader{width:100px;height:100px;border-radius:100%;position:relative;margin:0 auto;top:40px;left:-2.5px}.loader span{display:inline-block;width:5px;height:20px;background-color:#c9302c}.loader span:first-child{animation:1s ease-in-out infinite grow}.loader span:nth-child(2){animation:1s ease-in-out .15s infinite grow}.loader span:nth-child(3){animation:1s ease-in-out .3s infinite grow}.loader span:nth-child(4){animation:1s ease-in-out .45s infinite grow}@keyframes grow{0%,100%{-webkit-transform:scaleY(1);-ms-transform:scaleY(1);-o-transform:scaleY(1);transform:scaleY(1)}50%{-webkit-transform:scaleY(1.8);-ms-transform:scaleY(1.8);-o-transform:scaleY(1.8);transform:scaleY(1.8)}}"; const styleElement = document.createElement("style"); styleElement.innerHTML = style; document.head.appendChild(styleElement); } function addMenuEntry() { const profileMenu = document.getElementById("logout_button").parentElement.parentElement; const divider = document.createElement("li"); divider.setAttribute("class", "divider"); divider.setAttribute("role", "presentation"); profileMenu.append(divider); const bedIcon = document.createElement("span"); bedIcon.setAttribute("class", "glyphicon glyphicon-user"); const button = document.createElement("a"); button.setAttribute("href", "javascript: void(0)"); button.setAttribute("id", "personaler-button"); button.append(bedIcon); button.append(" Personaler"); button.addEventListener("click", buttonClick); const li = document.createElement("li"); li.appendChild(button); profileMenu.append(li); } function addModal() { const modal = document.createElement("div"); modal.className = "modal fade"; modal.id = "personaler-modal"; modal.setAttribute("tabindex", "-1"); modal.setAttribute("role", "dialog"); modal.setAttribute("aria-labelledby", "personaler-modal-label"); modal.setAttribute("aria-hidden", "true"); modal.style.zIndex = "5000"; modal.innerHTML = ` <div class="modal-dialog modal-lg" role="document" style="width: 1280px;"> <div class="modal-content"> <div class="modal-header"> <h1 class="modal-title" id="personaler-modal-label"><span class="glyphicon glyphicon-user" aria-hidden="true"></span> Personaler</h1> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body" style="max-height: calc(100vh - 212px);overflow-y: auto;"> <ul class="nav nav-tabs" role="tablist"> <li role="presentation" class="active"> <a href="#tab-buildings-with-incorrect-personal-count-target" aria-controls="tab-buildings-with-incorrect-personal-count-target" role="tab" data-toggle="tab">Gebäude mit falschem Personal (Soll)</a> </li> <li role="presentation"> <a href="#tab-buildings-without-automatic-hiring" aria-controls="tab-buildings-without-automatic-hiring" role="tab" data-toggle="tab">Gebäude ohne automatische Werbung</a> </li> </ul> <div> <div class="tab-content"> <div role="tabpanel" class="tab-pane active" id="tab-buildings-with-incorrect-personal-count-target"> <div id="buildings-with-incorrect-personal-count-target" class="resizable"> <div class="row"> <div class="col-md-12 bg"> <div class="loader"> <span></span> <span></span> <span></span> <span></span> </div> </div> </div> </div> </div> <div role="tabpanel" class="tab-pane" id="tab-buildings-without-automatic-hiring"> <div id="buildings-without-automatic-hiring" class="resizable"> <div class="row"> <div class="col-md-12 bg"> <div class="loader"> <span></span> <span></span> <span></span> <span></span> </div> </div> </div> </div> </div> </div> </div> </div> </div> </div> `; document.body.appendChild(modal); } function buttonClick(event) { event.preventDefault(); render(); $("#personaler-modal").modal("show"); } function getPersonalCountTarget(building_type) { return buildingTypePersonalCountTarget[building_type]; } async function getBuildings() { if ( !sessionStorage.aBuildings || JSON.parse(sessionStorage.aBuildings).lastUpdate < new Date().getTime() - 5 * 1000 * 60 ) { const buildings = await fetch("/api/buildings.json").then(response => response.json()); try { sessionStorage.setItem("aBuildings", JSON.stringify({ lastUpdate: new Date().getTime(), value: buildings })); } catch (e) { return buildings; } } return JSON.parse(sessionStorage.aBuildings).value; } async function getBuildingsWithIncorrectPersonalCountTarget() { const buildings = await getBuildings(); return buildings.filter( building => buildingsWithPersonal.includes(building.building_type) && building.personal_count_target !== getPersonalCountTarget(building.building_type), ); } async function getBuildingsWithoutAutomaticHiring() { const buildings = await getBuildings(); return buildings.filter( building => buildingsWithPersonal.includes(building.building_type) && building.hiring_automatic !== true, ); } async function render() { const buildingsWithIncorrectPersonalCountTarget = await getBuildingsWithIncorrectPersonalCountTarget(); if (buildingsWithIncorrectPersonalCountTarget.length > 0) { const tabPersonalCountTarget = document.getElementById("buildings-with-incorrect-personal-count-target"); tabPersonalCountTarget.innerHTML = ` <table class="table table-striped table-hover"> <thead> <tr> <th>Gebäude</th> <th>Ist: Personal (Soll)</th> <th>Soll: Personal (Soll)</th> </tr> </thead> <tbody> ${buildingsWithIncorrectPersonalCountTarget .map( building => ` <tr> <td><a href="/buildings/${building.id}">${building.caption}</a></td> <td>${building.personal_count_target}</td> <td>${getPersonalCountTarget(building.building_type)}</td> </tr> `, ) .join("")} </tbody> </table> `; } else { const tabPersonalCountTarget = document.getElementById("buildings-with-incorrect-personal-count-target"); tabPersonalCountTarget.innerHTML = ` <div class="row"> <div class="col-md-12 bg"> <div class="alert alert-success" role="alert"> <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> Alle Gebäude haben das richtige Soll-Personal </div> </div> </div> `; } const tabHiring = document.getElementById("buildings-without-automatic-hiring"); const buildingsWithoutAutomaticHiring = await getBuildingsWithoutAutomaticHiring(); if (buildingsWithoutAutomaticHiring.length > 0) { tabHiring.innerHTML = ` <table class="table table-striped table-hover"> <thead> <tr> <th>Gebäude</th> </tr> </thead> <tbody> ${buildingsWithoutAutomaticHiring .map( building => ` <tr> <td><a href="/buildings/${building.id}">${building.caption}</a></td> </tr> `, ) .join("")} </tbody> </table> `; } else { tabHiring.innerHTML = ` <div class="row"> <div class="col-md-12 bg"> <div class="alert alert-success" role="alert"> <span class="glyphicon glyphicon-ok" aria-hidden="true"></span> Alle Gebäude haben automatische Werbung aktiviert </div> </div> </div> `; } } async function main() { addStyle(); addMenuEntry(); addModal(); } main(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址