diff --git a/src/api/base/pbApi.ts b/src/api/base/pbApi.ts new file mode 100644 index 0000000..a966b47 --- /dev/null +++ b/src/api/base/pbApi.ts @@ -0,0 +1,57 @@ +import { get, post } from "@/utils/request"; + +/** + * 获取选课排班分页数据 + */ +export const getPbPageApi = async (params: any) => { + return await get("/api/pb/findPage", params); +}; + +/** + * 根据ID获取选课排班详情 + */ +export const getPbByIdApi = async (id: string) => { + return await get(`/api/pb/${id}`); +}; + +/** + * 创建选课排班 + */ +export const createPbApi = async (params: any) => { + return await post("/api/pb", params); +}; + +/** + * 更新选课排班 + */ +export const updatePbApi = async (params: any) => { + return await post("/api/pb/update", params); +}; + +/** + * 删除选课排班 + */ +export const deletePbApi = async (id: string) => { + return await post(`/api/pb/delete/${id}`); +}; + +/** + * 根据选课ID获取排班列表 + */ +export const getPbListByXkIdApi = async (params: any) => { + return await get("/api/pb/findByXkId", params); +}; + +/** + * 课程巡查接口 + */ +export const getXcCourseListApi = async (params: any) => { + return await get("/api/pb/getXcCourseList", params); +}; + +/** + * 课业辅导巡查接口 + */ +export const getKyXcCourseListApi = async (params: any) => { + return await get("/api/pb/getKyXcCourseList", params); +}; diff --git a/src/api/base/xkPbApi.ts b/src/api/base/xkPbApi.ts deleted file mode 100644 index 6c8716e..0000000 --- a/src/api/base/xkPbApi.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { get, post } from "@/utils/request"; - -/** - * 获取选课排班分页数据 - */ -export const getXkPbPageApi = async (params: any) => { - return await get("/api/xkPb/findPage", params); -}; - -/** - * 根据ID获取选课排班详情 - */ -export const getXkPbByIdApi = async (id: string) => { - return await get(`/api/xkPb/${id}`); -}; - -/** - * 创建选课排班 - */ -export const createXkPbApi = async (params: any) => { - return await post("/api/xkPb", params); -}; - -/** - * 更新选课排班 - */ -export const updateXkPbApi = async (params: any) => { - return await post("/api/xkPb/update", params); -}; - -/** - * 删除选课排班 - */ -export const deleteXkPbApi = async (id: string) => { - return await post(`/api/xkPb/delete/${id}`); -}; - -/** - * 根据选课ID获取排班列表 - */ -export const getXkPbListByXkIdApi = async (params: any) => { - return await get("/api/xkPb/findByXkId", params); -}; - -/** - * 课程巡查接口 - */ -export const getXcCourseListApi = async (params: any) => { - return await get("/api/xkPb/getXcCourseList", params); -}; - -/** - * 课业辅导巡查接口 - */ -export const getKyXcCourseListApi = async (params: any) => { - return await get("/api/xkPb/getKyXcCourseList", params); -}; diff --git a/src/components/BasicNjBjSelect/demo.vue b/src/components/BasicNjBjSelect/demo.vue index b7af54c..4f83ca9 100644 --- a/src/components/BasicNjBjSelect/demo.vue +++ b/src/components/BasicNjBjSelect/demo.vue @@ -155,3 +155,6 @@ const setDefaultValue = () => { + + + diff --git a/src/pages/view/quantitativeAssessment/quantitativeSummary/quantitativeSummary.vue b/src/pages/view/quantitativeAssessment/quantitativeSummary/quantitativeSummary.vue index a29bac6..237867d 100644 --- a/src/pages/view/quantitativeAssessment/quantitativeSummary/quantitativeSummary.vue +++ b/src/pages/view/quantitativeAssessment/quantitativeSummary/quantitativeSummary.vue @@ -13,7 +13,7 @@ @@ -65,9 +65,56 @@ onMounted(() => { height.value = getWindowHeight() }) -const head = ref([]) +const head = ref([]) const dataLiat = ref([]) +// 获取检查项基础分:baseScore * 5 +function getBaseScore(ditem: any) { + const inspectItem = head.value.find(item => item.id === ditem.id); + if (inspectItem && inspectItem.baseScore) { + return inspectItem.baseScore * 5; + } + return 0; +} + +// 计算单个检查项得分:baseScore * 5 - 扣分项 +function calculateItemScore(bitem: any, ditem: any) { + if (bitem.itemScoreMap && bitem.itemScoreMap[ditem.id]) { + // 找到对应的检查项获取baseScore + const inspectItem = head.value.find(item => item.id === ditem.id); + if (inspectItem && inspectItem.baseScore) { + const baseScore = inspectItem.baseScore * 5; // 基础分 + const deduction = bitem.itemScoreMap[ditem.id]; // 扣分项(负数) + // 得分 = baseScore * 5 - 扣分项 + return baseScore + deduction; // deduction是负数,所以用加法 + } + } + return 0; +} + +// 计算总分:所有检查项汇总 +function calculateTotalScore(bitem: any) { + let totalScore = 0; + + // 遍历所有检查项(从head中获取) + head.value.forEach(item => { + if (item.id && item.baseScore) { + const baseScore = item.baseScore * 5; // 基础分 + let deduction = 0; // 扣分项 + + // 如果有扣分记录,获取扣分 + if (bitem.itemScoreMap && bitem.itemScoreMap[item.id]) { + deduction = bitem.itemScoreMap[item.id]; + } + + // 得分 = baseScore * 5 - 扣分项 + totalScore += baseScore + deduction; // deduction是负数,所以用加法 + } + }); + + return totalScore; +} + async function getWeekData() { let res = await inspectItemFindAllApi(); let arr: any = [{name: "班级,得分"}]; @@ -79,8 +126,25 @@ async function getWeekData() { // arr.push(); head.value = arr let res1 = await evaluationGetWeekReportApi(); - const grouped = groupBy(res1.result, 'gradeNum'); - dataLiat.value = values(grouped); + + // 按年级分组,但保持排序 + // 提取年级名称进行分组 + const grouped = groupBy(res1.result, (item) => { + // 从"一年级1班"中提取"一年级" + const match = item.gradeFullName.match(/^(.+?)(\d+班)$/); + return match ? match[1] : item.gradeFullName; + }); + + // 获取所有年级并排序(按年级名称排序) + const gradeNames = Object.keys(grouped).sort((a, b) => { + // 提取年级数字进行排序 + const numA = parseInt(a.replace(/[^\d]/g, '')) || 0; + const numB = parseInt(b.replace(/[^\d]/g, '')) || 0; + return numA - numB; + }); + + // 按排序后的年级顺序重新组织数据 + dataLiat.value = gradeNames.map(gradeName => grouped[gradeName]); // forEach(result, (data) => { // let rowDatas: any = []; // if (data && data.length > 0) { diff --git a/src/pages/view/routine/gwlz/gwFlow.vue b/src/pages/view/routine/gwlz/gwFlow.vue index 675b9a1..1df893a 100644 --- a/src/pages/view/routine/gwlz/gwFlow.vue +++ b/src/pages/view/routine/gwlz/gwFlow.vue @@ -30,70 +30,21 @@ 附件 - + - 🖼️ - 🎥 - 📄 - 📎 - - - {{ gwInfo.fileName || '未知文件' }} - {{ (gwInfo.fileFormat || 'unknown').toUpperCase() }} - - - - - - - - - - - - - 🖼️ - 🎥 - 📄 - 📎 {{ getFileName(file) }} - {{ formatFileSize(file.size) }} - {{ getFileSuffix(file).toUpperCase() }} @@ -208,7 +159,6 @@ {{ formatTime(log.operationTime) }} - {{ log.operationType }} {{ log.operationContent }} @@ -265,7 +215,7 @@ - + 操作详情 @@ -287,6 +237,48 @@ + + + + + + 文件下载 + + + + 文件名: + {{ downloadFileName }} + + + 下载路径: + 将下载到默认下载目录 + + + 点击确认后将开始下载文件 + + + + + 正在下载文件,请稍候... + + + + + + + + @@ -305,7 +297,8 @@ import { canPreview, previewFile as previewFileUtil, previewVideo as previewVideoUtil, - previewImage as previewImageUtil + previewImage as previewImageUtil, + downloadFile } from "@/utils/filePreview"; // 类型定义 @@ -332,6 +325,7 @@ interface GwInfo { } interface FileInfo { + id?: string; // 文件ID name: string; size: number; url: string; @@ -379,6 +373,10 @@ const gwId = ref(""); // 弹窗控制 const showLogDetailModal = ref(false); +const showDownloadModal = ref(false); +const downloadUrl = ref(''); +const downloadFileName = ref(''); +const isDownloading = ref(false); // 用户store const { getUser, getJs } = useUserStore(); @@ -396,9 +394,54 @@ const ccExpanded = ref(false); // 操作记录展开状态 const logExpanded = ref(false); +// 计算属性:解析后的附件列表 +const parsedAttachments = computed(() => { + const attachments = []; + + // 处理files数组 + if (gwInfo.value.files && gwInfo.value.files.length > 0) { + attachments.push(...gwInfo.value.files); + } + // 处理逗号分隔的fileUrl字符串 + else if (gwInfo.value.fileUrl) { + const fileUrls = gwInfo.value.fileUrl.split(',').map(url => url.trim()).filter(url => url); + + // 解析fileName字符串(如果存在) + let fileNames: string[] = []; + if (gwInfo.value.fileName) { + fileNames = gwInfo.value.fileName.split(',').map(name => name.trim()).filter(name => name); + } + + // 将URL字符串转换为文件对象 + fileUrls.forEach((url, index) => { + // 优先使用解析出的文件名,如果没有则从URL提取 + let displayName = fileNames[index] || url.split('/').pop() || `文件${index + 1}`; + const fileFormat = url.split('.').pop() || 'unknown'; + + // 如果文件名包含扩展名,去掉扩展名(保持resourName不包含扩展名) + let resourName = displayName; + if (displayName.includes('.' + fileFormat)) { + resourName = displayName.replace('.' + fileFormat, ''); + } + + attachments.push({ + id: `file_${index}`, + name: displayName, // 保持原始文件名(可能包含扩展名) + url: url, + resourUrl: url, + resourName: resourName, // 不包含扩展名的文件名 + resSuf: fileFormat, + size: 0 // 无法从URL获取大小 + }); + }); + } + + return attachments; +}); + // 计算属性:是否有附件 const hasAttachments = computed(() => { - return gwInfo.value.fileUrl || (gwInfo.value.files && gwInfo.value.files.length > 0); + return parsedAttachments.value.length > 0; }); // 计算属性:显示的抄送人列表 @@ -683,7 +726,13 @@ const getCurrentUserApproverId = (currentUserId: string) => { }; // 预览单个附件(从gwInfo直接获取) -const previewSingleFile = () => { +const previewSingleFile = (event?: Event) => { + // 手动阻止事件冒泡 + if (event) { + event.stopPropagation(); + event.preventDefault(); + } + if (!gwInfo.value.fileUrl) { return; } @@ -706,69 +755,34 @@ const previewSingleFile = () => { }; // 下载单个附件 -const downloadSingleFile = () => { +const downloadSingleFile = (event?: Event) => { + // 手动阻止事件冒泡 + if (event) { + event.stopPropagation(); + event.preventDefault(); + } + if (!gwInfo.value.fileUrl) { return; } - const fileUrl = imagUrl(gwInfo.value.fileUrl); + const finalUrl = imagUrl(gwInfo.value.fileUrl); const fileName = gwInfo.value.fileName || '未知文件'; const fileFormat = gwInfo.value.fileFormat || ''; const fullFileName = fileFormat ? `${fileName}.${fileFormat}` : fileName; - // 方法1: 使用 fetch 和 blob 方式强制下载 - fetch(fileUrl) - .then(response => { - if (!response.ok) { - throw new Error('网络请求失败'); - } - return response.blob(); - }) - .then(blob => { - const downloadUrl = window.URL.createObjectURL(blob); - const link = document.createElement('a'); - link.href = downloadUrl; - link.download = fullFileName; // 使用 download 属性强制下载 - link.style.display = 'none'; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - window.URL.revokeObjectURL(downloadUrl); - - uni.showToast({ - title: '开始下载', - icon: 'success' - }); - }) - .catch(error => { - console.error('fetch下载失败:', error); - // 方法2: 如果fetch失败,尝试直接打开链接 - try { - const link = document.createElement('a'); - link.href = fileUrl; - link.download = fullFileName; - link.target = '_blank'; - link.style.display = 'none'; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - - uni.showToast({ - title: '开始下载', - icon: 'success' - }); - } catch (fallbackError) { - console.error('备用下载也失败:', fallbackError); - uni.showToast({ - title: '下载失败', - icon: 'error' - }); - } - }); + // 显示下载路径选择弹窗 + showDownloadPathModal(finalUrl, fullFileName); }; // 文件预览 -const previewFile = (file: FileInfo) => { +const previewFile = (file: FileInfo, event?: Event) => { + // 手动阻止事件冒泡 + if (event) { + event.stopPropagation(); + event.preventDefault(); + } + // 确定文件URL和名称 const fileUrl = file.resourUrl ? imagUrl(file.resourUrl) : file.url; const fileName = file.resourName ? `${file.resourName}.${file.resSuf}` : file.name; @@ -848,65 +862,22 @@ const handlePreviewImageSingle = (imageUrl: string) => { }); }; -// 文件下载 -const downloadFile = (file: FileInfo) => { - downloadFileAction(file); -}; - -// 文件下载实现 -const downloadFileAction = (file: FileInfo) => { - const fileUrl = file.resourUrl ? imagUrl(file.resourUrl) : file.url; - const fileName = file.resourName ? `${file.resourName}.${file.resSuf}` : file.name; +// 文件下载 - 支持选择下载路径 +const downloadFileAction = (file: FileInfo, event?: Event) => { + // 手动阻止事件冒泡 + if (event) { + event.stopPropagation(); + event.preventDefault(); + } - // 方法1: 使用 fetch 和 blob 方式强制下载 - fetch(fileUrl) - .then(response => { - if (!response.ok) { - throw new Error('网络请求失败'); - } - return response.blob(); - }) - .then(blob => { - const downloadUrl = window.URL.createObjectURL(blob); - const link = document.createElement('a'); - link.href = downloadUrl; - link.download = fileName; // 使用 download 属性强制下载 - link.style.display = 'none'; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - window.URL.revokeObjectURL(downloadUrl); - - uni.showToast({ - title: '开始下载', - icon: 'success' - }); - }) - .catch(error => { - console.error('fetch下载失败:', error); - // 方法2: 如果fetch失败,尝试直接打开链接 - try { - const link = document.createElement('a'); - link.href = fileUrl; - link.download = fileName; - link.target = '_blank'; - link.style.display = 'none'; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - - uni.showToast({ - title: '开始下载', - icon: 'success' - }); - } catch (fallbackError) { - console.error('备用下载也失败:', fallbackError); - uni.showToast({ - title: '下载失败', - icon: 'error' - }); - } - }); + const finalUrl = file.resourUrl ? imagUrl(file.resourUrl) : imagUrl(file.url); + // 获取原始文件名 + const originalFileName = getOriginalFileName(file); + + console.log('下载文件:', { finalUrl, originalFileName, file }); + + // 显示下载路径选择弹窗 + showDownloadPathModal(finalUrl, originalFileName); }; // 格式化时间 @@ -952,6 +923,31 @@ const getFileSuffix = (file: FileInfo) => { return 'unknown'; }; +// 获取文件图标 +const getFileIcon = (fileType: string) => { + const type = fileType.toLowerCase(); + + switch (type) { + case 'pdf': + return '/static/base/view/pdf.png'; + case 'doc': + case 'docx': + return '/static/base/view/word.png'; + case 'xls': + case 'xlsx': + return '/static/base/view/excel.png'; + case 'ppt': + case 'pptx': + return '/static/base/view/ppt.png'; + case 'zip': + case 'rar': + case '7z': + return '/static/base/view/zip.png'; + default: + return '/static/base/view/more.png'; + } +}; + // 获取状态样式类 const getStatusClass = (status: any) => { const statusMap: Record = { @@ -1040,6 +1036,314 @@ const getUrgencyText = (level: string) => { return levelMap[level] || "未知"; }; +// 获取原始文件名 +const getOriginalFileName = (file: FileInfo) => { + // 优先使用resourName,如果没有则使用name,确保文件名正确 + let fileName = ''; + if (file.resourName) { + // 如果resourName已经包含扩展名,直接使用 + if (file.resSuf && !file.resourName.includes('.' + file.resSuf)) { + fileName = `${file.resourName}.${file.resSuf}`; + } else { + fileName = file.resourName; + } + } else if (file.name) { + // 如果name已经包含扩展名,直接使用 + if (file.resSuf && !file.name.includes('.' + file.resSuf)) { + fileName = `${file.name}.${file.resSuf}`; + } else { + fileName = file.name; + } + } else { + // 最后备用方案,从URL提取文件名 + const urlFileName = file.url.split('/').pop() || '未知文件'; + fileName = urlFileName; + } + + return fileName; +}; + +// 显示下载路径选择弹窗 +const showDownloadPathModal = (url: string, fileName: string) => { + downloadUrl.value = url; + downloadFileName.value = fileName; + showDownloadModal.value = true; +}; + +// 确认下载 +const confirmDownload = () => { + // 设置下载状态 + isDownloading.value = true; + + // 检查当前平台 + const systemInfo = uni.getSystemInfoSync(); + const { platform } = systemInfo; + + // 备用检测方法 + const isH5 = platform === 'web' || typeof window !== 'undefined'; + + console.log('平台检测:', { platform, systemInfo, isH5 }); + + if (isH5) { + console.log('使用H5下载方式'); + // H5环境下使用直接链接下载,避免跨域问题 + downloadForH5(downloadUrl.value, downloadFileName.value); + } else { + console.log('使用原生下载方式'); + // 原生环境下使用原有下载方式 + downloadFile(downloadUrl.value, downloadFileName.value) + .then(() => { + // 下载成功后关闭弹窗 + isDownloading.value = false; + showDownloadModal.value = false; + uni.showToast({ + title: "下载成功", + icon: "success", + }); + }) + .catch((error) => { + console.error('下载失败:', error); + // 下载失败后也关闭弹窗 + isDownloading.value = false; + showDownloadModal.value = false; + uni.showToast({ + title: "下载失败", + icon: "error", + }); + }); + } +}; + +// H5环境下的下载方法 +const downloadForH5 = (url: string, fileName: string) => { + try { + console.log('H5下载开始:', { url, fileName }); + + // 直接使用强制下载方式,避免打开文件 + forceDownload(url, fileName); + + } catch (error) { + console.error('H5下载失败:', error); + // 如果整个方法失败,回退到直接链接方式 + fallbackDownload(url, fileName); + } +}; + +// 强制下载方法 +const forceDownload = (url: string, fileName: string) => { + try { + console.log('尝试强制下载:', { url, fileName }); + + // 方法1: 使用fetch下载文件内容,然后创建blob下载 + fetch(url, { + method: 'GET', + mode: 'cors', + cache: 'no-cache' + }) + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.blob(); + }) + .then(blob => { + console.log('文件下载成功,创建blob下载'); + + // 创建blob URL + const blobUrl = window.URL.createObjectURL(blob); + + // 创建下载链接 + const link = document.createElement('a'); + link.href = blobUrl; + link.download = fileName; + link.style.display = 'none'; + + // 添加到DOM并触发点击 + document.body.appendChild(link); + link.click(); + + // 清理DOM和blob URL + document.body.removeChild(link); + window.URL.revokeObjectURL(blobUrl); + + // 下载成功后关闭弹窗 + isDownloading.value = false; + showDownloadModal.value = false; + uni.showToast({ + title: "下载成功", + icon: "success", + }); + }) + .catch(error => { + console.error('Fetch下载失败,尝试其他方法:', error); + // 如果fetch失败,尝试其他方法 + tryAlternativeDownload(url, fileName); + }); + + } catch (error) { + console.error('强制下载失败,尝试其他方法:', error); + tryAlternativeDownload(url, fileName); + } +}; + +// 尝试替代下载方法 +const tryAlternativeDownload = (url: string, fileName: string) => { + console.log('尝试替代下载方法'); + + // 方法1: 使用XMLHttpRequest下载 + try { + const xhr = new XMLHttpRequest(); + xhr.open('GET', url, true); + xhr.responseType = 'blob'; + + xhr.onload = function() { + if (xhr.status === 200) { + const blob = xhr.response; + 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); + + window.URL.revokeObjectURL(blobUrl); + + // 下载成功后关闭弹窗 + isDownloading.value = false; + showDownloadModal.value = false; + uni.showToast({ + title: "下载成功", + icon: "success", + }); + + console.log('XMLHttpRequest下载成功'); + } else { + throw new Error(`HTTP error! status: ${xhr.status}`); + } + }; + + xhr.onerror = function() { + console.error('XMLHttpRequest下载失败'); + console.log('调用手动下载提示'); + showManualDownloadModal(url, fileName); + }; + + xhr.send(); + + } catch (error) { + console.error('XMLHttpRequest失败:', error); + console.log('调用手动下载提示(catch)'); + showManualDownloadModal(url, fileName); + } +}; + +// 显示手动下载提示 +const showManualDownloadModal = (url: string, fileName: string) => { + console.log('尝试原生下载'); + + // 尝试使用浏览器原生下载 + try { + const link = document.createElement('a'); + link.href = url; + link.download = fileName; + link.target = '_blank'; + link.style.display = 'none'; + + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + + console.log('原生下载已触发'); + + // 延迟关闭弹窗,给用户时间看到下载开始 + setTimeout(() => { + isDownloading.value = false; + showDownloadModal.value = false; + }, 1000); + + uni.showToast({ + title: "开始下载", + icon: "success", + }); + } catch (error) { + console.error('原生下载失败:', error); + // 下载失败也关闭弹窗 + isDownloading.value = false; + showDownloadModal.value = false; + uni.showToast({ + title: "下载失败", + icon: "error", + }); + } +}; + +// 直接下载方法 +const directDownload = (url: string, fileName: string) => { + try { + // 修改URL添加下载参数 + const downloadUrl = url.includes('?') + ? `${url}&download=1&attachment=1` + : `${url}?download=1&attachment=1`; + + const link = document.createElement('a'); + link.href = downloadUrl; + link.download = fileName; + link.target = '_self'; // 使用_self而不是_blank + link.style.display = 'none'; + + // 添加到DOM并触发点击 + document.body.appendChild(link); + link.click(); + + // 清理DOM + document.body.removeChild(link); + + uni.showToast({ + title: "开始下载", + icon: "success", + }); + + } catch (error) { + console.error('直接下载失败:', error); + // 最后的方法:提示用户手动下载 + uni.showModal({ + title: '下载提示', + content: `由于浏览器限制,无法自动下载文件。请长按链接手动保存:\n${url}`, + showCancel: false, + confirmText: '知道了' + }); + } +}; + +// 备用下载方法 +const fallbackDownload = (url: string, fileName: string) => { + try { + console.log('使用备用下载方法'); + + // 使用直接下载方法 + directDownload(url, fileName); + + } catch (error) { + console.error('备用下载也失败:', error); + // 最后的方法:提示用户手动下载 + uni.showModal({ + title: '下载提示', + content: `由于浏览器限制,无法自动下载文件。请长按链接手动保存:\n${url}`, + showCancel: false, + confirmText: '知道了' + }); + } +}; + +// 取消下载 +const cancelDownload = () => { + showDownloadModal.value = false; +}; + // 获取创建人名称 const getCreatorName = (tjrId: string) => { if (!tjrId) return "未知"; @@ -1232,9 +1536,16 @@ onMounted(() => { .file-icon { margin-right: 12px; - font-size: 24px; width: 32px; - text-align: center; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + + .icon-image { + width: 28px; + height: 28px; + } } .file-info { @@ -1524,4 +1835,121 @@ onMounted(() => { } } } + +.download-modal { + width: 85vw; + max-width: 450px; + padding: 20px; + background: #fff; + border-radius: 12px; + + .download-header { + text-align: center; + margin-bottom: 20px; + padding-bottom: 15px; + border-bottom: 1px solid #eee; + + .download-title { + font-size: 18px; + font-weight: bold; + color: #333; + } + } + + .download-content { + margin-bottom: 25px; + + .file-info-section { + display: flex; + align-items: flex-start; + margin-bottom: 15px; + + .file-label { + font-weight: 500; + color: #666; + margin-right: 10px; + flex-shrink: 0; + width: 60px; + } + + .file-name { + color: #333; + font-size: 14px; + word-break: break-all; + flex: 1; + background: #f8f9fa; + padding: 8px 12px; + border-radius: 6px; + border: 1px solid #e9ecef; + } + } + + .path-info-section { + display: flex; + align-items: center; + margin-bottom: 15px; + + .path-label { + font-weight: 500; + color: #666; + margin-right: 10px; + flex-shrink: 0; + width: 60px; + } + + .path-text { + color: #007aff; + font-size: 14px; + flex: 1; + } + } + + .download-tips { + text-align: center; + + .tips-text { + color: #999; + font-size: 12px; + } + } + } + + .download-actions { + display: flex; + justify-content: center; + gap: 10px; + + .u-button { + flex: 1; + max-width: 120px; + } + } + + .download-progress { + display: flex; + flex-direction: column; + align-items: center; + padding: 20px 0; + + .progress-spinner { + width: 24px; + height: 24px; + border: 2px solid #f3f3f3; + border-top: 2px solid #007aff; + border-radius: 50%; + animation: spin 1s linear infinite; + margin-bottom: 10px; + } + + .progress-text { + color: #666; + font-size: 14px; + } + } +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} diff --git a/src/pages/view/routine/gwlz/index.vue b/src/pages/view/routine/gwlz/index.vue index f5d6f9a..ccaa049 100644 --- a/src/pages/view/routine/gwlz/index.vue +++ b/src/pages/view/routine/gwlz/index.vue @@ -79,7 +79,11 @@ @click="previewAttachmentFile(file)" > - 📄 + {{ getFileName(file) }} @@ -529,6 +533,30 @@ const getFileSuffix = (file: FileInfo) => { return 'unknown'; }; +// 获取文件图标 +const getFileIcon = (fileType: string) => { + const type = fileType.toLowerCase(); + switch (type) { + case 'pdf': + return '/static/base/view/pdf.png'; + case 'doc': + case 'docx': + return '/static/base/view/word.png'; + case 'xls': + case 'xlsx': + return '/static/base/view/excel.png'; + case 'ppt': + case 'pptx': + return '/static/base/view/ppt.png'; + case 'zip': + case 'rar': + case '7z': + return '/static/base/view/zip.png'; + default: + return '/static/base/view/more.png'; + } +}; + // 监听数据变化 watch(dataList, (val) => { // 数据变化监听 @@ -810,8 +838,17 @@ onUnmounted(() => { .attachment-icon { margin-right: 6px; - font-size: 16px; + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; flex-shrink: 0; + + .icon-image { + width: 18px; + height: 18px; + } } .attachment-name { diff --git a/src/pages/view/routine/kefuxuncha/kyRecord.vue b/src/pages/view/routine/kefuxuncha/kyRecord.vue index 3e5fd0a..799ffec 100644 --- a/src/pages/view/routine/kefuxuncha/kyRecord.vue +++ b/src/pages/view/routine/kefuxuncha/kyRecord.vue @@ -174,6 +174,9 @@ let inspectionParams = ref({ rows: 10, kyXcId: xkkc.value.id, jsId: js.value.id, + njId: xkkc.value.njId, + bjId: xkkc.value.bjId, + njmcId: xkkc.value.njmcId, }); // 巡查记录列表 diff --git a/src/pages/view/routine/kefuxuncha/kyXkList.vue b/src/pages/view/routine/kefuxuncha/kyXkList.vue index 33f442c..faf5300 100644 --- a/src/pages/view/routine/kefuxuncha/kyXkList.vue +++ b/src/pages/view/routine/kefuxuncha/kyXkList.vue @@ -91,7 +91,7 @@