Files
ylst-h5/src/layouts/utils.js
liu.huiying@ebiz-digits.com 29823bd10e fix:投放测试
2025-03-18 10:35:25 +08:00

482 lines
13 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { showConfirmDialog } from 'vant';
import { getQuestionList, getCheckSurvey } from '@/api/survey';
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
*/
function showModal(options) {
showConfirmDialog({
title: '提示',
icon: null,
...options
})
.then(() => {})
.catch(() => {});
}
/**
* PSM的判断
* @param {*} data
* @returns
*/
const canPlanetPublishPSM = function (data) {
let isFb = true;
let message = '';
let title = '题目设置未完成';
const incompleteQuestionList = [];
data.questions &&
data.questions.forEach((s) => {
if (s.question_type === 101 && s.config.price_gradient.length <= 0) {
isFb = false;
message = 'psm题目未完成设置请设置价格区间后投放';
title = '题目设置未完成';
incompleteQuestionList.push(s);
}
});
if (isFb === true && data.questions.length > 0) {
return true;
} else {
const titleStr = incompleteQuestionList.map((item) => item.title).join('、') || '';
showModal({
title,
message: `${titleStr} ${message}`,
incompleteQuestionList
});
}
};
/**
* Mxd和热区的判断
* @param {*} data
* @returns
*/
const canPlanetPublishMxdAndHotArea = function (data) {
let isFb = true;
let message = '';
const qSteams = [];
const incompleteQuestionList = [];
let type = 0;
let title = '题目设置未完成';
data.questions &&
data.questions.forEach((s) => {
if (s.question_type === 105 && s.config.design_version <= 0) {
isFb = false;
message = 'maxdiff题目未完成设置请生成设计后投放';
title = '题目设置未完成';
type = 1;
incompleteQuestionList.push(s);
}
if (s.question_type === 25 || s.question_type === 26) {
if ((s.options?.[0]?.length || 0) <= 0 && (s?.associate?.length || 0) <= 0) {
isFb = false;
qSteams.push(`(${s.title})`);
type = 2;
incompleteQuestionList.push(s);
}
}
});
if (isFb === true) {
return true;
} else {
if (type === 2) {
const titleStr = qSteams.join(',');
title = '添加选区';
message = `${titleStr} 未添加选区,请添加选区后进行投放`;
}
showModal({
title,
message,
incompleteQuestionList
});
}
};
/**
* 3D相关的判断
* @param {*} data
* @returns
*/
const canPlanetPublish3D = function (data) {
{
let canFB = true;
let message = '';
const qSteams = [];
let title = '';
data.questions &&
data.questions.forEach((s) => {
if (QUESTION_TYPE.contains(s.question_type)) {
try {
if (s.config.is_three_dimensions && !s.config.scene) {
canFB = false;
qSteams.push(`(${s.title})`);
}
} catch (error) {
// error
}
}
});
if (!canFB === true) {
const titleStr = qSteams.join(',');
title = '选择场景';
message = `${titleStr} 未选择场景,请选择场景后进行投放`;
showModal({
title,
message
});
return;
}
}
{
let canFB = true;
let message = '';
const qSteams = [];
let title = '';
data.questions &&
data.questions.forEach((s) => {
if (QUESTION_TYPE.contains(s.question_type)) {
try {
if (s.config.is_three_dimensions && s.config.is_binding_goods) {
const wares = [];
const _sceneInformation = s.config.scene_information;
const sceneInformation =
typeof _sceneInformation === 'string'
? JSON.parse(_sceneInformation)
: _sceneInformation;
sceneInformation.shelves.forEach((shelf) => {
shelf.wares.forEach((ware) => {
if (!ware.option_index) return;
wares.push(ware);
});
});
const options = s.options.flat();
s.associate.forEach((ass) => {
// eslint-disable-next-line no-eval
const question = data.questions.find(
(q) => q.question_index === ass.question_index
);
if (!question) return;
options.push(...question.options.flat());
});
// 判定是否有选项未关联商品
if (options.length > wares.length) {
canFB = false;
qSteams.push(`(${s.title})`);
}
}
} catch (error) {
// error
}
}
});
if (!canFB === true) {
const titleStr = qSteams.join(',');
title = '商品关联选项';
message = `${titleStr} 仍有选项未关联商品,无法进行投放`;
showModal({
title,
message
});
return;
}
}
return true;
};
/**
* 图片题的判断
* @param {*} data
* @returns
*/
const canPlanetPublishImage = function (data) {
{
let canFB = true;
let message = '';
const qSteams = [];
let title = '';
data.questions &&
data.questions.forEach((s) => {
if (s.question_type === 13) {
try {
if (s.options.length <= 0 || s.options.some((y) => y.length <= 0)) {
canFB = false;
qSteams.push(`(${s.title})`);
}
} catch (error) {
// console.warn(error);
}
}
});
if (!canFB === true) {
const titleStr = qSteams.join(',');
title = '题目设置未完成';
message = `图片题 ${titleStr} 未上传图片,请设置后投放`;
showModal({
title,
message
});
return;
}
}
return true;
};
/**
* 多项填空题
* @param data
* @param publishType
*/
function canPublishMultiCompletion(data, publishType) {
const publishStr = ['', '预览', '投放'][publishType] || '投放';
const questions = [];
if (!data?.questions?.length) {
return true;
}
data.questions.forEach((quiz) => {
if (quiz.question_type !== 27) {
return;
}
if (!getDomText(quiz.config?.text_content)) {
questions.push(quiz.title);
}
});
if (questions.length) {
showModal({
title: '题目设置未完成',
message: `多项填空题 (${questions.join('、')}) 未设置填空,请设置后${publishStr}`
});
return false;
}
return true;
}
/**
* 校验 "逻辑 -> 随机列表" 是否满足投放条件
* @param data
* @return {boolean}
*/
function canPublishRandom(data, publishType) {
const publishStr = ['', '预览', '投放'][publishType] || '投放';
const errors = [];
// eslint-disable-next-line no-eval
const randomList = data?.survey?.group_pages || [];
randomList.forEach((random) => {
const list = random.list || [];
// 每一个随机,至少要有两个随机题组
if (list.length < 2) {
errors.push({ message: `"${random.title}"需至少配置2个"随机题组"` });
return false;
}
list.forEach((item, index) => {
// 这三个是必填的
const fields = [
{ label: 'title', name: '题组名称', validator: (value) => !!value },
{ label: 'start', name: '题组起点', validator: (value) => !!value },
{ label: 'end', name: '题组终点', validator: (value) => !!value }
];
fields.forEach((field) => {
const isValidated = field.validator(item[field.label]);
if (!isValidated) {
errors.push({
message:
field.message ||
`请填写"${random.title}"中第${index + 1}组"随机题组"的"${field.name}"`
});
}
});
});
});
if (errors.length) {
showModal({
title: '修改随机题组',
message: `随机题组设置不完全,请前往"逻辑设置-随机列表"修改后${publishStr}`
});
return false;
}
return true;
}
/**
* 将接口返回的题目和分页两个数组合并为一个
* @param {Array} quesList 要合并的题目
* @param {Array} pages 分页完成的题目id数组
* @param {Array} pagesStr 分页的内容数组
* @returns
*/
function combineQuesAndPage(quesList, pages, pagesStr) {
if (pages.length === 0) return quesList;
const newPages = `${pages.join(',empty,')},empty`.split(',').filter((x) => x.length !== 0);
const copyList = quesList.filter((x) => x.id);
let startIndex = 0;
newPages.forEach((x, index) => {
if (x === 'empty') {
copyList.splice(index, 0, pagesStr[startIndex]);
startIndex += 1;
}
});
return copyList;
}
/**
* 根据原始数据pages和问题列表quesList处理成包含分页的quesList
* @param {Array} questions 要合并的题目
* @param {Array} page 分页完成的题目ques_index数组
* @param {Array} pageConfig 分页配置,由于是后添加的功能,所以只好分开传,再合到一起了
* @returns
*/
function getQuesByPages(questions, page, pageConfig) {
const oldPages = questions.filter((q) => !!q.page);
const quesList = questions.filter((ques) => ques.id);
const pageStr = [];
page.forEach((x, xIndex) => {
const temp = {
...(oldPages[xIndex] || {}),
page: xIndex + 1,
total: page.length,
first_title: '',
last_title: '',
...(pageConfig?.[xIndex] || {})
};
x.forEach((y, yIndex) => {
if (yIndex === 0) {
temp.first_title = quesList.find((ques) => ques.question_index === y)?.title || '';
}
if (yIndex === x.length - 1) {
temp.last_title = quesList.find((ques) => ques.question_index === y)?.title || '';
}
});
pageStr.push(temp);
});
return combineQuesAndPage(quesList, page, pageStr);
}
/**
* 循环逻辑的判断
* @param data
* @param publishType
*/
function isLoopingLogicValid(data, publishType) {
const publishStr = ['', '预览', '投放'][publishType] || '投放';
if (
(data?.cycle_pages || []).every((i) => {
return (
i.question_index &&
i.relation_type !== undefined &&
i.relation_type !== null &&
i.first_page &&
i.last_page
);
})
) {
return loopingAvailable({
cycles: data.cycle_pages || [],
questions: getQuesByPages(data.questions || [], data.survey.pages),
logics: data.logics || [],
isPerPage: data.survey?.is_one_page_one_question
});
}
showModal({
title: '修改循环',
message: `循环题组不完全,请前往循环列表修改后${publishStr}`
});
return false;
}
/**
* 判断问卷是否可以投放(原本应该后端实现,前端实现会有并发的问题,但后端表示做不了)
* @param sn
* @param publishType undefined投放null投放0投放1预览2投放3测试
*/
export const canPlanetPublish = async function (sn, publishType) {
const parsedPublishType = !publishType ? 2 : publishType;
const num = window.location.href.indexOf('code=');
let code;
if (num > -1) {
code = window.location.href.slice(num + 5, window.location.href.length);
} else {
code = '';
}
const { data } = await getQuestionList(sn, code);
if (!canPlanetPublishPSM(data?.data)) return false;
if (!canPlanetPublishMxdAndHotArea(data?.data)) return false;
if (!canPlanetPublish3D(data?.data)) return false;
if (!canPlanetPublishImage(data?.data)) return false;
if (!canPublishMultiCompletion(data, parsedPublishType)) return false;
if (!canPublishRandom(data?.data, parsedPublishType)) return false;
if (!isLoopingLogicValid(data?.data, parsedPublishType)) return false;
if (parsedPublishType === 2) {
const qrcodeRes = await getCheckSurvey(sn);
if (qrcodeRes?.data?.data?.show_test_button) {
const res = await new Promise((resolve) => {
showConfirmDialog({
class: 'custom-modal custom-modal-title-confirm-notice show-icon',
title: '确认要投放这个问卷吗?',
messageStyle: {
position: 'absolute',
top: '0',
right: '0',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: '56px',
height: '56px',
fontSize: '14px',
cursor: 'pointer'
},
message:
'投放前测试能帮助您确认问卷设计逻辑及作答数据是否正确,避免因问卷设计问题造成重大损失。',
confirmButtonText: '去测试',
onConfirm() {
resolve(false);
if (utils.getSessionStorage('xToken')) {
appBridge.openInBrowser(
`${location.origin}/preview?sn=${sn}&name=${data.data.survey.project_name}+source=0&is_test=1`
);
} else {
window.open(
`${location.origin}/preview?sn=${sn}&name=${data.data.survey.project_name}+source=0&is_test=1`
);
}
},
width: '640px',
height: '364px',
cancelButtonText: '继续投放',
onCancel() {
resolve(true);
},
dialogStyle: {
fontSize: '44px'
},
zIndex: 9999999
});
});
if (!res) return;
}
}
return true;
};