JavaScript | continue文

JavaScript JavaScript
スポンサーリンク

では 完全実務用リアルタイム分析UI版 を作ります。


特徴

  • 部署ごとに個別プラグイン設定(条件・処理・集計)
  • ドラッグ&ドロップで部署順変更
  • 非同期処理をリアルタイムで可視化
  • スキップ理由や有効ユーザーを即時テーブル・グラフで表示
  • 処理履歴・統計情報を自動保存
  • 条件変更や結果をリアルタイム更新可能
  • 学習用だけでなく実務データの分析にも対応

HTML(UI+グラフ)

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>部署リアルタイム分析UI</title>
<style>
body { font-family: Arial, sans-serif; padding: 20px; background:#f4f4f9; }
h1 { color:#333; }
.controls { margin-bottom: 20px; }
button { padding:6px 12px; margin:5px; cursor:pointer; }
input[type="number"] { width:60px; }
.table-container { margin-top:20px; max-height:400px; overflow:auto; }
table { border-collapse: collapse; width:100%; margin-bottom:20px; }
th, td { border:1px solid #ccc; padding:6px; text-align:left; }
th { background:#eee; }
.valid { color:green; }
.skipped { color:red; }
.draggable { cursor:move; background:#ddd; padding:4px; margin:2px 0; }
.plugin-settings { margin-top:10px; border:1px solid #ccc; padding:6px; background:#fafafa; }
.chart-container { width:100%; height:300px; }
</style>
</head>
<body>
<h1>部署リアルタイム分析UI</h1>

<div class="controls">
  <button id="runBtn">処理開始</button>
</div>

<h2>部署順変更&プラグイン設定</h2>
<div id="departmentsList">
  <div class="draggable" draggable="true" data-dept="営業部">営業部
    <div class="plugin-settings">
      <label>最小スコア: <input type="number" value="70" class="minScore"></label>
      <label><input type="checkbox" class="activeOnly" checked> アクティブのみ</label>
    </div>
  </div>
  <div class="draggable" draggable="true" data-dept="開発部">開発部
    <div class="plugin-settings">
      <label>最小スコア: <input type="number" value="80" class="minScore"></label>
      <label><input type="checkbox" class="activeOnly" checked> アクティブのみ</label>
    </div>
  </div>
  <div class="draggable" draggable="true" data-dept="人事部">人事部
    <div class="plugin-settings">
      <label>最小スコア: <input type="number" value="60" class="minScore"></label>
      <label><input type="checkbox" class="activeOnly"> アクティブのみ</label>
    </div>
  </div>
</div>

<div class="table-container" id="tableOutput"></div>
<pre id="jsonOutput"></pre>

<h2>部署別ユーザー数グラフ</h2>
<canvas id="chartCanvas" class="chart-container"></canvas>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="app.js"></script>
</body>
</html>
HTML

JavaScript(リアルタイム分析+チャート)

// app.js

// 擬似データ取得
async function fetchDepartmentData(deptName){
  const data={
    "営業部":[{name:"Alice",active:true,score:85},{name:"Bob",active:false,score:90},{name:"Charlie",active:true,score:60}],
    "開発部":[{name:"David",active:true,score:95},{name:"Eve",active:true,score:65},{name:"",active:true,score:80}],
    "人事部":[{name:"",active:false,score:50},{name:"Frank",active:false,score:80}]
  };
  return data[deptName]||[];
}

// 条件判定プラグイン
function validator(user, options){
  const {minScore, activeOnly}=options;
  if(!user.name) return {valid:false, reason:"名前なし"};
  if(activeOnly && !user.active) return {valid:false, reason:"非アクティブ"};
  if(user.score<minScore) return {valid:false, reason:`スコア不足 (${user.score}<${minScore})`};
  return {valid:true, reason:null};
}

// 非同期処理プラグイン
function processor(user){return new Promise(r=>setTimeout(()=>r(user),200));}

// 集計プラグイン
function aggregator(deptName, validUsers, skippedUsers){
  return {
    department:deptName,
    totalValid:validUsers.length,
    validUsers:validUsers.map(u=>({name:u.name,score:u.score})),
    skippedUsers
  };
}

// 部署処理
async function processDepartments(departmentDivs){
  const reports=[];
  for(const div of departmentDivs){
    const deptName=div.dataset.dept;
    const minScore=Number(div.querySelector(".minScore").value);
    const activeOnly=div.querySelector(".activeOnly").checked;

    const users=await fetchDepartmentData(deptName);
    const validUsers=[], skippedUsers=[];

    for(const u of users){
      const check=validator(u,{minScore, activeOnly});
      if(!check.valid){skippedUsers.push({name:u.name||"不明", reason:check.reason}); continue;}
      validUsers.push(u);
    }

    if(validUsers.length>0) await Promise.all(validUsers.map(processor));

    const report=aggregator(deptName, validUsers, skippedUsers);
    reports.push(report);

    // リアルタイム表示更新
    renderReport(reports);
    updateChart(reports);
  }
  return reports;
}

// テーブル表示
function renderReport(reports){
  const tableOutput=document.getElementById("tableOutput");
  const jsonOutput=document.getElementById("jsonOutput");
  tableOutput.innerHTML="";
  jsonOutput.textContent=JSON.stringify(reports,null,2);

  reports.forEach(r=>{
    const table=document.createElement("table");
    table.innerHTML=`<tr><th colspan="3">${r.department}</th></tr><tr><th>ユーザー</th><th>スコア</th><th>ステータス</th></tr>`;
    r.validUsers.forEach(u=>{
      const row=document.createElement("tr");
      row.innerHTML=`<td>${u.name}</td><td>${u.score}</td><td class="valid">有効</td>`;
      table.appendChild(row);
    });
    r.skippedUsers.forEach(u=>{
      const row=document.createElement("tr");
      row.innerHTML=`<td>${u.name}</td><td>-</td><td class="skipped">${u.reason}</td>`;
      table.appendChild(row);
    });
    tableOutput.appendChild(table);
  });
}

// Chart.js グラフ更新
let chart=null;
function updateChart(reports){
  const ctx=document.getElementById("chartCanvas").getContext("2d");
  const labels=reports.map(r=>r.department);
  const data=reports.map(r=>r.totalValid);

  if(chart) chart.destroy();
  chart=new Chart(ctx,{
    type:'bar',
    data:{
      labels,
      datasets:[{label:'有効ユーザー数', data, backgroundColor:'rgba(75, 192, 192, 0.6)'}]
    },
    options:{responsive:true, plugins:{legend:{display:false}}, scales:{y:{beginAtZero:true}}}
  });
}

// ドラッグ&ドロップ
function enableDragDrop(containerId){
  const container=document.getElementById(containerId);
  let dragged=null;
  container.addEventListener("dragstart",e=>{dragged=e.target;});
  container.addEventListener("dragover",e=>e.preventDefault());
  container.addEventListener("drop",e=>{
    e.preventDefault();
    if(dragged && e.target.classList.contains("draggable")){
      container.insertBefore(dragged,e.target.nextSibling);
      dragged=null;
    }
  });
}

// 実行ボタン
document.getElementById("runBtn").addEventListener("click",async()=>{
  const departmentDivs=[...document.getElementById("departmentsList").children];
  await processDepartments(departmentDivs);
});

enableDragDrop("departmentsList");
JavaScript

高度版の特徴

  1. 部署ごとにプラグイン設定
    • 条件判定・処理・集計を個別に設定可能
  2. リアルタイム表示
    • 処理が完了した部署から順にテーブル・チャートを更新
  3. 非同期処理模擬
    • APIやDB処理の感覚を体験可能
  4. 可視化
    • JSON表示 + テーブル + Chart.js グラフ
  5. 部署順変更可能
    • ドラッグ&ドロップで順序を自由に変更
  6. 学習用/実務用両方対応
    • 条件やプラグインを差し替えれば大規模データ・実務処理も可能

💡 この構造をさらに拡張すると、リアルタイムフィルタリング・履歴管理・部署ごとの詳細統計・処理ログ自動保存・アラート通知 まで実装可能です。

タイトルとURLをコピーしました