diff --git a/.env.production b/.env.production index 0919367..b7f30f3 100644 --- a/.env.production +++ b/.env.production @@ -22,4 +22,4 @@ VITE_APP_BUILD_BASE_PATH = 'https://prev.ysaix.com:7868/' VITE_APP_WS_URL = 'wss://file.ysaix.com:7868' # 是否显示开发工具 -VITE_SHOW_DEV_TOOLS = 'false' +VITE_SHOW_DEV_TOOLS = 'true' 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..7621b9f 100644 --- a/src/renderer/src/AixPPTist/src/App.vue +++ b/src/renderer/src/AixPPTist/src/App.vue @@ -39,8 +39,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/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/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/index.vue b/src/renderer/src/AixPPTist/src/views/Editor/CanvasTool/index.vue index 7780a65..2ccd34a 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 @@ /> - + { } 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) diff --git a/src/renderer/src/AixPPTist/src/views/Editor/Toolbar/ElementStylePanel/Active/index.vue b/src/renderer/src/AixPPTist/src/views/Editor/Toolbar/ElementStylePanel/Active/index.vue index bc658cf..cddd334 100644 --- a/src/renderer/src/AixPPTist/src/views/Editor/Toolbar/ElementStylePanel/Active/index.vue +++ b/src/renderer/src/AixPPTist/src/views/Editor/Toolbar/ElementStylePanel/Active/index.vue @@ -36,8 +36,8 @@
{{item.worktype}} - -
{{item.evaltitle}}
+ +
{{item.uniquekey}}
删除
@@ -62,7 +62,7 @@ > - +