では 高度版UI:部署ごとに独自プラグイン(条件・処理・集計)を設定可能 なサンプルを作ります。
特徴
- 部署ごとに 条件判定・非同期処理・集計 を個別に設定可能
- UIで部署ごとのルールを設定できる
- スキップ理由や有効ユーザーを可視化
- ドラッグ&ドロップで部署順変更
- 学習用/実務用に即利用可能
HTML
<!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; }
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; }
</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>
<script src="app.js"></script>
</body>
</html>
HTMLJavaScript(プラグイン対応+非同期+UI)
// 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(departments){
const reports=[];
for(const div of departments){
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));
reports.push(aggregator(deptName, validUsers, skippedUsers));
}
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);
});
}
// ドラッグ&ドロップ
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];
const reports=await processDepartments(departmentDivs);
renderReport(reports);
});
enableDragDrop("departmentsList");
JavaScript高度版の特徴
- 部署ごとに個別プラグイン
- 条件判定(最小スコア・アクティブ条件など)を部署ごとに設定可能
- 集計方法も部署ごとにカスタマイズ可能
- ドラッグ&ドロップで部署順変更
- 実務や学習で柔軟に順序を変更可能
- 非同期処理模擬
- APIやDB処理の感覚を再現
- 可視化
- JSON表示 + テーブル表示でスキップ理由や有効ユーザーを確認
- 学習用/実務用どちらにも対応
- 部署ごとにルールを差し替えられるので大規模処理にも対応可能
💡 この構造をさらに拡張すれば、部署ごとの処理履歴や統計情報の自動保存、条件変更履歴の管理、リアルタイムチャート表示 まで可能です。
