shaogen1995 vor 2 Jahren
Ursprung
Commit
392ac3e69f

+ 2 - 2
重写子系统/public/model.html

@@ -18,8 +18,8 @@
   <div id="ui"></div>
   <script>
     let url = getQueryVariable("m");
-    fdage.embed(url, {
-      // fdage.embed('https://hnbwg.4dage.com' + url, {
+    // fdage.embed(url, {
+    fdage.embed('https://lsbwg.4dage.com' + url, {
       // fdage.embed('http://192.168.20.55:8041/api' + url, {
       transparentBackground: true,
       width: 800,

BIN
重写子系统/src/assets/img/icon-music.png


BIN
重写子系统/src/assets/img/icon-musicX.png


BIN
重写子系统/src/assets/img/icon-share.png


+ 1 - 1
重写子系统/src/assets/styles/base.css

@@ -90,7 +90,7 @@ textarea {
   /*滚动条里面小方块*/
   border-radius: 10px;
   -webkit-box-shadow: inset 0 0 5px transparent;
-  background: #8a7351;
+  background: var(--themeColor);
 }
 #root .myscroll::-webkit-scrollbar-track {
   /*滚动条里面轨道*/

+ 1 - 1
重写子系统/src/assets/styles/base.less

@@ -111,7 +111,7 @@ textarea {
     /*滚动条里面小方块*/
     border-radius: 10px;
     -webkit-box-shadow: inset 0 0 5px transparent;
-    background: #8a7351;
+    background: var(--themeColor);
   }
 
   .myscroll::-webkit-scrollbar-track {

+ 12 - 1
重写子系统/src/pages/A1Home/index.module.scss

@@ -1,4 +1,6 @@
 .A1Home {
+  position: relative;
+
   :global {
     .homeTop {
       width: 100%;
@@ -53,10 +55,18 @@
           align-items: center;
 
           .ant-btn {
+            border: 1px solid rgba(159, 25, 39, .6);
+            color: rgba(159, 25, 39, .6);
             height: 40px;
             border-radius: 20px;
             padding-left: 20px;
             padding-right: 20px;
+
+            &:hover {
+              border: 1px solid rgba(159, 25, 39, 1);
+              color: rgba(159, 25, 39, 1);
+
+            }
           }
 
           .ant-input-affix-wrapper {
@@ -134,7 +144,8 @@
               text-overflow: ellipsis;
               white-space: nowrap;
             }
-            &:nth-of-type(5n){
+
+            &:nth-of-type(5n) {
               margin-right: 0;
             }
           }

+ 19 - 11
重写子系统/src/pages/A1Home/index.tsx

@@ -1,18 +1,12 @@
-import React, {
-  useCallback,
-  useEffect,
-  useMemo,
-  useRef,
-  useState,
-} from "react";
+import React, { useCallback, useEffect, useRef, useState } from "react";
 import styles from "./index.module.scss";
 import { Button, Input, Pagination, Select } from "antd";
 import { useDispatch, useSelector } from "react-redux";
 import { A1_APIgetList, A1_APIgetSelect } from "@/store/action/A1Home";
 import { RootState } from "@/store";
 import { SearchOutlined } from "@ant-design/icons";
-import { A1_itemType } from "@/types";
 import ImageLazy from "@/components/ImageLazy";
+import A2Goods from "../A2Goods";
 function A1Home() {
   const dispatch = useDispatch();
 
@@ -84,6 +78,9 @@ function A1Home() {
     [fromObj]
   );
 
+  // 藏品详情id
+  const [goodsId, setGoodsId] = useState(0);
+
   return (
     <div className={styles.A1Home}>
       {/* 公共顶部 */}
@@ -91,7 +88,7 @@ function A1Home() {
         <h3>馆藏鉴赏</h3>
         <p>Collection Appreciation</p>
       </div>
-      {/* 首页滚动列表盒子 */}
+      {/* 首页列表盒子 */}
       <div className="homeMain">
         {/* 搜索 */}
         <div className="homeSearch">
@@ -115,13 +112,14 @@ function A1Home() {
           </div>
           <div className="homeSearchrr">
             <Input
+              style={{ width: 300 }}
               key={inputKey}
               placeholder="请输入文物标题"
               suffix={<SearchOutlined rev={undefined} />}
               maxLength={25}
               onChange={(e) => nameChange(e)}
             />
-            &emsp;
+            &emsp;&emsp;
             <Button onClick={resetSelectFu}>重置</Button>
           </div>
         </div>
@@ -133,7 +131,12 @@ function A1Home() {
           <div className="homeMainCon">
             <div className="homeRowBox">
               {list.map((v) => (
-                <div className="homeRow" title={v.name} key={v.id}>
+                <div
+                  className="homeRow"
+                  onClick={() => setGoodsId(v.id)}
+                  title={v.name}
+                  key={v.id}
+                >
                   <div className="homeRowT">
                     <ImageLazy
                       width="100%"
@@ -161,6 +164,11 @@ function A1Home() {
           />
         </div>
       </div>
+
+      {/* 文物详情页 */}
+      {goodsId ? (
+        <A2Goods id={goodsId} closePageFu={() => setGoodsId(0)} />
+      ) : null}
     </div>
   );
 }

+ 240 - 0
重写子系统/src/pages/A2Goods/index.module.scss

@@ -0,0 +1,240 @@
+.A2Goods {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 100;
+
+  :global {
+    .top {
+      width: 100%;
+      height: 180px;
+      background-image: url("../../assets/img/home/top.jpg");
+      background-size: 100% 100%;
+      color: #fff;
+      padding: 46px 0 0 160px;
+
+      h3 {
+        font-size: 36px;
+        font-weight: 400;
+      }
+
+      p {
+        font-size: 20px;
+        margin-top: 5px;
+      }
+    }
+
+    .main {
+      width: 100%;
+      height: calc(100% - 180px);
+      padding: 0px 0 80px;
+      background-image: url('../../assets/img/home/bg.jpg');
+      background-size: 100% 100%;
+      padding: 60px 140px 100px;
+
+      .mainCon {
+        width: 100%;
+        height: 100%;
+        display: flex;
+
+        .mainConll {
+          width: calc(60% - 80px);
+          margin-right: 80px;
+          background-image: linear-gradient(#75736E, #BCBBB8);
+          position: relative;
+
+          .flooRow {
+            position: absolute;
+            z-index: 99;
+            bottom: 20px;
+            left: 50%;
+            transform: translateX(-50%);
+            display: flex;
+
+            .row {
+              cursor: pointer;
+              padding: 0 20px;
+              height: 30px;
+              line-height: 28px;
+              border-radius: 15px;
+              border: 1px solid var(--themeColor);
+              color: var(--themeColor);
+              font-size: 14px;
+              background-color: #fff;
+              margin: 0 15px;
+            }
+
+            .active {
+              background-color: var(--themeColor);
+              color: #fff;
+              pointer-events: none;
+            }
+          }
+
+          // 左右按钮
+          .iconBtn {
+            position: absolute;
+            z-index: 99;
+            top: 50%;
+            transform: translateY(-50%);
+            left: 20px;
+            width: 50px;
+            height: 50px;
+            background-color: #696966;
+            border-radius: 50%;
+            cursor: pointer;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            color: #fff;
+            font-size: 30px;
+          }
+
+          .R_right {
+            left: auto;
+            right: 20px;
+          }
+
+          .R_arrowNo {
+            opacity: .4;
+            cursor: default;
+          }
+
+
+          .conMain {
+            opacity: 0;
+            pointer-events: none;
+            transition: all .3s;
+            position: absolute;
+            z-index: 20;
+            width: 100%;
+            height: 100%;
+
+            &>div {
+              width: 100%;
+              height: 100%;
+            }
+
+            .modelBox {
+              iframe {
+                width: 100%;
+                height: 100%;
+              }
+            }
+
+            .imgBox {
+              img {
+                object-fit: contain !important;
+              }
+            }
+
+            .videoBox {
+              position: relative;
+
+              video {
+                position: absolute;
+                top: 50%;
+                left: 50%;
+                transform: translate(-50%, -50%);
+                max-width: 100%;
+                max-height: calc(100% - 140px);
+              }
+            }
+          }
+
+          .conMainAc {
+            opacity: 1;
+            pointer-events: auto;
+          }
+        }
+
+        .noFileInfo {
+          background-image: linear-gradient(#75736E, #BCBBB8);
+          width: calc(60% - 80px);
+          margin-right: 80px;
+          display: flex;
+          justify-content: center;
+          align-items: center;
+          color: #fff;
+          font-size: 24px;
+
+        }
+
+        .mainConrr {
+          width: 40%;
+          position: relative;
+          padding-top: 50px;
+
+          .back {
+            position: absolute;
+            right: 0;
+            top: 0;
+            z-index: 9;
+
+            .ant-btn {
+              border: 1px solid rgba(159, 25, 39, .6);
+              padding-left: 20px;
+              padding-right: 20px;
+              height: 40px;
+              border-radius: 20px;
+              color: rgba(159, 25, 39, .6);
+
+              &:hover {
+                border: 1px solid rgba(159, 25, 39, 1);
+                color: rgba(159, 25, 39, 1);
+
+              }
+            }
+          }
+
+          .txtMain {
+            width: 100%;
+            height: calc(100% - 90px);
+            padding-right: 10px;
+            overflow-y: auto;
+
+            &>h3 {
+              font-size: 34px;
+              font-weight: 700;
+              color: var(--themeColor);
+              margin-bottom: 30px;
+            }
+
+            .ttTop {
+              font-size: 20px;
+              margin-bottom: 20px;
+              color: #333;
+            }
+
+            .ttTop2 {
+              margin-top: 30px;
+              font-size: 16px;
+              color: #666;
+              line-height: 22px;
+            }
+          }
+
+          .botBtn {
+            width: 100%;
+            height: 60px;
+            margin-top: 20px;
+            display: flex;
+
+            .row {
+              &>img {
+                width: 46px;
+                margin-bottom: 4px;
+              }
+
+              cursor: pointer;
+              text-align: center;
+              margin-right: 30px;
+            }
+          }
+        }
+      }
+    }
+  }
+}

+ 317 - 0
重写子系统/src/pages/A2Goods/index.tsx

@@ -0,0 +1,317 @@
+/* eslint-disable jsx-a11y/iframe-has-title */
+import React, {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from "react";
+import styles from "./index.module.scss";
+import { A2_APIgetInfo } from "@/store/action/A1Home";
+import { A1_itemType, A2_TabType, A2_fileObjType, A2_fileType } from "@/types";
+import { Button } from "antd";
+import history from "@/utils/history";
+import shareImg from "@/assets/img/icon-share.png";
+import musicImg from "@/assets/img/icon-music.png";
+import musicImgX from "@/assets/img/icon-musicX.png";
+import { baseURL } from "@/utils/http";
+import classNames from "classnames";
+import { LeftOutlined, RightOutlined } from "@ant-design/icons";
+import MemoImageLazy from "@/components/ImageLazy";
+
+type Props = {
+  id?: number;
+  closePageFu?: () => void;
+};
+
+function A2Goods({ id, closePageFu }: Props) {
+  // 从分享链接进来的id
+  const uidRef = useRef("");
+
+  // 底部 tab
+  const botTabTemp = useMemo(() => {
+    const arr: A2_TabType = [
+      { id: 1, type: "model", name: "模型", show: false },
+      { id: 2, type: "img", name: "图片", show: false },
+      { id: 3, type: "video", name: "视频", show: false },
+    ];
+    return arr;
+  }, []);
+  const [botTab, setBotTab] = useState(botTabTemp.filter((v) => v.show));
+
+  // 是否有上传音频
+  const [audioSrc, setAudioSrc] = useState("");
+  // 音频的播放和暂停
+  const [audioSta, setAudioSta] = useState(false);
+  const audioRef = useRef<HTMLAudioElement>(null);
+
+  useEffect(() => {
+    const dom = audioRef.current;
+    if (dom) {
+      if (audioSta) {
+        setAudioSta(true);
+        dom.play();
+        dom.onended = () => {
+          // 音频播放结束
+          setAudioSta(false);
+        };
+      } else {
+        setAudioSta(false);
+        dom.pause();
+      }
+    }
+  }, [audioSta]);
+
+  const getInfoFu = useCallback(
+    async (id: number) => {
+      const res = await A2_APIgetInfo(id);
+      if (res.code === 0) {
+        setInfo(res.data.entity);
+        // 处理附件信息
+
+        const tempArr = res.data.file || [];
+        const delAudioArr = tempArr.filter((v: any) => v.type !== "audio");
+
+        if (delAudioArr.length === 0) setNoFile(true);
+
+        const fileArr: A2_fileType[] = res.data.file || [];
+        const obj = {
+          model: [],
+          img: [],
+          video: [],
+          audio: [],
+        } as A2_fileObjType;
+
+        let audioTemp = "";
+
+        // 底部 type 应该高亮 哪一个
+        if (fileArr.find((v) => v.type === "model")) setType("model");
+        else if (fileArr.find((v) => v.type === "img")) setType("img");
+        else if (fileArr.find((v) => v.type === "video")) setType("video");
+
+        fileArr.forEach((v) => {
+          obj[v.type].push(v);
+
+          // 处理音频信息
+          if (v.type === "audio") audioTemp = v.filePath;
+
+          // 底部tab 应该显示 那几个
+          if (v.type === "model") botTabTemp[0].show = true;
+          if (v.type === "img") botTabTemp[1].show = true;
+          if (v.type === "video") botTabTemp[2].show = true;
+        });
+        setAudioSrc(audioTemp);
+
+        setBotTab(botTabTemp.filter((v) => v.show));
+
+        setFile(obj);
+      }
+    },
+    [botTabTemp]
+  );
+
+  // 藏品信息
+  const [info, setInfo] = useState({} as A1_itemType);
+
+  // 藏品附件
+  const [file, setFile] = useState<A2_fileObjType>({
+    model: [],
+    img: [],
+    video: [],
+    audio: [],
+  });
+
+  const [type, setType] = useState("" as "model" | "img" | "video" | "audio");
+
+  const [myInd, setMyInd] = useState(0);
+
+  useEffect(() => {
+    setMyInd(0);
+  }, [type]);
+
+  useEffect(() => {
+    if (id) getInfoFu(id);
+    else {
+      // 从分享的链接单独进来,从地址栏获取id
+    }
+  }, [getInfoFu, id]);
+
+  // 没有附件信息
+  const [noFile, setNoFile] = useState(false);
+
+  // 在页面展示的数据
+  const data = useMemo(() => {
+    const arr = file[type] || [];
+    return arr;
+  }, [file, type]);
+
+  // 点击返回
+  const backOrToHome = useCallback(() => {
+    if (id) closePageFu!();
+    else history.push("/");
+  }, [closePageFu, id]);
+
+  // 点击分享
+  const shareFu = useCallback(() => {
+    const goodId = id ? id : uidRef.current;
+    let OrderNumber = window.location.origin + "/web/#/goods?id=" + goodId;
+    let newInput = document.createElement("input");
+    newInput.value = OrderNumber;
+    document.body.appendChild(newInput);
+    newInput.select();
+    document.execCommand("Copy");
+    newInput.remove();
+    alert("复制链接成功");
+  }, [id]);
+
+  // 点击左右按钮
+  const cutIndFu = useCallback(
+    (num: number, flag: boolean) => {
+      const numRes = myInd + num;
+      if (flag) return;
+      setMyInd(numRes);
+    },
+    [myInd]
+  );
+
+  return (
+    <div className={styles.A2Goods}>
+      {/* 公共顶部 */}
+      <div className="top">
+        <h3>馆藏鉴赏</h3>
+        <p>Collection Appreciation</p>
+      </div>
+      {/* 主体 */}
+      <div className="main">
+        {audioSrc ? (
+          <audio src={baseURL + audioSrc} ref={audioRef}></audio>
+        ) : null}
+
+        <div className="mainCon">
+          {noFile ? (
+            <div className="noFileInfo">暂无信息</div>
+          ) : (
+            <div className="mainConll">
+              {/* 底部模块 */}
+              <div className="flooRow">
+                {botTab.map((v) => (
+                  <div
+                    onClick={() => setType(v.type)}
+                    className={classNames(
+                      "row",
+                      type === v.type ? "active" : ""
+                    )}
+                    key={v.id}
+                  >
+                    {v.name}
+                    {type === v.type && data.length > 1
+                      ? myInd + 1 + "/"
+                      : null}
+                    {file[v.type].length > 1 ? file[v.type].length : null}
+                  </div>
+                ))}
+              </div>
+
+              {/* 左右按钮 */}
+              <div
+                hidden={data.length <= 1}
+                onClick={() => cutIndFu(-1, myInd === 0)}
+                className={classNames(
+                  "R_left iconBtn",
+                  myInd === 0 ? "R_arrowNo" : ""
+                )}
+              >
+                <LeftOutlined rev={undefined} />
+              </div>
+              <div
+                hidden={data.length <= 1}
+                onClick={() => cutIndFu(1, myInd >= data.length - 1)}
+                className={classNames(
+                  "R_right iconBtn",
+                  myInd >= data.length - 1 ? "R_arrowNo" : ""
+                )}
+              >
+                <RightOutlined rev={undefined} />
+              </div>
+
+              {/* 内容主体 */}
+              {data.map((v, i) => (
+                <div
+                  className={classNames(
+                    "conMain",
+                    myInd === i ? "conMainAc" : ""
+                  )}
+                  key={v.id}
+                >
+                  {v.type === "model" && myInd === i ? (
+                    <div className="modelBox">
+                      <iframe
+                        src={`model.html?m=${v.filePath}`}
+                        frameBorder="0"
+                      ></iframe>
+                    </div>
+                  ) : v.type === "img" ? (
+                    <div className="imgBox">
+                      <MemoImageLazy
+                        src={v.filePath}
+                        width="100%"
+                        height="100%"
+                      />
+                    </div>
+                  ) : v.type === "video" && myInd === i ? (
+                    <div className="videoBox">
+                      <video src={baseURL + v.filePath} controls></video>
+                    </div>
+                  ) : null}
+                </div>
+              ))}
+            </div>
+          )}
+
+          <div className="mainConrr">
+            {/* 返回按钮 */}
+            <div className="back">
+              <Button onClick={backOrToHome}>{id ? "返回" : "首页"}</Button>
+            </div>
+            {/* 内容 */}
+            <div className="txtMain myscroll">
+              <h3>{info.name}</h3>
+              <div className="ttTop">
+                年代:
+                {info.dictAge}
+              </div>
+              <div className="ttTop">
+                尺寸:
+                {info.sizeSpecific}
+              </div>
+              <div className="ttTop2">
+                {info.description ? info.description : "暂无说明"}
+              </div>
+            </div>
+            {/* 分享,声音按钮 */}
+            <div className="botBtn">
+              <div className="row" onClick={shareFu}>
+                <img src={shareImg} alt="" />
+                <p>分享</p>
+              </div>
+              {audioSrc ? (
+                <div
+                  className="row"
+                  title={audioSta ? "关闭音频" : "打开音频"}
+                  onClick={() => setAudioSta(!audioSta)}
+                >
+                  <img src={audioSta ? musicImg : musicImgX} alt="" />
+                  <p>声音</p>
+                </div>
+              ) : null}
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
+
+const MemoA2Goods = React.memo(A2Goods);
+
+export default MemoA2Goods;

+ 7 - 0
重写子系统/src/store/action/A1Home.ts

@@ -47,3 +47,10 @@ export const A1_APIgetSelect = () => {
     }
   };
 };
+
+/**
+ * 通过id获取详情
+ */
+export const A2_APIgetInfo = (id: number) => {
+  return http.get(`show/ledger/detail/${id}`);
+};

+ 2 - 2
重写子系统/src/types/index.d.ts

@@ -1,2 +1,2 @@
-
-export * from './store/A1Home'
+export * from './store/A1Home'
+export * from './store/A2Goods'

+ 19 - 0
重写子系统/src/types/store/A2Goods.d.ts

@@ -0,0 +1,19 @@
+export type A2_fileType = {
+  filePath: string;
+  id: number;
+  type: "model" | "img" | "video" | "audio";
+};
+
+export type A2_fileObjType = {
+  model: A2_fileType[];
+  img: A2_fileType[];
+  video: A2_fileType[];
+  audio: A2_fileType[];
+};
+
+export type A2_TabType ={
+  id: number;
+  type: "model" | "img" | "video";
+  name: string;
+  show: boolean;
+}[]