杨磊
12 小时以前 a460a8094e5e1f3954185b25df0361c3b2d3d948
src/views/chronology/index.vue
@@ -1,9 +1,533 @@
<template>
  <div>年谱</div>
  <div class="page">
    <div class="page-header">
      <p>王永炎院士年谱</p>
    </div>
    <div class="pageBox">
      <div class="tagBox">
        <div class="tagItem">
          <div style="background-color: #87a7b9" class="item-tag"></div>
          <div>期刊</div>
        </div>
        <div class="tagItem">
          <div style="background-color: #c48787" class="item-tag"></div>
          <div>图书</div>
        </div>
        <div class="tagItem">
          <div style="background-color: #6f8f5a" class="item-tag"></div>
          <div>视频</div>
        </div>
        <div class="tagItem">
          <div style="background-color: #b9a587" class="item-tag"></div>
          <div>音频</div>
        </div>
        <div class="tagItem">
          <div style="background-color: #8d77b3" class="item-tag"></div>
          <div>报纸</div>
        </div>
        <div class="tagItem">
          <div style="background-color: #009f9f" class="item-tag"></div>
          <div>其他</div>
        </div>
      </div>
      <div
        class="contentBox"
        element-loading-text="年谱加载中"
        element-loading-spinner="el-icon-loading"
        element-loading-background="rgba(0, 0, 0, 0)"
        v-loading="!showList"
      >
        <div class="chartsBox">
          <div
            class="chartsItemBox"
            v-for="(item, index) in contentList"
            :key="index"
          >
            <div class="chartsItem">
              <div class="item-grad">
                <div
                  class="gradchild"
                  v-for="(citem, cindex) in item.list"
                  :style="{ background: citem.color }"
                  @click.self="showDetail(index, cindex, 1, $event)"
                  :key="cindex"
                >
                  <div
                    class="detailDialog"
                    :style="popupStyle"
                    v-if="citem.showChildDetail"
                  >
                    <div
                      class="closeBtn"
                      @click.stop="closeDetail(index, cindex, 0)"
                    >
                      <i class="el-icon-close"></i>
                    </div>
                    <floatingWindow :info="citem" />
                  </div>
                </div>
              </div>
              <div class="item-circle" @click="showYearWindow(index, 1)"></div>
              <div class="item-text">
                <div class="">
                  {{ item.name.split(",")[0] }}
                </div>
                <div style="margin-top: 10px">
                  {{ item.age }}
                </div>
              </div>
              <div class="yaerWindow" v-if="item.showDetail">
                <div class="closeBtn" @click="closeYearWindow(index, 0)">
                  <i class="el-icon-close"></i>
                </div>
                <yearWindow :info="item" />
              </div>
            </div>
          </div>
        </div>
        <div></div>
      </div>
    </div>
  </div>
</template>
<script>
export default {};
import moment from "moment";
import floatingWindow from "./floatingWindow.vue";
import yearWindow from "./yearWindow.vue";
import { nextTick } from "vue";
import fileApi from "@/assets/js/middleGround/api/file";
import { requestCtx, appRefCode } from "@/assets/js/config";
export default {
  components: {
    floatingWindow,
    yearWindow,
  },
  data() {
    return {
      contentList: [],
      currentYear: null,
      showList: false,
      colorList: {
        journal: "#87a7b9",
        books: "#c48787",
        video: "#6f8f5a",
        audio: "#b9a587",
        newspaper: "#8d77b3",
        other: "#009f9f",
      },
      popupStyle: {
        left: "0",
        top: "0",
      },
    };
  },
  mounted() {
    this.getListData();
  },
  methods: {
    showYearWindow(item, event) {
      console.log(item, "item");
      for (let i = 0; i < this.contentList.length; i++) {
        const item = this.contentList[i];
        this.$set(item, "showDetail", false);
      }
      this.contentList[item].showDetail = true;
    },
    closeYearWindow(item) {
      for (let i = 0; i < this.contentList.length; i++) {
        const item = this.contentList[i];
        this.$set(item, "showDetail", false);
      }
    },
    gotoDetail(item) {},
    getListData() {
      this.MG.resource
        .getItem({
          path: "WYY_chronology",
          fields: {
            year: [],
            age: [],
            eventOverview: [],
            eventPictures: [],
          },
          paging: {
            start: 0,
            size: 999,
          },
        })
        .then(async (res) => {
          console.log(res, "res");
          for (let i = 0; i < res.datas.length; i++) {
            const item = res.datas[i];
            this.$set(item, "showDetail", false);
            const listData = await this.getYearResource(item);
            if (listData.length > 0) {
              this.$set(item, "list", listData);
              for (let j = 0; j < listData.length; j++) {
                const element = listData[j];
                this.$set(element, "showChildDetail", false);
              }
              console.log(item, "item");
            }
          }
          this.contentList = res.datas;
          this.showList = true;
        });
    },
    async getYearResource(item) {
      const endDate = item.year.split("/")[0] + "/12/31 23:59:59";
      const startDate = item.year.split("/")[0] + "/01/01 00:00:00";
      const yearDataList = await this.MG.resource.getItem({
        path: "*",
        queryType: "*",
        fields: {
          "year>=": startDate,
          "year<=": endDate,
          source: [],
          IssueNumber: [],
          author: [],
          authorsUnits: [],
          abstract: [],
          keyWords: [],
          subjectAffiliation: [],
          file: [],
        },
        SysType: "CmsItem",
        paging: {
          start: 0,
          size: 999,
        },
      });
      const filterList = yearDataList.datas.filter((item) => {
        return item.cmsItemType != "chronology" && item.cmsItemType != "AWARD";
      });
      if (filterList && filterList.length > 0) {
        for (let i = 0; i < filterList.length; i++) {
          const item = filterList[i];
          if (item.file) {
            const requestCtx = await this.getResourcePath(item.file);
            console.log(requestCtx, "requestCtx");
            this.$set(item, "fileLink", requestCtx);
          }
          this.$set(item, "showDetail", false);
          this.$set(item, "color", this.colorList[item.cmsItemType]);
        }
      }
      if (filterList.length > 0) {
        console.log(filterList, "filterList");
      }
      return filterList;
    },
    // 获取阿里云加速地址 (视频,音频)
    async getResourcePath(md5) {
      try {
        // 如果返回的数据为空或未定义,则拼接默认下载路径
        return requestCtx + "/file/api/ApiDownload?md5=" + md5;
      } catch (error) {
        // 捕获异常并打印错误日志
        console.error("获取资源路径失败:", error);
        // 返回一个默认值或抛出错误(根据业务需求)
        return requestCtx + "/file/api/ApiDownload?md5=" + md5;
      }
    },
    closeDetail(index, cindex, type) {
      for (let i = 0; i < this.contentList.length; i++) {
        const item = this.contentList[i];
        if (item && item.list?.length > 0) {
          for (let j = 0; j < item.list.length; j++) {
            const citem = item.list[j];
            this.$set(citem, "showChildDetail", false);
          }
        }
      }
      this.contentList[index].list[cindex].showDetail = false;
      console.log(
        this.contentList[index].list,
        "this.contentList[index].list[cindex]"
      );
    },
    showDetail(index, cindex, type, event) {
      const rect = event.target.getBoundingClientRect();
      const screenWidth = window.innerWidth;
      const popupWidth = 542; // 假设弹框宽度为200px
      // 判断触发元素位置
      if (rect.left + rect.width / 2 < screenWidth / 2) {
        // 左侧显示弹框在右侧
        this.popupStyle = {
          left: `${rect.right}px`,
          top: `${rect.bottom - 150}px`,
        };
      } else {
        // 右侧显示弹框在左侧
        this.popupStyle = {
          left: `${rect.left - popupWidth}px`,
          top: `${rect.bottom - 150}px`,
        };
      }
      console.log(this.popupStyle.top, "this.top");
      console.log(this.popupStyle.left, "this.left");
      // if (rect.left - popupWidth < 0) {
      //   // 左侧空间不足时强制右侧显示
      //   this.popupStyle.left = `${rect.right}px`;
      // } else if (rect.right + popupWidth > screenWidth) {
      //   // 右侧空间不足时强制左侧显示
      //   this.popupStyle.left = `${rect.left - popupWidth}px`;
      // }
      for (let i = 0; i < this.contentList.length; i++) {
        const item = this.contentList[i];
        if (item && item.list?.length > 0) {
          for (let j = 0; j < item.list.length; j++) {
            const citem = item.list[j];
            if (citem.showChildDetail) {
              this.contentList[i].list[j].showDetail = false;
              citem.showChildDetail = false;
            }
          }
        }
      }
      if (this.contentList[index].list[cindex].type) {
        this.contentList[index].list[cindex].showChildDetail = true;
      }
    },
  },
};
</script>
<style></style>
<style lang="less" scoped>
.page {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  background-color: #e9e1d4;
  display: flex;
  flex-direction: column;
  overflow: auto;
  font-family: Source Han Sans;
}
.pageBox {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  .tagBox {
    display: flex;
    margin-top: 20px;
    .item-tag {
      width: 20px;
      height: 20px;
      margin-right: 10px;
    }
    .tagItem {
      display: flex;
      line-height: 20px;
      margin-left: 30px;
    }
  }
  .contentBox {
    flex: 1;
    padding-bottom: 100px;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: end;
    overflow: auto;
    ::v-deep .el-loading-spinner .el-loading-text {
      font-size: 14px;
      color: #937950;
    }
    .chartsBox {
      white-space: nowrap;
      padding: 0 80px;
      width: calc(100vw - 400px);
      padding-bottom: 100px;
    }
    // &::-webkit-scrollbar {
    //   width: 0 !important;
    //   height: 0 !important;
    // }
    /* 对于WebKit浏览器和Blink引擎(如Chrome, Opera) */
    ::-webkit-scrollbar {
      width: 4px; /* 滚动条的宽度 */
      height: 16px; /* 滚动条的高度 */
    }
    ::-webkit-scrollbar-track {
      background: #ebe5d6; /* 滚动条轨道的颜色 */
    }
    ::-webkit-scrollbar-thumb {
      background: #b9a587; /* 滚动条滑块的颜色 */
      border-radius: 2px; /* 滚动条滑块的圆角 */
      width: 4px;
    }
    ::-webkit-scrollbar-thumb:hover {
      background: #b9a587; /* 鼠标悬停在滚动条滑块上的颜色 */
    }
  }
}
.page-header {
  height: 9.4%;
  width: 100%;
  text-align: left;
  margin-bottom: 8px;
  border-bottom: 2px solid #937950;
  p {
    padding: 1.6% 0 1.55% 0;
    font-family: Alimama DongFangDaKai;
    font-size: 30px;
    text-indent: 1em;
    border-bottom: 1px solid #937950;
  }
}
.chartsItemBox {
  display: inline-block;
  width: 105px;
  height: 100%;
  position: relative;
  margin-right: 30px;
}
.chartsItem {
  width: 100%;
  height: 100%;
  position: relative;
}
.item-grad {
  width: 80px;
  display: flex;
  flex-wrap: wrap-reverse;
}
.gradchild {
  width: 20px;
  height: 20px;
  margin-top: 2px;
  margin-right: 2px;
  cursor: pointer;
  position: relative;
}
// .gradchild :hover {
//   transform: scale(1.1);
//   z-index: 999;
// }
/* 重置子元素的样式 */
// .gradchild:hover .detailDialog {
//   transform: scale(1);
//   z-index: 999;
// }
.item-circle :hover ::before {
  background-color: #b9a587 !important;
}
.item-circle {
  width: 100%;
  height: 20px;
  margin-top: 20px;
  position: relative;
}
.item-circle::after {
  content: "";
  position: absolute;
  top: 9px;
  display: block;
  width: 135px;
  height: 2px;
  background-color: #b9a587;
  z-index: 1;
}
.item-circle::before {
  content: "";
  display: block;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1px solid #b9a587;
  position: absolute;
  top: 0;
  left: 50%;
  margin-left: -9px;
  z-index: 99;
  background: #fff;
  cursor: pointer;
}
.item-text {
  margin-top: 16px;
  font-size: 18px;
  color: #b9a587;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.detailDialog {
  position: fixed;
  width: 524px;
  z-index: 9999;
  cursor: pointer;
  background: #fff;
  border: 2px solid #cbbeaa;
  box-shadow: 2px 2px 4px 1px rgba(0, 0, 0, 0.5);
}
video {
  border-radius: 10px;
  border: 1px solid #dcdcdc;
  box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.1);
}
.yaerWindow {
  position: absolute;
  left: -54px;
  bottom: 50px;
  width: 700px;
  z-index: 9999;
  cursor: pointer;
  background: #fff;
  border: 2px solid #cbbeaa;
  box-shadow: 2px 2px 4px 1px rgba(0, 0, 0, 0.5);
}
// .detailDialog .dialogContent {
//   width: 100%;
//   height: 100%;
//   background-color: #fff;
//   position: relative;
//   padding: 5px;
//   z-index: 20;
//   box-sizing: border-box;
// }
.closeBtn {
  position: absolute;
  width: 20px;
  height: 20px;
  top: 10px;
  right: 5px;
  z-index: 999;
}
::v-deep .el-loading-spinner {
  .el-loading-text {
    font-size: 14px;
    color: #937950;
  }
  .el-icon-loading {
    font-size: 14px;
    color: #937950;
  }
}
</style>