From 674d0b9308278856e9ba26aeb2e8cf80d0653477 Mon Sep 17 00:00:00 2001 From: zoujing Date: Sun, 5 Apr 2026 16:48:11 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8E=A5=E5=8F=A3=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/AigcCreateGeneratorPhotoTaskApi.ts | 16 ++++++++ src/api/UploadFile.ts | 44 +++++++++++++++++++++ src/api/index.ts | 4 +- src/common/ajax.js | 5 +-- src/constant/token.ts | 7 ++++ src/views/history/index.vue | 3 ++ src/views/home/index.vue | 46 +++++++++++++++++++++- src/views/prepicture/index.vue | 19 ++++++++- 8 files changed, 137 insertions(+), 7 deletions(-) create mode 100644 src/api/AigcCreateGeneratorPhotoTaskApi.ts create mode 100644 src/api/UploadFile.ts create mode 100644 src/constant/token.ts diff --git a/src/api/AigcCreateGeneratorPhotoTaskApi.ts b/src/api/AigcCreateGeneratorPhotoTaskApi.ts new file mode 100644 index 0000000..f1c8e09 --- /dev/null +++ b/src/api/AigcCreateGeneratorPhotoTaskApi.ts @@ -0,0 +1,16 @@ +/* eslint-disable */ +// @ts-ignore +import request from '@common/ajax'; +import type { Response } from './types'; + +export interface CreateGeneratorPhotoTaskRequest { + photoUrlList: string[]; +} + +export const createGeneratorPhotoTask = (params: CreateGeneratorPhotoTaskRequest) => { + return request>({ + url: '/aigc/createGeneratorPhotoTask', + method: 'post', + params, + }); +}; \ No newline at end of file diff --git a/src/api/UploadFile.ts b/src/api/UploadFile.ts new file mode 100644 index 0000000..66a70be --- /dev/null +++ b/src/api/UploadFile.ts @@ -0,0 +1,44 @@ +import request from "@/common/ajax"; +import { getAccessToken } from "@/constant/token"; +// @ts-ignore +const { VITE_BASE_API, VITE_ENV } = import.meta.env + +async function toFileObject(input: string | File | Blob): Promise { + if (input instanceof File) return input; + if (input instanceof Blob) return new File([input], "file.jpg", { type: input.type || "image/jpeg" }); + + const res = await fetch(input); + const blob = await res.blob(); + try { + const urlObj = new URL(input); + const segments = urlObj.pathname.split("/"); + const name = segments.pop() || "file.jpg"; + return new File([blob], name, { type: blob.type || "image/jpeg" }); + } catch (e) { + return new File([blob], "file.jpg", { type: blob.type || "image/jpeg" }); + } +} + +export const updateImageFile = async (file: string | File | Blob) => { + const baseUrl = VITE_ENV === 'development' ? '/ingress/agent' : VITE_BASE_API + const url = baseUrl + "/hotBizCommon/upload"; + const token = getAccessToken(); + + try { + const fileObj = await toFileObject(file); + const form = new FormData(); + form.append("file", fileObj); + + const resp = await request.post(url, form, { + headers: { + "Content-Type": "multipart/form-data", + Authorization: `Bearer ${token}`, + }, + }); + + return resp; + } catch (err) { + console.error("上传图片失败:", err); + throw err; + } +}; diff --git a/src/api/index.ts b/src/api/index.ts index b2d4b88..2bd08a2 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -3,4 +3,6 @@ export * from './types'; export * from './AigcSceneListApi'; -export * from './AigcGeneratorPhotoTaskListApi'; \ No newline at end of file +export * from './AigcGeneratorPhotoTaskListApi'; +export * from './AigcCreateGeneratorPhotoTaskApi'; +export * from './UploadFile'; diff --git a/src/common/ajax.js b/src/common/ajax.js index 615b208..fb5f56c 100644 --- a/src/common/ajax.js +++ b/src/common/ajax.js @@ -1,6 +1,6 @@ import axios from 'axios' import { tansParams } from '@utils/tansParams' -import { Session } from '@utils/storage' +import { getAccessToken } from '@/constant/token' // 获取.env中的服务地址 const { VITE_BASE_API, VITE_ENV } = import.meta.env @@ -18,8 +18,7 @@ const instance = axios.create({ // 添加拦截器 instance.interceptors.request.use((config) => { - // const token = Session.getToken() - const token = 'H7rzcCtsvPqwc0ecDnBT9mlhOqHsWDyS6nXkRjnd1oAgOQqlEhsCy4OZPQ8YyVBj57pmNpwSXJYcd6Ox4YB-W1pHr4aTM9_d6nYJ3OrbRB9f0J7kP9FbbviN609nGO0m' + const token = getAccessToken(); config.headers['Authorization'] = `Bearer ${token}` // get请求映射params参数 diff --git a/src/constant/token.ts b/src/constant/token.ts new file mode 100644 index 0000000..3217151 --- /dev/null +++ b/src/constant/token.ts @@ -0,0 +1,7 @@ +import { Session } from '@/utils/storage' + + export const getAccessToken = () => { + const token = Session.getToken() + // const token = 'H7rzcCtsvPqwc0ecDnBT9mlhOqHsWDyS6nXkRjnd1oAgOQqlEhsCy4OZPQ8YyVBj57pmNpwSXJYcd6Ox4YB-W1pHr4aTM9_d6nYJ3OrbRB9f0J7kP9FbbviN609nGO0m' + return token; +} \ No newline at end of file diff --git a/src/views/history/index.vue b/src/views/history/index.vue index ba560ee..c4f2f53 100644 --- a/src/views/history/index.vue +++ b/src/views/history/index.vue @@ -68,6 +68,7 @@ import { useRouter } from 'vue-router'; import TopNavBar from '../components/TopNavBar.vue'; // @ts-ignore import { generatorPhotoTaskList } from '@api'; +import { closeToast, showLoadingToast } from 'vant'; interface TaskItem { name: string @@ -92,7 +93,9 @@ const lookPicture = (item: TaskItem) => { } const getTaskList = () => { + showLoadingToast('加载中...'); generatorPhotoTaskList({ pageNum: 1, pageSize: 20 }).then(res => { + closeToast(); // 关闭加载提示 if (res.code === 0) { const data = res.data || []; list.splice(0, list.length, ...data.map(item => { diff --git a/src/views/home/index.vue b/src/views/home/index.vue index 782aa8f..4ff3c6c 100644 --- a/src/views/home/index.vue +++ b/src/views/home/index.vue @@ -58,6 +58,9 @@ import PhotoGuide from '../components/PhotoGuide.vue'; import AgreementTip from '../components/AgreementTip.vue'; // @ts-ignore import { getAigcSceneList, AigcSceneListItem, AigcSceneStyleItem } from '@api'; +// @ts-ignore +import { createGeneratorPhotoTask, updateImageFile } from '@api'; +import { showFailToast, showSuccessToast } from 'vant'; // --- 测试数据 --- const styles = [ @@ -107,7 +110,48 @@ const onStartSelect = () => { console.log("用户已阅读说明,开始打开相册逻辑..."); showGuide.value = false; // 这里写调用系统相册的代码 - router.push('/generate'); + uploadImage(); +}; + +// 调用上传 +const uploadImage = () => { + wx.miniProgram.postMessage({ + data: { action: 'chooseAndUpload' } + }); +} + +// 监听 hash 变化,获取结果 +window.addEventListener('hashchange', function() { + const hash = window.location.hash; + if (hash.startsWith('#uploadResult=')) { + const imageUrl = decodeURIComponent(hash.substring('#uploadResult='.length)); + console.log('上传成功,图片地址:', imageUrl); + // 这里就可以使用 imageUrl 了,比如赋值给某个变量或调用业务逻辑 + if (!imageUrl || imageUrl === 'error') { + showFailToast('获取图片地址失败,请重试。'); + return; + } + sendGeneratorPhotoTask(imageUrl); + // 可选:清除 hash,避免重复触发 + history.replaceState(null, null, window.location.pathname + window.location.search); + } +}); + +/// 发送生成任务 +const sendGeneratorPhotoTask = async (photoUrl: string) => { + const photoUrlList = [photoUrl]; + try { + const response = await createGeneratorPhotoTask({ photoUrlList: photoUrlList }); + if (response) { + showSuccessToast('生成任务创建成功!'); + router.push('/generate'); + } else { + showFailToast('生成任务创建失败,请重试。'); + } + } catch (error) { + console.error('创建生成任务时发生错误:', error); + showFailToast('创建生成任务时发生错误,请稍后再试。'); + } }; diff --git a/src/views/prepicture/index.vue b/src/views/prepicture/index.vue index 5d5ef06..f51802a 100644 --- a/src/views/prepicture/index.vue +++ b/src/views/prepicture/index.vue @@ -38,6 +38,7 @@ import TopNavBar from '../components/TopNavBar.vue'; import VueEasyLightbox from 'vue-easy-lightbox'; // @ts-ignore import 'vue-easy-lightbox/dist/external-css/vue-easy-lightbox.css'; // 导入其 CSS +import { showToast } from 'vant'; const disclaimerText = ref('脑洞特效由 AI 随机生成,如未达预期敬请谅解。') @@ -69,8 +70,22 @@ const handleHide = () => { }; const handleSave = () => { - console.log('保存图片:', sceneData.value ? (sceneData.value.title || sceneData.value.name) : ''); - alert('图片已保存至相册 (示例)'); + saveImage(); +}; + +const saveImage = () => { + if (!imageUrl.value) { + showToast('图片地址无效,无法保存'); + return; + } + + // 发送消息给小程序 + wx.miniProgram.postMessage({ + data: { + action: 'saveImage', + imageUrl: imageUrl + } + }); };