shaogen1995 9 月之前
父節點
當前提交
6da1c4d838

二進制
web/src/assets/img/goods/left.png


二進制
web/src/assets/img/goods/right.png


+ 52 - 3
web/src/assets/styles/base.css

@@ -9,8 +9,7 @@ html {
   user-select: none;
 }
 body {
-  font: 1em/1.4 'Microsoft Yahei', 'PingFang SC', 'Avenir', 'Segoe UI', 'Hiragino Sans GB',
-    'STHeiti', 'Microsoft Sans Serif', 'WenQuanYi Micro Hei', sans-serif;
+  font: 1em/1.4 'Microsoft Yahei', 'PingFang SC', 'Avenir', 'Segoe UI', 'Hiragino Sans GB', 'STHeiti', 'Microsoft Sans Serif', 'WenQuanYi Micro Hei', sans-serif;
   height: 100%;
   color: black;
 }
@@ -86,6 +85,57 @@ textarea {
 #root .ant-image {
   display: none;
 }
+#root .ant-carousel {
+  width: 100%;
+  height: 100%;
+}
+#root .ant-carousel .slick-slider,
+#root .ant-carousel .slick-track,
+#root .ant-carousel .slick-slide,
+#root .ant-carousel .slick-list {
+  width: 100%;
+  height: 100%;
+}
+#root .ant-carousel .slick-slide > div {
+  width: 100%;
+  height: 100%;
+}
+#root .ant-carousel .adm-image {
+  width: 100% !important;
+  height: 100% !important;
+}
+#root .ant-carousel .slick-arrow {
+  width: 40px;
+  height: 40px;
+  left: -50px;
+}
+#root .ant-carousel .slick-arrow::before {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 40px;
+  height: 40px;
+  background-image: url('../img/goods/left.png');
+  background-size: 100% 100%;
+}
+#root .ant-carousel .slick-next {
+  left: auto;
+  right: -50px;
+}
+#root .ant-carousel .slick-next::before {
+  background-image: url('../img/goods/right.png');
+  background-size: 100% 100%;
+}
+#root .ant-carousel .slick-dots {
+  bottom: -20px;
+}
+#root .ant-carousel .slick-dots li button {
+  opacity: 1;
+  background-color: #fff;
+}
+#root .ant-carousel .slick-dots .slick-active button {
+  background-color: var(--themeColor);
+}
 [hidden] {
   display: none !important;
 }
@@ -126,7 +176,6 @@ textarea {
   background: rgba(0, 0, 0, 0.2);
 }
 #root {
-  /* 待完善 */
   /*横屏*/
 }
 #root #ScreenChange {

+ 57 - 0
web/src/assets/styles/base.less

@@ -102,6 +102,63 @@ textarea {
   .ant-image {
     display: none;
   }
+
+  // 走马灯样式
+  .ant-carousel {
+    width: 100%;
+    height: 100%;
+    .slick-slider,
+    .slick-track,
+    .slick-slide,
+    .slick-list {
+      width: 100%;
+      height: 100%;
+    }
+    .slick-slide > div {
+      width: 100%;
+      height: 100%;
+    }
+    .adm-image {
+      width: 100% !important;
+      height: 100% !important;
+    }
+
+    // 左右箭头
+    .slick-arrow {
+      width: 40px;
+      height: 40px;
+      left: -50px;
+      &::before {
+        position: absolute;
+        top: 0;
+        left: 0;
+        width: 40px;
+        height: 40px;
+        background-image: url('../img/goods/left.png');
+        background-size: 100% 100%;
+      }
+    }
+    .slick-next {
+      left: auto;
+      right: -50px;
+      &::before {
+        background-image: url('../img/goods/right.png');
+        background-size: 100% 100%;
+      }
+    }
+
+    // 下面的指示标
+    .slick-dots {
+      bottom: -20px;
+      li button {
+        opacity: 1;
+        background-color: #fff;
+      }
+      .slick-active button {
+        background-color: var(--themeColor);
+      }
+    }
+  }
 }
 
 [hidden] {

+ 1 - 18
web/src/pages/A3goods/A3look/index.module.scss

@@ -26,24 +26,7 @@
       .LmainCen {
         width: 100%;
         height: 490px;
-        .ant-carousel {
-          width: 100%;
-          height: 100%;
-          .adm-image {
-            width: 100% !important;
-            height: 490px !important;
-          }
-          .slick-dots {
-            bottom: -20px;
-            li button {
-              opacity: 1;
-              background-color: #fff;
-            }
-            .slick-active button {
-              background-color: var(--themeColor);
-            }
-          }
-        }
+
         .Limg {
           width: 100%;
           height: 100%;

+ 1 - 1
web/src/pages/A3goods/A3look/index.tsx

@@ -42,7 +42,7 @@ function A3look({ closeFu, id }: Props) {
           <div className={classNames('Lmain', info.fileType === 'model' ? 'LmainFull' : '')}>
             <div className='LmainCen'>
               {info.fileType === 'img' ? (
-                <Carousel>
+                <Carousel arrows infinite={false}>
                   {file.map(v => (
                     <div
                       key={v.id}

+ 106 - 0
web/src/pages/A4expert/A4look/index.module.scss

@@ -0,0 +1,106 @@
+.A4look {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  z-index: 10;
+  padding: 7% 10% 9%;
+  :global {
+    .Lcolse {
+      z-index: 10;
+      cursor: pointer;
+      position: absolute;
+      top: 20px;
+      right: 20px;
+      width: 50px;
+    }
+
+    .A4Lmani {
+      width: 100%;
+      height: 100%;
+      display: flex;
+      justify-content: space-between;
+      .A4Lll {
+        margin-right: 80px;
+        width: 580px;
+        height: 100%;
+        display: inline-block;
+
+        .Limg {
+          width: 100%;
+          height: 100%;
+
+          & > div {
+            cursor: zoom-in;
+            width: 100%;
+            height: 100%;
+            img {
+              pointer-events: none;
+              width: 100%;
+              height: 100%;
+              object-fit: contain !important;
+            }
+          }
+
+          video {
+            width: 100%;
+            height: 100%;
+            object-fit: contain;
+          }
+        }
+      }
+      .A4Lrr {
+        width: calc(100% - 660px);
+        height: 100%;
+        .A4Lrr1 {
+          display: flex;
+          padding-bottom: 15px;
+          border-bottom: 2px solid var(--themeColor2);
+          margin-bottom: 30px;
+          justify-content: space-between;
+          align-items: center;
+          & > h1 {
+            color: var(--themeColor2);
+            font-weight: 700;
+            font-size: 34px;
+            margin-right: 20px;
+          }
+        }
+        .A4Lrr2 {
+          display: flex;
+          margin-bottom: 20px;
+          .A4Lrr2_1 {
+            width: 80px;
+            height: 26px;
+            display: flex;
+            align-items: center;
+            & > img {
+              width: 26px;
+              height: 26px;
+            }
+            & > span {
+              font-weight: 700;
+              font-size: 16px;
+              color: var(--themeColor2);
+            }
+          }
+
+          .A4Lrr2_2 {
+            width: calc(100% - 80px);
+            font-size: 16px;
+            letter-spacing: 4px;
+          }
+        }
+        .A4Lrr3 {
+          padding-right: 15px;
+          height: calc(100% - 235px);
+          overflow-y: auto;
+          line-height: 30px;
+          font-size: 16px;
+          letter-spacing: 4px;
+        }
+      }
+    }
+  }
+}

+ 109 - 0
web/src/pages/A4expert/A4look/index.tsx

@@ -0,0 +1,109 @@
+import React, { useCallback, useEffect, useRef, useState } from 'react'
+import styles from './index.module.scss'
+
+import LazyImg from '@/components/LazyImg'
+
+// 图片导入
+import topBgImg from '@/assets/img/goods/close.png'
+import li1Img from '@/assets/img/expert/li1.png'
+import li3Img from '@/assets/img/expert/li3.png'
+
+import { getExpertInfo } from '@/store/action/all'
+import { FileType, GoodsRow } from '@/types'
+import { baseURL } from '@/utils/http'
+import { Carousel } from 'antd'
+import store from '@/store'
+
+type Props = {
+  editId: number
+  closeFu: () => void
+}
+
+function A4look({ editId, closeFu }: Props) {
+  const getInfoFu = useCallback(async (id: number) => {
+    const res = await getExpertInfo(id)
+    if (res.code === 0) {
+      setInfo(res.data.entity)
+
+      const fileArr: FileType[] = res.data.file
+      setFile(fileArr)
+    }
+  }, [])
+
+  useEffect(() => {
+    getInfoFu(editId)
+  }, [editId, getInfoFu])
+
+  const [info, setInfo] = useState({} as GoodsRow)
+
+  const [file, setFile] = useState([] as FileType[])
+
+  // 视频播放暂停逻辑
+  const videoRef = useRef<HTMLVideoElement>(null)
+
+  const beforeChange = useCallback(() => {
+    videoRef.current?.pause()
+  }, [])
+
+  return (
+    <div id='LookGood' className={styles.A4look}>
+      {/* 关闭按钮 */}
+      <img onClick={closeFu} className='Lcolse' src={topBgImg} alt='' />
+
+      <div className='A4Lmani'>
+        <div className='A4Lll'>
+          <Carousel arrows infinite={false} beforeChange={beforeChange}>
+            {file.map(v => (
+              <div key={v.id} className='Limg'>
+                {v.type === 'img' ? (
+                  <div
+                    onClick={() =>
+                      store.dispatch({
+                        type: 'layout/lookBigImg',
+                        payload: { url: baseURL + v.filePath, show: true }
+                      })
+                    }
+                  >
+                    <LazyImg src={baseURL + v.thumb} />
+                  </div>
+                ) : (
+                  <video ref={videoRef} controls src={baseURL + v.filePath}></video>
+                )}
+              </div>
+            ))}
+          </Carousel>
+        </div>
+
+        <div className='A4Lrr'>
+          <div className='A4Lrr1'>
+            <h1>{info.name}</h1>
+          </div>
+
+          <div className='A4Lrr2'>
+            <div className='A4Lrr2_1'>
+              <img src={li1Img} alt='' />
+              <span>简介:</span>
+            </div>
+
+            <div className='A4Lrr2_2'>{info.intro || '(空)'}</div>
+          </div>
+
+          <div className='A4Lrr2'>
+            <div className='A4Lrr2_1'>
+              <img src={li3Img} alt='' />
+              <span>介绍:</span>
+            </div>
+          </div>
+
+          <div className='A4Lrr3 mySorrl'>
+            <div dangerouslySetInnerHTML={{ __html: info.remark || '(空)' }}></div>
+          </div>
+        </div>
+      </div>
+    </div>
+  )
+}
+
+const MemoA4look = React.memo(A4look)
+
+export default MemoA4look

+ 7 - 0
web/src/pages/A4expert/data.ts

@@ -0,0 +1,7 @@
+export type FromDataType = {
+  searchKey: string
+  dictId: number | null
+
+  pageNum: number
+  pageSize: number
+}

+ 49 - 39
web/src/pages/A4expert/index.module.scss

@@ -2,6 +2,7 @@
   background-size: 100% 100%;
   padding: 5% 5% 4% 5%;
   position: relative;
+  background-image: url('../../assets/img/expert/bg.jpg');
   :global {
     .A4top {
       height: 90px;
@@ -17,6 +18,14 @@
         display: flex;
         height: 100%;
         align-items: center;
+        max-width: 1000px;
+        width: auto;
+        .appSw {
+          width: calc(100% - 320px);
+        }
+        .swiper-slide {
+          width: auto !important;
+        }
         .A4trRow {
           cursor: pointer;
           padding: 0 14px;
@@ -25,7 +34,7 @@
         }
         .A4trRowAc {
           pointer-events: none;
-          color: #fcda99;
+          color: #fff;
           background-color: var(--themeColor2);
           border-radius: 15px;
         }
@@ -34,13 +43,16 @@
           margin-left: 24px;
           display: flex;
           height: 32px;
-          border-radius: 16px;
+          border-radius: 0 8px 8px 0;
           overflow: hidden;
           width: 230px;
           background-color: #fff;
+          .ant-input-affix-wrapper {
+            border-radius: 8px 0 0 8px;
+          }
           input {
+            border-radius: 0;
             width: 190px;
-            padding: 0 15px;
             border: none;
             outline: none;
             outline: 0;
@@ -71,7 +83,6 @@
             display: flex;
             justify-content: center;
             align-items: center;
-            cursor: pointer;
             font-size: 24px;
             color: #fff;
           }
@@ -84,18 +95,18 @@
       width: 100%;
       height: calc(100% - 130px);
       padding-bottom: 80px;
-      overflow-x: auto;
 
       .A4mBox {
         display: flex;
         height: 100%;
         .A4mRow {
-          width: 310px;
+          width: calc(20% - 16px);
           height: 100%;
-          margin-right: 30px;
+          margin-right: 20px;
           padding-bottom: 50px;
 
           & > div {
+            transition: all 0.5s;
             cursor: pointer;
             width: 100%;
             height: 100%;
@@ -107,27 +118,39 @@
             .A4mRtitle {
               position: relative;
               width: 100%;
-              margin: 30px 0 10px;
+              margin: 20px 0;
               color: var(--themeColor2);
               font-weight: 700;
-              font-size: 24px;
+              font-size: 20px;
               background-size: 100% 100%;
-              padding: 0 20px;
+              padding: 0 52px;
+              background-image: url('../../assets/img/expert/mjfc.png');
+              & > div {
+                width: 100%;
+                height: 100%;
+                overflow: hidden;
+                text-overflow: ellipsis;
+                white-space: nowrap;
+              }
             }
-            .A4mRtitle2 {
-              margin-bottom: 24px;
-              color: #999;
+
+            .A4mRtitleDuo {
+              margin-top: 60px;
             }
+
             .A4mRtxt {
+              text-align: left;
               line-height: 20px;
               letter-spacing: 2px;
               color: #333;
+              height: 60px;
+              overflow: auto;
             }
 
             .A4mRowShow {
               position: relative;
               z-index: 2;
-              padding: 50px;
+              padding: 40px;
               text-align: center;
               background-color: #faf3e6;
               width: 100%;
@@ -136,41 +159,25 @@
               pointer-events: auto;
               transition: opacity 0.5s;
               .adm-image {
-                height: 220px !important;
+                height: 270px !important;
                 img {
                   pointer-events: none;
-                  width: 90%;
-                  height: 220px;
+                  width: 100%;
+                  height: 100%;
                   object-fit: cover !important;
                   display: inline-block;
                 }
               }
             }
-            .A4mRowMoveShow {
-              position: absolute;
-              top: 0;
-              left: 0;
-              width: 100%;
-              height: 100%;
-              background-size: 100% 100%;
-              padding: 50px;
-              text-align: center;
-              .A4mRowMoveShowInco {
-                position: absolute;
-                bottom: 80px;
-                left: 50%;
-                transform: translateX(-50%);
-                width: 50px;
-                pointer-events: none;
-              }
-            }
+
             &:hover {
-              .A4mRowShow {
-                opacity: 0;
-                pointer-events: none;
-              }
+              border: 4px solid #f58543;
+              transform: scale(1.05);
             }
           }
+          &:nth-of-type(5n) {
+            margin-right: 0;
+          }
         }
         .A4mRowOu {
           padding: 50px 0 0;
@@ -211,5 +218,8 @@
         }
       }
     }
+    .pageBox {
+      text-align: right;
+    }
   }
 }

+ 171 - 6
web/src/pages/A4expert/index.tsx

@@ -1,13 +1,178 @@
-import React from 'react'
+import React, { useCallback, useEffect, useRef, useState } from 'react'
 import styles from './index.module.scss'
-function AAAAA() {
+import LeftTopLogo from '@/components/LeftTopLogo'
+import { SearchOutline } from 'antd-mobile-icons'
+import classNames from 'classnames'
+import LazyImg from '@/components/LazyImg'
+
+import { Swiper, SwiperSlide } from 'swiper/react'
+
+import { FreeMode, Mousewheel } from 'swiper'
+// Import Swiper styles
+import 'swiper/css'
+import 'swiper/css/free-mode'
+import 'swiper/css/mousewheel'
+
+import { getDictList, getExpertList } from '@/store/action/all'
+import { DictType, ExpertType, GoodsRow } from '@/types'
+import { FromDataType } from './data'
+import { Input, Pagination } from 'antd'
+import { baseURL } from '@/utils/http'
+
+// 图片导入
+import topBgImg from '@/assets/img/expert/topBg.png'
+import nullImg from '@/assets/img/goods/null.png'
+import A4look from './A4look'
+
+function A4expert() {
+  const [topArr, setTopArr] = useState<DictType[]>([])
+
+  const getDictListFu = useCallback(async () => {
+    const res = await getDictList()
+    if (res.code === 0) {
+      setTopArr([{ id: null, name: '全部' }, ...res.data])
+    }
+  }, [])
+
+  useEffect(() => {
+    getDictListFu()
+  }, [getDictListFu])
+
+  const [fromData, setFromData] = useState<FromDataType>({
+    searchKey: '',
+    dictId: null,
+    pageNum: 1,
+    pageSize: 5
+  })
+
+  // 输入框的输入
+  const timeRef = useRef(-1)
+  const txtChangeFu = useCallback(
+    (e: React.ChangeEvent<HTMLInputElement>, key: 'searchKey') => {
+      clearTimeout(timeRef.current)
+      timeRef.current = window.setTimeout(() => {
+        setFromData({ ...fromData, [key]: e.target.value.replaceAll("'", ''), pageNum: 1 })
+      }, 500)
+    },
+    [fromData]
+  )
+
+  // 列表数据
+  const [listObj, setListObj] = useState<ExpertType>({ list: [], total: 0 })
+  const [loding, setLoding] = useState(false)
+
+  const getListFu = useCallback(async () => {
+    const res = await getExpertList(fromData)
+    if (res.code === 0) {
+      setLoding(true)
+      setListObj({ list: res.data.records || [], total: res.data.total })
+    }
+  }, [fromData])
+
+  useEffect(() => {
+    getListFu()
+  }, [getListFu])
+
+  // 平时展示 和 鼠标移入的相同dom
+  const rowTongDom = useCallback((info: GoodsRow) => {
+    return (
+      <>
+        <div className={classNames('A4mRtitle', info.intro ? '' : 'A4mRtitleDuo')}>
+          <div>{info.name}</div>
+        </div>
+        <div className='A4mRtxt mySorrl'>{info.intro}</div>
+      </>
+    )
+  }, [])
+
+  const [editId, setEditId] = useState(0)
+
   return (
-    <div className={styles.AAAAA}>
-      <h1>AAAAA</h1>
+    <div className={styles.A4expert}>
+      <LeftTopLogo />
+
+      <div className='A4top' hidden={!!editId}>
+        <img className='A4topll' src={topBgImg} alt='' />
+        <div className='A4toprr'>
+          类型:&nbsp;&nbsp;
+          <Swiper
+            modules={[FreeMode, Mousewheel]}
+            className='appSw'
+            spaceBetween={0}
+            slidesPerView='auto'
+            freeMode={true}
+            mousewheel={true}
+          >
+            {topArr.map(v => (
+              <SwiperSlide key={v.id}>
+                <div
+                  onClick={() => setFromData({ ...fromData, pageNum: 1, dictId: v.id })}
+                  className={classNames('A4trRow', fromData.dictId === v.id ? 'A4trRowAc' : '')}
+                  key={v.id}
+                >
+                  {v.name}
+                </div>
+              </SwiperSlide>
+            ))}
+          </Swiper>
+          <div className='A4trInp'>
+            <Input
+              placeholder='请输入搜索内容'
+              allowClear
+              onChange={e => txtChangeFu(e, 'searchKey')}
+            />
+            <div className='A4trInpInco'>
+              <SearchOutline />
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <div hidden={!!editId} className='A4main'>
+        {listObj.list.length ? (
+          <div className='A4mBox'>
+            {listObj.list.map((v, i) => (
+              <div
+                onClick={() => setEditId(v.id)}
+                title={v.name}
+                className={classNames('A4mRow', i % 2 === 0 ? 'A4mRowOu' : '')}
+                key={v.id}
+              >
+                <div>
+                  <div className='A4mRowShow'>
+                    <LazyImg src={baseURL + v.thumb} />
+                    {rowTongDom(v)}
+                  </div>
+                </div>
+              </div>
+            ))}
+          </div>
+        ) : (
+          <div className='A4mNull' hidden={!loding}>
+            <img src={nullImg} alt='' />
+            <p>暂时没有数据</p>
+            <p>请试一下其他关键字</p>
+          </div>
+        )}
+      </div>
+
+      {/* 分页 */}
+      <div className='pageBox' hidden={!!editId}>
+        <Pagination
+          current={fromData.pageNum}
+          pageSize={fromData.pageSize}
+          onChange={(pageNum, pageSize) => setFromData({ ...fromData, pageNum, pageSize })}
+          total={listObj.total}
+        />
+        ;
+      </div>
+
+      {/* 查看详情 */}
+      {editId ? <A4look editId={editId} closeFu={() => setEditId(0)} /> : null}
     </div>
   )
 }
 
-const MemoAAAAA = React.memo(AAAAA)
+const MemoA4expert = React.memo(A4expert)
 
-export default MemoAAAAA
+export default MemoA4expert

+ 21 - 0
web/src/store/action/all.ts

@@ -20,3 +20,24 @@ export const getGoodsList = (data: any) => {
 export const getGoodsInfo = (id: number) => {
   return http.get(`show/goods/detail/${id}`)
 }
+
+/**
+ * 获取专家字典列表
+ */
+export const getDictList = () => {
+  return http.get(`show/dict/getList?type=expert`)
+}
+
+/**
+ * 获取专家数据列表
+ */
+export const getExpertList = (data: any) => {
+  return http.post('show/expert/pageList', data)
+}
+
+/**
+ * 获取专家详情
+ */
+export const getExpertInfo = (id: number) => {
+  return http.get(`show/expert/detail/${id}`)
+}

+ 15 - 0
web/src/types/api/layot.d.ts

@@ -15,6 +15,7 @@ export type GoodsRow = {
   thumb: string
   thumbPc: string
   updateTime: string
+  intro: string
 }
 
 export type FileType = {
@@ -29,3 +30,17 @@ export type FileType = {
   type: string
   updateTime: string
 }
+
+export type DictType = {
+  creatorName: string
+  id: number
+  name: string
+  rtf: string
+  sort: number
+  type: string
+}
+
+export type ExpertType = {
+  list: GoodsRow[]
+  total: number
+}