您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Fügt Buttons zum schnellen Wechseln zwischen den Filter-Optionen hinzu.
// ==UserScript== // @name * Filter Express // @namespace bos-ernie.leitstellenspiel.de // @version 1.1.0 // @license BSD-3-Clause // @author BOS-Ernie // @description Fügt Buttons zum schnellen Wechseln zwischen den Filter-Optionen hinzu. // @match https://www.leitstellenspiel.de/ // @match https://polizei.leitstellenspiel.de/ // @icon https://www.google.com/s2/favicons?sz=64&domain=leitstellenspiel.de // @run-at document-idle // @grant none // @resource https://forum.leitstellenspiel.de/index.php?thread/28150-skript-filter-express-blitzschnelles-filtern-sortieren-der-einsatzliste/ // ==/UserScript== /* global $, progressBarScrollUpdate, missionSelectionActive, missionSelectionDeactive, missionSelectionOnly */ (function () { /* * BEGINN DER BENUTZERKONFIGURATION - BUTTONS ANPASSEN * * Jeder Button wird durch ein Objekt in der buttonConfig-Array definiert. * Verfügbare Optionen für jeden Button: * * - text: Der auf dem Button angezeigte Text (z.B. "M", "V", etc.) * - title: Der Tooltip-Text (wird beim Hovern angezeigt) * - action: Die Aktion, die beim Klick ausgeführt wird * ├─ sources: Array von Quellen-Filtern * ├─ states: Array von Status-Filtern * ├─ participations: Array von Beteiligungs-Filtern * └─ sorting: Sortierkonfiguration {key, direction} * * Verfügbare Filter- und Sortieroptionen: * * SOURCES: * - "own" Eigene Einsätze ("Notfälle") * - "patient_transport" Krankentransporte * - "alliance" Verbandseinsätze * - "event" Event-Einsätze * - "planned" Geplante Einsätze * * STATES: * - "red" Unbearbeitete Einsätze * - "yellow" Bearbeitete Einsätze * - "green" Einsätze in Durchführung * * PARTICIPATIONS: * - "without" Einsätze ohne eigener Beteiligung ("Neue Einsätze") * - "with" Einsätze mit eigener Beteiligung ("Gestartete Einsätze") * * SORTING KEYS: * - "shared_at" Alter des Einsatzes (Freigeben) * - "created_at" Alter des Einsatzes (Erstellt) * - "caption" Einsatzname (A bis Z) * - "credits" Durchschnittliche Belohnung (Credits) * - "prisoners" Anzahl der Gefangenen * - "patients" Anzahl der Patienten * * SORTING DIRECTIONS: * - "asc" Aufsteigend (A-Z, 1-9) * - "desc" Absteigend (Z-A, 9-1) */ const buttonConfig = [ { text: "M", title: "Unbearbeitete eigene Einsätze", action: { sources: ["own"], states: ["red", "yellow", "green"], participations: ["without"], sorting: { key: "shared_at", direction: "asc" }, }, }, { text: "M:$↑", title: "Unbearbeitete eigene Einsätze sortiert nach Credits aufsteigend", action: { sources: ["own"], states: ["red", "yellow", "green"], participations: ["without"], sorting: { key: "credits", direction: "asc" }, }, }, { text: "M:R", title: "Alle eigenen roten Einsätze", action: { sources: ["own"], states: ["red"], participations: ["without", "with"], sorting: { key: "shared_at", direction: "asc" }, }, }, { text: "V", title: "Unbearbeitete Verbandseinsätze", action: { sources: ["alliance"], states: ["red", "yellow", "green"], participations: ["without"], sorting: { key: "shared_at", direction: "asc" }, }, }, { text: "V:$↓", title: "Unbearbeitete Verbandseinsätze sortiert nach Credits absteigend", action: { sources: ["alliance"], states: ["red", "yellow", "green"], participations: ["without"], sorting: { key: "credits", direction: "desc" }, }, }, { text: "E", title: "Unbearbeitete Event-Einsätze", action: { sources: ["event"], states: ["red", "yellow", "green"], participations: ["without"], sorting: { key: "shared_at", direction: "asc" }, }, }, { text: "E:P", title: "Event-Einsätze sortiert nach Patienten", action: { sources: ["event"], states: ["red", "yellow", "green"], participations: ["without", "with"], sorting: { key: "patients", direction: "desc" }, }, }, { text: "G", title: "Unbearbeitete geplante Einsätze", action: { sources: ["planned"], states: ["red", "yellow", "green"], participations: ["without"], sorting: { key: "shared_at", direction: "asc" }, }, }, { text: "VG", title: "Unbearbeitete Verbands- und geplante Einsätze", action: { sources: ["alliance", "planned"], states: ["red", "yellow", "green"], participations: ["without"], sorting: { key: "shared_at", direction: "asc" }, }, }, ]; // ENDE DER BENUTZERKONFIGURATION // Ab hier folgt der Skript-Code - Änderungen nur für fortgeschrittene Benutzer empfohlen! // Mapping der sprechenden Strings auf die tatsächlichen Werte const sourceMapping = { own: "#mission_select_emergency", patient_transport: "#mission_select_krankentransporte", alliance: "#mission_select_alliance", event: "#mission_select_alliance_event", planned: "#mission_select_sicherheitswache", }; const stateMapping = { red: "#mission_select_unattended", yellow: "#mission_select_attended", green: "#mission_select_finishing", }; const participationMapping = { without: "#mission_select_new", with: "#mission_select_started", }; const sortingMapping = { shared_at: "age", created_at: "created_at", caption: "caption", credits: "average_credits", prisoners: "prisoners_count", patients: "patients_count", }; function mapSources(sources) { return sources.map(source => { if (sourceMapping[source]) { return sourceMapping[source]; } console.error(`[Filter Express] Unknown source: ${source}`); return source; }); } function mapStates(states) { return states.map(state => { if (stateMapping[state]) { return stateMapping[state]; } console.error(`[Filter Express] Unknown state: ${state}`); return state; }); } function mapParticipations(participations) { return participations.map(participation => { if (participationMapping[participation]) { return participationMapping[participation]; } console.error(`[Filter Express] Unknown participation: ${participation}`); return participation; }); } const supportedSources = Object.values(sourceMapping); const supportedStates = Object.values(stateMapping); const supportedParticipations = Object.values(participationMapping); const supportedSortingDirections = ["asc", "desc"]; function sortMissions(key, direction) { const mappedKey = sortingMapping[key]; if (!mappedKey) { console.error(`[Filter Express] Unable to sort missions: key ${key} is not mapped`); return; } if (!supportedSortingDirections.includes(direction)) { console.error(`[Filter Express] Unable to sort missions: direction ${direction} is not allowed`); return; } const select = document.querySelector("#missions-sortable-select"); if (!select) { console.error("[Filter Express] Unable to sort missions: select not found"); return; } const options = Array.from(select.options); const option = options.find(option => { return ( option.getAttribute("data-sort-key") === mappedKey && option.getAttribute("data-sort-direction") === direction ); }); if (option) { select.value = option.value; select.dispatchEvent(new Event("change")); } else { console.error( `[Filter Express] Unable to sort missions: option not found for key ${mappedKey} (mapped from ${key}) and direction ${direction}`, ); } } function selectSources(sources) { if (!Array.isArray(sources)) { console.error(`[Filter Express] Unable to select source: ${sources} is not an array`); return; } const mappedSources = mapSources(sources); const unsupportedSources = mappedSources.filter(source => !supportedSources.includes(source)); if (unsupportedSources.length > 0) { console.error(`[Filter Express] Unable to select source: ${unsupportedSources} are not supported`); return; } supportedSources.forEach(source => { if (!mappedSources.includes(source)) { missionSelectionDeactive($(source)); } else { missionSelectionActive($(source)); } }); } function selectStates(states) { if (!Array.isArray(states)) { console.error(`[Filter Express] Unable to select state: ${states} is not an array`); return; } const mappedStates = mapStates(states); const unsupportedStates = mappedStates.filter(state => !supportedStates.includes(state)); if (unsupportedStates.length > 0) { console.error(`[Filter Express] Unable to select state: ${unsupportedStates} are not supported`); return; } supportedStates.forEach(state => { if (!mappedStates.includes(state)) { missionSelectionDeactive($(state)); } else { missionSelectionActive($(state)); } }); } function selectParticipations(participations) { if (!Array.isArray(participations)) { console.error(`[Filter Express] Unable to select participation: ${participations} is not an array`); return; } const mappedParticipations = mapParticipations(participations); const unsupportedParticipations = mappedParticipations.filter( participation => !supportedParticipations.includes(participation), ); if (unsupportedParticipations.length > 0) { console.error(`[Filter Express] Unable to select participation: ${unsupportedParticipations} are not supported`); return; } supportedParticipations.forEach(participation => { if (!mappedParticipations.includes(participation)) { missionSelectionDeactive($(participation)); } else { missionSelectionActive($(participation)); } }); } function createButtonHandler(config) { return function () { if (config.action.sources) selectSources(config.action.sources); if (config.action.states) selectStates(config.action.states); if (config.action.participations) selectParticipations(config.action.participations); if (config.action.sorting) sortMissions(config.action.sorting.key, config.action.sorting.direction); }; } function addButtonGroup() { const buttonGroup = document.createElement("div"); buttonGroup.className = "btn-group btn-group-xs"; buttonGroup.style.marginLeft = "10px"; buttonConfig.forEach(config => { const button = document.createElement("button"); button.className = "btn btn-default"; button.innerText = config.text; button.title = config.title; button.onclick = createButtonHandler(config); buttonGroup.appendChild(button); }); const lastElement = document.querySelector("#missions-panel-main > div:last-child"); if (!lastElement) { console.error("[Filter Express] Unable to render button group: lastElement not found"); return; } lastElement.parentNode.insertBefore(buttonGroup, lastElement); } addButtonGroup(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址