MediaWiki:Common.js
MediaWiki界面页面
更多操作
注意:在发布之后,您可能需要清除浏览器缓存才能看到所作出的更改的影响。
- Firefox或Safari:按住Shift的同时单击刷新,或按Ctrl-F5或Ctrl-R(Mac为⌘-R)
- Google Chrome:按Ctrl-Shift-R(Mac为⌘-Shift-R)
- Edge:按住Ctrl的同时单击刷新,或按Ctrl-F5。
( function () {
'use strict';
var MAIN_SITE = 'https://www.dolshipmaker.vip';
var WIKI_BASE = 'https://wiki.dolshipmaker.vip';
function setupLogout() {
$( document ).on( 'click', '[href*="action=logout"], [href*="UserLogout"], [data-mw-logouturl]', function(e) {
e.preventDefault();
e.stopImmediatePropagation();
new mw.Api().postWithToken( 'csrf', { action: 'logout' } )
.then( function() { return fetch( MAIN_SITE + '/api/auth/cookie-logout', { method: 'POST', credentials: 'include' } ); } )
.catch( function(){} )
.finally( function() { window.location.href = WIKI_BASE + '/wiki/首页'; } );
return false;
} );
}
function interceptLoginButton() {
$( document ).on( 'click', 'a[href*="Special:UserLogin"], a[href*="action=login"]', function(e) {
e.preventDefault();
window.location.href = MAIN_SITE + '/login.html?redirect=' + encodeURIComponent( window.location.href );
} );
}
function interceptRegisterButton() {
$( document ).on( 'click', 'a[href*="Special:CreateAccount"], a[href*="action=createaccount"]', function(e) {
e.preventDefault();
window.location.href = MAIN_SITE + '/register.html?redirect=' + encodeURIComponent( window.location.href );
} );
}
function interceptEditForAnon() {
if ( mw.config.get( 'wgUserId' ) !== 0 ) return;
$( document ).on( 'click', 'a[href*="action=edit"], a[href*="veaction=edit"]', function(e) {
e.preventDefault();
window.location.href = MAIN_SITE + '/login.html?redirect=' + encodeURIComponent( window.location.href );
} );
}
// ── 语言切换 ──────────────────────────────────────────
var currentLang = localStorage.getItem( 'dol-wiki-lang' ) || 'zh';
function applyLang( lang ) {
currentLang = lang;
localStorage.setItem( 'dol-wiki-lang', lang );
$( '.lang-btn' ).css( { background: 'transparent', color: '#b0c4d8' } );
$( '.lang-btn[data-lang="' + lang + '"]' ).css( { background: '#c9a84c', color: '#0a1628' } );
$( document ).trigger( 'dol-lang-change', [ lang ] );
}
function setupLangSwitch() {
$( document ).on( 'click', '.lang-btn', function() { applyLang( $( this ).data( 'lang' ) ); } );
applyLang( currentLang );
}
// ── 地图公共 ──────────────────────────────────────────
var MAP_W = 4096, MAP_H = 2048;
var GAME_W = 16384, GAME_H = 8192;
var IMG = '/images/e/ea/Map.jpg';
// 循环副本偏移量(足够覆盖无限拖动)
var OFFSETS = [ 0, -1, 1, -2, 2, -3, 3, -4, 4 ].map( function(n) { return n * MAP_W; } );
function gameToMap( gx, gy ) {
return [ MAP_H - ( gy / GAME_H * MAP_H ), gx / GAME_W * MAP_W ];
}
function parseCityWikitext( title, wikitext ) {
var city = { title: title };
[ 'id', 'zh', 'zh-tw', 'ja', 'en', '坐标', '船厂', 'type', 'region', 'country' ].forEach( function( f ) {
var m = wikitext.match( new RegExp( '\\|' + f + '=([^\\|\\}]*)' ) );
city[ f ] = m ? m[1].trim() : '';
} );
return city;
}
function getCityName( city ) {
return city[ currentLang ] || city['zh'] || city.title;
}
function setupMapCursor( map ) {
map.getContainer().style.cursor = 'default';
map.on( 'mousedown', function() { map.getContainer().style.cursor = 'grabbing'; } );
map.on( 'mouseup dragend', function() { map.getContainer().style.cursor = 'default'; } );
}
function addMapImages( L, map ) {
OFFSETS.forEach( function( ox ) {
L.imageOverlay( IMG, [ [0, ox], [MAP_H, ox + MAP_W] ] ).addTo( map );
} );
map.setMaxBounds( [ [-MAP_H * 0.2, -MAP_W * 4.5], [MAP_H * 1.2, MAP_W * 4.5] ] );
}
// ── 世界地图 ──────────────────────────────────────────
var worldMap = null;
var cityMarkers = [];
function updateMarkerTooltips() {
cityMarkers.forEach( function( item ) { item.marker.setTooltipContent( getCityName( item.city ) ); } );
}
function showCityDetail( city ) {
$( '#city-detail-name' ).text( getCityName( city ) );
$( '#city-detail-type' ).text( city.type );
$( '#city-detail-region' ).text( city.region );
$( '#city-detail-country' ).text( city.country );
$( '#city-detail-coord' ).text( city['坐标'] );
$( '#city-detail-shipyard' ).text( city['船厂'] );
$( '#city-detail-link' ).attr( 'href', WIKI_BASE + '/wiki/' + encodeURIComponent( city.title ) );
$( '#city-detail' ).show();
}
function addCityMarkers( L, map, markers, cities, clickHandler ) {
var mOpts = { radius: 4, fillColor: '#c9a84c', color: '#fff', weight: 1, opacity: 1, fillOpacity: 0.9 };
var tOpts = { permanent: false, direction: 'top', className: 'city-tooltip' };
// 按坐标去重:相同坐标只保留 ID 最小的
var coordMap = {};
cities.forEach( function( city ) {
if ( !city['坐标'] ) return;
var key = city['坐标'];
var id = parseInt( city['id'] ) || 999999;
if ( !coordMap[ key ] || id < parseInt( coordMap[ key ]['id'] ) ) {
coordMap[ key ] = city;
}
} );
Object.keys( coordMap ).forEach( function( key ) {
var city = coordMap[ key ];
var parts = key.split( ',' );
if ( parts.length !== 2 ) return;
var gx = parseInt( parts[0] ), gy = parseInt( parts[1] );
if ( isNaN(gx) || isNaN(gy) ) return;
var latlng = gameToMap( gx, gy );
OFFSETS.forEach( function( ox ) {
var m = L.circleMarker( [ latlng[0], latlng[1] + ox ], mOpts ).addTo( map );
m.bindTooltip( getCityName( city ), tOpts );
if ( clickHandler ) m.on( 'click', ( function( c ) { return function() { clickHandler( c ); }; } )( city ) );
markers.push( { marker: m, city: city } );
} );
} );
}
function loadAllCities( callback ) {
var api = new mw.Api();
api.get( { action: 'query', list: 'allpages', apprefix: '城市/', aplimit: 500, format: 'json' } )
.then( function( data ) {
var titles = data.query.allpages.map( function( p ) { return p.title; } );
if ( !titles.length ) return;
var batches = [], allCities = [], done = 0;
for ( var i = 0; i < titles.length; i += 50 ) batches.push( titles.slice( i, i + 50 ) );
batches.forEach( function( batch ) {
api.get( { action: 'query', titles: batch.join( '|' ), prop: 'revisions', rvprop: 'content', format: 'json' } )
.then( function( res ) {
Object.keys( res.query.pages ).forEach( function( pid ) {
var page = res.query.pages[ pid ];
if ( !page.revisions ) return;
var wt = page.revisions[0]['*'] || page.revisions[0].content || '';
allCities.push( parseCityWikitext( page.title, wt ) );
} );
if ( ++done === batches.length ) callback( allCities );
} );
} );
} );
}
function initWorldMap() {
if ( !document.getElementById( 'world-map' ) ) return;
mw.loader.load( 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css', 'text/css' );
var script = document.createElement( 'script' );
script.src = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js';
script.onload = function() {
var L = window.L;
worldMap = L.map( 'world-map', { crs: L.CRS.Simple, minZoom: -2, maxZoom: 3, zoomSnap: 0.5, attributionControl: false } );
addMapImages( L, worldMap );
setupMapCursor( worldMap );
worldMap.setView( [ 1248, -145 ], 0 );
loadAllCities( function( cities ) {
addCityMarkers( L, worldMap, cityMarkers, cities, showCityDetail );
} );
$( document ).on( 'dol-lang-change', function() { updateMarkerTooltips(); } );
};
document.head.appendChild( script );
}
// ── 城市详情页小地图 ──────────────────────────────────
function initCityMiniMap() {
var container = document.getElementById( 'city-mini-map' );
if ( !container ) return;
var coordStr = container.getAttribute( 'data-coord' );
if ( !coordStr ) return;
var parts = coordStr.split( ',' );
if ( parts.length !== 2 ) return;
var gx = parseInt( parts[0] ), gy = parseInt( parts[1] );
if ( isNaN(gx) || isNaN(gy) ) return;
mw.loader.load( 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css', 'text/css' );
var script = document.createElement( 'script' );
script.src = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js';
script.onload = function() {
var L = window.L;
var latlng = gameToMap( gx, gy );
var miniMap = L.map( 'city-mini-map', { crs: L.CRS.Simple, minZoom: -1, maxZoom: 3, zoomSnap: 0.5, attributionControl: false } );
addMapImages( L, miniMap );
setupMapCursor( miniMap );
miniMap.setView( latlng, 1 );
L.circleMarker( latlng, { radius: 6, fillColor: '#e74c3c', color: '#fff', weight: 2, opacity: 1, fillOpacity: 1 } ).addTo( miniMap );
};
document.head.appendChild( script );
}
// ── 交易品分类切换 ────────────────────────────────────
function initGoodsFilter() {
$( '.goods-table' ).each( function() {
var table = $( this );
// 收集所有分类
var types = [];
table.find( 'tr' ).each( function() {
var td = $( this ).find( 'td' ).eq( 1 ).text().trim();
if ( td && types.indexOf( td ) === -1 ) types.push( td );
} );
if ( !types.length ) return;
// 生成切换按钮
var bar = $( '<div class="goods-filter-bar" style="margin-bottom:6px;"></div>' );
var allBtn = $( '<span class="goods-filter-btn active" data-type="all" style="cursor:pointer;padding:3px 10px;border-radius:3px;margin:0 3px 3px 0;display:inline-block;background:#c9a84c;color:#0a1628;">全部</span>' );
bar.append( allBtn );
types.forEach( function( t ) {
bar.append( $( '<span class="goods-filter-btn" data-type="' + t + '" style="cursor:pointer;padding:3px 10px;border-radius:3px;margin:0 3px 3px 0;display:inline-block;background:#1a3a5c;color:#b0c4d8;">' + t + '</span>' ) );
} );
table.before( bar );
// 点击切换
bar.on( 'click', '.goods-filter-btn', function() {
var type = $( this ).data( 'type' );
bar.find( '.goods-filter-btn' ).css( { background: '#1a3a5c', color: '#b0c4d8' } );
$( this ).css( { background: '#c9a84c', color: '#0a1628' } );
table.find( 'tr' ).each( function() {
var tds = $( this ).find( 'td' );
if ( !tds.length ) return; // 表头行
if ( type === 'all' ) {
$( this ).show();
} else {
$( this ).toggle( tds.eq( 1 ).text().trim() === type );
}
} );
} );
} );
}
mw.loader.using( 'mediawiki.util' ).done( function() {
$( document ).ready( function() {
setupLogout();
interceptLoginButton();
interceptRegisterButton();
interceptEditForAnon();
setupLangSwitch();
initWorldMap();
initCityMiniMap();
initGoodsFilter();
} );
} );
}() );