Files
ylst-pc/src/views/planetDesign/Logical/fragment/RandomListV2.vue
2022-12-05 15:45:14 +08:00

838 lines
24 KiB
Vue

<template>
<div class="random-list">
<div class="random-list-add">
<a-button class="custom-button" type="primary" @click="addRaddom">添加随机</a-button>
</div>
<div
class="random-list-show"
v-click-outside="onClickOutside"
v-if="options && options.length > 0"
>
<template v-for="(item, index) in options" :key="index">
<div class="random-list-item">
<div class="random-list-item-title">
<span class="random-list-item-title-left">
<QuestionTinymceOption
v-model:html="item.title"
placeholder="特性"
:max-length="25"
:showHover="true"
@focusChange="edit"
>
</QuestionTinymceOption>
</span>
<span
><a
class="random-list-item-title-right"
@click="delectRaddom(index)"
>删除</a
></span
>
</div>
<!-- active -->
<div
class="random-list-item-body"
@click="toActive(item)"
:class="item.active ? 'active' : ''"
>
<template v-for="(itemj, idx) in item.list" :key="idx">
<div class="random-list-item-body-item">
<span class="title">随机题组</span>
<span>
<a-input
style="border-radius:4px;"
placeholder="请输入题组名称"
@blur="edit"
v-model:value="itemj.title"
></a-input>
</span>
<span>
<a-select
class="w-100"
placeholder="请选择题组起点"
v-model:value="itemj.start"
:options="itemj.questionStartInfo"
style=" border-radius:4px;"
@change="
(value) => {
onStartChange(itemj, value, item, idx);
}
"
></a-select>
</span>
<span>
<a-select
class="w-100"
placeholder="请选择题组终点"
v-model:value="itemj.end"
:options="itemj.questionEndInfo"
style=" border-radius:4px;"
@change="
(value) => {
onEndChange(itemj, value, item, idx);
}
"
></a-select>
</span>
<span>
<a-input-number v-model:value="itemj.sample_num" :formatter="val => val && !isNaN(val) ? Math.floor(Number(val)) : '' " class="w-100" :min="0" placeholder="请输入样本数" @blur="edit" style=" border-radius:4px;"/>
</span>
<span>
<a
@click="deleteOptions(item, idx, itemj, index)"
v-if="idx > 1"
class="right-10"
>删除</a
>
<a v-if="idx > 0" @click="addoptions(item)">新增</a>
</span>
</div>
</template>
<div class="random-list-item-body-item">
<span class="title"
><a-checkbox
:checked="item.is_select === 1"
class="custom-checkbox"
@change="
(value) => {
onchange(value, item);
}
"
>显示题组数</a-checkbox
>
</span>
<span>
<a-input-number
class="w-100"
style=" border-radius:4px;"
v-model:value="item.num"
:max="item.list.length"
@blur="edit"
placeholder="请输入显示数量"
></a-input-number
></span>
</div>
</div>
<div class="random-list-item-border" />
</div>
</template>
</div>
<div v-else class="logical-list-empty">
<img src="../../../../assets/img/no_logic@2x.png" />
<span>暂无题组随机</span>
</div>
</div>
</template>
<script>
import { computed, onMounted, ref, watch } from 'vue';
import { useStore } from 'vuex';
import { getProcess, postProcess } from '../../api/api';
import { useRoute } from 'vue-router';
import QuestionTinymceOption from '../../Design/components/QuestionTinymceOption.vue';
//import { sendMessage } from '../util/util';
export default {
components: {
QuestionTinymceOption
},
props: {
data: {
type: [Array, Object],
default: () => []
}
},
setup(props) {
const store = useStore();
const route = useRoute();
const questionInfo = ref([]);
const options = ref([]);
const procesData = ref([]);
const survey = ref(props.data.survey);
const questions = ref(props.data.questions);
const logics = ref(props.data.logics);
const deal_questions = ref(props.data.deal_questions);
onMounted(async () => {
var data= await getProcess({
sn: route.query.sn
});
procesData.value =data.data.group_pages;
watch(
() => props.data,
() => {
getOptions();
}
);
getOptions();
});
const getOptions = () => {
survey.value = props.data.survey;
questions.value = props.data.questions;
logics.value = props.data.logics;
deal_questions.value = props.data.deal_questions;
questionInfo.value =
deal_questions?.value?.map((s, index) => {
const value = index + 1;
return {
label: `${index + 1}`,
value
};
}) || [];
options.value =
procesData.value?.map((s, index) => {
return {
...s,
num: s?.num,
questionIndex: index,
list: s.list.map((item, idx) => {
return {
...item,
start:Number.parseInt( item.start) || null,
end:Number.parseInt(item.end) || null,
questionIndex: idx + 1
};
})
};
}) || [];
getProcesQuestion();
// getSendList();
};
const addRaddom = () => {
options.value.push({
title: `随机${options.value.length + 1}`,
num: undefined,
questionIndex: 1,
is_select: 0,
list: [
{
title: undefined,
start: undefined,
end: undefined,
sample_num: "",
questionIndex: 0
},
{
title: undefined,
start: undefined,
end: undefined,
sample_num: "",
questionIndex: 0
}
]
});
edit();
options.value[options.value.length - 1].active = true;
setTimeout(() => {
document.getElementById('logicalContent').scrollTop =
options.value.length * 775;
});
};
const addoptions = (item) => {
//onClickOutside();
options.value.forEach((s) => {
s.active = false;
});
item.list.push({
title: undefined,
start: undefined,
end: undefined,
questionIndex: item.questionIndex,
questionStartInfo: questionInfo.value,
questionEndInfo: questionInfo.value
});
item.questionIndex += 1;
edit();
item.active = true;
};
const deleteOptions = (item, idx) => {
item.list.splice(idx, 1);
item.questionIndex -= 1;
edit();
};
const delectRaddom = (index) => {
options.value.splice(index, 1);
edit();
};
const toActive = (item) => {
options.value.map((s) => {
delete s.active;
return {
...s
};
});
item.active = true;
};
const onchange = (value, item) => {
item.is_select = value.target.checked ? 1 : 0;
edit();
};
const edit = () => {
const optionsCopy = JSON.parse(JSON.stringify(options.value));
const group_pages = optionsCopy.map((s) => {
delete s.questionIndex;
s.list.map((s) => {
delete s.questionInfo;
delete s.questionIndex;
delete s.questionEndInfo;
delete s.questionStartInfo;
return {
...s
};
});
return {
...s
};
});
postProcess({
group_pages: group_pages,
sn: route.query.sn
});
getProcesQuestion();
};
const onStartChange = () => {
edit();
};
const onEndChange = () => {
edit();
};
//获取 全部信息
const getProcesQuestion = () => {
options.value.forEach((s, index) => {
const newOptionsList = ref([]);
const newOptions = JSON.parse(JSON.stringify(options.value))
.filter((item, idx) => index !== idx)
.forEach((s, index) => {
s.list.forEach((x, index) => {
if (x.start) {
newOptionsList.value.push(...reasoning(x.start, x.end));
const end = reasoningLgoic(x.start, x.end) || x.start;
newOptionsList.value.push(...reasoning(x.start, end));
}
});
});
getOptionsList(index, newOptionsList.value);
});
// getSendList();
};
//获取选项信息
const getOptionsList = (index, newOptions) => {
options.value[index].list.forEach((s, idx) => {
const newOptionsItemList = ref([]);
let index2 = 0;
//不可选择
const newOptionsItem = JSON.parse(JSON.stringify(options.value))
.filter((item, idx) => idx === index)
.forEach((s, idx2) => {
s.list.forEach((x, idx3) => {
if (idx !== idx3) {
if (x.start) {
newOptionsItemList.value.push(...reasoning(x.start, x.end));
const end = reasoningLgoic(x.start, x.end) || x.start;
// const copyInfoOptionsItemList = JSON.parse(
// JSON.stringify(newOptionsItemList.value)
// );
// copyInfoOptionsItemList.forEach((s) => {
// newOptionsItemList.value.push(...reasoningLgoic(s));
// });
newOptionsItemList.value.push(...reasoning(x.start, end));
}
} else {
index2 = idx3;
}
});
});
s.questionStartInfo = getStart(
s,
newOptions,
newOptionsItemList,
index,
index2
);
s.questionEndInfo = getEnd(
s,
newOptions,
newOptionsItemList,
index,
index2
);
});
};
//获取开始选项
const getStart = (item, newOptions, newOptionsItemList, index, index2) => {
//全部试题
const deal_questionsOptions = ref(
deal_questions?.value?.map((s, index) => {
return {
...s,
label: `${index + 1}`,
value: index + 1
};
})
);
if (deal_questionsOptions.value) {
if (newOptions && newOptions.length > 0) {
newOptions.forEach((s, index) => {
deal_questionsOptions.value = deal_questionsOptions.value.filter(
(x) => {
return x.value !== s;
}
);
});
}
if (newOptionsItemList.value && newOptionsItemList.value.length > 0) {
newOptionsItemList.value.forEach((s, index) => {
deal_questionsOptions.value = deal_questionsOptions.value.filter(
(x) => {
return x.value !== s;
}
);
});
}
let resultOptions = deal_questionsOptions.value.map((s, index) => {
return {
label: s.label,
value: s.value
};
});
// let endlist =[];
// resultOptions.forEach((s) => {
// const end = reasoningLgoic(s.value);
// endlist.push();
// });
// const data = getEndOptions(item, resultOptions);
// resultOptions = data.options;
// resultOptions = reasoningOptional(resultOptions);
resultOptions = reasoningStartOptional(resultOptions);
const result = getOptionsMath(index, index2, deal_questions?.value);
resultOptions = resultOptions.filter(
(s) => s.value > result?.start && s.value <= result?.end
);
return resultOptions;
}
};
//获取结束 选项
const getEnd = (item, newOptions, newOptionsItemList, index, index2) => {
//全部试题
const deal_questionsOptions = ref(
deal_questions?.value?.map((s, index) => {
return {
...s,
label: `${index + 1}`,
value: index + 1
};
})
);
if (deal_questionsOptions.value) {
if (newOptions && newOptions.length > 0) {
newOptions.forEach((s, index) => {
deal_questionsOptions.value = deal_questionsOptions.value.filter(
(x) => {
return x.value !== s;
}
);
});
}
if (newOptionsItemList.value && newOptionsItemList.value.length > 0) {
newOptionsItemList.value.forEach((s, index) => {
deal_questionsOptions.value = deal_questionsOptions.value.filter(
(x) => {
return x.value !== s;
}
);
});
}
const end = reasoningLgoic(item.start, item.end) || item.start;
let resultOptions = deal_questionsOptions.value
.filter((s) => s.value >= end)
.map((s, index) => {
return {
label: s.label,
value: s.value
};
});
//
const data = getEndOptions(end, resultOptions);
resultOptions = data.options;
resultOptions = reasoningEndOptional(resultOptions);
const result = getOptionsMath(index, index2, deal_questions?.value);
resultOptions = resultOptions.filter(
(s) => s.value > result?.start && s.value <= result?.end
);
return resultOptions;
} else {
return [];
}
};
//结束选项推理
const getEndOptions = (start, optionalOptions) => {
if (start) {
const indexList = [];
let index2 = 0;
let result = 0;
optionalOptions.forEach((s, index) => {
if (s.value === start + index2) {
indexList.push(s);
index2++;
result = start + index2;
}
});
return {
endIndex: result,
options: indexList
};
} else {
return {
endIndex: undefined,
options: []
};
}
};
//推理 开始 - 结束
const reasoning = (start, end) => {
end = end || start;
const options = [];
for (let index = start; index <= end; index++) {
options.push(index);
}
return options;
};
//逻辑推理 开始-结束
const reasoningLgoic = (start, end, skipQuestionsIndex) => {
if (!deal_questions.value) {
return;
}
end = end || start;
skipQuestionsIndex = skipQuestionsIndex || 0;
const quic = ref([]);
deal_questions.value
.filter((s, index) => {
return end >= index + 1 && start <= index + 1;
})
.forEach((s, index) => {
quic.value.push(...s);
});
let skip_question_index = 0;
let skipIndex = 0;
logics.value.forEach((s, index) => {
let isLogics = false;
s.logic.forEach((item, index) => {
let questionIndex = 0;
const quicItem = quic.value.find(
(x) => x.question_index === item.question_index
);
if (quicItem) {
if (s.skip_type === 3) {
questionIndex = s.question_index;
}
if (s.skip_type === 0) {
questionIndex = s.skip_question_index;
}
deal_questions.value.forEach((element, idx) => {
const skipItem = element.find(
(s) => s.question_index === questionIndex
);
if (skipItem) {
skipIndex = skipIndex > idx + 1 ? skipIndex : idx + 1;
}
});
}
});
});
if (skipIndex > end) {
return reasoningLgoic(start, skipIndex, skipIndex);
}
return skipIndex;
};
//开始逻辑 开始-结束
const reasoningStartOptional = (resultOptions) => {
let end = [];
resultOptions.forEach((s) => {
const skipIndex = reasoningLgoic(s.value);
if (skipIndex > 0) {
end.push({
start: s.value,
end: skipIndex
});
}
});
end.forEach((s) => {
resultOptions = resultOptions.filter((x) => {
return x.value <= s.start || x.value > s.end;
});
});
return resultOptions;
};
//结束逻辑 开始-结束
const reasoningEndOptional = (resultOptions) => {
let end = [];
resultOptions.forEach((s) => {
const skipIndex = reasoningLgoic(s.value);
if (skipIndex > 0) {
end.push({
start: s.value,
end: skipIndex
});
}
});
end.forEach((s) => {
resultOptions = resultOptions.filter((x) => {
return x.value < s.start || x.value >= s.end;
});
});
return resultOptions;
};
//向下选择
const getOptionsMath = (index, index2, deal_questions) => {
const result = {
start: 0,
end: deal_questions?.length ?? 0
};
const prev =
options.value?.[index]?.list
?.filter((s, idx) => idx < index2)
.map((s) => s.end || s.start || 0) ?? 0;
const next =
options.value?.[index]?.list
?.filter((s, idx) => idx > index2)
.map((s) => s.start || s.end) ?? 0;
result.start = Math.max(
...prev.filter(function (s) {
return s !== undefined;
})
);
result.end =
Math.min(...next.filter((s) => s !== undefined)) === 0
? deal_questions?.length
: Math.min(...next.filter((s) => s !== undefined));
let end = deal_questions?.length;
let start = 0;
options.value
.filter((s, idx) => idx < index)
.forEach((s) => {
s.list.forEach((s) => {
const reuslt = s.start || s.end;
if (reuslt) {
start = start > reuslt ? start : reuslt;
}
});
});
options.value
.filter((s, idx) => idx > index)
.forEach((s) => {
s.list.forEach((s) => {
const reuslt = s.end || s.start;
if (reuslt) {
end = end < reuslt ? end : reuslt;
}
});
});
result.start = result.start > start ? result.start : start;
result.end = result.end < end ? result.end : end;
return result;
};
// const getSendList = () => {
// // const sendList = ref([]);
// // let idx = 0;
// // const item = ref({});
// // if (!deal_questions.value) {
// // return;
// // }
// // questions.value.forEach((itemj) => {
// // if (!itemj.question_index > 0) {
// // return;
// // }
// // const index = survey.value.detail_pages.findIndex((x) =>
// // x.includes(itemj.question_index)
// // );
// // if (index > 0) {
// // // const sendItem = survey.value.detail_pages.find((x) =>
// // // x.includes(s.question_index)
// // // );
// // const id = `E${new Date().getTime()}${index + 1}`;
// // if (idx !== index) {
// // idx = index;
// // item.value = {
// // associate: [],
// // created_at: '',
// // created_user_id: 0,
// // id: id,
// // last_option_index: id,
// // logics_has: 0,
// // options: [],
// // question_index: id,
// // question_type: 201,
// // stem: `${index + 1}`,
// // survey_id: `${new Date().getTime()}${index + 1}`,
// // title: '',
// // nodeType: 'group',
// // updated_user_id: ''
// // };
// // sendList.value.push({
// // ...item.value
// // });
// // }
// // sendList.value.push({
// // ...itemj,
// // parentNode: id,
// // nodeType: 'input'
// // });
// // } else {
// // sendList.value.push({
// // ...itemj,
// // nodeType: 'output'
// // });
// // }
// // });
// // console.log('-------sendList.value------------', sendList.value);
// // sendMessage(sendList.value, 1);
// };
const onClickOutside = (e) => {
const path = e.path || (e.composedPath && e.composedPath());
const newPath = path.slice(0, path.length - 4);
if (!newPath.find((x) => x.getAttribute('outside'))) {
options.value.forEach((s) => {
s.active = false;
});
// dataList.value.forEach((x) => {
// x.logicals.forEach((y) => {
// if (y.edit && y.skip_type === 3 && x.ques.question_type === 4 && y.autofill.error) {
// return;
// }
// y.edit = false;
// });
// });
}
};
return {
options,
addRaddom,
addoptions,
deleteOptions,
toActive,
delectRaddom,
onchange,
edit,
onStartChange,
onEndChange,
onClickOutside
};
}
};
</script>
<style lang="scss" scoped>
.random-list {
.random-list-add {
margin-top: 10px;
text-align: right;
}
.random-list-show {
.random-list-item {
margin-top: 10px;
.random-list-item-title {
margin: 14px;
display: flex;
.random-list-item-title-left {
flex: 1;
font-size: 14px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #434343;
}
.random-list-item-title-right {
color: #c5c5c5;
}
}
.random-list-item-body {
min-height: 212px;
background: #ffffff;
border-radius: 6px;
padding: 15px 12px;
.random-list-item-body-item {
display: flex;
justify-items: center;
align-items: center;
.title {
width: 120px;
max-width: 120px;
display: inline-block;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #434343;
}
span {
flex: 1;
margin: 7px;
width: 186px;
border-radius: 4px;
max-width: 186px;
}
}
}
.active {
box-shadow: 0px 4px 12px 0px rgba(52, 52, 52, 0.13);
border: 1px solid $yili-default-color;
}
.random-list-item-border {
margin: 0 auto;
margin-top: 22px;
height: 1px;
border-bottom: 1px solid #bfbfbf;
width: 98%;
}
}
}
}
.w-100 {
width: 100%;
}
.w-100:deep(.ant-select-selector){
border-radius:4px;
}
.right-10 {
margin-right: 10px;
}
.logical-list-empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: $yili-default-color;
img {
width: 160px;
height: 160px;
margin-top: 120px;
}
}
</style>