| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- import { getToken } from '@/utils/auth';
- import errorCode from '@/utils/errorCode';
- import { tansParams } from '@/utils/common';
- import config from '@/config';
- import { getCurrentPage } from '@/utils/public';
- import { useInfoStore } from '@/store';
- interface UploadConfig {
- url: string;
- filePath: string;
- name?: string;
- header?: Record<string, any>;
- headers?: Record<string, any>;
- formData?: Record<string, any>;
- params?: Record<string, any>;
- timeout?: number;
- }
- interface UploadResult {
- code: number;
- data?: any;
- msg?: string;
- }
- const timeout = 10000;
- const { baseUrl, clientId, appid } = config;
- const upload = (uploadConfig: UploadConfig): Promise<UploadResult> => {
- // 是否需要设置 token
- const isToken = (uploadConfig.headers || {}).isToken === false;
- uploadConfig.header = uploadConfig.header || {};
- if (getToken() && !isToken) {
- uploadConfig.header['Authorization'] = 'Bearer ' + getToken();
- }
- uploadConfig.header['Clientid'] = clientId; // 默认值
- uploadConfig.header['xid'] = appid; // 默认值
- // get请求映射params参数
- if (uploadConfig.params) {
- let url = uploadConfig.url + '?' + tansParams(uploadConfig.params);
- url = url.slice(0, -1);
- uploadConfig.url = url;
- }
- return new Promise((resolve, reject) => {
- uni.uploadFile({
- timeout: uploadConfig.timeout || timeout,
- url: baseUrl + uploadConfig.url,
- filePath: uploadConfig.filePath,
- name: uploadConfig.name || 'file',
- header: uploadConfig.header,
- formData: uploadConfig.formData,
- success: (res) => {
- const result: UploadResult = JSON.parse(res.data);
- const code = result.code || 200;
- const msg = errorCode[code.toString()] || result.msg || errorCode['default'];
- if (code === 200) {
- resolve(result);
- } else if (code === 401) {
- uni.hideLoading();
- // 跳转到登录页面
- uni.$u.route({
- type: 'reLaunch',
- url: '/pages/login/login',
- params: {
- redirect: getCurrentPage()?.route || '',
- },
- });
- reject('无效的会话,或者会话已过期,请重新登录。');
- } else if (code === 500) {
- uni.showToast({
- title: msg,
- icon: 'none',
- });
- reject('500');
- } else if (code !== 200) {
- uni.showToast({
- title: msg,
- icon: 'none',
- });
- reject(code);
- }
- },
- fail: (error) => {
- console.log(error);
- let message = '上传失败';
- if (error.errMsg) {
- if (error.errMsg.includes('timeout')) {
- message = '系统接口请求超时';
- } else if (error.errMsg.includes('fail')) {
- message = '网络连接异常';
- }
- }
- uni.showToast({
- title: message,
- icon: 'none',
- });
- reject(error);
- },
- });
- });
- };
- /**
- * 获取文件扩展名
- * @param {string} url - 文件 URL
- * @param {object} [result] - 响应结果对象
- * @param {object} [result.header] - 响应头
- * @returns {string|null} 文件扩展名(不带点),找不到则返回 null
- */
- const getFileType = (url: string, result?: { header?: Record<string, any> }): string | null => {
- // 1. 首先尝试从 URL 获取扩展名
- if (url) {
- // 获取 URL 中最后一个斜杠后的文件名
- const filenameFromUrl = url.split('/').pop();
- // 提取扩展名(处理可能存在的查询参数)
- const urlExt = filenameFromUrl?.includes('.') ? filenameFromUrl.split('.').pop()?.split(/[?#]/)[0] : null;
- if (urlExt) return urlExt.toLowerCase() || 'pdf';
- }
- // 2. 如果 URL 中没有扩展名,尝试从 Content-Disposition 头获取
- if (result?.header?.['content-disposition']) {
- try {
- const disposition = result.header['content-disposition'];
- // 匹配 filename="file.ext" 或 filename*=UTF-8''file.ext 格式
- const filenameMatch = disposition.match(/filename\*?=(?:UTF-8''|")?([^;"\n]*)/i);
- if (filenameMatch && filenameMatch[1]) {
- const filename = filenameMatch[1].replace(/['"]/g, '');
- if (filename.includes('.')) {
- const ext = filename.split('.').pop()?.split(/[?#]/)[0];
- return ext?.toLowerCase() || 'pdf';
- }
- }
- } catch (e) {
- console.warn('解析 Content-Disposition 失败:', e);
- }
- }
- // 3. 都找不到则返回 pdf 作为默认值
- return 'pdf';
- };
- // 导出数据函数(按照 handleDownload 规范完善)
- export const exportDataFn = (config: { url: string; fileName?: string; params?: Record<string, any>; timeout?: number }, showTitle?: string): Promise<void> =>
- new Promise((resolve, reject) => {
- // 判断是否为完整 URL(以 http://或 https://开头)
- const isFullUrl = config.url.startsWith('http://') || config.url.startsWith('https://');
- // 获取基础 URL 并拼接完整路径
- const baseUrl = isFullUrl ? '' : import.meta.env.VITE_API_BASE_URL || config.url.split('/').slice(0, 3).join('/');
- const downloadUrl = baseUrl + config.url;
- // 获取 token
- const token = useInfoStore().token;
- // 设置请求头
- const header = {
- 'Content-Type': 'application/json',
- Authorization: `Bearer ${token}`,
- xid: appid,
- clientId: clientId,
- };
- uni.showLoading({
- title: showTitle || '正在导出数据...',
- mask: true,
- });
- uni.downloadFile({
- url: downloadUrl,
- header: header,
- success: (res) => {
- uni.hideLoading();
- if (res.statusCode === 200) {
- // 直接打开文件
- uni.openDocument({
- filePath: res.tempFilePath,
- showMenu: true,
- fileType: getFileType(config.fileName || config.url, res as any) as any,
- success: () => {
- resolve();
- },
- fail: (err) => {
- console.log('打开文档失败:', err);
- uni.showToast({
- title: '打开文件失败',
- icon: 'none',
- });
- reject(err);
- },
- });
- } else {
- uni.showToast({
- title: '下载失败',
- icon: 'none',
- });
- reject(res);
- }
- },
- fail: () => {
- uni.hideLoading();
- uni.showToast({
- title: '下载失败',
- icon: 'none',
- });
- reject();
- },
- });
- });
- export default upload;
|