- 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.
587 lines
22 KiB
HTML
587 lines
22 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>
|
||
<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;
|
||
}
|
||
a{
|
||
text-decoration: none;
|
||
}
|
||
.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%;
|
||
height: 68px;
|
||
text-align: center;
|
||
font-size: 24px;
|
||
font-weight: bold;
|
||
color: #000;
|
||
background: #CEEACA;
|
||
box-shadow: 1px 2px 2px rgba(0,0,0,0.4);
|
||
border-radius: 2px;
|
||
}
|
||
|
||
.question-title:hover{
|
||
background: #FCFF00;
|
||
}
|
||
.but{
|
||
width: 99%;
|
||
height: 40px;
|
||
background-color: #D3D3D3;
|
||
margin-bottom: 25px;
|
||
text-align: center;
|
||
line-height: 40px;
|
||
font-size: 20px;
|
||
font-weight: bold;
|
||
color: #000000;
|
||
padding: 10px 0 50px 0;
|
||
transition: margin-top 0.3s;
|
||
cursor: pointer;
|
||
}
|
||
hr{
|
||
width: 100%;
|
||
}
|
||
.ctrl-bar{
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin: 20px 0;
|
||
}
|
||
.endtime{
|
||
margin-left: 20%;
|
||
}
|
||
.endtime span{
|
||
margin-right: 16px;
|
||
}
|
||
.pushbut{
|
||
margin-right: 20%;
|
||
}
|
||
.pushbut button{
|
||
margin-right: 10px;
|
||
}
|
||
.quetype{
|
||
margin-top: 20px;
|
||
padding: 20px 20%;
|
||
width: 99%;
|
||
border: 1px solid #b3b3b3;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
}
|
||
.quetype button {
|
||
font-size: 16px;
|
||
line-height: 16px;
|
||
padding: 1px 25px;
|
||
}
|
||
|
||
.question-item {
|
||
width: 99%;
|
||
margin: 20px 0;
|
||
padding: 20px;
|
||
background: #fff;
|
||
border: 1px solid #ddd;
|
||
box-shadow: 1px 2px 2px rgba(0,0,0,0.1);
|
||
position: relative;
|
||
}
|
||
|
||
.question-header {
|
||
display: block;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.question-content input[type="text"] {
|
||
width: 100%;
|
||
padding: 8px;
|
||
margin-bottom: 10px;
|
||
border: 1px solid #ddd;
|
||
}
|
||
|
||
.option-item {
|
||
display: flex;
|
||
align-items: center;
|
||
margin: 10px 0;
|
||
}
|
||
|
||
.option-item input[type="text"] {
|
||
margin-left: 10px;
|
||
width: 80%;
|
||
}
|
||
|
||
.delete-btn {
|
||
padding: 2px 8px;
|
||
background: #ff4d4f;
|
||
color: white;
|
||
border: none;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.ctrl-btns {
|
||
display: none;
|
||
position: absolute;
|
||
bottom: 10px;
|
||
right: 10px;
|
||
gap: 10px;
|
||
background: rgba(255, 255, 255, 0.9);
|
||
padding: 5px;
|
||
border-radius: 4px;
|
||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||
}
|
||
|
||
.ctrl-btns button {
|
||
padding: 2px 8px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.quelist{
|
||
width: 100%;
|
||
}
|
||
|
||
.question-item:hover .ctrl-btns {
|
||
display: flex;
|
||
}
|
||
|
||
.question-content {
|
||
margin-bottom: 40px;
|
||
}
|
||
</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">
|
||
<input class="question-title" type="text" placeholder="请在这里输入问卷的标题">
|
||
<div class="quelist"></div>
|
||
<div class="quetype" style="display: none;">
|
||
<button><img style="width: 16px; height: 16px;" src="/img/radio.svg" alt="">单选题</button>
|
||
<button><img style="width: 16px; height: 16px;" src="/img/checkbox.svg" alt="">多选题</button>
|
||
<button><img style="width: 16px; height: 16px;" src="/img/text.svg" alt="">文本题</button>
|
||
</div>
|
||
<a href="javascript:void(0)" class="but" onclick="toggleQueType()">+ 添加问题</a>
|
||
<hr>
|
||
<div class="ctrl-bar">
|
||
<div class="endtime">
|
||
<span>问卷截止日期</span>
|
||
<input type="date" name="endtime" id="endtime">
|
||
</div>
|
||
<div class="pushbut">
|
||
<button onclick="updateQuestionnaire()">保存修改</button>
|
||
<button onclick="window.location.href='myQuestion.html'">返回列表</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</main>
|
||
|
||
<script>
|
||
let questionCount = 0;
|
||
let currentQuestionnaireId = null;
|
||
|
||
function toggleQueType() {
|
||
const queType = document.querySelector('.quetype');
|
||
const addButton = document.querySelector('.but');
|
||
|
||
if (queType.style.display === 'none') {
|
||
queType.style.display = 'flex';
|
||
addButton.style.marginTop = '0';
|
||
}
|
||
}
|
||
|
||
// 添加单选题
|
||
function addRadioQuestion(existingQuestion = null) {
|
||
questionCount++;
|
||
const questionHtml = `
|
||
<div class="question-item" id="question-${questionCount}">
|
||
<div class="question-header">
|
||
<div class="question-title-area">
|
||
<span>${questionCount}. </span>
|
||
<input type="text" placeholder="请输入问题" value="${existingQuestion ? existingQuestion.title : ''}">
|
||
<button onclick="addOption(${questionCount})">添加选项</button>
|
||
<label style="margin-left: 20px;">
|
||
<input type="checkbox" class="required-checkbox" ${existingQuestion && existingQuestion.required ? 'checked' : ''}> 此题为必答题
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<div class="question-content" id="options-${questionCount}">
|
||
${existingQuestion ?
|
||
existingQuestion.options.map(option => `
|
||
<div class="option-item">
|
||
<input type="radio" name="question${questionCount}" disabled>
|
||
<input type="text" placeholder="选项内容" value="${option.content}">
|
||
<button class="delete-btn" onclick="deleteOption(this)">删除</button>
|
||
</div>
|
||
`).join('') :
|
||
Array(4).fill(`
|
||
<div class="option-item">
|
||
<input type="radio" name="question${questionCount}" disabled>
|
||
<input type="text" placeholder="选项内容">
|
||
<button class="delete-btn" onclick="deleteOption(this)">删除</button>
|
||
</div>
|
||
`).join('')
|
||
}
|
||
</div>
|
||
<div class="ctrl-btns">
|
||
<button onclick="moveUp(${questionCount})">上移</button>
|
||
<button onclick="moveDown(${questionCount})">下移</button>
|
||
<button onclick="copyQuestion(${questionCount})">复用</button>
|
||
<button class="delete-btn" onclick="deleteQuestion(${questionCount})">删除</button>
|
||
</div>
|
||
</div>
|
||
`;
|
||
document.querySelector('.quelist').insertAdjacentHTML('beforeend', questionHtml);
|
||
toggleQueType();
|
||
}
|
||
|
||
// 添加多选题
|
||
function addCheckboxQuestion(existingQuestion = null) {
|
||
questionCount++;
|
||
const questionHtml = `
|
||
<div class="question-item" id="question-${questionCount}">
|
||
<div class="question-header">
|
||
<div class="question-title-area">
|
||
<span>${questionCount}. </span>
|
||
<input type="text" placeholder="请输入问题" value="${existingQuestion ? existingQuestion.title : ''}">
|
||
<button onclick="addCheckboxOption(${questionCount})">添加选项</button>
|
||
<label style="margin-left: 20px;">
|
||
<input type="checkbox" class="required-checkbox" ${existingQuestion && existingQuestion.required ? 'checked' : ''}> 此题为必答题
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<div class="question-content" id="options-${questionCount}">
|
||
${existingQuestion ?
|
||
existingQuestion.options.map(option => `
|
||
<div class="option-item">
|
||
<input type="checkbox" name="question${questionCount}" disabled>
|
||
<input type="text" placeholder="选项内容" value="${option.content}">
|
||
<button class="delete-btn" onclick="deleteOption(this)">删除</button>
|
||
</div>
|
||
`).join('') :
|
||
Array(4).fill(`
|
||
<div class="option-item">
|
||
<input type="checkbox" name="question${questionCount}" disabled>
|
||
<input type="text" placeholder="选项内容">
|
||
<button class="delete-btn" onclick="deleteOption(this)">删除</button>
|
||
</div>
|
||
`).join('')
|
||
}
|
||
</div>
|
||
<div class="ctrl-btns">
|
||
<button onclick="moveUp(${questionCount})">上移</button>
|
||
<button onclick="moveDown(${questionCount})">下移</button>
|
||
<button onclick="copyQuestion(${questionCount})">复用</button>
|
||
<button class="delete-btn" onclick="deleteQuestion(${questionCount})">删除</button>
|
||
</div>
|
||
</div>
|
||
`;
|
||
document.querySelector('.quelist').insertAdjacentHTML('beforeend', questionHtml);
|
||
toggleQueType();
|
||
}
|
||
|
||
// 添加文本题
|
||
function addTextQuestion(existingQuestion = null) {
|
||
questionCount++;
|
||
const questionHtml = `
|
||
<div class="question-item" id="question-${questionCount}">
|
||
<div class="question-header">
|
||
<div class="question-title-area">
|
||
<span>${questionCount}. </span>
|
||
<input type="text" placeholder="请输入问题" value="${existingQuestion ? existingQuestion.title : ''}">
|
||
<label style="margin-left: 20px;">
|
||
<input type="checkbox" class="required-checkbox" ${existingQuestion && existingQuestion.required ? 'checked' : ''}> 此题为必答题
|
||
</label>
|
||
</div>
|
||
</div>
|
||
<div class="question-content" id="options-${questionCount}">
|
||
<textarea disabled placeholder="此处供填写者输入文本答案"
|
||
style="width: 100%; min-height: 100px; padding: 8px; margin-top: 10px; resize: vertical;"></textarea>
|
||
</div>
|
||
<div class="ctrl-btns">
|
||
<button onclick="moveUp(${questionCount})">上移</button>
|
||
<button onclick="moveDown(${questionCount})">下移</button>
|
||
<button onclick="copyQuestion(${questionCount})">复用</button>
|
||
<button class="delete-btn" onclick="deleteQuestion(${questionCount})">删除</button>
|
||
</div>
|
||
</div>
|
||
`;
|
||
document.querySelector('.quelist').insertAdjacentHTML('beforeend', questionHtml);
|
||
toggleQueType();
|
||
}
|
||
|
||
// 其他辅助函数
|
||
function addOption(questionId) {
|
||
const optionHtml = `
|
||
<div class="option-item">
|
||
<input type="radio" name="question${questionId}" disabled>
|
||
<input type="text" placeholder="选项内容">
|
||
<button class="delete-btn" onclick="deleteOption(this)">删除</button>
|
||
</div>
|
||
`;
|
||
document.querySelector(`#options-${questionId}`).insertAdjacentHTML('beforeend', optionHtml);
|
||
}
|
||
|
||
function addCheckboxOption(questionId) {
|
||
const optionHtml = `
|
||
<div class="option-item">
|
||
<input type="checkbox" name="question${questionId}" disabled>
|
||
<input type="text" placeholder="选项内容">
|
||
<button class="delete-btn" onclick="deleteOption(this)">删除</button>
|
||
</div>
|
||
`;
|
||
document.querySelector(`#options-${questionId}`).insertAdjacentHTML('beforeend', optionHtml);
|
||
}
|
||
|
||
function deleteOption(btn) {
|
||
btn.parentElement.remove();
|
||
}
|
||
|
||
function deleteQuestion(questionId) {
|
||
document.querySelector(`#question-${questionId}`).remove();
|
||
}
|
||
|
||
function copyQuestion(questionId) {
|
||
const original = document.querySelector(`#question-${questionId}`);
|
||
const clone = original.cloneNode(true);
|
||
questionCount++;
|
||
clone.id = `question-${questionCount}`;
|
||
original.after(clone);
|
||
}
|
||
|
||
function moveUp(questionId) {
|
||
const question = document.querySelector(`#question-${questionId}`);
|
||
const prev = question.previousElementSibling;
|
||
if (prev) {
|
||
prev.before(question);
|
||
}
|
||
}
|
||
|
||
function moveDown(questionId) {
|
||
const question = document.querySelector(`#question-${questionId}`);
|
||
const next = question.nextElementSibling;
|
||
if (next) {
|
||
next.after(question);
|
||
}
|
||
}
|
||
|
||
// 获取问卷数据
|
||
function getQuestionnaireData(isPublished = false) {
|
||
const now = new Date().getTime();
|
||
const questionnaire = {
|
||
title: document.querySelector('.question-title').value,
|
||
createTime: now,
|
||
endTime: document.querySelector('#endtime').value,
|
||
publishTime: isPublished ? now : null,
|
||
status: isPublished ? '已发布' : '未发布',
|
||
questions: []
|
||
};
|
||
|
||
const questionItems = document.querySelectorAll('.question-item');
|
||
questionItems.forEach((item, index) => {
|
||
const questionType = item.querySelector('input[type="radio"]') ? 'radio' :
|
||
item.querySelector('input[type="checkbox"]') ? 'checkbox' : 'text';
|
||
|
||
const question = {
|
||
id: index + 1,
|
||
type: questionType,
|
||
title: item.querySelector('.question-title-area input[type="text"]').value,
|
||
required: item.querySelector('.required-checkbox').checked,
|
||
options: []
|
||
};
|
||
|
||
if (questionType === 'radio' || questionType === 'checkbox') {
|
||
const options = item.querySelectorAll('.option-item input[type="text"]');
|
||
options.forEach((option, optionIndex) => {
|
||
question.options.push({
|
||
id: optionIndex + 1,
|
||
content: option.value
|
||
});
|
||
});
|
||
}
|
||
|
||
questionnaire.questions.push(question);
|
||
});
|
||
|
||
return questionnaire;
|
||
}
|
||
|
||
// 加载问卷数据
|
||
function loadQuestionnaireData() {
|
||
const urlParams = new URLSearchParams(window.location.search);
|
||
const questionnaireId = urlParams.get('id');
|
||
|
||
if (!questionnaireId) {
|
||
alert('问卷ID不存在!');
|
||
window.location.href = 'myQuestion.html';
|
||
return;
|
||
}
|
||
|
||
currentQuestionnaireId = questionnaireId;
|
||
const questionnaireList = JSON.parse(localStorage.getItem('questionnaireList') || '[]');
|
||
const questionnaire = questionnaireList.find(q => q.id === questionnaireId);
|
||
|
||
if (!questionnaire) {
|
||
alert('问卷不存在!');
|
||
window.location.href = 'myQuestion.html';
|
||
return;
|
||
}
|
||
|
||
// 填充问卷数据
|
||
document.querySelector('.question-title').value = questionnaire.title;
|
||
document.querySelector('#endtime').value = questionnaire.data.endTime;
|
||
|
||
// 渲染问题列表
|
||
questionnaire.data.questions.forEach(question => {
|
||
if (question.type === 'radio') {
|
||
addRadioQuestion(question);
|
||
} else if (question.type === 'checkbox') {
|
||
addCheckboxQuestion(question);
|
||
} else {
|
||
addTextQuestion(question);
|
||
}
|
||
});
|
||
}
|
||
|
||
// 更新问卷
|
||
function updateQuestionnaire() {
|
||
if (!validateQuestionnaire()) return;
|
||
|
||
const questionnaireList = JSON.parse(localStorage.getItem('questionnaireList') || '[]');
|
||
const index = questionnaireList.findIndex(q => q.id === currentQuestionnaireId);
|
||
|
||
if (index === -1) {
|
||
alert('问卷不存在!');
|
||
return;
|
||
}
|
||
|
||
const updatedData = getQuestionnaireData(false);
|
||
questionnaireList[index].title = updatedData.title;
|
||
questionnaireList[index].data = updatedData;
|
||
|
||
localStorage.setItem('questionnaireList', JSON.stringify(questionnaireList));
|
||
alert('问卷修改成功!');
|
||
window.location.href = 'myQuestion.html';
|
||
}
|
||
|
||
// 验证问卷
|
||
function validateQuestionnaire() {
|
||
const title = document.querySelector('.question-title').value.trim();
|
||
if (!title) {
|
||
alert('请输入问卷标题!');
|
||
return false;
|
||
}
|
||
|
||
const endTime = document.querySelector('#endtime').value;
|
||
if (!endTime) {
|
||
alert('请设置问卷截止日期!');
|
||
return false;
|
||
}
|
||
|
||
const questions = document.querySelectorAll('.question-item');
|
||
if (questions.length === 0) {
|
||
alert('请至少添加一个问题!');
|
||
return false;
|
||
}
|
||
|
||
for (let question of questions) {
|
||
const questionTitle = question.querySelector('.question-title-area input[type="text"]').value.trim();
|
||
if (!questionTitle) {
|
||
alert('请填写所有问题的标题!');
|
||
return false;
|
||
}
|
||
|
||
const questionType = question.querySelector('input[type="radio"]') ? 'radio' :
|
||
question.querySelector('input[type="checkbox"]') ? 'checkbox' : 'text';
|
||
|
||
if (questionType !== 'text') {
|
||
const options = question.querySelectorAll('.option-item input[type="text"]');
|
||
for (let option of options) {
|
||
if (!option.value.trim()) {
|
||
alert('请填写所有选项的内容!');
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
// 初始化页面
|
||
window.onload = function() {
|
||
// 为题型按钮添加点击事件
|
||
const buttons = document.querySelectorAll('.quetype button');
|
||
buttons[0].onclick = addRadioQuestion;
|
||
buttons[1].onclick = addCheckboxQuestion;
|
||
buttons[2].onclick = addTextQuestion;
|
||
|
||
// 加载问卷数据
|
||
loadQuestionnaireData();
|
||
}
|
||
</script>
|
||
</body>
|
||
</html> |