打开/关闭菜单
打开/关闭外观设置菜单
打开/关闭个人菜单
未登录
未登录用户的IP地址会在进行任意编辑后公开展示。

MediaWiki:CardData.js:修订间差异

MediaWiki界面页面
Rin留言 | 贡献
新建:卡片数据 JS,从 Directus API 获取数据并渲染到 .ron-card 骨架 (via create-page on MediaWiki MCP Server)
 
Rin留言 | 贡献
更新:完整的卡片数据获取与渲染逻辑 (via update-page on MediaWiki MCP Server)
 
第84行: 第84行:
         html += '<div class="ron-skill-desc">' + safe( skill.description ) + '</div>';
         html += '<div class="ron-skill-desc">' + safe( skill.description ) + '</div>';


         // 升级数值
         // 升级数值表格
         if ( skill.levels && skill.levels.length > 0 ) {
         if ( skill.levels && skill.levels.length > 0 ) {
             skill.levels.forEach( function ( lv ) {
             skill.levels.forEach( function ( lv ) {
第196行: 第196行:


     // ==============================
     // ==============================
     // 入口:页面加载完成后执行
     // 入口:页面内容加载完成后执行
     // ==============================
     // ==============================



2026年3月10日 (二) 23:11的最新版本

/**
 * CardData.js
 * 找到页面上所有 .ron-card[data-cardname] 元素
 * 从 Directus API 获取卡片数据,渲染成 HTML 填充进去
 */

( function () {
    'use strict';

    // ==============================
    // 配置
    // ==============================

    var API_BASE = 'https://data.saltedkiss.org/items/cards';
    var FIELDS = [
        'stylename',
        'rarity',
        'character.name',
        'profession.name',
        'desire.name',
        'skill_normal_attack.name',
        'skill_normal_attack.type',
        'skill_normal_attack.weapon',
        'skill_normal_attack.description',
        'skill_normal_attack.levels.*',
        'skill_passive.name',
        'skill_passive.type',
        'skill_passive.trigger_type',
        'skill_passive.trigger_value',
        'skill_passive.description',
        'skill_passive.levels.*',
        'skill_ultimate.name',
        'skill_ultimate.type',
        'skill_ultimate.desire_cost',
        'skill_ultimate.description',
        'skill_ultimate.levels.*',
        'feats.stages'
    ].join( ',' );

    // ==============================
    // 工具函数
    // ==============================

    /** 安全取值,null/undefined 返回 fallback */
    function safe( val, fallback ) {
        return ( val !== null && val !== undefined && val !== '' )
            ? String( val )
            : ( fallback || '—' );
    }

    /** 生成稀有度星星 */
    function renderRarity( n ) {
        return '<span class="ron-card-rarity">' + '★'.repeat( Number( n ) || 0 ) + '</span>';
    }

    // ==============================
    // 渲染函数
    // ==============================

    /** 渲染单个技能区块 */
    function renderSkill( skill ) {
        if ( !skill ) return '';

        var html = '<div class="ron-skill">';
        html += '<div class="ron-skill-name">' + safe( skill.name ) + '</div>';
        html += '<div class="ron-skill-type">' + safe( skill.type ) + '</div>';

        // 普通攻击:武器
        if ( skill.weapon ) {
            html += '<div class="ron-skill-meta">武器:' + safe( skill.weapon ) + '</div>';
        }

        // 被动:触发条件
        if ( skill.trigger_type ) {
            html += '<div class="ron-skill-meta">触发:普通攻击 × '
                + safe( skill.trigger_value ) + '</div>';
        }

        // 终结技:欲望消耗
        if ( skill.desire_cost !== null && skill.desire_cost !== undefined ) {
            html += '<div class="ron-skill-meta">欲望消耗:' + safe( skill.desire_cost ) + '</div>';
        }

        html += '<div class="ron-skill-desc">' + safe( skill.description ) + '</div>';

        // 升级数值表格
        if ( skill.levels && skill.levels.length > 0 ) {
            skill.levels.forEach( function ( lv ) {
                html += '<div class="ron-skill-levels">';
                html += '<span class="ron-skill-level-name">' + safe( lv.name ) + ':</span>';
                html += safe( lv.levels ? lv.levels.join( ' / ' ) : null );
                html += '</div>';
            } );
        }

        html += '</div>';
        return html;
    }

    /** 渲染觉醒区块 */
    function renderFeats( feats ) {
        if ( !feats || feats.length === 0 ) return '';

        var html = '<div class="ron-feats"><div class="ron-feats-title">觉醒</div>';

        feats.forEach( function ( feat ) {
            if ( !feat.stages ) return;
            feat.stages.forEach( function ( stage ) {
                var stageName = stage.extra_name || ( '觉醒 ' + stage.stage );
                html += '<div class="ron-feat-stage">';
                html += '<div class="ron-feat-stage-name">' + stageName + '</div>';

                // 属性加成
                if ( stage.stat_boosts ) {
                    stage.stat_boosts.forEach( function ( boost ) {
                        html += '<div class="ron-feat-boost">'
                            + safe( boost.type ) + ' +'
                            + safe( boost.value ) + '</div>';
                    } );
                }

                // 技能效果描述
                if ( stage.value ) {
                    stage.value.forEach( function ( v ) {
                        html += '<div class="ron-feat-desc">' + safe( v.description ) + '</div>';
                    } );
                }

                html += '</div>';
            } );
        } );

        html += '</div>';
        return html;
    }

    /** 把完整卡片数据渲染成 HTML */
    function renderCard( card ) {
        var html = '<div class="ron-card-inner">';

        // 标题行
        html += '<div class="ron-card-header">';
        html += '<span class="ron-card-name">' + safe( card.stylename ) + '</span>';
        html += renderRarity( card.rarity );
        html += '</div>';

        // 基本信息
        html += '<div class="ron-card-info">';
        html += '<span class="ron-card-meta">角色:' + safe( card.character && card.character.name ) + '</span>';
        html += '<span class="ron-card-meta">职业:' + safe( card.profession && card.profession.name ) + '</span>';
        html += '<span class="ron-card-meta">欲望:' + safe( card.desire && card.desire.name ) + '</span>';
        html += '</div>';

        // 技能
        html += '<div class="ron-card-skills">';
        html += renderSkill( card.skill_normal_attack );
        html += renderSkill( card.skill_passive );
        html += renderSkill( card.skill_ultimate );
        html += '</div>';

        // 觉醒
        html += renderFeats( card.feats );

        html += '</div>';
        return html;
    }

    // ==============================
    // 主流程:fetch 并填充
    // ==============================

    function loadCard( el ) {
        var name = el.getAttribute( 'data-cardname' );
        if ( !name ) return;

        var url = API_BASE
            + '?fields=' + encodeURIComponent( FIELDS )
            + '&filter[stylename][_eq]=' + encodeURIComponent( name );

        fetch( url )
            .then( function ( res ) {
                if ( !res.ok ) throw new Error( 'HTTP ' + res.status );
                return res.json();
            } )
            .then( function ( json ) {
                if ( !json.data || json.data.length === 0 ) {
                    el.innerHTML = '<span class="error">找不到卡片:' + name + '</span>';
                    return;
                }
                el.innerHTML = renderCard( json.data[ 0 ] );
            } )
            .catch( function ( err ) {
                el.innerHTML = '<span class="error">加载失败:' + err.message + '</span>';
            } );
    }

    // ==============================
    // 入口:页面内容加载完成后执行
    // ==============================

    mw.hook( 'wikipage.content' ).add( function () {
        document.querySelectorAll( '.ron-card[data-cardname]' ).forEach( loadCard );
    } );

}() );