|
@@ -0,0 +1,480 @@
|
|
|
|
+<template>
|
|
|
|
+ <div class="mark-param-group">
|
|
|
|
+ <div class="box-justify part-box part-box-pad">
|
|
|
|
+ <div>
|
|
|
|
+ <p class="tips-info">
|
|
|
|
+ 1.如果采用整卷批阅,请将全部主观题选上。如果采用分题阅卷,请将需要在一个评阅任务里评阅的题目勾选在一起;
|
|
|
|
+ </p>
|
|
|
|
+ <p class="tips-info">
|
|
|
|
+ 2.如果采用分班阅卷,每个班都将按设置的评卷任务进行评卷,请给每个班级选择对应评卷老师;
|
|
|
|
+ </p>
|
|
|
|
+ <p class="tips-info tips-error">3.开始阅卷后不允许删除评卷分组!</p>
|
|
|
|
+ </div>
|
|
|
|
+ <div>
|
|
|
|
+ <span>分班阅卷</span>
|
|
|
|
+ <el-switch
|
|
|
|
+ v-model="markClassIsOpen"
|
|
|
|
+ @change="markClassChange"
|
|
|
|
+ ></el-switch>
|
|
|
|
+ <el-button class="ml-2" type="primary" @click="toAdd">新增</el-button>
|
|
|
|
+ </div>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <div class="part-box part-box-pad">
|
|
|
|
+ <el-table :data="groupList" border>
|
|
|
|
+ <el-table-column type="index" width="50"> </el-table-column>
|
|
|
|
+ <el-table-column label="评卷员">
|
|
|
|
+ <template slot-scope="scope">
|
|
|
|
+ <el-tag
|
|
|
|
+ v-for="user in scope.row.markerList"
|
|
|
|
+ :key="user.id"
|
|
|
|
+ class="tag-spin"
|
|
|
|
+ size="medium"
|
|
|
|
+ >
|
|
|
|
+ {{ user.name }}({{ user.orgName }})
|
|
|
|
+ </el-tag>
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ <el-table-column label="评卷方式" width="100">
|
|
|
|
+ <template slot-scope="scope">
|
|
|
|
+ {{ scope.row.doubleEnable ? "双评" : "单评" }}
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ <el-table-column label="仲裁阀值" width="100">
|
|
|
|
+ <template v-if="scope.row.doubleEnable" slot-scope="scope">
|
|
|
|
+ {{ scope.row.arbitrateThreshold }}
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ <el-table-column label="合分策略" width="100">
|
|
|
|
+ <template v-if="scope.row.doubleEnable" slot-scope="scope">
|
|
|
|
+ {{ SCORE_POLICY_TYPE[scope.row.scorePolicy] }}
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ <el-table-column label="双评比例" width="100">
|
|
|
|
+ <template v-if="scope.row.doubleEnable" slot-scope="scope">
|
|
|
|
+ {{ scope.row.doubleRate }}%
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ <el-table-column label="评阅题目">
|
|
|
|
+ <template slot-scope="scope">
|
|
|
|
+ {{ scope.row.questions | questionsFilter }}
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ <el-table-column label="评卷区" width="80" align="center">
|
|
|
|
+ <template slot-scope="scope">
|
|
|
|
+ <i
|
|
|
|
+ v-if="scope.row.pictureConfigs.length"
|
|
|
|
+ class="el-icon-success color-success"
|
|
|
|
+ ></i>
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ <el-table-column class-name="action-column" label="操作" width="160px">
|
|
|
|
+ <template slot-scope="scope">
|
|
|
|
+ <el-button
|
|
|
|
+ class="btn-primary"
|
|
|
|
+ type="text"
|
|
|
|
+ @click="toEdit(scope.row)"
|
|
|
|
+ >编辑</el-button
|
|
|
|
+ >
|
|
|
|
+ <el-button
|
|
|
|
+ class="btn-primary"
|
|
|
|
+ type="text"
|
|
|
|
+ :disabled="!paperList.length"
|
|
|
|
+ @click="toSetArea(scope.row)"
|
|
|
|
+ >评卷区</el-button
|
|
|
|
+ >
|
|
|
|
+ <el-button
|
|
|
|
+ class="btn-danger"
|
|
|
|
+ type="text"
|
|
|
|
+ @click="toDelete(scope.row)"
|
|
|
|
+ >删除</el-button
|
|
|
|
+ >
|
|
|
|
+ </template>
|
|
|
|
+ </el-table-column>
|
|
|
|
+ </el-table>
|
|
|
|
+ <p v-if="unsetQuestionNos.length" class="tips-info tips-error">
|
|
|
|
+ 未设置试题:{{ unsetQuestionNos.join(",") }}
|
|
|
|
+ </p>
|
|
|
|
+ </div>
|
|
|
|
+
|
|
|
|
+ <!-- ModifyMarkGroup -->
|
|
|
|
+ <modify-mark-group
|
|
|
|
+ ref="ModifyMarkGroup"
|
|
|
|
+ :course-code="basicInfo.courseCode"
|
|
|
|
+ :instance="curGroupInfo"
|
|
|
|
+ :disabled-question-nos="disabledQuestionNos"
|
|
|
|
+ :paper-structure="subjectiveQuestionList"
|
|
|
|
+ @modified="groupModified"
|
|
|
|
+ ></modify-mark-group>
|
|
|
|
+ <!-- ModifyMarkArea -->
|
|
|
|
+ <modify-mark-area
|
|
|
|
+ ref="ModifyMarkArea"
|
|
|
|
+ :base-info="basicInfo"
|
|
|
|
+ :group="curGroupInfo"
|
|
|
|
+ :paper-list="paperList"
|
|
|
|
+ @modified="areaModified"
|
|
|
|
+ ></modify-mark-area>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script>
|
|
|
|
+import { mapState, mapMutations } from "vuex";
|
|
|
|
+import ModifyMarkGroup from "./ModifyMarkGroup.vue";
|
|
|
|
+import ModifyMarkArea from "./ModifyMarkArea.vue";
|
|
|
|
+import {
|
|
|
|
+ examStructureFindJpg,
|
|
|
|
+ markGroupItemSave,
|
|
|
|
+ markGroupItemUpdate,
|
|
|
|
+ markGroupItemDelete,
|
|
|
|
+ markGroupAreaSave,
|
|
|
|
+ markClassStatusUpdate,
|
|
|
|
+} from "../../api";
|
|
|
|
+import { cardDetail } from "../../../card/api";
|
|
|
|
+import { deepCopy, maxNum } from "@/plugins/utils";
|
|
|
|
+import { SCORE_POLICY_TYPE } from "@/constants/enumerate";
|
|
|
|
+import { omit, pick } from "lodash";
|
|
|
|
+
|
|
|
|
+export default {
|
|
|
|
+ name: "mark-param-group",
|
|
|
|
+ components: {
|
|
|
|
+ ModifyMarkGroup,
|
|
|
|
+ ModifyMarkArea,
|
|
|
|
+ },
|
|
|
|
+ data() {
|
|
|
|
+ return {
|
|
|
|
+ markClassIsOpen: false,
|
|
|
|
+ SCORE_POLICY_TYPE,
|
|
|
|
+ questionCount: 0,
|
|
|
|
+ groupQuestionCount: 0,
|
|
|
|
+ groupList: [],
|
|
|
|
+ disabledQuestionNos: [],
|
|
|
|
+ unsetQuestionNos: [],
|
|
|
|
+ curGroupInfo: {},
|
|
|
|
+ subjectiveQuestionList: [],
|
|
|
|
+ subjectiveQuestionCount: 0,
|
|
|
|
+ objectiveQuestionCount: 0,
|
|
|
|
+ MARK_TYPE: {
|
|
|
|
+ 0: "单评",
|
|
|
|
+ 1: "双评",
|
|
|
|
+ },
|
|
|
|
+ paperList: [],
|
|
|
|
+ cardPages: [],
|
|
|
|
+ dataReady: false,
|
|
|
|
+ deleting: false,
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+ computed: {
|
|
|
|
+ ...mapState("markParam", [
|
|
|
|
+ "basicInfo",
|
|
|
|
+ "paperStructureInfo",
|
|
|
|
+ "openMarkClass",
|
|
|
|
+ "groupInfo",
|
|
|
|
+ ]),
|
|
|
|
+ },
|
|
|
|
+ filters: {
|
|
|
|
+ questionsFilter(val) {
|
|
|
|
+ return val
|
|
|
|
+ .map((item) => `${item.mainNumber}-${item.subNumber}`)
|
|
|
|
+ .join(",");
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+ mounted() {
|
|
|
|
+ this.initData();
|
|
|
|
+ this.getPaperList();
|
|
|
|
+ this.getCardPages();
|
|
|
|
+ },
|
|
|
|
+ methods: {
|
|
|
|
+ ...mapMutations("markParam", ["setGroupInfo", "setOpenMarkClass"]),
|
|
|
|
+ async getPaperList() {
|
|
|
|
+ this.paperList = [];
|
|
|
|
+ const data = await examStructureFindJpg({
|
|
|
|
+ examId: this.basicInfo.examId,
|
|
|
|
+ courseCode: this.basicInfo.courseCode,
|
|
|
|
+ paperNumber: this.basicInfo.paperNumber,
|
|
|
|
+ paperType: this.basicInfo.paperType,
|
|
|
|
+ });
|
|
|
|
+ const papers = data || [];
|
|
|
|
+ papers.sort((a, b) => a.index - b.index);
|
|
|
|
+ this.paperList = papers.map((paper) => {
|
|
|
|
+ return {
|
|
|
|
+ imgUrl: paper.path,
|
|
|
|
+ areas: [],
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ async getCardPages() {
|
|
|
|
+ const detData = await cardDetail(this.basicInfo.cardId);
|
|
|
|
+ const cardContent = JSON.parse(detData.content);
|
|
|
|
+ this.cardPages = cardContent.pages;
|
|
|
|
+ },
|
|
|
|
+ initData() {
|
|
|
|
+ this.markClassIsOpen = this.openMarkClass;
|
|
|
|
+ this.groupList = this.groupInfo.map((item) => {
|
|
|
|
+ return { ...deepCopy(item), id: this.$randomCode() };
|
|
|
|
+ });
|
|
|
|
+ this.questionCount = this.paperStructureInfo.length;
|
|
|
|
+ this.updateDisableQuestionNos();
|
|
|
|
+
|
|
|
|
+ this.subjectiveQuestionList = this.paperStructureInfo
|
|
|
|
+ .filter((item) => !item.isObjective)
|
|
|
|
+ .map((item) => {
|
|
|
|
+ return {
|
|
|
|
+ ...item,
|
|
|
|
+ qno: `${item.mainNumber}-${item.subNumber}`,
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+ this.subjectiveQuestionCount = this.subjectiveQuestionList.length;
|
|
|
|
+ this.objectiveQuestionCount =
|
|
|
|
+ this.questionCount - this.subjectiveQuestionCount;
|
|
|
|
+
|
|
|
|
+ this.dataReady = true;
|
|
|
|
+ },
|
|
|
|
+ updateDisableQuestionNos(filterId) {
|
|
|
|
+ let groupList = this.groupList;
|
|
|
|
+ if (filterId)
|
|
|
|
+ groupList = groupList.filter((item) => item.id !== filterId);
|
|
|
|
+ let disabledQuestionNos = [];
|
|
|
|
+ groupList.forEach((item) => {
|
|
|
|
+ disabledQuestionNos = [
|
|
|
|
+ ...disabledQuestionNos,
|
|
|
|
+ ...item.questions.map((item) => item.qno),
|
|
|
|
+ ];
|
|
|
|
+ });
|
|
|
|
+ this.disabledQuestionNos = disabledQuestionNos;
|
|
|
|
+ if (!filterId) this.groupQuestionCount = disabledQuestionNos.length;
|
|
|
|
+ this.updateUnsetQuestionNos();
|
|
|
|
+ },
|
|
|
|
+ updateUnsetQuestionNos() {
|
|
|
|
+ this.unsetQuestionNos = this.subjectiveQuestionList
|
|
|
|
+ .filter((q) => !this.disabledQuestionNos.includes(q.qno))
|
|
|
|
+ .map((q) => q.qno);
|
|
|
|
+ },
|
|
|
|
+ toAdd() {
|
|
|
|
+ this.updateDisableQuestionNos();
|
|
|
|
+ if (this.groupQuestionCount === this.subjectiveQuestionCount) {
|
|
|
|
+ this.$message.error("当前已经没有主观题目可供设置!");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.curGroupInfo = {
|
|
|
|
+ id: this.$randomCode(),
|
|
|
|
+ groupNumber: maxNum(this.groupList.map((item) => item.groupNumber)) + 1,
|
|
|
|
+ doubleEnable: false,
|
|
|
|
+ doubleRate: 100,
|
|
|
|
+ arbitrateThreshold: 1,
|
|
|
|
+ scorePolicy: "AVG",
|
|
|
|
+ markers: [],
|
|
|
|
+ pictureConfigs: [],
|
|
|
|
+ questions: [],
|
|
|
|
+ };
|
|
|
|
+ this.$refs.ModifyMarkGroup.open();
|
|
|
|
+ },
|
|
|
|
+ toEdit(row) {
|
|
|
|
+ this.curGroupInfo = row;
|
|
|
|
+ this.updateDisableQuestionNos(row.id);
|
|
|
|
+ this.$refs.ModifyMarkGroup.open();
|
|
|
|
+ },
|
|
|
|
+ toSetArea(row) {
|
|
|
|
+ this.curGroupInfo = row;
|
|
|
|
+ this.$refs.ModifyMarkArea.open();
|
|
|
|
+ },
|
|
|
|
+ async toDelete(row) {
|
|
|
|
+ if (!this.deleting) return;
|
|
|
|
+
|
|
|
|
+ const confirm = await this.$confirm(`确定要删除当前分组吗?`, "提示", {
|
|
|
|
+ type: "warning",
|
|
|
|
+ }).catch(() => {});
|
|
|
|
+ if (confirm !== "confirm") return;
|
|
|
|
+
|
|
|
|
+ this.deleting = true;
|
|
|
|
+ const res = await markGroupItemDelete({
|
|
|
|
+ examId: this.basicInfo.examId,
|
|
|
|
+ paperNumber: this.basicInfo.paperNumber,
|
|
|
|
+ groupNumber: row.groupNumber,
|
|
|
|
+ }).catch(() => {});
|
|
|
|
+ this.deleting = false;
|
|
|
|
+ if (!res) return;
|
|
|
|
+
|
|
|
|
+ const pos = this.groupList.findIndex((item) => item.id === row.id);
|
|
|
|
+ this.groupList.splice(pos, 1);
|
|
|
|
+ this.updateDisableQuestionNos();
|
|
|
|
+ this.updateData();
|
|
|
|
+ },
|
|
|
|
+ async groupModified(row) {
|
|
|
|
+ const pos = this.groupList.findIndex((item) => item.id === row.id);
|
|
|
|
+ if (!row.pictureConfigs.length) {
|
|
|
|
+ row.pictureConfigs = this.autoParsePictureConfigList(row.questions);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ await this.updateMarkGroup(row, pos === -1);
|
|
|
|
+ if (pos === -1) {
|
|
|
|
+ this.groupList.push(row);
|
|
|
|
+ } else {
|
|
|
|
+ this.groupList.splice(pos, 1, row);
|
|
|
|
+ }
|
|
|
|
+ this.updateDisableQuestionNos();
|
|
|
|
+ this.updateData();
|
|
|
|
+ },
|
|
|
|
+ async updateMarkGroup(row, isAdd) {
|
|
|
|
+ const data = {
|
|
|
|
+ examId: this.basicInfo.examId,
|
|
|
|
+ paperNumber: this.basicInfo.paperNumber,
|
|
|
|
+ groupInfo: omit(row, ["id"]),
|
|
|
|
+ };
|
|
|
|
+ const updateApi = isAdd ? markGroupItemSave : markGroupItemUpdate;
|
|
|
|
+ await updateApi(data);
|
|
|
|
+ },
|
|
|
|
+ autoParsePictureConfigList(questions) {
|
|
|
|
+ if (!questions.length) return [];
|
|
|
|
+ let pictureConfigs = [];
|
|
|
|
+ const structs = questions.map(
|
|
|
|
+ (item) => `${item.mainNumber}_${item.subNumber}`
|
|
|
|
+ );
|
|
|
|
+ this.cardPages.forEach((page, pindex) => {
|
|
|
|
+ page.exchange.answer_area.forEach((area) => {
|
|
|
|
+ const [x, y, w, h] = area.area;
|
|
|
|
+ const qStruct = `${area.main_number}_${area.sub_number}`;
|
|
|
|
+
|
|
|
|
+ const pConfig = {
|
|
|
|
+ i: pindex + 1,
|
|
|
|
+ x,
|
|
|
|
+ y,
|
|
|
|
+ w,
|
|
|
|
+ h,
|
|
|
|
+ qStruct,
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ if (typeof area.sub_number === "number") {
|
|
|
|
+ if (!structs.includes(qStruct)) return;
|
|
|
|
+ pictureConfigs.push(pConfig);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ // 复合区域处理,比如填空题,多个小题合并为一个区域
|
|
|
|
+ if (typeof area.sub_number === "string") {
|
|
|
|
+ const areaStructs = area.sub_number
|
|
|
|
+ .split(",")
|
|
|
|
+ .map((subNumber) => `${area.main_number}_${subNumber}`);
|
|
|
|
+ if (
|
|
|
|
+ structs.some((struct) => areaStructs.includes(struct)) &&
|
|
|
|
+ !pictureConfigs.find((item) => item.qStruct === qStruct)
|
|
|
|
+ ) {
|
|
|
|
+ pictureConfigs.push(pConfig);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ pictureConfigs.forEach((item) => {
|
|
|
|
+ delete item.qStruct;
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 合并相邻区域
|
|
|
|
+ pictureConfigs.sort((a, b) => {
|
|
|
|
+ return a.i - b.i || a.x - b.x || a.y - b.y;
|
|
|
|
+ });
|
|
|
|
+ let combinePictureConfigList = [];
|
|
|
|
+ let prevConfig = null;
|
|
|
|
+ pictureConfigs.forEach((item, index) => {
|
|
|
|
+ if (!index) {
|
|
|
|
+ prevConfig = { ...item };
|
|
|
|
+ combinePictureConfigList.push(prevConfig);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (
|
|
|
|
+ prevConfig.i === item.i &&
|
|
|
|
+ prevConfig.y + prevConfig.h >= item.y &&
|
|
|
|
+ prevConfig.w === item.w &&
|
|
|
|
+ prevConfig.x === item.x
|
|
|
|
+ ) {
|
|
|
|
+ prevConfig.h = item.y + item.h - prevConfig.y;
|
|
|
|
+ } else {
|
|
|
|
+ prevConfig = { ...item };
|
|
|
|
+ combinePictureConfigList.push(prevConfig);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ // console.log(combinePictureConfigList);
|
|
|
|
+ // 自动扩展区域。
|
|
|
|
+ let scaleRate = 0.002;
|
|
|
|
+ combinePictureConfigList = combinePictureConfigList.map((item) => {
|
|
|
|
+ return {
|
|
|
|
+ i: item.i,
|
|
|
|
+ x: item.x - scaleRate,
|
|
|
|
+ y: item.y - scaleRate,
|
|
|
|
+ w: item.w + 2 * scaleRate,
|
|
|
|
+ h: item.h + 2 * scaleRate,
|
|
|
|
+ };
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ return combinePictureConfigList;
|
|
|
|
+ },
|
|
|
|
+ async areaModified(row) {
|
|
|
|
+ const pos = this.groupList.findIndex((item) => item.id === row.id);
|
|
|
|
+ if (pos === -1) return;
|
|
|
|
+
|
|
|
|
+ await markGroupAreaSave({
|
|
|
|
+ examId: this.basicInfo.examId,
|
|
|
|
+ paperNumber: this.basicInfo.paperNumber,
|
|
|
|
+ groupNumber: row.groupNumber,
|
|
|
|
+ pictureConfigs: row.pictureConfigs,
|
|
|
|
+ });
|
|
|
|
+ this.groupList.splice(pos, 1, row);
|
|
|
|
+ this.updateData();
|
|
|
|
+ },
|
|
|
|
+ async markClassChange() {
|
|
|
|
+ const name = this.markClassIsOpen ? "开启" : "取消";
|
|
|
|
+ const confirm = await this.$confirm(`确定要${name}分班阅卷吗?`, "提示", {
|
|
|
|
+ type: "warning",
|
|
|
|
+ }).catch(() => {});
|
|
|
|
+ if (confirm !== "confirm") {
|
|
|
|
+ this.markClassIsOpen = !this.markClassIsOpen;
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const res = await markClassStatusUpdate({
|
|
|
|
+ examId: this.basicInfo.examId,
|
|
|
|
+ paperNumber: this.basicInfo.paperNumber,
|
|
|
|
+ openMarkClass: this.markClassIsOpen,
|
|
|
|
+ }).catch(() => {
|
|
|
|
+ this.markClassIsOpen = !this.markClassIsOpen;
|
|
|
|
+ });
|
|
|
|
+ if (!res) return;
|
|
|
|
+ this.setOpenMarkClass(this.markClassIsOpen);
|
|
|
|
+ },
|
|
|
|
+ checkData() {
|
|
|
|
+ let errorMessages = [];
|
|
|
|
+
|
|
|
|
+ if (this.subjectiveQuestionCount > this.groupQuestionCount) {
|
|
|
|
+ errorMessages.push("当前还有题目未设置分组");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.groupList.forEach((item, index) => {
|
|
|
|
+ if (item.doubleRate === 1 && !item.arbitrateThreshold) {
|
|
|
|
+ errorMessages.push(`序号${index + 1}设置中,仲裁阀值不能为空`);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ if (errorMessages.length) {
|
|
|
|
+ this.$message.error(errorMessages.join("。"));
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ getData() {
|
|
|
|
+ return this.groupList.map((item) => {
|
|
|
|
+ const group = omit(item, ["id"]);
|
|
|
|
+ group.questions = group.questions.map((item) =>
|
|
|
|
+ pick(item, [
|
|
|
|
+ "id",
|
|
|
|
+ "mainNumber",
|
|
|
|
+ "mainTitle",
|
|
|
|
+ "subNumber",
|
|
|
|
+ "questionType",
|
|
|
|
+ ])
|
|
|
|
+ );
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ updateData() {
|
|
|
|
+ this.setGroupInfo(this.getData());
|
|
|
|
+ },
|
|
|
|
+ },
|
|
|
|
+};
|
|
|
|
+</script>
|