Merge branch 'yongpxu-dev' into yongpxu-master

# Conflicts:
#	nkebao/src/App.tsx   resolved by yongpxu-dev version
This commit is contained in:
2025-07-17 08:54:04 +08:00
19 changed files with 2050 additions and 1615 deletions

View File

@@ -1,4 +1,4 @@
import { get, del } from './request';
import { get, del, post,put } from './request';
import type { ApiResponse } from '@/types/common';
// 服务器返回的场景数据类型
@@ -50,12 +50,72 @@ export interface Task {
trend: { date: string; customers: number }[];
}
// 消息内容类型
export interface MessageContent {
id: string;
type: string; // "text" | "image" | "video" | "file" | "miniprogram" | "link" | "group" 等
content?: string;
intervalUnit?: "seconds" | "minutes";
sendInterval?: number;
// 其他可选字段
[key: string]: any;
}
// 每天的消息计划
export interface MessagePlan {
day: number;
messages: MessageContent[];
}
// 海报类型
export interface Poster {
id: string;
name: string;
type: string;
preview: string;
}
// 标签类型
export interface Tag {
id: string;
name: string;
[key: string]: any;
}
// textUrl类型
export interface TextUrl {
apiKey: string;
originalString?: string;
sign?: string;
fullUrl: string;
}
// 计划详情类型
export interface PlanDetail {
id: number;
name: string;
scenario: number;
scenarioTags: Tag[];
customTags: Tag[];
posters: Poster[];
device: string[];
enabled: boolean;
addInterval: number;
remarkFormat: string;
endTime: string;
greeting: string;
startTime: string;
remarkType: string;
addFriendInterval: number;
messagePlans: MessagePlan[];
sceneId: number | string;
userId: number;
companyId: number;
status: number;
apiKey: string;
textUrl: {
fullUrl: string;
};
wxMinAppSrc?: any;
textUrl: TextUrl;
[key: string]: any;
}
/**
@@ -239,4 +299,13 @@ export const transformSceneItem = (item: SceneItem): Channel => {
};
};
export const getPlanScenes = () => get<any>('/v1/plan/scenes');
export const getPlanScenes = () => get<any>('/v1/plan/scenes');
export async function createScenarioPlan(data: any) {
return post('/v1/plan/create', data);
}
// 编辑计划
export async function updateScenarioPlan(planId: number | string, data: any) {
return await put(`/v1/plan/update?planId=${planId}`, data);
}

View File

@@ -1,5 +1,6 @@
import { authApi } from './auth';
import { get, post, put, del } from './request';
import type { ApiResponse, PaginatedResponse } from '@/types/common';
// 设置token到localStorage
export const setToken = (token: string) => {
if (typeof window !== 'undefined') {
@@ -170,25 +171,24 @@ export const requestCancelManager = new RequestCancelManager();
* @returns {Promise<string>} - 上传成功后返回文件url
*/
export async function uploadFile(file: File, uploadUrl: string = '/v1/attachment/upload'): Promise<string> {
const formData = new FormData();
formData.append('file', file);
const token = typeof window !== 'undefined' ? localStorage.getItem('token') : '';
const headers: Record<string, string> = {};
if (token) headers['Authorization'] = `Bearer ${token}`;
try {
const response = await fetch(uploadUrl, {
method: 'POST',
headers,
body: formData,
// 创建 FormData 对象用于文件上传
const formData = new FormData();
formData.append('file', file);
// 使用 post 方法上传文件,设置正确的 Content-Type
const res = await post(uploadUrl, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
const res = await response.json();
if (res?.url) {
return res.url;
}
if (res?.data?.url) {
// 检查响应结果
if (res?.code === 200 && res?.data?.url) {
return res.data.url;
} else {
throw new Error(res?.msg || '文件上传失败');
}
throw new Error(res?.msg || '文件上传失败');
} catch (e: any) {
throw new Error(e?.message || '文件上传失败');
}