プロジェクト

全般

プロフィール

機能 #103 » knowledge_base_management.html

Redmine Admin, 2025-05-15 03:02

 
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>知識ベース管理 - 講師AI分身管理システム</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Hiragino Sans', 'ヒラギノ角ゴシック', 'Yu Gothic UI', 'Meiryo', sans-serif;
background-color: #f8f9fb;
color: #2c3e50;
}
.header {
background: linear-gradient(135deg, #4A90B2 0%, #5B9BC4 100%);
color: white;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.logo-section h1 {
font-size: 1.5rem;
font-weight: 600;
}
.container {
display: flex;
min-height: calc(100vh - 70px);
}
.sidebar {
width: 250px;
background: white;
box-shadow: 2px 0 10px rgba(0,0,0,0.05);
padding: 1.5rem 0;
}
.nav-item {
display: flex;
align-items: center;
padding: 1rem 1.5rem;
color: #5a6c7d;
text-decoration: none;
transition: all 0.3s ease;
border-left: 3px solid transparent;
}
.nav-item:hover {
background-color: #f1f3f4;
color: #4A90B2;
border-left-color: #4A90B2;
}
.nav-item.active {
background-color: #e3f2fd;
color: #4A90B2;
border-left-color: #4A90B2;
font-weight: 600;
}
.nav-icon {
margin-right: 0.75rem;
font-size: 1.2rem;
}
.main-content {
flex: 1;
padding: 2rem;
overflow-y: auto;
}
.page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
}
.page-title {
font-size: 2rem;
color: #2c3e50;
}
.add-qa-btn {
background: #27AE60;
color: white;
padding: 0.75rem 1.5rem;
border: none;
border-radius: 8px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
gap: 0.5rem;
}
.add-qa-btn:hover {
background: #219A52;
}
.control-bar {
background: white;
padding: 1.5rem;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
margin-bottom: 2rem;
display: flex;
gap: 1rem;
align-items: center;
flex-wrap: wrap;
}
.search-box {
flex: 1;
min-width: 250px;
padding: 0.75rem;
border: 1px solid #ddd;
border-radius: 8px;
font-size: 0.9rem;
}
.search-box:focus {
outline: none;
border-color: #4A90B2;
box-shadow: 0 0 0 3px rgba(74, 144, 178, 0.1);
}
.filter-select {
padding: 0.75rem;
border: 1px solid #ddd;
border-radius: 8px;
background: white;
font-size: 0.9rem;
cursor: pointer;
}
.filter-select:focus {
outline: none;
border-color: #4A90B2;
}
.bulk-actions {
display: flex;
gap: 0.5rem;
}
.bulk-btn {
padding: 0.75rem 1rem;
border: 1px solid #ddd;
border-radius: 8px;
background: white;
font-size: 0.9rem;
cursor: pointer;
transition: all 0.3s ease;
}
.bulk-btn:hover {
background: #f8f9fa;
border-color: #4A90B2;
}
.qa-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(450px, 1fr));
gap: 1.5rem;
}
.qa-card {
background: white;
border-radius: 12px;
box-shadow: 0 2px 15px rgba(0,0,0,0.08);
overflow: hidden;
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.qa-card:hover {
transform: translateY(-2px);
box-shadow: 0 5px 25px rgba(0,0,0,0.12);
}
.qa-card-header {
padding: 1.5rem;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: flex-start;
}
.category-tag {
background: #4A90B2;
color: white;
padding: 0.5rem 1rem;
border-radius: 20px;
font-size: 0.8rem;
font-weight: 600;
}
.category-tag.lighting {
background: #E67E22;
}
.category-tag.color {
background: #9B59B6;
}
.category-tag.furniture {
background: #27AE60;
}
.category-tag.layout {
background: #F39C12;
}
.qa-actions {
display: flex;
gap: 0.5rem;
}
.action-btn {
padding: 0.5rem;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 1rem;
transition: all 0.3s ease;
}
.action-btn.edit {
background: #E3F2FD;
color: #4A90B2;
}
.action-btn.delete {
background: #FFEBEE;
color: #E74C3C;
}
.action-btn:hover {
transform: scale(1.1);
}
.qa-content {
padding: 1.5rem;
}
.question {
font-weight: 600;
color: #2c3e50;
margin-bottom: 1rem;
line-height: 1.5;
font-size: 1.1rem;
}
.answer {
color: #5a6c7d;
line-height: 1.6;
font-size: 0.95rem;
}
.qa-meta {
padding: 1rem 1.5rem;
background: #f8fafb;
border-top: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0.85rem;
color: #7f8c8d;
}
.usage-stats {
display: flex;
gap: 1rem;
}
.stat-item {
display: flex;
align-items: center;
gap: 0.25rem;
}
.modal {
display: none;
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.5);
animation: fadeIn 0.3s ease;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.modal-content {
background: white;
margin: 5% auto;
padding: 0;
border-radius: 12px;
width: 90%;
max-width: 800px;
box-shadow: 0 10px 50px rgba(0,0,0,0.2);
animation: slideIn 0.3s ease;
}
@keyframes slideIn {
from { transform: translateY(-50px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.modal-header {
padding: 1.5rem;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
}
.modal-title {
font-size: 1.5rem;
font-weight: 600;
color: #2c3e50;
}
.close-btn {
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
color: #7f8c8d;
transition: color 0.3s ease;
}
.close-btn:hover {
color: #e74c3c;
}
.modal-body {
padding: 2rem;
}
.form-group {
margin-bottom: 1.5rem;
}
.form-label {
display: block;
font-weight: 600;
margin-bottom: 0.5rem;
color: #2c3e50;
}
.form-input {
width: 100%;
padding: 0.75rem;
border: 1px solid #ddd;
border-radius: 8px;
font-size: 0.9rem;
font-family: inherit;
}
.form-input:focus {
outline: none;
border-color: #4A90B2;
box-shadow: 0 0 0 3px rgba(74, 144, 178, 0.1);
}
.form-textarea {
min-height: 120px;
resize: vertical;
line-height: 1.6;
}
.modal-footer {
padding: 1.5rem;
border-top: 1px solid #eee;
display: flex;
justify-content: flex-end;
gap: 1rem;
}
.cancel-btn {
padding: 0.75rem 1.5rem;
border: 1px solid #ddd;
border-radius: 8px;
background: white;
color: #5a6c7d;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
.cancel-btn:hover {
background: #f8f9fa;
}
.save-btn {
padding: 0.75rem 1.5rem;
border: none;
border-radius: 8px;
background: #27AE60;
color: white;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
}
.save-btn:hover {
background: #219A52;
}
.stats-summary {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-bottom: 2rem;
}
.stat-card {
background: white;
padding: 1.5rem;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
text-align: center;
}
.stat-number {
font-size: 2rem;
font-weight: 700;
color: #4A90B2;
margin-bottom: 0.5rem;
}
.stat-label {
color: #7f8c8d;
font-size: 0.9rem;
}
@media (max-width: 768px) {
.qa-grid {
grid-template-columns: 1fr;
}
.control-bar {
flex-direction: column;
align-items: stretch;
}
.search-box {
min-width: auto;
}
.container {
flex-direction: column;
}
.sidebar {
width: 100%;
order: 2;
}
}
</style>
</head>
<body>
<header class="header">
<div class="logo-section">
<h1>🎨 講師AI分身管理システム</h1>
</div>
<div class="user-info">
<span>山田 美和子先生</span>
</div>
</header>

<div class="container">
<aside class="sidebar">
<nav>
<a href="#" class="nav-item">
<span class="nav-icon">📊</span>
ダッシュボード
</a>
<a href="#" class="nav-item">
<span class="nav-icon">💬</span>
リアルタイム会話
</a>
<a href="#" class="nav-item">
<span class="nav-icon">📈</span>
分析・レポート
</a>
<a href="#" class="nav-item">
<span class="nav-icon">⚙️</span>
AI設定
</a>
<a href="#" class="nav-item active">
<span class="nav-icon">📚</span>
知識ベース管理
</a>
<a href="#" class="nav-item">
<span class="nav-icon">👥</span>
受講者管理
</a>
<a href="#" class="nav-item">
<span class="nav-icon"></span>
FAQ管理
</a>
<a href="#" class="nav-item">
<span class="nav-icon">🔔</span>
通知・アラート
</a>
<a href="#" class="nav-item">
<span class="nav-icon">🔧</span>
システム設定
</a>
</nav>
</aside>

<main class="main-content">
<div class="page-header">
<h1 class="page-title">知識ベース管理</h1>
<button class="add-qa-btn" onclick="openModal()">
<span></span>
新しいQ&Aを追加
</button>
</div>

<div class="stats-summary">
<div class="stat-card">
<div class="stat-number">247</div>
<div class="stat-label">総Q&A数</div>
</div>
<div class="stat-card">
<div class="stat-number">5</div>
<div class="stat-label">カテゴリー数</div>
</div>
<div class="stat-card">
<div class="stat-number">1,842</div>
<div class="stat-label">今月の利用回数</div>
</div>
<div class="stat-card">
<div class="stat-number">4.7</div>
<div class="stat-label">平均評価</div>
</div>
</div>

<div class="control-bar">
<input type="text" class="search-box" placeholder="Q&Aを検索...">
<select class="filter-select">
<option value="">すべてのカテゴリー</option>
<option value="lighting">照明計画</option>
<option value="color">色彩・配色</option>
<option value="furniture">家具選び</option>
<option value="layout">レイアウト</option>
<option value="storage">収納</option>
</select>
<select class="filter-select">
<option value="">すべての状態</option>
<option value="active">アクティブ</option>
<option value="draft">下書き</option>
<option value="archived">アーカイブ</option>
</select>
<div class="bulk-actions">
<button class="bulk-btn">一括編集</button>
<button class="bulk-btn">エクスポート</button>
</div>
</div>

<div class="qa-grid">
<div class="qa-card">
<div class="qa-card-header">
<div class="category-tag lighting">照明計画</div>
<div class="qa-actions">
<button class="action-btn edit" onclick="editQA(1)">✏️</button>
<button class="action-btn delete" onclick="deleteQA(1)">🗑️</button>
</div>
</div>
<div class="qa-content">
<div class="question">
リビングの照明が暗い感じがします。明るくするにはどうすれば良いでしょうか?
</div>
<div class="answer">
お疲れ様です!照明のお悩み、とてもよく分かります。明るい空間づくりには層状照明がポイントです。全体照明に加えて、間接照明やスポット照明を組み合わせることで、明るさと居心地の良さを両立できます...
</div>
</div>
<div class="qa-meta">
<div class="usage-stats">
<div class="stat-item">
<span>👁️</span>
<span>324回</span>
</div>
<div class="stat-item">
<span></span>
<span>4.8</span>
</div>
</div>
<div>最終更新: 2日前</div>
</div>
</div>

<div class="qa-card">
<div class="qa-card-header">
<div class="category-tag color">色彩・配色</div>
<div class="qa-actions">
<button class="action-btn edit" onclick="editQA(2)">✏️</button>
<button class="action-btn delete" onclick="deleteQA(2)">🗑️</button>
</div>
</div>
<div class="qa-content">
<div class="question">
北欧風インテリアの色使いについて教えてください。
</div>
<div class="answer">
北欧風インテリアの色使いは、ナチュラルで心地よい空間づくりの基本ですね。ベースカラーは白やベージュ、グレーといった中性色を中心に、アクセントカラーとして自然由来の色合いを取り入れるのがポイントです...
</div>
</div>
<div class="qa-meta">
<div class="usage-stats">
<div class="stat-item">
<span>👁️</span>
<span>189回</span>
</div>
<div class="stat-item">
<span></span>
<span>4.6</span>
</div>
</div>
<div>最終更新: 5日前</div>
</div>
</div>

<div class="qa-card">
<div class="qa-card-header">
<div class="category-tag furniture">家具選び</div>
<div class="qa-actions">
<button class="action-btn edit" onclick="editQA(3)">✏️</button>
<button class="action-btn delete" onclick="deleteQA(3)">🗑️</button>
</div>
</div>
<div class="qa-content">
<div class="question">
狭いリビングに適したソファの選び方を教えてください。
</div>
<div class="answer">
狭いリビングでのソファ選びは、サイズだけでなく、デザインや配置も重要なポイントです。まず、部屋のサイズに対して適切なソファサイズの選び方から説明いたします。一般的に、ソファ幅は部屋の幅の1/3程度が理想的です...
</div>
</div>
<div class="qa-meta">
<div class="usage-stats">
<div class="stat-item">
<span>👁️</span>
<span>267回</span>
</div>
<div class="stat-item">
<span></span>
<span>4.9</span>
</div>
</div>
<div>最終更新: 1週間前</div>
</div>
</div>

<div class="qa-card">
<div class="qa-card-header">
<div class="category-tag layout">レイアウト</div>
<div class="qa-actions">
<button class="action-btn edit" onclick="editQA(4)">✏️</button>
<button class="action-btn delete" onclick="deleteQA(4)">🗑️</button>
</div>
</div>
<div class="qa-content">
<div class="question">
ワンルームマンションの家具配置のコツを教えてください。
</div>
<div class="answer">
ワンルームマンションでは、限られた空間を効率的に使うことがポイントですね。家具配置の基本原則は「生活動線の確保」と「視覚的な広がりの演出」です。まず、玄関から奥に向かって家具を配置し...
</div>
</div>
<div class="qa-meta">
<div class="usage-stats">
<div class="stat-item">
<span>👁️</span>
<span>412回</span>
</div>
<div class="stat-item">
<span></span>
<span>4.7</span>
</div>
</div>
<div>最終更新: 3日前</div>
</div>
</div>

<div class="qa-card">
<div class="qa-card-header">
<div class="category-tag">収納</div>
<div class="qa-actions">
<button class="action-btn edit" onclick="editQA(5)">✏️</button>
<button class="action-btn delete" onclick="deleteQA(5)">🗑️</button>
</div>
</div>
<div class="qa-content">
<div class="question">
子供部屋の収納アイデアを教えてください。おもちゃが散らかりがちです。
</div>
<div class="answer">
お子様のお部屋の収納、親御さんの共通の悩みですね。子供が自分で片付けられる収納システムを作ることが重要です。まず、おもちゃの種類別に分類し、それぞれに専用の収納場所を決めましょう...
</div>
</div>
<div class="qa-meta">
<div class="usage-stats">
<div class="stat-item">
<span>👁️</span>
<span>298回</span>
</div>
<div class="stat-item">
<span></span>
<span>4.8</span>
</div>
</div>
<div>最終更新: 1日前</div>
</div>
</div>

<div class="qa-card">
<div class="qa-card-header">
<div class="category-tag lighting">照明計画</div>
<div class="qa-actions">
<button class="action-btn edit" onclick="editQA(6)">✏️</button>
<button class="action-btn delete" onclick="deleteQA(6)">🗑️</button>
</div>
</div>
<div class="qa-content">
<div class="question">
ダイニングエリアの照明選びで気をつけるべきポイントは?
</div>
<div class="answer">
ダイニングエリアの照明は、食事を美味しく見せる重要な要素ですね。ペンダントライトを中心とした計画をお勧めします。テーブル上60-70cm程度の高さに設置し、食卓全体が均一に照らされるようにします...
</div>
</div>
<div class="qa-meta">
<div class="usage-stats">
<div class="stat-item">
<span>👁️</span>
<span>156回</span>
</div>
<div class="stat-item">
<span></span>
<span>4.5</span>
</div>
</div>
<div>最終更新: 1週間前</div>
</div>
</div>
</div>
</main>
</div>

<!-- Q&A編集モーダル -->
<div id="qa-modal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title" id="modal-title">新しいQ&Aを追加</h2>
<button class="close-btn" onclick="closeModal()">&times;</button>
</div>
<div class="modal-body">
<div class="form-group">
<label class="form-label">カテゴリー</label>
<select class="form-input" id="qa-category">
<option value="">カテゴリーを選択</option>
<option value="lighting">照明計画</option>
<option value="color">色彩・配色</option>
<option value="furniture">家具選び</option>
<option value="layout">レイアウト</option>
<option value="storage">収納</option>
</select>
</div>
<div class="form-group">
<label class="form-label">質問</label>
<textarea class="form-input form-textarea" id="qa-question" placeholder="受講者からの質問を入力してください..."></textarea>
</div>
<div class="form-group">
<label class="form-label">回答</label>
<textarea class="form-input form-textarea" id="qa-answer" placeholder="講師の語り口で回答を入力してください..." style="min-height: 200px;"></textarea>
</div>
<div class="form-group">
<label class="form-label">タグ(カンマ区切り)</label>
<input type="text" class="form-input" id="qa-tags" placeholder="例: 初心者, 照明, LED">
</div>
</div>
<div class="modal-footer">
<button class="cancel-btn" onclick="closeModal()">キャンセル</button>
<button class="save-btn" onclick="saveQA()">保存</button>
</div>
</div>
</div>

<script>
function openModal() {
document.getElementById('qa-modal').style.display = 'block';
document.getElementById('modal-title').textContent = '新しいQ&Aを追加';
// フォームをクリア
document.getElementById('qa-category').value = '';
document.getElementById('qa-question').value = '';
document.getElementById('qa-answer').value = '';
document.getElementById('qa-tags').value = '';
}

function closeModal() {
document.getElementById('qa-modal').style.display = 'none';
}

function editQA(id) {
document.getElementById('qa-modal').style.display = 'block';
document.getElementById('modal-title').textContent = 'Q&Aを編集';
// 実際の実装では、IDに基づいてデータを取得
console.log('編集するQ&A ID:', id);
}

function deleteQA(id) {
if (confirm('このQ&Aを削除してもよろしいですか?')) {
console.log('削除するQ&A ID:', id);
// 実際の実装では削除処理を実行
}
}

function saveQA() {
const category = document.getElementById('qa-category').value;
const question = document.getElementById('qa-question').value;
const answer = document.getElementById('qa-answer').value;
const tags = document.getElementById('qa-tags').value;

if (!category || !question || !answer) {
alert('必須項目を入力してください。');
return;
}

// 保存処理(実際の実装ではAPI呼び出し)
console.log('保存データ:', { category, question, answer, tags });
closeModal();
// 実際の実装では成功メッセージの表示やページ更新
}

// モーダル外クリックで閉じる
window.onclick = function(event) {
const modal = document.getElementById('qa-modal');
if (event.target === modal) {
closeModal();
}
}

// 検索機能(簡易実装)
document.querySelector('.search-box').addEventListener('input', function(e) {
const searchTerm = e.target.value.toLowerCase();
const cards = document.querySelectorAll('.qa-card');
cards.forEach(card => {
const question = card.querySelector('.question').textContent.toLowerCase();
const answer = card.querySelector('.answer').textContent.toLowerCase();
if (question.includes(searchTerm) || answer.includes(searchTerm)) {
card.style.display = 'block';
} else {
card.style.display = 'none';
}
});
});

// フィルター機能(簡易実装)
document.querySelectorAll('.filter-select').forEach(select => {
select.addEventListener('change', function() {
// 実際の実装ではより複雑なフィルタリングロジック
console.log('フィルター変更:', this.value);
});
});
</script>
</body>
</html>
(1-1/6)