fix:投放
This commit is contained in:
424
src/assets/js/logic.js
Normal file
424
src/assets/js/logic.js
Normal file
@@ -0,0 +1,424 @@
|
|||||||
|
/**
|
||||||
|
* 问卷设计中涉及到的一些 【逻辑】 中公共方法
|
||||||
|
*/
|
||||||
|
import config from '@/config';
|
||||||
|
import { Modal } from 'ant-design-vue';
|
||||||
|
import { advancedQuesTypeList } from './quesInfoList';
|
||||||
|
|
||||||
|
const advancedTypes = advancedQuesTypeList.map((i) => i.type); // 高级题型的 question_type
|
||||||
|
|
||||||
|
const performance = {
|
||||||
|
start(label) {
|
||||||
|
if (config.currentMode === 'dev') {
|
||||||
|
console.time(`${label} Performance`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
end(label) {
|
||||||
|
if (config.currentMode === 'dev') {
|
||||||
|
console.timeEnd(`${label} Performance`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
log(...rest) {
|
||||||
|
if (config.currentMode === 'dev') {
|
||||||
|
console.log(...rest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function isNullish(value) {
|
||||||
|
return value === undefined || value === null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改(添加、移动、删除)问卷 题目、分页,编辑(添加、删除)逻辑 时,判断循环逻辑是否满足
|
||||||
|
* 的异步方法,感觉题多了这个方法执行会很慢。。。
|
||||||
|
* @param rest
|
||||||
|
* @return {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
export async function loopingAvailableAsync(...rest) {
|
||||||
|
return Promise.resolve(loopingAvailable(...rest));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改(添加、移动、删除)问卷 题目、分页,编辑(添加、删除)逻辑 时,判断循环逻辑是否满足
|
||||||
|
* @param cycles 循环逻辑列表
|
||||||
|
* @param questions 被操作后的问题列表
|
||||||
|
* @param logics 逻辑列表
|
||||||
|
* @param isPerPage 是否是每页一道题
|
||||||
|
* @param reason 提示信息
|
||||||
|
* @return {boolean} 是否满足循环逻辑
|
||||||
|
*/
|
||||||
|
export function loopingAvailable({ cycles, questions, logics, isPerPage, reason } = {}) {
|
||||||
|
const performanceName = 'CheckLoopingAvailable';
|
||||||
|
performance.start(performanceName);
|
||||||
|
|
||||||
|
let result = true;
|
||||||
|
let prompt = reason || '';
|
||||||
|
|
||||||
|
if (!cycles.length) {
|
||||||
|
// 没有配置循环逻辑
|
||||||
|
performance.end(performanceName);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const quizList = generateQuestionPages({ questions, logics, isPerPage });
|
||||||
|
const cycleList = generateCyclePages(cycles, quizList);
|
||||||
|
const logicList = generateLogicPages(logics, quizList);
|
||||||
|
|
||||||
|
const lastPage = quizList.reduce((prev, curr) => Math.max(prev, curr.$page || 0), 0); // 最后一页的页码
|
||||||
|
|
||||||
|
// console.log('questions', questions, quizList);
|
||||||
|
// console.log('cycles', cycles, cycleList);
|
||||||
|
// console.log('logics', logics, logicList);
|
||||||
|
// console.log('last page', lastPage);
|
||||||
|
|
||||||
|
for (let i = 0; i < cycleList.length; i += 1) {
|
||||||
|
const { index, page, startPage, endPage } = cycleList[i] || {};
|
||||||
|
|
||||||
|
// 循环关联问题被删除时,才会出现这种情况
|
||||||
|
if (!quizList.find((j) => j.question_index === index)) {
|
||||||
|
result = false;
|
||||||
|
prompt = '问题被循环关联,不能删除';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((startPage && startPage <= page) || (endPage && endPage <= page)) {
|
||||||
|
result = false;
|
||||||
|
prompt = '问题被循环关联,不能位于循环题组后';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 循环关联问题位于自己或其它循环的循环题组分页中间
|
||||||
|
if (page && cycleList.some((j) => j.startPage < page && page < j.endPage)) {
|
||||||
|
result = false;
|
||||||
|
prompt = '问题被循环关联,不能位于循环题组中';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 循环的循环题组,修改问题或分页的时候应该不会出现这种情况
|
||||||
|
if (startPage && endPage && startPage > endPage) {
|
||||||
|
result = false;
|
||||||
|
prompt = '循环题组的起始分页应该小于结束分页';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除分页,或者删除自带分页的题,导致分页变化,校验分页是否包含了所有的循环题组分页
|
||||||
|
if (endPage > lastPage) {
|
||||||
|
result = false;
|
||||||
|
prompt = '请勿在循环题组中编辑分页,请调整循环题组后再试';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 循环题组分页和跳转逻辑有冲突
|
||||||
|
if (
|
||||||
|
logicList.some((j) => {
|
||||||
|
// 跳转到这几个的时候,循环不校验,只校验带题的
|
||||||
|
// 正常完成、提前终止、配额超限
|
||||||
|
if ([-1, -2, -3].includes(Math.min(...j))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isCross(j, [startPage, endPage]);
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
result = false;
|
||||||
|
prompt = '循环题组分页区间与跳转逻辑冲突,请修改后再试';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result && (reason || prompt)) {
|
||||||
|
Modal.warning({
|
||||||
|
class: 'custom-modal custom-modal-title-notice hide-ant-icon',
|
||||||
|
title: '无法操作',
|
||||||
|
width: '450px',
|
||||||
|
content: reason || prompt
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
performance.end(performanceName);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给问题列表中的问题添加,问题所在的页码字段($page)
|
||||||
|
* 说明:
|
||||||
|
* 1. 需要过滤掉没有题的空白页
|
||||||
|
* 2. 高级题型的题前后需要加分页
|
||||||
|
* 3. 添加了逻辑的基础题型前后需要加分页
|
||||||
|
* @param questions
|
||||||
|
* @param logics
|
||||||
|
* @param isPerPage
|
||||||
|
* @param addon 自定义额外操作,是一个方法
|
||||||
|
* @return {array} 题目列表,包括题和分页
|
||||||
|
*/
|
||||||
|
export function generateQuestionPages({ questions, logics, isPerPage, addon }) {
|
||||||
|
if (!questions?.length) {
|
||||||
|
return questions || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
let page = 1;
|
||||||
|
let pageObjectCount = 0; // 计数,在 questions 有几个分页的对象
|
||||||
|
return questions.map((item, index, arr) => {
|
||||||
|
const asBlock = [...advancedTypes, 23]; // 需要自动加分页的题型:高级题型及知情同意书
|
||||||
|
const isPrevAdv = asBlock.includes(arr[index - 1]?.question_type); // 前一道题是高级题型
|
||||||
|
const isAdv = asBlock.includes(item?.question_type); // 当前题是高级题型
|
||||||
|
// const isPrevAdv = advancedTypes.includes(arr[index - 1]?.question_type); // 前一道题是高级题型
|
||||||
|
// const isAdv = advancedTypes.includes(item?.question_type); // 当前题是高级题型
|
||||||
|
|
||||||
|
// 前一道题配置了跳转逻辑
|
||||||
|
const isPrevLogic = !!logics.find((logic) => logic.question_index === arr[index - 1]?.question_index);
|
||||||
|
// 当前题配置了跳转逻辑
|
||||||
|
const isLogic = !!logics.find((logic) => logic.question_index === item.question_index);
|
||||||
|
|
||||||
|
const isSurroundedByPage = isAdv || isLogic; // 需要在该题前后添加分页
|
||||||
|
|
||||||
|
const isPrevPage = !!arr[index - 1]?.page; // 前一道题是一个分页对象
|
||||||
|
const prevIsQuestion = !arr[index - 1]?.page; // 前一道题是一道题而不是一个分页对象
|
||||||
|
|
||||||
|
if (!index) {
|
||||||
|
page = 1;
|
||||||
|
pageObjectCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.page) {
|
||||||
|
pageObjectCount += 1;
|
||||||
|
if (index && prevIsQuestion && !isPrevLogic && !isPrevAdv) {
|
||||||
|
// 过滤掉没有题的空白页
|
||||||
|
page += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (index && !isPrevPage && !isPrevAdv && !isPrevLogic && isSurroundedByPage) {
|
||||||
|
page += 1;
|
||||||
|
}
|
||||||
|
item.$page = isPerPage ? index + 1 - pageObjectCount : page;
|
||||||
|
if (isSurroundedByPage) {
|
||||||
|
page += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addon) {
|
||||||
|
addon(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化循环列表,便于后续使用
|
||||||
|
* @param cycles
|
||||||
|
* @param questions
|
||||||
|
* @return {array} 格式化后的循环列表
|
||||||
|
*/
|
||||||
|
export function generateCyclePages(cycles, questions) {
|
||||||
|
if (!cycles?.length) {
|
||||||
|
return cycles || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return cycles.map((cycle) => ({
|
||||||
|
index: cycle.question_index,
|
||||||
|
page: getPageByQuestionIndex(cycle.question_index, questions),
|
||||||
|
startPage: cycle.first_page,
|
||||||
|
endPage: cycle.last_page
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 逻辑关联的页码,便于后续使用
|
||||||
|
* @param logics {*[]}
|
||||||
|
* @param questions {*[]}
|
||||||
|
* @param fillRangeItem {boolean} 用数字填充满 range[index] 数组
|
||||||
|
* @return {number[][]} 逻辑关联的页码
|
||||||
|
*/
|
||||||
|
export function generateLogicPages(logics, questions, fillRangeItem) {
|
||||||
|
if (!logics?.length) {
|
||||||
|
return logics || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const pages = [];
|
||||||
|
|
||||||
|
logics.forEach((logic) => {
|
||||||
|
if (![0, 2].includes(logic.skip_type)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let page = [
|
||||||
|
getPageByQuestionIndex(logic.logic?.[0]?.question_index, questions),
|
||||||
|
getPageByQuestionIndex(logic.question_index, questions),
|
||||||
|
getPageByQuestionIndex(logic.skip_question_index, questions) || logic.skip_question_index
|
||||||
|
];
|
||||||
|
page = page.filter((i) => !!i);
|
||||||
|
|
||||||
|
if (fillRangeItem) {
|
||||||
|
const min = Math.min(...page.filter((i) => i > 0));
|
||||||
|
const max = Math.max(...page);
|
||||||
|
page = generateRange(min, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
pages.push(page);
|
||||||
|
});
|
||||||
|
|
||||||
|
return pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过问题的 question_index 找到问题在第几页
|
||||||
|
* @param questionIndex
|
||||||
|
* @param questions
|
||||||
|
* @return {number|*|undefined}
|
||||||
|
*/
|
||||||
|
export function getPageByQuestionIndex(questionIndex, questions) {
|
||||||
|
return questions.find((i) => i.question_index === questionIndex)?.$page || undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成一个从 start 开始到 end 结束的数组
|
||||||
|
* @param start {number}
|
||||||
|
* @param end {number}
|
||||||
|
* @return {number[]}
|
||||||
|
*/
|
||||||
|
export function generateRange(start, end) {
|
||||||
|
if (isNullish(start) || isNullish(end)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNaN(Number(start)) || isNaN(Number(end))) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
let i = start;
|
||||||
|
let range = [];
|
||||||
|
while (i <= end) {
|
||||||
|
range.push(i);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断逻辑与循环分组,是否不合理
|
||||||
|
* @param range1 {array} 跳转逻辑的分页数组
|
||||||
|
* @param range2 {array} 循环分组的分页数组
|
||||||
|
* @return {boolean} true 不合理, false 合理
|
||||||
|
*/
|
||||||
|
export function isCross(range1, range2) {
|
||||||
|
if (!range1 || !range2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsedRange1 = range1.slice(1);
|
||||||
|
const judge = range1[0];
|
||||||
|
|
||||||
|
const start1 = Math.min(...parsedRange1);
|
||||||
|
const end1 = Math.max(...parsedRange1);
|
||||||
|
const start2 = range2[0];
|
||||||
|
const end2 = range2[1];
|
||||||
|
|
||||||
|
const isPlainSequence = parsedRange1[0] === start1; // 跳转逻辑的方向,true 为从前向后跳转
|
||||||
|
|
||||||
|
if (isNullish(start1) || isNullish(end1) || end1 < 0 || (isNullish(start2) && isNullish(end2))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [judge, start1, end1]; // isPlainSequence
|
||||||
|
// [start1, judge, end1]; // isPlainSequence || !isPlainSequence
|
||||||
|
//
|
||||||
|
// [start2, end2];
|
||||||
|
|
||||||
|
// 逻辑在循环之前
|
||||||
|
const isLeft = isNullish(start2) ? end1 < end2 : end1 < start2;
|
||||||
|
// 逻辑在循环之后
|
||||||
|
const isRight = isNullish(end2) ? start2 < start1 && start2 < judge : end2 < start1 && end2 < judge;
|
||||||
|
// 不相交也不包含
|
||||||
|
const isSibling = isLeft || isRight;
|
||||||
|
|
||||||
|
// 逻辑包含循环
|
||||||
|
const contain = (isPlainSequence
|
||||||
|
&& (((isNullish(start2) || isSequence(judge, start2, start1))
|
||||||
|
&& (isNullish(end2) || isSequence(judge, end2, start1)))
|
||||||
|
|| ((isNullish(start2) || isSequence(start1, start2, end1))
|
||||||
|
&& (isNullish(end2) || isSequence(start1, end2, end1)))))
|
||||||
|
|| (!isPlainSequence
|
||||||
|
&& (judge < start1
|
||||||
|
? ((isNullish(start2) || isSequence(judge, start2, start1))
|
||||||
|
&& (isNullish(end2) || isSequence(judge, end2, start1)))
|
||||||
|
|| ((isNullish(start2) || isSequence(start1, start2, end1))
|
||||||
|
&& (isNullish(end2) || isSequence(start1, end2, end1)))
|
||||||
|
: ((isNullish(start2) || isSequence(start1, start2, judge))
|
||||||
|
&& (isNullish(end2) || isSequence(start1, end2, judge)))
|
||||||
|
|| ((isNullish(start2) || isSequence(judge, start2, end1))
|
||||||
|
&& (isNullish(end2) || isSequence(judge, end2, end1)))));
|
||||||
|
// 循环存在封闭区间,并且循环包含逻辑
|
||||||
|
const contained = !isNullish(start2)
|
||||||
|
&& !isNullish(end2)
|
||||||
|
// [judge, start1, end1];
|
||||||
|
&& ((isPlainSequence && start2 <= judge && end1 <= end2)
|
||||||
|
// [judge, start1, end1];
|
||||||
|
// [start1, judge, end1];
|
||||||
|
|| (!isPlainSequence && start2 <= start1 && start2 <= judge && end1 <= end2));
|
||||||
|
// 循环不存在封闭区间
|
||||||
|
const unCircled = (!isNullish(start2)
|
||||||
|
&& isNullish(end2)
|
||||||
|
&& ((isPlainSequence && start2 === judge) || (!isPlainSequence && judge < start1)
|
||||||
|
? start2 === judge
|
||||||
|
: start2 === start1))
|
||||||
|
|| (isNullish(start2) && !isNullish(end2) && end2 === end1);
|
||||||
|
|
||||||
|
return !(isSibling || contain || contained || unCircled);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSequence(s1, s2, s3, equal) {
|
||||||
|
return equal ? s1 <= s2 && s2 <= s3 : s1 < s2 && s2 < s3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用保存问题接口前,检查是否有问题受到循环影响需要重新保存,如果有则重新保存一下这道题,没有则不需要特殊处理
|
||||||
|
* bugfix for : 有循环的问卷发布后,再次编辑问卷,将循环题组内的问题移除循环题组,
|
||||||
|
* 再次发布,后端不处理被移除的问题 title,导致该题的 title 仍保持上次发布时的值
|
||||||
|
* 错误格式一般为:B3.1 正确格式一般为:B3
|
||||||
|
* 导致作答出现错误,例如:引用找不到题
|
||||||
|
* 从 store 里查出修改前和修改后的问题、分页、循环;比较修改前后问题是否被移除了某个循环题组;修改 quesSaveParam.newQuestion;
|
||||||
|
* @param quesSaveParam 将要保存的数据,会被此方法修改的字段:quesSaveParam.newQuestion
|
||||||
|
* @param store
|
||||||
|
*/
|
||||||
|
export function updateNewQuestionsByLoopingEffect(quesSaveParam, store) {
|
||||||
|
const { questionInfoBeforeModified = {}, questionInfo = {} } = JSON.parse(JSON.stringify(store.state.common)) || {};
|
||||||
|
|
||||||
|
const oldPages = questionInfoBeforeModified.survey.pages;
|
||||||
|
const newQuestions = questionInfo.questions;
|
||||||
|
const newPages = questionInfo.survey.is_one_page_one_question
|
||||||
|
? questionInfo.questions.filter((i) => i.question_index).map((i, idx) => [i.question_index])
|
||||||
|
: questionInfo.survey.pages;
|
||||||
|
const cycles = questionInfo.cycle_pages || [];
|
||||||
|
|
||||||
|
if (!cycles.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const moveOutOfCycleQuestionIndex = [];
|
||||||
|
const cyclePages = cycles.map((i) => [i.first_page, i.last_page]).filter((i) => i[0] && i[1]);
|
||||||
|
cyclePages.forEach((i) => {
|
||||||
|
const start = i[0] - 1;
|
||||||
|
const end = i[1] - 1;
|
||||||
|
|
||||||
|
for (let j = start; j <= end; j += 1) {
|
||||||
|
if (oldPages[j]?.join(',') !== newPages[j]?.join(',')) {
|
||||||
|
oldPages[j]?.forEach((k) => {
|
||||||
|
if (!newPages?.[j]?.includes(k)) {
|
||||||
|
moveOutOfCycleQuestionIndex.push(k);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const movedOutOfCycleQuestions = newQuestions.filter((i) => moveOutOfCycleQuestionIndex.includes(i.question_index));
|
||||||
|
|
||||||
|
if (movedOutOfCycleQuestions.length) {
|
||||||
|
if (!quesSaveParam.newQuestion) {
|
||||||
|
quesSaveParam.newQuestion = [];
|
||||||
|
}
|
||||||
|
quesSaveParam.newQuestion.push(...movedOutOfCycleQuestions);
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/layouts/config3d.constant.js
Normal file
32
src/layouts/config3d.constant.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// 问题类型
|
||||||
|
export const QUESTION_TYPE = {
|
||||||
|
// 单选
|
||||||
|
CHOICE: 1,
|
||||||
|
|
||||||
|
// 多选
|
||||||
|
CHOICE_MULT: 2,
|
||||||
|
|
||||||
|
// 输入
|
||||||
|
INPUT_MULT: 4,
|
||||||
|
|
||||||
|
// 图文说明
|
||||||
|
IMG_TEXT_EXPLAIN: 6,
|
||||||
|
|
||||||
|
// 热区-开关
|
||||||
|
HOTAREA: 25,
|
||||||
|
|
||||||
|
// 热区-喜欢/不喜欢
|
||||||
|
HOTAREA_2: 26,
|
||||||
|
|
||||||
|
// 矩阵-填空
|
||||||
|
MATRIX_INPUT: 8,
|
||||||
|
|
||||||
|
// 矩阵-单选
|
||||||
|
MATRIX_RADIO: 9,
|
||||||
|
|
||||||
|
contains(item) {
|
||||||
|
return Object.keys(this).some((key) => this[key] == item);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {};
|
||||||
424
src/layouts/logic.js
Normal file
424
src/layouts/logic.js
Normal file
@@ -0,0 +1,424 @@
|
|||||||
|
/**
|
||||||
|
* 问卷设计中涉及到的一些 【逻辑】 中公共方法
|
||||||
|
*/
|
||||||
|
import config from '@/config';
|
||||||
|
import { Modal } from 'ant-design-vue';
|
||||||
|
import { advancedQuesTypeList } from './quesInfoList';
|
||||||
|
|
||||||
|
const advancedTypes = advancedQuesTypeList.map((i) => i.type); // 高级题型的 question_type
|
||||||
|
|
||||||
|
const performance = {
|
||||||
|
start(label) {
|
||||||
|
if (config.currentMode === 'dev') {
|
||||||
|
console.time(`${label} Performance`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
end(label) {
|
||||||
|
if (config.currentMode === 'dev') {
|
||||||
|
console.timeEnd(`${label} Performance`);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
log(...rest) {
|
||||||
|
if (config.currentMode === 'dev') {
|
||||||
|
console.log(...rest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function isNullish(value) {
|
||||||
|
return value === undefined || value === null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改(添加、移动、删除)问卷 题目、分页,编辑(添加、删除)逻辑 时,判断循环逻辑是否满足
|
||||||
|
* 的异步方法,感觉题多了这个方法执行会很慢。。。
|
||||||
|
* @param rest
|
||||||
|
* @return {Promise<boolean>}
|
||||||
|
*/
|
||||||
|
export async function loopingAvailableAsync(...rest) {
|
||||||
|
return Promise.resolve(loopingAvailable(...rest));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改(添加、移动、删除)问卷 题目、分页,编辑(添加、删除)逻辑 时,判断循环逻辑是否满足
|
||||||
|
* @param cycles 循环逻辑列表
|
||||||
|
* @param questions 被操作后的问题列表
|
||||||
|
* @param logics 逻辑列表
|
||||||
|
* @param isPerPage 是否是每页一道题
|
||||||
|
* @param reason 提示信息
|
||||||
|
* @return {boolean} 是否满足循环逻辑
|
||||||
|
*/
|
||||||
|
export function loopingAvailable({ cycles, questions, logics, isPerPage, reason } = {}) {
|
||||||
|
const performanceName = 'CheckLoopingAvailable';
|
||||||
|
performance.start(performanceName);
|
||||||
|
|
||||||
|
let result = true;
|
||||||
|
let prompt = reason || '';
|
||||||
|
|
||||||
|
if (!cycles.length) {
|
||||||
|
// 没有配置循环逻辑
|
||||||
|
performance.end(performanceName);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const quizList = generateQuestionPages({ questions, logics, isPerPage });
|
||||||
|
const cycleList = generateCyclePages(cycles, quizList);
|
||||||
|
const logicList = generateLogicPages(logics, quizList);
|
||||||
|
|
||||||
|
const lastPage = quizList.reduce((prev, curr) => Math.max(prev, curr.$page || 0), 0); // 最后一页的页码
|
||||||
|
|
||||||
|
// console.log('questions', questions, quizList);
|
||||||
|
// console.log('cycles', cycles, cycleList);
|
||||||
|
// console.log('logics', logics, logicList);
|
||||||
|
// console.log('last page', lastPage);
|
||||||
|
|
||||||
|
for (let i = 0; i < cycleList.length; i += 1) {
|
||||||
|
const { index, page, startPage, endPage } = cycleList[i] || {};
|
||||||
|
|
||||||
|
// 循环关联问题被删除时,才会出现这种情况
|
||||||
|
if (!quizList.find((j) => j.question_index === index)) {
|
||||||
|
result = false;
|
||||||
|
prompt = '问题被循环关联,不能删除';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((startPage && startPage <= page) || (endPage && endPage <= page)) {
|
||||||
|
result = false;
|
||||||
|
prompt = '问题被循环关联,不能位于循环题组后';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 循环关联问题位于自己或其它循环的循环题组分页中间
|
||||||
|
if (page && cycleList.some((j) => j.startPage < page && page < j.endPage)) {
|
||||||
|
result = false;
|
||||||
|
prompt = '问题被循环关联,不能位于循环题组中';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 循环的循环题组,修改问题或分页的时候应该不会出现这种情况
|
||||||
|
if (startPage && endPage && startPage > endPage) {
|
||||||
|
result = false;
|
||||||
|
prompt = '循环题组的起始分页应该小于结束分页';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除分页,或者删除自带分页的题,导致分页变化,校验分页是否包含了所有的循环题组分页
|
||||||
|
if (endPage > lastPage) {
|
||||||
|
result = false;
|
||||||
|
prompt = '请勿在循环题组中编辑分页,请调整循环题组后再试';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 循环题组分页和跳转逻辑有冲突
|
||||||
|
if (
|
||||||
|
logicList.some((j) => {
|
||||||
|
// 跳转到这几个的时候,循环不校验,只校验带题的
|
||||||
|
// 正常完成、提前终止、配额超限
|
||||||
|
if ([-1, -2, -3].includes(Math.min(...j))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isCross(j, [startPage, endPage]);
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
result = false;
|
||||||
|
prompt = '循环题组分页区间与跳转逻辑冲突,请修改后再试';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!result && (reason || prompt)) {
|
||||||
|
Modal.warning({
|
||||||
|
class: 'custom-modal custom-modal-title-notice hide-ant-icon',
|
||||||
|
title: '无法操作',
|
||||||
|
width: '450px',
|
||||||
|
content: reason || prompt
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
performance.end(performanceName);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 给问题列表中的问题添加,问题所在的页码字段($page)
|
||||||
|
* 说明:
|
||||||
|
* 1. 需要过滤掉没有题的空白页
|
||||||
|
* 2. 高级题型的题前后需要加分页
|
||||||
|
* 3. 添加了逻辑的基础题型前后需要加分页
|
||||||
|
* @param questions
|
||||||
|
* @param logics
|
||||||
|
* @param isPerPage
|
||||||
|
* @param addon 自定义额外操作,是一个方法
|
||||||
|
* @return {array} 题目列表,包括题和分页
|
||||||
|
*/
|
||||||
|
export function generateQuestionPages({ questions, logics, isPerPage, addon }) {
|
||||||
|
if (!questions?.length) {
|
||||||
|
return questions || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
let page = 1;
|
||||||
|
let pageObjectCount = 0; // 计数,在 questions 有几个分页的对象
|
||||||
|
return questions.map((item, index, arr) => {
|
||||||
|
const asBlock = [...advancedTypes, 23]; // 需要自动加分页的题型:高级题型及知情同意书
|
||||||
|
const isPrevAdv = asBlock.includes(arr[index - 1]?.question_type); // 前一道题是高级题型
|
||||||
|
const isAdv = asBlock.includes(item?.question_type); // 当前题是高级题型
|
||||||
|
// const isPrevAdv = advancedTypes.includes(arr[index - 1]?.question_type); // 前一道题是高级题型
|
||||||
|
// const isAdv = advancedTypes.includes(item?.question_type); // 当前题是高级题型
|
||||||
|
|
||||||
|
// 前一道题配置了跳转逻辑
|
||||||
|
const isPrevLogic = !!logics.find((logic) => logic.question_index === arr[index - 1]?.question_index);
|
||||||
|
// 当前题配置了跳转逻辑
|
||||||
|
const isLogic = !!logics.find((logic) => logic.question_index === item.question_index);
|
||||||
|
|
||||||
|
const isSurroundedByPage = isAdv || isLogic; // 需要在该题前后添加分页
|
||||||
|
|
||||||
|
const isPrevPage = !!arr[index - 1]?.page; // 前一道题是一个分页对象
|
||||||
|
const prevIsQuestion = !arr[index - 1]?.page; // 前一道题是一道题而不是一个分页对象
|
||||||
|
|
||||||
|
if (!index) {
|
||||||
|
page = 1;
|
||||||
|
pageObjectCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.page) {
|
||||||
|
pageObjectCount += 1;
|
||||||
|
if (index && prevIsQuestion && !isPrevLogic && !isPrevAdv) {
|
||||||
|
// 过滤掉没有题的空白页
|
||||||
|
page += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (index && !isPrevPage && !isPrevAdv && !isPrevLogic && isSurroundedByPage) {
|
||||||
|
page += 1;
|
||||||
|
}
|
||||||
|
item.$page = isPerPage ? index + 1 - pageObjectCount : page;
|
||||||
|
if (isSurroundedByPage) {
|
||||||
|
page += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addon) {
|
||||||
|
addon(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化循环列表,便于后续使用
|
||||||
|
* @param cycles
|
||||||
|
* @param questions
|
||||||
|
* @return {array} 格式化后的循环列表
|
||||||
|
*/
|
||||||
|
export function generateCyclePages(cycles, questions) {
|
||||||
|
if (!cycles?.length) {
|
||||||
|
return cycles || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return cycles.map((cycle) => ({
|
||||||
|
index: cycle.question_index,
|
||||||
|
page: getPageByQuestionIndex(cycle.question_index, questions),
|
||||||
|
startPage: cycle.first_page,
|
||||||
|
endPage: cycle.last_page
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 逻辑关联的页码,便于后续使用
|
||||||
|
* @param logics {*[]}
|
||||||
|
* @param questions {*[]}
|
||||||
|
* @param fillRangeItem {boolean} 用数字填充满 range[index] 数组
|
||||||
|
* @return {number[][]} 逻辑关联的页码
|
||||||
|
*/
|
||||||
|
export function generateLogicPages(logics, questions, fillRangeItem) {
|
||||||
|
if (!logics?.length) {
|
||||||
|
return logics || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const pages = [];
|
||||||
|
|
||||||
|
logics.forEach((logic) => {
|
||||||
|
if (![0, 2].includes(logic.skip_type)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let page = [
|
||||||
|
getPageByQuestionIndex(logic.logic?.[0]?.question_index, questions),
|
||||||
|
getPageByQuestionIndex(logic.question_index, questions),
|
||||||
|
getPageByQuestionIndex(logic.skip_question_index, questions) || logic.skip_question_index
|
||||||
|
];
|
||||||
|
page = page.filter((i) => !!i);
|
||||||
|
|
||||||
|
if (fillRangeItem) {
|
||||||
|
const min = Math.min(...page.filter((i) => i > 0));
|
||||||
|
const max = Math.max(...page);
|
||||||
|
page = generateRange(min, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
pages.push(page);
|
||||||
|
});
|
||||||
|
|
||||||
|
return pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过问题的 question_index 找到问题在第几页
|
||||||
|
* @param questionIndex
|
||||||
|
* @param questions
|
||||||
|
* @return {number|*|undefined}
|
||||||
|
*/
|
||||||
|
export function getPageByQuestionIndex(questionIndex, questions) {
|
||||||
|
return questions.find((i) => i.question_index === questionIndex)?.$page || undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成一个从 start 开始到 end 结束的数组
|
||||||
|
* @param start {number}
|
||||||
|
* @param end {number}
|
||||||
|
* @return {number[]}
|
||||||
|
*/
|
||||||
|
export function generateRange(start, end) {
|
||||||
|
if (isNullish(start) || isNullish(end)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNaN(Number(start)) || isNaN(Number(end))) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
let i = start;
|
||||||
|
let range = [];
|
||||||
|
while (i <= end) {
|
||||||
|
range.push(i);
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return range;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断逻辑与循环分组,是否不合理
|
||||||
|
* @param range1 {array} 跳转逻辑的分页数组
|
||||||
|
* @param range2 {array} 循环分组的分页数组
|
||||||
|
* @return {boolean} true 不合理, false 合理
|
||||||
|
*/
|
||||||
|
export function isCross(range1, range2) {
|
||||||
|
if (!range1 || !range2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsedRange1 = range1.slice(1);
|
||||||
|
const judge = range1[0];
|
||||||
|
|
||||||
|
const start1 = Math.min(...parsedRange1);
|
||||||
|
const end1 = Math.max(...parsedRange1);
|
||||||
|
const start2 = range2[0];
|
||||||
|
const end2 = range2[1];
|
||||||
|
|
||||||
|
const isPlainSequence = parsedRange1[0] === start1; // 跳转逻辑的方向,true 为从前向后跳转
|
||||||
|
|
||||||
|
if (isNullish(start1) || isNullish(end1) || end1 < 0 || (isNullish(start2) && isNullish(end2))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// [judge, start1, end1]; // isPlainSequence
|
||||||
|
// [start1, judge, end1]; // isPlainSequence || !isPlainSequence
|
||||||
|
//
|
||||||
|
// [start2, end2];
|
||||||
|
|
||||||
|
// 逻辑在循环之前
|
||||||
|
const isLeft = isNullish(start2) ? end1 < end2 : end1 < start2;
|
||||||
|
// 逻辑在循环之后
|
||||||
|
const isRight = isNullish(end2) ? start2 < start1 && start2 < judge : end2 < start1 && end2 < judge;
|
||||||
|
// 不相交也不包含
|
||||||
|
const isSibling = isLeft || isRight;
|
||||||
|
|
||||||
|
// 逻辑包含循环
|
||||||
|
const contain = (isPlainSequence
|
||||||
|
&& (((isNullish(start2) || isSequence(judge, start2, start1))
|
||||||
|
&& (isNullish(end2) || isSequence(judge, end2, start1)))
|
||||||
|
|| ((isNullish(start2) || isSequence(start1, start2, end1))
|
||||||
|
&& (isNullish(end2) || isSequence(start1, end2, end1)))))
|
||||||
|
|| (!isPlainSequence
|
||||||
|
&& (judge < start1
|
||||||
|
? ((isNullish(start2) || isSequence(judge, start2, start1))
|
||||||
|
&& (isNullish(end2) || isSequence(judge, end2, start1)))
|
||||||
|
|| ((isNullish(start2) || isSequence(start1, start2, end1))
|
||||||
|
&& (isNullish(end2) || isSequence(start1, end2, end1)))
|
||||||
|
: ((isNullish(start2) || isSequence(start1, start2, judge))
|
||||||
|
&& (isNullish(end2) || isSequence(start1, end2, judge)))
|
||||||
|
|| ((isNullish(start2) || isSequence(judge, start2, end1))
|
||||||
|
&& (isNullish(end2) || isSequence(judge, end2, end1)))));
|
||||||
|
// 循环存在封闭区间,并且循环包含逻辑
|
||||||
|
const contained = !isNullish(start2)
|
||||||
|
&& !isNullish(end2)
|
||||||
|
// [judge, start1, end1];
|
||||||
|
&& ((isPlainSequence && start2 <= judge && end1 <= end2)
|
||||||
|
// [judge, start1, end1];
|
||||||
|
// [start1, judge, end1];
|
||||||
|
|| (!isPlainSequence && start2 <= start1 && start2 <= judge && end1 <= end2));
|
||||||
|
// 循环不存在封闭区间
|
||||||
|
const unCircled = (!isNullish(start2)
|
||||||
|
&& isNullish(end2)
|
||||||
|
&& ((isPlainSequence && start2 === judge) || (!isPlainSequence && judge < start1)
|
||||||
|
? start2 === judge
|
||||||
|
: start2 === start1))
|
||||||
|
|| (isNullish(start2) && !isNullish(end2) && end2 === end1);
|
||||||
|
|
||||||
|
return !(isSibling || contain || contained || unCircled);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSequence(s1, s2, s3, equal) {
|
||||||
|
return equal ? s1 <= s2 && s2 <= s3 : s1 < s2 && s2 < s3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调用保存问题接口前,检查是否有问题受到循环影响需要重新保存,如果有则重新保存一下这道题,没有则不需要特殊处理
|
||||||
|
* bugfix for : 有循环的问卷发布后,再次编辑问卷,将循环题组内的问题移除循环题组,
|
||||||
|
* 再次发布,后端不处理被移除的问题 title,导致该题的 title 仍保持上次发布时的值
|
||||||
|
* 错误格式一般为:B3.1 正确格式一般为:B3
|
||||||
|
* 导致作答出现错误,例如:引用找不到题
|
||||||
|
* 从 store 里查出修改前和修改后的问题、分页、循环;比较修改前后问题是否被移除了某个循环题组;修改 quesSaveParam.newQuestion;
|
||||||
|
* @param quesSaveParam 将要保存的数据,会被此方法修改的字段:quesSaveParam.newQuestion
|
||||||
|
* @param store
|
||||||
|
*/
|
||||||
|
export function updateNewQuestionsByLoopingEffect(quesSaveParam, store) {
|
||||||
|
const { questionInfoBeforeModified = {}, questionInfo = {} } = JSON.parse(JSON.stringify(store.state.common)) || {};
|
||||||
|
|
||||||
|
const oldPages = questionInfoBeforeModified.survey.pages;
|
||||||
|
const newQuestions = questionInfo.questions;
|
||||||
|
const newPages = questionInfo.survey.is_one_page_one_question
|
||||||
|
? questionInfo.questions.filter((i) => i.question_index).map((i, idx) => [i.question_index])
|
||||||
|
: questionInfo.survey.pages;
|
||||||
|
const cycles = questionInfo.cycle_pages || [];
|
||||||
|
|
||||||
|
if (!cycles.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const moveOutOfCycleQuestionIndex = [];
|
||||||
|
const cyclePages = cycles.map((i) => [i.first_page, i.last_page]).filter((i) => i[0] && i[1]);
|
||||||
|
cyclePages.forEach((i) => {
|
||||||
|
const start = i[0] - 1;
|
||||||
|
const end = i[1] - 1;
|
||||||
|
|
||||||
|
for (let j = start; j <= end; j += 1) {
|
||||||
|
if (oldPages[j]?.join(',') !== newPages[j]?.join(',')) {
|
||||||
|
oldPages[j]?.forEach((k) => {
|
||||||
|
if (!newPages?.[j]?.includes(k)) {
|
||||||
|
moveOutOfCycleQuestionIndex.push(k);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const movedOutOfCycleQuestions = newQuestions.filter((i) => moveOutOfCycleQuestionIndex.includes(i.question_index));
|
||||||
|
|
||||||
|
if (movedOutOfCycleQuestions.length) {
|
||||||
|
if (!quesSaveParam.newQuestion) {
|
||||||
|
quesSaveParam.newQuestion = [];
|
||||||
|
}
|
||||||
|
quesSaveParam.newQuestion.push(...movedOutOfCycleQuestions);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
|
|
||||||
import { showConfirmDialog } from 'vant';
|
import { showConfirmDialog } from 'vant';
|
||||||
import { getQuestionList, getCheckSurvey } from '@/api/survey';
|
import { getQuestionList, getCheckSurvey } from '@/api/survey';
|
||||||
import appBridge from '@/assets/js/appBridge';
|
import appBridge from '@/assets/js/appBridge';
|
||||||
|
import { QUESTION_TYPE } from '@/layouts/config3d.constant.js';
|
||||||
|
import { loopingAvailable } from '@/layouts/logic.js';
|
||||||
|
import { getDomText } from '@/utils/utils';
|
||||||
// /**
|
// /**
|
||||||
// * 统一的弹窗
|
// * 统一的弹窗
|
||||||
// * @param options
|
// * @param options
|
||||||
@@ -46,8 +48,8 @@ const canPlanetPublishPSM = function(data) {
|
|||||||
let message = '';
|
let message = '';
|
||||||
let title = '题目设置未完成';
|
let title = '题目设置未完成';
|
||||||
const incompleteQuestionList = [];
|
const incompleteQuestionList = [];
|
||||||
data.questions
|
data.questions &&
|
||||||
&& data.questions.forEach((s) => {
|
data.questions.forEach((s) => {
|
||||||
if (s.question_type === 101 && s.config.price_gradient.length <= 0) {
|
if (s.question_type === 101 && s.config.price_gradient.length <= 0) {
|
||||||
isFb = false;
|
isFb = false;
|
||||||
message = 'psm题目未完成设置,请设置价格区间后投放';
|
message = 'psm题目未完成设置,请设置价格区间后投放';
|
||||||
@@ -79,8 +81,8 @@ const canPlanetPublishMxdAndHotArea = function(data) {
|
|||||||
const incompleteQuestionList = [];
|
const incompleteQuestionList = [];
|
||||||
let type = 0;
|
let type = 0;
|
||||||
let title = '题目设置未完成';
|
let title = '题目设置未完成';
|
||||||
data.questions
|
data.questions &&
|
||||||
&& data.questions.forEach((s) => {
|
data.questions.forEach((s) => {
|
||||||
if (s.question_type === 105 && s.config.design_version <= 0) {
|
if (s.question_type === 105 && s.config.design_version <= 0) {
|
||||||
isFb = false;
|
isFb = false;
|
||||||
message = 'maxdiff题目未完成设置,请生成设计后投放';
|
message = 'maxdiff题目未完成设置,请生成设计后投放';
|
||||||
@@ -125,8 +127,8 @@ const canPlanetPublish3D = function(data) {
|
|||||||
let message = '';
|
let message = '';
|
||||||
const qSteams = [];
|
const qSteams = [];
|
||||||
let title = '';
|
let title = '';
|
||||||
data.questions
|
data.questions &&
|
||||||
&& data.questions.forEach((s) => {
|
data.questions.forEach((s) => {
|
||||||
if (QUESTION_TYPE.contains(s.question_type)) {
|
if (QUESTION_TYPE.contains(s.question_type)) {
|
||||||
try {
|
try {
|
||||||
if (s.config.is_three_dimensions && !s.config.scene) {
|
if (s.config.is_three_dimensions && !s.config.scene) {
|
||||||
@@ -156,15 +158,15 @@ const canPlanetPublish3D = function(data) {
|
|||||||
let message = '';
|
let message = '';
|
||||||
const qSteams = [];
|
const qSteams = [];
|
||||||
let title = '';
|
let title = '';
|
||||||
data.questions
|
data.questions &&
|
||||||
&& data.questions.forEach((s) => {
|
data.questions.forEach((s) => {
|
||||||
if (QUESTION_TYPE.contains(s.question_type)) {
|
if (QUESTION_TYPE.contains(s.question_type)) {
|
||||||
try {
|
try {
|
||||||
if (s.config.is_three_dimensions && s.config.is_binding_goods) {
|
if (s.config.is_three_dimensions && s.config.is_binding_goods) {
|
||||||
const wares = [];
|
const wares = [];
|
||||||
const _sceneInformation = s.config.scene_information;
|
const _sceneInformation = s.config.scene_information;
|
||||||
const sceneInformation
|
const sceneInformation =
|
||||||
= typeof _sceneInformation === 'string'
|
typeof _sceneInformation === 'string'
|
||||||
? JSON.parse(_sceneInformation)
|
? JSON.parse(_sceneInformation)
|
||||||
: _sceneInformation;
|
: _sceneInformation;
|
||||||
sceneInformation.shelves.forEach((shelf) => {
|
sceneInformation.shelves.forEach((shelf) => {
|
||||||
@@ -219,8 +221,8 @@ const canPlanetPublishImage = function(data) {
|
|||||||
let message = '';
|
let message = '';
|
||||||
const qSteams = [];
|
const qSteams = [];
|
||||||
let title = '';
|
let title = '';
|
||||||
data.questions
|
data.questions &&
|
||||||
&& data.questions.forEach((s) => {
|
data.questions.forEach((s) => {
|
||||||
if (s.question_type === 13) {
|
if (s.question_type === 13) {
|
||||||
try {
|
try {
|
||||||
if (s.options.length <= 0 || s.options.some((y) => y.length <= 0)) {
|
if (s.options.length <= 0 || s.options.some((y) => y.length <= 0)) {
|
||||||
@@ -314,8 +316,8 @@ function canPublishRandom(data, publishType) {
|
|||||||
if (!isValidated) {
|
if (!isValidated) {
|
||||||
errors.push({
|
errors.push({
|
||||||
message:
|
message:
|
||||||
field.message
|
field.message ||
|
||||||
|| `请填写"${random.title}"中第${index + 1}组"随机题组"的"${field.name}"`
|
`请填写"${random.title}"中第${index + 1}组"随机题组"的"${field.name}"`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -375,11 +377,11 @@ function isLoopingLogicValid(data, publishType) {
|
|||||||
if (
|
if (
|
||||||
(data?.cycle_pages || []).every((i) => {
|
(data?.cycle_pages || []).every((i) => {
|
||||||
return (
|
return (
|
||||||
i.question_index
|
i.question_index &&
|
||||||
&& i.relation_type !== undefined
|
i.relation_type !== undefined &&
|
||||||
&& i.relation_type !== null
|
i.relation_type !== null &&
|
||||||
&& i.first_page
|
i.first_page &&
|
||||||
&& i.last_page
|
i.last_page
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
) {
|
) {
|
||||||
|
|||||||
Reference in New Issue
Block a user