zhongshujie
2024-12-05 b00acb907054a7119862de9c037e600b3818e266
大学生心理测评
6个文件已修改
13个文件已添加
8468 ■■■■■ 已修改文件
app.json 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/bookServices/detail/components/testResource/testResource.js 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/bookServices/detail/components/testResource/testResource.wxml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/bookServices/detail/index.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/bookServices/examination/examination.js 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/psychologyAnswer/psychologyAnswer.js 726 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/psychologyAnswer/psychologyAnswer.json 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/psychologyAnswer/psychologyAnswer.wxml 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/psychologyAnswer/psychologyAnswer.wxss 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/psychologyAnswer/questionList/index.js 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/psychologyAnswer/questionList/index.json 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/psychologyAnswer/questionList/index.wxml 334 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/psychologyAnswer/questionList/index.wxss 312 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/psychologyAnswer/questionOptions/index.js 250 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/psychologyAnswer/questionOptions/index.json 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/psychologyAnswer/questionOptions/index.wxml 184 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/psychologyAnswer/questionOptions/index.wxss 261 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
packageBookService/pages/psychologyAnswer/testdata/index.js 6025 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
project.config.json 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app.json
@@ -79,7 +79,8 @@
        "pages/components/webView/index",
        "pages/bookServices/detail/buyResource/index",
        "pages/bookServices/detail/components/learnTask/index",
        "pages/bookServices/linkPage/index"
        "pages/bookServices/linkPage/index",
        "pages/psychologyAnswer/psychologyAnswer"
      ]
    }
  ],
packageBookService/pages/bookServices/detail/components/testResource/testResource.js
@@ -124,15 +124,38 @@
        }
      }
      wx.hideLoading();
      wx.navigateTo({
        url: `/packageBookService/pages/bookServices/examination/examination?bookId=${
          this.properties.bookInfo.id
        }&productLinkPath=${value.productLinkPath}&rootCmsItemId=${
          this.properties.bookInfo.rootCmsItemId
        }&idPathList=${JSON.stringify(idPathList)}&answerTitle=${
          value.name
        }&answerType=${"option"}&storeInfo=${this.properties.storeInfo}&jslx=${this.properties.jslx}`,
      });
      if (value.fromType == "json") {
        const questuionList = this.properties.list
        var psychologyList = []
        var listIndex = 0
        for (let index = 0; index < questuionList.length; index++) {
          const item = questuionList[index];
          if (item.name == "心理测评") {
            psychologyList = [...item.children]
          }
        }
        for (let cindex = 0; cindex < psychologyList.length; cindex++) {
          const citem = psychologyList[cindex];
          if (value.name == citem.name) {
            listIndex = cindex
          }
        }
        wx.navigateTo({
          url: `/packageBookService/pages/psychologyAnswer/psychologyAnswer?listIndex=${
            listIndex
        }`
        })
      } else {
        wx.navigateTo({
          url: `/packageBookService/pages/bookServices/examination/examination?bookId=${
            this.properties.bookInfo.id
          }&productLinkPath=${value.productLinkPath}&rootCmsItemId=${
            this.properties.bookInfo.rootCmsItemId
          }&idPathList=${JSON.stringify(idPathList)}&answerTitle=${
            value.name
          }&answerType=${"option"}&storeInfo=${this.properties.storeInfo}&jslx=${this.properties.jslx}`,
        });
      }
    },
    goMycollect(e) {
      const answertype = e.currentTarget.dataset.answertype;
packageBookService/pages/bookServices/detail/components/testResource/testResource.wxml
@@ -102,6 +102,7 @@
  </view> -->
  <!-- 练习列表树结构 -->
  <view wx:if="{{radioItem == 'test'}}">
<<<<<<< Updated upstream
    <view class="buy-question-btn" wx:if="{{!isBuyBank}}">
      <t-button
        class="error-btn"
@@ -119,6 +120,8 @@
        </view>
      </t-button>
    </view>
=======
>>>>>>> Stashed changes
    <tree
      id="test-tree"
      openIds="{{openIds}}"
@@ -126,7 +129,12 @@
      tab="{{tab}}"
      treeList="{{list}}"
      bind:goTest="goTest"
<<<<<<< Updated upstream
    ></tree>
=======
    >
    </tree>
>>>>>>> Stashed changes
  </view>
  <view
    wx:if="{{noResources}}"
@@ -137,7 +145,10 @@
    <empty />
  </view>
</view>
<<<<<<< Updated upstream
=======
>>>>>>> Stashed changes
<!-- 组卷列表 -->
<view class="mock-data" wx:if="{{radioItem == 'mock'}}">
  <view>
packageBookService/pages/bookServices/detail/index.js
@@ -7,6 +7,7 @@
} from "../../../../assets/js/login";
import FormData from '../../../../utils/formdata/index.js';
const app = getApp();
var pastData = require('../../psychologyAnswer/testdata/index')
Page({
  /**
   * 页面的初始数据
@@ -1187,6 +1188,19 @@
                loading: false,
                openTeachids: result,
              });
              const bookId = that.data.bookId
              if (bookId == 6619) {
                const jsonData = {}
                jsonData.name = "心理测评"
                jsonData.children = [...pastData.postData.list]
                var test = that.data.test;
                test.push(jsonData);
                that.setData({
                  test: test,
                });
                console.log(that.data.test, "教学互动");
              }
            } else {
              that.setData({
                noResources: true,
packageBookService/pages/bookServices/examination/examination.js
@@ -77,6 +77,7 @@
      storeInfo: options.storeInfo,
      jslx: options.jslx,
    });
    console.log(options, 'options');
    wx.setNavigationBarTitle({
      title: options.answerTitle,
    })
@@ -841,6 +842,7 @@
        catalogName: pathitem.name,
        infoList: [],
      });
      console.log(pathList, "pathList");
      this.setData({
        cardList: pathList,
      });
@@ -1820,6 +1822,7 @@
        cardList: cardList,
        loading: false,
      });
      console.log(this.data.questionDataList, "questionDataList");
    });
  },
  // 获取组卷结果
packageBookService/pages/psychologyAnswer/psychologyAnswer.js
New file
@@ -0,0 +1,726 @@
// packageBookService/pages/psychologyAnswer/psychologyAnswer.js
import {
  getPublicImage
} from "../../../assets/js/middleGround/tool";
import {
  loginInfo
} from '../../../assets/js/login';
const app = getApp();
var pastData = require('./testdata/index')
Page({
  /**
   * 页面的初始数据
   */
  data: {
    dataList: "",
    barHeight: "",
    navBarHeight: "",
    loading: false,
    answerTitle: "", // 导航栏标题
    submitStatus: false, // 提交状态
    currentIndex: 0, // 当前显示的题号
    total: 0, // 题目总数
    totalScore: 0, //题目总分
    scoreDataList: [], // 特殊分数
    cardList: [], // 提交项,
    questionDataList: [], // 显示题目列表
    questionDataTitle: "", //显示题目的提示信息
    jumpQuestionList: [], //存储被删除的题目
    noData: false,
    isNight: false,
    sliderValue: 0, // 字体滑块
    showDialog: false, // 未提交退出拦截弹窗
    showId: '',
    isShowDialog: false, // 测试报告弹窗是否显示
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    const indexof = options.listIndex;
    const systInfo = wx.getSystemInfoSync();
    const menu = wx.getMenuButtonBoundingClientRect(); // 胶囊信息
    const navBarHeight =
      (menu.top - systInfo.statusBarHeight) * 2 + menu.height; // 导航栏高度
    this.setData({
      dataList: pastData,
      questionDataList: pastData.postData.list[indexof].list,
      questionDataTitle: pastData.postData.list[indexof].title,
      questionDataOptions: pastData.postData.list[indexof].optionList,
      scoreDataList: pastData.postData.list[indexof].scoreData
    });
    wx.setNavigationBarTitle({
      title: pastData.postData.list[indexof].name,
    })
    const token = wx.getStorageSync(app.config.tokenKey)
    if (!token) {
      loginInfo(app, (data) => {
        if (data) {
          this.init();
        } else {
          this.init();
        }
      })
    } else {
      this.init()
    }
  },
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {},
  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {
    if (this.data.answerType != "mock") {
      if (wx.timer) {
        clearInterval(wx.timer);
      }
    }
    if (this.data.answerType == "mock") {
      if (wx.timer) {
        clearInterval(wx.timer);
      }
      wx.timer = setInterval(() => {
        this.setData({
          saveTime: this.data.saveTime - 1,
        });
        if (this.data.saveTime == 0) {
          this.saveMockData();
        }
      }, 1000);
    }
    this.setData({
      startTime: Date.now(),
    });
  },
  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {
    if (wx.timer) {
      clearInterval(wx.timer);
    }
    this.setData({
      pauseTime: Date.now(),
    });
    if (wx.getStorageSync(app.config.tokenKey)) {
      let duration = this.data.pauseTime - this.data.startTime;
      this.count(duration);
    }
  },
  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload(e) {
    if (wx.timer) {
      clearInterval(wx.timer);
    }
    if (this.data.countdownInterval !== null) {
      clearInterval(this.data.countdownInterval);
    }
    this.setData({
      pauseTime: Date.now(),
    });
    if (wx.getStorageSync(app.config.tokenKey)) {
      let duration = this.data.pauseTime - this.data.startTime;
      this.count(duration);
    }
  },
  count(timeStr) {
    const data = {
      appRefCode: app.config.appRefCode,
      type: "LearningTime", //统计类型--阅读时长
      data: timeStr + "", //统计内容--时长毫秒
      event: "LearningTime",
      sysType: "App",
    };
    //阅读商品的id
    if (this.data.bookId) {
      data.productId = this.data.bookId;
    }
    //阅读资源的id
    // if (product.cmsItemId) {
    //   data.cmsItemId = product.cmsItemId
    // }
    app.MG.job.newJobWithApiNewEvent(data).then((res) => {});
  },
  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {},
  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {},
  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {},
  onShareTimeline() {},
  // 监听watch
  watch(context, variableName, callback) {
    let value = context.data[variableName]; // 获取被监听属性的当前值
    // 使用 Object.defineProperty 方法在数据对象上定义属性的 getter 和 setter
    Object.defineProperty(context.data, variableName, {
      configurable: true, // 可配置
      enumerable: true, // 可枚举
      get: function () {
        return value; // 返回属性的当前值
      },
      set: function (newVal) {
        const oldVal = value; // 记录属性的旧值
        value = newVal; // 更新属性的值
        callback.call(context, newVal, oldVal); // 调用回调函数,传递新值和旧值
      },
    });
  },
  // 修改nav颜色
  changeNavBarColor(e) {
    if (type == 'night') {
      wx.setNavigationBarColor({
        backgroundColor: '#000000',
        frontColor: '#ffffff',
      })
    } else {
      wx.setNavigationBarColor({
        backgroundColor: '#ffffff',
        frontColor: '#000000',
      })
    }
  },
  // 正则找出听力src
  extractSourceSrc(htmlString) {
    // 正则表达式匹配<source>标签中的src属性值
    var srcRegex = /<source\s+src="([^"]+)"/i;
    var srcTwo = /<audio\s+src="([^"]+)"/i;
    // 执行正则匹配
    var match = srcRegex.exec(htmlString);
    const local = srcTwo.exec(htmlString)
    // 如果匹配成功,返回第一个捕获组的内容(src属性的值)
    if (match && match[1]) {
      return match[1].replace('../file', app.config.requestCtx + '/file');
    } else if (local && local[1]) {
      return local[1].replace('../file', app.config.requestCtx + '/file')
    } else {
      // 如果没有匹配到,返回null
      return null;
    }
  },
  // 拿到听力题除audio标签外其他内容
  removeVideoAndAudioTags(htmlString) {
    // 使用正则表达式匹配并移除所有的 <video> 和 <audio> 标签
    var cleanedHtml = htmlString.replace(/<video[^>]*>[\s\S]*?<\/video>|<audio[^>]*>[\s\S]*?<\/audio>/gi, '');
    return cleanedHtml;
  },
  // 改变loading状态
  changeLoadingState() {
    this.setData({
      loading: true
    })
  },
  // 返回拦截
  beforeleave() {
    if (!this.data.submitStatus) {
      wx.showModal({
        title: "提示",
        content: "未提交,是否退出答题",
        confirmColor: "#ff6c00",
        cancelColor: "#949494",
        complete: (res) => {
          if (res.cancel) {
            this.setData({
              showDialog: true
            })
          }
          if (res.confirm) {
            this.setData({
              submitStatus: true,
              showDialog: false
            });
            wx.navigateBack();
          }
        },
      });
    }
  },
  onChangeSlider(e) {
    this.setData({
      sliderValue: e.detail.value,
    });
    console.log(e.detail.value);
  },
  // 返回
  goBack() {
    console.log(this.data.submitStatus);
    wx.navigateBack();
  },
  //设置背景色
  changeBGColor(e) {
    const flag = e.detail.value
    this.setData({
      isNight: flag,
    });
    if (flag) {
      wx.setNavigationBarColor({
        backgroundColor: '#000000',
        frontColor: '#ffffff',
      })
    } else {
      wx.setNavigationBarColor({
        backgroundColor: '#ffffff',
        frontColor: '#000000',
      })
    }
  },
  // 切换题目
  changeSwiper(e) {
    let index = e.detail.index - 1 >= 0 ? e.detail.index - 1 : 0;
    const item = this.data.questionDataList[index];
    const lastItem = this.data.questionDataList[index + 1];
    this.setData({
      currentIndex: e.detail.index,
      showId: lastItem.id
    });
    if (
      (this.data.answerType == "collectQuestion" ||
        this.data.answerType == "errorQuestion") &&
      !item.isComplete
    ) {
      let flag = this.isHaveAnswer(item.userAnswer);
      if (flag) this.handleQuestion(index);
    }
  },
  // 我的错题,收藏查看解析按钮
  viewParsing() {
    if (
      this.data.answerType == "collectQuestion" ||
      this.data.answerType == "errorQuestion"
    ) {
      const item = this.data.questionDataList[this.data.currentIndex];
      if (!item.isComplete) {
        this.handleQuestion(this.data.currentIndex);
      }
    }
  },
  // 点击答题卡跳转题目
  goQuestion(e) {
    const id = e.detail.id;
    this.data.questionDataList.forEach((item, index) => {
      if (item.id == id) {
        this.setData({
          currentIndex: index,
        });
      }
    });
  },
  handeleOption(e) {
    const id = e.detail.value.currentTarget.dataset.id;
    const radioChecked = e.detail.value.detail.value;
    const questionList = this.data.questionDataList;
    // 我的错题和我的收藏模式下,单选题选择了直接批改
    for (let index = 0; index < questionList.length; index++) {
      const item = questionList[index];
      if (item.id == id && !item.isComplete) {
        if (item.questionType == "linkage") {
          item.questionTab = radioChecked;
          item.userAnswer = "";
        }
      }
    }
    this.setData({
      questionDataList: questionList,
    });
  },
  // 单选 多选 触发
  onChangeRadio(e) {
    const radioData = e.detail.value.currentTarget.dataset.value;
    const id = e.detail.value.currentTarget.dataset.id;
    const radioChecked = e.detail.value.detail.value;
    const questionList = this.data.questionDataList;
    const jumpQuestion = this.data.jumpQuestionList
    const radioChange = (item) => {
      if (!item.jumpData) return false
      if (item.userAnswer == item.jumpData.value) {
        // 选中跳过答题选项 记录并删除跳过的题
        for (let cindex = 0; cindex < item.jumpData.list.length; cindex++) {
          const citem = item.jumpData.list[cindex];
          jumpQuestion.push({
            questionIndex: questionList.findIndex((ditem) => ditem.id == citem),
            data: questionList.find((ditem) => ditem.id == citem),
          })
        }
        this.setData({
          questionDataList: questionList.filter(
            (citem) => !item.jumpData.list.includes(citem.id)
          ),
          jumpQuestionList: jumpQuestion,
        });
        console.log(this.data.questionDataList, "删除后的questionDataList");
      } else {
        // 选中另外的选项,要判断题目列表是否已经删除了题,删除了则加回去
        for (let cindex = 0; cindex < item.jumpData.list.length; cindex++) {
          const citem = item.jumpData.list[cindex]
          if (!questionList.some((ditem) => ditem.id == citem)) {
            const delData = jumpQuestion.find((eitem) => eitem.data.id == citem)
            questionList.splice(delData.questionIndex, 0, delData.data)
          }
        }
        this.setData({
          questionDataList: questionList,
        });
        console.log(this.data.questionDataList, "恢复后的questionDataList");
      }
    }
    for (let index = 0; index < questionList.length; index++) {
      const item = questionList[index];;
      if (item.id == id && !item.isComplete) {
        item.userAnswer = radioChecked;
        item.isUserAnswer = this.isHaveAnswer(radioChecked);
      }
    }
    this.setData({
      questionDataList: questionList,
    });
    // 调用处理方法
    for (let cindex = 0; cindex < questionList.length; cindex++) {
      const citem = questionList[cindex];;
      if (citem.id == id && !citem.isComplete) {
        radioChange(citem)
      }
    }
  },
  // 输入框触发
  onChangeInput(e) {
    const inputData = e.detail.value.detail.value;
    const id = e.detail.value.currentTarget.dataset.id;
    const index = Number(e.detail.value.currentTarget.dataset.index);
    const questionList = this.data.questionDataList;
    questionList.forEach((item) => {
      if (item.id == id) {
        item.userAnswer[index] = inputData;
        return (item.isUserAnswer = this.isHaveAnswer(inputData));
      }
    });
    const cardListUpdata = this.data.cardList;
    cardListUpdata.forEach((item) => {
      item.infoList.forEach((citem) => {
        if (citem.id == id) {
          citem.userAnswer[index] = inputData;
          return (citem.isUserAnswer = this.isHaveAnswer(inputData));
        }
      });
    });
    this.setData({
      questionDataList: questionList,
      cardList: cardListUpdata,
    });
    if (this.data.answerType == "mock") {
      this.setData({
        saveTime: 20,
      });
    }
  },
  // 数组转为字符串方法
  arrayToString(data) {
    // 检查是否为数组
    if (Array.isArray(data)) {
      // 使用 join 方法将数组转换为字符串,默认使用逗号分隔
      return data.join(",").replace(/<[^>]*>/g, "");
    } else {
      // 如果不是数组,直接返回原始值
      return data.replace(/<[^>]*>/g, "");
    }
  },
  // 判断是否有用户答案
  isHaveAnswer(data) {
    if (typeof data == "string") {
      data = data
        .replace(/<[^>]*>/g, "")
        .replace(/&nbsp;/g, "")
        .trim();
      if (data.length) {
        return true;
      } else {
        return false;
      }
    } else if (typeof data == "object") {
      const answer = data.find((item) => item.length > 0);
      if (answer) {
        return true;
      } else {
        return false;
      }
    } else {
      return false;
    }
  },
  // 提交逻辑
  submitPaper() {
    this.setData({
      submitStatus: true,
      loading: true,
    });
    // 先遍历所有题目,将未批改的题目批改
    const qustionList = this.data.questionDataList;
    if (qustionList.length) this.handleQuestion();
    this.setData({
      isShowDialog: true,
      submitStatus: true,
    })
    // 记录用户答题数据
    let saveData = [];
    for (let index = 0; index < this.data.questionDataList.length; index++) {
      const item = this.data.questionDataList[index];
      saveData.push({
        id: item.id,
        answer: item.userAnswer,
        isRight: item.isRight,
      });
    }
    this.setData({
      loading: false,
      showDialog: false,
    });
  },
  // 初始化函数
  async init() {
    this.setData({
      loading: false,
    });
  },
  // 获取题库题目
  async getQuestionList(oldData) {
    // 清空正确题数记录
    this.setData({
      noData: false,
      cardList: [],
      correctNum: 0,
    });
  },
  // 批改题目 (练习,我的错题,我的收藏,,组卷)
  handleQuestion() {
    const questionList = this.data.questionDataList;
    const optionList = this.data.questionDataOptions;
    const scoreData = this.data.scoreDataList;
    for (let index = 0; index < questionList.length; index++) {
      const item = questionList[index];
      if (item.questionType == 'judge' && item.userAnswer) {
        if (optionList && optionList.length) {
          const optionData = optionList[item.optionIndex].find(
            (citem) => citem.value == item.userAnswer
          )
          item.score = optionData.score
        }
      }
      if (item.questionType == 'singleChoice' && item.userAnswer) {
        if (optionList && optionList.length) {
          const optionData = optionList[item.optionIndex].find(
            (citem) => citem.value == item.userAnswer
          )
          item.score = optionData.score
        } else {
          item.score = item.option.find((citem) => citem.value == item.userAnswer).score
        }
      }
      if (item.questionType == 'linkage' && item.userAnswer) {
        if (item.optionData) {
          const optionScore = item.optionData[item.questionTab].find(
            (citem) => citem.value == item.userAnswer
          )
          item.score = optionScore.score
        }
      }
      if (!item.userAnswer) item.score = 0
    }
    //计算各项的总分
    for (let cindex = 0; cindex < scoreData.length; cindex++) {
      const scoreItem = scoreData[cindex];
      if (scoreItem.range == 'all') {
        questionList.forEach((item) => {
          scoreItem.score += item.score
        })
      } else {
        questionList.forEach((item, index) => {
          if (scoreItem.range.includes(index)) scoreItem.score += item.score
        })
      }
      if (scoreItem.isAverage) {
        scoreItem.score = Math.floor(scoreItem.score / scoreItem.range.length)
      }
      if (scoreItem.multiply) {
        scoreItem.score = Math.floor(scoreItem.score * scoreItem.multiply)
      }
    }
    //根据总分给出测试结果(文字)
    for (let dindex = 0; dindex < scoreData.length; dindex++) {
      const scoreItem = scoreData[dindex];
      scoreItem.dispatch = scoreItem.result.find((item) => item.score[0] <= scoreItem.score && item.score[1] >= scoreItem.score).desc
    }
    this.setData({
      scoreDataList: scoreData,
      questionDataList: questionList,
      submitStatus: true,
      dialogState: true,
    });
  },
  // 处理答题数据
  recordAnswerData() {
    this.data.cardList.push({
      name: "客观题得分",
      score: this.data.subjectiveNum,
      path: this.data.productLinkPath,
      // infoList: [],
      // catalogName: ''
    });
    let setInfoData = {
      currentIndex: this.data.currentIndex,
      dataList: JSON.parse(JSON.stringify(this.data.cardList)),
    };
    for (let i = 0; i < setInfoData.dataList.length; i++) {
      const item = setInfoData.dataList[i];
      if (!item.name && !item.name == "客观题得分") {
        for (let j = 0; j < item.infoList.length; j++) {
          let obj = {
            id: item.infoList[j].id,
            userAnswer: item.infoList[j].userAnswer,
            isComplete: item.infoList[j].isComplete,
            isRight: item.infoList[j].isRight,
            isCollect: item.infoList[j].isCollect,
          };
          item.infoList[j] = obj;
        }
      }
    }
    this.setAnswerInfo(setInfoData);
  },
  // 提交答题数据
  setAnswerInfo(data) {
    app.MG.identity
      .setUserKey({
        setKeyRequests: [{
          domain: "answerData",
          key: this.data.productLinkPath,
          value: JSON.stringify(data),
        }, ],
      })
      .then((res) => {});
  },
  // 记录模考答题数据
  saveMockData() {
    const data = this.data.mockData.datas.find(
      (itme) => itme.id == this.data.uuid
    );
    if (data.state == "3") return true;
    const saveData = this.data.mockData.answer;
    for (let i = 0; i < this.data.questionDataList.length; i++) {
      const item = this.data.questionDataList[i];
      if (this.isHaveAnswer(item.userAnswer)) {
        const index = saveData.findIndex((saveitem) => saveitem.id == item.id);
        if (index + "" != "-1") {
          saveData[index].answer = item.userAnswer;
        } else {
          saveData.push({
            id: item.id,
            answer: item.userAnswer,
          });
        }
      }
    }
    //
    if (this.data.mockData.state == "1") {
      const datas = this.data.mockData.datas;
      datas.forEach((item) => {
        if (item.id == this.data.uuid) {
          item.state = "2";
        }
      });
      this.setMockInfo(datas);
    }
    //
    app.MG.identity
      .setUserKey({
        setKeyRequests: [{
          domain: "mockAnswerData",
          key: this.data.uuid,
          value: JSON.stringify({
            currentIndex: this.data.currentIndex,
            time: this.data.countdownTime,
            answerData: saveData,
          }),
        }, ],
      })
      .then((res) => {
        this.setData({
          saveTime: 20,
        });
        console.log("模考答题数据已记录");
      });
  },
  // 富文本处理
  formatRichText(html) {
    console.log(html);
    let newContent = html.replace(/<img[^>]*>/gi, function (match, capture) {
      match = match
        .replace(/style="[^"]+"/gi, "")
        .replace(/style='[^']+'/gi, "");
      match = match
        .replace(/width="[^"]+"/gi, "")
        .replace(/width='[^']+'/gi, "");
      match = match
        .replace(/height="[^"]+"/gi, "")
        .replace(/height='[^']+'/gi, "");
      return match;
    });
    newContent = newContent.replace(
      /style="[^"]+"/gi,
      function (match, capture) {
        match = match
          .replace(/<p>/gi, '<p class="p_class">')
          .replace(/width:[^;]+;/gi, "max-width:100%;")
          .replace(/width:[^;]+;/gi, "max-width:100%;");
        return match;
      }
    );
    newContent = newContent.replace(/<br[^>]*\/>/gi, "");
    newContent = newContent.replace(/<a>/gi, '<a class="p_class "');
    newContent = newContent.replace(/<li>/gi, '<li class="p_class "');
    newContent = newContent.replace(/\<p/gi, '<p class="p_class "');
    newContent = newContent.replace(/\<span/gi, '<span class="p_class "');
    newContent = newContent.replace(
      /\<img/gi,
      '<img style="max-width:100%;height:auto;display:block;margin-top:0;margin-bottom:0;"'
    );
    return newContent;
  },
});
packageBookService/pages/psychologyAnswer/psychologyAnswer.json
New file
@@ -0,0 +1,10 @@
{
  "usingComponents": {
    "question-options": "./questionOptions/index",
    "question-list": "./questionList/index",
    "t-icon": "tdesign-miniprogram/icon/icon",
    "t-image": "tdesign-miniprogram/image/image",
    "t-button": "tdesign-miniprogram/button/button",
    "t-loading": "tdesign-miniprogram/loading/loading"
  }
}
packageBookService/pages/psychologyAnswer/psychologyAnswer.wxml
New file
@@ -0,0 +1,57 @@
<!--packageBookService/pages/psychologyAnswer/psychologyAnswer.wxml-->
<view
  class="page"
  wx:if="{{!loading}}"
  style="background-color:{{isNight ? '#222' : ''}}"
>
  <view class="page-content" style="background-color:{{isNight ? '#222' : ''}}">
    <question-list
      wx:if="{{!loading}}"
      sliderValue="{{sliderValue}}"
      isNight="{{isNight}}"
      currentIndex="{{currentIndex}}"
      questionList="{{questionDataList}}"
      questionTitle="{{questionDataTitle}}"
      questionOptions="{{questionDataOptions}}"
      submitStatus="{{submitStatus}}"
      noData="{{noData}}"
      bind:onChangeRadio="onChangeRadio"
      bind:handeleOption="handeleOption"
      bind:onChangeInput="onChangeInput"
      bind:changeSwiper="changeSwiper"
      bind:viewParsing="viewParsing"
    ></question-list>
  </view>
  <!-- 底部区域-->
  <view
    class="page-bottom"
    style="background-color:{{isNight ? '#202020' : ''}}"
    wx:if="{{answerType !== 'errorQuestion' || (answerType == 'errorQuestion' && !loading)}}"
  >
    <question-options
      id="question-options"
      isShowDialog="{{isShowDialog}}"
      isNight="{{isNight}}"
      submitStatus="{{submitStatus}}"
      currentIndex="{{currentIndex}}"
      questionDataList="{{questionDataList}}"
      showId="{{showId}}"
      scoreData="{{scoreDataList}}"
      bind:setCollect="setCollect"
      bind:submitPaper="submitPaper"
      bind:restart="restart"
      bind:goQuestion="goQuestion"
      bind:changeBGColor="changeBGColor"
      bind:onChangeSlider="onChangeSlider"
      bind:changeLoadingState="changeLoadingState"
      bind:changeNavBarColor="changeNavBarColor"
    ></question-options>
  </view>
</view>
<page-container
  show="{{showDialog}}"
  duration="{{false}}"
  overlay="{{false}}"
  bind:beforeleave="beforeleave"
></page-container>
packageBookService/pages/psychologyAnswer/psychologyAnswer.wxss
New file
@@ -0,0 +1,50 @@
/* packageBookService/pages/psychologyAnswer/psychologyAnswer.wxss */
page {
  padding: 0 !important;
}
.page {
  width: 100%;
  height: 100vh;
}
.nacigationBar {
  display: flex;
  align-items: center;
}
.navbar-title {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: #0F1214;
  font-size: 40rpx;
  font-weight: 600;
}
.lodaing-box {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  --td-loading-color: #ff6c00;
}
.page-content {
  box-sizing: border-box;
  width: 100%;
  height: calc(100vh - env(safe-area-inset-bottom) - 100px);
  padding: 20rpx;
  background-color: #F2F3F8;
}
.daytime {
  background-color: #fff;
  color: #000;
}
.night {
  background-color: #000;
  color: #fff;
}
packageBookService/pages/psychologyAnswer/questionList/index.js
New file
@@ -0,0 +1,153 @@
// pages/bookServices/examination/questionList/index.js
const innerAudioContext = wx.createInnerAudioContext({
  useWebAudioImplement: false
})
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    questionList: {
      type: Array,
      value: []
    },
    questionTitle: {
      type: String,
      value: "",
    },
    questionOptions: {
      type: Array,
      value: []
    },
    submitStatus: {
      type: Boolean,
      value: false
    },
    currentIndex: {
      type: Number,
      value: 1
    },
    isNight: {
      type: Boolean,
      value: false
    },
    sliderValue: {
      type: Number,
    },
    noData: {
      type: Boolean,
    }
  },
  observers: {},
  detached() {
    if (innerAudioContext) {
      innerAudioContext.stop();
      innerAudioContext.destroy();
    }
  },
  /**
   * 组件的初始数据
   */
  data: {
    inputstyle: 'border: 2rpx solid rgba(220,220,220,1);border-radius: 12rpx;',
    shortAnswer: 'font-size: 28rpx',
    placeholderstyle: "font-size:28rpx",
    current: 2,
    autoplay: true,
    duration: 500,
    interval: 5000,
    paginationPosition: 'bottom-right',
    navigation: {
      type: 'fraction'
    },
    showIndex: 0,
    isPlay: false
  },
  /**
   * 组件的方法列表
   */
  methods: {
    audioPlay(e) {
      const src = e.currentTarget.dataset.src
      innerAudioContext.src = src
      if (!this.data.isPlay) {
        innerAudioContext.play()
      } else {
        innerAudioContext.pause()
      }
      this.setData({
        isPlay: !this.data.isPlay
      })
    },
    // 切换题目
    changeSwiper(e) {
      this.setData({
        showIndex: e.detail.current
      })
      var myEventDetail = {
        index: e.detail.current
      }
      var myEventOption = {
        bubbles: true,
        composed: true,
      }
      this.triggerEvent('changeSwiper', myEventDetail, myEventOption)
    },
    // 联动选择题的选中
    handeleOption(e) {
      var myEventDetail = {
        value: e
      } // detail对象,提供给事件监听函数
      var myEventOption = {
        bubbles: true,
        composed: true,
      } // 触发事件的选项
      this.triggerEvent('handeleOption', myEventDetail, myEventOption)
    },
    // 单选  富文本框输入  触发
    onChangeRadio(e) {
      var myEventDetail = {
        value: e
      } // detail对象,提供给事件监听函数
      var myEventOption = {
        bubbles: true,
        composed: true,
      } // 触发事件的选项
      this.triggerEvent('onChangeRadio', myEventDetail, myEventOption)
    },
    // 多选触发
    onChangeCheck(e) {
      var myEventDetail = {
        value: e
      } // detail对象,提供给事件监听函数
      var myEventOption = {
        bubbles: true,
        composed: true,
      } // 触发事件的选项
      this.triggerEvent('onChangeRadio', myEventDetail, myEventOption)
    },
    // 输入框触发
    onChangeInput(e) {
      var myEventDetail = {
        value: e
      } // detail对象,提供给事件监听函数
      var myEventOption = {
        bubbles: true,
        composed: true,
      } // 触发事件的选项
      this.triggerEvent('onChangeInput', myEventDetail, myEventOption)
    },
    // 我的错题,收藏查看解析按钮
    viewParsing() {
      var myEventDetail = {}
      var myEventOption = {
        bubbles: true,
        composed: true,
      }
      this.triggerEvent('viewParsing', myEventDetail, myEventOption)
    }
  }
})
packageBookService/pages/psychologyAnswer/questionList/index.json
New file
@@ -0,0 +1,18 @@
{
  "component": true,
  "usingComponents": {
    "t-swiper": "tdesign-miniprogram/swiper/swiper",
    "t-swiper-nav": "tdesign-miniprogram/swiper-nav/swiper-nav",
    "t-image": "tdesign-miniprogram/image/image",
    "t-input": "tdesign-miniprogram/input/input",
    "t-radio": "tdesign-miniprogram/radio/radio",
    "t-radio-group": "tdesign-miniprogram/radio-group/radio-group",
    "t-checkbox": "tdesign-miniprogram/checkbox/checkbox",
    "t-checkbox-group": "tdesign-miniprogram/checkbox-group/checkbox-group",
    "t-textarea": "tdesign-miniprogram/textarea/textarea",
    "t-empty": "tdesign-miniprogram/empty/empty",
    "t-button": "tdesign-miniprogram/button/button",
    "mp-html": "mp-html",
    "empty": "/components/empty/index"
  }
}
packageBookService/pages/psychologyAnswer/questionList/index.wxml
New file
@@ -0,0 +1,334 @@
<!--pages/bookServices/examination/questionList/index.wxml-->
<view
  class="question-list"
  style="background-color:{{isNight ? '#222' : '#fff'}}"
>
  <!-- 答题提示title -->
  <view class="question-title" wx:if="{{questionTitle}}">
    <text class="title-name">提示:{{questionTitle}}</text>
  </view>
  <!-- 题目列表 -->
  <swiper
    class="swiper"
    bindanimationfinish="changeSwiper"
    current="{{currentIndex}}"
  >
    <swiper-item
      wx:for="{{questionList}}"
      wx:for-index="index"
      wx:key="id"
      style="overflow-y: auto"
    >
      <!-- 题干 -->
      <view
        class="question-stem title-score"
        style="color: {{isNight ? '#fff' : '#000'}}; font-size: {{sliderValue || 32}}rpx;"
      >
        <!-- 题号 -->
        <text>{{index+1}}.</text>
        <!-- 听力题 -->
        <view wx:if="{{item.questionType == 'singleChoice' && item.src}}">
          <rich-text nodes="{{item.stem.stemTxt }}" />
          <view
            style="margin-top: {{item.stem.stemTxt ? '10rpx' : ''}};"
            class="audio-play-box"
            bind:tap="audioPlay"
            data-src="{{item.src}}"
          >
            <image
              src="{{isPlay ? '/static/images/resourceDetailsMyAudio/zanting@2x.png' : '/static/images/resourceDetailsMyAudio/play@2x.png'}}"
              mode="aspectFit"
            ></image>
          </view>
        </view>
        <!-- 仅文字 -->
        <view
          class="title-content text-space"
          wx:elif="{{item.stemStyle == 'Txt' && item.questionType != 'completion'}}"
          >{{item.stem.stemTxt}}</view
        >
        <!-- 仅图片 -->
        <view wx:elif="{{item.stemStyle == 'Image'}}" class="title-content">
          <image src="{{item.stem.stemImage}}" mode="aspectFit" />
        </view>
        <!-- 图片加文字 -->
        <view
          wx:elif="{{item.stemStyle == 'TxtAndImage'}}"
          class="title-content text-space"
        >
          <view>{{item.stem.stemTxt}}</view>
          <image src="{{item.stem.stemImage}}" mode="aspectFit" />
        </view>
        <!-- 富文本 -->
        <view wx:elif="{{item.stemStyle == 'RichText'}} " class="title-content">
          <mp-html content="{{item.stem.stemTxt}}" />
        </view>
        <!-- 填空题 -->
        <view wx:if="{{item.questionType == 'completion'}}">
          <view
            class="completion-box"
            wx:for="{{item.stem}}"
            wx:for-item="inputItem"
            wx:for-index="inputIndex"
            wx:key="inputIndex"
          >
            <t-input
              disabled="{{item.isComplete}}"
              borderless
              bind:change="onChangeInput"
              data-value="{{item.option}}"
              data-id="{{item.id}}"
              data-index="{{inputItem.num}}"
              class="title-input {{isNight ? 'input-night-color' : ''}}"
              style="border: 2rpx solid rgba(220,220,220,1);border-radius: 12rpx;background-color:{{isNight ? '#000' : '#fff'}}; "
              placeholder-style="{{placeholderstyle}}"
              wx:if="{{inputItem.data == 'input'}}"
              placeholder="请输入文字"
              value="{{item.userAnswer[inputItem.num]}}"
            ></t-input>
            <text wx:else class="text-space">{{inputItem}}</text>
          </view>
        </view>
      </view>
      <!-- 答题区域 -->
      <view
        class="question-answer {{item.questionType == 'shortAnswer' ? 'textarea-center' : ''}}"
      >
        <!-- 单选题 -->
        <t-radio-group
          wx:if="{{item.questionType == 'singleChoice' || item.questionType == 'judge'}}"
          defaultValue="{{item.userAnswer}}"
          disabled="{{item.isComplete}}"
          bind:change="onChangeRadio"
          class="radio-group"
          data-id="{{item.id}}"
        >
          <view
            wx:for="{{questionOptions && questionOptions.length ? questionOptions[item.optionIndex] : item.option}}"
            wx:for-item="contentItem"
            wx:for-index="contentIndex"
            wx:key="contentIndex"
          >
            <t-radio
              value="{{contentItem.value}}"
              icon="none"
              placement="right"
              borderless
              style="background-color: {{isNight ? '#222' : '#fff'}}"
            >
              <view
                style="font-size: {{sliderValue || 32}}rpx;"
                class="radio-item {{!submitStatus && item.userAnswer == contentItem.value ? 'radio-active' : isNight ? 'night' :''}} {{item.userAnswer == contentItem.value && submitStatus ?  item.isRight ? 'radio-correct' : 'radio-error' :''}}"
              >
                <!-- 仅文字 -->
                <view wx:if="{{item.optionStyle == 'Txt'}}" class="text-space">
                  {{contentItem.value}}、{{contentItem.txt}}
                </view>
                <!-- 仅图片 -->
                <view wx:if="{{item.optionStyle == 'Image'}}" class="fl-center">
                  <text>{{contentItem.value}}、</text>
                  <image src="{{contentItem.img}}" mode="aspectFit" />
                </view>
                <!-- 文字加图片 -->
                <view
                  wx:if="{{item.optionStyle == 'TxtAndImage'}}"
                  class="fl-center"
                  class="TxtAndImage-box"
                >
                  <text class="text-space">{{contentItem.value}}、</text>
                  <view class="radio-textimg">{{contentItem.txt}}</view>
                  <image src="{{contentItem.img}}" mode="aspectFit" />
                </view>
                <!-- 富文本 -->
                <view
                  wx:if="{{item.optionStyle == 'RichText'}}"
                  class="judge-rich-box"
                >
                  <text>{{contentItem.value}}、</text>
                  <rich-text
                    nodes="{{  contentItem.txt}}"
                    style="display: flex; align-items: center; width: 100%"
                  ></rich-text>
                </view>
              </view>
            </t-radio>
          </view>
        </t-radio-group>
        <view wx:if="{{item.questionType == 'linkage'}}">
          <!-- 特殊题 -->
          <t-radio-group
            defaultValue="{{item.questionTab}}"
            disabled="{{item.isComplete}}"
            bind:change="handeleOption"
            class="radio-group"
            data-value="{{item.questionTab}}"
            data-id="{{item.id}}"
          >
            <view
              wx:if="{{item.optionData}}"
              wx:for="{{item.option}}"
              wx:for-item="contentItem"
              wx:for-index="contentIndex"
              wx:key="contentIndex"
            >
              <t-radio
                value="{{contentItem.value}}"
                icon="none"
                placement="right"
                borderless
                style="background-color: {{isNight ? '#222' : '#fff'}}"
              >
                <view
                  style="font-size: {{sliderValue || 32}}rpx;"
                  class="radio-item {{!submitStatus && item.questionTab == contentItem.value ? 'radio-active' : isNight ? 'night' :''}}"
                >
                  <!-- 仅文字 -->
                  <view class="text-space">
                    {{contentItem.value}}、{{contentItem.txt}}
                  </view>
                </view>
              </t-radio>
            </view>
          </t-radio-group>
          <view class="title-content text-space">{{item.stem.stem}}</view>
          <t-radio-group
            defaultValue="{{item.userAnswer}}"
            disabled="{{item.isComplete}}"
            bind:change="onChangeRadio"
            class="radio-group"
            data-value="{{item.userAnswer}}"
            data-id="{{item.id}}"
          >
            <view
              wx:for="{{item.optionData[item.questionTab]}}"
              wx:for-item="citem"
              wx:for-index="cindex"
              wx:key="cindex"
            >
              <t-radio
                value="{{citem.value}}"
                icon="none"
                placement="right"
                borderless
                style="background-color: {{isNight ? '#222' : '#fff'}}"
              >
                <view
                  style="font-size: {{sliderValue || 32}}rpx;"
                  class="radio-item {{!submitStatus && item.userAnswer == citem.value ? 'radio-active' : isNight ? 'night' :''}}"
                >
                  <!-- 仅文字 -->
                  <view class="text-space">
                    {{citem.value}}、{{citem.txt}}
                  </view>
                </view>
              </t-radio>
            </view>
          </t-radio-group>
        </view>
        <!-- 多选题 -->
        <t-checkbox-group
          class="checkbox-group"
          wx:elif="{{item.questionType == 'multipleChoice'}}"
          t-class="box"
          borderless
          bind:change="onChangeRadio"
          data-value="{{item.option}}"
          data-id="{{item.id}}"
          defaultValue="{{item.userAnswer}}"
        >
          <view
            wx:for="{{item.option}}"
            wx:for-item="contentItem"
            wx:for-index="contentIndex"
            wx:key="contentIndex"
          >
            <t-checkbox
              disabled="{{item.isComplete}}"
              icon="rectangle"
              block="{{false}}"
              class="t-checkbox"
              value="{{contentItem.value}}"
              style="background-color:{{isNight ? '#222' :'#F9F9F9'}}; "
            >
              <!-- 仅文字 -->
              <view
                class="fl-center mh text-space"
                wx:if="{{item.optionStyle == 'Txt'}}"
                style="color:{{ isNight  ? '#fff' : '#000'}};font-size:{{sliderValue || 32}}rpx;"
              >
                <text>{{contentItem.value}}、</text>
                <text class="check-text-box">{{contentItem.txt}}</text>
              </view>
              <!-- 仅图片 -->
              <view
                wx:if="{{item.optionStyle == 'Image'}}"
                class="fl-center mh"
              >
                <text
                  style="color:{{ isNight  ? '#fff' : '#000'}};font-size:{{sliderValue || 32}}rpx;"
                  >{{contentItem.value}}、</text
                >
                <image src="{{contentItem.img}}" mode="aspectFit" />
              </view>
              <!-- 文字加图片 -->
              <view
                wx:if="{{item.optionStyle == 'TxtAndImage'}}"
                class="fl-center mh text-space"
              >
                <text
                  style="color:{{ isNight  ? '#fff' : '#000'}};font-size:{{sliderValue || 32}}rpx;"
                  >{{contentItem.value}}、</text
                >
                <text
                  style="color:{{ isNight  ? '#fff' : '#000'}};font-size:{{sliderValue || 32}}rpx;"
                  >{{contentItem.txt}}</text
                >
                <image
                  src="{{contentItem.img}}"
                  wx:if="{{contentItem.img}}"
                  mode="aspectFit"
                />
              </view>
              <!-- 富文本 -->
              <view
                wx:if="{{item.optionStyle == 'RichText'}}"
                class="check-rich-box mh"
              >
                <text>{{contentItem.value}}、</text>
                <rich-text
                  nodes="{{contentItem.txt}}"
                  class="multipleChoice"
                ></rich-text>
              </view>
            </t-checkbox>
          </view>
        </t-checkbox-group>
        <!-- 简答 翻译 -->
        <t-textarea
          disabled="{{item.isComplete}}"
          value="{{item.userAnswer}}"
          bind:change="onChangeRadio"
          data-value="{{item.option}}"
          data-id="{{item.id}}"
          class="option-textarea {{isNight ? 'textarea-night-color' :''}}"
          wx:elif="{{item.questionType == 'shortAnswer'}}"
          t-class="external-class"
          placeholder="请输入文字"
          bordered
          maxlength="500"
          disableDefaultPadding="{{true}}"
          indicator
          style="background-color:{{isNight ? '#000' : '#fff'}}; "
        />
      </view>
    </swiper-item>
    <swiper-item wx:if="{{noData}}">
      <view class="noData">
        <!-- <t-empty icon="folder-open" description="暂无数据" /> -->
        <empty />
      </view>
    </swiper-item>
  </swiper>
</view>
packageBookService/pages/psychologyAnswer/questionList/index.wxss
New file
@@ -0,0 +1,312 @@
/* pages/bookServices/examination/questionList/index.wxss */
.question-list {
  width: 95%;
  height: calc(100% - 30px);
  padding: 20rpx;
  background-color: #ffffff;
  border-radius: 20rpx;
  margin-top: 20rpx;
}
.question-title {
  font-size: 30rpx;
  margin-bottom: 20rpx;
}
.title-content {
  margin-left: 10rpx;
}
.title-name {
  padding: 6rpx;
  color: #000;
  margin-right: 10rpx;
}
.title-score {
  color: #000;
}
.question-stem {
  font-size: 32rpx;
  font-weight: bold;
  display: flex;
  margin-bottom: 20rpx;
}
.swiper {
  height: 85%;
}
/* 单选题 */
.radio-group {
  margin-top: 20rpx;
  --td-radio-vertical-padding: 12rpx
}
.text-space {
  letter-spacing: 2rpx;
  line-height: 1.5;
}
.radio-item {
  min-height: 100rpx;
  /* 根据需要调整 */
  padding: 0 32rpx;
  display: flex;
  align-items: center;
  /* 垂直居中 */
  justify-content: flex-start;
  /* 如果只需要文本水平靠左对齐 */
  background-color: #F9F9F9;
  box-sizing: border-box;
}
.night {
  background-color: #000;
  color: #ffffff;
}
.radio-active {
  background-color: #fff0e6;
}
.radio-correct {
  background-color: #EAF7EE !important;
}
.radio-error {
  background-color: #FFEBEB !important;
}
.question-stem image {
  width: 300rpx;
  object-fit: contain;
  height: 200rpx;
}
.question-answer image {
  margin: 10rpx 0 10rpx 10rpx;
  width: 180rpx;
  height: 120rpx;
}
.fl-center {
  display: flex;
  align-items: center;
}
.t-checkbox {
  display: flex;
  align-items: center;
  margin-bottom: 20rpx;
  --td-checkbox-icon-checked-color: #ff6c00;
}
/* .t-checkbox {
  display: flex;
  align-items: center;
} */
.completion-box {
  display: inline-block;
  margin-bottom: 15rpx;
}
.t-input--border::after {
  height: 0 !important;
}
.title-input {
  /* display: inline-block; */
  height: 40rpx;
  --td-input-vertical-padding: 16rpx
}
.option-textarea {
  width: 97%;
}
/* 单选 、多选 解析 */
.analysis {
  margin-top: 40rpx;
}
.analysis-answer {
  display: flex;
  /* justify-content: space-between; */
}
.answer-correct {
  color: #1FBC1F;
}
.answer-error {
  color: #EE1818;
}
.marginL {
  margin-left: 40rpx;
}
.answer-center {
  display: flex;
  align-items: center;
}
.answer-text {
  font-size: 40rpx;
}
.answer-correct {
  display: flex;
}
.analysis-title-box {
  display: inline-block;
  white-space: nowrap;
}
.analysis-content {
  display: inline-block
}
.analysis-text {
  display: flex;
  color: #333333;
  font-size: 28rpx;
  margin-top: 20rpx;
}
/* 简单、翻译解析 */
.short-answer-fz {
  font-size: 28rpx;
}
.short-answer-mr {
  margin-top:
    40rpx;
}
.textarea-center {
  display: flex;
  justify-content: center;
  margin-bottom: 30rpx;
}
.input-night-color {
  --td-input-default-text-color: #fff;
}
.textarea-night-color {
  --td-textarea-text-color: rgba(255, 255, 255, 1);
}
.noData {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}
.multipleChoice img {
  width: 40rpx !important;
}
/* .judge-rich-image {
  max-height: 300rpx !important;
} */
.stem-rich-img {
  max-width: 300rpx !important;
  height: auto;
  object-fit: contain;
}
.option-rich-img {
  display: inline-block;
  max-width: 180rpx !important;
  height: auto;
  object-fit: contain;
}
.stem-rich-p {
  letter-spacing: 2rpx;
  line-height: 1.5;
  display: block;
}
.judge-rich-box {
  min-height: 104rpx;
  /* height: 100%; */
  display: flex;
  align-items: center;
}
.t-checkbox {
  display: flex;
  align-items: center;
}
.check-rich-box {
  display: flex;
  align-items: center;
}
.check-rich-box text {
  height: min-content;
}
.audio-play-box {
  margin-left: 10rpx;
  background-color: #e7e7e7;
  display: flex;
  align-items: center;
  width: 70rpx;
  height: 70rpx;
}
.TxtAndImage-box {
  display: flex;
  align-items: center;
  min-height: 144rpx;
}
.radio-textimg {
  height: min-content;
  width: calc(100% - 90rpx);
}
.check-text-box {
  display: inline-block;
  width: calc(100% - 25px);
}
.view-parsing {
  margin-top: 40rpx;
  --td-button-primary-bg-color: #fff;
  --td-button-primary-color: #ff6c00;
  --td-button-primary-active-bg-color: #fff0e6;
  --td-button-primary-border-color: #ff6c00;
  --td-button-primary-active-border-color: #ff6c00;
}
.answer-analysis {
  display: inline-block;
  width: 192rpx;
}
.fl-cl {
  display: flex;
  flex-direction: column;
}
.mh {
  min-height: 104rpx;
}
packageBookService/pages/psychologyAnswer/questionOptions/index.js
New file
@@ -0,0 +1,250 @@
// pages/bookServices/examination/questionOptions/index.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    currentIndex: {
      type: Number,
      value: 0,
    },
    questionDataList: {
      type: Array,
      value: [],
    },
    scoreData: {
      type: Array,
      value: [],
    },
    correctNum: {
      type: Number,
      value: 0,
    },
    submitStatus: {
      type: Boolean,
      value: false,
    },
    isNight: {
      type: Boolean,
      value: false,
    },
    showId: {
      type: String
    },
    isShowDialog: {
      type: Boolean
    }
  },
  /**
   * 组件的初始数据
   */
  data: {
    btnStyle: "width:320rpx;border-radius:60rpx",
    noReady: 0,
    questionCardState: false,
    setUpPopup: false,
    testReportState: false,
    sliderValue: 36,
    useTime: "",
    radioItem: "daytime",
  },
  observers: {
    isShowDialog: function (newValue, oldValue) {
      if (newValue)
        this.setData({
          testReportState: newValue,
        });
    }
  },
  created() {},
  /**
   * 组件的方法列表
   */
  methods: {
    // // 格式化时间
    formatTime(ms) {
      const hours = Math.floor((ms / (1000 * 60 * 60)) % 24)
        .toString()
        .padStart(2, "0");
      const minutes = Math.floor((ms / (1000 * 60)) % 60)
        .toString()
        .padStart(2, "0");
      const seconds = Math.floor((ms / 1000) % 60)
        .toString()
        .padStart(2, "0");
      return `${hours}:${minutes}:${seconds}`;
    },
    // 判断是否输入答案
    isHaveAnswer(data) {
      if (typeof data == "string") {
        data = data
          .replace(/<[^>]*>/g, "")
          .replace(/&nbsp;/g, "")
          .trim();
        if (data.length) {
          return true;
        } else {
          return false;
        }
      } else {
        const answer = data.find((item) => item.length > 0);
        if (answer) {
          return true;
        } else {
          return false;
        }
      }
    },
    setCollect() {
      var myEventDetail = {};
      var myEventOption = {
        bubbles: true,
        composed: true,
      };
      this.triggerEvent("setCollect", myEventDetail, myEventOption);
    },
    // 答题卡按钮
    handlePopup() {
      this.setData({
        questionCardState: true,
      });
    },
    // 答题卡跳转题目
    goQuestion(e) {
      var myEventDetail = {
        id: e.currentTarget.dataset.id,
      };
      var myEventOption = {
        bubbles: true,
        composed: true,
      };
      this.triggerEvent("goQuestion", myEventDetail, myEventOption);
    },
    // 答题卡遮罩层点击
    onVisibleChange(e) {
      this.setData({
        questionCardState: e.detail.visible,
      });
    },
    // 设置按钮
    setUpBtn() {
      this.setData({
        setUpPopup: true,
      });
    },
    // 滑块变化
    onChangeSlider(e) {
      const value = e.detail.value;
      console.log(value);
      this.triggerEvent("onChangeSlider", {
        value
      });
    },
    // 设置遮罩层点击
    onSetUpChange(e) {
      this.setData({
        setUpPopup: e.detail.visible,
      });
    },
    // 设置模式切换
    onRadioChange(e) {
      this.setData({
        radioItem: e.detail.value,
      });
      const value = e.detail.value == "night" ? true : false;
      this.triggerEvent("changeBGColor", {
        value
      });
    },
    // 重做按钮
    resterBtn() {
      wx.showModal({
        title: "提示",
        content: "是否重新开始答题?", //editable如果为true,这就是输入框的内容
        confirmColor: "#ff6c00",
        cancelColor: "#949494",
        editable: false, //是否显示输入框
        success: (res) => {
          if (res.confirm) {
            this.restart();
          }
        },
      });
    },
    // 重做事件
    restart() {
      var myEventDetail = {};
      var myEventOption = {
        bubbles: true,
        composed: true,
      };
      this.triggerEvent("restart", myEventDetail, myEventOption);
    },
    // 还有N道题未做弹窗
    confrimPromptDialog() {
      wx.showToast({
        title: `您还有 ${this.data.noReady}道题未答,请完成所有题目后提交。`,
        icon: 'none',
        duration: 2000
      });
    },
    // 底部提交按钮
    submitBtn() {
      this.setData({
        noReady: 0,
      });
      if (this.properties.submitStatus) return wx.navigateBack();
      this.properties.questionDataList.forEach((item) => {
        if (!this.isHaveAnswer(item.userAnswer)) {
          this.setData({
            noReady: this.data.noReady + 1,
          });
        }
      });
      // 直接走提交逻辑
      if (this.data.noReady > 0) {
        this.confrimPromptDialog();
      } else {
        // 做完了直接执行提交事件
        this.submitPaper();
      }
    },
    // 提交事件
    submitPaper() {
      var myEventDetail = {};
      var myEventOption = {
        bubbles: true,
        composed: true,
      };
      this.triggerEvent("submitPaper", myEventDetail, myEventOption);
    },
    // 打开测试报告弹窗
    openTestReportDialog() {
      this.setData({
        testReportState: true,
      });
    },
    // 关闭测试报告弹窗
    closeTestReportDialog(e) {
      this.setData({
        testReportState: false,
      });
    },
    // 答题时间到
    timeout() {
      wx.showModal({
        title: "提示",
        content: "答题时间已到", //editable如果为true,这就是输入框的内容
        confirmColor: "#ff6c00",
        cancelColor: "#949494",
        editable: false, //是否显示输入框
        showCancel: false,
        success: (res) => {},
      });
      this.submitPaper();
    },
  },
});
packageBookService/pages/psychologyAnswer/questionOptions/index.json
New file
@@ -0,0 +1,13 @@
{
  "component": true,
  "usingComponents": {
    "t-icon": "tdesign-miniprogram/icon/icon",
    "t-image": "tdesign-miniprogram/image/image",
    "t-button": "tdesign-miniprogram/button/button",
    "t-dialog": "tdesign-miniprogram/dialog/dialog",
    "t-popup": "tdesign-miniprogram/popup/popup",
    "t-slider": "tdesign-miniprogram/slider/slider",
    "t-radio": "tdesign-miniprogram/radio/radio",
    "t-radio-group": "tdesign-miniprogram/radio-group/radio-group"
  }
}
packageBookService/pages/psychologyAnswer/questionOptions/index.wxml
New file
@@ -0,0 +1,184 @@
<!--pages/bookServices/examination/questionOptions/index.wxml-->
<view
  class="page-bottom"
  style="color: {{isNight ? '#fff' : '#000'}}; background-color:{{isNight ? '#202020' : '#fff'}}"
>
  <view
    class="li-option"
    bind:tap="handlePopup"
    style="color: {{isNight ? '#fff' : '#000'}};"
  >
    <image
      src="{{isNight ? '/static/images/bookService/examination/datika-w.png' : '/static/images/bookService/examination/questionCard.png'}}"
    />
    答题卡
  </view>
  <view
    class="li-option"
    bind:tap="setUpBtn"
    style="color: {{isNight ? '#fff' : '#000'}};"
  >
    <image
      src="{{isNight ? '/static/images/bookService/examination/setting-w.png' : '/static/images/bookService/examination/setting.png'}}"
    />
    设置
  </view>
  <view class="bottom-submit">
    <t-button
      theme="primary"
      size="large"
      style="{{btnStyle}}"
      bind:tap="submitBtn"
      >{{!submitStatus ? '提交' : '退出'}}</t-button
    >
  </view>
</view>
<!-- 答题卡 -->
<t-popup
  visible="{{questionCardState}}"
  bind:visible-change="onVisibleChange"
  placement="bottom"
>
  <view class="popup-block">
    <view class="popup-header">
      <view class="popup-title">答题卡</view>
    </view>
    <view class="question-explain">
      <view class="explain-answered">
        <text class="answered explain-color-box"></text>
        <text>已答</text>
      </view>
      <view class="explain-un-answered" wx:if="{{!submitStatus}}">
        <text class="un-answered explain-color-box"></text>
        <text>未答</text>
      </view>
    </view>
    <scroll-view scroll-y="{{true}}" class="question-card-list">
      <view class="question-list">
        <view
          bind:tap="goQuestion"
          data-id="{{citem.id}}"
          wx:for="{{questionDataList}}"
          wx:for-item="citem"
          wx:for-index="cindex"
          wx:key="cindex"
          style="border: {{showId == citem.id ? '1px solid #ff6c00' : ''}}"
          class="question-box {{ citem.isUserAnswer ? 'answered' : 'un-answered' }}"
        >
          {{cindex+1}}
        </view>
      </view>
    </scroll-view>
  </view>
</t-popup>
<!-- 设置 -->
<t-popup
  visible="{{setUpPopup}}"
  bind:visible-change="onSetUpChange"
  placement="bottom"
>
  <view class="popup-block set-up-popup">
    <view class="popup-header">
      <view class="popup-title">设置</view>
    </view>
    <!-- 亮度 -->
    <view class="brightness">
      <text>A-</text>
      <view class="brightness-slider">
        <!-- <t-slider
          value="{{sliderValue}}"
          theme="capsule"
          min="{{24}}"
          max="{{100}}"
          step="{{7}}"
          bind:change="onChangeSlider"
        /> -->
        <slider
          value="{{sliderValue}}"
          min="{{28}}"
          max="{{48}}"
          step="{{7}}"
          activeColor="#ff6c00"
          bind:change="onChangeSlider"
        />
      </view>
      <text>A+</text>
    </view>
    <!-- 模式 -->
    <view>
      <t-radio-group
        class="test-radio"
        t-class="horizontal-box"
        value="{{radioItem}}"
        bind:change="onRadioChange"
        style="margin: 0px"
      >
        <view class="card {{radioItem == 'daytime' ? 'card--active' : ''}}">
          <t-radio value="daytime" icon="none" borderless style="height: 100%">
            <view class="radio-content" slot="content">
              <image
                src="{{ radioItem == 'daytime' ? '/static/images/bookService/examination/rijian-click.png' : '/static/images/bookService/examination/rijian.png'}}"
              />
              <text style="color: {{radioItem == 'daytime' ? '#fff':''}};"
                >日间模式</text
              >
            </view>
          </t-radio>
        </view>
        <view class="card {{radioItem == 'night' ? 'card--active' : ''}}">
          <t-radio value="night" icon="none" borderless style="height: 100%">
            <view class="radio-content" slot="content">
              <image
                src="{{ radioItem == 'night' ? '/static/images/bookService/examination/yejian-click.png' : '/static/images/bookService/examination/yejian.png'}}"
              />
              <text style="color: {{radioItem == 'night' ? '#fff':''}};"
                >夜间模式</text
              >
            </view>
          </t-radio>
        </view>
      </t-radio-group>
    </view>
  </view>
</t-popup>
<!-- 测试报告 -->
<t-dialog
  class="test-report"
  visible="{{testReportState}}"
  confirm-btn="{{null}}"
  title="测试报告"
  bind:close="closeTestReportDialog"
>
  <view slot="content" class="test-report">
    <view class="report-content-top">
      <view class="report-li">
        <view class="report-li-left">题目总数:</view>
        <view class="report-li-right">{{questionDataList.length}}道</view>
      </view>
      <view
        wx:for="{{scoreData}}"
        wx:for-item="ditem"
        wx:for-index="dindex"
        wx:key="dindex"
      >
        <view class="report-li">
          <view class="report-li-left">{{ditem.name}}:</view>
          <view class="report-li-right"
            ><text class="score-color">{{ditem.score}}</text> 分</view
          >
        </view>
        <view class="report-li">
          <view class="report-li-left" style="white-space: nowrap">结果:</view>
          <view class="report-li-right"
            ><text class="score-color">{{ditem.dispatch}}</text></view
          >
        </view>
      </view>
    </view>
  </view>
</t-dialog>
packageBookService/pages/psychologyAnswer/questionOptions/index.wxss
New file
@@ -0,0 +1,261 @@
/* pages/bookServices/examination/questionOptions/index.wxss */
.page-bottom {
  display: flex;
  justify-content: space-evenly;
  align-items: center;
  position: fixed;
  bottom: 30rpx;
  width: 100%;
  height: 180rpx;
  /* background-color: red; */
}
.li-option {
  display: flex;
  flex-direction: column;
  align-items: center;
  font-size: 24rpx;
  color: #010101;
}
.li-option image {
  margin-bottom: 16rpx;
}
.page-bottom image {
  width: 36rpx;
  height: 36rpx;
}
.bottom-submit {
  --td-button-primary-bg-color: #ff6c00;
  --td-button-primary-border-color: #FF6C00;
  --td-button-primary-active-bg-color: #ff984d;
  --td-button-primary-active-border-color: #ff984d;
}
/* 答题卡 */
.popup-block {
  width: 100vw;
  height: 700rpx;
  padding-bottom: 100rpx;
  background: #fff;
  border-top-left-radius: 16rpx;
  border-top-right-radius: 16rpx;
}
.popup-header {
  display: flex;
  align-items: center;
  height: 116rpx;
}
.popup-title {
  color: #333;
  flex: 1;
  text-align: center;
  font-weight: 600;
  font-size: 36rpx;
}
.question-card-list {
  padding: 0 20rpx;
  margin-bottom: 100rpx;
  height: 500rpx;
}
.question-title {
  /* margin-top: 40rpx; */
  display: flex;
  align-items: center;
}
.question-explain {
  height: 100rpx;
  padding-right: 40rpx;
  display: flex;
  justify-content: flex-end;
}
.explain-un-answered,
.correct-box,
.error-box {
  margin-left: 80rpx;
}
.explain-answered,
.explain-un-answered,
.correct-box,
.error-box {
  display: flex;
  align-items: center;
}
.explain-color-box {
  width: 30rpx;
  height: 30rpx;
  border-radius: 5rpx;
  display: inline-block;
  margin-right: 10rpx;
}
.color-box {
  display: inline-block;
  width: 8rpx;
  height: 60rpx;
  background-color: #ff6c00;
  border-radius: 0 10rpx 10rpx 0;
}
.title-text {
  color: #333;
  margin-left: 10rpx;
}
.card-box {
  margin-bottom: 50rpx;
}
.card-box:last-child {
  margin-bottom: 100rpx;
}
.question-list {
  margin: 8rpx 0;
  display: flex;
  flex-wrap: wrap;
}
.question-box {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 20rpx 20rpx 0 0;
  width: 120rpx;
  height: 62rpx;
  font-size: 34rpx;
}
.question-box:nth-child(5n) {
  margin-right: 0;
}
.answered {
  background-color: #FF6C00;
  color: #fff;
}
.error-box-color {
  background-color: #EE1818 !important;
  color: #fff !important;
}
.correct-box-color {
  background-color: #1FBC1F !important;
  color: #fff !important;
}
.un-answered {
  background-color: #F1F3F8;
  color: #B4B6BD;
}
/* 设置 */
.set-up-popup {
  height: 400rpx;
}
/* 测试报告 */
.test-report {
  --td-dialog-width: 660rpx
}
.report-content-top {
  padding-top: 40rpx;
}
.report-li {
  display: flex;
  color: #333;
  margin-bottom: 44rpx;
}
.report-li-left {
  width: 192rpx;
}
.report-li-right {
  margin-left: 120rpx;
}
.report-content-bottom {
  --td-button-border-radius: 60rpx;
  --td-button-primary-bg-color: #fff;
  --td-button-primary-color: #ff6c00;
  --td-button-primary-border-color: #ff6c00;
  --td-button-primary-active-bg-color: #fff0e6;
  --td-button-primary-active-border-color: #ff6c00;
}
.correct-color {
  color: #1FBC1F;
}
.error-color {
  color: #EE1818;
}
.score-color {
  color: #ff6c00;
}
.brightness {
  display: flex;
  justify-content: space-evenly;
  align-items: center;
  margin-bottom: 40rpx;
}
.brightness-slider {
  width: 80%;
  --td-slider-active-color: #ff6c00;
}
.test-radio {
  height: 80rpx;
  display: flex;
  justify-content: space-evenly;
  --td-radio-content-font-size: 28rpx;
  --td-radio-vertical-padding: 0
}
.test-radio image {
  width: 34rpx;
  height: 34rpx;
  margin-right: 18rpx;
}
.card {
  position: relative;
  border-radius: 10rpx;
  overflow: hidden;
  box-sizing: border-box;
  /* border: 3rpx solid #ff6c00; */
  --td-radio-content-color: #0F1214;
  --td-radio-bg-color: #EFF0F1;
}
.card--active {
  border-color: #ff6c00;
  --td-radio-bg-color: #ff6c00;
  --td-radio-content-color: #fff;
}
.radio-content {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 300rpx;
  height: 68rpx;
}
packageBookService/pages/psychologyAnswer/testdata/index.js
New file
Diff too large
project.config.json
@@ -135,5 +135,6 @@
    "ignore": [],
    "include": []
  },
  "appid": "wx7f362fe7cb6e0d1f"
  "appid": "wx7f362fe7cb6e0d1f",
  "libVersion": "3.6.3"
}