From bfbb1ea3c6bb2dd7db064fb189290a1bfcf6c9cd Mon Sep 17 00:00:00 2001 From: seatonwan9 Date: 星期四, 28 八月 2025 02:14:48 +0800 Subject: [PATCH] 提交源码 --- src/views/tradeManage/detail/index.vue | 684 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 564 insertions(+), 120 deletions(-) diff --git a/src/views/tradeManage/detail/index.vue b/src/views/tradeManage/detail/index.vue index abfcfe1..7882083 100644 --- a/src/views/tradeManage/detail/index.vue +++ b/src/views/tradeManage/detail/index.vue @@ -143,14 +143,94 @@ </div> <!-- 绉婚櫎鍘熸潵鐨勮〃鏍煎簳閮ㄤ俊鎭紝鍥犱负宸茬粡绉诲埌琛ㄦ牸鏈�鍚庝竴琛� --> - </el-card> + + <!-- 浜ゆ槗鏂囦欢锛堢Щ鍔ㄥ埌璁㈠崟璇︽儏涓嬮潰锛屽悓涓�鍗$墖鍐咃級 --> + <div class="file-section" v-if="isAgreementOrder && fileList.length > 0"> + <el-table + :data="fileList" + border + class="file-table" + :header-cell-style="fileTableHeaderStyle" + :cell-style="fileTableCellStyle" + > + <el-table-column min-width="200"> + <template #header> + <el-icon class="header-icon"><Document /></el-icon> + <span>浜ゆ槗鏂囦欢</span> + </template> + <template #default="{ row }"> + <div class="file-name"> + <el-icon class="file-icon"><Document /></el-icon> + <span>{{ row.name }}</span> + </div> + </template> + </el-table-column> + <el-table-column label="鏂囦欢澶у皬" prop="size" width="120"> + <template #default="{ row }"> + {{ formatFileSize(row.size) }} + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" width="180"> + <template #default="{ row }"> + <div class="file-actions"> + <el-button + type="text" + size="small" + class="preview-btn" + @click="handlePreview(row)" + v-if="isPreviewable(row)" + :disabled="!isFileUploaded(row)" + > + 棰勮 + </el-button> + <el-button + type="text" + size="small" + class="download-btn" + @click="handleDownload(row)" + :disabled="!isFileUploaded(row)" + > + 涓嬭浇 + </el-button> + </div> + </template> + </el-table-column> + </el-table> + </div> + </el-card> + + <!-- 浜ゆ槗淇℃伅澶囨敞锛堜粎鍦ㄨ鍗曠姸鎬佷负"寰呬氦鏄撶‘璁�"鎴栦箣鍚庢椂鏄剧ず锛� --> + <el-card class="mt15" shadow="never" v-if="shouldShowRemark"> + <div class="title">浜ゆ槗淇℃伅澶囨敞</div> + <el-table :data="remarkItems" border class="mt10 remark-table"> + <el-table-column label="璇︽儏" prop="name" min-width="200" /> + <el-table-column label="鎺堟潈寮�濮嬫椂闂�" width="200"> + <template #default="{ row, $index }"> + <span>{{ remarkItems[$index].start || '-' }}</span> + </template> + </el-table-column> + <el-table-column label="鎺堟潈缁撴潫鏃堕棿" width="200"> + <template #default="{ row, $index }"> + <div class="end-time-wrapper"> + <span v-if="remarkItems[$index].forever" class="forever-text">姘镐箙</span> + <span v-else>{{ remarkItems[$index].end || '-' }}</span> + </div> + </template> + </el-table-column> + <el-table-column label="澶囨敞" min-width="300"> + <template #default="{ row, $index }"> + <span>{{ remarkItems[$index].remark || '-' }}</span> + </template> + </el-table-column> + </el-table> + </el-card> <!-- 瀹℃壒杩借釜 --> - <el-card class="mt15" shadow="never" v-if="detail.records?.length"> + <el-card class="mt15" shadow="never"> <div class="title">瀹℃壒杩借釜</div> <!-- 鏍囩椤� --> - <el-tabs v-model="activeTab" class="approval-tabs"> + <!-- <el-tabs v-model="activeTab" class="approval-tabs"> <el-tab-pane label="瀹℃壒璁板綍" name="records"> <el-table :data="detail.records" @@ -199,13 +279,18 @@ </el-table-column> </el-table> </el-tab-pane> - </el-tabs> + </el-tabs> --> - <!-- 杩斿洖鎸夐挳 --> - <div class="action-buttons"> + <!-- 澶栭儴绯荤粺瀹℃壒杞ㄨ抗 iframe --> + <div class="iframe-wrap" v-if="workflowIframeUrl"> + <iframe :src="workflowIframeUrl" class="workflow-iframe" referrerpolicy="no-referrer"></iframe> + </div> + + </el-card> + <!-- 杩斿洖鎸夐挳 --> + <div class="action-buttons"> <el-button @click="goBack">杩斿洖</el-button> </div> - </el-card> </div> </template> @@ -213,14 +298,42 @@ import { onMounted, reactive, ref, computed, type CSSProperties } from 'vue' import { Document, User, Goods, List } from '@element-plus/icons-vue' import { useRoute, useRouter } from 'vue-router' +import { ElMessage } from 'element-plus' +import orderApi from '@/api/orderApi' +import createAxios from '@/utils/axios' +import productApi from '@/api/productApi' +import { useUserInfo } from '@/stores/modules/userInfo' +const hostUrl = import.meta.env.VITE_AXIOS_BASE_URL const route = useRoute() const router = useRouter() const detail = reactive<any>({ items: [], records: [], nodes: [] }) const orderTableWrapRef = ref<HTMLElement | null>(null) const activeTab = ref('records') +const userStore = useUserInfo() +// 澶栭儴瀹℃壒杞ㄨ抗iframe鍦板潃 +const workflowIframeUrl = computed(() => { + const pid = (detail.workflowId || route.query.processinstId || '').toString().trim() + if (!pid) return '' + return `${hostUrl}/activity/history?processinstId=${encodeURIComponent(pid)}&token=${userStore.getAdminToken}` +}) const labelStyle = { width: '180px', maxWidth: '180px' } const contentStyle = { width: 'calc(50% - 180px)' } + +// 鏂囦欢鐩稿叧 +const fileList = ref<any[]>([]) +const isAgreementOrder = ref(false) + +// 浜ゆ槗淇℃伅澶囨敞 +const remarkItems = ref<any[]>([]) +const shouldShowRemark = computed(() => { + const statusName = detail.statusName || '' + // 褰撹鍗曠姸鎬佷负"寰呬氦鏄撶‘璁�"鎴栦箣鍚庣殑鐘舵�佹椂鏄剧ず浜ゆ槗淇℃伅澶囨敞 + // "寰呬笂浼犳枃浠�"鍜�"寰呮巿鏉�"鐘舵�佷笉鏄剧ず浜ゆ槗淇℃伅澶囨敞 + const statusOrder = ['WAIT_UPLOAD', 'WAIT_AUTHORIZE', 'WAIT_CONFIRM', 'COMPLETED', 'EVALUATED'] + const currentStatus = statusServerToUi[statusName] + return currentStatus && statusOrder.indexOf(currentStatus) >= statusOrder.indexOf('WAIT_CONFIRM') +}) // 璁$畻琛ㄦ牸鏁版嵁锛屾坊鍔犳眹鎬昏 const tableData = computed(() => { @@ -240,120 +353,159 @@ return [...detail.items, summaryRow] }) -onMounted(async () => { - // 浣跨敤鍓嶇妯℃嫙鏁版嵁浠ヤ究寮�鍙� UI锛堜笉鏀瑰姩鍚庣鏈嶅姟锛� - const mockDetail = { - orderNo: '4348442557619205545', - resourceTypeName: '杞欢浜у搧', - status: 'WAIT_APPROVAL', - statusName: '寰呭鏍�', - applyTime: '2025-05-21 10:00:00', - unitName: '涓氦鏂硅繙寤鸿鏈夐檺鍏徃', - userName: '寮犻潤', - userAccount: 'L20159922', - userDept: '淇℃伅涓績', - userPhone: '13800000000', - productName: '涓氦鏂硅繙鏅鸿兘瀹炴祴瀹為噺绠$悊绯荤粺', - supplier: '涓氦鏂硅繙绉戞妧鏈夐檺鍏徃', - industry: '寤虹瓚宸ョ▼', - projectUnit: '鍦熷缓宸ョ▼', - productType: '杞欢搴�', - productDesc: - '闈㈠悜宸ョ▼椤圭洰鐨勮川閲忓疄娴嬪疄閲忔暟瀛楀寲绠$悊绯荤粺锛屾敮鎸佹爣鍑嗗寲閲囬泦銆佽嚜鍔ㄧ粺璁′笌杩囩▼绠℃帶銆�', - items: [ - { - id: '1', - name: '浼佷笟绉佹湁SaaS鐗堣鍙�', - saleType: '涔版柇', - accountCount: 50, - customerTarget: '浼佷笟', - concurrentNodes: 50, - pricePoint: 50000, - priceCash: 0, - quantity: 1, - period: 0, - }, - { - id: '2', - name: '浼佷笟绉佹湁SaaS鐗圤TA鍗囩骇鏈嶅姟', - saleType: 'OTA鏈嶅姟', - accountCount: 50, - customerTarget: '浼佷笟', - concurrentNodes: 50, - pricePoint: 0, - priceCash: 7500, - quantity: 1, - period: 1, - }, - { - id: '3', - name: '浼佷笟绉佹湁SaaS鐗堢敤鎴峰閲忓寘', - saleType: '绉佹湁澧為噺鍖�', - accountCount: 100, - customerTarget: '浼佷笟', - concurrentNodes: 100, - pricePoint: 0, - priceCash: 0, - priceProtocol: true, - quantity: 1, - period: 1, - }, - { - id: '4', - name: '涓汉鍏湁SaaS鐗堣鍙�', - saleType: '绉佹湁澧為噺鍖�', - accountCount: 50, - customerTarget: '涓汉', - concurrentNodes: 50, - pricePoint: 0, - priceCash: 0, - quantity: 1, - period: 0, - }, - ], - pointTotal: '50,000', - cashTotal: '7,500', - records: [ - { - nodeName: '鎻愪氦浜�', - approver: '寮犻潤', - department: '闂ㄦ埛绯荤粺涓存椂缁�', - startTime: '2025-05-21 16:08:09', - endTime: '2025-05-21 16:08:09', - statusName: '宸插畬鎴�', - opinion: '', - }, - { - nodeName: '浜ゆ槗瀹℃壒', - approver: '鍠讳細宄�', - department: '闂ㄦ埛绯荤粺涓存椂缁�', - startTime: '2025-05-21 16:08:09', - endTime: '', - statusName: '瀹¢槄涓�', - opinion: '', - }, - ], - nodes: [ - { - nodeName: '鎻愪氦鐢宠', - nodeType: '寮�濮嬭妭鐐�', - handler: '寮犻潤', - department: '闂ㄦ埛绯荤粺涓存椂缁�', - status: 'completed', - statusName: '宸插畬鎴�', - }, - { - nodeName: '浜ゆ槗瀹℃壒', - nodeType: '瀹℃壒鑺傜偣', - handler: '鍠讳細宄�', - department: '闂ㄦ埛绯荤粺涓存椂缁�', - status: 'processing', - statusName: '澶勭悊涓�', - }, - ], - } +// 鐘舵�佹槧灏勶紙鍚庣涓枃 -> 鍓嶇鏋氫妇锛� +const statusServerToUi: Record<string, string> = { + '寰呬笂浼犳枃浠�': 'WAIT_UPLOAD', + '寰呮巿鏉�': 'WAIT_AUTHORIZE', + '寰呬氦鏄撶‘璁�': 'WAIT_CONFIRM', + '宸插畬鎴�': 'COMPLETED', + '宸茶瘎浠�': 'EVALUATED', +} - Object.assign(detail, mockDetail) +const formatDateTime = (val?: string) => (val ? val.replace('T', ' ').slice(0, 19) : '') + +const normalizePriceType = (val?: string): 'points' | 'currency' | 'agreement' | 'free' => { + if (!val) return 'currency' + const s = String(val) + if (/(绉垎|points)/i.test(s)) return 'points' + if (/(鍗忚|agreement)/i.test(s)) return 'agreement' + if (/(鍏嶈垂|free)/i.test(s)) return 'free' + return 'currency' +} + +onMounted(async () => { + const orderId = String(route.params.id || '') + if (!orderId) return + + try { + // 骞惰鑾峰彇璁㈠崟璇︽儏鍜屽崗璁被鍨嬫鏌� + const [orderRes, agreementRes] = await Promise.all([ + orderApi.getOrderDetail(orderId), + orderApi.checkAgreementPriceType(orderId) + ]) + + const res = orderRes as any + const data = res?.data || {} + + // 璁剧疆鏄惁涓哄崗璁鍗� + const agreementResult = agreementRes as any + isAgreementOrder.value = agreementResult?.data === true + + const statusName: string = data.orderStatus || '' + const uiStatus = statusServerToUi[statusName] || 'INFO' + + // 鏍规嵁浜у搧id鑾峰彇浜у搧淇℃伅锛屾洿鏂板ご閮ㄥ睍绀� + try { + if (data.productId) { + const detailRes: any = await productApi.getProductById({ id: data.productId }) + if (detailRes?.code === 200 && detailRes.data) { + // 鐢ㄤ骇鍝佽鎯呰ˉ鍏ㄥご淇℃伅 + data.productName = detailRes.data.name || data.productName + data.providerName = detailRes.data.submissionUnit || data.providerName + data.industry = detailRes.data.industrialChainName || data.industry + data.productDesc = detailRes.data.describe || data.productDesc + data.projectUnit = detailRes.data.importantAreaName || data.productDesc + data.productType = detailRes.data.typeName || data.productDesc + } + } + } catch (e) { + // 蹇界暐浜у搧璇︽儏澶辫触锛屼笉闃诲璁㈠崟璇︽儏 + } + + // 鑾峰彇鐢ㄦ埛淇℃伅 + + // 鏄犲皠璁㈠崟璇︽儏澶撮儴淇℃伅 + const head = { + orderNo: data.orderId, + resourceTypeName: '杞欢浜у搧', + status: uiStatus, + statusName, + applyTime: formatDateTime(data.applyTime), + unitName: data.unitName || '-', + userName: data.userName || '-', + userAccount: data.userAccount || '-', + userDept: data.userDept || '-', + userPhone: data.userPhone || '-', + productName: data.productName || '-', + supplier: data.providerName || '-', + industry: data.industry || '-', + projectUnit: data.projectUnit || '-', + productType: data.productType || '-', + productDesc: data.productDesc || '-', + } + + // 鏄庣粏椤规槧灏� + const items: any[] = Array.isArray(data.orderDetails) + ? data.orderDetails.map((d: any, idx: number) => { + const pt = normalizePriceType(d.priceType) + return { + id: String(d.id ?? idx + 1), + name: d.suiteName, + saleType: d.salesForm, + accountCount: d.accountLimit, + customerTarget: d.customerType, + concurrentNodes: d.concurrentNodes, + pricePoint: pt === 'points' ? Number(d.unitPrice || 0) : 0, + priceCash: pt === 'currency' ? Number(d.unitPrice || 0) : 0, + priceProtocol: pt === 'agreement', + quantity: Number(d.quantity || 0), + period: Number(d.duration || 0), + remarks: d.remarks || '', // 鏂板 remarks 瀛楁 + } + }) + : [] + + // 姹囨�伙紙绠�鍗曠浉鍔狅細鍗曚环*鏁伴噺锛� + const pointTotalNum = items.reduce((sum, it) => sum + Number(it.pricePoint || 0) * Number(it.quantity || 0), 0) + const cashTotalNum = items.reduce((sum, it) => sum + Number(it.priceCash || 0) * Number(it.quantity || 0), 0) + + Object.assign(detail, head, { + items, + pointTotal: pointTotalNum.toLocaleString(), + cashTotal: cashTotalNum.toLocaleString(), + records: [], + nodes: [], + workflowId: data.workflowId || data.processinstId || '' + }) + + // 鍒濆鍖栦氦鏄撲俊鎭娉ㄦ暟鎹� + remarkItems.value = (detail.items || []).map((item: any, index: number) => { + // 璁$畻鎺堟潈缁撴潫鏃堕棿 + let endDate = '' + if (item.period > 0) { + // 濡傛灉鏈夋湡闄愶紝璁$畻缁撴潫鏃堕棿 + const startDate = new Date(data.applyTime || new Date()) + const endDateObj = new Date(startDate) + endDateObj.setFullYear(endDateObj.getFullYear() + item.period) + endDate = endDateObj.toISOString().split('T')[0] // 鏍煎紡鍖栦负 YYYY-MM-DD + } + + return { + name: item.name, + start: data.applyTime ? data.applyTime.split('T')[0] : '', // 浣跨敤璁㈠崟鐢宠鏃堕棿 + end: endDate, + forever: item.period === 0, // 鏈熼檺涓�0鏃惰缃负姘镐箙 + remark: item.remarks || '' // 浣跨敤濂椾欢淇℃伅涓殑remarks瀛楁 + } + }) + + // 鑾峰彇璁㈠崟闄勪欢鍒楄〃锛堝鏋滄湁鐨勮瘽锛� + if (data.attachments && Array.isArray(data.attachments)) { + fileList.value = data.attachments.map((file: any) => ({ + name: file.fileName || file.originalName, + size: file.fileSize || 0, + uid: file.id, + status: 'success', + url: file.fileUrl, + uploaded: true + })) + } else { + fileList.value = [] + } + } catch (error) { + console.error('鑾峰彇璁㈠崟璇︽儏澶辫触:', error) + ElMessage.error('鑾峰彇璁㈠崟璇︽儏澶辫触') + } }) // 涓庡垪琛ㄩ〉淇濇寔涓�鑷寸殑鐘舵�佺被鍨嬫槧灏勶紙UI灞曠ず鐢級 @@ -411,6 +563,15 @@ } const recordTableCellStyle: CSSProperties = { fontSize: '12px' } +// 鏂囦欢鍒楄〃琛ㄦ牸琛ㄥご鏂囧瓧灞呬腑锛屼絾绗竴鍒楃殑"浜ゆ槗鏂囦欢"鏂囧瓧闈犲乏瀵归綈 +const fileTableHeaderStyle: CSSProperties = { + textAlign: 'center', + fontSize: '14px', + background: '#f3f6fb' +} +// 鏂囦欢鍒楄〃琛ㄦ牸琛ㄤ綋鏂囧瓧澶у皬 +const fileTableCellStyle: CSSProperties = { fontSize: '12px' } + // 涓烘眹鎬昏娣诲姞鐗规畩鏍峰紡绫诲悕 const getRowClassName = ({ row }: { row: any }) => { return row.isSummary ? 'summary-row' : '' @@ -441,6 +602,210 @@ // 杩斿洖鎸夐挳 const goBack = () => router.back() + +// 鏂囦欢澶у皬鏍煎紡鍖� +const formatFileSize = (size: number) => { + if (!size || size === 0) return '0 Bytes'; + const k = 1024; + const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; + const i = Math.floor(Math.log(size) / Math.log(k)); + return parseFloat((size / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; +}; + +// 鍒ゆ柇鏂囦欢鏄惁鍙瑙� +const isPreviewable = (file: any) => { + // 棣栧厛妫�鏌IME绫诲瀷 + const previewableTypes = [ + 'image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/bmp', 'image/webp', + 'text/plain', 'text/html', 'text/css', 'text/javascript', + 'application/pdf', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // .docx + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // .pptx + ] + + // 濡傛灉MIME绫诲瀷鍖归厤锛岀洿鎺ヨ繑鍥瀟rue + if (previewableTypes.includes(file.type || '')) { + return true + } + + // 濡傛灉MIME绫诲瀷涓虹┖鎴栦笉鍖归厤锛屾牴鎹枃浠舵墿灞曞悕鍒ゆ柇 + const fileName = file.name || '' + const fileExtension = fileName.toLowerCase().split('.').pop() + + const previewableExtensions = [ + 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', + 'txt', 'html', 'htm', 'css', 'js', + 'pdf', + 'docx', 'xlsx', 'pptx' + ] + + return previewableExtensions.includes(fileExtension) +} + +// 鍒ゆ柇鏂囦欢鏄惁宸蹭笂浼犳垚鍔� +const isFileUploaded = (file: any) => { + // 鏂囦欢鏈塽rl涓旂姸鎬佷负success琛ㄧず宸蹭笂浼犳垚鍔� + return file.url && (file.status === 'success' || file.uploaded) +} + +// 鏂囦欢棰勮 +const handlePreview = async (file: any) => { + if (!file.url) { + ElMessage.warning('鏂囦欢閾炬帴涓嶅瓨鍦�') + return + } + + // 鑾峰彇鏂囦欢鎵╁睍鍚� + const fileName = file.name || '' + const fileExtension = fileName.toLowerCase().split('.').pop() + + let previewUrl = file.url + + // 濡傛灉鏂囦欢瀛樺偍鍦∕inIO锛屼紭鍏堜娇鐢ㄩ瑙圲RL + if (file.url.includes('order-attachments')) { + try { + // 棣栧厛灏濊瘯鑾峰彇棰勮URL + const previewResponse = await createAxios({ + url: `/admin/file/preview`, + method: 'GET', + params: { + fileName: file.url + } + }) + + console.log('棰勮URL鍝嶅簲:', previewResponse) + + // 妫�鏌ュ搷搴旀牸寮� + const responseData = previewResponse as any + if (responseData && responseData.code === 200 && responseData.data) { + previewUrl = responseData.data + console.log('浣跨敤棰勮URL:', previewUrl) + } else { + console.log('棰勮URL鑾峰彇澶辫触锛屼娇鐢ㄤ笅杞芥柟寮�') + // 濡傛灉棰勮URL鑾峰彇澶辫触锛屽洖閫�鍒颁笅杞芥柟寮� + const response = await createAxios({ + url: `/admin/file/download`, + method: 'GET', + responseType: 'blob', + params: { + fileName: file.url, + originalName: file.name + } + }) + + // 鍒涘缓棰勮URL + const blob = new Blob([response as any]) + previewUrl = window.URL.createObjectURL(blob) + console.log('浣跨敤Blob URL:', previewUrl) + } + } catch (error) { + console.error('鑾峰彇鏂囦欢澶辫触:', error) + ElMessage.error('鑾峰彇鏂囦欢澶辫触锛屾棤娉曢瑙�') + return + } + } + + // 鍥剧墖鏂囦欢鐩存帴鍦ㄦ柊绐楀彛鎵撳紑 + if ((file.type && file.type.startsWith('image/')) || + ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'].includes(fileExtension)) { + console.log('棰勮鍥剧墖鏂囦欢:', previewUrl) + window.open(previewUrl, '_blank') + return + } + + // PDF鏂囦欢鍦ㄦ柊绐楀彛鎵撳紑 + if (file.type === 'application/pdf' || fileExtension === 'pdf') { + console.log('棰勮PDF鏂囦欢:', previewUrl) + window.open(previewUrl, '_blank') + return + } + + // 鏂囨湰鏂囦欢鍦ㄦ柊绐楀彛鎵撳紑 + if ((file.type && file.type.startsWith('text/')) || + ['txt', 'html', 'htm', 'css', 'js'].includes(fileExtension)) { + console.log('棰勮鏂囨湰鏂囦欢:', previewUrl) + window.open(previewUrl, '_blank') + return + } + + // Office鏂囨。鍜屽叾浠栨枃浠剁被鍨嬶紝灏濊瘯鍦ㄦ柊绐楀彛鎵撳紑 + try { + console.log('棰勮鍏朵粬鏂囦欢:', previewUrl) + window.open(previewUrl, '_blank') + } catch (error) { + console.error('棰勮澶辫触:', error) + ElMessage.error('棰勮澶辫触锛岃涓嬭浇鍚庢煡鐪�') + } +} + +// 鏂囦欢涓嬭浇 +const handleDownload = async (file: any) => { + if (!file.url) { + ElMessage.warning('鏂囦欢閾炬帴涓嶅瓨鍦�') + return + } + + console.log('寮�濮嬩笅杞芥枃浠�:', file.name, 'URL:', file.url) + + try { + // 濡傛灉鏂囦欢瀛樺偍鍦∕inIO锛屼娇鐢ㄥ悗绔洿鎺ヤ笅杞紸PI + if (file.url.includes('order-attachments')) { + console.log('浣跨敤MinIO涓嬭浇API') + + // 浣跨敤axios閫氳繃浠g悊璁块棶鍚庣API + const response = await createAxios({ + url: `/admin/file/download`, + method: 'GET', + responseType: 'blob', + params: { + fileName: file.url, + originalName: file.name + } + }) + + console.log('涓嬭浇鍝嶅簲:', response) + + // 鍒涘缓涓嬭浇閾炬帴 + const blob = new Blob([response as any]) + const downloadUrl = window.URL.createObjectURL(blob) + + console.log('鍒涘缓涓嬭浇閾炬帴:', downloadUrl) + + const link = document.createElement('a') + link.href = downloadUrl + link.download = file.name || 'download' + link.target = '_blank' + link.rel = 'noopener noreferrer' + + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + + // 娓呯悊URL瀵硅薄 + window.URL.revokeObjectURL(downloadUrl) + + ElMessage.success('鏂囦欢涓嬭浇鎴愬姛') + } else { + console.log('浣跨敤鐩存帴URL涓嬭浇') + // 鍏朵粬鎯呭喌鐩存帴浣跨敤鍘烾RL + const link = document.createElement('a') + link.href = file.url + link.download = file.name || 'download' + link.target = '_blank' + link.rel = 'noopener noreferrer' + + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + + ElMessage.success('寮�濮嬩笅杞芥枃浠�') + } + } catch (error) { + console.error('涓嬭浇澶辫触:', error) + ElMessage.error('涓嬭浇澶辫触锛岃閲嶈瘯') + } +} // 鍗曞厓鏍煎悎骞舵柟娉� const arraySpanMethod = ({ row, column, rowIndex, columnIndex }: any) => { @@ -645,6 +1010,85 @@ margin: 0 10px; } } + +/* 鏂囦欢鍒楄〃琛ㄦ牸鏍峰紡 */ +.file-section { + margin-top: 15px; + .file-title { + font-weight: 600; + margin-bottom: 10px; + } + .file-table { + width: 100%; + .file-name { + display: flex; + align-items: center; + .file-icon { + margin-right: 8px; + color: #409eff; + } + } + .preview-btn { + color: #409eff; + &:hover { + text-decoration: underline; + } + } + } +} + +/* 鏂囦欢琛ㄦ牸琛ㄥご绗竴鍒�"浜ゆ槗鏂囦欢"鏂囧瓧闈犲乏瀵归綈 */ +.file-table :deep(.el-table__header-wrapper thead tr th:first-child) { + text-align: left !important; +} + +/* 澶栭儴瀹℃壒杞ㄨ抗 iframe 鏍峰紡 */ +.iframe-wrap { margin-top: 10px; } +.workflow-iframe { width: 100%; height: 500px; border: none; border-radius: 6px; } + +/* 鏂囦欢鎿嶄綔鎸夐挳鏍峰紡 */ +.file-actions { + display: flex; + gap: 8px; + align-items: center; + justify-content: center; + + .preview-btn { + color: #409eff; + &:hover { + text-decoration: underline; + } + &:disabled { + color: #c0c4cc; + cursor: not-allowed; + } + } + + .download-btn { + color: #67c23a; + &:hover { + text-decoration: underline; + } + &:disabled { + color: #c0c4cc; + cursor: not-allowed; + } + } +} + +/* 浜ゆ槗淇℃伅澶囨敞琛ㄦ牸鏍峰紡 */ +.remark-table { + width: 100%; + .end-time-wrapper { + display: flex; + align-items: center; + gap: 10px; + .forever-text { + color: #409eff; + font-weight: 500; + } + } +} </style> -- Gitblit v1.8.0