本章主要内容是完善index.js逻辑功能。
1,修改index.html,直接copy
html和css文件直接从源码中拷贝:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>问卷设计工具</title>
<link rel="stylesheet" href="./index.css" />
</head>
<body class="wrapper">
<div class="row">
<div class="form">
<div class="row">
问卷ID:<br />
<input id="qid" type="text" value="1" />
</div>
<div class="row">
问卷名称:<br />
<input id="qname" type="text" value="测试问卷" />
</div>
<div class="row">
问卷题目:<br />
<textarea name="" id="text" cols="60" rows="20">
1. 题目1
选项1
选项2
选项3
2.题目2[多选题]
选项4
选项5
选项6
3.单行文本题
</textarea>
</div>
<div class="row">
<button id="btn">生成问卷</button>
</div>
<div class="row">
JSON结果:<br />
<pre class="json-preview" id="json-preview"></pre>
</div>
<div class="row">
<button id="copy">拷贝JSON内容</button>
</div>
</div>
<div class="result">
<div class="row">
问卷预览:<br />
<div class="html-preview" id="html-preview"></div>
</div>
</div>
</div>
<div class="footer">
「Powered by
<a href="https://webify.cloudbase.net/">CloudBase Webify</a>」
</div>
<script type="module" src="./index.js"></script>
</body>
</html>
css
.form {
float: left;
min-height: 300px;
padding: 20px;
}
.row {
clear: both;
margin: 5px 0;
}
.row::after {
content: "";
display: table;
clear: both;
}
.result {
float: left;
margin-left: 20px;
}
.question-wrap {
padding: 20px;
}
.question-wrap:hover {
background-color: #f5f5f5;
}
.label {
display: block;
margin: 5px;
}
.html-preview {
width: 500px;
box-sizing: border-box;
padding: 20px;
border: solid 1px #ccc;
}
.json-preview {
width: 500px;
height: 100px;
border: solid 1px #ccc;
overflow: scroll;
}
html结构说明:
从上到下:问卷id(输入框),问卷名称(输入框),问卷题目(文本框 存放对象数据),生成问卷(button按钮),JSON结果(文本框),拷贝JSON内容(button按钮)。
其中,用户点击 生成问卷(button按钮),右边生成一个问卷游览;并且把这套问卷的json题目展示到JSON结果文本框中,用户点击 拷贝JSON内容(button按钮),可以将JSON结果文本框中的内容拷贝到剪切板,方便粘贴到其他使用。
2,运行index后,界面如下图
从text富文本中拿到内容并把用户输入的内容打印输出
document.getElementById("btn").addEventListener("click", function () {
// 用户输入的字符串
let text = document.getElementById("text").value;
console.log(text);
})
对打印输出的富文本内容进行修改
4,按空行分割题目,生成数组并打印输出:
利用正则表达式,使用string.split方法,里面传一个正则表达式,将字符串进行空行分割。
没有文字内容,只有空内容。
//正则表达式 除了空白和换行,其他什么都没有,就是一个空行
const regexQuestionSplit = /\n\s*\n/gm;
document.getElementById("btn").addEventListener("click", function () {
// 用户输入的字符串
let text = document.getElementById("text").value;
console.log(text);
// 按空行分割题目
let questionArr = text.split(regexQuestionSplit);
console.log(questionArr);
})
开始对每个题目进行处理,分割每一行
let questions = [];
// 开始对每个题目进行处理
questionArr.forEach((q) => {
// 分割每一行
let rows = q.split(regexQuestionRowSplit);
//console.log(JSON.stringify(rows));
// 去掉空行
rows = rows.filter((item) => item.trim() !== "");
// console.log(JSON.stringify(rows));
// 全部去掉前后空格
rows = rows.reduce((acc, cur) => {
return [...acc, cur.trim()];
}, []);
console.log(JSON.stringify(rows));
})
5,对填空题,单选题和多选题分别利用正则表达式来处理:
import { prettyPrintJson } from "pretty-print-json";
import copy from "copy-to-clipboard";
import gotpl from "gotpl";
const regexQuestionSplit = /\n\s*\n/gm;
const regexQuestionRowSplit = /\n/gm;
const regexTitle1 = /(?<index>\d+)[.、][\s]*(?<title>[^\n]*)$/;
const retexTitle2 =
/(?<index>\d+)[.、][\s]*(?<title>[^\[【]*)[\[【](?<type>\W+)[\]】]$/;
let resultObj = {
id: 0,
name: "",
questions: [],
};
let resultJson = "";
const tpl = `
<div class="question">
<div class="row">
问卷ID:<%= id %>
</div>
<div class="row">
问卷名称:<%= name %>
</div>
<% for(var i=0, l=questions.length; i<l; ++i){ %>
<% var item = questions[i]; %>
<div class="question-wrap">
<div class="question-title"><%= item.id %>. <%= item.title %>【<%=item.question_type_text %>】</div>
<% if(item.question_type === 'input'){ %>
<div class="input">
<input type="text" name="<%= item.id %>" />
</div>
<% }else if(item.question_type === 'radio'){ %>
<div class="radio">
<% for(var j=0, k=item.options.length; j<k; ++j){ %>
<label class="label">
<input type="radio" name="<%= item.id %>" value="<%= item.options[j].option_id %>" />
<%= item.options[j].option_id %>.
<%= item.options[j].option_value %>
</label>
<% } %>
</div>
<% }else if(item.question_type === 'checkbox'){ %>
<div class="checkbox">
<% for(var j=0, k=item.options.length; j<k; ++j){ %>
<label class="label">
<input type="checkbox" name="<%= item.id %>" value="<%= item.options[j].option_id %>" />
<%= item.options[j].option_id %>.
<%= item.options[j].option_value %>
</label>
<% } %>
</div>
<% } %>
</div>
<% } %>
</div>
`;
const alphabet = [
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
];
const type_map = {
填空题: "input",
单选题: "radio",
多选题: "checkbox",
};
function getQuestionType(questionType) {
return type_map[questionType] || "类型错误";
}
function formatQuestion(index, title, typeText, options = null) {
// console.log(index, title, questionType);
const questionType = getQuestionType(typeText);
let question = {
id: +index,
title: title,
question_type: questionType,
question_type_text: typeText,
};
// console.log(options);
if (options && options.length) {
let tmpOptions = [];
options.forEach((item, index) => {
tmpOptions.push({
option_id: alphabet[index],
option_value: item,
});
});
question.options = tmpOptions;
}
return question;
}
document.getElementById("btn").addEventListener("click", function () {
resultObj.id = +document.getElementById("qid").value.trim();
resultObj.name = document.getElementById("qname").value.trim();
// 用户输入的字符串
let text = document.getElementById("text").value;
// console.log(text);
// 按空行分割题目
let questionArr = text.split(regexQuestionSplit);
// console.log(questionArr);
let questions = [];
// 开始对每个题目进行处理
questionArr.forEach((q) => {
// 分割每一行
let rows = q.split(regexQuestionRowSplit);
// console.log(JSON.stringify(rows));
// 去掉空行
rows = rows.filter((item) => item.trim() !== "");
// console.log(JSON.stringify(rows));
// 全部去掉前后空格
rows = rows.reduce((acc, cur) => {
return [...acc, cur.trim()];
}, []);
// console.log(JSON.stringify(rows));
// 如果是单行,是填空题
if (rows.length === 1) {
if (regexTitle1.test(rows[0])) {
let matches = rows[0].match(regexTitle1);
// console.log(matches);
let { index, title } = matches.groups;
questions.push(formatQuestion(index, title, "填空题"));
}
}
// console.log(questions);
// 多行,可能是单选或多选
if (rows.length > 1) {
// 第一行是标题,其他行是选项
let [titleRow, ...options] = rows;
// console.log("titleRow", titleRow);
// console.log("options", options);
// 先验证带题目类型的格式
if (retexTitle2.test(titleRow)) {
let matches = titleRow.match(retexTitle2);
// console.log(matches)
let { index, title, type } = matches.groups;
questions.push(formatQuestion(index, title, type, options));
} else if (regexTitle1.test(titleRow)) {
// 没有设置类型的,当成单选题
let matches = titleRow.match(regexTitle1);
let { index, title } = matches.groups;
console.log(index, title, options);
questions.push(formatQuestion(index, title, "单选题", options));
}
// console.log(questions);
}
});
resultObj.questions = questions;
resultJson = JSON.stringify(resultObj);
console.log(resultObj);
document.getElementById("json-preview").innerHTML =
prettyPrintJson.toHtml(resultObj);
document.getElementById("html-preview").innerHTML = gotpl.render(
tpl,
resultObj
);
});
document.getElementById("copy").onclick = () => {
copy(resultJson);
alert("已复制到剪贴板");
};
6,输出最终结果:
输出的json数据如下:
[
{
"id": 1,
"title": "题目1",
"question_type": "radio",
"question_type_text": "单选题",
"options": [
{
"option_id": "A",
"option_value": "选项1"
},
{
"option_id": "B",
"option_value": "选项2"
},
{
"option_id": "C",
"option_value": "选项3"
}
]
},
{
"id": 2,
"title": "题目2",
"question_type": "checkbox",
"question_type_text": "多选题",
"options": [
{
"option_id": "A",
"option_value": "选项4"
},
{
"option_id": "B",
"option_value": "选项5"
},
{
"option_id": "C",
"option_value": "选项6"
}
]
},
{
"id": 3,
"title": "单行文本题",
"question_type": "input",
"question_type_text": "填空题"
},
{
"id": 4,
"title": "题目2",
"question_type": "checkbox",
"question_type_text": "多选题",
"options": [
{
"option_id": "A",
"option_value": "选项4"
},
{
"option_id": "B",
"option_value": "选项5"
},
{
"option_id": "C",
"option_value": "选项6"
}
]
}
]
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/135672.html