This commit is contained in:
钱冠学
2024-09-26 17:10:12 +08:00
parent 1c8938ef2a
commit 6ce5e6f2dc
2 changed files with 3 additions and 425 deletions

View File

@@ -1,2 +1,5 @@
/src/views/Creative/3d
/src/font
/src/plugins/tinymce-placeholder.js
/src/plugins/tinymce-quickbars.js
/public

View File

@@ -1,425 +0,0 @@
import AnswerApi from "../../api";
import { computed, getCurrentInstance, defineComponent, inject, ref } from "vue";
import { message } from "ant-design-vue";
import PfePagination from "@/components/PfePagination.vue";
import Question from "../../questions/Question.vue";
import QRadio from '@/views/Answer/questions/QRadio'
import QCheckbox from "../../questions/QCheckbox.vue";
import QCascader from "../../questions/QCascader.vue";
import QInput from "../../questions/QInput.vue";
import QRate from "../../questions/QRate.vue";
import QImgText from "../../questions/QImgText.vue";
import QDate from "../../questions/QDate.vue";
import MatrixInput from "../../questions/QMatrix/MatrixInput.vue";
import MatrixRadio from "../../questions/QMatrix/MatrixRadio.vue";
import MatrixCheck from "../../questions/QMatrix/MatrixCheck.vue";
import MatrixRate from "../../questions/QMatrix/MatrixRate.vue";
import QImgShow from "../../questions/QImgShow.vue";
import QImgRadio from "../../questions/QImgRadio.vue";
import QImgCheck from "../../questions/QImgCheck.vue";
import QClass from "../../questions/QClass.vue";
import QSort from "../../questions/QSort.vue";
import QSum from "../../questions/QSum.vue";
import QUpload from "../../questions/QUpload.vue";
import QMap from "../../questions/QMap.vue";
import QPhone from "../../questions/QPhone.vue";
import QPassword from "../../questions/QPassword.vue";
import QSign from "../../questions/QSign.vue";
import QConsent from "../../questions/QConsent.vue";
import QPSM from "../../questions/high/QPSM.vue";
import QKANO from "../../questions/high/QKANO.vue";
import QBPTO from "../../questions/high/QBPTO.vue";
import QMXD from "../../questions/high/QMXD.vue";
export default defineComponent({
components: {
PfePagination,
Question,
QFirst,
QLast,
QRadio,
QCheckbox,
QInput,
QCascader,
QRate,
QImgText,
QDate,
MatrixInput,
MatrixRadio,
MatrixCheck,
MatrixRate,
QImgShow,
QImgRadio,
QImgCheck,
QClass,
QSort,
QSum,
QUpload,
QMap,
QPhone,
QPassword,
QSign,
QConsent,
QPSM,
QKANO,
QBPTO,
QMXD,
},
props: {
// 是否答题模式
isAnswer: {
type: Boolean,
default: false,
},
},
setup(props) {
const page = ref(0); // 当前页数
const questionsData = inject("questionsData"); // 问卷数据
const { proxy } = getCurrentInstance();
const loading = ref(false);
// 主题样式
const styleInfo = computed(() => questionsData.value.survey?.style || {});
// 分页
const pages = computed(() => questionsData.value.answer?.pages || []);
// 当前页问卷
const questions = computed(() => {
const currentPages = pages.value[page.value - 1] || [];
return (questionsData.value.questions || []).filter((quetion) =>
currentPages.find((index) => quetion.question_index === index)
);
});
// 是否显示分页器
const showPage = computed(() => {
let show = true;
if (questions.value[0]?.question_type === 104 || questions.value[0]?.question_type === 105) {
show = false;
}
return show;
});
// 答题
async function answer(callback) {
if ((questions.value.length && props.isAnswer) || !questionsData.value.questions.length) {
// 表单验证(当前页)
const errors = questions.value.filter((question) => {
const { config, answer, question_type: questionType } = question;
let isError = false;
if (config.is_required && !answer) {
isError = true;
if (questionType === 10) {
// 矩阵多选题
question.error = `每行最少选${config.min_select}`;
} else if (questionType === 15) {
// 分类题
question.error = "部分选项未归类";
} else if (!question.error) {
question.error = "这是一道必答题";
}
} else if (
answer &&
questionType === 1 &&
Object.keys(answer).findIndex((value) => !answer[value]) !== -1
) {
// 单选题
isError = true;
question.error = `请输入`;
} else if (answer && questionType === 2) {
// 多选题
if (Object.keys(answer).length < config.min_select) {
let options = [];
question.list.forEach((list) => {
options = [...options, ...list.options];
});
const index = options.findIndex(
(option) => option.option_key === Object.keys(answer)[0] && option.is_remove_other
);
if (index === -1) {
isError = true;
question.error = `最少选择${config.min_select}`;
} else {
question.error = "";
}
} else if (Object.keys(answer).findIndex((value) => !answer[value]) !== -1) {
isError = true;
question.error = `请输入`;
} else {
question.error = "";
}
} else if (
answer &&
questionType === 14 &&
Object.keys(answer).length < config.min_select
) {
// 图片多选题
isError = true;
question.error = `最少选择${config.min_select}`;
} else if (answer && questionType === 17) {
// 恒定总和题
let sum = 0;
Object.keys(answer).forEach((key) => {
sum += answer[key] * 1;
});
if (sum === config.total) {
question.error = "";
} else {
isError = true;
question.error = `请让总和等于${config.total}`;
}
} else if (answer && questionType === 18 && answer.length < config.min_number) {
// 文件上传题
isError = true;
question.error = `最少上传${config.min_number}个文件`;
} else if (answer && questionType === 4) {
question.error = "";
// 填空题
const { value } = answer;
switch (config.text_type) {
case 3: // 字母
isError = !/^[a-zA-Z]+$/.test(value);
question.error = isError ? "请输入字母" : "";
break;
case 4: // 中文
isError =
!/^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])+$/.test(
value
);
question.error = isError ? "请输入中文" : "";
break;
case 5: // 邮箱
isError = !/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
value
);
question.error = isError ? "请输入正确的email" : "";
break;
case 6: // 手机号
isError = !/^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(value);
question.error = isError ? "请输入正确的手机号" : "";
break;
case 7: // 身份证号
isError =
!/^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/.test(
value
);
question.error = isError ? "请输入正确的身份证号" : "";
break;
default:
break;
}
if (!isError && value.length < config.min) {
isError = true;
question.error = `请至少输入${config.min}个字`;
}
} else if (answer && questionType === 8) {
// 矩阵填空题
question.error = "";
Object.keys(answer).forEach((key) => {
const value = answer[key];
switch (config.text_type) {
case 3: // 字母
if (!/^[a-zA-Z]+$/.test(value)) question.error = "请输入字母";
break;
case 4: // 中文
if (
!/^(?:[\u3400-\u4DB5\u4E00-\u9FEA\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872\uD874-\uD879][\uDC00-\uDFFF]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0])+$/.test(
value
)
)
question.error = "请输入中文";
break;
case 5: // 邮箱
if (!/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(value))
question.error = "请输入正确的email";
break;
case 6: // 手机号
if (!/^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(value))
question.error = "请输入正确的手机号";
break;
case 7: // 身份证号
if (
!/^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|10|11|12)(?:0[1-9]|[1-2]\d|30|31)\d{3}[\dXx]$/.test(
value
)
)
question.error = "请输入正确的身份证号";
break;
default:
break;
}
if (!question.error && value.length < config.min) {
question.error = `请至少输入${config.min}个字`;
}
});
if (question.error) isError = true;
} else {
question.error = "";
}
return isError;
});
if (!errors.length) {
// 表单验证通过,开始答题
const questionsAnswer = questions.value.map((question) => ({
question_index: question.question_index,
answer: question.answer || {},
}));
loading.value = true;
try {
const { data } = await AnswerApi.answer({
id: proxy.$route.query.sn,
data: {
answer: JSON.stringify(questionsAnswer),
},
});
// 更新答案
updateAnswer(data.answer_info_autofill);
// 更新分页数组
questionsData.value.answer.pages = data.pages;
// 更新问卷状态
if (data.action.code === 20014) {
const timer = setTimeout(() => {
let url = data.action.msg;
if (url.indexOf("http://") === -1 && url.indexOf("https://") === -1) {
url = `http://${url}`;
}
open(url);
clearTimeout(timer);
});
}
questionsData.value.action = data.action;
callback();
} catch (error) {
console.log(error);
}
loading.value = false;
} else {
const { question_index, error } = errors[0];
const index = questions.value.findIndex(
(question) => question.question_index === question_index
);
message.error(`${index + 1}题:${error}`);
}
} else {
callback();
}
}
// 上一页
function previous() {
page.value -= 1;
}
// 下一页
async function next() {
answer(() => {
page.value += 1;
});
}
// 关联引用
function onRelation(
{ options, value, list },
{ question_type, question_index, related, answer }
) {
// 关联
related.forEach((relationItem) => {
let relationOptions = [];
if (question_type === 9 || question_type === 10) {
// 矩阵选择
list.forEach((item) => {
if (item.type === relationItem.cite_type) {
relationOptions = [...relationOptions, ...item.options];
}
if (relationItem.relation_type === 1) {
relationOptions = relationOptions.filter((option) =>
question_type === 9 ? option.value : option.value?.length
);
} else if (relationItem.relation_type === 2) {
relationOptions = relationOptions.filter((option) =>
question_type === 9 ? !option.value : !option.value?.length
);
}
});
} else if (question_type === 11) {
// 矩阵打分
list.forEach((item) => {
if (item.type === relationItem.cite_type) {
relationOptions = [...relationOptions, ...item.options];
}
});
} else if (relationItem.relation_type === 0) {
// 全部选项
relationOptions = options;
} else {
// 过滤选中/未选中选项
relationOptions = options.filter((option) => {
if (question_type === 1) {
// 单选
if (relationItem.relation_type === 1) return value === option.option_key;
return value !== option.option_key;
} else if (question_type === 2) {
// 多选
if (relationItem.relation_type === 1) return value.includes(option.option_key);
return !value.includes(option.option_key);
}
return true;
});
}
// 找到关联题
const question = questionsData.value.questions.find(
(question) => question.question_index === relationItem.relation_question_index
);
// 深拷贝关联选项
const copyRelationOptions = JSON.parse(JSON.stringify(relationOptions));
// 更新关联选项key
copyRelationOptions.forEach((option) => {
if (option.option_key[0] !== "Q") {
let letter = "A";
// 矩阵题行、列
if (question_type >= 9 && question_type <= 11) {
letter = relationItem.cite_type === 1 ? "R" : "C";
}
option.option_key = `Q${question_index}${letter}${option.option_key}`;
}
// 其他项特殊处理
if (option.is_other) {
// option.is_other = 0
option.oldOption = option.option;
option.option = option.value || option.option;
}
delete option.value;
});
// 更新关联题列表
if (answer) {
question.list[0].options = copyRelationOptions;
} else {
question.list[0].options = [];
}
});
}
function updateAnswer(auto) {
if (auto) {
auto.forEach((autoItem) => {
const question = questionsData.value.questions.find(
(question) => question.question_index === autoItem.question_index
);
question.answer = JSON.parse(autoItem.answer);
});
}
}
return {
page,
pages,
loading,
showPage,
styleInfo,
questions,
questionsData,
answer,
previous,
next,
onRelation,
};
},
});