// API服务工具文件 // 统一访问 crmeb-front 项目,基地址来自 config/app.js import { domain } from '@/config/app.js' const API_BASE_URL = domain /** * 通用请求方法 * @param {string} url 请求地址 * @param {object} options 请求配置 * @returns {Promise} 请求结果 */ function request(url, options = {}) { return new Promise((resolve, reject) => { uni.request({ url: `${API_BASE_URL}${url}`, method: options.method || 'GET', data: options.data || {}, header: { 'Content-Type': 'application/json', ...options.header }, success: (res) => { if (res.statusCode === 200) { resolve(res.data) } else { reject(new Error(`请求失败: ${res.statusCode}`)) } }, fail: (error) => { reject(error) } }) }) } /** * 根据ID获取文章详情 * @param {string|number} id 文章ID * @returns {Promise} 文章详情数据 */ function getArticleById(id) { return request(`/api/front/article-models/${id}`) } /** * 获取文章列表 * @param {object} params 查询参数 * @param {number} params.page 页码,默认1 * @param {number} params.size 每页数量,默认10 * @returns {Promise} 文章列表数据 */ function getArticleList(params = { page: 1, size: 10 }) { // 构建查询字符串(兼容小程序环境) const queryString = Object.keys(params) .filter(key => params[key] !== undefined && params[key] !== null) .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`) .join('&') const url = queryString ? `/api/front/article-models?${queryString}` : '/api/front/article-models' return request(url, { method: 'GET' }) } /** * 根据条件查询文章列表 * @param {object} params 查询参数 * @param {number} params.statusTask 任务状态(可选) * @param {string} params.uid 用户ID(可选) * @param {string} params.tags 标签(可选) * @param {string} params.type 文章类型(可选) * @param {number} params.page 页码,默认1 * @param {number} params.size 每页数量,默认10 * @returns {Promise} 符合条件的文章列表数据 */ function searchArticles(params = { page: 1, size: 10 }) { // 构建查询字符串(兼容小程序环境) const queryString = Object.keys(params) .filter(key => params[key] !== undefined && params[key] !== null) .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`) .join('&') const url = queryString ? `/api/front/article-models/search?${queryString}` : '/api/front/article-models/search' return request(url, { method: 'GET' }) } /** * 创建文生视频任务 * @param {object} params 创建参数 * @param {string} params.prompt 文本描述 * @param {Array} params.image_urls 图片URL数组(可选) * @param {string} params.aspect_ratio 视频比例,如 'portrait' 或 '16:9' * @param {number} params.n_frames 帧数,默认5 * @param {string} params.size 视频尺寸,默认 'standard' * @param {boolean} params.remove_watermark 是否移除水印,默认true * @returns {Promise} 任务创建结果 */ function createTextToVideoTask(params) { const requestBody = { model: "sora-2-text-to-video", title: params.prompt, task_id: "", nickname: params.nickname || "", uid: params.uid || "", input: { prompt: params.prompt, image_urls: params.image_urls || [], aspect_ratio: params.aspect_ratio || "portrait", n_frames: params.n_frames || 5, size: params.size || "standard", remove_watermark: params.remove_watermark !== false } } return request('/api/front/kieai/text-to-video', { method: 'POST', data: requestBody }) } /** * 创建图生视频任务 * @param {object} params 创建参数 * @param {string} params.imageUrl 图片URL * @param {string} params.prompt 文本描述(可选) * @param {string} params.aspect_ratio 视频比例,如 'portrait' 或 '16:9' * @param {number} params.n_frames 帧数,默认5 * @param {string} params.size 视频尺寸,默认 'standard' * @param {boolean} params.remove_watermark 是否移除水印,默认true * @returns {Promise} 任务创建结果 */ function createImageToVideoTask(params) { const requestBody = { model: "sora-2-image-to-video", title: params.prompt || "根据图片生成视频", task_id: "", nickname: params.nickname || "", uid: params.uid || "", input: { prompt: params.prompt || "根据图片生成视频", image_urls: [params.imageUrl], aspect_ratio: params.aspect_ratio || "portrait", n_frames: params.n_frames || 5, size: params.size || "standard", remove_watermark: params.remove_watermark !== false } } return request('/api/front/kieai/image-to-video', { method: 'POST', data: requestBody }) } /** * 创建图片编辑任务 * @param {object} params 创建参数 * @param {string} params.prompt 编辑描述,如"改一下"、"去掉背景" * @param {Array} params.image_urls 图片URL数组 * @param {string} params.output_format 输出格式,默认'png' * @param {string} params.image_size 图片尺寸,默认'2:3' * @param {string} params.title 任务标题,默认使用prompt * @param {string} params.task_id 任务ID(可选) * @returns {Promise} 任务创建结果 */ function createImageEditTask(params) { const requestBody = { model: "google/nano-banana-edit", title: params.title || params.prompt || "图片编辑", task_id: params.task_id || "", nickname: params.nickname || "", uid: params.uid || "", input: { prompt: params.prompt, image_urls: params.image_urls || [], output_format: params.output_format || "png", image_size: params.image_size || "2:3", aspect_ratio: params.aspect_ratio || "9:16", resolution: params.resolution || "2K", } } return request('/api/front/kieai/image-edit', { method: 'POST', data: requestBody }) } /** * 创建图片编辑任务 * @param {object} params 创建参数 * @param {string} params.prompt 编辑描述,如"改一下"、"去掉背景" * @param {Array} params.image_urls 图片URL数组 * @param {string} params.output_format 输出格式,默认'png' * @param {string} params.aspect_ratio 图片尺寸,默认'2:3' * @param {string} params.title 任务标题,默认使用prompt * @param {string} params.task_id 任务ID(可选) * @returns {Promise} 任务创建结果 */ function createImageEditTaskPro(params) { const requestBody = { model: "nano-banana-pro", title: params.title || params.prompt || "图片编辑", task_id: params.task_id || "", nickname: params.nickname || "", uid: params.uid || "", input: { prompt: params.prompt, image_urls: params.image_urls || [], output_format: params.output_format || "png", aspect_ratio: params.aspect_ratio || "2:3", resolution: params.resolution || "2K" } } return request('/api/front/kieai/image-edit', { method: 'POST', data: requestBody }) } /** * 用户上传文件 * @param {string} filePath 文件路径 * @param {object} options 上传配置 * @param {string} options.model 模块类型,默认'user' * @param {string} options.pid 分类ID,默认'0' * @returns {Promise} 上传结果 */ function uploadFile(filePath, options = {}) { return new Promise((resolve, reject) => { uni.uploadFile({ url: `${API_BASE_URL}/api/front/upload/imageOuter`, filePath: filePath, name: 'multipart', formData: { model: options.model || 'user', pid: options.pid || '0' }, success: (res) => { try { let data = res.data if (typeof data === 'string') { data = JSON.parse(data) } if (!data || typeof data !== 'object') { throw new Error('响应格式异常') } if (data.code === 200) { // 拼接完整的图片URL const fullUrl = data.data.url.startsWith('http') ? data.data.url : `https://uthink2025.oss-cn-shanghai.aliyuncs.com/${data.data.url}` resolve({ ...data, data: { ...data.data, fullUrl: fullUrl } }) } else { reject(new Error(data.message || '上传失败')) } } catch (error) { const raw = typeof res.data === 'string' ? res.data.slice(0, 300) : String(res.data || '') const msg = error.message || '响应数据解析失败' reject(new Error(msg + (raw ? ' body: ' + raw : ''))) } }, fail: (error) => { reject(new Error('上传请求失败')) } }) }) } /** * 创建语音识别任务 * @param {object} params 请求参数 * @param {string} params.url 音频文件URL * @param {string} params.engineModelType 引擎模型类型,默认16k_zh * @param {number} params.channelNum 声道数,默认1 * @param {number} params.resTextFormat 结果文本格式,默认0 * @param {number} params.sourceType 源类型,默认0 * @returns {Promise} 识别任务信息 */ function createAsrTask(params) { const defaultParams = { engineModelType: '16k_zh', channelNum: 1, resTextFormat: 0, sourceType: 0, filterDirty: false, filterModal: false, convertNumMode: false, wordInfo: false } return request('/api/front/tencent/asr/create-task', { method: 'POST', data: { ...defaultParams, ...params } }) } /** * 查询语音识别任务状态 * @param {string|number} taskId 任务ID * @returns {Promise} 任务状态和识别结果 */ function queryAsrStatus(taskId) { return request(`/api/front/tencent/asr/query-status/${taskId}`) } // ==================== 扣子Coze API ==================== /** * Coze - 发起对话 (Chat) * @param {object} data 请求参数 * @param {string} data.bot_id 机器人ID * @param {string} data.user_id 用户ID * @param {Array} data.additional_messages 附加消息列表 * @param {boolean} data.stream 是否流式返回 * @param {boolean} data.auto_save_history 是否自动保存历史 * @param {object} data.meta_data 元数据 * @returns {Promise} 对话响应 */ /** * KieAI Gemini 对话(POST /api/front/kieai/gemini/chat) * 文本对话请求体: { messages: [{ role: 'user', content: 用户输入 }], stream: false } * @param {object} data 请求体 * @param {Array} data.messages 消息列表 [{ role: 'user'|'assistant'|'system', content: string|Array }] * @param {boolean} data.stream 是否流式,默认 false * @returns {Promise} 响应 data 为 Gemini 格式 { choices: [{ message: { content } }] },回复取 data.choices[0].message.content */ function kieaiGeminiChat(data) { return request('/api/front/kieai/gemini/chat', { method: 'POST', data: data }) } function cozeChat(data) { return request('/api/front/coze/chat', { method: 'POST', data: data }) } /** * Coze - 检索对话详情 (Retrieve Chat) * @param {object} params 请求参数 * @param {string} params.conversationId 会话ID * @param {string} params.chatId 对话ID * @returns {Promise} 对话详情 */ function cozeRetrieveChat(params) { return request('/api/front/coze/chat/retrieve', { method: 'POST', data: params }) } /** * Coze - 查看对话消息详情 (List Messages) * @param {object} params 请求参数 * @param {string} params.conversationId 会话ID * @param {string} params.chatId 对话ID * @returns {Promise} 消息列表 */ function cozeMessageList(params) { return request('/api/front/coze/chat/messages/list', { method: 'POST', data: params }) } /** * Coze - 执行工作流 (Run Workflow) * @param {object} data 请求参数 * @param {string} data.workflowId 工作流ID * @param {object} data.parameters 工作流参数 * @param {boolean} data.isAsync 是否异步 * @returns {Promise} 执行结果 */ function cozeWorkflowRun(data) { return request('/api/front/coze/workflow/run', { method: 'POST', data: data }) } /** * Coze - 执行工作流 (Run Workflow Stream) * @param {object} data 请求参数 * @param {string} data.workflowId 工作流ID * @param {object} data.parameters 工作流参数 * @returns {Promise} 执行结果 */ function cozeWorkflowStream(data) { return request('/api/front/coze/workflow/stream', { method: 'POST', data: data }) } /** * Coze - 恢复工作流 (Resume Workflow) * @param {object} data 请求参数 * @param {string} data.workflow_id 工作流ID * @param {string} data.event_id 事件ID * @param {string} data.resume_data 恢复数据 * @param {number} data.resume_type 恢复类型 * @returns {Promise} 执行结果 */ function cozeWorkflowResume(data) { return request('/api/front/coze/workflow/resume', { method: 'POST', data: data }) } /** * Coze - 上传文件 (Upload File) * @param {string} filePath 文件路径 * @returns {Promise} 上传结果 */ function cozeUploadFile(filePath) { return new Promise((resolve, reject) => { uni.uploadFile({ url: `${API_BASE_URL}/api/front/coze/file/upload`, filePath: filePath, name: 'file', success: (res) => { if (res.statusCode === 200) { try { const data = JSON.parse(res.data) resolve(data) } catch (e) { reject(new Error('响应解析失败')) } } else { reject(new Error(`上传失败: ${res.statusCode}`)) } }, fail: (err) => { reject(err) } }) }) } export default { request, getArticleById, getArticleList, searchArticles, createTextToVideoTask, createImageToVideoTask, createImageEditTask, createImageEditTaskPro, uploadFile, createAsrTask, queryAsrStatus, kieaiGeminiChat, // Coze API cozeChat, cozeRetrieveChat, cozeMessageList, cozeWorkflowRun, cozeWorkflowStream, cozeWorkflowResume, cozeUploadFile }