ppt上课 拖动更新排序 动画播放等
This commit is contained in:
parent
0b9fce21f3
commit
9ad959dfb7
|
@ -33,6 +33,7 @@ export default defineConfig({
|
||||||
proxy: {
|
proxy: {
|
||||||
'/dev-api': {
|
'/dev-api': {
|
||||||
target: 'http://27.128.240.72:7865',
|
target: 'http://27.128.240.72:7865',
|
||||||
|
// target: 'https://prev.ysaix.com:7868/prod-api/',
|
||||||
// target: 'http://36.134.181.164:7863',
|
// target: 'http://36.134.181.164:7863',
|
||||||
// target: 'http://192.168.0.102:7865',
|
// target: 'http://192.168.0.102:7865',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
|
|
|
@ -28,8 +28,8 @@ import msgUtils from '@/plugins/modal' // 消息工具
|
||||||
import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api
|
import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api
|
||||||
import { PPTApi } from './api'
|
import { PPTApi } from './api'
|
||||||
import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
||||||
// import './api/watcher' // 监听
|
|
||||||
import watcher from './api/watcher' // 监听
|
import watcher from './api/watcher' // 监听
|
||||||
|
import emitter from '@/utils/mitt' //mitt 事件总线
|
||||||
watcher() // 监听启动
|
watcher() // 监听启动
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
const _isPC = isPC()
|
const _isPC = isPC()
|
||||||
|
|
|
@ -7,7 +7,6 @@ import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
||||||
import * as useStore from '../store' // pptist-状态管理
|
import * as useStore from '../store' // pptist-状态管理
|
||||||
import ChatWs from '@/plugins/socket' // 聊天socket
|
import ChatWs from '@/plugins/socket' // 聊天socket
|
||||||
import msgUtils from '@/plugins/modal' // 消息工具
|
import msgUtils from '@/plugins/modal' // 消息工具
|
||||||
import * as Fullscreen from '../utils/fullscreen' // 全屏
|
|
||||||
import useExecPlay from '../views/Screen/hooks/useExecPlay' // 播放控制
|
import useExecPlay from '../views/Screen/hooks/useExecPlay' // 播放控制
|
||||||
|
|
||||||
const slidesStore = useStore.useSlidesStore() // 幻灯片-状态管理
|
const slidesStore = useStore.useSlidesStore() // 幻灯片-状态管理
|
||||||
|
@ -31,10 +30,9 @@ export class Classcourse {
|
||||||
console.log('classcourse-load', classcourse)
|
console.log('classcourse-load', classcourse)
|
||||||
// 打开全屏
|
// 打开全屏
|
||||||
const isCourse = !!classcourse
|
const isCourse = !!classcourse
|
||||||
if (isCourse) Fullscreen.enterFullscreen()
|
|
||||||
screenStore.setScreening(isCourse)
|
screenStore.setScreening(isCourse)
|
||||||
// 如果课堂信息有值,则连接socket
|
// 如果课堂信息有值,则连接socket
|
||||||
if (!!classcourse) {
|
if (isCourse) {
|
||||||
// 连接socket
|
// 连接socket
|
||||||
if (!ChatWs.ws) ChatWs.init()
|
if (!ChatWs.ws) ChatWs.init()
|
||||||
ChatWs.id = classcourse.timgroupid // 群组id
|
ChatWs.id = classcourse.timgroupid // 群组id
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
* @author zdg
|
* @author zdg
|
||||||
* @date 2024-11-26
|
* @date 2024-11-26
|
||||||
*/
|
*/
|
||||||
import { toRaw } from 'vue'
|
import { toRaw, nextTick } from 'vue'
|
||||||
import type { Result } from './types' // 接口类型
|
import type { Result } from './types' // 接口类型
|
||||||
import msgUtils from '@/plugins/modal' // 消息工具
|
import msgUtils from '@/plugins/modal' // 消息工具
|
||||||
import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api
|
import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api
|
||||||
|
@ -12,7 +12,8 @@ import * as useStore from '../store' // pptist-状态管理
|
||||||
import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
||||||
import useUserStore from '@/store/modules/user' // 外部-用户信息
|
import useUserStore from '@/store/modules/user' // 外部-用户信息
|
||||||
import * as Api_server from '@/api/apiService' // 相关api
|
import * as Api_server from '@/api/apiService' // 相关api
|
||||||
import * as commUtils from '@/utils/comm.js'
|
import * as commUtils from '@/utils/comm.js' // 工具
|
||||||
|
import { toPng, toJpeg } from 'html-to-image' // 引入html-to-image库
|
||||||
const slidesStore = useStore.useSlidesStore()
|
const slidesStore = useStore.useSlidesStore()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
@ -133,6 +134,9 @@ export class PPTApi {
|
||||||
|
|
||||||
const currentSlide = toRaw(slidesStore.currentSlide)
|
const currentSlide = toRaw(slidesStore.currentSlide)
|
||||||
const isAdd = !/^\d+$/.test(currentSlide.id) // 是否新增
|
const isAdd = !/^\d+$/.test(currentSlide.id) // 是否新增
|
||||||
|
const currInd = toRaw(slidesStore.slideIndex) // 当前页索引-new
|
||||||
|
const oldInd = oldData.findIndex(o => o.id == currentSlide.id) // 当前页索引-old
|
||||||
|
const isBatch = oldVal && oldVal.length && currInd != oldInd // 是否批量更新-排序
|
||||||
if (isAdd) { // 新增的幻灯片(id 为非数字,说明是新增的幻灯片)
|
if (isAdd) { // 新增的幻灯片(id 为非数字,说明是新增的幻灯片)
|
||||||
const bool = await this.addSlide(currentSlide)
|
const bool = await this.addSlide(currentSlide)
|
||||||
bool && await this.batchUpdateSlides(newData, true) // 批量更新-排序
|
bool && await this.batchUpdateSlides(newData, true) // 批量更新-排序
|
||||||
|
@ -140,6 +144,9 @@ export class PPTApi {
|
||||||
await PPTApi.getSlideList(resource.id)
|
await PPTApi.getSlideList(resource.id)
|
||||||
} else { // 防抖-更新
|
} else { // 防抖-更新
|
||||||
if (!this.isUpdate) return this.isUpdate = true // 下次更新数据
|
if (!this.isUpdate) return this.isUpdate = true // 下次更新数据
|
||||||
|
if (isBatch) { // 批量更新-排序
|
||||||
|
this.batchUpdateSlides(newData, true)
|
||||||
|
} else { // 更新当前页幻灯片
|
||||||
const params = {
|
const params = {
|
||||||
id: currentSlide.id,
|
id: currentSlide.id,
|
||||||
datacontent: JSON.stringify(currentSlide),
|
datacontent: JSON.stringify(currentSlide),
|
||||||
|
@ -147,9 +154,12 @@ export class PPTApi {
|
||||||
Utils.mxThrottle(() => {this.updateSlide(params)}, 200, 2)
|
Utils.mxThrottle(() => {this.updateSlide(params)}, 200, 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// 更新幻灯片
|
// 更新幻灯片
|
||||||
static updateSlide(data: object): Promise<Boolean> {
|
static updateSlide(data: object): Promise<Boolean> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
|
const thumUrl = await this.getSlideThumUrl()
|
||||||
|
data.base64Code = thumUrl // 更新缩略图
|
||||||
const res: Result = await API_entpcoursefile.updateEntpcoursefileNew(data)
|
const res: Result = await API_entpcoursefile.updateEntpcoursefileNew(data)
|
||||||
if (res.code === 200) {
|
if (res.code === 200) {
|
||||||
resolve(true)
|
resolve(true)
|
||||||
|
@ -192,7 +202,18 @@ export class PPTApi {
|
||||||
else msgUtils.msgError(res.msg || '更新失败');return false
|
else msgUtils.msgError(res.msg || '更新失败');return false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// thumbnail-slide thumbnail 缩略图
|
||||||
|
static getSlideThumUrl(): Promise<Boolean> {
|
||||||
|
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 (o:any) => {
|
static toRousrceUrl =async (o:any) => {
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
|
@ -203,7 +224,6 @@ export class PPTApi {
|
||||||
url &&(o.src = url)
|
url &&(o.src = url)
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,8 +86,8 @@ export default () => {
|
||||||
case MsgEnum.HEADS.MSG_slideFlapping: // 幻灯片翻页
|
case MsgEnum.HEADS.MSG_slideFlapping: // 幻灯片翻页
|
||||||
const slideIndex = content?.current || 0
|
const slideIndex = content?.current || 0
|
||||||
const type = content?.animation
|
const type = content?.animation
|
||||||
if (type === 'Nextsteps') execPlay.execNext() // 下一步
|
if (type === 'Nextsteps') emitter.emit('useExecPlay', 'execNext') // 下一步
|
||||||
else if (type === 'Previoustep') execPlay.execPrev() // 上一步
|
else if (type === 'Previoustep') emitter.emit('useExecPlay', 'turnPrevSlide') // 上一步清空-动画
|
||||||
else slidesStore.updateSlideIndex(slideIndex) // 更新幻灯片下标
|
else slidesStore.updateSlideIndex(slideIndex) // 更新幻灯片下标
|
||||||
break
|
break
|
||||||
case MsgEnum.HEADS.MSG_homework: // 作业|活动-布置
|
case MsgEnum.HEADS.MSG_homework: // 作业|活动-布置
|
||||||
|
|
|
@ -100,7 +100,6 @@ const {
|
||||||
execNext,
|
execNext,
|
||||||
animationIndex,
|
animationIndex,
|
||||||
} = useExecPlay()
|
} = useExecPlay()
|
||||||
|
|
||||||
const { slideWidth, slideHeight } = useSlideSize()
|
const { slideWidth, slideHeight } = useSlideSize()
|
||||||
const { exitScreening } = useScreening()
|
const { exitScreening } = useScreening()
|
||||||
const { fullscreenState, manualExitFullscreen } = useFullscreen()
|
const { fullscreenState, manualExitFullscreen } = useFullscreen()
|
||||||
|
@ -197,6 +196,37 @@ const contextmenus = (): ContextmenuItem[] => {
|
||||||
emitter.on('upvoteTrigger', (type) => {
|
emitter.on('upvoteTrigger', (type) => {
|
||||||
upvoteRef.value?.trigger(type)
|
upvoteRef.value?.trigger(type)
|
||||||
});
|
});
|
||||||
|
// zdg: 使用方法才生效
|
||||||
|
const execPlay = {
|
||||||
|
autoPlayTimer,
|
||||||
|
autoPlay,
|
||||||
|
closeAutoPlay,
|
||||||
|
autoPlayInterval,
|
||||||
|
setAutoPlayInterval,
|
||||||
|
loopPlay,
|
||||||
|
setLoopPlay,
|
||||||
|
mousewheelListener,
|
||||||
|
touchStartListener,
|
||||||
|
touchEndListener,
|
||||||
|
turnPrevSlide,
|
||||||
|
turnNextSlide,
|
||||||
|
turnSlideToIndex,
|
||||||
|
turnSlideToId,
|
||||||
|
execPrev,
|
||||||
|
execNext,
|
||||||
|
animationIndex,
|
||||||
|
}
|
||||||
|
emitter.on('useExecPlay', (data: string|any) => {
|
||||||
|
if (!data) throw new Error('参数错误')
|
||||||
|
if (typeof data === 'string') { // 字符串
|
||||||
|
if (execPlay[data]) execPlay[data]()
|
||||||
|
else throw new Error('方法不存在')
|
||||||
|
} else { // 对象
|
||||||
|
const { method, ...params } = data || {}
|
||||||
|
if (execPlay[method]) execPlay[method](...params)
|
||||||
|
else throw new Error('方法不存在')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -174,9 +174,8 @@ export default () => {
|
||||||
|
|
||||||
// 鼠标滚动翻页
|
// 鼠标滚动翻页
|
||||||
const mousewheelListener = throttle(function(e: WheelEvent) {
|
const mousewheelListener = throttle(function(e: WheelEvent) {
|
||||||
e.preventDefault() // 阻止默认事件
|
if (e.deltaY < 0) turning(e, 'prev')
|
||||||
if (e.deltaY < 0) execPrev()
|
else if (e.deltaY > 0) turning(e, 'next')
|
||||||
else if (e.deltaY > 0) execNext()
|
|
||||||
}, 500, { leading: true, trailing: false })
|
}, 500, { leading: true, trailing: false })
|
||||||
|
|
||||||
// 触摸屏上下滑动翻页
|
// 触摸屏上下滑动翻页
|
||||||
|
@ -197,24 +196,28 @@ export default () => {
|
||||||
const offsetY = e.changedTouches[0].clientY - touchInfo.value.y
|
const offsetY = e.changedTouches[0].clientY - touchInfo.value.y
|
||||||
if ( Math.abs(offsetY) > offsetX && Math.abs(offsetY) > 50 ) {
|
if ( Math.abs(offsetY) > offsetX && Math.abs(offsetY) > 50 ) {
|
||||||
touchInfo.value = null
|
touchInfo.value = null
|
||||||
if (offsetY > 0) execPrev()
|
if (offsetY > 0) turning(e, 'prev')
|
||||||
else execNext()
|
else turning(e, 'next')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 向上翻页/向下翻页
|
||||||
|
const turning = (e, type) => {
|
||||||
|
e.preventDefault() // 阻止默认事件
|
||||||
|
if (type === 'prev') execPrev()
|
||||||
|
else if (type === 'next') execNext()
|
||||||
|
}
|
||||||
// 快捷键翻页
|
// 快捷键翻页
|
||||||
const keydownListener = (e: KeyboardEvent) => {
|
const keydownListener = (e: KeyboardEvent) => {
|
||||||
e.preventDefault() // 阻止默认事件
|
|
||||||
const key = e.key.toUpperCase()
|
const key = e.key.toUpperCase()
|
||||||
|
|
||||||
if (key === KEYS.UP || key === KEYS.LEFT || key === KEYS.PAGEUP) execPrev()
|
if (key === KEYS.UP || key === KEYS.LEFT || key === KEYS.PAGEUP) turning(e, 'prev')
|
||||||
else if (
|
else if (
|
||||||
key === KEYS.DOWN ||
|
key === KEYS.DOWN ||
|
||||||
key === KEYS.RIGHT ||
|
key === KEYS.RIGHT ||
|
||||||
key === KEYS.SPACE ||
|
key === KEYS.SPACE ||
|
||||||
key === KEYS.ENTER ||
|
key === KEYS.ENTER ||
|
||||||
key === KEYS.PAGEDOWN
|
key === KEYS.PAGEDOWN
|
||||||
) execNext()
|
) turning(e, 'next')
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => document.addEventListener('keydown', keydownListener))
|
onMounted(() => document.addEventListener('keydown', keydownListener))
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<div style="font-size: 18px; display: flex; flex-wrap: nowrap">
|
<div style="font-size: 18px; display: flex; flex-wrap: nowrap">
|
||||||
<div style="flex: 1">
|
<div style="flex: 1">
|
||||||
{{ classWorkAnalysis.title }}完成情况
|
{{ classWorkAnalysis.title }}完成情况
|
||||||
<el-tag :type="classWorkAnalysis.workclass" size="large" style="height: 25px">{{
|
<el-tag :type="classWorkAnalysis.workclass||'info'" size="large" style="height: 25px">{{
|
||||||
classWorkAnalysis.worktype
|
classWorkAnalysis.worktype
|
||||||
}}</el-tag>
|
}}</el-tag>
|
||||||
</div>
|
</div>
|
||||||
|
@ -726,6 +726,7 @@ const msgHandle = (msg) => {
|
||||||
openDialog(data, false);
|
openDialog(data, false);
|
||||||
break
|
break
|
||||||
case MsgEnum.HEADS.MSG_slideFlapping: // 切换页面
|
case MsgEnum.HEADS.MSG_slideFlapping: // 切换页面
|
||||||
|
console.log('切换页面-关闭窗口')
|
||||||
window.close() // 关闭窗口
|
window.close() // 关闭窗口
|
||||||
break
|
break
|
||||||
// case 'TIMAddRecvNewMsgCallback': // 收到新消息 data=[]
|
// case 'TIMAddRecvNewMsgCallback': // 收到新消息 data=[]
|
||||||
|
@ -765,6 +766,7 @@ onMounted(() => {
|
||||||
|
|
||||||
// im监听消息
|
// im监听消息
|
||||||
if (ChatWs.ws) {
|
if (ChatWs.ws) {
|
||||||
|
console.log('socket监听消息')
|
||||||
ChatWs.watch((msg, e) => {
|
ChatWs.watch((msg, e) => {
|
||||||
try {
|
try {
|
||||||
msgHandle(JSON.parse(msg))
|
msgHandle(JSON.parse(msg))
|
||||||
|
|
Loading…
Reference in New Issue