chenlei 1 개월 전
부모
커밋
73af201e41
100개의 변경된 파일1717개의 추가작업 그리고 48개의 파일을 삭제
  1. 245 0
      packages/base/src/constants.js
  2. 1 0
      packages/base/src/index.js
  3. BIN
      packages/base/story/1936年6月报纸刊登固北县成立.png
  4. BIN
      packages/base/story/1945年5月韩练成(左)部署国民党第46军参加桂柳追击战.png
  5. BIN
      packages/base/story/一大队大队长杨得志.png
  6. BIN
      packages/base/story/一大队政委肖华.png
  7. BIN
      packages/base/story/中共固原县委旧址.png
  8. BIN
      packages/base/story/五大队政委赖传珠.png
  9. BIN
      packages/base/story/四大队大队长王开湘.png
  10. BIN
      packages/base/story/四大队政委杨成武.png
  11. BIN
      packages/base/story/固北县苏维埃政府刷写的标语.png
  12. BIN
      packages/base/story/固原县城残破废弃的城墙窑洞.png
  13. BIN
      packages/base/story/毛泽东10月5日晚在单家集张崇德家里住过的房屋.png
  14. BIN
      packages/base/story/毛泽东10月7日晚在张有仁家住过的窑洞旧貌.png
  15. BIN
      packages/base/story/毛泽东10月8日晚在乔家渠的宿营旧址.png
  16. BIN
      packages/base/story/红军长征青石嘴战斗纪念碑.png
  17. BIN
      packages/base/story/苏维埃政府旧址.png
  18. BIN
      packages/base/story/西北军区司令部合影.png
  19. BIN
      packages/base/story/青石嘴战斗遗址.png
  20. BIN
      packages/base/story/韩练成.png
  21. BIN
      packages/base/story/韩练成迁居陕西临潼留影.png
  22. 4 1
      packages/mobile/package.json
  23. 1 1
      packages/mobile/src/App.vue
  24. BIN
      packages/mobile/src/assets/images/back.png
  25. BIN
      packages/mobile/src/assets/images/bg-min.jpg
  26. BIN
      packages/mobile/src/assets/images/close.png
  27. BIN
      packages/mobile/src/assets/images/left.png
  28. BIN
      packages/mobile/src/assets/images/logo-min.png
  29. BIN
      packages/mobile/src/assets/images/right.png
  30. 121 0
      packages/mobile/src/components/DetailPopup.vue
  31. 104 0
      packages/mobile/src/components/SharePopup.vue
  32. 51 0
      packages/mobile/src/components/VideoPopup.vue
  33. 25 0
      packages/mobile/src/router/index.js
  34. 25 0
      packages/mobile/src/stores/base.js
  35. BIN
      packages/mobile/src/views/Antique/images/search.png
  36. BIN
      packages/mobile/src/views/Antique/images/tab1-ac-min.png
  37. BIN
      packages/mobile/src/views/Antique/images/tab1-min.png
  38. BIN
      packages/mobile/src/views/Antique/images/tab2-ac-min.png
  39. BIN
      packages/mobile/src/views/Antique/images/tab2-min.png
  40. 135 0
      packages/mobile/src/views/Antique/index.scss
  41. 69 0
      packages/mobile/src/views/Antique/index.vue
  42. 52 0
      packages/mobile/src/views/History/components/Panel.vue
  43. BIN
      packages/mobile/src/views/History/images/bg2-min.jpg
  44. BIN
      packages/mobile/src/views/History/images/tab1-ac.png
  45. BIN
      packages/mobile/src/views/History/images/tab1.png
  46. BIN
      packages/mobile/src/views/History/images/tab2-ac.png
  47. BIN
      packages/mobile/src/views/History/images/tab2.png
  48. BIN
      packages/mobile/src/views/History/images/tab3-ac.png
  49. BIN
      packages/mobile/src/views/History/images/tab3.png
  50. BIN
      packages/mobile/src/views/History/images/tab4-ac.png
  51. BIN
      packages/mobile/src/views/History/images/tab4.png
  52. 159 0
      packages/mobile/src/views/History/index.scss
  53. 90 0
      packages/mobile/src/views/History/index.vue
  54. 107 0
      packages/mobile/src/views/Home/constants.js
  55. BIN
      packages/mobile/src/views/Home/images/bg-min.jpg
  56. BIN
      packages/mobile/src/views/Home/images/c1-min.png
  57. BIN
      packages/mobile/src/views/Home/images/c2-min.png
  58. BIN
      packages/mobile/src/views/Home/images/c3-min.png
  59. BIN
      packages/mobile/src/views/Home/images/c4-min.png
  60. BIN
      packages/mobile/src/views/Home/images/c5-min.png
  61. BIN
      packages/mobile/src/views/Home/images/c6-min.png
  62. BIN
      packages/mobile/src/views/Home/images/line-active.png
  63. BIN
      packages/mobile/src/views/Home/images/m1-min.png
  64. BIN
      packages/mobile/src/views/Home/images/m2-min.png
  65. BIN
      packages/mobile/src/views/Home/images/m3-min.png
  66. BIN
      packages/mobile/src/views/Home/images/m4-min.png
  67. BIN
      packages/mobile/src/views/Home/images/map-min.png
  68. BIN
      packages/mobile/src/views/Home/images/point-bg-min.png
  69. BIN
      packages/mobile/src/views/Home/images/step.png
  70. BIN
      packages/mobile/src/views/Home/images/t1-min.png
  71. BIN
      packages/mobile/src/views/Home/images/t2-min.png
  72. BIN
      packages/mobile/src/views/Home/images/t3-min.png
  73. BIN
      packages/mobile/src/views/Home/images/t4-min.png
  74. BIN
      packages/mobile/src/views/Home/images/t5-min.png
  75. BIN
      packages/mobile/src/views/Home/images/t6-min.png
  76. BIN
      packages/mobile/src/views/Home/images/tab-bg.png
  77. BIN
      packages/mobile/src/views/Home/images/title-min.png
  78. 210 0
      packages/mobile/src/views/Home/index.scss
  79. 84 4
      packages/mobile/src/views/Home/index.vue
  80. BIN
      packages/mobile/src/views/Loading/images/bg-min.png
  81. BIN
      packages/mobile/src/views/Loading/images/loading.png
  82. 29 0
      packages/mobile/src/views/Loading/index.scss
  83. 45 0
      packages/mobile/src/views/Loading/index.vue
  84. 86 0
      packages/mobile/src/views/Story/detail.vue
  85. BIN
      packages/mobile/src/views/Story/images/bd-min.png
  86. BIN
      packages/mobile/src/views/Story/images/detail-bg-min.jpg
  87. BIN
      packages/mobile/src/views/Story/images/menu-bg-min.png
  88. BIN
      packages/mobile/src/views/Story/images/title-min.png
  89. 44 0
      packages/mobile/src/views/Story/index.scss
  90. 28 0
      packages/mobile/src/views/Story/index.vue
  91. 0 40
      packages/pc/src/views/Antique/constants.js
  92. 1 1
      packages/pc/src/views/Antique/index.vue
  93. BIN
      packages/pc/src/views/Home/components/Biographies/images/bg-min.jpg
  94. 1 1
      packages/pc/src/views/Home/components/SharePopup.vue
  95. BIN
      packages/pc/src/views/Home/images/c1-min.png
  96. BIN
      packages/pc/src/views/Home/images/c2-min.png
  97. BIN
      packages/pc/src/views/Home/images/c3-min.png
  98. BIN
      packages/pc/src/views/Home/images/c4-min.png
  99. BIN
      packages/pc/src/views/Home/images/c5-min.png
  100. 0 0
      packages/pc/src/views/Home/images/c6-min.png

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 245 - 0
packages/base/src/constants.js


+ 1 - 0
packages/base/src/index.js

@@ -1,3 +1,4 @@
 export * from "./utils";
 export * from "./usePreloader";
+export * from "./constants";
 export { default as Apng } from "./apng";

BIN
packages/base/story/1936年6月报纸刊登固北县成立.png


BIN
packages/base/story/1945年5月韩练成(左)部署国民党第46军参加桂柳追击战.png


BIN
packages/base/story/一大队大队长杨得志.png


BIN
packages/base/story/一大队政委肖华.png


BIN
packages/base/story/中共固原县委旧址.png


BIN
packages/base/story/五大队政委赖传珠.png


BIN
packages/base/story/四大队大队长王开湘.png


BIN
packages/base/story/四大队政委杨成武.png


BIN
packages/base/story/固北县苏维埃政府刷写的标语.png


BIN
packages/base/story/固原县城残破废弃的城墙窑洞.png


BIN
packages/base/story/毛泽东10月5日晚在单家集张崇德家里住过的房屋.png


BIN
packages/base/story/毛泽东10月7日晚在张有仁家住过的窑洞旧貌.png


BIN
packages/base/story/毛泽东10月8日晚在乔家渠的宿营旧址.png


BIN
packages/base/story/红军长征青石嘴战斗纪念碑.png


BIN
packages/base/story/苏维埃政府旧址.png


BIN
packages/base/story/西北军区司令部合影.png


BIN
packages/base/story/青石嘴战斗遗址.png


BIN
packages/base/story/韩练成.png


BIN
packages/base/story/韩练成迁居陕西临潼留影.png


+ 4 - 1
packages/mobile/package.json

@@ -10,10 +10,13 @@
   },
   "dependencies": {
     "@guyuan/base": "workspace:*",
+    "clipboard": "^2.0.11",
     "pinia": "^2.2.6",
-    "swiper": "^11.1.15",
+    "swiper": "^11.2.10",
     "vant": "^4.9.15",
     "vue": "^3.5.13",
+    "vue-draggable-resizable": "^3.0.0",
+    "vue-qrcode": "^2.2.2",
     "vue-router": "^4.4.5"
   },
   "devDependencies": {

+ 1 - 1
packages/mobile/src/App.vue

@@ -11,6 +11,6 @@ import { RouterView } from "vue-router";
   --van-primary-color: #981b23;
   --van-base-font: "SourceHanSerifSC-Regular";
   --design-width: 750;
-  --design-height: 1424;
+  --design-height: 1448;
 }
 </style>

BIN
packages/mobile/src/assets/images/back.png


BIN
packages/mobile/src/assets/images/bg-min.jpg


BIN
packages/mobile/src/assets/images/close.png


BIN
packages/mobile/src/assets/images/left.png


BIN
packages/mobile/src/assets/images/logo-min.png


BIN
packages/mobile/src/assets/images/right.png


+ 121 - 0
packages/mobile/src/components/DetailPopup.vue

@@ -0,0 +1,121 @@
+<template>
+  <van-popup
+    v-model:show="show"
+    :close-on-click-overlay="false"
+    class="detail-popup"
+  >
+    <h3>一级解放勋章</h3>
+
+    <Swiper
+      :modules="[Navigation]"
+      class="detail-popup-swiper"
+      :slides-per-view="1"
+      :centered-slides="true"
+      :navigation="true"
+    >
+      <SwiperSlide>
+        <van-image
+          src="https://houseoss.4dkankan.com/project/guyuan/pc/assets/c1-min-Cebn0ppc.png"
+          fit="scale-down"
+        />
+      </SwiperSlide>
+      <SwiperSlide>
+        <van-image
+          src="https://houseoss.4dkankan.com/project/guyuan/pc/assets/c1-min-Cebn0ppc.png"
+          fit="scale-down"
+        />
+      </SwiperSlide>
+    </Swiper>
+
+    <div class="detail-popup-info">
+      <p>
+        1955 年 9 月,韩练成被授予中将军衔、一级解放勋章。授衔
+        前,周恩来曾经征求他的意见。
+      </p>
+    </div>
+
+    <img
+      class="detail-popup__close"
+      src="@/assets/images/close.png"
+      @click="show = false"
+    />
+  </van-popup>
+</template>
+
+<script setup>
+import { computed } from "vue";
+import { Swiper, SwiperSlide } from "swiper/vue";
+import { Navigation } from "swiper/modules";
+import "swiper/css";
+import "swiper/css/navigation";
+
+const props = defineProps(["visible"]);
+const emits = defineEmits(["update:visible"]);
+
+const show = computed({
+  get() {
+    return props.visible;
+  },
+  set(v) {
+    emits("update:visible", v);
+  },
+});
+</script>
+
+<style lang="scss">
+@use "@/assets/utils.scss";
+
+.detail-popup {
+  --van-popup-background: transparent;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  padding: utils.vh-calc(50) 0 utils.vh-calc(40);
+  height: 100%;
+
+  h3 {
+    font-size: utils.vh-calc(32);
+    font-weight: bold;
+    color: #fcd97e;
+  }
+  &-swiper {
+    --swiper-navigation-sides-offset: -12px;
+
+    width: 100%;
+    height: utils.vh-calc(988);
+
+    .swiper-button-next,
+    .swiper-button-prev {
+      width: utils.vh-calc(48);
+      height: utils.vh-calc(48);
+
+      &::after {
+        display: none;
+      }
+    }
+    .swiper-button-prev {
+      background: url("@/assets/images/left.png") no-repeat center / contain;
+    }
+    .swiper-button-next {
+      background: url("@/assets/images/right.png") no-repeat center / contain;
+    }
+    .van-image {
+      width: 100%;
+      height: 100%;
+    }
+  }
+  &-info {
+    padding: 0 30px;
+    flex: 1;
+    height: 0;
+    overflow-y: auto;
+    text-indent: 2em;
+    color: #d6d6d6;
+    line-height: 47px;
+    font-size: 24px;
+  }
+  &__close {
+    width: 91px;
+  }
+}
+</style>

+ 104 - 0
packages/mobile/src/components/SharePopup.vue

@@ -0,0 +1,104 @@
+<template>
+  <van-dialog
+    class="share-popup"
+    v-model:show="show"
+    title="分享"
+    :showConfirmButton="false"
+    :closeOnClickOverlay="true"
+  >
+    <p>请使用手机扫描二维码或 复制分享链接</p>
+
+    <vue-qrcode
+      :value="url"
+      :width="200"
+      class="share-popup__qrcode"
+      :color="{}"
+      type="image/jpeg"
+    />
+
+    <div class="share-popup-tools">
+      <div class="share-popup__btn" @click="copyUrl">复制分享链接</div>
+      <div v-if="_isMobile" class="share-popup__btn" @click="saveQRCode">
+        保存二维码
+      </div>
+    </div>
+  </van-dialog>
+</template>
+
+<script setup>
+import { computed } from "vue";
+import VueQrcode from "vue-qrcode";
+import clipboard from "clipboard";
+import { isMobile } from "@guyuan/base";
+import { showNotify } from "vant";
+import "vant/lib/notify/style/index";
+
+const url = window.location.href;
+const _isMobile = isMobile();
+const props = defineProps(["visible"]);
+const emits = defineEmits(["update:visible"]);
+
+const show = computed({
+  get() {
+    return props.visible;
+  },
+  set(v) {
+    emits("update:visible", v);
+  },
+});
+
+const copyUrl = () => {
+  clipboard.copy(url);
+
+  showNotify({
+    type: "success",
+    message: "链接已复制",
+  });
+};
+
+const saveQRCode = () => {
+  const img = document.getElementsByClassName("share-popup__qrcode");
+  if (img && img.length) {
+    const a = document.createElement("a");
+    // @ts-ignore
+    a.href = img[0].src;
+    a.download = "shareCode.jpg";
+    a.click();
+  }
+};
+</script>
+
+<style lang="scss">
+.share-popup {
+  width: 85%;
+
+  &__qrcode {
+    margin: 36px 0 40px;
+    overflow: hidden;
+    border-radius: 20px;
+  }
+  &__btn {
+    flex: 1;
+    height: 100px;
+    line-height: 100px;
+    text-align: center;
+    color: white;
+    font-size: 30px;
+    background: #610415;
+    border-radius: 100px;
+    cursor: pointer;
+  }
+  &-tools {
+    display: flex;
+    align-items: center;
+    gap: 24px;
+    width: 100%;
+  }
+  .van-dialog__content {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    padding: 20px 30px;
+  }
+}
+</style>

+ 51 - 0
packages/mobile/src/components/VideoPopup.vue

@@ -0,0 +1,51 @@
+<template>
+  <van-popup
+    v-model:show="show"
+    :close-on-click-overlay="false"
+    class="video-popup"
+  >
+    <video controls autoplay :src="src" />
+
+    <img
+      class="video-popup__close"
+      src="@/assets/images/close.png"
+      @click="show = false"
+    />
+  </van-popup>
+</template>
+
+<script setup>
+import { computed } from "vue";
+
+const props = defineProps(["visible", "src"]);
+const emits = defineEmits(["update:visible"]);
+
+const show = computed({
+  get() {
+    return props.visible;
+  },
+  set(v) {
+    emits("update:visible", v);
+  },
+});
+</script>
+
+<style lang="scss" scoped>
+.video-popup {
+  --van-popup-background: none;
+  height: 100%;
+
+  video {
+    position: relative;
+    top: 310px;
+    width: 100%;
+  }
+  &__close {
+    position: absolute;
+    left: 50%;
+    bottom: 44px;
+    width: 91px;
+    transform: translateX(-50%);
+  }
+}
+</style>

+ 25 - 0
packages/mobile/src/router/index.js

@@ -5,9 +5,34 @@ const router = createRouter({
   routes: [
     {
       path: "/",
+      name: "loading",
+      component: () => import("../views/Loading/index.vue"),
+    },
+    {
+      path: "/index",
       name: "home",
       component: () => import("../views/Home/index.vue"),
     },
+    {
+      path: "/story",
+      name: "story",
+      component: () => import("../views/Story/index.vue"),
+    },
+    {
+      path: "/story/:id",
+      name: "storyDetail",
+      component: () => import("../views/Story/detail.vue"),
+    },
+    {
+      path: "/antique",
+      name: "antique",
+      component: () => import("../views/Antique/index.vue"),
+    },
+    {
+      path: "/history",
+      name: "history",
+      component: () => import("../views/History/index.vue"),
+    },
   ],
 });
 

+ 25 - 0
packages/mobile/src/stores/base.js

@@ -0,0 +1,25 @@
+import { ref } from "vue";
+import { defineStore } from "pinia";
+import { parseUrlName } from "@guyuan/base";
+import Img1 from "../views/Home/images/bg-min.jpg";
+import Img2 from "../views/Home/images/title-min.png";
+import Img3 from "../views/Home/images/tab-bg.png";
+import Img4 from "../views/Home/images/step.png";
+import Img5 from "../views/Home/images/map-min.png";
+import Img7 from "../views/Home/images/line-active.png";
+
+export const RESOURCE_LIST = [Img1, Img2, Img3, Img4, Img5, Img7];
+
+export const useBaseStore = defineStore("base", () => {
+  const mediaUrlMap = ref(new Map());
+
+  RESOURCE_LIST.forEach((url) => {
+    mediaUrlMap.value.set(parseUrlName(url), url);
+  });
+
+  const setMediaUrlMap = (list) => {
+    mediaUrlMap.value = list;
+  };
+
+  return { mediaUrlMap, setMediaUrlMap };
+});

BIN
packages/mobile/src/views/Antique/images/search.png


BIN
packages/mobile/src/views/Antique/images/tab1-ac-min.png


BIN
packages/mobile/src/views/Antique/images/tab1-min.png


BIN
packages/mobile/src/views/Antique/images/tab2-ac-min.png


BIN
packages/mobile/src/views/Antique/images/tab2-min.png


+ 135 - 0
packages/mobile/src/views/Antique/index.scss

@@ -0,0 +1,135 @@
+.antique {
+  position: absolute;
+  inset: 0;
+  overflow-y: auto;
+  background: url("@/assets/images/bg-min.jpg") no-repeat center / cover;
+
+  &-back {
+    position: absolute;
+    top: 30px;
+    left: 30px;
+    width: 76px;
+    height: 76px;
+    background: url("@/assets/images/back.png") no-repeat center / contain;
+    z-index: 10;
+  }
+  &-head {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    padding: 0 10px;
+    z-index: 999;
+
+    ul {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      gap: 5px;
+      padding: 70px 0 20px;
+
+      li {
+        width: 263px;
+        height: 79px;
+
+        img {
+          width: 100%;
+          height: 100%;
+          object-fit: cover;
+        }
+      }
+    }
+    &-tools {
+      display: flex;
+      align-items: center;
+      gap: 16px;
+      padding: 0 16px;
+      height: 127px;
+      background: #f8f8f8;
+      box-shadow: 0px 4px 5px 0px rgba(0, 0, 0, 0.1);
+      border-radius: 5px;
+      border-top: 7px solid #d9d9d9;
+      overflow: hidden;
+    }
+  }
+  &-class {
+    --van-dropdown-menu-shadow: none;
+    --van-dropdown-menu-height: 68px;
+    --van-dropdown-menu-title-font-size: 28px;
+    width: 285px;
+    border-radius: 5px;
+    overflow: hidden;
+    border: 2px solid rgba(0, 0, 0, 0.05);
+  }
+  &-search {
+    padding: 0 10px 0 28px;
+    display: flex;
+    align-items: center;
+    flex: 1;
+    width: 0;
+    height: 68px;
+    border-radius: 5px;
+    overflow: hidden;
+    background: white;
+    border: 2px solid rgba(0, 0, 0, 0.1);
+
+    input {
+      flex: 1;
+      width: 0;
+      border: 0;
+      user-select: none;
+      background: transparent;
+      font-size: 24px;
+    }
+    .icon {
+      flex-shrink: 0;
+      width: 59px;
+      height: 59px;
+      background: url("./images/search.png") no-repeat center / contain;
+    }
+  }
+  &-wrap {
+    position: absolute;
+    top: 314px;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    padding: 0 10px 40px;
+    display: grid;
+    grid-template-columns: repeat(2, 1fr);
+    column-gap: 30px;
+    row-gap: 32px;
+    overflow-y: auto;
+
+    li {
+      position: relative;
+      height: 332px;
+      background: radial-gradient(
+        57% 57% at 50% 50%,
+        #ffffff 41%,
+        #cfcabd 100%
+      );
+      border-radius: 11px;
+      overflow: hidden;
+      box-shadow: 0px 7px 11px 0px rgba(0, 0, 0, 0.3);
+
+      .van-image {
+        --van-image-placeholder-background: none;
+        width: 100%;
+        height: 100%;
+      }
+      p {
+        position: absolute;
+        left: 0;
+        right: 0;
+        bottom: 0;
+        padding: 0 20px;
+        height: 55px;
+        font-size: 25px;
+        color: #ffffff;
+        line-height: 55px;
+        background: #741a1a;
+      }
+    }
+  }
+}

+ 69 - 0
packages/mobile/src/views/Antique/index.vue

@@ -0,0 +1,69 @@
+<template>
+  <div class="antique">
+    <div class="antique-head">
+      <i class="antique-back" @click="$router.back" />
+
+      <ul>
+        <li v-for="item in TABS" :key="item.id" @click="activeTab = item.id">
+          <img :src="activeTab === item.id ? item.img2 : item.img" />
+        </li>
+      </ul>
+
+      <div class="antique-head-tools">
+        <van-dropdown-menu class="antique-class">
+          <van-dropdown-item
+            v-model="curCategory"
+            :options="TABS[activeTab].list"
+          />
+        </van-dropdown-menu>
+
+        <div class="antique-search">
+          <input placeholder="请输入文物名称" />
+          <i class="icon" />
+        </div>
+      </div>
+    </div>
+
+    <ul class="antique-wrap">
+      <li v-for="item in 10" :key="item" @click="detailVisible = true">
+        <van-image src="" />
+        <p class="limit-line">一级解放勋章</p>
+      </li>
+    </ul>
+  </div>
+
+  <DetailPopup v-model:visible="detailVisible" />
+</template>
+
+<script setup>
+import Tab1Icon from "./images/tab1-min.png";
+import Tab1ActIcon from "./images/tab1-ac-min.png";
+import Tab2Icon from "./images/tab2-min.png";
+import Tab2ActIcon from "./images/tab2-ac-min.png";
+import { ref } from "vue";
+import { ANTIQUE_THREE, ANTIQUE_TWO } from "@guyuan/base";
+import DetailPopup from "@/components/DetailPopup.vue";
+
+const TABS = [
+  {
+    id: 0,
+    img: Tab1Icon,
+    img2: Tab1ActIcon,
+    list: ANTIQUE_THREE,
+  },
+  {
+    id: 1,
+    img: Tab2Icon,
+    img2: Tab2ActIcon,
+    list: ANTIQUE_TWO,
+  },
+];
+
+const activeTab = ref(0);
+const detailVisible = ref(false);
+const curCategory = ref(0);
+</script>
+
+<style lang="scss" scoped>
+@use "./index.scss";
+</style>

+ 52 - 0
packages/mobile/src/views/History/components/Panel.vue

@@ -0,0 +1,52 @@
+<template>
+  <div class="panel">
+    <p class="panel__title">{{ title }}</p>
+
+    <slot />
+  </div>
+</template>
+
+<script setup>
+defineProps(["title"]);
+</script>
+
+<style lang="scss" scoped>
+.panel {
+  position: relative;
+  padding: 40px 32px;
+  border-radius: 8px;
+  overflow: hidden;
+  background: #e4dac9;
+
+  &::before {
+    content: "";
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    height: 18px;
+    background: linear-gradient(90deg, #dcd3bf 0%, #ceb68f 100%);
+  }
+  &::after {
+    content: "";
+    position: absolute;
+    top: 18px;
+    left: 0;
+    right: 0;
+    height: 36px;
+    background: linear-gradient(
+      0deg,
+      rgba(96, 79, 55, 0) 0%,
+      rgba(96, 79, 55, 0.4) 100%
+    );
+  }
+  &__title {
+    margin-bottom: 36px;
+    padding: 10px 0 20px;
+    color: #343a40;
+    font-weight: bold;
+    font-size: 36px;
+    border-bottom: 2px solid #ccc4b4;
+  }
+}
+</style>

BIN
packages/mobile/src/views/History/images/bg2-min.jpg


BIN
packages/mobile/src/views/History/images/tab1-ac.png


BIN
packages/mobile/src/views/History/images/tab1.png


BIN
packages/mobile/src/views/History/images/tab2-ac.png


BIN
packages/mobile/src/views/History/images/tab2.png


BIN
packages/mobile/src/views/History/images/tab3-ac.png


BIN
packages/mobile/src/views/History/images/tab3.png


BIN
packages/mobile/src/views/History/images/tab4-ac.png


BIN
packages/mobile/src/views/History/images/tab4.png


+ 159 - 0
packages/mobile/src/views/History/index.scss

@@ -0,0 +1,159 @@
+.history {
+  position: absolute;
+  inset: 0;
+  overflow-y: auto;
+  background: url("./images/bg2-min.jpg") no-repeat center / cover;
+
+  &-back {
+    position: absolute;
+    top: 30px;
+    left: 30px;
+    width: 76px;
+    height: 76px;
+    background: url("@/assets/images/back.png") no-repeat center / contain;
+    z-index: 10;
+  }
+  &-head {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    z-index: 999;
+
+    ul {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      gap: 12px;
+      padding: 80px 0 0;
+
+      li {
+        &.active {
+          img {
+            width: 177px;
+            height: 87px;
+          }
+        }
+        img {
+          width: 104px;
+          height: 80px;
+        }
+      }
+    }
+    &-tools {
+      display: flex;
+      align-items: center;
+      gap: 16px;
+      padding: 0 16px;
+      height: 127px;
+      background: #f8f8f8;
+      box-shadow: 0px 4px 5px 0px rgba(0, 0, 0, 0.1);
+      border-radius: 5px;
+      border-top: 7px solid #d9d9d9;
+      overflow: hidden;
+    }
+  }
+  &-class {
+    --van-dropdown-menu-shadow: none;
+    --van-dropdown-menu-height: 68px;
+    --van-dropdown-menu-title-font-size: 28px;
+    width: 285px;
+    border-radius: 5px;
+    overflow: hidden;
+    border: 2px solid rgba(0, 0, 0, 0.05);
+  }
+  &-search {
+    padding: 0 10px 0 28px;
+    display: flex;
+    align-items: center;
+    flex: 1;
+    width: 0;
+    height: 68px;
+    border-radius: 5px;
+    overflow: hidden;
+    background: white;
+    border: 2px solid rgba(0, 0, 0, 0.1);
+
+    input {
+      flex: 1;
+      width: 0;
+      border: 0;
+      user-select: none;
+      background: transparent;
+      font-size: 24px;
+    }
+    .icon {
+      flex-shrink: 0;
+      width: 59px;
+      height: 59px;
+      background: url("./images/search.png") no-repeat center / contain;
+    }
+  }
+  &-wrap {
+    position: absolute;
+    top: 166px;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    padding: 0 12px 40px;
+    overflow-y: auto;
+    box-sizing: border-box;
+
+    .image {
+      display: grid;
+      grid-template-columns: repeat(2, 1fr);
+      column-gap: 30px;
+      row-gap: 32px;
+
+      li {
+        position: relative;
+        height: 210px;
+
+        .van-image {
+          width: 100%;
+          height: 100%;
+        }
+        p {
+          position: absolute;
+          left: 0;
+          right: 0;
+          bottom: 0;
+          padding: 0 20px;
+          height: 40px;
+          font-size: 25px;
+          color: #ffffff;
+          line-height: 40px;
+          background: #741a1a;
+        }
+      }
+    }
+    .video {
+      display: grid;
+      grid-template-columns: repeat(1, 1fr);
+      row-gap: 36px;
+
+      li {
+        position: relative;
+        height: 378px;
+
+        .van-image {
+          width: 100%;
+          height: 100%;
+        }
+        p {
+          position: absolute;
+          left: 0;
+          right: 0;
+          bottom: 0;
+          padding: 0 20px;
+          height: 60px;
+          font-size: 28px;
+          font-weight: bold;
+          color: #ffffff;
+          line-height: 60px;
+          background: #741a1a;
+        }
+      }
+    }
+  }
+}

+ 90 - 0
packages/mobile/src/views/History/index.vue

@@ -0,0 +1,90 @@
+<template>
+  <div class="history">
+    <div class="history-head">
+      <i class="history-back" @click="$router.back" />
+
+      <ul>
+        <li
+          v-for="item in TABS"
+          :key="item.id"
+          :class="{ active: activeTab === item.id }"
+          @click="activeTab = item.id"
+        >
+          <img :src="activeTab === item.id ? item.img2 : item.img" />
+        </li>
+      </ul>
+    </div>
+
+    <div class="history-wrap">
+      <panel v-if="activeTab === 1" title="视频">
+        <ul class="video">
+          <li v-for="item in 10" :key="item" @click="videoVisible = true">
+            <van-image src="" />
+            <p class="limit-line">一级解放勋章</p>
+          </li>
+        </ul>
+      </panel>
+
+      <panel v-else title="图片">
+        <ul class="image">
+          <li v-for="item in 10" :key="item" @click="detailVisible = true">
+            <van-image src="" />
+            <p class="limit-line">一级解放勋章</p>
+          </li>
+        </ul>
+      </panel>
+    </div>
+  </div>
+
+  <DetailPopup v-model:visible="detailVisible" />
+  <VideoPopup
+    v-model:visible="videoVisible"
+    src="https://houseoss.4dkankan.com/project/guyuan/base/videos/video1.mp4"
+  />
+</template>
+
+<script setup>
+import { ref } from "vue";
+import DetailPopup from "@/components/DetailPopup.vue";
+import VideoPopup from "@/components/VideoPopup.vue";
+import Panel from "./components/Panel.vue";
+import Tab1Icon from "./images/tab1.png";
+import Tab1ActIcon from "./images/tab1-ac.png";
+import Tab2Icon from "./images/tab2.png";
+import Tab2ActIcon from "./images/tab2-ac.png";
+import Tab3Icon from "./images/tab3.png";
+import Tab3ActIcon from "./images/tab3-ac.png";
+import Tab4Icon from "./images/tab4.png";
+import Tab4ActIcon from "./images/tab4-ac.png";
+
+const TABS = [
+  {
+    id: 0,
+    img: Tab1Icon,
+    img2: Tab1ActIcon,
+  },
+  {
+    id: 1,
+    img: Tab2Icon,
+    img2: Tab2ActIcon,
+  },
+  {
+    id: 2,
+    img: Tab3Icon,
+    img2: Tab3ActIcon,
+  },
+  {
+    id: 3,
+    img: Tab4Icon,
+    img2: Tab4ActIcon,
+  },
+];
+
+const activeTab = ref(0);
+const detailVisible = ref(false);
+const videoVisible = ref(false);
+</script>
+
+<style lang="scss" scoped>
+@use "./index.scss";
+</style>

+ 107 - 0
packages/mobile/src/views/Home/constants.js

@@ -0,0 +1,107 @@
+import M1Img from "./images/m1-min.png";
+import M2Img from "./images/m2-min.png";
+import M3Img from "./images/m3-min.png";
+import M4Img from "./images/m4-min.png";
+import C1Img from "./images/c1-min.png";
+import C2Img from "./images/c2-min.png";
+import C3Img from "./images/c3-min.png";
+import C4Img from "./images/c4-min.png";
+import C5Img from "./images/c5-min.png";
+import C6Img from "./images/c6-min.png";
+import T1Img from "./images/t1-min.png";
+import T2Img from "./images/t2-min.png";
+import T3Img from "./images/t3-min.png";
+import T4Img from "./images/t4-min.png";
+import T5Img from "./images/t5-min.png";
+import T6Img from "./images/t6-min.png";
+
+export const MIMAGES = [
+  {
+    default: M1Img,
+    href: "https://houseoss.4dkankan.com/project/guyuan/scene/index.html?m=SG-IDyBc0bleFF",
+  },
+  {
+    default: M2Img,
+    routeName: "antique",
+  },
+  {
+    default: M3Img,
+    routeName: "history",
+  },
+  {
+    type: "share",
+    default: M4Img,
+  },
+];
+
+export const POINTS = [
+  {
+    img: C1Img,
+    img2: T1Img,
+    content: `
+      <p>入境西吉县,</p>
+      <p>毛泽东夜访单南寺,</p>
+      <p>与马德海秉烛长谈,</p>
+      <p>宣讲民族政策及抗日主张,</p>
+      <p>军民鱼水情浓,</p>
+      <p>史称“单家集夜话”。</p>
+    `,
+  },
+  {
+    img: C2Img,
+    img2: T2Img,
+    content: `
+      <p>夜宿张易堡,</p>
+      <p>红军继续行军,</p>
+      <p>宿营张易堡,</p>
+      <p>严守纪律不扰民,</p>
+      <p>借门板铺地休息,</p>
+      <p>清晨归还并留铜元致谢,</p>
+      <p>百姓称“仁义之师”。</p>
+    `,
+  },
+  {
+    img: C3Img,
+    img2: T3Img,
+    content: `
+      <p>青石嘴突袭战,</p>
+      <p>红军突袭青石嘴,</p>
+      <p>半小时歼敌两个连,</p>
+      <p>缴获战马百余匹,</p>
+      <p>遂组建中央红军首支骑兵侦察连。</p>
+    `,
+  },
+  {
+    img: C4Img,
+    img2: T4Img,
+    content: `
+      <p>翻越六盘山后,</p>
+      <p>毛泽东登顶六盘山,</p>
+      <p>远望长城,</p>
+      <p>夜宿小岔沟土炕,</p>
+      <p>即兴吟成《长征谣》初稿,</p>
+      <p>“不到长城非好汉”由此诞生。</p>
+    `,
+  },
+  {
+    img: C5Img,
+    img2: T5Img,
+    content: `
+      <p>过境彭阳县,</p>
+      <p>午后抵乔家渠,</p>
+      <p>毛泽东宿乔生魁家,</p>
+      <p>土炕上铺地图部署陕北行军,</p>
+      <p>房东悄悄塞给战士两筐土豆,</p>
+      <p>军民泪别。</p>
+    `,
+  },
+  {
+    img: C6Img,
+    img2: T6Img,
+    content: `
+      <p>出境固原,</p>
+      <p>拂晓从彭阳长城塬出发,</p>
+      <p>踏上奔赴陕北抗日的新征程。</p>
+    `,
+  },
+];

BIN
packages/mobile/src/views/Home/images/bg-min.jpg


BIN
packages/mobile/src/views/Home/images/c1-min.png


BIN
packages/mobile/src/views/Home/images/c2-min.png


BIN
packages/mobile/src/views/Home/images/c3-min.png


BIN
packages/mobile/src/views/Home/images/c4-min.png


BIN
packages/mobile/src/views/Home/images/c5-min.png


BIN
packages/mobile/src/views/Home/images/c6-min.png


BIN
packages/mobile/src/views/Home/images/line-active.png


BIN
packages/mobile/src/views/Home/images/m1-min.png


BIN
packages/mobile/src/views/Home/images/m2-min.png


BIN
packages/mobile/src/views/Home/images/m3-min.png


BIN
packages/mobile/src/views/Home/images/m4-min.png


BIN
packages/mobile/src/views/Home/images/map-min.png


BIN
packages/mobile/src/views/Home/images/point-bg-min.png


BIN
packages/mobile/src/views/Home/images/step.png


BIN
packages/mobile/src/views/Home/images/t1-min.png


BIN
packages/mobile/src/views/Home/images/t2-min.png


BIN
packages/mobile/src/views/Home/images/t3-min.png


BIN
packages/mobile/src/views/Home/images/t4-min.png


BIN
packages/mobile/src/views/Home/images/t5-min.png


BIN
packages/mobile/src/views/Home/images/t6-min.png


BIN
packages/mobile/src/views/Home/images/tab-bg.png


BIN
packages/mobile/src/views/Home/images/title-min.png


+ 210 - 0
packages/mobile/src/views/Home/index.scss

@@ -0,0 +1,210 @@
+@use "@/assets/utils.scss";
+
+.home {
+  position: absolute;
+  inset: 0;
+  overflow: hidden;
+  background: url("./images/bg-min.jpg") no-repeat center / cover;
+
+  &::after {
+    content: "";
+    position: absolute;
+    top: utils.vh-calc(42);
+    left: utils.vh-calc(8);
+    width: utils.vh-calc(158);
+    height: utils.vh-calc(112);
+    background: url("@/assets/images/logo-min.png") no-repeat center / contain;
+    z-index: 9;
+  }
+  &::before {
+    content: "";
+    position: absolute;
+    top: utils.vh-calc(0);
+    right: utils.vh-calc(26);
+    width: utils.vh-calc(187);
+    height: utils.vh-calc(510);
+    background: url("./images/title-min.png") no-repeat center / contain;
+    z-index: 9;
+  }
+  &-menu {
+    position: fixed;
+    left: utils.vh-calc(28);
+    bottom: utils.vh-calc(256);
+    display: flex;
+    flex-direction: column;
+    justify-content: space-between;
+    padding: utils.vh-calc(10) 0;
+    width: utils.vh-calc(104);
+    height: utils.vh-calc(478);
+    border-radius: 4px;
+    background: rgba($color: #000000, $alpha: 0.2);
+
+    li {
+      img {
+        width: 100%;
+      }
+    }
+  }
+  &-tab {
+    position: fixed;
+    right: utils.vw-calc(30);
+    bottom: utils.vh-calc(35);
+    width: utils.vh-calc(429);
+    height: utils.vh-calc(248);
+    background: url("./images/tab-bg.png") no-repeat center / contain;
+    z-index: 5;
+
+    > div {
+      position: absolute;
+      cursor: pointer;
+    }
+    .story {
+      top: utils.vh-calc(34);
+      left: utils.vh-calc(100);
+      width: utils.vh-calc(200);
+      height: utils.vh-calc(85);
+    }
+    .biographies {
+      left: utils.vh-calc(100);
+      bottom: utils.vh-calc(35);
+      width: utils.vh-calc(220);
+      height: utils.vh-calc(80);
+    }
+  }
+  .vdr {
+    border: 0;
+  }
+  &__map {
+    width: 100%;
+    height: 100%;
+  }
+  &-point {
+    position: absolute;
+    width: utils.vw-calc(103);
+    height: utils.vw-calc(252);
+
+    &.point0 {
+      top: utils.vw-calc(780);
+      left: utils.vw-calc(460);
+    }
+    &.point1 {
+      top: utils.vw-calc(630);
+      left: utils.vw-calc(620);
+    }
+    &.point2 {
+      top: utils.vw-calc(560);
+      left: utils.vw-calc(340);
+    }
+    &.point3 {
+      top: utils.vw-calc(320);
+      left: utils.vw-calc(250);
+    }
+    &.point4 {
+      right: utils.vw-calc(110);
+      bottom: utils.vw-calc(340);
+    }
+    &.point5 {
+      right: utils.vw-calc(390);
+      bottom: utils.vw-calc(330);
+    }
+    img {
+      position: absolute;
+      left: 50%;
+      bottom: utils.vw-calc(85);
+      width: utils.vw-calc(103);
+      transform: translateX(-50%);
+    }
+    &::after {
+      content: "";
+      position: absolute;
+      left: 50%;
+      bottom: utils.vw-calc(0);
+      width: utils.vw-calc(100);
+      height: utils.vw-calc(100);
+      transform: translateX(-50%);
+      background: url("./images/step.png") no-repeat center / contain;
+    }
+    &.active {
+      z-index: 9;
+
+      img {
+        display: none;
+      }
+      &::after {
+        display: none;
+      }
+      &::before {
+        content: "";
+        position: absolute;
+        left: 50%;
+        bottom: utils.vw-calc(-70);
+        width: utils.vw-calc(360);
+        height: utils.vw-calc(600);
+        transform: translateX(-50%);
+        background: url("./images/line-active.png") no-repeat center / contain;
+      }
+    }
+  }
+}
+
+.point-panel {
+  display: flex;
+  align-items: center;
+  gap: 30px;
+  padding: 25px 70px 80px;
+  background: rgba(0, 0, 0, 0.8);
+  backdrop-filter: blur(20px);
+  box-shadow: 0 -8px 16px rgba(0, 0, 0, 0.6);
+
+  &-img {
+    position: relative;
+    width: utils.vw-calc(173);
+    height: utils.vw-calc(281);
+    background: url("./images/point-bg-min.png") no-repeat center / contain;
+
+    img {
+      position: relative;
+    }
+    .c0 {
+      top: utils.vw-calc(20);
+      left: utils.vw-calc(22);
+      width: utils.vw-calc(139);
+      height: utils.vw-calc(227);
+    }
+    .c1 {
+      top: utils.vw-calc(20);
+      left: utils.vw-calc(22);
+      width: utils.vw-calc(114);
+      height: utils.vw-calc(229);
+    }
+    .c2 {
+      top: utils.vw-calc(20);
+      left: utils.vw-calc(22);
+      width: utils.vw-calc(139);
+      height: utils.vw-calc(227);
+    }
+    .c3 {
+      top: utils.vw-calc(20);
+      left: utils.vw-calc(22);
+      width: utils.vw-calc(108);
+      height: utils.vw-calc(222);
+    }
+    .c4 {
+      top: utils.vw-calc(20);
+      left: utils.vw-calc(22);
+      width: utils.vw-calc(133);
+      height: utils.vw-calc(227);
+    }
+    .c5 {
+      top: utils.vw-calc(20);
+      left: utils.vw-calc(22);
+      width: utils.vw-calc(104);
+      height: utils.vw-calc(231);
+    }
+  }
+  &-content {
+    color: white;
+    font-size: 24px;
+    line-height: 56px;
+  }
+}

+ 84 - 4
packages/mobile/src/views/Home/index.vue

@@ -1,13 +1,93 @@
 <template>
-  <div v-if="!loading" class="loading"></div>
+  <div class="home">
+    <VueDraggableResizable
+      :x="mapX"
+      :y="mapY"
+      :w="mapWidth"
+      :h="mapHeight"
+      :draggable="true"
+      :resizable="true"
+      :handles="[]"
+    >
+      <img class="home__map" src="./images/map-min.png" />
 
-  <div v-else class="home"></div>
+      <div
+        v-for="(item, index) in POINTS"
+        :key="index"
+        class="home-point"
+        :class="[{ active: pointIndex === index }, `point${index}`]"
+        @click="handlePoint(index)"
+      >
+        <img :src="item.img2" />
+      </div>
+    </VueDraggableResizable>
+
+    <ul class="home-menu">
+      <li v-for="(item, index) in MIMAGES" :key="index">
+        <img :src="item.default" @click="handleMenu(index)" />
+      </li>
+    </ul>
+
+    <div class="home-tab">
+      <div class="story" />
+      <div class="biographies" @click="$router.push({ name: 'story' })" />
+    </div>
+  </div>
+
+  <SharePopup v-model:visible="shareVisible" />
+  <VanPopup
+    v-model:show="pointDetailVisible"
+    :overlay="true"
+    position="bottom"
+    class="point-panel"
+    :overlay-style="{
+      background: 'transparent',
+    }"
+    @closed="pointIndex = -1"
+  >
+    <template v-if="activePoint">
+      <div class="point-panel-img">
+        <img :class="`c${pointIndex}`" :src="activePoint.img" />
+      </div>
+      <div class="point-panel-content" v-html="activePoint.content" />
+    </template>
+  </VanPopup>
 </template>
 
 <script setup>
-import { ref } from "vue";
+import { ref, computed } from "vue";
+import VueDraggableResizable from "vue-draggable-resizable";
+import "vue-draggable-resizable/style.css";
+import { POINTS, MIMAGES } from "./constants";
+import SharePopup from "@/components/SharePopup.vue";
+import { useRouter } from "vue-router";
+
+const mapWidth = window.innerWidth * (1600 / 750);
+const mapHeight = window.innerWidth * (1215 / 750);
+const mapX = window.innerWidth * (30 / 750);
+const mapY = window.innerWidth * (80 / 750);
+
+const router = useRouter();
+const pointIndex = ref(-1);
+const shareVisible = ref(false);
+const pointDetailVisible = ref(false);
+const activePoint = computed(() => POINTS[pointIndex.value]);
+
+const handlePoint = (index) => {
+  pointIndex.value = index;
+  pointDetailVisible.value = true;
+};
 
-const loading = ref(false);
+const handleMenu = (index) => {
+  const item = MIMAGES[index];
+  if (item.routeName) {
+    router.push({ name: item.routeName, query: item.query });
+  } else if (item.href) {
+    window.location.href = item.href;
+  } else if (item.type === "share") {
+    shareVisible.value = true;
+  }
+};
 </script>
 
 <style lang="scss" scoped>

BIN
packages/mobile/src/views/Loading/images/bg-min.png


BIN
packages/mobile/src/views/Loading/images/loading.png


+ 29 - 0
packages/mobile/src/views/Loading/index.scss

@@ -0,0 +1,29 @@
+@use "@/assets/utils.scss";
+
+.loading {
+  position: absolute;
+  inset: 0;
+  background: url("./images/bg-min.png") no-repeat center right / cover;
+  background-size: utils.vh-calc(750) utils.vh-calc(1338);
+  background-position: utils.vh-calc(30) utils.vh-calc(-40);
+
+  &-wrap {
+    position: absolute;
+    inset: 0;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    flex-direction: column;
+    background: rgba(97, 4, 21, 0.8);
+    backdrop-filter: blur(40px);
+  }
+  img {
+    width: utils.vh-calc(370);
+    height: utils.vh-calc(268);
+  }
+  &-text {
+    font-weight: bold;
+    font-size: utils.vh-calc(18);
+    color: #8b4e0e;
+  }
+}

+ 45 - 0
packages/mobile/src/views/Loading/index.vue

@@ -0,0 +1,45 @@
+<template>
+  <div class="loading">
+    <div class="loading-wrap">
+      <img src="./images/loading.png" alt="loading" />
+      <!-- <div class="loading-text">{{ loadingProgress }}%</div> -->
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { onMounted, watch } from "vue";
+import { usePreloader } from "@guyuan/base";
+import { useBaseStore, RESOURCE_LIST } from "@/stores/base";
+import { useRouter } from "vue-router";
+
+const baseStore = useBaseStore();
+const router = useRouter();
+
+const {
+  percent: loadingProgress,
+  mediaUrlMap,
+  start,
+} = usePreloader({
+  list: RESOURCE_LIST,
+  success() {
+    baseStore.setMediaUrlMap(mediaUrlMap);
+  },
+});
+
+onMounted(() => {
+  start();
+});
+
+watch(loadingProgress, (newVal) => {
+  if (newVal === "100") {
+    setTimeout(() => {
+      router.replace({ name: "home" });
+    }, 500);
+  }
+});
+</script>
+
+<style lang="scss" scoped>
+@use "./index.scss";
+</style>

+ 86 - 0
packages/mobile/src/views/Story/detail.vue

@@ -0,0 +1,86 @@
+<template>
+  <div class="story-detail">
+    <i class="story-detail-back" @click="$router.back" />
+
+    <img class="story-detail-title" src="./images/title-min.png" />
+
+    <div class="story-detail-wrap">
+      <h3>{{ item.title }}</h3>
+      <div class="story-detail-content" v-html="item.content" />
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { STORY_LIST } from "@guyuan/base";
+import { computed } from "vue";
+import { useRoute } from "vue-router";
+
+const route = useRoute();
+const item = computed(() => STORY_LIST[route.params.id]);
+</script>
+
+<style lang="scss" scoped>
+.story-detail {
+  position: absolute;
+  inset: 0;
+  overflow-y: auto;
+  background: url("./images/detail-bg-min.jpg") no-repeat center top / cover;
+
+  &-wrap {
+    position: absolute;
+    top: 336px;
+    left: 50px;
+    right: 30px;
+    bottom: 70px;
+    padding-right: 20px;
+    overflow: auto;
+
+    h3 {
+      position: relative;
+      padding: 0 8px 8px;
+      font-size: 56px;
+      color: #610415;
+      line-height: 96px;
+      letter-spacing: 1px;
+
+      &::after {
+        content: "";
+        position: absolute;
+        left: 0;
+        bottom: 0;
+        right: 0;
+        height: 4px;
+        background: url("./images/bd-min.png") no-repeat center / contain;
+      }
+    }
+  }
+  &-back {
+    position: fixed;
+    top: 34px;
+    left: 34px;
+    width: 76px;
+    height: 76px;
+    background: url("@/assets/images/back.png") no-repeat center / contain;
+    z-index: 10;
+  }
+  &-title {
+    margin: 60px 0 0 -90px;
+    width: 603px;
+  }
+  &-content {
+    margin-top: 20px;
+    padding: 0 8px 60px;
+    line-height: 36px;
+    color: #610415;
+    letter-spacing: 4px;
+    text-indent: 2em;
+
+    :deep(img) {
+      margin: 28px 0;
+      width: 100%;
+      object-fit: scale-down;
+    }
+  }
+}
+</style>

BIN
packages/mobile/src/views/Story/images/bd-min.png


BIN
packages/mobile/src/views/Story/images/detail-bg-min.jpg


BIN
packages/mobile/src/views/Story/images/menu-bg-min.png


BIN
packages/mobile/src/views/Story/images/title-min.png


+ 44 - 0
packages/mobile/src/views/Story/index.scss

@@ -0,0 +1,44 @@
+.story {
+  position: absolute;
+  inset: 0;
+  background: url("@/assets/images/bg-min.jpg") no-repeat center / cover;
+
+  &-back {
+    position: fixed;
+    top: 34px;
+    left: 34px;
+    width: 76px;
+    height: 76px;
+    background: url("@/assets/images/back.png") no-repeat center / contain;
+    z-index: 10;
+  }
+  &-menu {
+    position: absolute;
+    top: 0;
+    left: 0;
+    bottom: 0;
+    width: 658px;
+    background: url("./images/menu-bg-min.png") no-repeat center / cover;
+
+    ul {
+      margin: 24px 0 0 16px;
+      display: flex;
+      flex-direction: column;
+      gap: 10px;
+      width: 538px;
+
+      li {
+        padding: 0 60px;
+        height: 86px;
+        line-height: 86px;
+        font-size: 36px;
+        color: white;
+        background: rgba(61, 1, 12, 0.6);
+      }
+    }
+  }
+  &-title {
+    margin: 152px 0 0 35px;
+    width: 603px;
+  }
+}

+ 28 - 0
packages/mobile/src/views/Story/index.vue

@@ -0,0 +1,28 @@
+<template>
+  <div class="story">
+    <i class="story-back" @click="$router.back" />
+
+    <div class="story-menu">
+      <img class="story-title" src="./images/title-min.png" />
+
+      <ul>
+        <li
+          v-for="(item, index) in STORY_LIST"
+          :key="item.title"
+          class="limit-line"
+          @click="$router.push({ name: 'storyDetail', params: { id: index } })"
+        >
+          {{ item.title }}
+        </li>
+      </ul>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { STORY_LIST } from "@guyuan/base";
+</script>
+
+<style lang="scss" scoped>
+@use "./index.scss";
+</style>

+ 0 - 40
packages/pc/src/views/Antique/constants.js

@@ -1,40 +0,0 @@
-// 三维文物
-export const ANTIQUE_THREE = [
-  {
-    label: "类别1",
-    children: [
-      {
-        label: "一级解放",
-        // 封面
-        thumb: "/base/images/xxx",
-        // 模型链接
-        link: "https://xxxx",
-        desc: "1955 年 9 月,韩练成被授予中将军衔、一级解放勋章。授衔 前,周恩来曾经征求他的意见。",
-      },
-    ],
-  },
-  {
-    label: "类别2",
-    children: [],
-  },
-];
-
-// 二维文物
-export const ANTIQUE_TWO = [
-  {
-    label: "类别3",
-    children: [
-      {
-        label: "一级解放勋章",
-        thumb: "/base/images/xxx",
-        // 图片列表
-        imgs: ["/base/images/xxx"],
-        desc: "1955 年 9 月,韩练成被授予中将军衔、一级解放勋章。授衔 前,周恩来曾经征求他的意见。",
-      },
-    ],
-  },
-  {
-    label: "类别2",
-    children: [],
-  },
-];

+ 1 - 1
packages/pc/src/views/Antique/index.vue

@@ -52,7 +52,7 @@
 
 <script setup>
 import { ref, computed } from "vue";
-import { ANTIQUE_THREE, ANTIQUE_TWO } from "./constants";
+import { ANTIQUE_THREE, ANTIQUE_TWO } from "@guyuan/base";
 import Popup from "./components/Popup.vue";
 
 const tabIndex = ref(0);

BIN
packages/pc/src/views/Home/components/Biographies/images/bg-min.jpg


+ 1 - 1
packages/pc/src/views/Home/components/SharePopup.vue

@@ -56,7 +56,7 @@ const saveQRCode = () => {
     const a = document.createElement("a");
     // @ts-ignore
     a.href = img[0].src;
-    a.download = "三亚家园.jpg";
+    a.download = "shareCode.jpg";
     a.click();
   }
 };

BIN
packages/pc/src/views/Home/images/c1-min.png


BIN
packages/pc/src/views/Home/images/c2-min.png


BIN
packages/pc/src/views/Home/images/c3-min.png


BIN
packages/pc/src/views/Home/images/c4-min.png


BIN
packages/pc/src/views/Home/images/c5-min.png


+ 0 - 0
packages/pc/src/views/Home/images/c6-min.png


이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.