- 新增 credit/my-order/index 页面用于订单进度查询 - 在 app.config.ts 中注册新的订单查询页面路由 - 修改文件上传逻辑,统一使用 uploadFile 方法替代手动选择图片流程 - 重构 uploadFileByPath 函数,增强错误处理和响应解析逻辑 - 修复STS token过期判断条件,确保及时刷新临时凭证 - 实现订单列表的搜索、筛选、排序和分页加载功能 - 添加日期范围选择器和回款状态过滤功能 - 优化图片上传用户体验,与用户认证页面保持一致
155 lines
4.5 KiB
TypeScript
155 lines
4.5 KiB
TypeScript
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('选择图片失败'))
|
||
}
|
||
});
|
||
})
|
||
|
||
}
|