feat: 更新文章功能和相关依赖
- 新增文章详情页面,支持根据文章 ID 加载和展示文章内容 - 添加文章卡片组件,展示推荐文章的标题、封面和阅读量 - 更新文章服务,支持获取文章列表和根据 ID 获取文章详情 - 集成腾讯云 COS SDK,支持文件上传功能 - 优化打卡功能,支持按日期加载和展示打卡记录 - 更新相关依赖,确保项目兼容性和功能完整性 - 调整样式以适应新功能的展示和交互
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { buildCosKey, buildPublicUrl } from '@/constants/Cos';
|
||||
import { uploadWithRetry } from '@/services/cos';
|
||||
import { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { Platform } from 'react-native';
|
||||
|
||||
export type UseCosUploadOptions = {
|
||||
prefix?: string;
|
||||
@@ -31,37 +32,44 @@ export function useCosUpload(defaultOptions?: UseCosUploadOptions) {
|
||||
setProgress(0);
|
||||
setUploading(true);
|
||||
try {
|
||||
let body: any = null;
|
||||
// 1) 直接可用类型:Blob 或 string
|
||||
if (typeof file === 'string') {
|
||||
body = file;
|
||||
} else if (typeof Blob !== 'undefined' && file instanceof Blob) {
|
||||
body = file;
|
||||
} else if ((file as any)?.blob && (typeof Blob === 'undefined' || (file as any).blob instanceof Blob || (file as any).blob?._data)) {
|
||||
// 2) 已提供 blob 字段
|
||||
body = (file as any).blob;
|
||||
} else if ((file as any)?.buffer) {
|
||||
// 3) ArrayBuffer/TypedArray -> Blob
|
||||
const buffer = (file as any).buffer;
|
||||
body = new Blob([buffer], { type: (file as any)?.type || finalOptions.contentType || 'application/octet-stream' });
|
||||
} else if ((file as any)?.uri) {
|
||||
// 4) Expo ImagePicker/文件:必须先转 Blob
|
||||
const resp = await fetch((file as any).uri);
|
||||
body = await resp.blob();
|
||||
} else {
|
||||
// 兜底:尝试直接作为字符串,否则抛错
|
||||
if (file && (typeof file === 'object')) {
|
||||
throw new Error('无效的上传体:请提供 Blob/String,或包含 uri 的对象');
|
||||
let res: any;
|
||||
if (Platform.OS === 'web') {
|
||||
// Web:使用 Blob 走 cos-js-sdk-v5 分支
|
||||
let body: any = null;
|
||||
if (typeof file === 'string') {
|
||||
// 允许直接传 Base64/DataURL 字符串
|
||||
body = file;
|
||||
} else if ((file as any)?.blob) {
|
||||
body = (file as any).blob;
|
||||
} else if ((file as any)?.uri) {
|
||||
const resp = await fetch((file as any).uri);
|
||||
body = await resp.blob();
|
||||
} else if (typeof Blob !== 'undefined' && file instanceof Blob) {
|
||||
body = file;
|
||||
} else {
|
||||
throw new Error('无效的文件:请提供 uri 或 Blob');
|
||||
}
|
||||
body = file;
|
||||
res = await uploadWithRetry({
|
||||
key,
|
||||
body,
|
||||
contentType: finalOptions.contentType || (file as any)?.type,
|
||||
signal: controller.signal,
|
||||
onProgress: ({ percent }: { percent: number }) => setProgress(percent),
|
||||
} as any);
|
||||
} else {
|
||||
// 原生:直接传本地路径
|
||||
const srcUri = (file as any)?.uri || (typeof file === 'string' ? file : undefined);
|
||||
if (!srcUri || typeof srcUri !== 'string') {
|
||||
throw new Error('请提供包含 uri 的对象,或传入本地文件路径字符串');
|
||||
}
|
||||
res = await uploadWithRetry({
|
||||
key,
|
||||
srcUri,
|
||||
contentType: finalOptions.contentType || (file as any)?.type,
|
||||
signal: controller.signal,
|
||||
onProgress: ({ percent }: { percent: number }) => setProgress(percent),
|
||||
} as any);
|
||||
}
|
||||
const res = await uploadWithRetry({
|
||||
key,
|
||||
body,
|
||||
contentType: finalOptions.contentType || (file as any)?.type,
|
||||
signal: controller.signal,
|
||||
onProgress: ({ percent }) => setProgress(percent),
|
||||
});
|
||||
const url = (res as any).publicUrl || buildPublicUrl(res.key);
|
||||
return { key: res.key, url };
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user