Compare commits

...

3 Commits

Author SHA1 Message Date
朱浩 656a58693f Merge remote-tracking branch 'origin/main' 2024-12-10 14:20:08 +08:00
朱浩 772b196b31 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	src/renderer/src/views/prepare/index.vue
2024-12-10 10:44:04 +08:00
朱浩 757edb0f67 改名AIPPT 2024-12-10 10:40:08 +08:00
2 changed files with 164 additions and 46 deletions

View File

@ -36,7 +36,7 @@
{{ item.async === 'on' ? '同步中' : '' }} {{ item.async === 'on' ? '同步中' : '' }}
</div> </div>
<template v-if="item.fileFlag ==='课件'">|</template> <template v-if="item.fileFlag ==='课件'">|</template>
<div style="width: 70px">访问 100</div> <!-- <div style="width: 70px">访问 100</div>
| |
<div style="width: 70px">引用 50</div> <div style="width: 70px">引用 50</div>
| |
@ -49,6 +49,16 @@
white-space: nowrap; white-space: nowrap;
width: 200px; width: 200px;
">点赞 20</div> ">点赞 20</div>
|-->
<div
style="
flex: 1;
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 200px;
">{{formatDate(item.createTime, 'yyyy-MM-dd hh:mm:ss')}}</div>
</div> </div>
</div> </div>
<div class="prepare-body-main-item-btn"> <div class="prepare-body-main-item-btn">
@ -107,6 +117,7 @@ import { endClass, getSelfReserv } from '@/api/classManage'
import { listEntpcourse } from '@/api/teaching/classwork' import { listEntpcourse } from '@/api/teaching/classwork'
import { createWindow } from '@/utils/tool' import { createWindow } from '@/utils/tool'
import { defineExpose } from 'vue' import { defineExpose } from 'vue'
import {formatDate} from '@/utils/comm'
const { ipcRenderer } = window.electron || {} const { ipcRenderer } = window.electron || {}
export default { export default {

View File

@ -8,15 +8,16 @@
</el-button> </el-button>
<template #dropdown> <template #dropdown>
<el-dropdown-menu> <el-dropdown-menu>
<el-dropdown-item @click="createAptFile">新建文枢课件</el-dropdown-item> <el-dropdown-item @click="createAIPPT">新建文枢课件</el-dropdown-item>
<el-dropdown-item>AI一键生成</el-dropdown-item> <el-dropdown-item @click="aiTOPPT">AI一键生成</el-dropdown-item>
<el-dropdown-item>导入PPT</el-dropdown-item> <el-dropdown-item @click="openFilePicker">导入PPT</el-dropdown-item>
<input type="file" ref="fileInput" style="display: none;" @change="handleFileChange" accept="application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation">
</el-dropdown-menu> </el-dropdown-menu>
</template> </template>
</el-dropdown> </el-dropdown>
<el-tabs v-model="activeAptTab" style="height: 100%;"> <el-tabs v-model="activeAptTab" style="height: 100%;">
<el-tab-pane label="文枢课件" name="教学课件" class="prepare-center-jxkj"> <el-tab-pane label="文枢课件" name="教学课件" class="prepare-center-jxkj">
<div class="prepare-center-header"> <!-- <div class="prepare-center-header">
<div class="center-create-btn" style="background-color: rgb(64,158,255)" @click="createAptFile"> <div class="center-create-btn" style="background-color: rgb(64,158,255)" @click="createAptFile">
<div class="create-btn-title"><el-icon><Plus /></el-icon><label>APT</label></div> <div class="create-btn-title"><el-icon><Plus /></el-icon><label>APT</label></div>
<div class="create-btn-info">智能交互课件</div> <div class="create-btn-info">智能交互课件</div>
@ -29,7 +30,7 @@
<div class="create-btn-title"><el-icon><Plus /></el-icon><label>PPT</label></div> <div class="create-btn-title"><el-icon><Plus /></el-icon><label>PPT</label></div>
<div class="create-btn-info">试验版</div> <div class="create-btn-info">试验版</div>
</div> </div>
</div> </div>-->
<div class="prepare-center-body"> <div class="prepare-center-body">
<kj-list-item <kj-list-item
v-for="(item, index) in currentKJFileList" v-for="(item, index) in currentKJFileList"
@ -152,6 +153,7 @@
<!-- 上课配置 --> <!-- 上课配置 -->
<class-start ref="calssRef" @close="closeChange"/> <class-start ref="calssRef" @close="closeChange"/>
<PptDialog @add-success="addAiPPT" :currentNode="currentNode" :uploadData="uploadData" v-model="pptDialog"/> <PptDialog @add-success="addAiPPT" :currentNode="currentNode" :uploadData="uploadData" v-model="pptDialog"/>
<progress-dialog v-model:visible="pgDialog.visible" v-bind="pgDialog" />
<!-- 章节弹窗 --> <!-- 章节弹窗 -->
<TreeLog ref="treelogRef"/> <TreeLog ref="treelogRef"/>
<!-- <button @click="test">test</button> --> <!-- <button @click="test">test</button> -->
@ -161,8 +163,16 @@ import {Check, Plus, Position} from '@element-plus/icons-vue'
import Reserv from '@/views/prepare/container/reserv.vue' import Reserv from '@/views/prepare/container/reserv.vue'
import { ArrowDown } from '@element-plus/icons-vue' import { ArrowDown } from '@element-plus/icons-vue'
import PptDialog from '@/views/prepare/container/ppt-dialog.vue' import PptDialog from '@/views/prepare/container/ppt-dialog.vue'
import progressDialog from '@/views/teachingDesign/container/progress-dialog.vue'
import {useRouter} from "vue-router";
const router = useRouter()
const aiTOPPT = ()=> {
router.push({path: '/model/design'})
}
</script> </script>
<script> <script>
import {PPTXFileToJson} from "@/AixPPTist/src/hooks/useImport";
const Remote = require('@electron/remote') const Remote = require('@electron/remote')
import ChooseTextbook from '@/components/choose-textbook/index.vue' import ChooseTextbook from '@/components/choose-textbook/index.vue'
import uploadDialog from '@/components/upload-dialog/index.vue' import uploadDialog from '@/components/upload-dialog/index.vue'
@ -192,6 +202,12 @@ import ClassReserv from '@/views/classManage/classReserv.vue'
import TreeLog from '@/views/prepare/components/treeLog.vue' import TreeLog from '@/views/prepare/components/treeLog.vue'
import classStart from './container/class-start.vue' // import classStart from './container/class-start.vue' //
import MsgEnum from '@/plugins/imChat/msgEnum' // im import MsgEnum from '@/plugins/imChat/msgEnum' // im
import Chat from '@/utils/chat'
import * as commUtils from "@/utils/comm";
import * as Api_server from "@/api/apiService";
import msgUtils from "@/plugins/modal";
import * as API_entpcoursefile from "@/api/education/entpcoursefile"; // im
if (!Chat.imChat) Chat.init()
// import Chat from '@/utils/chat' // im // import Chat from '@/utils/chat' // im
// if (!Chat.imChat) Chat.init() // if (!Chat.imChat) Chat.init()
// import ChatWs from '@/plugins/socket' // import ChatWs from '@/plugins/socket'
@ -201,7 +217,6 @@ import MsgEnum from '@/plugins/imChat/msgEnum' // im 消息枚举
const toolStore = useToolState() const toolStore = useToolState()
const fs = require('fs') const fs = require('fs')
const { ipcRenderer } = window.electron || {} const { ipcRenderer } = window.electron || {}
export default { export default {
name: 'Prepare', name: 'Prepare',
components: { components: {
@ -257,7 +272,23 @@ export default {
// //
treelogRef:null, treelogRef:null,
// Entpcourse // Entpcourse
entp: null entp: null,
pgDialog: { // -
visible: false,
title: 'PPT解析中...',
width: 300,
showClose: false,
draggable: true,
beforeClose: done => {}, // -
pg: { // -
percentage: 0, //
color: [
{ color: '#1989fa', percentage: 50 }, //
{ color: '#e6a23c', percentage: 80 }, //
{ color: '#5cb87a', percentage: 100 }, // 绿
]
}
}
} }
}, },
computed: { computed: {
@ -476,6 +507,117 @@ export default {
},500) },500)
}) })
}, },
openFilePicker(){
this.$refs.fileInput.click();
},
handleFileChange(){
const file = event.target.files[0];
if (file) {
console.log(file);
console.log('文件名:', file.name);
console.log('文件类型:', file.type);
console.log('文件大小:', file.size);
this.createAIPPTByFile(file)
}
},
async toRousrceUrl(o) {
if (!!o.src) { // src
const isBase64 = /^data:image\/(\w+);base64,/.test(o.src)
const isBlobUrl = /^blob:/.test(o.src)
console.log('isBase64', o, isBase64)
if (isBase64) {
const bolb = commUtils.base64ToBlob(o.src)
const fileName = Date.now() + '.png'
const file = commUtils.blobToFile(bolb, fileName)
// o.src = fileName
// console.log('file', file)
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)
}
} else if (isBlobUrl) { //
}
}
if (o?.background?.image) await this.toRousrceUrl(o.background.image)
if (o?.elements) o.elements.forEach(async o => {await this.toRousrceUrl(o)})
},
async createAIPPTByFile(file) {
this.pgDialog.visible = true
this.pgDialog.pg.percentage = 0
const resPptJson = await PPTXFileToJson(file)
const { def, slides, ...content } = resPptJson
// || 线
let completed = 0
const total = slides.length
for( let o of slides ) {
completed++
await this.toRousrceUrl(o)
//
this.pgDialog.pg.percentage = Math.floor(completed / total * 100)
}
this.pgDialog.pg.percentage = 0
this.pgDialog.visible = false
listEntpcourse({
evalid: this.currentNode.id,
edituserid: this.userStore.userId,
pageSize: 500
}).then((response) => {
if (response.rows.length <= 0) return
let resCourse = response.rows[0]
//
let form = {
parentid: 0,
entpid: this.userStore.deptId,
entpcourseid: resCourse.id,
ppttype: 'file',
title: resCourse.coursetitle,
fileurl: '',
filetype: 'aippt',
datacontent: '',
parentContent: JSON.stringify(content),
filekey: '',
filetag: '',
fileidx: 0,
dflag: 0,
status: '',
edituserid: this.userStore.userId
}
addEntpcoursefileReturnId(form).then((slideid) => {
creatAPT({
...this.uploadData,
fileId: slideid,
fileFlag: 'aippt',
fileShowName: this.currentNode.itemtitle + '.aippt'
}).then(async (res) => {
const resSlides = slides.map(({id, ...slide}) => JSON.stringify(slide))
let params = {
parentid: slideid,
entpid: resCourse.entpid,
entpcourseid: resCourse.id,
title: '',
filetype: 'slide',
slides: resSlides,
edituserid: this.userStore.userId
}
const res_3 = await API_entpcoursefile.batchAddNew(params)
if (res_3 && res_3.code == 200) {
msgUtils.msgSuccess('导入PPT课件成功')
this.currentFileList.unshift(res.resData)
setTimeout(()=>{
this.$refs['kjItemRef'+res.resData.id][0].openFileWin(res.resData);
},500)
} else {
msgUtils.msgWarning('导入PPT课件失败')
}
})
})
})
},
createAIPPT() { createAIPPT() {
listEntpcourse({ listEntpcourse({
evalid: this.currentNode.id, evalid: this.currentNode.id,
@ -502,57 +644,22 @@ export default {
edituserid: this.userStore.userId edituserid: this.userStore.userId
} }
addEntpcoursefileReturnId(form).then((slideid) => { addEntpcoursefileReturnId(form).then((slideid) => {
let pagearray = []
//
pagearray.push({
key: '公屏',
title: '公屏页',
slidedata: {
attrs: { width: 1333, height: 749.8125 },
className: 'Stage',
children: [
{
attrs: {},
className: 'Layer',
children: [
{
attrs: {
width: 1333,
height: 749.8125,
fill: 'white',
name: 'fixedbackground',
listening: true
},
className: 'Rect'
}
]
}
]
}
})
// //
var form = { var form = {
parentid: slideid, parentid: slideid,
entpid: resCourse.entpid, entpid: resCourse.entpid,
entpcourseid: resCourse.id, entpcourseid: resCourse.id,
ppttype: 'file',
title: '第一页', title: '第一页',
fileurl: '',
filetype: 'slide', filetype: 'slide',
datacontent: JSON.stringify(pagearray), datacontent: '{"elements":[],"background":{"type":"solid","color":"#fff"}}',
filekey: '',
filetag: '',
fileidx: 0,
dflag: 0,
status: '',
edituserid: this.userStore.userId edituserid: this.userStore.userId
} }
addEntpcoursefileReturnId(form).then((res) => { addEntpcoursefileReturnId(form).then((res) => {
creatAPT({ creatAPT({
...this.uploadData, ...this.uploadData,
fileId: slideid, fileId: slideid,
fileShowName: this.currentNode.itemtitle + '.apt' fileFlag: 'aippt',
fileShowName: this.currentNode.itemtitle + '.aippt'
}).then((res) => { }).then((res) => {
this.currentFileList.unshift(res.resData) this.currentFileList.unshift(res.resData)
setTimeout(()=>{ setTimeout(()=>{