diff --git a/src/api/base/server.ts b/src/api/base/server.ts
index 1cc16a9..6c2c56f 100644
--- a/src/api/base/server.ts
+++ b/src/api/base/server.ts
@@ -163,9 +163,13 @@ export const typesFindTreeApi = async () => {
export const resourcesFindPageApi = async (params: any) => {
return await get("/api/resources/findPage", params);
};
-// 获取资源分页
+
+export const resourcesSaveApi = async (params: any) => {
+ return await post("/api/resources/save", params);
+};
+
export const resourcesAddNumByTypeApi = async (params: any) => {
- return await post("/api/resources/addNumByType", params);
+ return await post("/api/resources/addNumByType", params);
};
// 获取工作量
diff --git a/src/config.ts b/src/config.ts
index 6a814b0..a58b5aa 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -1,7 +1,7 @@
const ip: string = "127.0.0.1:8897";
// const ip: string = "yufangzc.com";
-// const ip: string = "yufangzc.com";
-const fwqip: string = "yufangzc.com";
+// const ip: string = "lzcxsx.cn";
+const fwqip: string = "lzcxsx.cn";
//打包服务器接口代理标识
const SERVERAGENT: string = "/jsd-api";
//本地代理url地址,配置了就启动代理,没配置就不启动代理
@@ -13,7 +13,9 @@ export const BASE_URL: string =
export const BASE_WS_URL: string = `wss://${ip}`;
//图片地址
// export const BASE_IMAGE_URL: string = process.env.NODE_ENV == "development" ? `https://${ip}` : `https://${fwqip}`;
-export const BASE_IMAGE_URL = `http://${fwqip}`;
+export const BASE_IMAGE_URL = `https://${fwqip}`;
+// kkFileView预览服务地址
+export const KK_FILE_VIEW_URL: string = `http://${fwqip}:8891`;
//存token的key
export const AUTH_KEY: string = "satoken";
//token过期返回状态码
diff --git a/src/pages.json b/src/pages.json
index 36dccee..087006a 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -51,6 +51,24 @@
"backgroundColor": "#ffffff"
}
},
+ {
+ "path": "pages/system/web-viewer/index",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "文件预览",
+ "enablePullDownRefresh": false,
+ "backgroundColor": "#f5f5f5"
+ }
+ },
+ {
+ "path": "pages/system/video-player/index",
+ "style": {
+ "navigationStyle": "custom",
+ "navigationBarTitleText": "视频播放",
+ "enablePullDownRefresh": false,
+ "backgroundColor": "#000000"
+ }
+ },
{
"path": "pages/system/updatePopup/updatePopup",
"style": {
diff --git a/src/pages/system/video-player/index.vue b/src/pages/system/video-player/index.vue
new file mode 100644
index 0000000..7ba44f3
--- /dev/null
+++ b/src/pages/system/video-player/index.vue
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+
+
+
+ {{ videoTitle }}
+ {{ videoDesc }}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/pages/system/web-viewer/index.vue b/src/pages/system/web-viewer/index.vue
new file mode 100644
index 0000000..2b3e578
--- /dev/null
+++ b/src/pages/system/web-viewer/index.vue
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/pages/view/notice/index.vue b/src/pages/view/notice/index.vue
index 7361f24..9eb2b05 100644
--- a/src/pages/view/notice/index.vue
+++ b/src/pages/view/notice/index.vue
@@ -27,20 +27,20 @@
>范围: {{ data.njmc + data.bjmc }}
diff --git a/src/pages/view/routine/JiaoXueZiYuan/index.vue b/src/pages/view/routine/JiaoXueZiYuan/index.vue
index 34324d5..49d5a3c 100644
--- a/src/pages/view/routine/JiaoXueZiYuan/index.vue
+++ b/src/pages/view/routine/JiaoXueZiYuan/index.vue
@@ -111,6 +111,22 @@ onMounted(async () => {
const res = await typesFindTreeApi();
typeTree.value = res.result || [];
console.log('教学资源页面加载完成', res);
+
+ // 默认选择语文科目
+ if (typeTree.value.length > 0) {
+ // 查找语文科目
+ const chineseSubject = typeTree.value.find(item =>
+ item.title && (item.title.includes('语文') || item.title.includes('语文'))
+ );
+
+ if (chineseSubject) {
+ // 选择语文科目
+ selectType(chineseSubject);
+ } else {
+ // 如果没找到语文,选择第一个科目
+ selectType(typeTree.value[0]);
+ }
+ }
});
diff --git a/src/pages/view/routine/JiaoXueZiYuan/indexList.vue b/src/pages/view/routine/JiaoXueZiYuan/indexList.vue
index 0ef3ccf..cb6d996 100644
--- a/src/pages/view/routine/JiaoXueZiYuan/indexList.vue
+++ b/src/pages/view/routine/JiaoXueZiYuan/indexList.vue
@@ -16,40 +16,265 @@
-
-
-
- {{ data.resSuf }}
-
+
+
+
-
- {{ data.resourName }}{{ data.hour ? ' - ' + data.hour : '' }}
- 《{{ data.resourName }}》{{ data.hour ? ' - ' + data.hour : '' }}
+
+
+
{{ tag }}
-
- {{ data.createdTime }}
- 浏览量: {{ data.lookNum }}
- 下载量: {{ data.downNum }}
+
+
+
+ {{ data.createdTime }}
+
+
+
+
+ 浏览量: {{ data.lookNum }}
+ 下载量: {{ data.downNum }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/pages/view/routine/qd/confirm.vue b/src/pages/view/routine/qd/confirm.vue
index 9379db6..e36d011 100644
--- a/src/pages/view/routine/qd/confirm.vue
+++ b/src/pages/view/routine/qd/confirm.vue
@@ -115,7 +115,7 @@
二维码信息
二维码有效期:
- 60秒
+ {{ qrExpireTime }}秒
当前时间:
@@ -126,6 +126,38 @@
+
+
+
+
+
+ 您已签到成功
+ 您已经完成本次签到,请勿重复签到
+ 如需重新签到,请联系会议组织者
+
+
+ 会议信息
+
+ 会议名称:
+ {{ meetingInfo?.qdmc || '未设置' }}
+
+
+ 会议时间:
+ {{ formatTime(meetingInfo?.qdkstime) }} - {{ formatTime(meetingInfo?.qdjstime) }}
+
+
+ 会议地点:
+ {{ meetingInfo?.qdwz || '未设置' }}
+
+
+ 签到时间:
+ {{ formatTime(qdzxRecord?.qdwctime) }}
+
+
+
+
+
+
@@ -139,11 +171,20 @@ import { qdFindByIdApi, qdzxSignInApi, qdzxFindByQdParamsApi, qdzxFindByQdAndJsA
import { useUserStore } from '@/store/modules/user';
// 页面参数
+const options = ref({});
+
+// 页面加载时接收参数
+onLoad((params) => {
+ options.value = params;
+});
+
+// 签到相关变量
const qdId = ref('');
const qdzxId = ref('');
+const qrExpireTime = ref(60); // 默认60秒
// 当前步骤
-const currentStep = ref<'sign' | 'confirm' | 'success' | 'notInList' | 'timeExpired' | 'qrExpired'>('confirm');
+const currentStep = ref<'sign' | 'confirm' | 'success' | 'notInList' | 'timeExpired' | 'qrExpired' | 'alreadySigned'>('confirm');
// 用户信息
const userInfo = ref(null);
@@ -163,21 +204,26 @@ const showSignature = ref(false);
// 获取用户store
const userStore = useUserStore();
-onLoad(async (options) => {
- if (options?.qdId) {
- qdId.value = options.qdId;
+// 页面初始化
+onMounted(async () => {
+ // 获取签到ID
+ if (options.value?.qdId) {
+ qdId.value = options.value.qdId;
+ } else {
+ uni.showToast({ title: '参数错误', icon: 'none' });
+ return;
}
- if (options?.qdzxId) {
- qdzxId.value = options.qdzxId;
+
+ // 获取二维码过期时间参数
+ if (options.value?.rqgqtime) {
+ qrExpireTime.value = parseInt(options.value.rqgqtime) || 60;
}
// 第一步:获取缓存的教师信息
const jsData = userStore.getJs;
if (jsData && Object.keys(jsData).length > 0) {
userInfo.value = jsData;
- console.log('获取到教师信息:', jsData);
} else {
- console.error('未找到教师信息,请先登录');
uni.showToast({ title: '请先登录', icon: 'none' });
// 跳转到登录页面
setTimeout(() => {
@@ -189,21 +235,13 @@ onLoad(async (options) => {
}
// 验证二维码时间戳是否过期
- if (options?.timestamp) {
- const qrTimestamp = parseInt(options.timestamp);
+ if (options.value?.timestamp) {
+ const qrTimestamp = parseInt(options.value.timestamp);
const currentTimestamp = Date.now();
const timeDiff = currentTimestamp - qrTimestamp;
- const maxValidTime = 60 * 1000; // 60秒有效期
-
- console.log('二维码时间戳验证:', {
- qrTimestamp,
- currentTimestamp,
- timeDiff,
- maxValidTime
- });
+ const maxValidTime = qrExpireTime.value * 1000; // 转换为毫秒
if (timeDiff > maxValidTime) {
- console.error('二维码已过期');
currentStep.value = 'qrExpired';
return;
}
@@ -220,23 +258,24 @@ const checkTeacherSignInPermission = async () => {
qdId: qdId.value,
jsId: userInfo.value.id
});
-
+
if (result && result.resultCode === 1 && result.result) {
// 找到签到记录
qdzxRecord.value = result.result;
qdzxId.value = result.result.id;
- console.log('找到教师签到记录:', result.result);
// 第三步:获取签到详情,验证是否需要签名
await loadMeetingInfo();
- } else {
- // 没有找到签到记录,显示"不在签到名单中"界面
+ } else if (result && result.resultCode === 0) {
+ // 后端明确返回未找到记录
currentStep.value = 'notInList';
await loadMeetingInfo(); // 仍然加载会议信息用于显示
+ } else {
+ // 其他错误情况
+ uni.showToast({ title: '查询签到权限失败', icon: 'none' });
}
} catch (error) {
- console.error('查询教师签到权限失败:', error);
- uni.showToast({ title: '查询签到权限失败', icon: 'none' });
+ uni.showToast({ title: '网络异常,请重试', icon: 'none' });
}
};
@@ -259,6 +298,13 @@ const loadMeetingInfo = async () => {
// 只有在找到qdzxId时才检查是否需要签名
if (qdzxId.value) {
+ // 检查是否已经签到
+ if (qdzxRecord.value?.qdStatus === '1') {
+ // 已经签到,跳转到重复签到界面
+ currentStep.value = 'alreadySigned';
+ return;
+ }
+
// 检查是否需要签名
if (meetingInfo.value?.mdqz === '1') {
// 需要签名,调用签名组件
@@ -270,7 +316,6 @@ const loadMeetingInfo = async () => {
}
}
} catch (error) {
- console.error('加载会议信息失败:', error);
uni.showToast({ title: '加载会议信息失败', icon: 'none' });
}
};
@@ -292,7 +337,6 @@ const handleSignature = async () => {
currentStep.value = 'confirm';
} catch (error) {
showSignature.value = false;
- console.error('签名失败:', error);
uni.showToast({ title: '签名失败', icon: 'none' });
}
};
@@ -310,24 +354,15 @@ const submitSignIn = async () => {
params.signatureImage = sign_file.value;
}
- console.log('提交签到参数:', JSON.stringify(params, null, 2));
- console.log('参数类型检查:', {
- qdzxId: typeof params.qdzxId,
- signInTime: typeof params.signInTime,
- signatureImage: typeof params.signatureImage
- });
-
const result = await qdzxSignInApi(params);
- console.log('签到结果:', result);
if (result && result.resultCode === 1) {
currentStep.value = 'success';
} else {
- const errorMsg = result?.msg || result?.message || '签到失败';
+ const errorMsg = result?.message || '签到失败';
uni.showToast({ title: errorMsg, icon: 'none' });
}
} catch (error) {
- console.error('签到失败:', error);
uni.showToast({ title: '网络异常,请重试', icon: 'none' });
}
};
@@ -627,4 +662,35 @@ const goBack = () => {
}
}
}
+
+/* 重复签到阶段 */
+.already-signed-step {
+ background: white;
+ border-radius: 16px;
+ padding: 40px 24px;
+ margin-top: 40px;
+ text-align: center;
+}
+
+.already-signed-content {
+ .already-signed-title {
+ display: block;
+ font-size: 24px;
+ font-weight: 600;
+ color: #333;
+ margin: 16px 0 8px;
+ }
+
+ .already-signed-subtitle {
+ font-size: 14px;
+ color: #666;
+ margin-bottom: 16px;
+ }
+
+ .already-signed-tip {
+ font-size: 14px;
+ color: #999;
+ margin-bottom: 24px;
+ }
+}
\ No newline at end of file
diff --git a/src/pages/view/routine/qd/qr-code.vue b/src/pages/view/routine/qd/qr-code.vue
index eda6df9..e75441a 100644
--- a/src/pages/view/routine/qd/qr-code.vue
+++ b/src/pages/view/routine/qd/qr-code.vue
@@ -57,7 +57,7 @@
使用说明
- 1. 二维码有效期为60秒,请及时扫描
+ 1. 二维码有效期为{{ qrExpireTime }}秒,请及时扫描
2. 使用微信扫一扫功能扫描二维码
3. 扫描后将跳转到签到确认页面
4. 请确保网络连接正常
@@ -74,6 +74,7 @@ import { qdFindByIdApi, generateQRCodeApi } from '@/api/base/server';
// 页面参数
const qdId = ref('');
+const qrExpireTime = ref(60); // 默认60秒
// 会议信息
const meetingInfo = ref(null);
@@ -88,6 +89,10 @@ onLoad((options) => {
if (options?.qdId) {
qdId.value = options.qdId;
}
+
+ // 启动默认倒计时,等待二维码数据解析后更新
+ startTimer();
+
loadMeetingInfo();
});
@@ -118,14 +123,24 @@ const initQRCode = async () => {
if (result && result.resultCode === 1) {
// 确保二维码数据是字符串格式
const qrData = result.result || '';
- console.log('二维码数据:', qrData);
+
+ // 从二维码数据中解析rqgqtime参数
+ const urlParams = new URLSearchParams(qrData.split('?')[1] || '');
+ const rqgqtime = urlParams.get('rqgqtime');
+ if (rqgqtime) {
+ const expireTime = parseInt(rqgqtime) || 60;
+ qrExpireTime.value = expireTime;
+ qrTimer.value = expireTime;
+ // 重新启动倒计时
+ startTimer();
+ }
+
generateQRCodeImage(qrData);
} else {
throw new Error('生成二维码失败');
}
- // 启动倒计时
- startTimer();
+ // 倒计时已在onLoad中启动,这里不需要重复启动
} catch (error) {
console.error('生成二维码失败:', error);
uni.showToast({ title: '生成二维码失败', icon: 'none' });
@@ -171,7 +186,6 @@ const generateQRCodeImage = (qrData: string) => {
qrCanvas.drawImage(url, 0, 0, qrSize.value, qrSize.value);
qrCanvas.draw();
- console.log('二维码生成成功');
});
}).catch((error) => {
console.error('加载qrcode库失败:', error);
@@ -186,8 +200,6 @@ const generateQRCodeImage = (qrData: string) => {
qrCanvas.draw();
});
- console.log('二维码数据:', qrData);
-
} catch (error) {
console.error('生成二维码异常:', error);
// 异常处理,显示错误信息
@@ -204,7 +216,7 @@ const generateQRCodeImage = (qrData: string) => {
// 启动倒计时
const startTimer = () => {
- qrTimer.value = 60;
+ qrTimer.value = qrExpireTime.value;
if (qrTimerInterval) {
clearInterval(qrTimerInterval);
}
@@ -224,6 +236,8 @@ const startTimer = () => {
const refreshQRCode = async () => {
try {
await initQRCode();
+ // 重新启动倒计时
+ startTimer();
uni.showToast({ title: '二维码已刷新', icon: 'success' });
} catch (error) {
uni.showToast({ title: '刷新失败', icon: 'none' });
diff --git a/src/utils/filePreview.ts b/src/utils/filePreview.ts
new file mode 100644
index 0000000..751cde3
--- /dev/null
+++ b/src/utils/filePreview.ts
@@ -0,0 +1,419 @@
+/**
+ * 文件预览工具函数
+ * 提供跨平台的文件预览功能
+ */
+
+import { KK_FILE_VIEW_URL } from '@/config';
+
+// 文件类型判断
+export const isVideo = (fileType: string): boolean => {
+ const videoTypes = ['mp4', 'avi', 'mov', 'wmv', 'flv', 'webm', 'mkv', '3gp', 'm4v'];
+ return videoTypes.includes(fileType.toLowerCase());
+};
+
+export const isImage = (fileType: string): boolean => {
+ const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
+ return imageTypes.includes(fileType.toLowerCase());
+};
+
+// 检查是否是压缩包文件
+export const isCompressedFile = (fileName: string): boolean => {
+ const compressedExtensions = ['zip', 'rar', '7z', 'tar', 'gz', 'bz2'];
+ const extension = fileName.split('.').pop()?.toLowerCase();
+ return compressedExtensions.includes(extension || '');
+};
+
+// 检查文件是否可以预览
+export const canPreview = (fileName: string): boolean => {
+ const previewableExtensions = [
+ 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx',
+ 'txt', 'rtf', 'odt', 'ods', 'odp',
+ 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp',
+ 'mp4', 'avi', 'mov', 'wmv', 'flv', 'webm',
+ 'mp3', 'wav', 'ogg', 'aac', 'm4a'
+ ];
+ const extension = fileName.split('.').pop()?.toLowerCase();
+ return previewableExtensions.includes(extension || '');
+};
+
+// 获取文件图标
+export const getFileIcon = (fileName: string): string => {
+ const extension = fileName.split('.').pop()?.toLowerCase();
+
+ // 压缩包文件显示下载图标
+ if (isCompressedFile(fileName)) {
+ return '📥';
+ }
+
+ switch (extension) {
+ case 'pdf':
+ return '📄';
+ case 'doc':
+ case 'docx':
+ return '📝';
+ case 'xls':
+ case 'xlsx':
+ return '📊';
+ case 'ppt':
+ case 'pptx':
+ return '📽️';
+ case 'txt':
+ return '📃';
+ case 'jpg':
+ case 'jpeg':
+ case 'png':
+ case 'gif':
+ case 'bmp':
+ case 'webp':
+ return '🖼️';
+ case 'mp4':
+ case 'avi':
+ case 'mov':
+ case 'wmv':
+ case 'flv':
+ case 'webm':
+ return '🎥';
+ case 'mp3':
+ case 'wav':
+ case 'ogg':
+ case 'aac':
+ case 'm4a':
+ return '🎵';
+ default:
+ return '📄';
+ }
+};
+
+// 获取文件类型名称
+export const getFileTypeName = (fileName: string): string => {
+ const extension = fileName.split('.').pop()?.toLowerCase();
+
+ // 压缩包文件
+ if (isCompressedFile(fileName)) {
+ switch (extension) {
+ case 'zip':
+ return 'ZIP压缩包';
+ case 'rar':
+ return 'RAR压缩包';
+ case '7z':
+ return '7Z压缩包';
+ case 'tar':
+ return 'TAR压缩包';
+ case 'gz':
+ return 'GZ压缩包';
+ case 'bz2':
+ return 'BZ2压缩包';
+ default:
+ return '压缩包';
+ }
+ }
+
+ switch (extension) {
+ case 'pdf':
+ return 'PDF文档';
+ case 'doc':
+ case 'docx':
+ return 'Word文档';
+ case 'xls':
+ case 'xlsx':
+ return 'Excel表格';
+ case 'ppt':
+ case 'pptx':
+ return 'PowerPoint演示';
+ case 'txt':
+ return '文本文件';
+ case 'jpg':
+ case 'jpeg':
+ case 'png':
+ case 'gif':
+ case 'bmp':
+ case 'webp':
+ return '图片文件';
+ case 'mp4':
+ case 'avi':
+ case 'mov':
+ case 'wmv':
+ case 'flv':
+ case 'webm':
+ return '视频文件';
+ case 'mp3':
+ case 'wav':
+ case 'ogg':
+ case 'aac':
+ case 'm4a':
+ return '音频文件';
+ default:
+ return '未知文件';
+ }
+};
+
+// 跨平台文件预览
+export const previewFile = (fileUrl: string, fileName: string, fileType: string) => {
+ return new Promise((resolve, reject) => {
+ const systemInfo = uni.getSystemInfoSync();
+ const { platform } = systemInfo;
+ const type = fileType.toLowerCase();
+
+ console.log('=== 文件预览调试信息 ===');
+ console.log('平台:', platform);
+ console.log('系统信息:', systemInfo);
+ console.log('原始文件URL:', fileUrl);
+ console.log('文件名:', fileName);
+ console.log('文件类型:', fileType);
+
+ // 检查是否是压缩包文件,如果是则直接下载
+ if (isCompressedFile(fileName)) {
+ console.log('=== 检测到压缩包文件,直接下载 ===');
+ uni.showToast({ title: '压缩包文件不支持预览,将为您下载', icon: 'none' });
+ downloadFile(fileUrl, fileName).then(resolve).catch(resolve);
+ return;
+ }
+
+ // 检查是否支持预览的文件格式
+ const canPreviewType = canPreview(fileName);
+
+ if (!canPreviewType) {
+ // 不支持预览的文件格式,直接下载
+ console.log('不支持预览的文件格式,执行下载');
+ uni.showToast({ title: '该文件格式暂不支持预览,将为您下载', icon: 'none' });
+ downloadFile(fileUrl, fileName).then(resolve).catch(resolve);
+ return;
+ }
+
+ // 检查URL是否已经是kkFileView生成的压缩包内文件URL
+ const isCompressedFileUrl = fileUrl.includes('kkCompressfileKey') && fileUrl.includes('kkCompressfilepath');
+
+ console.log('=== 压缩包内文件检测 ===');
+ console.log('URL包含kkCompressfileKey:', fileUrl.includes('kkCompressfileKey'));
+ console.log('URL包含kkCompressfilepath:', fileUrl.includes('kkCompressfilepath'));
+ console.log('是否为压缩包内文件URL:', isCompressedFileUrl);
+
+ if (isCompressedFileUrl) {
+ console.log('=== 压缩包内文件处理 ===');
+ console.log('检测到压缩包内文件URL,直接使用');
+ console.log('原始压缩包内文件URL:', fileUrl);
+
+ const previewUrl = fileUrl; // 直接使用这个URL,不重新编码
+ console.log('最终预览URL (压缩包内文件):', previewUrl);
+
+ const needLandscape = ['ppt', 'pptx'].includes(type);
+ console.log('是否需要横屏显示:', needLandscape);
+
+ const targetPageUrl = `/pages/system/web-viewer/index?url=${encodeURIComponent(previewUrl)}&title=${encodeURIComponent(fileName)}&landscape=${needLandscape ? '1' : '0'}`;
+ console.log('跳转目标页面URL:', targetPageUrl);
+
+ uni.navigateTo({
+ url: targetPageUrl,
+ success: () => {
+ console.log('跳转到压缩包内文件预览页面成功');
+ resolve(true);
+ },
+ fail: (err) => {
+ console.error('跳转到压缩包内文件预览页面失败:', err);
+ console.log('错误详情:', JSON.stringify(err));
+ uni.showToast({ title: '预览加载失败,尝试下载', icon: 'none' });
+ setTimeout(() => {
+ downloadFile(fileUrl, fileName).then(resolve).catch(resolve);
+ }, 1000);
+ }
+ });
+ return; // 退出函数
+ }
+
+ console.log('=== 普通文件处理 ===');
+
+ // 处理普通文件预览
+ const finalFileUrl = fileUrl;
+ console.log('DEBUG: 最终用于编码的URL (finalFileUrl):', finalFileUrl);
+
+ // 使用kkFileView进行预览
+ const encodedUrl = btoa(finalFileUrl);
+ console.log('使用kkFileView预览,Base64编码后的URL:', encodedUrl);
+
+ const previewUrl = `http://yufangzc.com:8891/onlinePreview?url=${encodeURIComponent(encodedUrl)}`;
+ console.log('最终预览URL (普通文件):', previewUrl);
+
+ const needLandscape = ['ppt', 'pptx'].includes(type);
+ console.log('是否需要横屏显示:', needLandscape);
+
+ const targetPageUrl = `/pages/system/web-viewer/index?url=${encodeURIComponent(previewUrl)}&title=${encodeURIComponent(fileName)}&landscape=${needLandscape ? '1' : '0'}`;
+ console.log('跳转目标页面URL:', targetPageUrl);
+
+ uni.navigateTo({
+ url: targetPageUrl,
+ success: () => {
+ console.log('跳转到预览页面成功');
+ resolve(true);
+ },
+ fail: (err) => {
+ console.error('跳转到预览页面失败:', err);
+ console.log('错误详情:', JSON.stringify(err));
+ uni.showToast({ title: '预览加载失败,尝试下载', icon: 'none' });
+ setTimeout(() => {
+ downloadFile(fileUrl, fileName).then(resolve).catch(resolve);
+ }, 1000);
+ }
+ });
+ });
+};
+
+// 下载文件
+export const downloadFile = (fileUrl: string, fileName: string) => {
+ const { platform } = uni.getSystemInfoSync();
+
+ if (platform === 'web') {
+ return downloadForWeb(fileUrl, fileName);
+ } else {
+ return downloadForNative(fileUrl, fileName);
+ }
+};
+
+// H5平台下载
+const downloadForWeb = (url: string, filename: string) => {
+ return new Promise((resolve, reject) => {
+ fetch(url)
+ .then((response) => response.blob())
+ .then((blob) => {
+ const downloadUrl = window.URL.createObjectURL(new Blob([blob]));
+ const link = document.createElement('a');
+ link.href = downloadUrl;
+ link.setAttribute('download', filename);
+ document.body.appendChild(link);
+ link.click();
+ link.remove();
+ window.URL.revokeObjectURL(downloadUrl);
+ uni.showToast({ title: "开始下载", icon: "success" });
+ resolve(true);
+ })
+ .catch((err) => {
+ console.error("H5下载失败:", err);
+ uni.showToast({ title: "下载失败", icon: "none" });
+ reject(err);
+ });
+ });
+};
+
+// 原生平台下载
+const downloadForNative = (url: string, filename: string) => {
+ return new Promise((resolve, reject) => {
+ uni.showLoading({ title: "下载中..." });
+
+ uni.downloadFile({
+ url: url,
+ success: async (res) => {
+ if (res.statusCode === 200) {
+ try {
+ const saved = await saveFile(res.tempFilePath, filename);
+ if (saved) {
+ // 尝试打开文件
+ uni.openDocument({
+ filePath: saved,
+ success: () => {
+ uni.showToast({ title: "文件已打开", icon: "success" });
+ resolve(true);
+ },
+ fail: (err) => {
+ console.warn('文件打开失败:', err);
+ uni.showToast({ title: "文件已下载,但无法打开", icon: "none" });
+ resolve(true); // 下载成功,即使打开失败也算成功
+ }
+ });
+ } else {
+ reject(new Error('保存失败'));
+ }
+ } catch (error) {
+ console.error('处理下载文件时出错:', error);
+ reject(error);
+ }
+ } else {
+ uni.showToast({ title: "下载失败", icon: "none" });
+ reject(new Error('下载失败'));
+ }
+ },
+ fail: (err) => {
+ console.error("下载失败:", err);
+ uni.showToast({ title: "下载失败", icon: "none" });
+ reject(err);
+ },
+ complete: () => uni.hideLoading()
+ });
+ });
+};
+
+// 保存文件
+const saveFile = (tempPath: string, filename: string): Promise => {
+ return new Promise((resolve) => {
+ try {
+ // 检查是否支持文件系统管理器
+ if (typeof uni.getFileSystemManager === 'function') {
+ const fs = uni.getFileSystemManager();
+ const appPath = `${filename}`;
+ fs.rename({
+ oldPath: tempPath,
+ newPath: appPath,
+ success: () => resolve(appPath),
+ fail: () => {
+ console.warn('文件重命名失败,使用临时路径');
+ resolve(tempPath);
+ }
+ });
+ } else {
+ // 不支持文件系统管理器时,直接使用临时路径
+ console.warn('当前平台不支持文件系统管理器,使用临时路径');
+ resolve(tempPath);
+ }
+ } catch (error) {
+ console.error('保存文件时出错:', error);
+ uni.showToast({ title: "保存失败", icon: "none" });
+ resolve(null);
+ }
+ });
+};
+
+// 视频预览
+export const previewVideo = (videoUrl: string, videoTitle: string) => {
+ console.log('=== 视频预览调试信息 ===');
+ console.log('视频URL:', videoUrl);
+ console.log('视频标题:', videoTitle);
+
+ return new Promise((resolve) => {
+ const targetUrl = `/pages/system/video-player/index?url=${encodeURIComponent(videoUrl)}&title=${encodeURIComponent(videoTitle)}`;
+ console.log('跳转目标URL:', targetUrl);
+
+ uni.navigateTo({
+ url: targetUrl,
+ success: () => {
+ console.log('跳转到视频播放页面成功');
+ resolve(true);
+ },
+ fail: (err) => {
+ console.error('跳转到视频播放页面失败:', err);
+ console.log('错误详情:', JSON.stringify(err));
+
+ // 跳转失败时尝试使用系统播放器
+ uni.showToast({
+ title: '跳转失败,尝试使用系统播放器',
+ icon: 'none',
+ duration: 2000
+ });
+
+ // 延迟后尝试下载视频
+ setTimeout(() => {
+ downloadFile(videoUrl, videoTitle + '.mp4').then(resolve).catch(resolve);
+ }, 2000);
+ }
+ });
+ });
+};
+
+// 图片预览
+export const previewImage = (imageUrl: string) => {
+ return new Promise((resolve) => {
+ uni.previewImage({
+ urls: [imageUrl],
+ current: imageUrl,
+ success: resolve,
+ fail: resolve
+ });
+ });
+};
\ No newline at end of file
diff --git a/src/utils/request/index.ts b/src/utils/request/index.ts
index e859b8b..91f935f 100644
--- a/src/utils/request/index.ts
+++ b/src/utils/request/index.ts
@@ -89,7 +89,7 @@ export function get(
options
)
).then((res) => {
- if (res.resultCode == 1) {
+ if (res.resultCode == 1 || res.resultCode == 0) {
resolve(res);
} else {
if (res.resultCode) {