308 lines
14 KiB
HTML
308 lines
14 KiB
HTML
|
<!DOCTYPE html>
|
||
|
<html lang="ja">
|
||
|
<head>
|
||
|
<meta charset="UTF-8">
|
||
|
<title>イントロクイズBOT管理ページ</title>
|
||
|
<style>
|
||
|
.form-group {
|
||
|
margin-bottom: 15px;
|
||
|
}
|
||
|
.form-group label {
|
||
|
display: inline-block;
|
||
|
width: 120px;
|
||
|
}
|
||
|
.form-group input, .form-group select {
|
||
|
width: calc(100% - 130px);
|
||
|
}
|
||
|
.form-group select {
|
||
|
height: 100px;
|
||
|
}
|
||
|
.form-container, .table-container {
|
||
|
margin-left: 0;
|
||
|
}
|
||
|
.button-group {
|
||
|
text-align: left;
|
||
|
}
|
||
|
table {
|
||
|
width: 100%;
|
||
|
border-collapse: collapse.
|
||
|
}
|
||
|
th, td {
|
||
|
padding: 8px;
|
||
|
text-align: left;
|
||
|
border: 1px solid #ddd;
|
||
|
white-space: nowrap;
|
||
|
}
|
||
|
th {
|
||
|
background-color: #f2f2f2;
|
||
|
}
|
||
|
#randomQuizResult, #selectedQuizResult {
|
||
|
display: none;
|
||
|
}
|
||
|
#message {
|
||
|
font-size: 24px;
|
||
|
color: red;
|
||
|
margin-top: 20px;
|
||
|
}
|
||
|
#searchResults div {
|
||
|
cursor: pointer;
|
||
|
padding: 5px;
|
||
|
border: 1px solid #ddd;
|
||
|
margin-top: -1px;
|
||
|
}
|
||
|
#searchResults div:hover {
|
||
|
background-color: #f2f2f2;
|
||
|
}
|
||
|
</style>
|
||
|
<script>
|
||
|
async function handleFormSubmit(event, formId, endpoint) {
|
||
|
event.preventDefault();
|
||
|
const form = document.getElementById(formId);
|
||
|
const formData = new FormData(form);
|
||
|
const payload = {};
|
||
|
formData.forEach((value, key) => {
|
||
|
payload[key] = value;
|
||
|
});
|
||
|
|
||
|
try {
|
||
|
const response = await fetch(endpoint, {
|
||
|
method: 'POST',
|
||
|
headers: {
|
||
|
'Content-Type': 'application/json'
|
||
|
},
|
||
|
body: JSON.stringify(payload)
|
||
|
});
|
||
|
const result = await response.json();
|
||
|
document.getElementById('message').innerText = result.message || result.error;
|
||
|
if (result.user_id && result.password) {
|
||
|
document.getElementById('accountInfo').innerText = `UserID: ${result.user_id}, Password: ${result.password}`;
|
||
|
}
|
||
|
} catch (error) {
|
||
|
document.getElementById('message').innerText = 'エラーが発生しました: ' + error.message;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function handleAction(event, endpoint) {
|
||
|
event.preventDefault();
|
||
|
try {
|
||
|
const response = await fetch(endpoint, { method: 'POST' });
|
||
|
const result = await response.json();
|
||
|
document.getElementById('message').innerText = result.message || result.error;
|
||
|
} catch (error) {
|
||
|
document.getElementById('message').innerText = 'エラーが発生しました: ' + error.message;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function updateUniqueKeywords() {
|
||
|
try {
|
||
|
const response = await fetch('/unique_keywords');
|
||
|
const keywords = await response.json();
|
||
|
keywords.sort(); // ここでキーワードを五十音順にソート
|
||
|
const keywordList = document.getElementById('uniqueKeywordsList');
|
||
|
keywordList.innerHTML = '';
|
||
|
keywords.forEach(keyword => {
|
||
|
const option = document.createElement('option');
|
||
|
option.value = keyword;
|
||
|
option.textContent = keyword;
|
||
|
keywordList.appendChild(option);
|
||
|
});
|
||
|
} catch (error) {
|
||
|
document.getElementById('message').innerText = 'ユニークキーワードの更新中にエラーが発生しました: ' + error.message;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function drawRandomQuiz(event) {
|
||
|
event.preventDefault();
|
||
|
const keyword = document.getElementById('uniqueKeywordsList').value;
|
||
|
if (!keyword) {
|
||
|
document.getElementById('message').innerText = 'キーワードを選択してください';
|
||
|
return;
|
||
|
}
|
||
|
try {
|
||
|
const response = await fetch('/random_quiz', {
|
||
|
method: 'POST',
|
||
|
headers: {
|
||
|
'Content-Type': 'application/json'
|
||
|
},
|
||
|
body: JSON.stringify({ keyword })
|
||
|
});
|
||
|
const result = await response.json();
|
||
|
if (result.error) {
|
||
|
document.getElementById('message').innerText = result.error;
|
||
|
document.getElementById('randomQuizResult').style.display = 'none';
|
||
|
} else {
|
||
|
document.getElementById('randomQuizResult').innerHTML = `
|
||
|
<p>ID: ${result.id}</p>
|
||
|
<p>タイトル: ${result.title}</p>
|
||
|
<p>フル音源名: ${result.full_audio_name}</p>
|
||
|
<p>イントロ音源名: ${result.intro_audio_name}</p>
|
||
|
<p>キーワード1: ${result.keyword1}</p>
|
||
|
<p>キーワード2: ${result.keyword2}</p>
|
||
|
<p>キーワード3: ${result.keyword3}</p>
|
||
|
<button onclick="startQuiz(${result.id}, '${result.intro_audio_name}')">クイズを開始</button>
|
||
|
<button onclick="stopAudio()">再生停止</button>
|
||
|
<button onclick="playFullAudio('${result.full_audio_name}')">フル音源を再生</button>
|
||
|
`;
|
||
|
document.getElementById('randomQuizResult').style.display = 'block';
|
||
|
}
|
||
|
} catch (error) {
|
||
|
document.getElementById('message').innerText = 'クイズの抽選中にエラーが発生しました: ' + error.message;
|
||
|
document.getElementById('randomQuizResult').style.display = 'none';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function startQuiz(quizId, introAudioName) {
|
||
|
const volume = document.getElementById('quizVolume').value;
|
||
|
try {
|
||
|
const response = await fetch('/start_quiz', {
|
||
|
method: 'POST',
|
||
|
headers: {
|
||
|
'Content-Type': 'application/json'
|
||
|
},
|
||
|
body: JSON.stringify({ quiz_id: quizId, intro_audio_name: introAudioName, volume: volume })
|
||
|
});
|
||
|
const result = await response.json();
|
||
|
document.getElementById('message').innerText = result.message || result.error;
|
||
|
} catch (error) {
|
||
|
document.getElementById('message').innerText = 'クイズの開始中にエラーが発生しました: ' + error.message;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function stopAudio() {
|
||
|
try {
|
||
|
const response = await fetch('/stop_audio', { method: 'POST' });
|
||
|
const result = await response.json();
|
||
|
document.getElementById('message').innerText = result.message || result.error;
|
||
|
} catch (error) {
|
||
|
document.getElementById('message').innerText = '再生停止中にエラーが発生しました: ' + error.message;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function playFullAudio(fullAudioName) {
|
||
|
const volume = document.getElementById('fullAudioVolume').value;
|
||
|
try {
|
||
|
const encodedFilename = encodeURIComponent(fullAudioName);
|
||
|
const response = await fetch(`/play/${encodedFilename}`, {
|
||
|
method: 'POST',
|
||
|
headers: {
|
||
|
'Content-Type': 'application/json'
|
||
|
},
|
||
|
body: JSON.stringify({ volume: volume })
|
||
|
});
|
||
|
const result = await response.json();
|
||
|
document.getElementById('message').innerText = result.message || result.error;
|
||
|
} catch (error) {
|
||
|
document.getElementById('message').innerText = 'フル音源の再生中にエラーが発生しました: ' + error.message;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function resetQuiz() {
|
||
|
try {
|
||
|
const response = await fetch('/reset_quiz', { method: 'POST' });
|
||
|
const result = await response.json();
|
||
|
document.getElementById('message').innerText = result.message || result.error;
|
||
|
document.getElementById('randomQuizResult').style.display = 'none';
|
||
|
document.getElementById('selectedQuizResult').style.display = 'none';
|
||
|
} catch (error) {
|
||
|
document.getElementById('message').innerText = 'クイズのリセット中にエラーが発生しました: ' + error.message;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function searchQuizByTitle(event) {
|
||
|
const title = document.getElementById('searchTitle').value;
|
||
|
if (!title) {
|
||
|
document.getElementById('message').innerText = 'タイトルを入力してください';
|
||
|
return;
|
||
|
}
|
||
|
try {
|
||
|
const response = await fetch(`/search_quiz?title=${encodeURIComponent(title)}`);
|
||
|
const results = await response.json();
|
||
|
const searchResults = document.getElementById('searchResults');
|
||
|
searchResults.innerHTML = '';
|
||
|
results.forEach(result => {
|
||
|
const resultDiv = document.createElement('div');
|
||
|
resultDiv.innerHTML = `
|
||
|
<p>ID: ${result.id}</p>
|
||
|
<p>タイトル: ${result.title}</p>
|
||
|
<p>フル音源名: ${result.full_audio_name}</p>
|
||
|
<p>イントロ音源名: ${result.intro_audio_name}</p>
|
||
|
<p>キーワード1: ${result.keyword1}</p>
|
||
|
<p>キーワード2: ${result.keyword2}</p>
|
||
|
<p>キーワード3: ${result.keyword3}</p>
|
||
|
`;
|
||
|
resultDiv.addEventListener('click', () => selectQuiz(result));
|
||
|
searchResults.appendChild(resultDiv);
|
||
|
});
|
||
|
} catch (error) {
|
||
|
document.getElementById('message').innerText = 'クイズの検索中にエラーが発生しました: ' + error.message;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function selectQuiz(result) {
|
||
|
document.getElementById('selectedQuizResult').innerHTML = `
|
||
|
<p>ID: ${result.id}</p>
|
||
|
<p>タイトル: ${result.title}</p>
|
||
|
<p>フル音源名: ${result.full_audio_name}</p>
|
||
|
<p>イントロ音源名: ${result.intro_audio_name}</p>
|
||
|
<p>キーワード1: ${result.keyword1}</p>
|
||
|
<p>キーワード2: ${result.keyword2}</p>
|
||
|
<p>キーワード3: ${result.keyword3}</p>
|
||
|
<button onclick="startQuiz(${result.id}, '${result.intro_audio_name}')">クイズを開始</button>
|
||
|
<button onclick="stopAudio()">再生停止</button>
|
||
|
<button onclick="playFullAudio('${result.full_audio_name}')">フル音源を再生</button>
|
||
|
`;
|
||
|
document.getElementById('selectedQuizResult').style.display = 'block';
|
||
|
}
|
||
|
|
||
|
document.addEventListener('DOMContentLoaded', () => {
|
||
|
updateUniqueKeywords();
|
||
|
});
|
||
|
</script>
|
||
|
</head>
|
||
|
<body>
|
||
|
<h1>イントロクイズBOT管理ページ</h1>
|
||
|
<div id="message" style="color: red; margin-top: 20px;"></div>
|
||
|
<button onclick="location.href='/quiz_master_page'">マスタデータ管理ページに移動</button>
|
||
|
<button onclick="location.href='/uploaded_files'">ファイル管理ページに移動</button>
|
||
|
<h2>ボイスチャンネル操作</h2>
|
||
|
<form id="joinForm" onsubmit="handleFormSubmit(event, 'joinForm', '/join')">
|
||
|
<label for="channel_id">チャンネルID:</label>
|
||
|
<input type="text" name="channel_id" id="channel_id" required>
|
||
|
<button type="submit">参加</button>
|
||
|
</form>
|
||
|
<form id="leaveForm" onsubmit="handleAction(event, '/leave')">
|
||
|
<button type="submit">退出</button>
|
||
|
</form>
|
||
|
<div class="form-group">
|
||
|
<label for="quizVolume">クイズ音量:</label>
|
||
|
<input type="text" id="quizVolume" name="quizVolume" value="13">
|
||
|
</div>
|
||
|
<div class="form-group">
|
||
|
<label for="fullAudioVolume">フル音源音量:</label>
|
||
|
<input type="text" id="fullAudioVolume" name="fullAudioVolume" value="3">
|
||
|
</div>
|
||
|
<h2>クイズ出題</h2>
|
||
|
<h4>グループランダム選択</h4>
|
||
|
<select id="uniqueKeywordsList">
|
||
|
<!-- ユニークキーワードはここに動的に挿入されます -->
|
||
|
</select>
|
||
|
<button onclick="drawRandomQuiz(event)">ランダムにクイズを抽選</button>
|
||
|
<button onclick="resetQuiz()">クイズをリセット</button>
|
||
|
<div id="randomQuizResult" style="color: green; margin-top: 20px;"></div>
|
||
|
|
||
|
<h4>タイトル検索</h4>
|
||
|
<form id="searchForm" onsubmit="searchQuizByTitle(event)">
|
||
|
<div class="form-group">
|
||
|
<input type="text" id="searchTitle" name="searchTitle" oninput="searchQuizByTitle(event)" required>
|
||
|
</div>
|
||
|
</form>
|
||
|
<div id="searchResults" style="color: green; margin-top: 20px;"></div>
|
||
|
<div id="selectedQuizResult" style="color: green; margin-top: 20px;"></div>
|
||
|
|
||
|
<h2>ログアウト</h2>
|
||
|
<form id="logoutForm" action="/logout" method="POST">
|
||
|
<button type="submit">ログアウト</button>
|
||
|
</form>
|
||
|
</body>
|
||
|
</html>
|