Commit bda229309dd1a6e8575f97c24dfa1f3cbece4b80

Authored by 史婷婷
1 parent f40a6f53

feat: 生产线详情-预览功能:pdt(单个与批量)+回退自定义方法

... ... @@ -15,8 +15,8 @@
15 15 "axios": "^1.7.9",
16 16 "react": "^18.3.1",
17 17 "react-dom": "^18.3.1",
18   - "react-pdf": "^9.2.1",
19   - "react-router-dom": "^7.1.1"
  18 + "react-router-dom": "^7.1.1",
  19 + "lodash": "^4.17.11"
20 20 },
21 21 "devDependencies": {
22 22 "@eslint/js": "^9.17.0",
... ... @@ -33,6 +33,7 @@
33 33 "postcss-px-to-viewport": "^1.1.1",
34 34 "typescript": "~5.6.2",
35 35 "typescript-eslint": "^8.18.2",
36   - "vite": "^5.3.4"
  36 + "vite": "^5.3.4",
  37 + "@types/lodash": "^4.17.7"
37 38 }
38 39 }
... ...
... ... @@ -12,8 +12,8 @@ interface NavBarProps {
12 12 backContent?: any;
13 13 hiddenHead?: boolean;
14 14 customBack?: {
15   - icon: any;
16   - onClick: () => void;
  15 + icon?: any;
  16 + onClick?: () => void;
17 17 };
18 18 }
19 19
... ...
  1 +.pdfPreview {
  2 + width: 100%;
  3 + height: 100%;
  4 +}
  5 +
... ...
  1 +import { useEffect, useState } from 'react';
  2 +import './index.less';
  3 +
  4 +interface pdfPreviewProps {
  5 + url: string
  6 +}
  7 +
  8 +const pdfPreview = (props: pdfPreviewProps) => {
  9 + const [filePath, setFilePath] = useState<string>();
  10 +
  11 + useEffect(()=>{
  12 + if (props.url) {
  13 + setFilePath(props.url);
  14 + }
  15 + },[props.url])
  16 +
  17 +
  18 + return (
  19 + <div className={'pdfPreview'}>
  20 + {/* pdf属性 page 跳转到指定页码,navpanes 控制左侧的缩略图预览导航是否默认打开。0-关闭,1-打开*/}
  21 + {/* navpanes=0&scrollbars=0&toolbar=0&statusbar=0 去除缩略图和工具栏 */}
  22 + {/* frameborder=0 和view=FitH,top 为全屏展示 */}
  23 + <iframe
  24 + title="pdf-preview"
  25 + style={{ width: '100%', height: '100%' }}
  26 + frameborder="0"
  27 + src={`${filePath}#page=1&navpanes=0&scrollbars=0&toolbar=0&statusbar=0&view=FitH,top`}
  28 + // src={`${filePath}`}
  29 + />
  30 + </div>
  31 + );
  32 +};
  33 +
  34 +export default pdfPreview;
\ No newline at end of file
... ...
src/components/video-play.tsx renamed from src/components/videoPlay.tsx
... ... @@ -25,7 +25,6 @@ a:hover {
25 25 body {
26 26 margin: 0;
27 27 min-height: 100vh;
28   - background: pink;
29 28 }
30 29
31 30 h1 {
... ...
1 1 import React, {useEffect, useState} from 'react'
2 2 import './style.less'
3 3 import NavBar from '@/components/nav-bar'
4   -import VideoPlay from '@/components/videoPlay'
  4 +import VideoPlay from '@/components/video-play'
  5 +import PdfPreview from '@/components/pdf-preview'
5 6 import {useSearchParams} from "react-router-dom";
6   -import { Document, Page, pdfjs } from "react-pdf";
7   -import 'react-pdf/dist/esm/Page/AnnotationLayer.css'
8   -import 'react-pdf/dist/esm/Page/TextLayer.css';
9 7 import {getCarouselSettings} from "@/api/apiConfig";
10   -pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.js`;
  8 +import _ from 'lodash';
  9 +import { useNavigate } from 'react-router-dom';
11 10
12 11
13 12 const ProductionDetail: React.FC = () => {
  13 + let navigate = useNavigate();
14 14 const [title, setTitle] = useState<string>('');
15 15 const [filePathItem, setFilePathItem] = useState();
16 16 // 自动预览 定时器
... ... @@ -23,8 +23,6 @@ const ProductionDetail: React.FC = () => {
23 23
24 24 const sxPreViewList = localStorage.getItem('sxPreViewListStorage') ? JSON.parse(localStorage.getItem('sxPreViewListStorage')) : [];
25 25
26   - console.log('sxPreViewList', sxPreViewList)
27   -
28 26 useEffect(() => {
29 27 if (sxPreViewList?.length) {
30 28 const _isLoop = sxPreViewList?.length > 1;
... ... @@ -68,6 +66,9 @@ const ProductionDetail: React.FC = () => {
68 66
69 67 useEffect(() => {
70 68 console.log('filePathItem', filePathItem)
  69 + if (!_.isEmpty(filePathItem)) {
  70 + setTitle(filePathItem?.name)
  71 + }
71 72 }, [filePathItem])
72 73
73 74
... ... @@ -75,7 +76,11 @@ const ProductionDetail: React.FC = () => {
75 76 return (
76 77 <div className={'sxjx-content-main sxjx-layout-main-unfoot'}>
77 78 <div className={'production-detail'}>
78   - <NavBar showBack={true} title={title}/>
  79 + <NavBar showBack={true} title={title} customBack={{onClick: () => {
  80 + const _url = localStorage.getItem('sxListPath');
  81 + navigate(_url, { replace: true });
  82 + }}}
  83 + />
79 84 {
80 85 filePathItem?.type === 'mp4' ? <div className={'production-detail-video-box'}>
81 86 <VideoPlay
... ... @@ -83,8 +88,7 @@ const ProductionDetail: React.FC = () => {
83 88 url={filePathItem?.url || ''}
84 89 className={'production-detail-video'}
85 90 />
86   - </div> : <>
87   - </>
  91 + </div> : filePathItem?.type === 'pdf' ? <PdfPreview url={filePathItem?.url}/> : ''
88 92 }
89 93 </div>
90 94 </div>
... ...
... ... @@ -8,8 +8,7 @@ import _preview from './preview.png';
8 8 import {useSearchParams} from "react-router-dom";
9 9 import {getFilePreview, getProductBook} from "@/api/apiConfig";
10 10 import {SpinLoading, Checkbox, Toast} from 'antd-mobile'
11   -import { useNavigate } from "react-router-dom";
12   -import {a} from "vite/dist/node/types.d-aGj9QkWt";
  11 +import { useNavigate, useLocation } from "react-router-dom";
13 12
14 13 interface ListType {
15 14 id: string;
... ... @@ -26,21 +25,18 @@ const ProductionList: React.FC = () => {
26 25 const [show, setShow] = useState<boolean>(false);
27 26 const [showBatch, setShowBatch] = useState<boolean>(false);
28 27 const navigate = useNavigate();
  28 + const location = useLocation();
  29 + console.log('location', location?.pathname, location?.search)
29 30 const [checkItems, setCheckItems] = useState<CheckboxValue[]>([])
30 31 const [checkValues, setCheckValues] = useState<CheckboxValue[]>([])
31   - // const [sxPreViewList, setSxPreViewList] = useState<ListType[]>([])
32 32
33 33
34 34 // 因是hook,必须写在组件的顶部执行,useSearchParams() 返回的是数组
35 35 const [params] = useSearchParams();
36   - console.log('ProductionList===params', params)
37 36 // 通过 get 方法获取目标参数
38 37 const name = params.get("name") || "";
39 38 const id = params.get("id") || "";
40 39
41   - useEffect(() => {
42   - localStorage.setItem('sxPreViewListStorage', '');
43   - }, [])
44 40
45 41 useEffect(() => {
46 42 if (name) {
... ... @@ -55,7 +51,7 @@ const ProductionList: React.FC = () => {
55 51 setShow(true);
56 52 let _checkItems = [];
57 53 const _list = res?.product_book?.map((item: any) => {
58   - _checkItems.push(item?.guide_book_file_info_?.[0]?.fileId);
  54 + _checkItems.push(item?.id);
59 55 const _arr = item?.guide_book_file_info_?.[0]?.name?.split('.') || [];
60 56 return {
61 57 id: item?.id || '',
... ... @@ -83,7 +79,6 @@ const ProductionList: React.FC = () => {
83 79 )
84 80
85 81 const checkboxChange = (value: CheckboxValue[]) => {
86   - console.log('checkboxChange-value', value)
87 82 setCheckValues(value)
88 83 }
89 84
... ... @@ -96,10 +91,8 @@ const ProductionList: React.FC = () => {
96 91
97 92
98 93 const toDetail = async (ids: CheckboxValue[]) => {
99   - console.log('toDetail-ids', ids)
100 94 if (ids?.length) {
101 95 let _arr = list?.filter((item: ListType) => ids?.includes(item?.id || '')) || [];
102   - console.log('_arr', _arr)
103 96 // 创建一个promise数组,每个promise都是对API的一次调用
104 97 const promises = _arr?.map((item: ListType) => fetchData(item));
105 98 // 使用Promise.all来并行地解决这些promise
... ... @@ -111,16 +104,17 @@ const ProductionList: React.FC = () => {
111 104 url: results?.[index]
112 105 }
113 106 })
114   - console.log('sxPreViewList', sxPreViewList)
115 107 localStorage.setItem('sxPreViewListStorage', JSON.stringify(sxPreViewList));
116   - navigate(`/production/detail?name=${sxPreViewList?.[0]?.name}`);
  108 + localStorage.setItem('sxListPath', `${location?.pathname}${location?.search}`);
  109 + navigate(`/production/detail?name=${sxPreViewList?.[0]?.name}`, { replace: true });
117 110 })
118 111 .catch(err => {
119 112 localStorage.setItem('sxPreViewListStorage', '');
120   - console.log('err', err)
  113 + localStorage.setItem('sxListPath', '');
121 114 });
122 115 } else {
123 116 localStorage.setItem('sxPreViewListStorage', '');
  117 + localStorage.setItem('sxListPath', '');
124 118 Toast.show({
125 119 content: '请先选择数据!',
126 120 maskClassName: 'to-detail-mask',
... ... @@ -129,19 +123,15 @@ const ProductionList: React.FC = () => {
129 123
130 124 }
131 125
132   - // useEffect(() => {
133   - // console.log('sxPreViewList', sxPreViewList)
134   - // if (sxPreViewList?.length) {
135   - // const _name = sxPreViewList?.[0]?.name;
136   - // console.log('_name', _name)
137   - // navigate(`/production/detail?name=${_name}`);
138   - // }
139   - // }, [sxPreViewList])
140   -
141 126 return (
142 127 <div className={'sxjx-content-main sxjx-layout-main-unfoot'}>
143 128 <div className={`production-list ${showBatch ? 'production-list--batch' : ''}`}>
144   - <NavBar title={title} showBack={true} rightInfo={ !showBatch ? rightInfo : ''}/>
  129 + <NavBar title={title} showBack={true} rightInfo={ !showBatch ? rightInfo : ''}
  130 + customBack={{onClick: () => {
  131 + const _url = '/production/management';
  132 + navigate(_url, { replace: true });
  133 + }}}
  134 + />
145 135 {
146 136 !show ? <SpinLoading color='primary'/> :
147 137 <div className={'production-list_list'}>
... ... @@ -184,6 +174,7 @@ const ProductionList: React.FC = () => {
184 174 indeterminate={checkValues.length > 0 && checkValues?.length < checkItems?.length}
185 175 checked={checkValues?.length === checkItems?.length}
186 176 onChange={checked => {
  177 + console.log('checked', checked)
187 178 if (checked) {
188 179 setCheckValues(checkItems)
189 180 } else {
... ...
... ... @@ -36,7 +36,6 @@ const ProductionManagement: React.FC = () => {
36 36 }, [])
37 37
38 38 const toProductionList = (item: any) => {
39   - console.log('toProductionList-item', item)
40 39 navigate(`/production/list?id=${item?.id}&name=${item?.name}`);
41 40 }
42 41
... ...