feat: 接入大屏文件上传服务

This commit is contained in:
zxr
2026-08-04 01:02:40 +08:00
parent 9f2482bf66
commit 100c652f2d
8 changed files with 94 additions and 116 deletions

View File

@@ -14,8 +14,3 @@ export const fetchAllowList = [
// 接口黑名单 // 接口黑名单
export const fetchBlockList = [] export const fetchBlockList = []
// fts 接口列表(不添加 /Visual/v1 前缀)
export const ftsList = [
'/Assets/v1/fts/uploader'
]

View File

@@ -5,8 +5,6 @@ import { StorageEnum } from '@/enums/storageEnum'
import { axiosPre } from '@/settings/httpSetting' import { axiosPre } from '@/settings/httpSetting'
import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d' import { SystemStoreEnum, SystemStoreUserInfoEnum } from '@/store/modules/systemStore/systemStore.d'
import { redirectErrorPage, getLocalStorage, routerTurnByName, isPreview } from '@/utils' import { redirectErrorPage, getLocalStorage, routerTurnByName, isPreview } from '@/utils'
import { fetchAllowList, ftsList } from './axios.config'
import includes from 'lodash/includes'
export interface MyResponseType<T> { export interface MyResponseType<T> {
code: ResultEnum code: ResultEnum
@@ -28,12 +26,6 @@ const axiosInstance = axios.create({
axiosInstance.interceptors.request.use( axiosInstance.interceptors.request.use(
(config: InternalAxiosRequestConfig) => { (config: InternalAxiosRequestConfig) => {
// fts 接口特殊处理:使用完整路径,不添加 /Visual/v1 前缀
if (config.url && includes(ftsList, config.url)) {
const baseUrl = import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : import.meta.env.VITE_DEV_PATH
config.baseURL = baseUrl
}
// 获取 token 并添加到所有请求 // 获取 token 并添加到所有请求
const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE) const info = getLocalStorage(StorageEnum.GO_SYSTEM_STORE)
if (info) { if (info) {

View File

@@ -1,29 +0,0 @@
import { AxiosProgressEvent } from "axios";
import axiosInstance from '@/api/axios'
import { ContentTypeEnum } from '@/enums/httpEnum'
/** 上传文件 */
const FtsUpload = (data: any, onUploadProgress?: (progress: number) => void) => {
data.append('provider', 'local')
data.append('bucket', 'visual')
// 使用完整URL绕过 /Visual/v1 前缀
const baseUrl = import.meta.env.PROD ? import.meta.env.VITE_PRO_PATH : import.meta.env.VITE_DEV_PATH
return axiosInstance({
url: `${baseUrl}/Assets/v1/fts/uploader`,
method: 'POST',
data,
headers: {
'Content-Type': ContentTypeEnum.FORM_DATA
},
onUploadProgress: onUploadProgress ? (progressEvent: AxiosProgressEvent) => {
if (progressEvent.total) {
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
onUploadProgress(percentCompleted);
}
} : undefined
})
}
export default FtsUpload

View File

@@ -81,19 +81,3 @@ export const changeProjectReleaseApi = async (data: object) => {
httpErrorHandle() httpErrorHandle()
} }
} }
// * 上传文件
export const uploadFile = async (data: object) => {
try {
const res = await http(RequestHttpEnum.POST)<{
/**
* 文件地址
*/
fileName: string,
fileurl: string,
}>(`${ModuleTypeEnum.PROJECT}/upload`, data, ContentTypeEnum.FORM_DATA)
return res
} catch {
httpErrorHandle()
}
}

View File

@@ -21,6 +21,18 @@ export type ProjectItem = {
* 预览图片url * 预览图片url
*/ */
indexImage: string indexImage: string
/**
* 预览图片 Files 标识
*/
indexImageFileId: string
/**
* 背景图片url
*/
backgroundImage: string
/**
* 背景图片 Files 标识
*/
backgroundImageFileId: string
/** /**
* 创建者 identity * 创建者 identity
*/ */

57
src/api/projectFiles.ts Normal file
View File

@@ -0,0 +1,57 @@
import { http } from '@/api/http'
import { RequestHttpEnum, ResultEnum } from '@/enums/httpEnum'
export type ProjectImageKind = 'index' | 'background'
interface PendingUpload {
file_id: string
object_key: string
upload: {
method: string
url: string
headers: Record<string, string>
expires_at: string
}
}
interface CompletedUpload {
file_id: string
url: string
}
/** 上传项目图片并由 Visual 完成文件绑定。 */
export async function uploadProjectImage(
projectIdentity: string,
kind: ProjectImageKind,
file: File
): Promise<CompletedUpload> {
const projectPath = `project/${encodeURIComponent(projectIdentity)}/images/${kind}`
const initResponse = await http(RequestHttpEnum.POST)<PendingUpload>(`${projectPath}/init`, {
filename: file.name,
size: file.size,
content_type: file.type || 'application/octet-stream'
})
const pendingUpload = initResponse.data
if (initResponse.code !== ResultEnum.SUCCESS || !pendingUpload?.file_id || !pendingUpload.upload?.url) {
throw new Error(initResponse.message || '初始化项目图片上传失败')
}
const uploadResponse = await fetch(pendingUpload.upload.url, {
method: pendingUpload.upload.method,
headers: pendingUpload.upload.headers,
body: file,
credentials: 'omit'
})
if (!uploadResponse.ok) {
throw new Error(`上传项目图片失败: HTTP ${uploadResponse.status}`)
}
const completeResponse = await http(RequestHttpEnum.POST)<CompletedUpload>(`${projectPath}/complete`, {
file_id: pendingUpload.file_id
})
const completedUpload = completeResponse.data
if (completeResponse.code !== ResultEnum.SUCCESS || !completedUpload?.file_id || !completedUpload.url) {
throw new Error(completeResponse.message || '完成项目图片上传失败')
}
return completedUpload
}

View File

@@ -126,27 +126,23 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, nextTick, watch } from 'vue' import { ref, watch } from 'vue'
import { backgroundImageSize } from '@/settings/designSetting' import { backgroundImageSize } from '@/settings/designSetting'
import { swatchesColors } from '@/settings/chartThemes/index' import { swatchesColors } from '@/settings/chartThemes/index'
import { FileTypeEnum } from '@/enums/fileTypeEnum' import { FileTypeEnum } from '@/enums/fileTypeEnum'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d' import { EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { useSystemStore } from '@/store/modules/systemStore/systemStore'
import { StylesSetting } from '@/components/Pages/ChartItemSetting' import { StylesSetting } from '@/components/Pages/ChartItemSetting'
import { UploadCustomRequestOptions } from 'naive-ui' import { UploadCustomRequestOptions } from 'naive-ui'
import { loadAsyncComponent, fetchRouteParamsLocation } from '@/utils' import { loadAsyncComponent, fetchRouteParamsLocation } from '@/utils'
import { PreviewScaleEnum } from '@/enums/styleEnum' import { PreviewScaleEnum } from '@/enums/styleEnum'
import { ResultEnum } from '@/enums/httpEnum'
import { icon } from '@/plugins' import { icon } from '@/plugins'
import { uploadFile } from '@/api/path' import { uploadProjectImage } from '@/api/projectFiles'
import FtsUpload from '@/api/fts'
const { ColorPaletteIcon } = icon.ionicons5 const { ColorPaletteIcon } = icon.ionicons5
const { ScaleIcon, FitToScreenIcon, FitToHeightIcon, FitToWidthIcon } = icon.carbon const { ScaleIcon, FitToScreenIcon, FitToHeightIcon, FitToWidthIcon } = icon.carbon
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const systemStore = useSystemStore()
const canvasConfig = chartEditStore.getEditCanvasConfig const canvasConfig = chartEditStore.getEditCanvasConfig
const editCanvas = chartEditStore.getEditCanvas const editCanvas = chartEditStore.getEditCanvas
@@ -276,37 +272,23 @@ const clearColor = () => {
} }
// 自定义上传操作 // 自定义上传操作
const customRequest = (options: UploadCustomRequestOptions) => { const customRequest = async ({ file, onFinish, onError }: UploadCustomRequestOptions) => {
const { file } = options if (!file.file) {
nextTick(async () => { onError()
if (file.file) { window['$message'].error('添加图片失败,请稍后重试!')
// 修改名称 return
// const newNameFile = new File([file.file], `${fetchRouteParamsLocation()}_index_background.png`, { }
// type: file.file.type
// }) try {
let uploadParams = new FormData() const result = await uploadProjectImage(fetchRouteParamsLocation(), 'background', file.file)
uploadParams.append('file', file.file) chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.BACKGROUND_IMAGE, result.url)
const uploadRes: any = await FtsUpload(uploadParams) chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.SELECT_COLOR, false)
if (uploadRes && uploadRes.code === ResultEnum.SUCCESS) { onFinish()
if (uploadRes.data.result_url) { } catch (error) {
chartEditStore.setEditCanvasConfig( console.error(error)
EditCanvasConfigEnum.BACKGROUND_IMAGE, onError()
uploadRes.data.result_url window['$message'].error('添加图片失败,请稍后重试!')
) }
} else {
// chartEditStore.setEditCanvasConfig(
// EditCanvasConfigEnum.BACKGROUND_IMAGE,
// `${systemStore.getFetchInfo.OSSUrl || ''}${uploadRes.data.fileName}?time=${new Date().getTime()}`
// )
}
chartEditStore.setEditCanvasConfig(EditCanvasConfigEnum.SELECT_COLOR, false)
return
}
window['$message'].error('添加图片失败,请稍后重试!')
} else {
window['$message'].error('添加图片失败,请稍后重试!')
}
})
} }
// 选择适配方式 // 选择适配方式

View File

@@ -5,7 +5,6 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
import { EditCanvasTypeEnum, ChartEditStoreEnum, ProjectInfoEnum, ChartEditStorage, EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d' import { EditCanvasTypeEnum, ChartEditStoreEnum, ProjectInfoEnum, ChartEditStorage, EditCanvasConfigEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore' import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
import { StylesSetting } from '@/components/Pages/ChartItemSetting' import { StylesSetting } from '@/components/Pages/ChartItemSetting'
import { useSystemStore } from '@/store/modules/systemStore/systemStore'
import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore' import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore'
import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d' import { ChartLayoutStoreEnum } from '@/store/modules/chartLayoutStore/chartLayoutStore.d'
import { fetchChartComponent, fetchConfigComponent, createComponent } from '@/packages/index' import { fetchChartComponent, fetchConfigComponent, createComponent } from '@/packages/index'
@@ -14,8 +13,8 @@ import throttle from 'lodash/throttle'
// 接口状态 // 接口状态
import { ResultEnum } from '@/enums/httpEnum' import { ResultEnum } from '@/enums/httpEnum'
// 接口 // 接口
import { saveProjectApi, fetchProjectApi, uploadFile, updateProjectApi } from '@/api/path' import { saveProjectApi, fetchProjectApi } from '@/api/path'
import FtsUpload from '@/api/fts' import { uploadProjectImage } from '@/api/projectFiles'
// 画布枚举 // 画布枚举
import { SyncEnum } from '@/enums/editPageEnum' import { SyncEnum } from '@/enums/editPageEnum'
import { CreateComponentType, CreateComponentGroupType, ConfigType } from '@/packages/index.d' import { CreateComponentType, CreateComponentGroupType, ConfigType } from '@/packages/index.d'
@@ -102,7 +101,6 @@ const componentMerge = (newObject: any, sources: any, notComponent = false) => {
export const useSync = () => { export const useSync = () => {
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const chartHistoryStore = useChartHistoryStore() const chartHistoryStore = useChartHistoryStore()
const systemStore = useSystemStore()
const chartLayoutStore = useChartLayoutStore() const chartLayoutStore = useChartLayoutStore()
/** /**
* * 组件动态注册 * * 组件动态注册
@@ -317,22 +315,9 @@ export const useSync = () => {
range.style.backgroundColor = originalBgColor range.style.backgroundColor = originalBgColor
} }
// 上传预览图(使用 FtsUpload const previewFile = base64toFile(canvasImage.toDataURL('image/png'), `${projectId}.png`)
let uploadParams = new FormData() const uploadResult = await uploadProjectImage(projectId, 'index', previewFile)
uploadParams.append('file', base64toFile(canvasImage.toDataURL('image/png'), `${fetchRouteParamsLocation()}.png`)) chartEditStore.setProjectInfo(ProjectInfoEnum.THUMBNAIL, uploadResult.url)
// console.log(base64toFile(canvasImage.toDataURL('image/png'), `${fetchRouteParamsLocation()}_index_preview.png`))
const uploadRes: any = await FtsUpload(uploadParams)
// 保存预览图
if(uploadRes && uploadRes.code === ResultEnum.SUCCESS) {
if (uploadRes.data.result_url) {
await updateProjectApi({
identity: fetchRouteParamsLocation(),
indexImage: uploadRes.data.result_url,
backgroundImage: chartEditStore.getEditCanvasConfig.backgroundImage
})
}
}
} }
} catch (e) { } catch (e) {
console.log(e) console.log(e)