账单与支付

This commit is contained in:
liu
2026-08-14 23:48:15 +08:00
parent 4138164bd8
commit 3bd26acbb9
32 changed files with 2052 additions and 475 deletions
+10 -3
View File
@@ -40,11 +40,18 @@ export function formatTime(value?: string): string {
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`
}
/**
* 解析服务器文件地址(收款码、汇款凭证等):绝对地址直接用,相对路径拼接服务器域名
*/
export function resolveFileUrl(url?: string): string {
if (!url) return ''
if (/^https?:\/\//i.test(url)) return url
return `${SERVER_ORIGIN}${url.startsWith('/') ? '' : '/'}${url}`
}
/**
* 解析头像地址:绝对地址直接用,相对路径拼接服务器域名
*/
export function resolveAvatarUrl(avatar?: string): string {
if (!avatar) return ''
if (/^https?:\/\//i.test(avatar)) return avatar
return `${SERVER_ORIGIN}${avatar.startsWith('/') ? '' : '/'}${avatar}`
return resolveFileUrl(avatar)
}
+58
View File
@@ -0,0 +1,58 @@
import Taro from '@tarojs/taro'
import { BASE_URL, getToken } from '@/utils/request'
import type { ApiResponse } from '@/types/api'
/** 上传结果(/mini/upload 返回) */
export interface UploadedFile {
/** 文件 ID(提交业务接口时使用的 voucher_ids 元素) */
id: number
/** 预览地址 */
url: string
}
/**
* 上传单张图片到 /mini/upload(凭证等场景,≤5MB
* uploadFile 不受 request 层封装(multipart),此处自行解析统一响应结构并 toast
*/
export function uploadImage(filePath: string): Promise<UploadedFile> {
const token = getToken()
return new Promise((resolve, reject) => {
Taro.uploadFile({
url: `${BASE_URL}/mini/upload`,
filePath,
name: 'file',
header: token ? { Authorization: `Bearer ${token}` } : {},
success(res) {
let body: ApiResponse<UploadedFile> | null = null
try {
body = JSON.parse(res.data)
} catch {
// 非 JSON 响应(网关错误页等)
}
if (res.statusCode >= 200 && res.statusCode < 300 && body?.success) {
resolve(body.data)
return
}
const msg = body?.msg || `上传失败(${res.statusCode}`
Taro.showToast({ title: msg, icon: 'none' })
reject(new Error(msg))
},
fail(err) {
Taro.showToast({ title: '上传失败,请检查网络', icon: 'none' })
reject(err)
},
})
})
}
/**
* 选择并上传图片:一次选择 count 张,逐张上传,全部成功才返回
*/
export async function chooseAndUploadImages(count: number): Promise<UploadedFile[]> {
const res = await Taro.chooseImage({ count, sizeType: ['compressed'] })
const files: UploadedFile[] = []
for (const path of res.tempFilePaths) {
files.push(await uploadImage(path))
}
return files
}