Files
template-10579/src/api/system/file/index.ts
赵忠林 372275ef44 feat(credit): 新增我的订单查询页面并优化文件上传功能
- 新增 credit/my-order/index 页面用于订单进度查询
- 在 app.config.ts 中注册新的订单查询页面路由
- 修改文件上传逻辑,统一使用 uploadFile 方法替代手动选择图片流程
- 重构 uploadFileByPath 函数,增强错误处理和响应解析逻辑
- 修复STS token过期判断条件,确保及时刷新临时凭证
- 实现订单列表的搜索、筛选、排序和分页加载功能
- 添加日期范围选择器和回款状态过滤功能
- 优化图片上传用户体验,与用户认证页面保持一致
2026-03-17 22:16:41 +08:00

155 lines
4.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import request from '@/utils/request';
import Taro from '@tarojs/taro'
import dayjs from 'dayjs';
import crypto from 'crypto-js';
import {Base64} from 'js-base64';
import {FileRecord} from "@/api/system/file/model";
import { TenantId } from "@/config/app";
export async function uploadOssByPath(filePath: string) {
return new Promise(async (resolve) => {
const date = new Date();
date.setMinutes(date.getMinutes() + 1);
const policyText = {
expiration: date.toISOString(), // 设置policy过期时间。
conditions: [
// 限制上传大小。
["content-length-range", 0, 1024 * 1024 * 1024],
],
};
let sts = Taro.getStorageSync('sts');
let stsExpired = Taro.getStorageSync('stsExpiredAt');
if (!sts || (stsExpired && dayjs().isAfter(dayjs(stsExpired)))) {
// @ts-ignore
const {data: {data: {credentials}}} = await request.get(`https://gle-server.websoft.top/api/oss/getSTSToken`)
Taro.setStorageSync('sts', credentials)
Taro.setStorageSync('stsExpiredAt', credentials.expiration)
sts = credentials
}
console.log(sts)
const [filename, ext] = filePath.split('.')
const key = `headers/${filename + (Math.random() * 100000)}.${ext}`
const policy = Base64.encode(JSON.stringify(policyText))
const signature = computeSignature(sts.accessKeySecret, policy)
Taro.uploadFile({
url: 'https://oss.wsdns.cn',
name: 'file',
filePath,
formData: {
key,
policy,
OSSAccessKeyId: sts.accessKeyId,
signature,
'x-oss-security-token': sts.securityToken
},
success: () => {
resolve(`https://oss.wsdns.cn/${key}`)
}
})
})
}
const computeSignature = (accessKeySecret: string, canonicalString: string): string => {
return crypto.enc.Base64.stringify(crypto.HmacSHA1(canonicalString, accessKeySecret));
}
/**
* 上传阿里云OSS
*/
export async function uploadFileByPath(filePath: string) {
const parseResponseToRecord = (res: any): FileRecord => {
const statusCode = Number(res?.statusCode)
if (Number.isFinite(statusCode) && statusCode !== 200) {
throw new Error(`上传失败HTTP ${statusCode}`)
}
const raw = res?.data
if (raw === null || raw === undefined || raw === '') {
throw new Error('上传失败:响应为空')
}
let data: any
if (typeof raw === 'string') {
const cleaned = raw.replace(/^\uFEFF/, '').trim()
try {
data = JSON.parse(cleaned)
} catch (_e) {
throw new Error('上传失败:响应格式错误')
}
} else {
data = raw
}
if (data?.code === 0) return data.data as FileRecord
const codeHint = data?.code !== undefined && data?.code !== null ? `code=${String(data.code)}` : ''
let msg = String(data?.message || data?.msg || data?.error || data?.errMsg || `上传失败${codeHint}`)
try {
msg = decodeURIComponent(escape(msg))
} catch (_e) {
// ignore
}
throw new Error(msg || '上传失败')
}
const tenantIdInStorage = Taro.getStorageSync('TenantId')
const tenantId =
tenantIdInStorage && String(tenantIdInStorage) === String(TenantId)
? tenantIdInStorage
: TenantId
const header: Record<string, string> = {
'content-type': 'application/json',
TenantId: String(tenantId)
}
return new Promise((resolve: (result: FileRecord) => void, reject) => {
if (!filePath) {
reject(new Error('缺少 filePath'))
return
}
Taro.uploadFile({
url: 'https://server.websoft.top/api/oss/upload',
filePath,
name: 'file',
header,
success: (res) => {
try {
resolve(parseResponseToRecord(res))
} catch (e) {
reject(e)
}
},
fail: (err) => {
const msg = String((err as any)?.errMsg || (err as any)?.message || '上传请求失败')
reject(new Error(msg))
}
})
})
}
export async function uploadFile() {
return new Promise(async (resolve: (result: FileRecord) => void, reject) => {
Taro.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: async (res) => {
const tempFilePath = res.tempFilePaths[0];
try {
const record = await uploadFileByPath(tempFilePath)
resolve(record)
} catch (e) {
reject(e)
}
},
fail: (err) => {
console.log('选择图片失败', err);
reject(new Error('选择图片失败'))
}
});
})
}