diff --git a/.env.production b/.env.production index 0919367..c3b1489 100644 --- a/.env.production +++ b/.env.production @@ -19,7 +19,7 @@ VITE_APP_RES_FILE_PATH = 'https://prev.ysaix.com:7868/src/assets/textbook/booktx VITE_APP_BUILD_BASE_PATH = 'https://prev.ysaix.com:7868/' # websocket 地址 -VITE_APP_WS_URL = 'wss://file.ysaix.com:7868' +VITE_APP_WS_URL = 'wss://prev.ysaix.com:7868' # 是否显示开发工具 VITE_SHOW_DEV_TOOLS = 'false' diff --git a/package.json b/package.json index 0f251bf..21aff1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aix-win-ws", - "version": "2.5.4", + "version": "2.5.5", "description": "", "main": "./out/main/index.js", "author": "上海交大重庆人工智能研究院", diff --git a/src/renderer/public/pdfjs-dist/web/viewer.mjs b/src/renderer/public/pdfjs-dist/web/viewer.mjs index 0ae4fbc..08b3d5d 100644 --- a/src/renderer/public/pdfjs-dist/web/viewer.mjs +++ b/src/renderer/public/pdfjs-dist/web/viewer.mjs @@ -13097,15 +13097,15 @@ const PDFViewerApplication = { } if (isValidSpreadMode(spread)) { //默认双页 - // this.pdfViewer.spreadMode = spread; - this.pdfViewer.spreadMode = 1; + this.pdfViewer.spreadMode = spread; + // this.pdfViewer.spreadMode = 1; } }; this.isInitialViewSet = true; this.pdfSidebar?.setInitialView(sidebarView); //默认双页 - // setViewerModes(scrollMode, spreadMode); - setViewerModes(scrollMode, 1); + setViewerModes(scrollMode, spreadMode); + // setViewerModes(scrollMode, 1); if (this.initialBookmark) { setRotation(this.initialRotation); delete this.initialRotation; diff --git a/src/renderer/src/AixPPTist/src/App.vue b/src/renderer/src/AixPPTist/src/App.vue index 20fca42..c06919f 100644 --- a/src/renderer/src/AixPPTist/src/App.vue +++ b/src/renderer/src/AixPPTist/src/App.vue @@ -28,8 +28,9 @@ import msgUtils from '@/plugins/modal' // 消息工具 import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api import { PPTApi } from './api' import { sessionStore } from '@/utils/store' // electron-store 状态管理 -import './api/watcher' // 监听 - +// import './api/watcher' // 监听 +import watcher from './api/watcher' // 监听 +watcher() // 监听启动 const loading = ref(true) const _isPC = isPC() @@ -39,8 +40,8 @@ const slidesStore = useSlidesStore() const { databaseId } = storeToRefs(mainStore) const { screening } = storeToRefs(useScreenStore()) -if (import.meta.env.MODE !== 'development') { - window.onbeforeunload = () => false +if (import.meta.env.MODE === 'development') { + // window.onbeforeunload = () => false } onMounted(async () => { diff --git a/src/renderer/src/AixPPTist/src/api/classcourse.ts b/src/renderer/src/AixPPTist/src/api/classcourse.ts index e78a19d..30e65e8 100644 --- a/src/renderer/src/AixPPTist/src/api/classcourse.ts +++ b/src/renderer/src/AixPPTist/src/api/classcourse.ts @@ -8,12 +8,15 @@ import * as useStore from '../store' // pptist-状态管理 import ChatWs from '@/plugins/socket' // 聊天socket import msgUtils from '@/plugins/modal' // 消息工具 +const slidesStore = useStore.useSlidesStore() // 幻灯片-状态管理 const screenStore = useStore.useScreenStore() // 全屏-状态管理 const classcourseStore = useStore.useClasscourseStore() // 课堂信息-状态管理 const classcourse = sessionStore.get('curr.classcourse') // 课堂信息 export class Classcourse { msgObj:ElMessageBox = null // 提示消息对象 + classcourse:any = null // 课堂信息 + id: number|string = null // 课堂id constructor() { this.load() @@ -22,6 +25,7 @@ export class Classcourse { * @description 加载 */ load() { + console.log('classcourse-load', classcourse) // 打开全屏 screenStore.setScreening(!!classcourse) // 如果课堂信息有值,则连接socket @@ -29,14 +33,19 @@ export class Classcourse { // 连接socket if (!ChatWs.ws) ChatWs.init() ChatWs.id = classcourse.timgroupid // 群组id - console.log('ws- ', classcourse) + this.classcourse = classcourse // 课堂信息 + this.id = classcourse.id // 课堂id + // 如果课堂信息有paging,则更新当前页码 + const isPaging = !!classcourse.paging||classcourse.paging==0 + if (isPaging) slidesStore.updateSlideIndex(classcourse.paging) + // 课堂信息-状态管理 classcourseStore.setClasscourse(classcourse) // 待上课提示 if (!classcourse.status) { this.msgObj = { type: 'success', title: '系统提示', - message: '公屏课堂已准备完毕,请等待老师开启课堂!', + message: '公屏课堂已准备完毕,等待老师开启课堂...', center: true, showClose: false, showCancelButton: false, diff --git a/src/renderer/src/AixPPTist/src/api/index.ts b/src/renderer/src/AixPPTist/src/api/index.ts index 057dcf3..611efb6 100644 --- a/src/renderer/src/AixPPTist/src/api/index.ts +++ b/src/renderer/src/AixPPTist/src/api/index.ts @@ -3,22 +3,22 @@ * @author zdg * @date 2024-11-26 */ -import { toRaw, nextTick } from 'vue' +import { toRaw } from 'vue' import type { Result } from './types' // 接口类型 import msgUtils from '@/plugins/modal' // 消息工具 import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api import * as API_smarttalk from '@/api/file' // 相关api -import * as Api_server from '@/api/apiService' // 相关api -import * as CreateHomework from '@/views/tool/createHomework' // 统计相关 import * as useStore from '../store' // pptist-状态管理 import { sessionStore } from '@/utils/store' // electron-store 状态管理 import useUserStore from '@/store/modules/user' // 外部-用户信息 -import { toPng, toJpeg } from 'html-to-image' // 引入html-to-image库 -// import * as commUtils from '@/utils/comm.js' -import { createWindow } from '@/utils/tool' -import { useToolState } from '@/store/modules/tool' +import * as Api_server from '@/api/apiService' // 相关api +import * as commUtils from '@/utils/comm.js' const slidesStore = useStore.useSlidesStore() const userStore = useUserStore() + +import { getClassWorkList,getStudentClassWorkData } from '@/views/tool/createHomework' +import {createWindow} from '@/utils/tool' +import { useToolState } from '@/store/modules/tool' const toolStore = useToolState() /** 工具类 */ export class Utils { @@ -73,7 +73,6 @@ export class PPTApi { // 活动列表处理 const workList = (res.rows || []).map(o => o.activityContent) const workItem = [...res.rows] - // 加入活动后刷新ppt数据内容,不跟换为第一页 // slidesStore.updateSlideIndex(0) // 下标0 为第一页 slidesStore.setSlides(slides) // 写入数据 // 写入作业列表数据 @@ -112,6 +111,7 @@ export class PPTApi { data.id = rid slidesStore.updateSlide(data) // msgUtils.msgSuccess('新增成功') + PPTApi.getSlideList(resource.id) this.isUpdate = false // 新增后会触发监听,不再更新数据 resolve(true) } else msgUtils.msgError('新增失败');resolve(false) @@ -147,11 +147,7 @@ export class PPTApi { // 更新幻灯片 static updateSlide(data: object): Promise { return new Promise(async (resolve, reject) => { - const thumUrl = await this.getSlideThumUrl() - data.base64Code = thumUrl // 更新缩略图 const res: Result = await API_entpcoursefile.updateEntpcoursefileNew(data) - console.log(data,'data'); - console.log(res,'dresata'); if (res.code === 200) { resolve(true) } else msgUtils.msgError(res.msg || '更新失败');resolve(false) @@ -193,40 +189,30 @@ export class PPTApi { else msgUtils.msgError(res.msg || '更新失败');return false }) } - // thumbnail-slide thumbnail - static getSlideThumUrl(): Promise { - return nextTick().then(async() => { - const slideIndex = slidesStore.slideIndex - const elements = document.querySelectorAll('.thumbnail-slide') - if (elements.length && slideIndex >= 0) { - const element = elements[slideIndex] - return await toPng(element) - } - return null - }) - } // 图片|音频|视频 转换为在线地址 - static toRousrceUrl =async (file: File|any) => { - const formData = new FormData() - formData.append('file', file) - const res = await Api_server.Other.uploadFile(formData) - if (res && res.code == 200){ - const url = res?.url - url &&(o.src = url) - return url - } - } + static toRousrceUrl =async (o:any) => { + const formData = new FormData() + formData.append('file', o) + const res = await Api_server.Other.uploadFile(formData) + if (res && res.code == 200){ + const url = res?.url + url &&(o.src = url) + return url + } + +} } export class Homework{ // 作业弹窗 static async showHomework(id: any) { - let result = await CreateHomework.getClassWorkList(id) - result = await CreateHomework.getStudentClassWorkData() - localStorage.setItem('teachClassWorkItem', JSON.stringify(result[0])); - toolStore.isTaskWin=true; // 设置打开批改窗口 - createWindow('open-taskwin',{url:'/teachClassTask'}); + let result = await getClassWorkList(id) +   result = await getStudentClassWorkData() +   localStorage.setItem('teachClassWorkItem', JSON.stringify(result[0])); +   toolStore.isTaskWin=true; // 设置打开批改窗口 + //   emit('closeActive') +   createWindow('open-taskwin',{url:'/teachClassTask'}); } } export default PPTApi \ No newline at end of file diff --git a/src/renderer/src/AixPPTist/src/api/types.ts b/src/renderer/src/AixPPTist/src/api/types.ts index 26881e9..e762748 100644 --- a/src/renderer/src/AixPPTist/src/api/types.ts +++ b/src/renderer/src/AixPPTist/src/api/types.ts @@ -106,6 +106,8 @@ export class MsgEnum { MSG_anmationclick : 'anmationclick', /** @desc: 群组创建成功 */ MSG_classcourseopen : 'classcourseopen', + /** @desc: 学生提交作业 */ + MSG_finishHomework : 'finishHomework', /** @desc: 学生的测练结果反馈 */ MSG_classquizfeedback : 'classquizfeedback', /** @desc: 老师端:接收到学生反馈消息-课堂测练中的其他任务 */ @@ -120,6 +122,12 @@ export class MsgEnum { MSG_classWorkOfPresentDataUpdate : 'classWorkOfPresentDataUpdate', /** @desc: 课堂讲授活动,选择不同的内容 */ MSG_classlecturePagesrc : 'classlecturePagesrc', + /** @desc: 课堂作业|活动 */ + MSG_homework : 'HOMEWORK', + /** @desc: 点赞 */ + MSG_dz : 'dz', + /** @desc: 疑惑 */ + MSG_yh : 'yh', // === 新定义-消息头 === /** @desc: 课程创建-待开课 */ MSG_0000: 0x0000, diff --git a/src/renderer/src/AixPPTist/src/api/watcher.ts b/src/renderer/src/AixPPTist/src/api/watcher.ts index ff14229..aee4d48 100644 --- a/src/renderer/src/AixPPTist/src/api/watcher.ts +++ b/src/renderer/src/AixPPTist/src/api/watcher.ts @@ -10,85 +10,106 @@ import { MsgEnum } from './types' // 消息枚举 import ChatWs from '@/plugins/socket' // 聊天socket import Classcourse from './classcourse' // 课程相关 import msgUtils from '@/plugins/modal' // 消息工具 -const slidesStore = store.useSlidesStore() -const classcourseStore = store.useClasscourseStore() // 课堂信息-状态管理 -const resource = sessionStore.get('curr.resource') // apt 资源 -const smarttalk = sessionStore.get('curr.smarttalk') // 备课资源 +import { Homework } from './index' // api-作业相关 +import emitter from '@/utils/mitt' //mitt 事件总线 + /** * @description 监听器 */ -// 监听幻灯片内容变化 -watch(() => slidesStore.slides, (newVal, oldVal) => { - PPTApi.updateSlides(newVal, oldVal) // 更新幻灯片内容 -},{ deep: true }) - -// 监听标题变化 -watch(() => slidesStore.title, (newVal, oldVal) => { - if (oldVal == '未命名演示文稿') return // 初始加载,不需要更新数据 - updatePPT({title: newVal}) -}) - -// 消息监听ws -console.log('监听器已开启', ChatWs) -if (ChatWs.ws) { - ChatWs.watch((msg, e) => { - try { - handleMessage(JSON.parse(msg)) - } catch (error) { - console.error('socket 解析异常 ', error, e) - handleMessage(msg) - } +export default () => { + const slidesStore = store.useSlidesStore() + const classcourseStore = store.useClasscourseStore() // 课堂信息-状态管理 + const resource = sessionStore.get('curr.resource') // apt 资源 + const smarttalk = sessionStore.get('curr.smarttalk') // 备课资源 + + // 监听幻灯片内容变化 + watch(() => slidesStore.slides, (newVal, oldVal) => { + PPTApi.updateSlides(newVal, oldVal) // 更新幻灯片内容 + },{ deep: true }) + + // 监听标题变化 + watch(() => slidesStore.title, (newVal, oldVal) => { + if (oldVal == '未命名演示文稿') return // 初始加载,不需要更新数据 + updatePPT({title: newVal}) }) -} - -// 更新ppt内容 -const updatePPT = async (data) => { - if (!resource) return - data.id = resource.id - await PPTApi.updateSlide(data) // 更新ppt内容 - sessionStore.set('curr.resource.title', data.title) - // 更新smarttalk内容 - if (!!smarttalk && !!data.title) { - const {id, fileFlag} = smarttalk - const params = { id, fileShowName: `${data.title}.${fileFlag}` } - await PPTApi.updateSmarttalk(params) // 更新ppt内容 - sessionStore.set('curr.smarttalk.fileShowName', params.fileShowName) + + // 消息监听ws + // console.log('监听器已开启', ChatWs) + if (!!ChatWs.ws) { + ChatWs.watch((data, e) => { + try { + handleMessage(JSON.parse(data)?.msg) + } catch (error) { + console.error('socket 解析异常 ', error, e) + handleMessage(data) + } + }) } -} - -// ws消息处理 -const handleMessage = (msg) => { - if (typeof msg === 'object'){ - const { head, content, ...other } = msg - switch (head) { - case MsgEnum.HEADS.MSG_open: // 开课 - // 课堂信息不一致 - if (Classcourse.id !== content.id) { - msgUtils.alertError('老师开课信息异常,请重新进入公屏!') - .then(() => { // 点击确定按钮,关闭窗口 - window.close() - }) - } else { // 正常更新数据 - classcourseStore.classcourse.status = 'open' - // 更新课堂信息-关闭警告框 - Classcourse?.msgObj?.onVanish() - } - break - case MsgEnum.HEADS.MSG_slideFlapping: // 幻灯片翻页 - const slideIndex = content.current - slidesStore.updateSlideIndex(slideIndex) // 更新幻灯片下标 - break - case MsgEnum.HEADS.MSG_closed: // 下课: - window.close() // 关闭窗口 - break - default: - break + + // 更新ppt内容 + const updatePPT = async (data) => { + if (!resource) return + data.id = resource.id + await PPTApi.updateSlide(data) // 更新ppt内容 + sessionStore.set('curr.resource.title', data.title) + // 更新smarttalk内容 + if (!!smarttalk && !!data.title) { + const {id, fileFlag} = smarttalk + const params = { id, fileShowName: `${data.title}.${fileFlag}` } + await PPTApi.updateSmarttalk(params) // 更新ppt内容 + sessionStore.set('curr.smarttalk.fileShowName', params.fileShowName) } } + + // ws消息处理 + const handleMessage = (msg) => { + console.log('ws消息处理', msg) + if (typeof msg === 'object'){ + const { head, content, ...other } = msg + switch (head) { + case MsgEnum.HEADS.MSG_open: // 开课 + // 课堂信息不一致 + if (Classcourse.id !== content.id) { + msgUtils.alertError('老师开课信息异常,请重新进入公屏!') + .then(() => { // 点击确定按钮,关闭窗口 + close() + }) + } else { // 正常更新数据 + classcourseStore.classcourse.status = 'open' + sessionStore.set('curr.classcourse.status', 'open') + // 更新课堂信息-关闭警告框 + Classcourse?.msgObj?.onVanish() + } + break + case MsgEnum.HEADS.MSG_slideFlapping: // 幻灯片翻页 + const slideIndex = content.current + slidesStore.updateSlideIndex(slideIndex) // 更新幻灯片下标 + break + case MsgEnum.HEADS.MSG_homework: // 作业|活动-布置 + if (!content.classWorkId) return + Homework.showHomework(content.classWorkId) + break + case MsgEnum.HEADS.MSG_closed: // 下课: + close() + break + case MsgEnum.HEADS.MSG_dz: // 点赞 + emitter.emit('upvoteTrigger', 1) + break + case MsgEnum.HEADS.MSG_yh: // 疑惑 + emitter.emit('upvoteTrigger', 2) + break + case MsgEnum.HEADS.MSG_0010: // 备用 + break + default: + break + } + } + } + // 关闭窗口 + const close = () => { + ChatWs?.close() // 关闭ws + setTimeout(() => { + window.close() // 关闭窗口 + }, 1000) + } } -// console.log('监听器已开启', Classcourse) -// setTimeout(() => { -// console.log('关闭弹窗') -// // Classcourse.msgObj?.close() -// Classcourse?.msgObj?.onVanish() -// }, 10 * 1000) \ No newline at end of file diff --git a/src/renderer/src/AixPPTist/src/hooks/useScreening.ts b/src/renderer/src/AixPPTist/src/hooks/useScreening.ts index e8cc32a..979b8c4 100644 --- a/src/renderer/src/AixPPTist/src/hooks/useScreening.ts +++ b/src/renderer/src/AixPPTist/src/hooks/useScreening.ts @@ -1,5 +1,6 @@ import { useScreenStore, useSlidesStore, useClasscourseStore } from '../store' import { enterFullscreen, exitFullscreen, isFullscreen } from '../utils/fullscreen' +import ChatWs from '@/plugins/socket' // 聊天socket export default () => { const screenStore = useScreenStore() @@ -23,7 +24,10 @@ export default () => { const classcourse = classcourseStore.classcourse if (!!classcourse) { //DOTO 有课堂,执行退相关操作 console.log('退出放映状态') - window.close() + ChatWs?.close() // 关闭ws + setTimeout(() => { + window.close() // 关闭窗口 + }, 1000) } else screenStore.setScreening(false) if (isFullscreen()) exitFullscreen() } diff --git a/src/renderer/src/AixPPTist/src/store/screen.ts b/src/renderer/src/AixPPTist/src/store/screen.ts index ec99745..e4fe1f5 100644 --- a/src/renderer/src/AixPPTist/src/store/screen.ts +++ b/src/renderer/src/AixPPTist/src/store/screen.ts @@ -1,17 +1,26 @@ import { defineStore } from 'pinia' export interface ScreenState { - screening: boolean + screening: boolean, + like: number, + doubt: number, } export const useScreenStore = defineStore('screen', { state: (): ScreenState => ({ screening: false, // 是否进入放映状态 + like:0, // 点赞数量 + doubt:0, // 疑问数量 }), actions: { setScreening(screening: boolean) { this.screening = screening }, + // 打开点赞或疑问 + openUpvote(type: 'like' | 'doubt'){ + if (type === 'like') this.like++ + else this.doubt++ + } }, }) \ No newline at end of file diff --git a/src/renderer/src/AixPPTist/src/store/slides.ts b/src/renderer/src/AixPPTist/src/store/slides.ts index 78e9d02..37ba6b2 100644 --- a/src/renderer/src/AixPPTist/src/store/slides.ts +++ b/src/renderer/src/AixPPTist/src/store/slides.ts @@ -5,9 +5,12 @@ import type { Slide, SlideTheme, PPTElement, PPTAnimation } from '../types/slide import { slides } from '../mocks/slides' import { theme } from '../mocks/theme' import { layouts } from '../mocks/layout' +import { sessionStore } from '@/utils/store' // electron-store 状态管理 +import useUserStore from '@/store/modules/user' // 外部-用户信息 +import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api import PPTApi from '../api/store' - +const userStore = useUserStore() interface RemovePropData { id: string propName: string | string[] @@ -142,16 +145,19 @@ export const useSlidesStore = defineStore('slides', { setWorkItem(list: Object[]) { this.workItem = list }, + addWorkItem(data: any) { + const id = data?.id + if (!id) return + this.workItem.splice(this.slideIndex + 1, 0, data) + this.slideIndex += 1 + }, addSlide(slide: Slide | Slide[]) { const slides = Array.isArray(slide) ? slide : [slide] for (const slide of slides) { if (slide.sectionTag) delete slide.sectionTag } - - const addIndex = this.slideIndex + 1 - this.slides.splice(addIndex, 0, ...slides) - this.slideIndex = addIndex + this.slides.splice(this.slideIndex, 0, ...slides) }, updateSlide(props: Partial, slideId?: string) { @@ -188,6 +194,7 @@ export const useSlidesStore = defineStore('slides', { const isDel = await PPTApi.delSlide(deletedId) if (isDel) { // 后端删除成功,更新页面数据 + this.workItem.splice(index, 1) deleteSlidesIndex.push(index) slides.splice(index, 1) } diff --git a/src/renderer/src/AixPPTist/src/utils/image.ts b/src/renderer/src/AixPPTist/src/utils/image.ts index 306ddbc..1336095 100644 --- a/src/renderer/src/AixPPTist/src/utils/image.ts +++ b/src/renderer/src/AixPPTist/src/utils/image.ts @@ -72,4 +72,55 @@ export const isSVGString = (text: string): boolean => { export const svg2File = (svg: string): File => { const blob = new Blob([svg], { type: 'image/svg+xml' }) return new File([blob], `${Date.now()}.svg`, { type: 'image/svg+xml' }) +} + +/** + * 获取当前的时间 + * @returns + */ +export const getTime=()=>{ + const now = new Date(); + const year = now.getFullYear(); + const month = ('0' + (now.getMonth() + 1)).slice(-2); + const day = ('0' + now.getDate()).slice(-2); + const hours = ('0' + now.getHours()).slice(-2); + const minutes = ('0' + now.getMinutes()).slice(-2); + const seconds = ('0' + now.getSeconds()).slice(-2); + return `${year}-${month}-${day}_${hours}:${minutes}:${seconds}`; +}; + +/** +* base64转图片File +* @param {String} base64 图片base64 +* @param {String} fileName 图片名称| 默认 → myimg +* @returns File 返回转换后的file数据类型 +*/ +export const base64ToFile = (base64: string, fileName = '试题图片') => { + // 将base64按照 , 进行分割 将前缀 与后续内容分隔开 + let data = base64.split(','), + // 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等) + type = data[0].match(/:(.*?);/)[1], + // 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp) + suffix = type.split('/')[1], + // 使用atob()对base64数据进行解码 结果是一个文件数据流 以字符串的格式输出 + bstr = window.atob(data[1]), + // 获取解码结果字符串的长度 + n = bstr.length, + // 根据解码结果字符串的长度创建一个等长的整形数字数组 + // 但在创建时 所有元素初始值都为 0 + u8arr = new Uint8Array(n) + + // 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元 + while (n--) { + // charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元 + u8arr[n] = bstr.charCodeAt(n) + } + const filename = fileName+getTime() + // 利用构造函数创建File文件对象 + // new File(bits, name, options) + const file = new File([u8arr], `${filename}.${suffix}`, { + type: type + }) + // 返回file + return file } \ No newline at end of file diff --git a/src/renderer/src/AixPPTist/src/views/Editor/CanvasTool/MaterialDialog.vue b/src/renderer/src/AixPPTist/src/views/Editor/CanvasTool/MaterialDialog.vue index 9ad6322..26c852e 100644 --- a/src/renderer/src/AixPPTist/src/views/Editor/CanvasTool/MaterialDialog.vue +++ b/src/renderer/src/AixPPTist/src/views/Editor/CanvasTool/MaterialDialog.vue @@ -19,7 +19,8 @@ import { ref, reactive, onMounted, computed } from 'vue'; import { sessionStore } from '@/utils/store' import { getSmarttalkPage } from '@/api/file' -import { getFileSuffix, urlToBase64 } from '@/utils/ruoyi.js' +import * as commUtils from '@/utils/comm.js' +import { getFileSuffix } from '@/utils/ruoyi.js' const emit = defineEmits(['insertMaterial', 'close']) @@ -62,12 +63,15 @@ const fileUrl = computed(() => (item) =>{ // 插入 const onInsert = async (item) =>{ + const res = await fetch(item.fileFullPath) + const bolb = await res.blob() + const file = commUtils.blobToFile(bolb, item.fileShowName) + if(videoSuffix.indexOf(getFileSuffix(item.fileShowName)) != -1){ - emit('insertMaterial',{ type: 'video', data: item.fileFullPath }) + emit('insertMaterial',{ type: 'video', file }) } else{ - const base64 = await urlToBase64(item.fileFullPath) - emit('insertMaterial',{ type: 'img', data: base64 }) + emit('insertMaterial',{ type: 'img', file }) } } diff --git a/src/renderer/src/AixPPTist/src/views/Editor/CanvasTool/index.vue b/src/renderer/src/AixPPTist/src/views/Editor/CanvasTool/index.vue index 879865f..ad51dd9 100644 --- a/src/renderer/src/AixPPTist/src/views/Editor/CanvasTool/index.vue +++ b/src/renderer/src/AixPPTist/src/views/Editor/CanvasTool/index.vue @@ -114,7 +114,7 @@ /> - + - + @@ -141,7 +141,7 @@ import { ref } from 'vue' import { storeToRefs } from 'pinia' import { useMainStore, useSnapshotStore } from '../../../store' -import { getImageDataURL } from '../../../utils/image' +import { getImageDataURL, base64ToFile } from '../../../utils/image' import type { ShapePoolItem } from '../../../configs/shapes' import type { LinePoolItem } from '../../../configs/lines' import useScaleCanvas from '../../../hooks/useScaleCanvas' @@ -165,6 +165,7 @@ import { PPTApi } from '../../../api' import TextCreateImg from '@/components/ai-kolors/index.vue' import { toPng } from 'html-to-image' // 引入html-to-image库 + const mainStore = useMainStore() const { creatingElement, creatingCustomShape, showSelectPanel, showSearchPanel, showNotesPanel } = storeToRefs(mainStore) const { canUndo, canRedo } = storeToRefs(useSnapshotStore()) @@ -209,8 +210,14 @@ const insertImageElement = (files: FileList) => { } const onhtml2canvas = async (html: HTMLElement) => { - const ele = await toPng(html); - createImageElement(ele); + const base64Dta = await toPng(html); + // base64转图片File + const toFile = base64ToFile(base64Dta) + // 上传图片转为线上地址 + PPTApi.toRousrceUrl(toFile).then(data=>{ + createImageElement(data) + }) + // createImageElement(ele); } const shapePoolVisible = ref(false) @@ -274,21 +281,31 @@ const toggleNotesPanel = () => { // 插入素材 interface MaterialParams { type: string, - data: string + file: any } const insertMaterial = (item: MaterialParams) =>{ - const { type, data } = item - if(type == 'video'){ - createVideoElement(data) - } - else{ - createImageElement(data) - } - materiaVisible.value = false + const { type, file } = item + PPTApi.toRousrceUrl(file).then(data=>{ + if(type == 'video'){ + createVideoElement(data) + } + else{ + createImageElement(data) + } + materiaVisible.value = false + }) + } // 文生图 const imgVisible = ref(false) +const insertImg = async (file: any) =>{ + PPTApi.toRousrceUrl(file).then(data=>{ + createImageElement(data) + imgVisible.value = false + }) +} +