- Changed links in index.html and myQuestion.html to point to the correct pages for better navigation. - Added new styles and JavaScript functions in createQuestion.html for dynamic question management, including adding, editing, and deleting questions and options. - Implemented local storage functionality for saving and managing questionnaires, including validation and publishing features. - Improved user interface elements for better interaction and usability.
375 lines
12 KiB
HTML
375 lines
12 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>问卷分析</title>
|
||
<!-- 引入 Chart.js -->
|
||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
body {
|
||
background: #C3C3C3;
|
||
}
|
||
header {
|
||
background-color: #CF9A30;
|
||
color: #EEE8E4;
|
||
text-align: start;
|
||
padding: 20px;
|
||
display: flex;
|
||
}
|
||
main {
|
||
padding: 30px 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
.box {
|
||
width: 90%;
|
||
padding: 14px;
|
||
background-color: #EBEBEB;
|
||
box-shadow: 1px 2px 2px rgba(0,0,0,0.4);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-direction: column;
|
||
}
|
||
.quesen{
|
||
width: 32px;
|
||
height: 32px;
|
||
font-size: 28px;
|
||
font-weight: bold;
|
||
text-align: center;
|
||
line-height: 24px;
|
||
color: #CF9A30;
|
||
border-radius: 50px;
|
||
padding-top: 5px;
|
||
background-color: #EBEBEB;
|
||
position: absolute;
|
||
font-style: normal;
|
||
top: 14px;
|
||
left: 60px;
|
||
}
|
||
.title{
|
||
margin-left: 80px;
|
||
font-size: 24px;
|
||
line-height: 20px;
|
||
font-weight: bold;
|
||
margin-right: 60px;
|
||
}
|
||
.nav-bar a {
|
||
line-height: 20px;
|
||
font-size: 20px;
|
||
color: #EEE8E4;
|
||
border: 2px solid #c78501;
|
||
padding: 2px;
|
||
text-decoration: none;
|
||
}
|
||
|
||
.question-title {
|
||
width: 100%;
|
||
padding: 20px;
|
||
text-align: center;
|
||
font-size: 24px;
|
||
font-weight: bold;
|
||
background: #CEEACA;
|
||
margin-bottom: 20px;
|
||
border-radius: 2px;
|
||
}
|
||
|
||
.question-info {
|
||
width: 100%;
|
||
padding: 10px;
|
||
margin-bottom: 20px;
|
||
display: flex;
|
||
justify-content: space-around;
|
||
background: #fff;
|
||
border-radius: 2px;
|
||
}
|
||
|
||
.question-item {
|
||
width: 100%;
|
||
margin: 10px 0;
|
||
padding: 20px;
|
||
background: #fff;
|
||
border-radius: 2px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
}
|
||
|
||
.question-content {
|
||
flex: 1;
|
||
padding-right: 20px;
|
||
}
|
||
|
||
.question-item-title {
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.option-item {
|
||
margin: 10px 0;
|
||
padding: 5px 0;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.option-item span {
|
||
margin-right: 10px;
|
||
}
|
||
|
||
.chart-container {
|
||
width: 300px;
|
||
height: 300px;
|
||
margin-left: 20px;
|
||
}
|
||
|
||
.back-button {
|
||
margin-top: 20px;
|
||
padding: 8px 24px;
|
||
background: #CF9A30;
|
||
color: #fff;
|
||
border: none;
|
||
border-radius: 2px;
|
||
cursor: pointer;
|
||
font-size: 16px;
|
||
}
|
||
|
||
.back-button:hover {
|
||
background: #c78501;
|
||
}
|
||
|
||
.total-responses {
|
||
margin-top: 10px;
|
||
font-size: 16px;
|
||
color: #666;
|
||
}
|
||
|
||
.question-list{
|
||
width: 100%;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<header>
|
||
<i class="quesen">?</i>
|
||
<div class="title">问卷管理</div>
|
||
<div class="nav-bar">
|
||
<a href="myQuestion.html">我的问卷</a>
|
||
</div>
|
||
</header>
|
||
<main>
|
||
<div class="box">
|
||
<div class="question-title"></div>
|
||
<div class="question-info" style="display: none;">
|
||
<span>创建日期:<span class="create-time"></span></span>
|
||
<span>发布日期:<span class="publish-time"></span></span>
|
||
<span>截止日期:<span class="end-time"></span></span>
|
||
<span>问卷状态:<span class="status"></span></span>
|
||
</div>
|
||
<div class="total-responses" style="display: none;">总回答数:<span class="response-count">0</span></div>
|
||
<div class="question-list"></div>
|
||
<button class="back-button" onclick="window.location.href='myQuestion.html'">返回列表</button>
|
||
</div>
|
||
</main>
|
||
|
||
<script>
|
||
let currentQuestionnaire = null;
|
||
let questionnaireAnswers = [];
|
||
|
||
function formatDate(timestamp) {
|
||
if (!timestamp) return '-';
|
||
const date = new Date(timestamp);
|
||
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
|
||
}
|
||
|
||
function renderPieChart(containerId, labels, data) {
|
||
const ctx = document.getElementById(containerId).getContext('2d');
|
||
return new Chart(ctx, {
|
||
type: 'pie',
|
||
data: {
|
||
labels: labels,
|
||
datasets: [{
|
||
data: data,
|
||
backgroundColor: [
|
||
'#FF6384',
|
||
'#36A2EB',
|
||
'#FFCE56',
|
||
'#4BC0C0',
|
||
'#9966FF',
|
||
'#FF9F40'
|
||
]
|
||
}]
|
||
},
|
||
options: {
|
||
responsive: true,
|
||
maintainAspectRatio: false
|
||
}
|
||
});
|
||
}
|
||
|
||
function renderBarChart(containerId, validCount, invalidCount) {
|
||
const ctx = document.getElementById(containerId).getContext('2d');
|
||
return new Chart(ctx, {
|
||
type: 'bar',
|
||
data: {
|
||
labels: ['有效回答', '无效回答'],
|
||
datasets: [{
|
||
data: [validCount, invalidCount],
|
||
backgroundColor: ['#36A2EB', '#FF6384']
|
||
}]
|
||
},
|
||
options: {
|
||
responsive: true,
|
||
maintainAspectRatio: false,
|
||
scales: {
|
||
y: {
|
||
beginAtZero: true,
|
||
ticks: {
|
||
stepSize: 1
|
||
}
|
||
}
|
||
},
|
||
plugins: {
|
||
legend: {
|
||
display: false
|
||
}
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
function analyzeAnswers(question) {
|
||
const answers = questionnaireAnswers.map(response =>
|
||
response.answers.find(a => a.questionId === question.id)
|
||
);
|
||
|
||
if (question.type === 'text') {
|
||
const validCount = answers.filter(a => a && a.answer && a.answer.trim()).length;
|
||
const invalidCount = answers.length - validCount;
|
||
return { validCount, invalidCount };
|
||
} else {
|
||
const optionCounts = {};
|
||
question.options.forEach(opt => optionCounts[opt.id] = 0);
|
||
|
||
answers.forEach(answer => {
|
||
if (answer && answer.answer) {
|
||
const selectedOptions = Array.isArray(answer.answer) ? answer.answer : [answer.answer];
|
||
selectedOptions.forEach(optId => {
|
||
if (optionCounts[optId] !== undefined) {
|
||
optionCounts[optId]++;
|
||
}
|
||
});
|
||
}
|
||
});
|
||
return optionCounts;
|
||
}
|
||
}
|
||
|
||
function renderQuestion(question, index) {
|
||
const analysis = analyzeAnswers(question);
|
||
const chartId = `chart_${question.id}`;
|
||
|
||
let questionHtml = `
|
||
<div class="question-item">
|
||
<div class="question-content">
|
||
<div class="question-item-title">
|
||
${index + 1}. ${question.title}
|
||
${question.required ? '<span style="color: red; margin-left: 5px;">*(必答题)</span>' : ''}
|
||
</div>
|
||
`;
|
||
|
||
if (question.type === 'text') {
|
||
questionHtml += `
|
||
<div class="text-analysis">
|
||
<div class="question-content">
|
||
<textarea class="text-answer" disabled
|
||
style="width: 100%; min-height: 100px; padding: 8px; margin-top: 10px; resize: vertical; background-color: #f5f5f5;"
|
||
placeholder="此处填写答案"></textarea>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="chart-container">
|
||
<canvas id="${chartId}"></canvas>
|
||
</div>
|
||
`;
|
||
|
||
setTimeout(() => renderBarChart(chartId, analysis.validCount, analysis.invalidCount), 0);
|
||
} else {
|
||
questionHtml += `
|
||
<div class="options">
|
||
${question.options.map(option => `
|
||
<div class="option-item">
|
||
<input type="${question.type}" disabled>
|
||
<label>${option.content}</label>
|
||
<span style="margin-left: 10px;"></span>
|
||
</div>
|
||
`).join('')}
|
||
</div>
|
||
</div>
|
||
<div class="chart-container">
|
||
<canvas id="${chartId}"></canvas>
|
||
</div>
|
||
`;
|
||
|
||
setTimeout(() => renderPieChart(
|
||
chartId,
|
||
question.options.map(opt => opt.content),
|
||
question.options.map(opt => analysis[opt.id])
|
||
), 0);
|
||
}
|
||
|
||
questionHtml += `</div>`;
|
||
return questionHtml;
|
||
}
|
||
|
||
function loadQuestionnaireData() {
|
||
const urlParams = new URLSearchParams(window.location.search);
|
||
const questionnaireId = urlParams.get('id');
|
||
|
||
if (!questionnaireId) {
|
||
alert('问卷ID不存在!');
|
||
window.location.href = 'myQuestion.html';
|
||
return;
|
||
}
|
||
|
||
const questionnaireList = JSON.parse(localStorage.getItem('questionnaireList') || '[]');
|
||
const questionnaire = questionnaireList.find(q => q.id === questionnaireId);
|
||
|
||
if (!questionnaire) {
|
||
alert('问卷不存在!');
|
||
window.location.href = 'myQuestion.html';
|
||
return;
|
||
}
|
||
|
||
currentQuestionnaire = questionnaire;
|
||
|
||
// 获取问卷答案
|
||
const allAnswers = JSON.parse(localStorage.getItem('questionnaireAnswers') || '[]');
|
||
questionnaireAnswers = allAnswers.filter(a => a.questionnaireId === questionnaireId);
|
||
|
||
// 填充问卷信息
|
||
document.querySelector('.question-title').textContent = questionnaire.title;
|
||
document.querySelector('.create-time').textContent = formatDate(questionnaire.createTime);
|
||
document.querySelector('.publish-time').textContent = formatDate(questionnaire.publishTime);
|
||
document.querySelector('.end-time').textContent = formatDate(questionnaire.data.endTime);
|
||
document.querySelector('.status').textContent = questionnaire.status;
|
||
document.querySelector('.response-count').textContent = questionnaireAnswers.length;
|
||
|
||
// 渲染问题列表
|
||
const questionListHtml = questionnaire.data.questions
|
||
.map((question, index) => renderQuestion(question, index))
|
||
.join('');
|
||
document.querySelector('.question-list').innerHTML = questionListHtml;
|
||
}
|
||
|
||
window.onload = loadQuestionnaireData;
|
||
</script>
|
||
</body>
|
||
</html> |