zhongshujie
昨天 c8daf100bf448c0c5abebe73f1dbc9b61cedc7a7
修改
2个文件已修改
465 ■■■■■ 已修改文件
src/views/achievements/details.vue 453 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/achievements/index.vue 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/achievements/details.vue
@@ -7,7 +7,9 @@
      <ul class="page-main">
        <li class="page-main-name">
          <p>
            <el-button icon="el-icon-arrow-left" @click="goBack()">返回</el-button>
            <el-button icon="el-icon-arrow-left" @click="goBack()"
              >返回</el-button
            >
          </p>
          <p>{{ details.name }}</p>
        </li>
@@ -20,38 +22,76 @@
        </li>
        <li class="page-main-title">
          <p>
            <span v-for="(item, index) in details.author" :key="index">{{ item }}</span>
            <span v-for="(item, index) in details.author" :key="index">{{
              item
            }}</span>
          </p>
          <p v-if="details.cleanAbstract">
            <span class="abstract-title">摘要:</span>
            <span class="page-main-abstract-main" v-html="details.cleanAbstract"></span>
            <span
              class="page-main-abstract-main"
              v-html="details.cleanAbstract"
            ></span>
          </p>
          <p v-if="details.keyWords && details.keyWords.length > 0">
            <span>关键词:</span>
            <span class="page-main-keyword" v-for="(item, index) in details.keyWords" :key="index">{{ item
            }}</span>
            <span
              class="page-main-keyword"
              v-for="(item, index) in details.keyWords"
              :key="index"
              >{{ item }}</span
            >
          </p>
          <p v-if="details.cmsItemType != 'video' && details.cmsItemType != 'audio'">
          <p
            v-if="
              details.cmsItemType != 'video' && details.cmsItemType != 'audio'
            "
          >
            <el-button @click="openPdf(details.name)">查看全文</el-button>
          </p>
          <p class="page-main-video" v-if="details.cmsItemType == 'video'">
            <video :src="details.src" controls autoplay class="video" width="70%"></video>
            <video
              :src="details.src"
              controls
              autoplay
              class="video"
              width="70%"
            ></video>
          </p>
          <p class="page-main-audio" v-if="details.cmsItemType == 'audio'">
            <audio :src="details.src" controls autoplay class="video" width="100%"></audio>
            <audio
              :src="details.src"
              controls
              autoplay
              class="video"
              width="100%"
            ></audio>
          </p>
        </li>
        <li class="page-main-literature">
          <p class="literature-header">相关文献</p>
          <div class="content-right" v-loading="loading" element-loading-text="检索结果加载中"
            element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0)">
          <div
            class="content-right"
            v-loading="loading"
            element-loading-text="检索结果加载中"
            element-loading-spinner="el-icon-loading"
            element-loading-background="rgba(0, 0, 0, 0)"
          >
            <!-- 结果展示 -->
            <ul class="right-main" v-for="(item, index) in resultList" :key="index">
            <ul
              class="right-main"
              v-for="(item, index) in resultList"
              :key="index"
              @click="goPage(item.id)"
            >
              <li class="main-name">
                <p>{{ item.name }}</p>
                <p>
                  <el-button @click="goPage(item.id)">详情</el-button>
                  <el-button>AI智能阅读</el-button>
                  <!-- <el-button>详情</el-button> -->
                  <el-button
                    @click.stop="openAiReading(item.AIReading, item.name)"
                    >AI智能阅读</el-button
                  >
                </p>
              </li>
              <li class="main-sources">
@@ -63,13 +103,27 @@
              <li class="main-author">
                {{ item.author }}
              </li>
              <li class="main-title" :title="item.abstract" v-if="item.cleanAbstract">
              <li
                class="main-title"
                :title="item.cleanAbstract"
                v-if="item.cleanAbstract"
              >
                <span>摘要: </span>
                <span class="page-main-abstract" v-html="item.cleanAbstract"></span>
                <span
                  class="page-main-abstract"
                  v-html="item.cleanAbstract"
                ></span>
              </li>
              <li class="main-keyword" v-if="item.keyWords && item.keyWords.length > 0">
              <li
                class="main-keyword"
                v-if="item.keyWords && item.keyWords.length > 0"
              >
                <span>关键词:</span>
                <span class="keyWord" v-for="(citem, cindex) in item.keyWords" :key="cindex">
                <span
                  class="keyWord"
                  v-for="(citem, cindex) in item.keyWords"
                  :key="cindex"
                >
                  {{ citem }}
                </span>
              </li>
@@ -79,16 +133,58 @@
      </ul>
    </div>
    <el-empty v-if="!loading && details == ''"></el-empty>
    <el-dialog v-model="dialogVisible" :title="pdfName" width="60vw" top="3vh" bottom="2vh"
      :visible.sync="dialogVisible" class="custom-dialog">
      <div class="pdfInfoBox" v-loading="pdfLoading" element-loading-text="图片加载中"
        element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0)">
        <div v-for="(item, index) in pdfList" :key="index" class="pdfItem" :page="index + 1">
          <img :src="item.showSrc" alt="" style="min-height: 550px" loading="lazy" />
          <el-divider content-position="center"> 第 {{ index + 1 }} 页 </el-divider>
    <el-dialog
      v-model="dialogVisible"
      :title="pdfName"
      width="60vw"
      top="3vh"
      bottom="2vh"
      :visible.sync="dialogVisible"
      class="custom-dialog"
    >
      <div
        class="pdfInfoBox"
        v-loading="pdfLoading"
        element-loading-text="图片加载中"
        element-loading-spinner="el-icon-loading"
        element-loading-background="rgba(0, 0, 0, 0)"
      >
        <div
          v-for="(item, index) in pdfList"
          :key="index"
          class="pdfItem"
          :page="index + 1"
        >
          <img
            :src="item.showSrc"
            alt=""
            style="min-height: 550px"
            loading="lazy"
          />
          <el-divider content-position="center">
            第 {{ index + 1 }} 页
          </el-divider>
        </div>
      </div>
      <el-empty v-if="!pdfLoading && !pdfList.length"></el-empty>
    </el-dialog>
    <el-dialog
      v-model="dialogVisibleAI"
      :title="aIName"
      width="60vw"
      top="3vh"
      bottom="2vh"
      :visible.sync="dialogVisibleAI"
      class="custom-dialog"
    >
      <div
        class="AIReadingBox"
        element-loading-spinner="el-icon-loading"
        element-loading-background="rgba(0, 0, 0, 0)"
      >
        <div class="richTextInitBox" v-if="AIReading" v-html="AIReading"></div>
        <div class="richTextInitError" v-else>网络繁忙,请稍后再试。</div>
      </div>
    </el-dialog>
  </div>
</template>
@@ -101,6 +197,9 @@
export default {
  data() {
    return {
      dialogVisibleAI: false,
      aIName: "",
      AIReading: "",
      observer: null,
      pdfName: "",
      dialogVisible: false,
@@ -165,62 +264,61 @@
    if (this.details.keyWords && this.details.keyWords.length) {
      for (let i = 0; i < this.details.keyWords.length; i++) {
        const item = this.details.keyWords[i];
        this.inputValue = item
        this.inputType = "keyWords"
        await this.getItemListOne()
        this.inputValue = item;
        this.inputType = "keyWords";
        await this.getItemListOne();
      }
      this.loading = false;
      console.log(this.resultList, "处理好的");
    } else {
      this.getItemList()
      this.getItemList();
    }
    if (this.resultList.length == 0) {
      this.getItemList()
      this.getItemList();
    }
    //处理文件
    if (this.details.cmsItemType == "video" || this.details.cmsItemType == "audio") {
    if (
      this.details.cmsItemType == "video" ||
      this.details.cmsItemType == "audio"
    ) {
      if (this.details.file != "") {
        this.details.src = await this.getResourcePath(this.details.file)
        this.details.src = await this.getResourcePath(this.details.file);
        console.log(this.details.src, "视频地址");
      }
    }
    this.observer = new IntersectionObserver(this.pageChangeCallback, {
      root: null, // 指定根元素,这里设为 null,表示选取整个视窗作为根元素。
      rootMargin: '0px', // 指定根元素的边界,这里设为 "0px",表示根元素的边界和视窗的边界重合
      threshold: 0.1 // 指定交叉比例,这里设为 0.5,表示当目标元素一半或更多显示在视窗中时触发回调函数。
    })
      rootMargin: "0px", // 指定根元素的边界,这里设为 "0px",表示根元素的边界和视窗的边界重合
      threshold: 0.1, // 指定交叉比例,这里设为 0.5,表示当目标元素一半或更多显示在视窗中时触发回调函数。
    });
  },
  methods: {
    // 根据id请求该页面数据
    async getContent(id) {
      this.loading = true;
      const res = await MG.resource
        .getItem({
          path: "*",
          queryType: "*",
          fields: {
            cmsType: ["cmsItem"],
            "Id=": [id + ""],
            source: [],
            isbn: [],
            year: [],
            abstract: [],
            keyWords: [],
            author: [],
            DOI: [],
            AIReading: [],
            file: [],
            IssueNumber: [],
          },
        })
      const res = await MG.resource.getItem({
        path: "*",
        queryType: "*",
        fields: {
          cmsType: ["cmsItem"],
          "Id=": [id + ""],
          source: [],
          isbn: [],
          year: [],
          abstract: [],
          keyWords: [],
          author: [],
          DOI: [],
          AIReading: [],
          file: [],
          IssueNumber: [],
        },
      });
      res.datas.forEach((item) => {
        item.year = moment(item.year).format("YYYY-MM-DD")
        if (typeof item.keyWords === 'string') {
        item.year = moment(item.year).format("YYYY-MM-DD");
        if (typeof item.keyWords === "string") {
          item.keyWords = item.keyWords.split(";;");
        } else {
          // 设置一个默认值或者进行其他错误处理
@@ -233,10 +331,12 @@
          item.cleanAbstract = item.abstract.replace(/<[^>]+>/g, "");
        }
        const foundItem = this.category.list.find((citem) => citem.value == item.cmsItemType);
        item.resourceTypeName = foundItem ? foundItem.name : '';
      })
      this.details = res.datas[0]
        const foundItem = this.category.list.find(
          (citem) => citem.value == item.cmsItemType
        );
        item.resourceTypeName = foundItem ? foundItem.name : "";
      });
      this.details = res.datas[0];
    },
    // 在此点击详情
@@ -248,30 +348,33 @@
      if (this.details.keyWords && this.details.keyWords.length) {
        for (let i = 0; i < this.details.keyWords.length; i++) {
          const item = this.details.keyWords[i];
          this.inputValue = item
          this.inputType = "keyWords"
          this.getItemListOne()
          this.inputValue = item;
          this.inputType = "keyWords";
          this.getItemListOne();
        }
      } else {
        this.getItemList()
        this.getItemList();
      }
      if (this.resultList.length == 0) {
        this.getItemList()
        this.getItemList();
      }
      //处理文件
      if (this.details.cmsItemType == "video" || this.details.cmsItemType == "audio") {
      if (
        this.details.cmsItemType == "video" ||
        this.details.cmsItemType == "audio"
      ) {
        if (this.details.file != "") {
          this.details.src = await this.getResourcePath(this.details.file)
          this.details.src = await this.getResourcePath(this.details.file);
        }
      }
      // 滚动到页面顶部
      this.$nextTick(() => {
        const pageMain = document.querySelector('.page-main-father');
        const pageMain = document.querySelector(".page-main-father");
        if (pageMain) {
          pageMain.scrollTo({
            top: 0,
            behavior: 'smooth'
            behavior: "smooth",
          });
        }
      });
@@ -308,42 +411,48 @@
    // 获取相关资源
    async getPDFInfo(md5) {
      const res = await this.MG.file.getPdfInfo({
        md5
      })
      if (!res || !res.totalPages) return (this.pdfList = [])
        md5,
      });
      if (!res || !res.totalPages) return (this.pdfList = []);
      for (let index = 0; index < res.totalPages; index++) {
        const src =
          requestCtx + '/file/GetPdfPageImage?md5=' + md5 + '&index=' + (index + 1) + '&dpi=300' + '&width=800'
          requestCtx +
          "/file/GetPdfPageImage?md5=" +
          md5 +
          "&index=" +
          (index + 1) +
          "&dpi=300" +
          "&width=800";
        this.pdfList.push({
          src,
          showSrc: ''
        })
          showSrc: "",
        });
      }
      this.pdfLoading = false;
      // 启动页码观察
      setTimeout(() => {
        this.initObservation()
      }, 500)
        this.initObservation();
      }, 500);
    },
    initObservation() {
      const sections = document.querySelectorAll('.pdfItem')
      const sections = document.querySelectorAll(".pdfItem");
      sections.forEach((section) => {
        // observer 观察每个元素,以便在它们进入或离开视窗时触发回调函数。
        const isObserver = section.getAttribute('observer')
        const isObserver = section.getAttribute("observer");
        if (!isObserver) {
          this.observer.observe(section)
          this.observer.observe(section);
          section.setAttribute('observer', '1')
          section.setAttribute("observer", "1");
        }
      })
      });
      // 预加载前几页资源
      const preloadPages = 3
      const preloadPages = 3;
      for (let i = 0; i < Math.min(preloadPages, sections.length); i++) {
        const section = sections[i]
        const page = section.getAttribute('page')
        if (this.pdfList[page - 1].showSrc == '') {
          this.pdfList[page - 1].showSrc = this.pdfList[page - 1].src
        const section = sections[i];
        const page = section.getAttribute("page");
        if (this.pdfList[page - 1].showSrc == "") {
          this.pdfList[page - 1].showSrc = this.pdfList[page - 1].src;
        }
      }
    },
@@ -353,17 +462,15 @@
      entries.forEach((entry) => {
        //entry.isIntersecting:检查当前目标元素是否与根元素相交。
        if (entry.isIntersecting) {
          const target = entry.target
          const target = entry.target;
          //entry.target:获取当前目标元素
          const page = target.getAttribute('page')
          if (this.pdfList[page - 1].showSrc == '') {
            this.pdfList[page - 1].showSrc = this.pdfList[page - 1].src
          const page = target.getAttribute("page");
          if (this.pdfList[page - 1].showSrc == "") {
            this.pdfList[page - 1].showSrc = this.pdfList[page - 1].src;
          }
        }
      })
      });
    },
    //获取下拉选择框的内容
    async getSelectData() {
@@ -375,10 +482,9 @@
        this.category.list = resourceListResult.option;
        if (this.category.list && this.category.list.length) {
          this.category.list.forEach((item) => {
            this.resourceTypeValueList.push(item.value)
            this.resourceTypeValueList.push(item.value);
          });
        }
      } catch (error) {
        console.error("获取下拉框数据失败:", error);
      }
@@ -392,7 +498,8 @@
        .then((res) => {
          const selestList = JSON.parse(res[0].config);
          return selestList;
        }).catch((error) => {
        })
        .catch((error) => {
          console.error("获取选择内容失败:", error);
          return null;
        });
@@ -401,19 +508,25 @@
    // 复制一份
    async getItemListOne() {
      let searchData = {}; // 初始化一个空对象来存储搜索数据
      if (this.inputValue) { // 如果输入值存在
        if (this.inputType != "all") { // 如果输入类型不是"all"
      if (this.inputValue) {
        // 如果输入值存在
        if (this.inputType != "all") {
          // 如果输入类型不是"all"
          // 将输入值与输入类型关联,并添加一个星号(*)作为后缀
          searchData[this.inputType + "*"] = this.inputValue;
        } else { // 如果输入类型是"all"
        } else {
          // 如果输入类型是"all"
          // 遍历输入选项
          for (let index = 0; index < this.inputOptions.length; index++) {
            const item = this.inputOptions[index]; // 获取当前选项
            if (item.value !== "all") { // 如果当前选项的值不是"all"
              if (!Object.keys(searchData).length) { // 如果searchData是空的
            if (item.value !== "all") {
              // 如果当前选项的值不是"all"
              if (!Object.keys(searchData).length) {
                // 如果searchData是空的
                // 将第一个选项的值与输入值关联,并添加一个星号(*)作为后缀
                searchData[item.value + "*"] = this.inputValue;
              } else { // 如果searchData不是空的
              } else {
                // 如果searchData不是空的
                // 使用"||"作为前缀,将后续选项的值与输入值关联,并添加一个星号(*)作为后缀
                // 这通常用于构建一个逻辑或(OR)查询
                searchData["||" + item.value + "*"] = this.inputValue;
@@ -422,33 +535,32 @@
          }
        }
      }
      const res = await MG.resource
        .getItem({
          path: "*",
          queryType: "*",
          paging: {
            size: 99999
          },
          fields: {
            cmsType: ["cmsItem"],
            // 'id=':[this.$route.params.key],
            "resourceType*": this.resourceTypeValueList,
            source: [],
            isbn: [],
            year: [],
            abstract: [],
            keyWords: [],
            author: [],
            DOI: [],
            AIReading: [],
            file: [],
            IssueNumber: [],
            ...searchData,
          },
        })
      const res = await MG.resource.getItem({
        path: "*",
        queryType: "*",
        paging: {
          size: 99999,
        },
        fields: {
          cmsType: ["cmsItem"],
          // 'id=':[this.$route.params.key],
          "resourceType*": this.resourceTypeValueList,
          source: [],
          isbn: [],
          year: [],
          abstract: [],
          keyWords: [],
          author: [],
          DOI: [],
          AIReading: [],
          file: [],
          IssueNumber: [],
          ...searchData,
        },
      });
      res.datas.forEach((item) => {
        item.year = moment(item.year).format("YYYY-MM-DD")
        if (typeof item.keyWords === 'string') {
        item.year = moment(item.year).format("YYYY-MM-DD");
        if (typeof item.keyWords === "string") {
          item.keyWords = item.keyWords.split(";;");
        } else {
          // 设置一个默认值或者进行其他错误处理
@@ -457,11 +569,17 @@
        if (item.abstract) {
          item.cleanAbstract = item.abstract.replace(/<[^>]+>/g, "");
        }
        const foundItem = this.category.list.find((citem) => citem.value == item.cmsItemType);
        item.resourceTypeName = foundItem ? foundItem.name : '';
        const foundItem = this.category.list.find(
          (citem) => citem.value == item.cmsItemType
        );
        item.resourceTypeName = foundItem ? foundItem.name : "";
        console.log(this.details.id, "");
        if (!this.resultList.find(citem => citem.id === item.id) && item.id != this.details.id && this.resultList.length < 11) {
        if (
          !this.resultList.find((citem) => citem.id === item.id) &&
          item.id != this.details.id &&
          this.resultList.length < 11
        ) {
          this.resultList.push(item);
        }
      });
@@ -469,7 +587,7 @@
    async openPdf(name) {
      this.pdfLoading = true;
      this.pdfList = []
      this.pdfList = [];
      this.pdfName = name;
      this.dialogVisible = true;
      await this.getPDFInfo(this.details.file);
@@ -482,7 +600,7 @@
          path: "*",
          queryType: "*",
          paging: {
            size: 5
            size: 5,
          },
          fields: {
            cmsType: ["cmsItem"],
@@ -501,8 +619,8 @@
        })
        .then((res) => {
          res.datas.forEach((item) => {
            item.year = moment(item.year).format("YYYY-MM-DD")
            if (typeof item.keyWords === 'string') {
            item.year = moment(item.year).format("YYYY-MM-DD");
            if (typeof item.keyWords === "string") {
              item.keyWords = item.keyWords.split(";;");
            } else {
              // 设置一个默认值或者进行其他错误处理
@@ -511,12 +629,16 @@
            if (item.abstract) {
              item.cleanAbstract = item.abstract.replace(/<[^>]+>/g, "");
            }
            const foundItem = this.category.list.find((citem) => citem.value == item.cmsItemType);
            item.resourceTypeName = foundItem ? foundItem.name : '';
          })
          this.resultList = res.datas
            const foundItem = this.category.list.find(
              (citem) => citem.value == item.cmsItemType
            );
            item.resourceTypeName = foundItem ? foundItem.name : "";
          });
          this.resultList = res.datas;
          this.loading = false;
        }).catch((err) => {
        })
        .catch((err) => {
          console.log("替换数据请求失败");
        });
    },
@@ -524,13 +646,19 @@
    //去重
    uniqueById(array) {
      const uniqueItems = new Map();
      array.forEach(item => {
      array.forEach((item) => {
        if (!uniqueItems.has(item.id)) {
          uniqueItems.set(item.id, item);
        }
      });
      return Array.from(uniqueItems.values());
    }
    },
    openAiReading(text, name) {
      this.AIReading = text;
      this.aIName = name;
      this.dialogVisibleAI = true;
    },
  },
};
</script>
@@ -578,7 +706,6 @@
  padding-top: 2%;
  padding-bottom: 2%;
}
.page-main {
  background-color: #fcfaf3;
@@ -699,7 +826,6 @@
        font-size: 14px;
        color: #333333;
      }
    }
    p:nth-child(3) {
@@ -743,7 +869,8 @@
    display: flex;
    justify-content: center;
    audio {}
    audio {
    }
  }
  .page-main-literature {
@@ -818,11 +945,15 @@
        }
      }
      .right-main {
        margin-bottom: 20px;
        padding: 19px 30px 15px 30px;
        border: 1px solid #decaac;
        &:hover {
          cursor: pointer;
          border: 1px solid #937950;
        }
        .main-name {
          display: flex;
@@ -854,7 +985,6 @@
            background-color: #87a8b9;
            color: #fff;
            margin-right: 10px;
          }
          span:nth-child(2) {
@@ -863,7 +993,6 @@
            font-weight: 350;
            padding-right: 10px;
            color: #333;
          }
          span:nth-child(3) {
@@ -931,7 +1060,6 @@
          }
          .keyWord {
            padding: 5px 10px;
            color: #937950;
            border: 1px solid #937950;
@@ -947,7 +1075,6 @@
  }
}
.pdfInfoBox {
  height: 85vh;
  margin-top: 20px;
@@ -961,6 +1088,23 @@
    box-shadow: 0px 0px 10px 1px rgba(0, 0, 0, 0.1);
    object-fit: contain;
  }
}
.AIReadingBox {
  height: 85vh;
  min-height: 600px;
  padding: 20px 10px;
}
.richTextInitBox {
  height: 100%;
  overflow: auto;
}
.richTextInitError {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
::v-deep .el-loading-spinner {
@@ -1000,7 +1144,6 @@
      }
    }
    .el-dialog__title,
    .el-dialog__headerbtn .el-dialog__close {
      color: #fff;
@@ -1009,4 +1152,4 @@
    }
  }
}
</style>
</style>
src/views/achievements/index.vue
@@ -224,12 +224,13 @@
              class="right-main"
              v-for="(item, index) in resultList"
              :key="index"
              @click ="goPage(item.id)"
            >
              <li class="main-name">
                <p>{{ item.name }}</p>
                <p>
                  <el-button @click="goPage(item.id)">详情</el-button>
                  <el-button @click="openAiReading(item.AIReading, item.name)"
                  <!-- <el-button >详情</el-button> -->
                  <el-button @click.stop="openAiReading(item.AIReading, item.name)"
                    >AI智能阅读</el-button
                  >
                </p>
@@ -265,7 +266,7 @@
                  class="keyWord"
                  v-for="(citem, cindex) in item.keyWords"
                  :key="cindex"
                  @click="
                  @click.stop="
                    () =>
                      handleSearch({
                        text: citem,
@@ -1325,6 +1326,11 @@
      padding: 19px 30px 15px 30px;
      border: 1px solid #decaac;
      &:hover {
        cursor: pointer;
        border: 1px solid #937950;
      }
      .main-name {
        display: flex;
        align-items: center;