| | |
| | | |
| | | |
| | | |
| | | <!-- æä½æé®åº --> |
| | | <view class="action-buttons" v-if="this.current"> |
| | | <button class="secondary-btn" @click="handleEmergencyRelease">ç´§æ¥æ¾è¡</button> |
| | | <button class="secondary-btn" @click="handleWithdraw">æ¤å</button> |
| | | <button class="secondary-btn" @click="getInspectionItems">è·åæ£éªé¡¹ç®</button> |
| | | </view> |
| | | |
| | | |
| | | |
| | |
| | | </table> |
| | | </view> |
| | | |
| | | <!-- æä½æé®åº --> |
| | | <view class="action-buttons"> |
| | | <button class="secondary-btn" @click="addDestruction" v-if="this.current">ç ´åå®éª</button> |
| | | <button class="secondary-btn" @click="uploadImages">ä¸ä¼ /æ¥çå¾ç</button> |
| | | <button class="secondary-btn" @click="fetchDrawingNumber">è°åPLMå¾çº¸</button> |
| | | <button class="secondary-btn" @click="viewAttachmentInfo">æ¥çéä»¶ä¿¡æ¯</button> |
| | | <button class="secondary-btn" @click="addDefectDescription" v-if="this.current">æ·»å ä¸è¯æè¿°</button> |
| | | <button class="primary-btn" @click="submitInspection" v-if="this.current">æ£éªæäº¤</button> |
| | | <!-- 页é¢å
容åºå --> |
| | | <view class="content-wrapper"> |
| | | <!-- 为åºé¨æé®çåºç©ºé´ --> |
| | | </view> |
| | | |
| | | <!-- åºå®å¨åºé¨çæä½æé®åº --> |
| | | <view class="fixed-action-buttons"> |
| | | <button class="action-btn" @click="handleEmergencyRelease" v-if="this.current">ç´§æ¥æ¾è¡</button> |
| | | <button class="action-btn" @click="handleWithdraw" v-if="this.current">æ¤å</button> |
| | | <button class="action-btn" @click="getInspectionItems" v-if="this.current">è·åæ£éªé¡¹ç®</button> |
| | | <button class="action-btn" @click="addDestruction" v-if="this.current">ç ´åå®éª</button> |
| | | <button class="action-btn" @click="uploadImages">ä¸ä¼ /æ¥çå¾ç</button> |
| | | <button class="action-btn" @click="fetchDrawingNumber">è°åPLMå¾çº¸</button> |
| | | <button class="action-btn" @click="viewAttachmentInfo">æ¥çéä»¶ä¿¡æ¯</button> |
| | | <button class="action-btn" @click="addDefectDescription" v-if="this.current">æ·»å ä¸è¯æè¿°</button> |
| | | <button class="action-btn primary" @click="submitInspection" v-if="this.current">æ£éªæäº¤</button> |
| | | </view> |
| | | <view v-if="remarksPopup" class="overlay"> |
| | | <view class="popup"> |
| | |
| | | |
| | | <view class="barcode"> |
| | | <u-modal :show="drawingShow" title="å¾çº¸æç»" @confirm="drawingConfirm" @cancel="drawingCancel" |
| | | showCancelButton> |
| | | <uni-table border stripe emptyText="ææ æ´å¤æ°æ®" style="margin-left: 5px;margin-right: 5px;height: 500px;"> |
| | | showCancelButton :z-index="1000"> |
| | | <uni-table border stripe emptyText="ææ æ´å¤æ°æ®" style="margin-left: 5px;margin-right: 5px;height: 400px;max-height: 60vh;overflow-y: auto;"> |
| | | <uni-tr> |
| | | <uni-th align="center">ç¸å
³ææ¡£</uni-th> |
| | | <uni-th align="center" width="90">ææ å
³èPDFæä»¶</uni-th> |
| | |
| | | <div class="attachment-detail-row"><span class="attachment-label">åæ§æ¥æï¼</span><span>{{ selectedAttachment.fdate }}</span></div> |
| | | <div class="attachment-detail-row"><span class="attachment-label">ä¸ä¼ 人ï¼</span><span>{{ selectedAttachment.createBy }}</span></div> |
| | | <div class="attachment-detail-row"><span class="attachment-label">ä¸ä¼ æ¶é´ï¼</span><span>{{ selectedAttachment.createDate }}</span></div> |
| | | <div v-if="isPreviewable(selectedAttachment.fattach)" class="attachment-preview-area"> |
| | | <div v-if="['pdf','jpg','jpeg','png','gif'].includes(selectedAttachment.fattach.trim().split('.').pop().toLowerCase())"> |
| | | <iframe :src="getAttachmentUrl(selectedAttachment)" style="width:100%;height:320px;border-radius:10px;background:#f8fafc;" frameborder="0"></iframe> |
| | | </div> |
| | | <div v-else-if="['txt'].includes(selectedAttachment.fattach.trim().split('.').pop().toLowerCase())"> |
| | | <iframe :src="getAttachmentUrl(selectedAttachment)" style="width:100%;height:320px;border-radius:10px;background:#f8fafc;" frameborder="0"></iframe> |
| | | </div> |
| | | <div v-else-if="['doc','docx','xls','xlsx'].includes(selectedAttachment.fattach.trim().split('.').pop().toLowerCase())"> |
| | | <iframe :src="'https://view.officeapps.live.com/op/view.aspx?src=' + encodeURIComponent(getAttachmentUrl(selectedAttachment))" style="width:100%;height:320px;border-radius:10px;background:#f8fafc;" frameborder="0"></iframe> |
| | | </div> |
| | | </div> |
| | | <div v-else class="attachment-download-area"> |
| | | <button class="attachment-download-link" @click="downloadAttachment(selectedAttachment)">ä¸è½½éä»¶</button> |
| | | <div class="attachment-actions-detail"> |
| | | <button class="attachment-action-btn preview-btn" |
| | | @click="previewFtpFile(selectedAttachment)" |
| | | v-if="isPreviewable(selectedAttachment.fattach)"> |
| | | ð å¨çº¿é¢è§ |
| | | </button> |
| | | <button class="attachment-action-btn download-btn" |
| | | @click="downloadAttachment(selectedAttachment)"> |
| | | ð¥ ä¸è½½æä»¶ |
| | | </button> |
| | | </div> |
| | | </div> |
| | | <div v-else class="attachment-detail-empty">ææ éä»¶ä¿¡æ¯</div> |
| | |
| | | <div v-else-if="attachments.length === 0">ææ éä»¶</div> |
| | | <ul class="attachment-list" v-else> |
| | | <li v-for="item in attachments" :key="item.id"> |
| | | <span class="attachment-name" @click="showAttachmentDetailDialog(item)"> |
| | | {{ item.fattach }} |
| | | </span> |
| | | <div class="attachment-info"> |
| | | <span class="attachment-name" @click="showAttachmentDetailDialog(item)"> |
| | | {{ item.fattach }} |
| | | </span> |
| | | <div class="attachment-meta"> |
| | | <span class="attachment-type">{{ item.ftype || 'æªç¥ç±»å' }}</span> |
| | | </div> |
| | | </div> |
| | | <div class="attachment-actions"> |
| | | <button class="secondary-btn" @click="showAttachmentDetailDialog(item)">详æ
</button> |
| | | <button class="secondary-btn preview-btn" @click="previewFtpFile(item)" |
| | | v-if="isPreviewable(item.fattach)">é¢è§</button> |
| | | <button class="secondary-btn" @click="downloadAttachment(item)">ä¸è½½</button> |
| | | </div> |
| | | </li> |
| | | </ul> |
| | | <button class="attachment-popup-close" @click="closeAttachmentPopup">å
³é</button> |
| | | </view> |
| | | </view> |
| | | |
| | | <!-- æä»¶é¢è§å¼¹çª --> |
| | | <view v-if="showFilePreviewPopup" class="overlay"> |
| | | <view class="popup file-preview-popup"> |
| | | <h3 class="file-preview-title">{{ previewTitle }}</h3> |
| | | <div class="file-preview-divider"></div> |
| | | <div class="file-preview-content"> |
| | | <!-- ææ¬å
容é¢è§ --> |
| | | <pre v-if="previewType === 'text'">{{ previewContent }}</pre> |
| | | |
| | | <!-- å¾çå
容é¢è§ --> |
| | | <view v-else-if="previewType === 'image'" class="image-preview-container"> |
| | | <image :src="previewContent" mode="widthFix" style="width: 100%; max-height: 400px;"></image> |
| | | </view> |
| | | |
| | | <!-- Excel ç Office æä»¶æç¤º --> |
| | | <view v-else-if="previewType === 'excel'" class="unsupported-preview"> |
| | | <view class="unsupported-icon">ð</view> |
| | | <view class="unsupported-text">Excel æä»¶æä¸æ¯æå¨çº¿é¢è§</view> |
| | | <view class="unsupported-hint">请ç¹å»ä¸è½½æé®è·å宿´æä»¶</view> |
| | | </view> |
| | | |
| | | <!-- 䏿¯æçæä»¶ç±»å --> |
| | | <view v-else class="unsupported-preview"> |
| | | <view class="unsupported-icon">ð</view> |
| | | <view class="unsupported-text">æ¤æä»¶æ ¼å¼æä¸æ¯æé¢è§</view> |
| | | <view class="unsupported-hint">请ç¹å»ä¸è½½æé®è·å宿´æä»¶</view> |
| | | </view> |
| | | </div> |
| | | <div class="file-preview-actions"> |
| | | <button v-if="previewType !== 'text'" class="file-preview-btn download-btn" @click="downloadPreviewFile">ð¥ ä¸è½½æä»¶</button> |
| | | <button class="file-preview-btn close-btn" @click="closeFilePreview">å
³é</button> |
| | | </div> |
| | | </view> |
| | | </view> |
| | | </view> |
| | |
| | | attachmentsLoading: false, |
| | | selectedAttachment: null, |
| | | showAttachmentDetail: false, |
| | | showFilePreviewPopup: false, |
| | | previewContent: '', |
| | | previewTitle: '', |
| | | previewItemNo: '', |
| | | previewType: '', // 'text', 'image', 'excel', 'unsupported' |
| | | |
| | | } |
| | | }, |
| | |
| | | this.attachmentsLoading = false; |
| | | if (res.status === 0) { |
| | | this.attachments = res.data.tbBillList; |
| | | // 为æ¯ä¸ªé件设置é»è®¤å¯ç¨ç¶æ |
| | | this.attachments.forEach((item, index) => { |
| | | this.$set(item, 'ftpAvailable', true); // é»è®¤è®¤ä¸ºæä»¶å¯ç¨ |
| | | this.$set(item, 'checking', false); |
| | | }); |
| | | } else if (res.status === 1 && res.message === "该æ£éªåæªä¸ä¼ éä»¶ä¿¡æ¯ï¼") { |
| | | uni.showToast({ title: res.message, icon: "none" }); |
| | | } else { |
| | |
| | | this.showAttachmentPopup = false; |
| | | }, |
| | | getAttachmentUrl(item) { |
| | | const baseUrl = "http://192.168.1.22:10054"; |
| | | // å»é¤ææç©ºç½å符ï¼å
æ¬ä¸è±æç©ºæ ¼ãå¶è¡¨ç¬¦çï¼ |
| | | let fileName = item.fattach.replace(/[\s\u3000]+/g, '').trim(); |
| | | return baseUrl + "/api/LLJ/DownloadAttachment?itemNo=" + encodeURIComponent(item.itemNo) + "&fileName=" + encodeURIComponent(fileName); |
| | | let fileName = item.fattach.replace(/[\s\u3000\r\n]+/g, '').trim(); |
| | | // ç»ä¸ä½¿ç¨FTPä¸è½½æ¥å£ï¼å
å«FTPæå¡å¨å°å |
| | | return this.$store.state.serverInfo.serverAPI + "/LLJ/DownloadFtpFile?itemNo=" + encodeURIComponent(item.itemNo) + "&fileName=" + encodeURIComponent(fileName) + "&ftpServer=" + encodeURIComponent(this.$store.state.serverInfo.ftpServer); |
| | | }, |
| | | showAttachmentDetailDialog(item) { |
| | | console.log('æ¥ç详æ
', item); |
| | |
| | | const ext = filename.trim().split('.').pop().toLowerCase(); |
| | | // æ¯æå¨çº¿é¢è§çæä»¶ç±»å |
| | | return [ |
| | | 'pdf', 'jpg', 'jpeg', 'png', 'gif', 'txt', 'doc', 'docx', 'xls', 'xlsx' |
| | | 'pdf', // PDFæä»¶ |
| | | 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', // å¾çæä»¶ |
| | | 'txt', 'log', 'md', // ææ¬æä»¶ |
| | | 'doc', 'docx', // Wordææ¡£ |
| | | 'xls', 'xlsx', // Excelè¡¨æ ¼ |
| | | 'ppt', 'pptx', // PowerPointæ¼ç¤ºæç¨¿ |
| | | 'csv' // CSVæä»¶ |
| | | ].includes(ext); |
| | | }, |
| | | // å¤çéä»¶ä¸è½½é误 |
| | |
| | | showCancel: false |
| | | }); |
| | | }, |
| | | downloadAttachment(item) { |
| | | const baseUrl = "http://192.168.1.22:10054"; |
| | | // å»é¤ææç©ºæ ¼ãå
¨è§ç©ºæ ¼ãåè½¦ãæ¢è¡ |
| | | // é¢è§FTPæä»¶ |
| | | previewFtpFile(item) { |
| | | const fileName = item.fattach.replace(/[\s\u3000\r\n]+/g, '').trim(); |
| | | const url = baseUrl + "/api/Llj/DownloadFtpFile?itemNo=" + encodeURIComponent(item.itemNo) + "&fileName=" + encodeURIComponent(fileName); |
| | | uni.downloadFile({ |
| | | const fileExt = fileName.split('.').pop().toLowerCase(); |
| | | |
| | | // æ£æ¥æä»¶ç±»åæ¯å¦æ¯æé¢è§ |
| | | if (!this.isPreviewable(fileName)) { |
| | | uni.showModal({ |
| | | title: '䏿¯æé¢è§', |
| | | content: '该æä»¶ç±»å䏿¯æå¨çº¿é¢è§ï¼è¯·ä¸è½½åæ¥ç', |
| | | showCancel: false |
| | | }); |
| | | return; |
| | | } |
| | | |
| | | const previewUrl = this.$store.state.serverInfo.serverAPI + "/LLJ/PreviewFtpFile?itemNo=" + encodeURIComponent(item.itemNo) + "&fileName=" + encodeURIComponent(fileName) + "&ftpServer=" + encodeURIComponent(this.$store.state.serverInfo.ftpServer); |
| | | |
| | | // æ ¹æ®æä»¶ç±»åè¿è¡ä¸åçé¢è§å¤ç |
| | | if (['pdf'].includes(fileExt)) { |
| | | this.previewPdfFile(previewUrl, fileName); |
| | | } else if (['jpg', 'jpeg', 'png', 'gif', 'bmp'].includes(fileExt)) { |
| | | this.previewImageFile(previewUrl, fileName); |
| | | } else if (['txt'].includes(fileExt)) { |
| | | this.previewTextFile(previewUrl, fileName); |
| | | } else if (['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'].includes(fileExt)) { |
| | | this.previewOfficeFile(previewUrl, fileName); |
| | | } else { |
| | | // å°è¯éç¨é¢è§ |
| | | this.previewGenericFile(previewUrl, fileName); |
| | | } |
| | | }, |
| | | |
| | | // é¢è§PDFæä»¶ |
| | | previewPdfFile(url, fileName) { |
| | | // å
ä¸è½½PDFæä»¶ï¼è½¬ä¸ºbase64åé¢è§ |
| | | uni.request({ |
| | | url: url, |
| | | method: 'GET', |
| | | responseType: 'arraybuffer', |
| | | success: (res) => { |
| | | if (res.statusCode === 200) { |
| | | if (typeof plus !== 'undefined' && plus.runtime && plus.runtime.openFile) { |
| | | plus.runtime.openFile({ path: res.tempFilePath }, () => { |
| | | uni.showToast({ title: 'æå¼æå', icon: 'success' }); |
| | | }, (e) => { |
| | | uni.showModal({ title: 'æç¤º', content: 'æä»¶ä¸è½½æåï¼ä½æ æ³èªå¨æå¼ãè¯·å¨æä»¶ç®¡ç䏿卿¥æ¾å¹¶æå¼ã', showCancel: false }); |
| | | }); |
| | | } else { |
| | | uni.showModal({ title: 'æç¤º', content: 'æä»¶ä¸è½½æåï¼ä½å½åç¯å¢æ æ³èªå¨æå¼ãè¯·å¨æä»¶ç®¡ç䏿卿¥æ¾å¹¶æå¼ã', showCancel: false }); |
| | | } |
| | | const base64Data = uni.arrayBufferToBase64(res.data); |
| | | // åå¨å°å
¨å±åé |
| | | getApp().globalData.tempPDF = base64Data; |
| | | uni.navigateTo({ |
| | | url: `/pages/fileView/pdfView` |
| | | }); |
| | | } else { |
| | | uni.showModal({ title: 'ä¸è½½å¤±è´¥', content: `ä¸è½½å¤±è´¥ï¼ç¶æç ï¼${res.statusCode}`, showCancel: false }); |
| | | this.handlePreviewError(res.statusCode, fileName); |
| | | } |
| | | }, |
| | | fail: (error) => { |
| | | uni.showModal({ title: 'ä¸è½½å¤±è´¥', content: `ä¸è½½å¤±è´¥ï¼è¯·æ£æ¥ç½ç»è¿æ¥ã${error.errMsg}`, showCancel: false }); |
| | | this.handlePreviewError(0, fileName, error.errMsg); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // é¢è§å¾çæä»¶ |
| | | previewImageFile(url, fileName) { |
| | | // #ifdef APP-PLUS |
| | | // APPç¯å¢ï¼å
ä¸è½½å°æ¬å°åé¢è§ï¼é¿å
ç½ç»å¾çå è½½é®é¢ |
| | | uni.showLoading({ title: 'å è½½å¾ç...' }); |
| | | uni.downloadFile({ |
| | | url: url, |
| | | success: (res) => { |
| | | uni.hideLoading(); |
| | | if (res.statusCode === 200) { |
| | | // ä½¿ç¨æ¬å°ä¸´æ¶è·¯å¾ |
| | | uni.navigateTo({ |
| | | url: `/pages/fileView/imageView?url=${encodeURIComponent(res.tempFilePath)}` |
| | | }); |
| | | } else { |
| | | this.handlePreviewError(res.statusCode, fileName); |
| | | } |
| | | }, |
| | | fail: (error) => { |
| | | uni.hideLoading(); |
| | | this.handlePreviewError(0, fileName, error.errMsg); |
| | | } |
| | | }); |
| | | // #endif |
| | | |
| | | // #ifdef H5 || MP |
| | | // H5åå°ç¨åºï¼ç´æ¥ä½¿ç¨ç½ç»URL |
| | | uni.navigateTo({ |
| | | url: `/pages/fileView/imageView?url=${encodeURIComponent(url)}` |
| | | }); |
| | | // #endif |
| | | }, |
| | | |
| | | // é¢è§ææ¬æä»¶ |
| | | previewTextFile(url, fileName) { |
| | | // ææ¬æä»¶ç´æ¥æ¾ç¤ºå¨å¼¹çªä¸ |
| | | uni.showLoading({ title: 'å è½½æä»¶å
容...' }); |
| | | uni.request({ |
| | | url: url, |
| | | method: 'GET', |
| | | success: (res) => { |
| | | uni.hideLoading(); |
| | | if (res.statusCode === 200) { |
| | | const fileType = this.getFileType(fileName); |
| | | |
| | | if (fileType === 'text') { |
| | | // ææ¬æä»¶ï¼æ¾ç¤ºå
容 |
| | | this.showFilePreview(res.data, fileName); |
| | | } else if (fileType === 'image') { |
| | | // å¾çæä»¶ï¼æ¾ç¤ºå¾çURL |
| | | this.showFilePreview(url, fileName); |
| | | } else { |
| | | // å
¶ä»æä»¶ç±»åï¼æ¾ç¤ºæç¤ºä¿¡æ¯ |
| | | this.showFilePreview('', fileName); |
| | | } |
| | | } else { |
| | | this.handlePreviewError(res.statusCode, fileName); |
| | | } |
| | | }, |
| | | fail: (error) => { |
| | | uni.hideLoading(); |
| | | this.handlePreviewError(0, fileName, error.errMsg); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // æ£æµæä»¶ç±»å |
| | | getFileType(fileName) { |
| | | const fileExt = fileName.split('.').pop().toLowerCase(); |
| | | |
| | | if (['txt', 'log', 'md', 'csv', 'json', 'xml'].includes(fileExt)) { |
| | | return 'text'; |
| | | } else if (['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(fileExt)) { |
| | | return 'image'; |
| | | } else if (['xls', 'xlsx', 'doc', 'docx', 'ppt', 'pptx'].includes(fileExt)) { |
| | | return 'excel'; |
| | | } else { |
| | | return 'unsupported'; |
| | | } |
| | | }, |
| | | |
| | | // æ¾ç¤ºæä»¶é¢è§å¼¹çª |
| | | showFilePreview(content, fileName) { |
| | | this.previewContent = content; |
| | | this.previewTitle = fileName; |
| | | this.previewItemNo = this.selectedAttachment?.itemNo || ''; |
| | | this.previewType = this.getFileType(fileName); |
| | | this.showFilePreviewPopup = true; |
| | | }, |
| | | |
| | | // å
³éæä»¶é¢è§å¼¹çª |
| | | closeFilePreview() { |
| | | this.showFilePreviewPopup = false; |
| | | this.previewContent = ''; |
| | | this.previewTitle = ''; |
| | | this.previewItemNo = ''; |
| | | this.previewType = ''; |
| | | }, |
| | | |
| | | // ä¸è½½é¢è§æä»¶ |
| | | downloadPreviewFile() { |
| | | const item = { fattach: this.previewTitle, itemNo: this.previewItemNo }; |
| | | this.downloadAttachment(item); |
| | | this.closeFilePreview(); |
| | | }, |
| | | |
| | | // é¢è§Officeæä»¶ |
| | | previewOfficeFile(url, fileName) { |
| | | // å
æ£æ¥Excelæä»¶ï¼ä½¿ç¨ä¸é¨çExcelé¢è§é¡µé¢ |
| | | const fileExt = fileName.split('.').pop().toLowerCase(); |
| | | if (['xls', 'xlsx'].includes(fileExt)) { |
| | | // Excelæä»¶é¢è§ |
| | | uni.request({ |
| | | url: url, |
| | | method: 'GET', |
| | | responseType: 'arraybuffer', |
| | | success: (res) => { |
| | | if (res.statusCode === 200) { |
| | | const base64Data = uni.arrayBufferToBase64(res.data); |
| | | // åå¨ Base64 æ°æ®å°æ¬å°åå¨ |
| | | uni.setStorageSync('excelBase64Data', base64Data); |
| | | uni.navigateTo({ |
| | | url: `/pages/fileView/excelView` |
| | | }); |
| | | } else { |
| | | this.handlePreviewError(res.statusCode, fileName); |
| | | } |
| | | }, |
| | | fail: (error) => { |
| | | this.handlePreviewError(0, fileName, error.errMsg); |
| | | } |
| | | }); |
| | | } else if (['doc', 'docx'].includes(fileExt)) { |
| | | // Wordæä»¶ï¼å°è¯ä½¿ç¨Wordé¢è§é¡µé¢æè
微软å¨çº¿é¢è§ |
| | | try { |
| | | const officePreviewUrl = `https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}`; |
| | | // 妿æwebView页é¢ï¼ä½¿ç¨webViewé¢è§ |
| | | this.previewGenericFile(officePreviewUrl, fileName); |
| | | } catch (error) { |
| | | this.handlePreviewError(0, fileName, '䏿¯ææ¤Officeæä»¶ç±»åçé¢è§'); |
| | | } |
| | | } else { |
| | | // å
¶ä»Officeæä»¶ï¼ä½¿ç¨å¾®è½¯å¨çº¿é¢è§æå¡ |
| | | const officePreviewUrl = `https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}`; |
| | | this.previewGenericFile(officePreviewUrl, fileName); |
| | | } |
| | | }, |
| | | |
| | | // éç¨æä»¶é¢è§ |
| | | previewGenericFile(url, fileName) { |
| | | // ç±äºæ²¡æéç¨çwebView页é¢ï¼æ¾ç¤ºæç¤ºå¹¶æä¾ä¸è½½ |
| | | uni.showModal({ |
| | | title: 'æä»¶é¢è§', |
| | | content: `æä»¶ "${fileName}" éè¦ä¸è½½åæ¥çï¼æ¯å¦ç«å³ä¸è½½ï¼`, |
| | | showCancel: true, |
| | | confirmText: 'ä¸è½½', |
| | | cancelText: 'åæ¶', |
| | | success: (res) => { |
| | | if (res.confirm) { |
| | | const item = { fattach: fileName, itemNo: this.selectedAttachment.itemNo }; |
| | | this.downloadAttachment(item); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // å¤çé¢è§é误 |
| | | handlePreviewError(statusCode, fileName, errorMsg = '') { |
| | | let message = ''; |
| | | if (statusCode === 404) { |
| | | message = `æä»¶ ${fileName} å¨FTPæå¡å¨ä¸ä¸åå¨`; |
| | | } else if (statusCode === 0) { |
| | | message = `é¢è§å¤±è´¥ï¼${errorMsg}`; |
| | | } else { |
| | | message = `é¢è§å¤±è´¥ï¼ç¶æç ï¼${statusCode}`; |
| | | } |
| | | |
| | | uni.showModal({ |
| | | title: 'é¢è§å¤±è´¥', |
| | | content: message, |
| | | showCancel: true, |
| | | confirmText: 'ä¸è½½', |
| | | cancelText: 'åæ¶', |
| | | success: (res) => { |
| | | if (res.confirm) { |
| | | // ç¨æ·éæ©ä¸è½½æä»¶ |
| | | const item = { fattach: fileName, itemNo: this.selectedAttachment.itemNo }; |
| | | this.downloadAttachment(item); |
| | | } |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | downloadAttachment(item) { |
| | | // å»é¤ææç©ºæ ¼ãå
¨è§ç©ºæ ¼ãåè½¦ãæ¢è¡ |
| | | const fileName = item.fattach.replace(/[\s\u3000\r\n]+/g, '').trim(); |
| | | // 使ç¨é
ç½®çæå¡å¨å°ååFTPæå¡å¨å°å |
| | | const url = this.$store.state.serverInfo.serverAPI + "/LLJ/DownloadFtpFile?itemNo=" + encodeURIComponent(item.itemNo) + "&fileName=" + encodeURIComponent(fileName) + "&ftpServer=" + encodeURIComponent(this.$store.state.serverInfo.ftpServer); |
| | | |
| | | // æ£æ¥è¿è¡ç¯å¢ |
| | | // #ifdef H5 |
| | | // H5ç¯å¢ï¼ä½¿ç¨æµè§å¨ä¸è½½ |
| | | this.downloadFileInBrowser(url, fileName); |
| | | // #endif |
| | | |
| | | // #ifdef APP-PLUS |
| | | // APPç¯å¢ï¼ä½¿ç¨uni.downloadFile |
| | | this.downloadFileInApp(url, fileName); |
| | | // #endif |
| | | |
| | | // #ifdef MP |
| | | // å°ç¨åºç¯å¢ï¼ä½¿ç¨uni.downloadFile |
| | | this.downloadFileInApp(url, fileName); |
| | | // #endif |
| | | }, |
| | | |
| | | // 卿µè§å¨ä¸ä¸è½½æä»¶ |
| | | downloadFileInBrowser(url, fileName) { |
| | | uni.showLoading({ title: 'æ£å¨åå¤ä¸è½½...' }); |
| | | |
| | | // æ¹æ³1ï¼å建éèçaæ ç¾ä¸è½½ |
| | | try { |
| | | const link = document.createElement('a'); |
| | | link.href = url; |
| | | link.download = fileName; |
| | | link.style.display = 'none'; |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | document.body.removeChild(link); |
| | | |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: 'ä¸è½½å·²å¼å§', |
| | | icon: 'success', |
| | | duration: 2000 |
| | | }); |
| | | } catch (error) { |
| | | console.log('aæ ç¾ä¸è½½å¤±è´¥ï¼å°è¯window.openæ¹å¼:', error); |
| | | // æ¹æ³2ï¼ä½¿ç¨window.open |
| | | try { |
| | | window.open(url, '_blank'); |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: 'ä¸è½½å·²å¼å§', |
| | | icon: 'success', |
| | | duration: 2000 |
| | | }); |
| | | } catch (error2) { |
| | | console.log('window.openä¸è½½å¤±è´¥ï¼å°è¯fetchæ¹å¼:', error2); |
| | | // æ¹æ³3ï¼ä½¿ç¨fetchä¸è½½ |
| | | this.downloadFileWithFetch(url, fileName); |
| | | } |
| | | } |
| | | }, |
| | | |
| | | // 使ç¨fetchä¸è½½æä»¶ |
| | | downloadFileWithFetch(url, fileName) { |
| | | fetch(url) |
| | | .then(response => { |
| | | if (!response.ok) { |
| | | throw new Error(`HTTP error! status: ${response.status}`); |
| | | } |
| | | return response.blob(); |
| | | }) |
| | | .then(blob => { |
| | | // å建blob URL |
| | | const blobUrl = window.URL.createObjectURL(blob); |
| | | |
| | | // å建ä¸è½½é¾æ¥ |
| | | const link = document.createElement('a'); |
| | | link.href = blobUrl; |
| | | link.download = fileName; |
| | | link.style.display = 'none'; |
| | | document.body.appendChild(link); |
| | | link.click(); |
| | | document.body.removeChild(link); |
| | | |
| | | // éæ¾blob URL |
| | | window.URL.revokeObjectURL(blobUrl); |
| | | |
| | | uni.hideLoading(); |
| | | uni.showToast({ |
| | | title: 'ä¸è½½æå', |
| | | icon: 'success', |
| | | duration: 2000 |
| | | }); |
| | | }) |
| | | .catch(error => { |
| | | console.error('Fetchä¸è½½å¤±è´¥:', error); |
| | | uni.hideLoading(); |
| | | if (error.message.includes('404')) { |
| | | uni.showModal({ |
| | | title: 'æä»¶ä¸åå¨', |
| | | content: `该éä»¶å¨FTPæå¡å¨ä¸ä¸åå¨`, |
| | | showCancel: false |
| | | }); |
| | | } else { |
| | | uni.showModal({ |
| | | title: 'ä¸è½½å¤±è´¥', |
| | | content: `ä¸è½½å¤±è´¥: ${error.message}`, |
| | | showCancel: false |
| | | }); |
| | | } |
| | | }); |
| | | }, |
| | | |
| | | // å¨APPä¸ä¸è½½æä»¶ |
| | | downloadFileInApp(url, fileName) { |
| | | // #ifdef APP-PLUS |
| | | uni.showLoading({ title: 'ä»FTPæå¡å¨ä¸è½½ä¸...' }); |
| | | |
| | | // Android è·ååå¨è·¯å¾ |
| | | const saveDir = plus.os.name === 'Android' ? plus.io.convertLocalFileSystemURL('_downloads/') : plus.io.convertLocalFileSystemURL('_documents/'); |
| | | const filePath = `${saveDir}${fileName}`; |
| | | |
| | | const downloadTask = uni.downloadFile({ |
| | | url: url, |
| | | filePath: filePath, // æå®ä¿åè·¯å¾ |
| | | success: (res) => { |
| | | uni.hideLoading(); |
| | | if (res.statusCode === 200) { |
| | | const fileInfo = { |
| | | name: fileName, |
| | | path: res.filePath || filePath, |
| | | tempPath: res.tempFilePath |
| | | }; |
| | | |
| | | uni.showModal({ |
| | | title: 'ä¸è½½æå', |
| | | content: `æä»¶å·²ä¿åå°ï¼${fileInfo.path}`, |
| | | showCancel: true, |
| | | confirmText: 'æå¼æä»¶', |
| | | cancelText: 'ç¡®å®', |
| | | success: (modalRes) => { |
| | | if (modalRes.confirm) { |
| | | // ç¨æ·éæ©æå¼æä»¶ |
| | | this.openFileInApp(fileInfo); |
| | | } |
| | | } |
| | | }); |
| | | } else if (res.statusCode === 404) { |
| | | uni.showModal({ |
| | | title: 'æä»¶ä¸åå¨', |
| | | content: `该éä»¶å¨FTPæå¡å¨ä¸ä¸åå¨`, |
| | | showCancel: false |
| | | }); |
| | | } else { |
| | | uni.showModal({ |
| | | title: 'ä¸è½½å¤±è´¥', |
| | | content: `ç¶æç ï¼${res.statusCode}`, |
| | | showCancel: false |
| | | }); |
| | | } |
| | | }, |
| | | fail: (error) => { |
| | | uni.hideLoading(); |
| | | console.error('ä¸è½½å¤±è´¥:', error); |
| | | uni.showModal({ |
| | | title: 'ä¸è½½å¤±è´¥', |
| | | content: `ç½ç»é误ï¼${error.errMsg}`, |
| | | showCancel: false |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | // çå¬ä¸è½½è¿åº¦ |
| | | downloadTask.onProgressUpdate((res) => { |
| | | const progress = Math.round(res.progress); |
| | | uni.showLoading({ |
| | | title: `ä¸è½½ä¸ ${progress}%`, |
| | | mask: true |
| | | }); |
| | | }); |
| | | // #endif |
| | | |
| | | // #ifdef MP |
| | | // å°ç¨åºç¯å¢çç®åå®ç° |
| | | uni.showLoading({ title: 'ä¸è½½ä¸...' }); |
| | | uni.downloadFile({ |
| | | url: url, |
| | | success: (res) => { |
| | | uni.hideLoading(); |
| | | if (res.statusCode === 200) { |
| | | uni.showToast({ title: 'ä¸è½½å®æ', icon: 'success' }); |
| | | } |
| | | }, |
| | | fail: (error) => { |
| | | uni.hideLoading(); |
| | | uni.showModal({ title: 'ä¸è½½å¤±è´¥', content: error.errMsg, showCancel: false }); |
| | | } |
| | | }); |
| | | // #endif |
| | | }, |
| | | |
| | | // APP䏿弿件 |
| | | openFileInApp(fileInfo) { |
| | | // #ifdef APP-PLUS |
| | | if (typeof plus !== 'undefined') { |
| | | const filePath = fileInfo.path || fileInfo.tempPath; |
| | | |
| | | // å°è¯æå¼æä»¶ |
| | | plus.runtime.openFile(filePath, {}, (error) => { |
| | | console.error('æå¼æä»¶å¤±è´¥:', error); |
| | | uni.showModal({ |
| | | title: 'æ æ³æå¼', |
| | | content: 'ç³»ç»ä¸æ²¡ææ¾å°è½æå¼æ¤æä»¶çåºç¨ç¨åº', |
| | | showCancel: false |
| | | }); |
| | | }); |
| | | } |
| | | // #endif |
| | | }, |
| | | |
| | | } |
| | |
| | | font-family: 'Microsoft YaHei', 'Segoe UI', sans-serif; |
| | | max-width: 1000px; |
| | | margin: 0 auto; |
| | | padding: 20px; |
| | | padding: 20px 20px 160px 20px; /* åºé¨å¢å padding为åºå®æé®çç©ºé´ */ |
| | | background-color: #fff; |
| | | box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); |
| | | min-height: 100vh; |
| | | position: relative; |
| | | } |
| | | |
| | | /* 头鍿 ·å¼ */ |
| | |
| | | background-color: #f1f5f9; |
| | | } |
| | | |
| | | /* æé®æ ·å¼ */ |
| | | /* åºå®åºé¨æé®æ ·å¼ */ |
| | | .fixed-action-buttons { |
| | | position: fixed; |
| | | bottom: 0; |
| | | left: 0; |
| | | right: 0; |
| | | background-color: #fff; |
| | | box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1); |
| | | padding: 10px 15px 20px 15px; |
| | | z-index: 100; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 8px; |
| | | max-height: 150px; |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .action-btn { |
| | | background-color: #ecf0f1; |
| | | color: #34495e; |
| | | padding: 12px 15px; |
| | | border: none; |
| | | border-radius: 6px; |
| | | cursor: pointer; |
| | | font-size: 14px; |
| | | font-weight: 500; |
| | | transition: all 0.3s ease; |
| | | text-align: center; |
| | | min-height: 44px; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .action-btn:hover { |
| | | background-color: #d5dbdb; |
| | | transform: translateY(-1px); |
| | | } |
| | | |
| | | .action-btn.primary { |
| | | background-color: #3498db; |
| | | color: #fff; |
| | | } |
| | | |
| | | .action-btn.primary:hover { |
| | | background-color: #2980b9; |
| | | } |
| | | |
| | | /* å
容å
è£
å¨ï¼ä¸ºåºé¨æé®çåºç©ºé´ */ |
| | | .content-wrapper { |
| | | height: 20px; /* é¢å¤ç空ç½åºå */ |
| | | } |
| | | |
| | | /* 忿鮿 ·å¼ä¿æå
¼å®¹ */ |
| | | .action-buttons { |
| | | display: flex; |
| | | gap: 10px; |
| | |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | z-index: 10; |
| | | z-index: 1000; /* æé«å±çº§ï¼ç¡®ä¿å¨åºå®æé®ä¸æ¹ */ |
| | | } |
| | | |
| | | /* å¼¹çªæ´ä½ç¾å */ |
| | |
| | | border: none; |
| | | position: relative; |
| | | min-width: 260px; |
| | | z-index: 1001; /* ç¡®ä¿å¼¹çªå
容卿ä¸å± */ |
| | | max-height: 80vh; /* é嶿大é«åº¦ï¼é¿å
被åºé¨æé®é®æ¡ */ |
| | | overflow-y: auto; /* å
容è¿å¤æ¶å¯æ»å¨ */ |
| | | } |
| | | .attachment-popup-title { |
| | | font-size: 22px; |
| | |
| | | background: linear-gradient(90deg,#bdbdbd 0%,#e0e0e0 100%); |
| | | color: #1976d2; |
| | | } |
| | | |
| | | /* é件详æ
页é¢çæä½æé® */ |
| | | .attachment-actions-detail { |
| | | margin: 20px 0; |
| | | display: flex; |
| | | gap: 12px; |
| | | justify-content: center; |
| | | flex-wrap: wrap; |
| | | } |
| | | .attachment-action-btn { |
| | | padding: 10px 20px; |
| | | border: none; |
| | | border-radius: 8px; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | min-width: 120px; |
| | | box-shadow: 0 2px 4px rgba(0,0,0,0.1); |
| | | } |
| | | .attachment-action-btn.preview-btn { |
| | | background: linear-gradient(135deg, #4CAF50, #45a049); |
| | | color: white; |
| | | } |
| | | .attachment-action-btn.preview-btn:hover { |
| | | background: linear-gradient(135deg, #45a049, #3d8b40); |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 4px 8px rgba(0,0,0,0.15); |
| | | } |
| | | .attachment-action-btn.download-btn { |
| | | background: linear-gradient(135deg, #2196F3, #1976D2); |
| | | color: white; |
| | | } |
| | | .attachment-action-btn.download-btn:hover { |
| | | background: linear-gradient(135deg, #1976D2, #1565C0); |
| | | transform: translateY(-1px); |
| | | box-shadow: 0 4px 8px rgba(0,0,0,0.15); |
| | | } |
| | | |
| | | /* æä»¶é¢è§å¼¹çªæ ·å¼ */ |
| | | .file-preview-popup { |
| | | width: 80vw; |
| | | max-width: 600px; |
| | | max-height: 70vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | /* APPç¯å¢éé
*/ |
| | | /* #ifdef APP-PLUS */ |
| | | .file-preview-popup { |
| | | width: 85vw; |
| | | max-height: 75vh; |
| | | } |
| | | .file-preview-content { |
| | | max-height: 350px; |
| | | } |
| | | /* #endif */ |
| | | .file-preview-title { |
| | | font-size: 18px; |
| | | font-weight: 700; |
| | | color: #222; |
| | | margin-bottom: 8px; |
| | | text-align: center; |
| | | word-break: break-all; |
| | | } |
| | | .file-preview-divider { |
| | | height: 1px; |
| | | background: linear-gradient(90deg,#e0e7ef 0%,#f5f7fa 100%); |
| | | margin-bottom: 16px; |
| | | } |
| | | .file-preview-content { |
| | | flex: 1; |
| | | max-height: 400px; |
| | | overflow-y: auto; |
| | | background: #f8fafc; |
| | | border-radius: 8px; |
| | | padding: 16px; |
| | | margin-bottom: 16px; |
| | | border: 1px solid #e2e8f0; |
| | | } |
| | | .file-preview-content pre { |
| | | font-family: 'Consolas', 'Monaco', 'Courier New', monospace; |
| | | font-size: 12px; |
| | | line-height: 1.5; |
| | | color: #2d3748; |
| | | white-space: pre-wrap; |
| | | word-wrap: break-word; |
| | | margin: 0; |
| | | } |
| | | |
| | | /* å¾çé¢è§æ ·å¼ */ |
| | | .image-preview-container { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | min-height: 200px; |
| | | } |
| | | |
| | | /* 䏿¯ææä»¶ç±»åçæç¤ºæ ·å¼ */ |
| | | .unsupported-preview { |
| | | text-align: center; |
| | | padding: 40px 20px; |
| | | color: #666; |
| | | } |
| | | .unsupported-icon { |
| | | font-size: 48px; |
| | | margin-bottom: 16px; |
| | | } |
| | | .unsupported-text { |
| | | font-size: 16px; |
| | | font-weight: 600; |
| | | color: #333; |
| | | margin-bottom: 8px; |
| | | } |
| | | .unsupported-hint { |
| | | font-size: 14px; |
| | | color: #999; |
| | | line-height: 1.4; |
| | | } |
| | | |
| | | .file-preview-actions { |
| | | display: flex; |
| | | gap: 12px; |
| | | justify-content: center; |
| | | } |
| | | .file-preview-btn { |
| | | padding: 8px 20px; |
| | | border: none; |
| | | border-radius: 6px; |
| | | font-size: 14px; |
| | | font-weight: 600; |
| | | cursor: pointer; |
| | | transition: all 0.3s ease; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | min-width: 120px; |
| | | } |
| | | .file-preview-btn.download-btn { |
| | | background: linear-gradient(135deg, #2196F3, #1976D2); |
| | | color: white; |
| | | } |
| | | .file-preview-btn.download-btn:hover { |
| | | background: linear-gradient(135deg, #1976D2, #1565C0); |
| | | transform: translateY(-1px); |
| | | } |
| | | .file-preview-btn.close-btn { |
| | | background: linear-gradient(135deg, #e0e0e0, #bdbdbd); |
| | | color: #444; |
| | | } |
| | | .file-preview-btn.close-btn:hover { |
| | | background: linear-gradient(135deg, #bdbdbd, #9e9e9e); |
| | | transform: translateY(-1px); |
| | | } |
| | | /* å表弹çªç¾åï¼ä¿çåæï¼ */ |
| | | .attachment-list { |
| | | padding: 0; |
| | |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | padding: 8px 0; |
| | | padding: 12px 0; |
| | | border-bottom: 1px solid #f0f0f0; |
| | | } |
| | | .attachment-name { |
| | | .attachment-info { |
| | | flex: 1; |
| | | margin-right: 10px; |
| | | } |
| | | .attachment-name { |
| | | color: #3498db; |
| | | cursor: pointer; |
| | | font-weight: 500; |
| | | transition: color 0.2s; |
| | | margin-right: 10px; |
| | | display: block; |
| | | margin-bottom: 4px; |
| | | } |
| | | .attachment-name:hover { |
| | | color: #217dbb; |
| | | text-decoration: underline; |
| | | } |
| | | .attachment-meta { |
| | | font-size: 12px; |
| | | } |
| | | .attachment-type { |
| | | color: #7f8c8d; |
| | | font-style: italic; |
| | | } |
| | | .attachment-actions { |
| | | display: flex; |
| | | gap: 8px; |
| | | flex-shrink: 0; |
| | | } |
| | | .attachment-list .secondary-btn { |
| | | padding: 4px 10px; |
| | |
| | | background: #e6f0fa; |
| | | color: #1976d2; |
| | | } |
| | | .preview-btn { |
| | | background: #e8f5e8 !important; |
| | | color: #2e7d2e !important; |
| | | border-color: #a5d6a5 !important; |
| | | } |
| | | .preview-btn:hover { |
| | | background: #d4eecc !important; |
| | | color: #1e5f1e !important; |
| | | } |
| | | .attachment-popup-close { |
| | | margin-top: 18px; |
| | | width: 100%; |