123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608 |
- import {
- getExplainChildren,
- getFillQuesitons,
- getFillLine,
- getNewPage,
- getTopicHead,
- getElementId
- } from "./elementModel";
- import { deepCopy, calcSum } from "@/plugins/utils";
- const state = {
- curElement: {},
- curDragElement: {},
- curPageNo: 0,
- pages: [],
- topicNos: [],
- cardConfig: {},
- paperParams: {},
- openElementEditDialog: false
- };
- const mutations = {
- setCurElement(state, curElement) {
- state.curElement = curElement;
- },
- setCurDragElement(state, curDragElement) {
- state.curDragElement = curDragElement;
- },
- setPages(state, pages) {
- state.pages = pages;
- },
- setTopicNos(state, topicNos) {
- topicNos.sort((a, b) => a - b);
- state.topicNos = topicNos;
- },
- setCardConfig(state, cardConfig) {
- state.cardConfig = Object.assign({}, state.cardConfig, cardConfig);
- },
- setPaperParams(state, paperParams) {
- state.paperParams = paperParams;
- },
- setCurPageNo(state, curPageNo) {
- state.curPageNo = curPageNo;
- },
- addPage(state, page) {
- state.pages.push(page);
- },
- modifyPage(state, page) {
- state.pages.splice(page._pageNo, 1, page);
- },
- setOpenElementEditDialog(state, openElementEditDialog) {
- state.openElementEditDialog = openElementEditDialog;
- },
- initTopicNos(state) {
- state.topicNos = getPageTopicNos(state.pages);
- },
- initState(state) {
- state.curElement = {};
- state.curDragElement = {};
- state.curPageNo = 0;
- state.pages = [];
- state.cardConfig = {};
- state.paperParams = {};
- state.openElementEditDialog = false;
- state.topicNos = [];
- }
- };
- /**
- * 获取所有相同元素的位置信息
- * @param {Object} element 元素
- * @param {Object} pages 页面结构
- */
- const fetchElementPositionInfos = (element, pages) => {
- let postionInfos = [];
- for (let i = 0, ilen = pages.length; i < ilen; i++) {
- for (let j = 0, jlen = pages[i].columns.length; j < jlen; j++) {
- pages[i].columns[j].elements.forEach((item, eindex) => {
- if (item.id === element.id) {
- postionInfos.push({ _pageNo: i, _columnNo: j, _elementNo: eindex });
- }
- });
- }
- }
- return postionInfos;
- };
- /**
- * 获取所有含有相同parent属性的元素位置信息
- * @param {Object} parentElement 父元素
- * @param {Object} pages 页面结构
- */
- const fetchAllRelateParentElementPositionInfos = (parentElement, pages) => {
- // 当为解答题时,parentElement传入的值是EXPLAIN
- let postionInfos = [];
- for (let i = 0, ilen = pages.length; i < ilen; i++) {
- for (let j = 0, jlen = pages[i].columns.length; j < jlen; j++) {
- pages[i].columns[j].elements.forEach((item, eindex) => {
- if (item["parent"] && item.parent.id === parentElement.id) {
- let pos = { _pageNo: i, _columnNo: j, _elementNo: eindex };
- if (parentElement.type === "EXPLAIN") {
- pos.explainNumber = item.explainNumber;
- }
- postionInfos.push(pos);
- }
- });
- }
- }
- return postionInfos;
- };
- const fetchFirstSubjectiveTopicPositionInfo = pages => {
- for (let i = 0, ilen = pages.length; i < ilen; i++) {
- for (let j = 0, jlen = pages[i].columns.length; j < jlen; j++) {
- const index = pages[i].columns[j].elements.findIndex(item => {
- return item.sign === "subjective";
- });
- if (index !== -1) return { _pageNo: i, _columnNo: j, _elementNo: index };
- }
- }
- };
- const fetchSameExplainNumberExplainChildernPositionInfo = (
- explainChildernElement,
- pages
- ) => {
- let postionInfos = [];
- const explainId = explainChildernElement.parent.id;
- const explainNumber = explainChildernElement.explainNumber;
- for (let i = 0, ilen = pages.length; i < ilen; i++) {
- for (let j = 0, jlen = pages[i].columns.length; j < jlen; j++) {
- pages[i].columns[j].elements.forEach((item, eindex) => {
- if (
- item.parent &&
- item.parent.id === explainId &&
- item.explainNumber === explainNumber
- ) {
- postionInfos.push({
- _pageNo: i,
- _columnNo: j,
- _elementNo: eindex,
- _elementId: item.id
- });
- }
- });
- }
- }
- return postionInfos;
- };
- function groupByParams(datas, paramKey) {
- let elementGroupInfos = [];
- for (let i = 0, len = datas.length; i < len; i++) {
- if (i === 0 || datas[i][paramKey] !== datas[i - 1][paramKey]) {
- elementGroupInfos.push([datas[i]]);
- } else {
- elementGroupInfos[elementGroupInfos.length - 1].push(datas[i]);
- }
- }
- return elementGroupInfos;
- }
- const getPageTopicNos = pages => {
- let topicNos = [];
- pages.forEach(page => {
- page.columns.forEach(column => {
- column.elements.forEach(element => {
- if (element["topicNo"] && !topicNos.includes(element["topicNo"]))
- topicNos.push(element["topicNo"]);
- });
- });
- });
- return topicNos;
- };
- const fetchPageLastColumnPositionInfo = pages => {
- return {
- _pageNo: pages.length - 1,
- _columnNo: pages[pages.length - 1].columns.length - 1
- };
- };
- const findElementById = (id, pages) => {
- let curElement = null;
- pages.forEach(page => {
- page.columns.forEach(column => {
- column.elements.forEach(element => {
- if (curElement) return;
- if (element.id === id) {
- curElement = element;
- return;
- }
- if (element["elements"]) {
- element["elements"].forEach(elem => {
- if (element.id === id) curElement = elem;
- });
- }
- });
- });
- });
- return curElement;
- };
- const createFunc = {
- EXPLAIN(element) {
- return getExplainChildren(element);
- },
- FILL_QUESTION(element) {
- return getFillQuesitons(element, state.cardConfig.columnNumber);
- },
- FILL_LINE(element) {
- return getFillLine(element);
- },
- COMPOSITION(element) {
- return [element];
- }
- };
- const actions = {
- modifyElement({ state, commit, dispatch }, element) {
- if (element.type === "COMPOSITION") {
- const positionInfos = fetchElementPositionInfos(element, state.pages);
- if (positionInfos.length) {
- const pos = positionInfos[0];
- const elements =
- state.pages[pos._pageNo].columns[pos._columnNo].elements;
- elements.splice(pos._elementNo, 1, element);
- } else {
- dispatch("addElement", element);
- }
- } else if (element.type === "EXPLAIN") {
- const positionInfos = fetchAllRelateParentElementPositionInfos(
- element,
- state.pages
- );
- if (positionInfos.length) {
- const elementGroupPosInfos = groupByParams(
- positionInfos,
- "explainNumber"
- );
- const orgElementCount = elementGroupPosInfos.length;
- if (orgElementCount > element.questionsCount) {
- // 原小题数多于新小题数,要删除原多于的小题;
- let needDeleteInfos = elementGroupPosInfos.splice(
- element.questionsCount,
- orgElementCount - element.questionsCount
- );
- needDeleteInfos.reverse().forEach(item => {
- item.reverse().forEach(pos => {
- const elems =
- state.pages[pos._pageNo].columns[pos._columnNo].elements;
- elems.splice(pos._elementNo, 1);
- });
- });
- }
- const newElements = getExplainChildren(element);
- const lastPos = elementGroupPosInfos.slice(-1)[0].slice(-1)[0];
- for (var i = 0; i < element.questionsCount; i++) {
- if (elementGroupPosInfos[i]) {
- elementGroupPosInfos[i].forEach(pos => {
- let child =
- state.pages[pos._pageNo].columns[pos._columnNo].elements[
- pos._elementNo
- ];
- child.explainNumber = i + element.startNumber;
- child.parent = { ...element };
- });
- } else {
- state.pages[lastPos._pageNo].columns[
- lastPos._columnNo
- ].elements.splice(lastPos._elementNo + 1, 0, newElements[i]);
- }
- }
- } else {
- dispatch("addElement", element);
- }
- } else {
- // 非作文题都是拆分题,即同一个题拆分成多个小题展示
- const positionInfos = fetchAllRelateParentElementPositionInfos(
- element,
- state.pages
- );
- if (positionInfos.length) {
- // 缓存已编辑的小题高度信息。
- const elementHeights = positionInfos.map(pos => {
- return state.pages[pos._pageNo].columns[pos._columnNo].elements[
- pos._elementNo
- ].h;
- });
- // 删除所有小题
- positionInfos.reverse().forEach(pos => {
- const elems =
- state.pages[pos._pageNo].columns[pos._columnNo].elements;
- elems.splice(pos._elementNo, 1);
- });
- // 创建新的小题元素
- const newElements = createFunc[element.type](element);
- const pos = positionInfos.pop();
- newElements.forEach((newElement, index) => {
- newElement.h = elementHeights[index] || newElement.h;
- state.pages[pos._pageNo].columns[pos._columnNo].elements.splice(
- pos._elementNo + index,
- 0,
- newElement
- );
- });
- } else {
- dispatch("addElement", element);
- }
- }
- commit("setCurElement", element);
- },
- addElement({ state, commit }, element) {
- let pos = null;
- // 客观题和主观题分别对待
- if (element.type === "FILL_QUESTION") {
- pos =
- fetchFirstSubjectiveTopicPositionInfo(state.pages) ||
- fetchPageLastColumnPositionInfo(state.pages);
- } else {
- pos = fetchPageLastColumnPositionInfo(state.pages);
- }
- const elements = state.pages[pos._pageNo].columns[pos._columnNo].elements;
- let preElements = createFunc[element.type](element);
- preElements.forEach(preElement => {
- elements.push(preElement);
- });
- commit("setCurElement", element);
- },
- modifyCardHead({ state }, element) {
- state.pages[0].columns[0].elements.splice(0, 1, element);
- },
- removeElement({ state, commit }, element) {
- if (element.type === "COMPOSITION") {
- const positionInfos = fetchElementPositionInfos(element, state.pages);
- if (!positionInfos.length) return;
- positionInfos.forEach(pos => {
- const elements =
- state.pages[pos._pageNo].columns[pos._columnNo].elements;
- elements.splice(pos._elementNo, 1);
- });
- } else {
- // 非作文题,删除所有小题。
- const positionInfos = fetchAllRelateParentElementPositionInfos(
- element.parent,
- state.pages
- );
- if (positionInfos.length) {
- positionInfos.reverse().forEach(pos => {
- const elems =
- state.pages[pos._pageNo].columns[pos._columnNo].elements;
- elems.splice(pos._elementNo, 1);
- });
- }
- }
- // 删除大题题号
- state.topicNos.splice(state.topicNos.indexOf(element.topicNo), 1);
- commit("setCurElement", {});
- },
- removeElementChild({ state, commit }, element) {
- // 删除解答题小题和作文题的子元素
- const positionInfos = fetchElementPositionInfos(
- element.container,
- state.pages
- );
- if (!positionInfos.length) return;
- positionInfos.forEach(pos => {
- const columnElement =
- state.pages[pos._pageNo].columns[pos._columnNo].elements[
- pos._elementNo
- ];
- const childIndex = columnElement.elements.findIndex(
- item => item.id === element.id
- );
- columnElement.elements.splice(childIndex, 1);
- });
- commit("setCurElement", {});
- },
- modifyElementChild({ state, commit }, element) {
- // 修改解答题小题和作文题的子元素
- const positionInfos = fetchElementPositionInfos(
- element.container,
- state.pages
- );
- if (!positionInfos.length) return;
- positionInfos.forEach(pos => {
- const columnElement =
- state.pages[pos._pageNo].columns[pos._columnNo].elements[
- pos._elementNo
- ];
- const childIndex = columnElement.elements.findIndex(
- item => item.id === element.id
- );
- columnElement.elements.splice(childIndex, 1, element);
- });
- commit("setCurElement", element);
- },
- resetElementProp({ state }, isResetId = false) {
- state.pages.forEach(page => {
- page.columns.forEach(column => {
- column.elements.forEach(element => {
- const elementDom = document.getElementById(element.id);
- if (elementDom) {
- element.h = elementDom.offsetHeight;
- element.w = elementDom.offsetWidth;
- }
- if (isResetId) {
- element.id = getElementId();
- }
- });
- });
- });
- },
- rebuildPages({ state, commit }) {
- const columnNumber = state.cardConfig.columnNumber;
- // 更新元件最新的高度信息
- // 整理所有元件
- let objectiveElements = [];
- let subjectiveElements = [];
- const cardHeadElement = state.pages[0].columns[0].elements[0];
- state.pages.forEach(page => {
- page.columns.forEach(column => {
- column.elements.forEach(element => {
- const elementDom = document.getElementById(element.id);
- if (elementDom) {
- element.h = elementDom.offsetHeight;
- element.w = elementDom.offsetWidth;
- // 解答题小题与其他题有些区别。
- // 其他题都是通过内部子元素自动撑高元件,而解答题则需要手动设置高度。
- element.isCovered =
- element.type !== "EXPLAIN_CHILDREN" &&
- elementDom.offsetHeight < elementDom.firstChild.offsetHeight;
- }
- // 过滤掉所有topic-head元素,这个元素是动态加的,页面重排时可能会添加重复元件。
- if (element.sign && element.type !== "TOPIC_HEAD") {
- if (element.sign === "objective") objectiveElements.push(element);
- if (element.sign === "subjective") subjectiveElements.push(element);
- }
- });
- });
- });
- // 动态计算每列可以分配的元件
- const columnHeight = document.getElementById("column-0-0").offsetHeight;
- const simpleCardHeadHeight = document.getElementById("simple-card-head")
- .offsetHeight;
- let pages = [];
- let page = {};
- let columns = [];
- let curColumnElements = [];
- let curColumnHeight = 0;
- const initCurColumnElements = () => {
- curColumnElements = [];
- curColumnHeight = 0;
- const groupColumnNumber = columnNumber * 2;
- // 奇数页第一栏;
- if (!(columns.length % groupColumnNumber)) {
- // 非第一页奇数页第一栏
- if (columns.length) {
- const cardHeadSimpleElement = {
- ...cardHeadElement
- };
- cardHeadSimpleElement.id = getElementId();
- cardHeadSimpleElement.isSimple = true;
- cardHeadSimpleElement.h = simpleCardHeadHeight;
- curColumnElements.push(cardHeadSimpleElement);
- curColumnHeight += simpleCardHeadHeight;
- } else {
- curColumnElements.push(cardHeadElement);
- curColumnHeight += cardHeadElement.h;
- }
- }
- };
- const checkElementIsCurColumnFirstType = element => {
- const topicHeadIndex = curColumnElements.findIndex(
- elem => elem.type === "TOPIC_HEAD" && elem.sign === element.sign
- );
- return topicHeadIndex === -1;
- };
- // 放入元素通用流程
- const pushElement = element => {
- // 当前栏中第一个题型之前新增题型头元素(topic-head)。
- // 题型头和当前题要组合加入栏中,不可拆分。
- let elementList = [element];
- if (checkElementIsCurColumnFirstType(element)) {
- elementList.unshift(
- getTopicHead(
- state.cardConfig[`${element.sign}Notice`],
- element.sign,
- !curColumnElements.length
- )
- );
- }
- const elementHeight = calcSum(elementList.map(elem => elem.h));
- if (curColumnHeight + elementHeight > columnHeight) {
- // 当前栏第一个元素高度超过一栏时,不拆分,直接放在当前栏。
- // 解决可能空栏的情况
- const curElementIsFirst = !curColumnElements.length;
- if (curElementIsFirst) {
- curColumnElements = [...curColumnElements, ...elementList];
- curColumnHeight += elementHeight;
- } else {
- columns.push([...curColumnElements]);
- initCurColumnElements();
- pushElement(element);
- }
- } else {
- curColumnElements = [...curColumnElements, ...elementList];
- curColumnHeight += elementHeight;
- }
- };
- // 批量添加所有元素。
- initCurColumnElements();
- [...objectiveElements, ...subjectiveElements].map((element, eindex) => {
- element.serialNo = eindex;
- pushElement(element);
- });
- // 最后一栏的处理。
- columns.push([...curColumnElements]);
- // 构建pages
- columns.forEach((column, cindex) => {
- const columnNo = cindex % columnNumber;
- if (!columnNo) {
- page = getNewPage(pages.length, columnNumber);
- }
- page.columns[columnNo].elements = column;
- if (columnNo + 1 === columnNumber || cindex === columns.length - 1) {
- pages.push(deepCopy(page));
- }
- });
- // 保证页面总是偶数页
- if (pages.length % 2) {
- pages.push(getNewPage(pages.length, columnNumber));
- }
- commit("setPages", pages);
- },
- actElementById({ state, commit }, id) {
- const curElement = findElementById(id, state.pages);
- if (!curElement) return;
- commit("setCurElement", curElement);
- },
- copyExplainChildren({ state }, element) {
- let newElement = deepCopy(element);
- newElement.id = getElementId();
- newElement.elements = [];
- newElement.h = 200;
- newElement.showTitle = false;
- const positionInfos = fetchElementPositionInfos(element, state.pages);
- if (!positionInfos.length) return;
- const pos = positionInfos[0];
- state.pages[pos._pageNo].columns[pos._columnNo].elements.splice(
- pos._elementNo + 1,
- 0,
- newElement
- );
- },
- deleteExplainChildren({ state }, element) {
- const positionInfos = fetchSameExplainNumberExplainChildernPositionInfo(
- element,
- state.pages
- );
- if (positionInfos.length < 2) return;
- const pindex = positionInfos.findIndex(
- item => item._elementId === element.id
- );
- const pos = positionInfos[pindex];
- state.pages[pos._pageNo].columns[pos._columnNo].elements.splice(
- pos._elementNo,
- 1
- );
- // 当删除的是含有标题解答题小题时,则需要将下一个答题区开启显示标题。
- // element.explainNumber === element.parent.startNumber && pindex === 0
- if (element.showTitle) {
- const nextPos = positionInfos[pindex + 1];
- state.pages[nextPos._pageNo].columns[nextPos._columnNo].elements[
- nextPos._elementNo
- ].showTitle = true;
- }
- }
- };
- export { fetchSameExplainNumberExplainChildernPositionInfo };
- export default {
- namespaced: true,
- state,
- mutations,
- actions
- };
|