跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
槌基百科
搜索
搜索
外观
登录
个人工具
登录
查看“︁MediaWiki:Gadget-Gallery.js”︁的源代码
系统消息
讨论
English
阅读
查看源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
查看源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
←
MediaWiki:Gadget-Gallery.js
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于这些用户组的用户执行:
Superadmin
、editor
此页面为本wiki上的软件提供界面文本,并受到保护以防止滥用。如欲修改所有wiki的翻译,请访问
translatewiki.net
上的MediaWiki本地化项目。
您无权编辑此JavaScript页面,因为编辑此页面可能会影响所有访问者。
您可以查看和复制此页面的源代码。
/** * Gallery gadget — Instagram-style image gallery with drag-and-drop upload. * Powers the full 图库 page and the homepage mini-widget. */ ( function () { 'use strict'; var CAT = 'Category:图库'; var PAGE_NAME = '图库'; var api = new mw.Api(); /* ── Fetch images from the 图库 category ─────────────────────── */ function fetchImages( limit, cb ) { api.get( { action: 'query', generator: 'categorymembers', gcmtitle: CAT, gcmtype: 'file', gcmlimit: limit, gcmsort: 'timestamp', gcmdir: 'descending', prop: 'imageinfo', iiprop: 'url|dimensions|timestamp', iiurlwidth: 400, format: 'json' } ).done( function ( data ) { if ( !data.query || !data.query.pages ) { cb( [] ); return; } var pages = Object.values( data.query.pages ).filter( function ( p ) { return p.imageinfo && p.imageinfo[ 0 ]; } ); pages.sort( function ( a, b ) { return b.imageinfo[ 0 ].timestamp.localeCompare( a.imageinfo[ 0 ].timestamp ); } ); cb( pages ); } ).fail( function () { cb( [] ); } ); } /* ── Build one grid item ────────────────────────────────────────*/ function makeItem( page, cls ) { var info = page.imageinfo[ 0 ]; var thumb = info.thumburl || info.url; var title = page.title; var href = mw.util.getUrl( title ); var a = document.createElement( 'a' ); a.href = href; a.className = cls + ' image'; a.title = title.replace( /^(File|文件):/, '' ); var img = document.createElement( 'img' ); img.src = thumb; img.alt = a.title; img.loading = 'lazy'; a.appendChild( img ); return a; } /* ── Upload a single file, auto-renaming on conflict ──────────── * Strategy: try original name → on exists/duplicate warning, * insert "_N" before the extension and retry (up to 99 times). * ─────────────────────────────────────────────────────────────── */ function uploadOne( file, token, attempt ) { attempt = attempt || 0; /* Build filename with optional suffix */ var filename; if ( attempt === 0 ) { filename = file.name; } else { var m = file.name.match( /^(.*?)(\.[^.]+)?$/ ); var base = m[ 1 ] || file.name; var ext = m[ 2 ] || ''; filename = base + '_' + attempt + ext; } if ( attempt > 99 ) { return Promise.resolve( { ok: false, filename: filename, error: '重命名次数超限' } ); } var fd = new FormData(); fd.append( 'action', 'upload' ); fd.append( 'format', 'json' ); fd.append( 'filename', filename ); fd.append( 'file', file ); fd.append( 'token', token ); /* No ignorewarnings — let MediaWiki tell us about conflicts */ fd.append( 'text', '[[Category:图库]]\n上传自图库。' ); fd.append( 'comment', '图库上传' ); return fetch( mw.config.get( 'wgScriptPath' ) + '/api.php', { method: 'POST', body: fd, credentials: 'same-origin' } ) .then( function ( r ) { return r.json(); } ) .then( function ( res ) { /* Success */ if ( res.upload && res.upload.result === 'Success' ) { return { ok: true, filename: filename }; } /* Conflict warnings → retry with next suffix */ var w = res.upload && res.upload.warnings; if ( w && ( w.exists || w[ 'page-exists' ] || w.duplicate || w.badfilename ) ) { return uploadOne( file, token, attempt + 1 ); } /* Any other error */ var msg = ( res.error && res.error.info ) || ( w && JSON.stringify( w ) ) || '未知错误'; return { ok: false, filename: filename, error: msg }; } ) .catch( function () { return { ok: false, filename: filename, error: '网络错误' }; } ); } /* ════════════════════════════════════════════════════════════════ FULL GALLERY PAGE ════════════════════════════════════════════════════════════════ */ function initFullGallery() { var root = document.getElementById( 'mw-gallery-root' ); if ( !root ) { return; } var groups = mw.config.get( 'wgUserGroups' ) || []; var canUpload = groups.indexOf( 'user' ) !== -1 || groups.indexOf( 'sysop' ) !== -1; root.innerHTML = ( canUpload ? '<div id="gal-drop">' + ' <div class="gal-drop-inner">' + ' <span class="gal-drop-icon">📷</span>' + ' <p>将图片拖放至此上传</p>' + ' <p class="gal-drop-sub">或 <label class="gal-browse">点击选择文件' + ' <input type="file" id="gal-file-input" multiple accept="image/*">' + ' </label></p>' + ' </div>' + ' <div id="gal-status"></div>' + '</div>' : '' ) + '<div id="gal-grid" class="gal-grid"></div>'; var grid = document.getElementById( 'gal-grid' ); var status = document.getElementById( 'gal-status' ); function reload() { grid.innerHTML = '<div class="gal-loading">加载中…</div>'; fetchImages( 200, function ( pages ) { grid.innerHTML = ''; if ( !pages.length ) { grid.innerHTML = '<div class="gal-empty">还没有图片,快来上传第一张吧!</div>'; return; } pages.forEach( function ( p ) { grid.appendChild( makeItem( p, 'gal-item' ) ); } ); } ); } reload(); if ( !canUpload ) { return; } var drop = document.getElementById( 'gal-drop' ); var input = document.getElementById( 'gal-file-input' ); drop.addEventListener( 'dragover', function ( e ) { e.preventDefault(); drop.classList.add( 'gal-dragover' ); } ); drop.addEventListener( 'dragleave', function () { drop.classList.remove( 'gal-dragover' ); } ); drop.addEventListener( 'drop', function ( e ) { e.preventDefault(); drop.classList.remove( 'gal-dragover' ); uploadFiles( e.dataTransfer.files ); } ); input.addEventListener( 'change', function () { uploadFiles( input.files ); input.value = ''; } ); function uploadFiles( fileList ) { var files = Array.from( fileList ); var total = files.length, done = 0, renamed = []; status.innerHTML = '<span class="gal-progress">上传中 0/' + total + '…</span>'; api.getToken( 'csrf' ).done( function ( token ) { /* Upload sequentially to avoid token races */ files.reduce( function ( chain, file ) { return chain.then( function () { return uploadOne( file, token, 0 ).then( function ( res ) { done++; if ( res.ok && res.filename !== file.name ) { renamed.push( file.name + ' → ' + res.filename ); } var progress = '上传中 ' + done + '/' + total + '…'; if ( renamed.length ) { progress += '<br><span class="gal-rename-note">已自动重命名:' + renamed.join( ',' ) + '</span>'; } if ( !res.ok ) { progress += '<br><span class="gal-err">' + res.filename + ' 失败:' + res.error + '</span>'; } status.innerHTML = '<span class="gal-progress">' + progress + '</span>'; if ( done === total ) { var summary = '✓ 全部上传完成!'; if ( renamed.length ) { summary += '<br><span class="gal-rename-note">以下文件因重名已自动重命名:<br>' + renamed.join( '<br>' ) + '</span>'; } status.innerHTML = '<span class="gal-ok">' + summary + '</span>'; reload(); } } ); } ); }, Promise.resolve() ); } ); } } /* ════════════════════════════════════════════════════════════════ HOMEPAGE MINI WIDGET ════════════════════════════════════════════════════════════════ */ function initWidget() { var root = document.getElementById( 'mw-gallery-widget' ); if ( !root ) { return; } root.innerHTML = '<div class="gal-widget-grid"></div>' + '<a href="' + mw.util.getUrl( PAGE_NAME ) + '" class="gal-widget-more">查看全部 →</a>'; var grid = root.querySelector( '.gal-widget-grid' ); fetchImages( 8, function ( pages ) { if ( !pages.length ) { root.innerHTML = '<p class="gal-widget-empty">图库暂无图片</p>' + '<a href="' + mw.util.getUrl( PAGE_NAME ) + '">前往图库上传 →</a>'; return; } pages.slice( 0, 8 ).forEach( function ( p ) { grid.appendChild( makeItem( p, 'gal-widget-item' ) ); } ); } ); } $( function () { if ( mw.config.get( 'wgPageName' ) === PAGE_NAME ) { initFullGallery(); } initWidget(); } ); }() );
返回
MediaWiki:Gadget-Gallery.js
。