Compare commits
72 Commits
Author | SHA1 | Date |
---|---|---|
zhangxuelin | 2463feb0b7 | |
zhangxuelin | d866f546bc | |
baigl | 991bbd179f | |
白了个白 | bf39850d2f | |
白了个白 | 0f51892d96 | |
zhengdegang | 2224de7144 | |
zdg | 14cf608c62 | |
zdg | eca310928e | |
zhangxuelin | 35e63e3587 | |
zhengdegang | 52f9a1493d | |
zdg | 0acde1952c | |
zdg | 719693bf63 | |
zhangxuelin | 1999104ee4 | |
zhangxuelin | 65643279ce | |
baigl | 53ccb2236e | |
白了个白 | 00119e4a49 | |
白了个白 | 4bbe89ed31 | |
zhangxuelin | 49e16c458f | |
zhangxuelin | 5fb447d5e6 | |
yangws | 9aa17ed786 | |
小杨 | 2a7fbc3577 | |
白了个白 | ccbafea3d4 | |
白了个白 | 1f9111a89d | |
“zouyf” | be78520410 | |
“zouyf” | 4b935b9110 | |
zhangxuelin | d0cbb5cbcd | |
zhangxuelin | 5686669563 | |
zhangxuelin | eb7d6df355 | |
白了个白 | 1a3598d7c0 | |
白了个白 | 2fdd997c5e | |
lyc | 960ab581c3 | |
“zouyf” | 96e01ae711 | |
“zouyf” | d8c4876119 | |
zhangxuelin | ae839825d4 | |
zhangxuelin | ef670dee99 | |
朱浩 | c81f393715 | |
zhangxuelin | 06bb6284c4 | |
朱浩 | b5caa7ba80 | |
朱浩 | 53ff508635 | |
“zouyf” | d9a0f2f8c3 | |
“zouyf” | 89cba04b8c | |
zouyf | 9cce9c224c | |
“zouyf” | 171dc72ee7 | |
zhangxuelin | c2750e3da6 | |
zhangxuelin | 5550ca570c | |
“zouyf” | dd0160865b | |
“zouyf” | ff0dd3600c | |
lyc | 62a419356c | |
zhangxuelin | ab9bad467a | |
zhengdegang | f63bb69919 | |
zdg | b3ffa9bdaa | |
zdg | 5510021566 | |
lyc | 89e0b2f97c | |
lyc | ea0e1c91cf | |
zhangxuelin | a366d5d4d6 | |
zhangxuelin | e0ec22c3ac | |
“zouyf” | 63b8a0d5c6 | |
“zouyf” | f6b08169b6 | |
“zouyf” | af60c5cc17 | |
“zouyf” | e67756192a | |
“zouyf” | 73d4ee03ba | |
“zouyf” | 8863e05a1a | |
“zouyf” | debd5e1942 | |
“zouyf” | c8b8c21875 | |
“zouyf” | c8729a7008 | |
“zouyf” | 2bdac6e2ea | |
“zouyf” | 058509b29c | |
“zouyf” | 9a2a55c62b | |
“zouyf” | 19efe185c5 | |
“zouyf” | 78ecf6ea55 | |
“zouyf” | cccf109499 | |
“zouyf” | 4a0e9b0b84 |
|
@ -17,6 +17,7 @@ VITE_APP_RES_FILE_PATH = 'https://file.ysaix.com:7868/src/assets/textbook/booktx
|
||||||
VITE_APP_BUILD_BASE_PATH = 'https://file.ysaix.com:7868/'
|
VITE_APP_BUILD_BASE_PATH = 'https://file.ysaix.com:7868/'
|
||||||
|
|
||||||
# websocket 地址
|
# websocket 地址
|
||||||
|
# VITE_APP_WS_URL = 'wss://prev.ysaix.com:7868'
|
||||||
VITE_APP_WS_URL = 'wss://file.ysaix.com:7868'
|
VITE_APP_WS_URL = 'wss://file.ysaix.com:7868'
|
||||||
# VITE_APP_WS_URL = 'ws://192.168.2.16:7865'
|
# VITE_APP_WS_URL = 'ws://192.168.2.16:7865'
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "aix-win-ws",
|
"name": "aix-win-ws",
|
||||||
"version": "2.5.8",
|
"version": "2.5.9",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "上海交大重庆人工智能研究院",
|
"author": "上海交大重庆人工智能研究院",
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
export default class gridPic {
|
||||||
|
private static Instance: gridPic | null = null;
|
||||||
|
private gridPicRef: any = null;
|
||||||
|
|
||||||
|
constructor(elRef?: any) {
|
||||||
|
if (elRef) {
|
||||||
|
this.gridPicRef = elRef;
|
||||||
|
}
|
||||||
|
if (!gridPic.Instance) {
|
||||||
|
gridPic.Instance = this;
|
||||||
|
}
|
||||||
|
return gridPic.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化
|
||||||
|
init(elRef) {
|
||||||
|
if (elRef) {
|
||||||
|
this.gridPicRef = elRef;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
addPIc(data) {
|
||||||
|
if (this.gridPicRef && this.gridPicRef.value && typeof this.gridPicRef.value.addPic === 'function') {
|
||||||
|
this.gridPicRef.value.addPic(data);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 静态方法 - 初始化
|
||||||
|
static init(elRef) {
|
||||||
|
if (!gridPic.Instance) {
|
||||||
|
gridPic.Instance = new gridPic(elRef);
|
||||||
|
} else {
|
||||||
|
gridPic.Instance.init(elRef);
|
||||||
|
}
|
||||||
|
return gridPic.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 静态方法 - 打开推图上屏幕
|
||||||
|
static addPIc(data) {
|
||||||
|
if (gridPic.Instance) {
|
||||||
|
return gridPic.Instance.addPIc(data);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -97,14 +97,30 @@ export class PPTApi {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 批量插入slide
|
||||||
|
* @param slides 批量新增的幻灯片
|
||||||
|
* @param slideAll 所有幻灯片
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
static async addSlideServer(slides: object[], slideAll: object[]) {
|
||||||
|
const resource = sessionStore.get('curr.resource')||{}
|
||||||
|
for(const slide of slides){
|
||||||
|
slide.id = resource.id // 覆盖默认随机id
|
||||||
|
await this.addSlide(slide)
|
||||||
|
}
|
||||||
|
await this.batchUpdateSlides(slideAll, true) // 批量更新-排序
|
||||||
|
return PPTApi.getSlideList(resource.id) // 更新幻灯片列表以及活动相关
|
||||||
|
}
|
||||||
|
|
||||||
// 新增幻灯片
|
// 新增幻灯片
|
||||||
static addSlide(data: object): Promise<Boolean> {
|
static addSlide(data: object): Promise<Boolean> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
const enpt = sessionStore.get('curr.entp')||{}
|
const enpt = sessionStore.get('curr.entp')||{}
|
||||||
const resource = sessionStore.get('curr.resource')||{}
|
// const resource = sessionStore.get('curr.resource')||{}
|
||||||
const {id, ...content} = data
|
const {id, ...content} = data
|
||||||
const params = {
|
const params = {
|
||||||
parentid: resource.id,
|
parentid: id,
|
||||||
entpid: userStore.user.deptId,
|
entpid: userStore.user.deptId,
|
||||||
entpcourseid: enpt.id,
|
entpcourseid: enpt.id,
|
||||||
ppttype: 'file',
|
ppttype: 'file',
|
||||||
|
@ -126,7 +142,7 @@ export class PPTApi {
|
||||||
// msgUtils.msgSuccess('新增成功')
|
// msgUtils.msgSuccess('新增成功')
|
||||||
this.isUpdate = false // 新增后会触发监听,不再更新数据
|
this.isUpdate = false // 新增后会触发监听,不再更新数据
|
||||||
resolve(true)
|
resolve(true)
|
||||||
} else msgUtils.msgError('新增失败');resolve(false)
|
} else msgUtils.msgError('新增失败');reject(false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -147,12 +163,8 @@ export class PPTApi {
|
||||||
const currInd = toRaw(slidesStore.slideIndex) // 当前页索引-new
|
const currInd = toRaw(slidesStore.slideIndex) // 当前页索引-new
|
||||||
const oldInd = oldData.findIndex(o => o.id == currentSlide.id) // 当前页索引-old
|
const oldInd = oldData.findIndex(o => o.id == currentSlide.id) // 当前页索引-old
|
||||||
const isBatch = oldVal && oldVal.length && currInd != oldInd // 是否批量更新-排序
|
const isBatch = oldVal && oldVal.length && currInd != oldInd // 是否批量更新-排序
|
||||||
if (isAdd) { // 新增的幻灯片(id 为非数字,说明是新增的幻灯片)
|
if (isAdd) return // 新增-这里不处理 状态管理-处理
|
||||||
const bool = await this.addSlide(currentSlide)
|
// 防抖-更新
|
||||||
bool && await this.batchUpdateSlides(newData, true) // 批量更新-排序
|
|
||||||
const resource = sessionStore.get('curr.resource')||{}
|
|
||||||
await PPTApi.getSlideList(resource.id)
|
|
||||||
} else { // 防抖-更新
|
|
||||||
if (!this.isUpdate) return this.isUpdate = true // 下次更新数据
|
if (!this.isUpdate) return this.isUpdate = true // 下次更新数据
|
||||||
if (isBatch) { // 批量更新-排序
|
if (isBatch) { // 批量更新-排序
|
||||||
this.batchUpdateSlides(newData, true)
|
this.batchUpdateSlides(newData, true)
|
||||||
|
@ -164,7 +176,6 @@ export class PPTApi {
|
||||||
Utils.mxThrottle(() => {this.updateSlide(params)}, 200, 2)
|
Utils.mxThrottle(() => {this.updateSlide(params)}, 200, 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// 更新幻灯片 isThum 是否更新缩略图
|
// 更新幻灯片 isThum 是否更新缩略图
|
||||||
static updateSlide(data: object, isThum = true): Promise<Boolean> {
|
static updateSlide(data: object, isThum = true): Promise<Boolean> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
|
@ -274,6 +285,7 @@ export class PPTApi {
|
||||||
static toRousrceUrl =async (o:any) => {
|
static toRousrceUrl =async (o:any) => {
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('file', o)
|
formData.append('file', o)
|
||||||
|
formData.append('ral', true)
|
||||||
const res = await Api_server.Other.uploadFile(formData)
|
const res = await Api_server.Other.uploadFile(formData)
|
||||||
if (res && res.code == 200){
|
if (res && res.code == 200){
|
||||||
const url = res?.url
|
const url = res?.url
|
||||||
|
|
|
@ -132,6 +132,8 @@ export class MsgEnum {
|
||||||
MSG_dz : 'dz',
|
MSG_dz : 'dz',
|
||||||
/** @desc: 疑惑 */
|
/** @desc: 疑惑 */
|
||||||
MSG_yh : 'yh',
|
MSG_yh : 'yh',
|
||||||
|
/** @desc: 推图片上屏 */
|
||||||
|
MSG_pushSreen_ImgList : 'pushSreen_ImgList',
|
||||||
// === 新定义-消息头 ===
|
// === 新定义-消息头 ===
|
||||||
/** @desc: 课程创建-待开课 */
|
/** @desc: 课程创建-待开课 */
|
||||||
MSG_0000: 0x0000,
|
MSG_0000: 0x0000,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* @description 公共监听器
|
* @description 公共监听器
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { watch } from 'vue'
|
import { watch, render } from 'vue'
|
||||||
import { PPTApi } from './index'
|
import { PPTApi } from './index'
|
||||||
import * as store from '../store'
|
import * as store from '../store'
|
||||||
import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
||||||
|
@ -12,9 +12,10 @@ import Classcourse from './classcourse' // 课程相关
|
||||||
import msgUtils from '@/plugins/modal' // 消息工具
|
import msgUtils from '@/plugins/modal' // 消息工具
|
||||||
import * as dialogUtils from '@/utils/dialog' // 弹窗-函数
|
import * as dialogUtils from '@/utils/dialog' // 弹窗-函数
|
||||||
import { Homework } from './index' // api-作业相关
|
import { Homework } from './index' // api-作业相关
|
||||||
// import emitter from '@/utils/mitt' //mitt 事件总线
|
import emitter from '@/utils/mitt' //mitt 事件总线
|
||||||
import useExecPlay from '../views/Screen/hooks/useExecPlay' // 播放控制
|
import useExecPlay from '../views/Screen/hooks/useExecPlay' // 播放控制
|
||||||
import hooksUpvote from './upvote' // 点赞-工具
|
import hooksUpvote from './upvote' // 点赞-工具
|
||||||
|
import gridPic from './gridPic' // 上屏-工具
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 监听器
|
* @description 监听器
|
||||||
|
@ -98,6 +99,8 @@ export default () => {
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case MsgEnum.HEADS.MSG_slideFlapping: // 幻灯片翻页
|
case MsgEnum.HEADS.MSG_slideFlapping: // 幻灯片翻页
|
||||||
|
render(null, document.body) //移除弹窗
|
||||||
|
emitter.emit('closegridPic') //如果有推图片窗口 就关闭
|
||||||
const slideIndex = content?.current || 0
|
const slideIndex = content?.current || 0
|
||||||
const type = content?.animation // 上下动作
|
const type = content?.animation // 上下动作
|
||||||
const steps = content?.animationSteps // 动画步骤
|
const steps = content?.animationSteps // 动画步骤
|
||||||
|
@ -128,6 +131,10 @@ export default () => {
|
||||||
case MsgEnum.HEADS.MSG_yh: // 疑惑
|
case MsgEnum.HEADS.MSG_yh: // 疑惑
|
||||||
hooksUpvote.trigger(2)
|
hooksUpvote.trigger(2)
|
||||||
break
|
break
|
||||||
|
case MsgEnum.HEADS.MSG_pushSreen_ImgList: // 推图片上屏
|
||||||
|
const imgArray = content.ImgList.map((obj) => obj.url);
|
||||||
|
emitter.emit('opengridPic',{arr:imgArray}) // 打开推图片上屏窗口
|
||||||
|
break
|
||||||
case MsgEnum.HEADS.MSG_0010: // 备用
|
case MsgEnum.HEADS.MSG_0010: // 备用
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { useScreenStore, useSlidesStore, useClasscourseStore } from '../store'
|
import { useScreenStore, useSlidesStore, useClasscourseStore } from '../store'
|
||||||
import { enterFullscreen, exitFullscreen, isFullscreen } from '../utils/fullscreen'
|
import { enterFullscreen, exitFullscreen, isFullscreen } from '../utils/fullscreen'
|
||||||
|
import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
||||||
import ChatWs from '@/plugins/socket' // 聊天socket
|
import ChatWs from '@/plugins/socket' // 聊天socket
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
|
@ -25,6 +26,9 @@ export default () => {
|
||||||
if (!!classcourse) { //DOTO 有课堂,执行退相关操作
|
if (!!classcourse) { //DOTO 有课堂,执行退相关操作
|
||||||
console.log('退出放映状态')
|
console.log('退出放映状态')
|
||||||
ChatWs?.close() // 关闭ws
|
ChatWs?.close() // 关闭ws
|
||||||
|
sessionStore.delete('curr.classcourse') // 清除课堂信息
|
||||||
|
sessionStore.delete('curr.resource') // 清除课件信息
|
||||||
|
sessionStore.delete('curr.isPublic') // 清除公屏状态
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.close() // 关闭窗口
|
window.close() // 关闭窗口
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
|
@ -148,7 +148,8 @@ export const useSlidesStore = defineStore('slides', {
|
||||||
this.workItem = list
|
this.workItem = list
|
||||||
},
|
},
|
||||||
|
|
||||||
addSlide(slide: Slide | Slide[]) {
|
async addSlide(slide: Slide | Slide[]) {
|
||||||
|
const { PPTApi } = await import('../api/index')
|
||||||
const slides = Array.isArray(slide) ? slide : [slide]
|
const slides = Array.isArray(slide) ? slide : [slide]
|
||||||
for (const slide of slides) {
|
for (const slide of slides) {
|
||||||
if (slide.sectionTag) delete slide.sectionTag
|
if (slide.sectionTag) delete slide.sectionTag
|
||||||
|
@ -156,6 +157,8 @@ export const useSlidesStore = defineStore('slides', {
|
||||||
const addIndex = this.slideIndex + 1
|
const addIndex = this.slideIndex + 1
|
||||||
this.slides.splice(addIndex, 0, ...slides)
|
this.slides.splice(addIndex, 0, ...slides)
|
||||||
this.slideIndex = addIndex
|
this.slideIndex = addIndex
|
||||||
|
// 添加到服务器
|
||||||
|
PPTApi.addSlideServer(slides, this.slides)
|
||||||
},
|
},
|
||||||
updateSlide(props: Partial<Slide>, slideId?: string) {
|
updateSlide(props: Partial<Slide>, slideId?: string) {
|
||||||
const slideIndex = slideId ? this.slides.findIndex(item => item.id === slideId) : this.slideIndex
|
const slideIndex = slideId ? this.slides.findIndex(item => item.id === slideId) : this.slideIndex
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<PopoverMenuItem>导入 pptx 文件</PopoverMenuItem>
|
<PopoverMenuItem>导入 pptx 文件</PopoverMenuItem>
|
||||||
</FileInput>
|
</FileInput>
|
||||||
<PopoverMenuItem @click="setDialogForExport('pptx')">导出文件</PopoverMenuItem> -->
|
<PopoverMenuItem @click="setDialogForExport('pptx')">导出文件</PopoverMenuItem> -->
|
||||||
<PopoverMenuItem @click="resetSlides(); mainMenuVisible = false">重置幻灯片</PopoverMenuItem>
|
<!-- <PopoverMenuItem @click="resetSlides(); mainMenuVisible = false">重置幻灯片</PopoverMenuItem> -->
|
||||||
<!-- <PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/issues')">意见反馈</PopoverMenuItem> -->
|
<!-- <PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/issues')">意见反馈</PopoverMenuItem> -->
|
||||||
<!-- <PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/blob/master/doc/Q&A.md')">常见问题</PopoverMenuItem> -->
|
<!-- <PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/blob/master/doc/Q&A.md')">常见问题</PopoverMenuItem> -->
|
||||||
<PopoverMenuItem @click="mainMenuVisible = false; hotkeyDrawerVisible = true">快捷操作</PopoverMenuItem>
|
<PopoverMenuItem @click="mainMenuVisible = false; hotkeyDrawerVisible = true">快捷操作</PopoverMenuItem>
|
||||||
|
|
|
@ -88,7 +88,7 @@ import Button from '../../../../components/Button.vue'
|
||||||
import ButtonGroup from '../../../../components/ButtonGroup.vue'
|
import ButtonGroup from '../../../../components/ButtonGroup.vue'
|
||||||
import Popover from '../../../../components/Popover.vue'
|
import Popover from '../../../../components/Popover.vue'
|
||||||
import NumberInput from '../../../../components/NumberInput.vue'
|
import NumberInput from '../../../../components/NumberInput.vue'
|
||||||
|
import { PPTApi } from '../../../../api'
|
||||||
const shapeClipPathOptions = CLIPPATHS
|
const shapeClipPathOptions = CLIPPATHS
|
||||||
const ratioClipOptions = [
|
const ratioClipOptions = [
|
||||||
{
|
{
|
||||||
|
@ -221,10 +221,14 @@ const presetImageClip = (shape: string, ratio = 0) => {
|
||||||
const replaceImage = (files: FileList) => {
|
const replaceImage = (files: FileList) => {
|
||||||
const imageFile = files[0]
|
const imageFile = files[0]
|
||||||
if (!imageFile) return
|
if (!imageFile) return
|
||||||
getImageDataURL(imageFile).then(dataURL => {
|
PPTApi.toRousrceUrl(imageFile).then(data=>{
|
||||||
const props = { src: dataURL }
|
const props = { src: data }
|
||||||
updateImage(props)
|
updateImage(props)
|
||||||
})
|
})
|
||||||
|
// getImageDataURL(imageFile).then(dataURL => {
|
||||||
|
// const props = { src: dataURL }
|
||||||
|
// updateImage(props)
|
||||||
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置图片:清除全部样式
|
// 重置图片:清除全部样式
|
||||||
|
|
|
@ -47,8 +47,9 @@
|
||||||
<IconListView class="tool-btn" v-tooltip="'演讲者视图'" @click="changeViewMode('presenter')" />
|
<IconListView class="tool-btn" v-tooltip="'演讲者视图'" @click="changeViewMode('presenter')" />
|
||||||
<IconOffScreenOne class="tool-btn" v-tooltip="'退出全屏'" v-if="fullscreenState" @click="manualExitFullscreen()" />
|
<IconOffScreenOne class="tool-btn" v-tooltip="'退出全屏'" v-if="fullscreenState" @click="manualExitFullscreen()" />
|
||||||
<IconFullScreenOne class="tool-btn" v-tooltip="'进入全屏'" v-else @click="enterFullscreen()" />
|
<IconFullScreenOne class="tool-btn" v-tooltip="'进入全屏'" v-else @click="enterFullscreen()" />
|
||||||
<IconPower class="tool-btn" v-tooltip="'结束放映'" @click="exitScreening()" />
|
<IconPower class="tool-btn" v-if="!classcourse" v-tooltip="'结束放映'" @click="exitScreening()" />
|
||||||
<IconPower class="tool-btn close" v-if="chat.groupid" v-tooltip="'结束课堂'" @click="exitCourse()" />
|
<IconPower class="tool-btn" v-else v-tooltip="'结束课堂'" @click="exitCourse()" size="30" fill="#d0021b" strokeLinecap="butt" />
|
||||||
|
<Share class="tool-btn" v-if="classcourse" v-tooltip="'分享'" @click="ShareCode()" />
|
||||||
</div>
|
</div>
|
||||||
<div :class="['tools-icon',{opacity:iconHide}]" @click.stop="toolTrigger('icon')">
|
<div :class="['tools-icon',{opacity:iconHide}]" @click.stop="toolTrigger('icon')">
|
||||||
<circle-double-down v-if="rightToolsVisible" theme="outline" size="30" fill="#409EFF"/>
|
<circle-double-down v-if="rightToolsVisible" theme="outline" size="30" fill="#409EFF"/>
|
||||||
|
@ -75,7 +76,8 @@ import WritingBoardTool from './WritingBoardTool.vue'
|
||||||
import CountdownTimer from './CountdownTimer.vue'
|
import CountdownTimer from './CountdownTimer.vue'
|
||||||
import emitter from '@/utils/mitt';
|
import emitter from '@/utils/mitt';
|
||||||
import Chat from '../../api/chat' // 聊天
|
import Chat from '../../api/chat' // 聊天
|
||||||
import { CircleDoubleDown, CircleDoubleUp } from '@icon-park/vue-next' // icon-park 图标库
|
import { CircleDoubleDown, CircleDoubleUp, Share } from '@icon-park/vue-next' // icon-park 图标库
|
||||||
|
import { ShareCode } from '@/utils/ppt' // ppt相关
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
changeViewMode: (mode: 'base' | 'presenter') => void
|
changeViewMode: (mode: 'base' | 'presenter') => void
|
||||||
|
@ -198,7 +200,7 @@ const contextmenus = (): ContextmenuItem[] => {
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
// 工具栏按钮触发
|
||||||
const toolTrigger = (type:string) => {
|
const toolTrigger = (type:string) => {
|
||||||
const curT = Date.now()
|
const curT = Date.now()
|
||||||
if (curT - timer.value < 200) return
|
if (curT - timer.value < 200) return
|
||||||
|
|
|
@ -10,9 +10,10 @@
|
||||||
<IconOffScreenOne class="tool-icon" v-else />
|
<IconOffScreenOne class="tool-icon" v-else />
|
||||||
<span>{{ fullscreenState ? '退出全屏' : '全屏' }}</span>
|
<span>{{ fullscreenState ? '退出全屏' : '全屏' }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="tool-btn" @click="ShareCode()"><Share class="tool-icon" /><span>分享</span></div>
|
||||||
<Divider class="divider" />
|
<Divider class="divider" />
|
||||||
<div class="tool-btn" @click="exitScreening()"><IconPower class="tool-icon" /><span>结束放映</span></div>
|
<div class="tool-btn" v-if="!classcourse" @click="exitScreening()"><IconPower class="tool-icon" /><span>结束放映</span></div>
|
||||||
<div class="tool-btn close" @click="exitCourse()" v-if="chat.groupid"><IconPower class="tool-icon" /><span>结束课堂</span></div>
|
<div class="tool-btn" v-else @click="exitCourse()" size="30" fill="#d0021b" strokeLinecap="butt"><IconPower class="tool-icon" /><span>结束课堂</span></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
@ -78,6 +79,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
|
import { Share } from '@icon-park/vue-next' // icon-park 图标库
|
||||||
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { useSlidesStore, useClasscourseStore } from '../../store'
|
import { useSlidesStore, useClasscourseStore } from '../../store'
|
||||||
|
@ -97,6 +99,7 @@ import CountdownTimer from './CountdownTimer.vue'
|
||||||
import Divider from '../../components/Divider.vue'
|
import Divider from '../../components/Divider.vue'
|
||||||
import emitter from '@/utils/mitt';
|
import emitter from '@/utils/mitt';
|
||||||
import Chat from '../../api/chat' // 聊天
|
import Chat from '../../api/chat' // 聊天
|
||||||
|
import { ShareCode } from '@/utils/ppt' // ppt相关
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
changeViewMode: (mode: 'base' | 'presenter') => void
|
changeViewMode: (mode: 'base' | 'presenter') => void
|
||||||
|
@ -125,7 +128,7 @@ const { slideWidth, slideHeight } = useSlideSize(slideListWrapRef)
|
||||||
const { exitScreening } = useScreening()
|
const { exitScreening } = useScreening()
|
||||||
const { slidesLoadLimit } = useLoadSlides()
|
const { slidesLoadLimit } = useLoadSlides()
|
||||||
const { fullscreenState, manualExitFullscreen } = useFullscreen()
|
const { fullscreenState, manualExitFullscreen } = useFullscreen()
|
||||||
const chat:any = Chat() // 聊天室
|
const chatApi:any = Chat() // 聊天室
|
||||||
|
|
||||||
const remarkFontSize = ref(16)
|
const remarkFontSize = ref(16)
|
||||||
const currentSlideRemark = computed(() => {
|
const currentSlideRemark = computed(() => {
|
||||||
|
@ -134,15 +137,20 @@ const currentSlideRemark = computed(() => {
|
||||||
|
|
||||||
// 切换到指定的幻灯片
|
// 切换到指定的幻灯片
|
||||||
const turnSlideTo = (index: number, e: PointerEvent) => {
|
const turnSlideTo = (index: number, e: PointerEvent) => {
|
||||||
// 课堂信息存在时,不允许翻页
|
const preInd = slideIndex.value
|
||||||
console.log('课堂信息', classcourse, index)
|
|
||||||
if (!!classcourse.value) return
|
|
||||||
turnSlideToIndex(index)
|
turnSlideToIndex(index)
|
||||||
|
if (!!classcourse.value) {// 上课中
|
||||||
|
if (preInd == index) return
|
||||||
|
const animationSteps = 0
|
||||||
|
const animation = index > preInd?'Nextsteps':'Previoustep'
|
||||||
|
const msg = { current:index, animation, animationSteps}
|
||||||
|
chatApi.slideFlapping(msg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 下课
|
// 下课
|
||||||
const exitCourse = async () => {
|
const exitCourse = async () => {
|
||||||
// console.log('下课', chat)
|
// console.log('下课', chat)
|
||||||
await chat.exitCourse() // 下课消息
|
await chatApi.exitCourse() // 下课消息
|
||||||
exitScreening() // 结束放映
|
exitScreening() // 结束放映
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,21 @@
|
||||||
<upvote-vue ref="upvoteRef" type="2"></upvote-vue>
|
<upvote-vue ref="upvoteRef" type="2"></upvote-vue>
|
||||||
<!-- <div style="z-index: 999;position: absolute;top:10px">
|
<!-- <div style="z-index: 999;position: absolute;top:10px">
|
||||||
</div> -->
|
</div> -->
|
||||||
|
<!-- 推图上屏弹窗 -->
|
||||||
|
<el-dialog
|
||||||
|
v-model="dialogVisible"
|
||||||
|
:fullscreen="true"
|
||||||
|
class="gridPicRefdiv"
|
||||||
|
style="overflow: hidden;"
|
||||||
|
:show-close="false"
|
||||||
|
>
|
||||||
|
<grid-pic ref="gridPicRef" style="height:100%;" @clear="clearchidrenPic"></grid-pic>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, onUnmounted, ref } from 'vue'
|
import { onMounted, onUnmounted, ref , nextTick} from 'vue'
|
||||||
import { KEYS } from '../../configs/hotkey'
|
import { KEYS } from '../../configs/hotkey'
|
||||||
import useScreening from '../../hooks/useScreening'
|
import useScreening from '../../hooks/useScreening'
|
||||||
import hooksUpvote from '../../api/upvote' // 点赞-工具
|
import hooksUpvote from '../../api/upvote' // 点赞-工具
|
||||||
|
@ -18,9 +28,13 @@ import hooksUpvote from '../../api/upvote' // 点赞-工具
|
||||||
import BaseView from './BaseView.vue'
|
import BaseView from './BaseView.vue'
|
||||||
import PresenterView from './PresenterView.vue'
|
import PresenterView from './PresenterView.vue'
|
||||||
import upvoteVue from '@/views/tool/components/upvote.vue' // 点赞-子组件
|
import upvoteVue from '@/views/tool/components/upvote.vue' // 点赞-子组件
|
||||||
|
import gridPic from '@/components/grid-pic/index.vue' // 推图上屏弹子组件
|
||||||
|
|
||||||
|
import emitter from '@/utils/mitt' //mitt 事件总线
|
||||||
|
|
||||||
const viewMode = ref<'base' | 'presenter'>('base')
|
const viewMode = ref<'base' | 'presenter'>('base')
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const gridPicRef:any= ref(null)
|
||||||
const changeViewMode = (mode: 'base' | 'presenter') => {
|
const changeViewMode = (mode: 'base' | 'presenter') => {
|
||||||
viewMode.value = mode
|
viewMode.value = mode
|
||||||
}
|
}
|
||||||
|
@ -35,6 +49,23 @@ const keydownListener = (e: KeyboardEvent) => {
|
||||||
if (key === KEYS.ESC) exitScreening()
|
if (key === KEYS.ESC) exitScreening()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const clearchidrenPic= ()=> {
|
||||||
|
dialogVisible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开启推图上屏幕
|
||||||
|
emitter.on('opengridPic', async (data:object)=> {
|
||||||
|
if(gridPicRef.value) gridPicRef.value.clearPic()
|
||||||
|
dialogVisible.value = true
|
||||||
|
await nextTick();
|
||||||
|
gridPicRef.value.addPic(data.arr)
|
||||||
|
});
|
||||||
|
// 关闭推图
|
||||||
|
emitter.on('closegridPic', ()=> {
|
||||||
|
if(!gridPicRef.value) return
|
||||||
|
gridPicRef.value.clearPic()
|
||||||
|
dialogVisible.value = false
|
||||||
|
});
|
||||||
onMounted(() => document.addEventListener('keydown', keydownListener))
|
onMounted(() => document.addEventListener('keydown', keydownListener))
|
||||||
onUnmounted(() => document.removeEventListener('keydown', keydownListener))
|
onUnmounted(() => document.removeEventListener('keydown', keydownListener))
|
||||||
</script>
|
</script>
|
||||||
|
@ -46,4 +77,8 @@ onUnmounted(() => document.removeEventListener('keydown', keydownListener))
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:deep(.gridPicRefdiv .el-dialog__body){
|
||||||
|
height: 100% !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -71,6 +71,14 @@ export function updateClassworkeval(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function updateClassworkevalList(data) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classworkeval/updateList',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 修改classworkdata
|
// 修改classworkdata
|
||||||
export function updateClassworkdata(data) {
|
export function updateClassworkdata(data) {
|
||||||
return request({
|
return request({
|
||||||
|
@ -80,6 +88,15 @@ export function updateClassworkdata(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 批阅后, 待所有学生都批改完成后自动结束当前作业为[已完成]
|
||||||
|
export function updateClassWorkDataAutoFinish(data) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classworkdata/updAutoFinish',
|
||||||
|
method: 'put',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 修改classwork
|
// 修改classwork
|
||||||
export function updateClasswork(data) {
|
export function updateClasswork(data) {
|
||||||
return request({
|
return request({
|
||||||
|
|
|
@ -136,3 +136,17 @@ export function getJYPath(url,config) {
|
||||||
params: config.params
|
params: config.params
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc: 百度识图转发
|
||||||
|
* @return: {*}
|
||||||
|
* @param {*} data
|
||||||
|
*/
|
||||||
|
export function getOcrContent(data) {
|
||||||
|
return request({
|
||||||
|
url: '/ocr/exam',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
|
@ -102,4 +102,16 @@ export function setPaging(data) {
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 获取分享码(邀请码)
|
||||||
|
* @param {*} id 课堂id
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export function getShareCode(id) {
|
||||||
|
return request({
|
||||||
|
url: '/education/classcourse/refresh/code',
|
||||||
|
method: 'post',
|
||||||
|
data: { id }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<i class="iconfont icon-xiangyou"></i>
|
<i class="iconfont icon-xiangyou"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="book-list" v-loading="treeLoading">
|
<div class="book-list" v-loading="treeLoading">
|
||||||
<el-tree :data="treeData" accordion :props="defaultProps" node-key="id"
|
<el-tree :data="treeData" accordion :props="defaultProps" node-key="id" :render-content="renderContent"
|
||||||
:default-expanded-keys="defaultExpandedKeys" :current-node-key="curNode.data.id" highlight-current
|
:default-expanded-keys="defaultExpandedKeys" :current-node-key="curNode.data.id" highlight-current
|
||||||
@node-click="handleNodeClick">
|
@node-click="handleNodeClick">
|
||||||
<template #default="{ node }">
|
<template #default="{ node }">
|
||||||
|
@ -178,6 +178,18 @@ const handleNodeClick = (data) => {
|
||||||
sessionStore.set('subject.curNode', nodeData)
|
sessionStore.set('subject.curNode', nodeData)
|
||||||
emit('nodeClick', curData)
|
emit('nodeClick', curData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const renderContent = (h, { node, data, store }) => {
|
||||||
|
return h(
|
||||||
|
'span',
|
||||||
|
{
|
||||||
|
style: {
|
||||||
|
color: data.bookId==''||data.bookId=='0' ? '#A5B3CA' : 'black',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
node.label
|
||||||
|
);
|
||||||
|
}
|
||||||
onMounted( async () => {
|
onMounted( async () => {
|
||||||
treeLoading.value = true
|
treeLoading.value = true
|
||||||
try{
|
try{
|
||||||
|
|
|
@ -16,15 +16,15 @@
|
||||||
<draggable handle=".header-btn" :draggable="false" item-key="backgroundColor" v-model="gridPicList" class="grid-pic-wrap" :style="getGrid">
|
<draggable handle=".header-btn" :draggable="false" item-key="backgroundColor" v-model="gridPicList" class="grid-pic-wrap" :style="getGrid">
|
||||||
<template #item="{ element, index }">
|
<template #item="{ element, index }">
|
||||||
<div class="grid-pic-item" :key="element.backgroundColor" :style="getWH(element,index)">
|
<div class="grid-pic-item" :key="element.backgroundColor" :style="getWH(element,index)">
|
||||||
<div class="delete-btn" @click="gridPicList.splice(index,1)">X</div>
|
<div class="delete-btn" @click="()=>{gridPicList.splice(index,1);if(!gridPicList.length) emits('clear')} ">X</div>
|
||||||
<div class="header-btn"></div>
|
<div class="header-btn"></div>
|
||||||
<ViewerItem :gridPicList="gridPicList" :index="index" :images="element"></ViewerItem>
|
<ViewerItem :gridPicList="gridPicList" :index="index" :images="element"></ViewerItem>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</draggable>
|
</draggable>
|
||||||
<div v-if="showToolbar" class="grid-pic-toolbar">
|
<div class="grid-pic-toolbar">
|
||||||
<el-input style="width: 500px" v-model="inputValue" type="text" />
|
<el-input v-if="showToolbar" style="width: 500px" v-model="inputValue" type="text" />
|
||||||
<el-button class="add-btn" @click="pushPic">
|
<el-button v-if="showToolbar" class="add-btn" @click="pushPic">
|
||||||
添加
|
添加
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button class="add-btn" @click="clearPic">
|
<el-button class="add-btn" @click="clearPic">
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
showToolbar: {
|
showToolbar: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// 获取图片样式
|
// 获取图片样式
|
||||||
|
@ -149,20 +149,26 @@
|
||||||
addPic(src)
|
addPic(src)
|
||||||
}
|
}
|
||||||
// 添加图片
|
// 添加图片
|
||||||
const addPic = (src) => {
|
const addPic = (data) => {
|
||||||
if (gridPicList.value.length >= 9) {
|
let list = Array.isArray(data)?data:[data]
|
||||||
|
if (gridPicList.value.length + list.length > 9) {
|
||||||
console.log("超出九个图片")
|
console.log("超出九个图片")
|
||||||
emits('outIndex')
|
emits('outIndex')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
let listArr = [];
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
let src = list[i]
|
||||||
if (!src) {
|
if (!src) {
|
||||||
console.log("图片链接不能为空")
|
console.log("图片链接不能为空")
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gridPicList.value.push({
|
listArr.push({
|
||||||
src: src,
|
src: src,
|
||||||
backgroundColor: getRandomColor()
|
backgroundColor: getRandomColor()
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
gridPicList.value.push(...listArr)
|
||||||
inputValue.value = ''
|
inputValue.value = ''
|
||||||
}
|
}
|
||||||
// 清空图片
|
// 清空图片
|
||||||
|
|
|
@ -140,5 +140,8 @@ watch(props.images, (newValue, oldValue) => {
|
||||||
.viewer-item-wrap{
|
.viewer-item-wrap{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
:deep(.viewer-canvas img) {
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="whiteboart-container" :style="{ height: height + 'px' }">
|
<div class="whiteboart-container" :style="{ height: height + 'px' }">
|
||||||
<div class="canvasBox" ref="box"></div>
|
<div class="canvasBox" ref="box" @mouseenter.capture="handleMouseEnter" @mouseleave.capture="handleMouseLeave"></div>
|
||||||
|
|
||||||
<div class="footerLeft" @click.stop
|
<div class="footerLeft" @click.stop
|
||||||
:style="type == 'design' ? ['top: 10px', 'justify-content: space-between'] : ['bottom: 10px', 'justify-content: center']">
|
:style="type == 'design' ? ['top: 10px', 'justify-content: space-between'] : ['bottom: 10px', 'justify-content: center']">
|
||||||
|
@ -278,7 +278,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, watch, toRaw, nextTick, computed, reactive, defineProps, defineEmits } from 'vue'
|
import { onMounted, onBeforeUnmount, ref, getCurrentInstance, watch, toRaw, nextTick, computed, reactive, defineProps, defineEmits } from 'vue'
|
||||||
import TinyWhiteboard from 'whiteboard_lyc'
|
import TinyWhiteboard from 'whiteboard_lyc'
|
||||||
import ColorPicker from './components/ColorPicker.vue'
|
import ColorPicker from './components/ColorPicker.vue'
|
||||||
import {
|
import {
|
||||||
|
@ -305,6 +305,7 @@ import { fontFamilyList, fontSizeList } from './constants'
|
||||||
|
|
||||||
const borderImg = new URL('../../../src/assets/images/borderwidth.png', import.meta.url).href
|
const borderImg = new URL('../../../src/assets/images/borderwidth.png', import.meta.url).href
|
||||||
const pointerImg = new URL('../../../src/assets/images/mouse-pointer.png', import.meta.url).href
|
const pointerImg = new URL('../../../src/assets/images/mouse-pointer.png', import.meta.url).href
|
||||||
|
const { proxy } = getCurrentInstance()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
|
@ -507,10 +508,6 @@ const backToCenter = () => {
|
||||||
app.scrollToCenter()
|
app.scrollToCenter()
|
||||||
}
|
}
|
||||||
|
|
||||||
const cancelActiveElement = () =>{
|
|
||||||
app.cancelActiveElement()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 显示全部
|
// 显示全部
|
||||||
const showFit = () => {
|
const showFit = () => {
|
||||||
|
@ -716,6 +713,13 @@ watch(() => props.data, (newVal) => {
|
||||||
|
|
||||||
// dom元素挂载完成
|
// dom元素挂载完成
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
init();
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化画布内容
|
||||||
|
*/
|
||||||
|
const init = () => {
|
||||||
// 创建实例
|
// 创建实例
|
||||||
app = new TinyWhiteboard({
|
app = new TinyWhiteboard({
|
||||||
container: box.value,
|
container: box.value,
|
||||||
|
@ -737,6 +741,7 @@ onMounted(() => {
|
||||||
})
|
})
|
||||||
// 监听元素激活事件
|
// 监听元素激活事件
|
||||||
app.on('activeElementChange', element => {
|
app.on('activeElementChange', element => {
|
||||||
|
console.log('点击元素 监听 activeElementChange-----------')
|
||||||
if (activeElement.value) {
|
if (activeElement.value) {
|
||||||
activeElement.value.off('elementRotateChange', onElementRotateChange)
|
activeElement.value.off('elementRotateChange', onElementRotateChange)
|
||||||
}
|
}
|
||||||
|
@ -784,7 +789,39 @@ onMounted(() => {
|
||||||
app.resize()
|
app.resize()
|
||||||
}, 300)
|
}, 300)
|
||||||
})
|
})
|
||||||
})
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const isMyCanvas = ref(false); // 鼠标 是否进入画布判断
|
||||||
|
const handleKeyDown=(event)=> {
|
||||||
|
// console.log('键盘按键被按下:', event.key);
|
||||||
|
// console.log(isMyCanvas.value,'??????????')
|
||||||
|
if(isMyCanvas.value == false){
|
||||||
|
event.stopPropagation();
|
||||||
|
// console.log('键盘事件被捕获,已阻止冒泡:', event.key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 鼠标进入事件
|
||||||
|
*/
|
||||||
|
const handleMouseEnter = () => {
|
||||||
|
console.log('进入白板')
|
||||||
|
isMyCanvas.value = true;
|
||||||
|
document.addEventListener('keydown', handleKeyDown, true);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 课堂展示-鼠标离开白板监听事件:该事件是避免,选中状态,在其他地方点击、后退、删除等事件,会删除白板内选中的元素
|
||||||
|
*/
|
||||||
|
const handleMouseLeave = () => {
|
||||||
|
console.log('离开白板')
|
||||||
|
// 清除激活项--点击事件的激活项
|
||||||
|
app.cancelActiveElement()
|
||||||
|
// 阻止 点击拖动范围的取消激活项……
|
||||||
|
isMyCanvas.value = false;
|
||||||
|
// 确保事件处理函数在组件挂载后绑定
|
||||||
|
document.addEventListener('keydown', handleKeyDown, true);
|
||||||
|
};
|
||||||
|
|
||||||
// 暴露方法
|
// 暴露方法
|
||||||
defineExpose({
|
defineExpose({
|
||||||
|
@ -795,7 +832,6 @@ defineExpose({
|
||||||
getCanvasBase64,
|
getCanvasBase64,
|
||||||
setCanvasData,
|
setCanvasData,
|
||||||
getCanvasBlob,
|
getCanvasBlob,
|
||||||
cancelActiveElement
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { listEntpcoursework,getEvaluationclue } from '@/api/classTask';
|
import { listEntpcoursework,getEvaluationclue } from '@/api/classTask';
|
||||||
import { processList } from '@/hooks/useProcessList';
|
import { processList } from '@/hooks/useProcessList';
|
||||||
|
import useClassTaskStore from '@/store/modules/classTask'
|
||||||
|
const useClassTaskStores = useClassTaskStore();
|
||||||
|
|
||||||
const isJson = (str) => {
|
const isJson = (str) => {
|
||||||
if (typeof str == 'string') {
|
if (typeof str == 'string') {
|
||||||
|
@ -114,6 +116,14 @@ export const editListItem = (row, courseObj) => {
|
||||||
}
|
}
|
||||||
else if (row.worktype == '科学实验') {
|
else if (row.worktype == '科学实验') {
|
||||||
if(isJson(row.workcodes)){
|
if(isJson(row.workcodes)){
|
||||||
|
// 同步更新实验内部的科目信息
|
||||||
|
if (row.worktag && row.worktag.indexOf('-') > -1){
|
||||||
|
const eduInfo = row.worktag.split('-');
|
||||||
|
useClassTaskStores.experimentObj.edustage = eduInfo[0];
|
||||||
|
useClassTaskStores.experimentObj.edusubject = eduInfo[1];
|
||||||
|
useClassTaskStores.experimentObj.updateEduInfo = row.worktag;
|
||||||
|
}
|
||||||
|
// 更新科学实验内容
|
||||||
classtaskObj.fileHomeworkList = JSON.parse(row.workcodes);
|
classtaskObj.fileHomeworkList = JSON.parse(row.workcodes);
|
||||||
//
|
//
|
||||||
// console.log('科学实验', classtaskObj);
|
// console.log('科学实验', classtaskObj);
|
||||||
|
|
|
@ -299,21 +299,28 @@ export const processList = (row, aloneOption=false) => {
|
||||||
if(!aloneOption && j%2== 0){
|
if(!aloneOption && j%2== 0){
|
||||||
tmp += '</div>';
|
tmp += '</div>';
|
||||||
}
|
}
|
||||||
row[i].workdescFormat = tmp
|
row[i].workdescFormat = tmp;
|
||||||
|
|
||||||
// 处理[答案显示] - 转换ABCD
|
// 处理[答案显示] - 转换ABCD
|
||||||
let arr2Char = workAnswerArr
|
let arr2Char = workAnswerArr
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
return String.fromCharCode(65 + Number(item))
|
return String.fromCharCode(65 + Number(item))
|
||||||
})
|
})
|
||||||
.join('')
|
.join('');
|
||||||
row[i].workanswerFormat = arr2Char
|
row[i].workanswerFormat = arr2Char;
|
||||||
} else if (row[i].worktype == '填空题') {
|
} else if (row[i].worktype == '填空题') {
|
||||||
// 处理[选项显示] - 填空题中无选项, 故置空
|
// 处理[选项显示] - 填空题中无选项, 故置空
|
||||||
row[i].workdescFormat = ''
|
row[i].workdescFormat = '';
|
||||||
|
|
||||||
// 处理[答案显示] - 逗号连接
|
// 处理[答案显示] - 逗号连接
|
||||||
row[i].workanswerFormat = workAnswerArr.join('、')
|
|
||||||
|
// 当[答案显示]为 [<div] 开头时,不再需逗号连接(一般为自主上传, 当前答案每个自带div标签)
|
||||||
|
let linkChar = '、';
|
||||||
|
if (workAnswerArr.length != 0 && workAnswerArr[0].indexOf('<div') == 0) {
|
||||||
|
linkChar = '';
|
||||||
|
}
|
||||||
|
row[i].workanswerFormat = workAnswerArr.join(linkChar);
|
||||||
|
|
||||||
} else if (row[i].worktype == '判断题') {
|
} else if (row[i].worktype == '判断题') {
|
||||||
// 处理[选项显示] - 判断题中无选项, 故置空
|
// 处理[选项显示] - 判断题中无选项, 故置空
|
||||||
row[i].workdescFormat = ''
|
row[i].workdescFormat = ''
|
||||||
|
|
|
@ -7,8 +7,9 @@ const useClassTaskStore = defineStore('classTask',{
|
||||||
state: () => ({
|
state: () => ({
|
||||||
experimentObj:{
|
experimentObj:{
|
||||||
edustage: '小学', // 教育阶段
|
edustage: '小学', // 教育阶段
|
||||||
edusubject: '', // 学科
|
edusubject: '数学', // 学科
|
||||||
experimentList: [], // 实验科目列表
|
experimentList: [], // 实验科目列表
|
||||||
|
updateEduInfo: '小学-数学', //实际需上传的学段+学科信息(用于上传及回显实验内的学段学科)
|
||||||
},
|
},
|
||||||
isOpenQuestUploadView: false, // 是否打开习题上传的页面
|
isOpenQuestUploadView: false, // 是否打开习题上传的页面
|
||||||
classListIds: [],
|
classListIds: [],
|
||||||
|
|
|
@ -6,6 +6,10 @@ import { toPng, toJpeg } from 'html-to-image' // 引入html-to-image库
|
||||||
import { PPTXFileToJson } from "@/AixPPTist/src/hooks/useImport"
|
import { PPTXFileToJson } from "@/AixPPTist/src/hooks/useImport"
|
||||||
import ThumbnailSlide from '@/AixPPTist/src/views/components/ThumbnailSlide/index.vue'
|
import ThumbnailSlide from '@/AixPPTist/src/views/components/ThumbnailSlide/index.vue'
|
||||||
import { useSlidesStore } from '@/AixPPTist/src/store'
|
import { useSlidesStore } from '@/AixPPTist/src/store'
|
||||||
|
import * as ElementPlus from 'element-plus'
|
||||||
|
import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
||||||
|
import * as Http_Classcourse from '@/api/teaching/classcourse' // api接口
|
||||||
|
|
||||||
// 延时
|
// 延时
|
||||||
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
|
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
|
||||||
|
|
||||||
|
@ -85,3 +89,43 @@ export const pptToImg = async(file, options) => {
|
||||||
const { slides } = await PPTXFileToJson(file)
|
const { slides } = await PPTXFileToJson(file)
|
||||||
return slidesToImg(slides, options)
|
return slidesToImg(slides, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 课堂-分享码
|
||||||
|
*/
|
||||||
|
export const ShareCode = async(code, cb) => {
|
||||||
|
let shareCode
|
||||||
|
if (typeof code =='string') shareCode = code
|
||||||
|
else { // 自动获取邀请码
|
||||||
|
const classcourse = sessionStore.get('curr.classcourse') // 课堂信息
|
||||||
|
if (!classcourse) return ElementPlus.ElMessage.warning('没有课堂信息')
|
||||||
|
const isRefresh = typeof code == 'boolean' && code // 是否刷新邀请码
|
||||||
|
shareCode = classcourse.shareCode
|
||||||
|
if (!shareCode || isRefresh) { // 获取邀请码
|
||||||
|
const res = await Http_Classcourse.getShareCode(classcourse.id)
|
||||||
|
shareCode = res.msg
|
||||||
|
// 更新邀请码
|
||||||
|
sessionStore.set('curr.classcourse.shareCode', shareCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const msg = h('div', [
|
||||||
|
h('h1', [`我的邀请码:`, h('b',{style:{color:'#F56C6C',fontSize:'1.5em'}}, shareCode)]),
|
||||||
|
h('div', {style:{color:'#E6A23C',fontSize:'13px'}}, `该邀请码1小时内有效,请在学生端填写邀请码后即可进入课堂。`)
|
||||||
|
])
|
||||||
|
return ElementPlus.ElMessageBox.alert(msg, '分享课程', {
|
||||||
|
confirmButtonText: '更新',
|
||||||
|
cancelButtonText: '关闭',
|
||||||
|
showCancelButton: true,
|
||||||
|
|
||||||
|
beforeClose: (action, instance, done) => {
|
||||||
|
if (action =='confirm') { // 更新
|
||||||
|
if (!!cb) { // 回调
|
||||||
|
cb({ h, instance, action, done }, done) && done()
|
||||||
|
} else { // 默认更新
|
||||||
|
ShareCode(true)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
} else done()
|
||||||
|
}
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
|
@ -435,7 +435,7 @@ import useUserStore from '@/store/modules/user'
|
||||||
import { ref, reactive } from 'vue'
|
import { ref, reactive } from 'vue'
|
||||||
// import { Plus } from '@element-plus/icons-vue'
|
// import { Plus } from '@element-plus/icons-vue'
|
||||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||||
import { updateClassworkeval, updateClassworkdata, getClassworkdata } from '@/api/classTask'
|
import { getClassworkdata, updateClassworkevalList, updateClassWorkDataAutoFinish } from '@/api/classTask'
|
||||||
import { getTimeDate } from '@/utils/date'
|
import { getTimeDate } from '@/utils/date'
|
||||||
import ReFilePreview from '@/components/refile-preview/index.vue'
|
import ReFilePreview from '@/components/refile-preview/index.vue'
|
||||||
import { quizStrToList } from '@/utils/comm';
|
import { quizStrToList } from '@/utils/comm';
|
||||||
|
@ -890,12 +890,12 @@ const onSubmit = () => {
|
||||||
updatedate: getTimeDate(),// = year+'-'+month+'-'+day+' '+hh+':'+mm;
|
updatedate: getTimeDate(),// = year+'-'+month+'-'+day+' '+hh+':'+mm;
|
||||||
};
|
};
|
||||||
// 更新作业批改状态
|
// 更新作业批改状态
|
||||||
updateClassworkdata(formd).then(res => {
|
updateClassWorkDataAutoFinish(formd).then(res => {
|
||||||
})
|
})
|
||||||
|
|
||||||
// 更新题目批改
|
// 更新题目批改
|
||||||
classWorkFormScore.teacherRating &&
|
const queryList = [];
|
||||||
classWorkFormScore.teacherRating.map((item, index) => {
|
classWorkFormScore.teacherRating && classWorkFormScore.teacherRating.map((item, index) => {
|
||||||
const queryParams = {
|
const queryParams = {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
teacherRating: item.score, // 教师评分
|
teacherRating: item.score, // 教师评分
|
||||||
|
@ -903,13 +903,32 @@ const onSubmit = () => {
|
||||||
teacherremark: classWorkFormScore.teacherremark, //评分说明
|
teacherremark: classWorkFormScore.teacherremark, //评分说明
|
||||||
timestamp: getTimeDate() // 时间
|
timestamp: getTimeDate() // 时间
|
||||||
}
|
}
|
||||||
console.log(queryParams)
|
queryList.push(queryParams)
|
||||||
updateClassworkeval(queryParams).then((res) => {
|
})
|
||||||
|
//console.log('queryList->', queryList)
|
||||||
|
updateClassworkevalList(queryList).then((res) => {
|
||||||
// if(res.code == 200){
|
// if(res.code == 200){
|
||||||
// 循环提交能干个啥
|
// 循环提交能干个啥
|
||||||
// }
|
// }
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
// 更新题目批改
|
||||||
|
// classWorkFormScore.teacherRating &&
|
||||||
|
// classWorkFormScore.teacherRating.map((item, index) => {
|
||||||
|
// const queryParams = {
|
||||||
|
// id: item.id,
|
||||||
|
// teacherRating: item.score, // 教师评分
|
||||||
|
// rating: classWorkFormScore.rating, // 评价
|
||||||
|
// teacherremark: classWorkFormScore.teacherremark, //评分说明
|
||||||
|
// timestamp: getTimeDate() // 时间
|
||||||
|
// }
|
||||||
|
// console.log(queryParams)
|
||||||
|
// updateClassworkeval(queryParams).then((res) => {
|
||||||
|
// // if(res.code == 200){
|
||||||
|
// // 循环提交能干个啥
|
||||||
|
// // }
|
||||||
|
// })
|
||||||
|
// })
|
||||||
ElMessage({
|
ElMessage({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: '提交成功!'
|
message: '提交成功!'
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="知识点" label-width="70">
|
<el-form-item label="知识点" label-width="70">
|
||||||
<el-cascader
|
<el-cascader
|
||||||
|
disabled
|
||||||
v-model="entpCourseWorkQueryParams.point"
|
v-model="entpCourseWorkQueryParams.point"
|
||||||
clearable
|
clearable
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
|
@ -172,7 +173,7 @@
|
||||||
<!-- 非习题训练:常规作业、 -->
|
<!-- 非习题训练:常规作业、 -->
|
||||||
<div v-if="classWorkForm.worktype!='习题训练'">
|
<div v-if="classWorkForm.worktype!='习题训练'">
|
||||||
<div :style="{ 'overflow': 'auto'}">
|
<div :style="{ 'overflow': 'auto'}">
|
||||||
<template v-if="classWorkForm.worktype!='常规作业'">
|
<!-- <template v-if="classWorkForm.worktype!='常规作业'">
|
||||||
<template v-for="(item, index) in workResource.teachResourceList" :key="item">
|
<template v-for="(item, index) in workResource.teachResourceList" :key="item">
|
||||||
<div v-if="item.worktype==classWorkForm.worktype" style="border-bottom: 1px dotted;display: flex;justify-content: space-between;">
|
<div v-if="item.worktype==classWorkForm.worktype" style="border-bottom: 1px dotted;display: flex;justify-content: space-between;">
|
||||||
<div style="margin-bottom: 5px; padding-left: 15px;display: flex;flex-direction: row;align-items: center;">
|
<div style="margin-bottom: 5px; padding-left: 15px;display: flex;flex-direction: row;align-items: center;">
|
||||||
|
@ -193,7 +194,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template> -->
|
||||||
<template v-if="classWorkForm.worktype =='常规作业'">
|
<template v-if="classWorkForm.worktype =='常规作业'">
|
||||||
<div v-loading="fileLoading" class="upload-homework">
|
<div v-loading="fileLoading" class="upload-homework">
|
||||||
<FileUpload v-model="classWorkForm.fileHomeworkList" :fileSize="800" :fileType="['mp3','mp4','doc','docx','xlsx','xls','pdf','ppt','pptx','jpg','jpeg','gif','png','txt']"/>
|
<FileUpload v-model="classWorkForm.fileHomeworkList" :fileSize="800" :fileType="['mp3','mp4','doc','docx','xlsx','xls','pdf','ppt','pptx','jpg','jpeg','gif','png','txt']"/>
|
||||||
|
@ -285,6 +286,7 @@ import { updateClasswork, listEvaluationclue, listClassworkeval,delClassworkeval
|
||||||
import { listEvaluation } from '@/api/subject'
|
import { listEvaluation } from '@/api/subject'
|
||||||
import { listEntpcoursefile } from '@/api/education/entpcoursefile'
|
import { listEntpcoursefile } from '@/api/education/entpcoursefile'
|
||||||
import { listKnowledgePoint } from "@/api/knowledge/knowledgePoint";
|
import { listKnowledgePoint } from "@/api/knowledge/knowledgePoint";
|
||||||
|
import { isJson } from "@/utils/comm";
|
||||||
|
|
||||||
|
|
||||||
import { useGetHomework } from '@/hooks/useGetHomework'
|
import { useGetHomework } from '@/hooks/useGetHomework'
|
||||||
|
@ -459,12 +461,13 @@ const client = new Apis('/paht');
|
||||||
*/
|
*/
|
||||||
const t = function(name, time) {
|
const t = function(name, time) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
const evalId = props.bookobj.levelSecondId=='' ? props.bookobj.levelFirstId : props.bookobj.levelSecondId;
|
||||||
const queryForm = {
|
const queryForm = {
|
||||||
// 分页参数
|
// 分页参数
|
||||||
currentPage: paginationParams.pageNum,
|
currentPage: paginationParams.pageNum,
|
||||||
pageSize: paginationParams.pageSize,
|
pageSize: paginationParams.pageSize,
|
||||||
// 课程相关参数
|
// 课程相关参数
|
||||||
eid: props.bookobj.levelSecondId,
|
eid: evalId, // 当前单元或章节id
|
||||||
sectionName: props.bookobj.coursetitle,
|
sectionName: props.bookobj.coursetitle,
|
||||||
edusubject: userStore.edusubject,
|
edusubject: userStore.edusubject,
|
||||||
edustage: userStore.edustage,
|
edustage: userStore.edustage,
|
||||||
|
@ -557,10 +560,13 @@ const getQueryFromEvaluationclue = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clueres.rows[i].childlist != '') {
|
if (clueres.rows[i].childlist != '') {
|
||||||
clueres.rows[i].childArray = JSON.parse('['+clueres.rows[i].childlist+']');
|
const tmpJson = '['+clueres.rows[i].childlist+']';
|
||||||
|
if (isJson(tmpJson)){
|
||||||
|
clueres.rows[i].childArray = JSON.parse(tmpJson);
|
||||||
for (var j=0; j<clueres.rows[i].childArray.length; j++) {
|
for (var j=0; j<clueres.rows[i].childArray.length; j++) {
|
||||||
clueres.rows[i].childArray[j].title = clueres.rows[i].childArray[j].title.replace(/(<([^>]+)>)/ig, '');
|
clueres.rows[i].childArray[j].title = clueres.rows[i].childArray[j].title.replace(/(<([^>]+)>)/ig, '');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
clueres.rows[i].childArray = {};
|
clueres.rows[i].childArray = {};
|
||||||
}
|
}
|
||||||
|
@ -990,6 +996,8 @@ const initPageParams = () => {
|
||||||
|
|
||||||
|
|
||||||
onMounted(async() => {
|
onMounted(async() => {
|
||||||
|
// 知识点
|
||||||
|
getEntpCourseWorkPointList();
|
||||||
})
|
})
|
||||||
|
|
||||||
// const refreshData = () => {
|
// const refreshData = () => {
|
||||||
|
@ -1016,9 +1024,9 @@ const debounceQueryData = debounce(() => {
|
||||||
// 习题资源
|
// 习题资源
|
||||||
handleQueryFromEntpCourseWork(0);
|
handleQueryFromEntpCourseWork(0);
|
||||||
// 框架梳理
|
// 框架梳理
|
||||||
getQueryFromEvaluationclue();
|
//getQueryFromEvaluationclue();
|
||||||
// 知识点
|
// 知识点
|
||||||
getEntpCourseWorkPointList();
|
//getEntpCourseWorkPointList();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
watch(() => props.propsformobj.uniquekey, (newVal) => {
|
watch(() => props.propsformobj.uniquekey, (newVal) => {
|
||||||
|
@ -1027,8 +1035,20 @@ watch(() => props.propsformobj.uniquekey, (newVal) => {
|
||||||
classWorkForm.uniquekey = props.propsformobj.uniquekey?cloneDeep(props.propsformobj.uniquekey):''; // 作业唯一标识 作业名称
|
classWorkForm.uniquekey = props.propsformobj.uniquekey?cloneDeep(props.propsformobj.uniquekey):''; // 作业唯一标识 作业名称
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
watch(() => props.bookobj.levelSecondId, (newVal, oldVal) => {
|
|
||||||
|
|
||||||
|
//watch(() => props.bookobj.levelSecondId, async (newVal, oldVal) => {
|
||||||
|
|
||||||
|
watch([
|
||||||
|
() => props.bookobj.levelFirstId,
|
||||||
|
() => props.bookobj.levelSecondId
|
||||||
|
], ([newLevelSecondId, newLevelFirstId], [oldLevelSecondId, oldLevelFirstId]) => {
|
||||||
console.log(props.bookobj,'课程选择')
|
console.log(props.bookobj,'课程选择')
|
||||||
|
// 默认选择一级单元时, 不自动获取试题, 需手动按钮获取试题
|
||||||
|
if (props.bookobj.levelSecondId == '') {
|
||||||
|
workResource.entpCourseWorkList = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
debounceQueryData();
|
debounceQueryData();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -36,16 +36,24 @@ const props = defineProps({
|
||||||
})
|
})
|
||||||
const value = ref('')
|
const value = ref('')
|
||||||
|
|
||||||
|
const updateLabel = (val) => {
|
||||||
|
value.value = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSelectOption = (option) => {
|
||||||
|
classTaskStore.updateEduInfo = `${classTaskStore.edustage}-${classTaskStore.edusubject}`;
|
||||||
|
console.log('updateEduInfo->', classTaskStore.updateEduInfo);
|
||||||
|
console.log(option,'选择的实验课-------')
|
||||||
|
emit('selectItem', classTaskStore.experimentList.filter(item => item.label === option)[0])
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
})
|
})
|
||||||
|
|
||||||
const onSelectOption = (option) => {
|
defineExpose({
|
||||||
console.log(option,'选择的实验课-------')
|
updateLabel
|
||||||
emit('selectItem', classTaskStore.experimentList.filter(item => item.label === option)[0])
|
})
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
@ -56,7 +56,7 @@ const subjectList = ref([])
|
||||||
const chooseGrade= ref({})
|
const chooseGrade= ref({})
|
||||||
const expList = ref([]) // 当前年级的所有课程
|
const expList = ref([]) // 当前年级的所有课程
|
||||||
const checkList = ref([])// 当前年级对应学科的课程,
|
const checkList = ref([])// 当前年级对应学科的课程,
|
||||||
|
const isLoaded = ref(false);
|
||||||
|
|
||||||
// 获取基础的学科
|
// 获取基础的学科
|
||||||
const getSubject = () => {
|
const getSubject = () => {
|
||||||
|
@ -80,8 +80,15 @@ const getSubject = () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
console.log(subjectList,'subjectList');
|
console.log(subjectList,'subjectList');
|
||||||
|
|
||||||
// 默认读取一个学科
|
// 默认读取一个学科
|
||||||
handleUserEduStage(useClassTaskStore().experimentObj.edustage)
|
const edusubject = useClassTaskStore().experimentObj.edusubject;
|
||||||
|
handleUserEduStage(useClassTaskStore().experimentObj.edustage);
|
||||||
|
// 这里确保第一次初始化时, 该任务是从左侧作业列表中进来而存在指定的学科时, 重新赋值回来.
|
||||||
|
useClassTaskStore().experimentObj.edusubject = edusubject;
|
||||||
|
// 执行完毕后标志位[置位]
|
||||||
|
isLoaded.value = true;
|
||||||
|
//console.log('初始化执行完毕----');
|
||||||
}
|
}
|
||||||
// 展示有 实验科目的学科
|
// 展示有 实验科目的学科
|
||||||
const isExpList = (edusubject) => {
|
const isExpList = (edusubject) => {
|
||||||
|
@ -108,7 +115,8 @@ const isExpList = (edusubject) => {
|
||||||
// 选择学段
|
// 选择学段
|
||||||
const handleUserEduStage = (item) => {
|
const handleUserEduStage = (item) => {
|
||||||
// userStore.edustage = item
|
// userStore.edustage = item
|
||||||
useClassTaskStore().experimentObj.edustage = item
|
useClassTaskStore().experimentObj.edustage = item;
|
||||||
|
|
||||||
//清空操作
|
//清空操作
|
||||||
expList.value = []
|
expList.value = []
|
||||||
if(item === '小学'){
|
if(item === '小学'){
|
||||||
|
@ -117,10 +125,11 @@ const handleUserEduStage = (item) => {
|
||||||
const newSubjectList = subjectList.value.filter(item => item.edustage === '小学');
|
const newSubjectList = subjectList.value.filter(item => item.edustage === '小学');
|
||||||
for(let i in newSubjectList){
|
for(let i in newSubjectList){
|
||||||
const name = newSubjectList[i].itemtitle
|
const name = newSubjectList[i].itemtitle
|
||||||
if(isExpList(name)){
|
if(isExpList(name) && useClassTaskStore().experimentObj.edusubject===name){
|
||||||
useClassTaskStore().experimentObj.edusubject = name;
|
//useClassTaskStore().experimentObj.edusubject = name;
|
||||||
// 更改学科默认与学科下的实验科目
|
// 更改学科默认与学科下的实验科目
|
||||||
handleUserEduSubject(name)
|
handleUserEduSubject(name)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else if(item === '初中'){
|
}else if(item === '初中'){
|
||||||
|
@ -129,10 +138,11 @@ const handleUserEduStage = (item) => {
|
||||||
const newSubjectList = subjectList.value.filter(item => item.edustage === '初中');
|
const newSubjectList = subjectList.value.filter(item => item.edustage === '初中');
|
||||||
for(let i in newSubjectList){
|
for(let i in newSubjectList){
|
||||||
const name = newSubjectList[i].itemtitle
|
const name = newSubjectList[i].itemtitle
|
||||||
if(isExpList(name)){
|
if(isExpList(name) && useClassTaskStore().experimentObj.edusubject===name){
|
||||||
useClassTaskStore().experimentObj.edusubject = name;
|
//useClassTaskStore().experimentObj.edusubject = name;
|
||||||
// 更改学科默认与学科下的实验科目
|
// 更改学科默认与学科下的实验科目
|
||||||
handleUserEduSubject(name)
|
handleUserEduSubject(name)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else if(item === '高中'){
|
}else if(item === '高中'){
|
||||||
|
@ -141,10 +151,11 @@ const handleUserEduStage = (item) => {
|
||||||
const newSubjectList = subjectList.value.filter(item => item.edustage === '高中');
|
const newSubjectList = subjectList.value.filter(item => item.edustage === '高中');
|
||||||
for(let i in newSubjectList){
|
for(let i in newSubjectList){
|
||||||
const name = newSubjectList[i].itemtitle
|
const name = newSubjectList[i].itemtitle
|
||||||
if(isExpList(name)){
|
if(isExpList(name) && useClassTaskStore().experimentObj.edusubject===name){
|
||||||
useClassTaskStore().experimentObj.edusubject = name;
|
//useClassTaskStore().experimentObj.edusubject = name;
|
||||||
// 更改学科默认与学科下的实验科目
|
// 更改学科默认与学科下的实验科目
|
||||||
handleUserEduSubject(name)
|
handleUserEduSubject(name)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,10 +188,59 @@ const handleUserEduSubject = (item) => {
|
||||||
// emit('experlist',checkList.value)
|
// emit('experlist',checkList.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const updateCheckList = async () => {
|
||||||
|
try {
|
||||||
|
await waitForSubjectData();
|
||||||
|
|
||||||
|
//console.log('父组件执行开始-------', );
|
||||||
|
//console.log('experimentObj-> ', useClassTaskStore().experimentObj);
|
||||||
|
// 再执行更新逻辑
|
||||||
|
const edustage = useClassTaskStore().experimentObj.edustage;
|
||||||
|
if(edustage === '小学'){
|
||||||
|
chooseGrade.value = jsonData.data.primary
|
||||||
|
}else if(edustage === '初中'){
|
||||||
|
chooseGrade.value = jsonData.data.junior
|
||||||
|
}else if(edustage === '高中'){
|
||||||
|
chooseGrade.value = jsonData.data.senior
|
||||||
|
}
|
||||||
|
expList.value = chooseGrade.value
|
||||||
|
const edusubject = useClassTaskStore().experimentObj.edusubject;
|
||||||
|
handleUserEduSubject(edusubject);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const waitForSubjectData = () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let timeoutId;
|
||||||
|
let intervalId;
|
||||||
|
|
||||||
|
const checkIsLoaded = () => {
|
||||||
|
if (isLoaded.value) {
|
||||||
|
clearInterval(intervalId);
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
intervalId = setInterval(checkIsLoaded, 100);
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
clearInterval(intervalId);
|
||||||
|
reject(new Error('该作业-等待[科学实验]学科学段初始化超时'));
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getSubject()
|
getSubject()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
updateCheckList
|
||||||
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.custom-button {
|
.custom-button {
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
<div class="activeExp-header">
|
<div class="activeExp-header">
|
||||||
<div class="infomation" v-if="isStadium() !== true" >
|
<div class="infomation" v-if="isStadium() !== true" >
|
||||||
<!-- <selectClass v-if="!isSubject" @experlist="getExperimentList" /> -->
|
<!-- <selectClass v-if="!isSubject" @experlist="getExperimentList" /> -->
|
||||||
<selectClass v-if="!isSubject" />
|
<selectClass ref="selectClassRef"/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<selectExperiment @selectItem="getExperimentListItem" />
|
<selectExperiment ref="selectExperimentRef" @selectItem="getExperimentListItem" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ref="mainDiv" class="activeExp-main" style="overflow: auto">
|
<div ref="mainDiv" class="activeExp-main" style="overflow: auto">
|
||||||
|
@ -44,6 +44,8 @@ const props = defineProps({
|
||||||
// 学科的 实验列
|
// 学科的 实验列
|
||||||
// const experimentList = ref([]);
|
// const experimentList = ref([]);
|
||||||
const activeExp = ref({});
|
const activeExp = ref({});
|
||||||
|
const selectExperimentRef = ref();
|
||||||
|
const selectClassRef = ref();
|
||||||
|
|
||||||
const isStadium = () => {
|
const isStadium = () => {
|
||||||
let roles = userStore.roles
|
let roles = userStore.roles
|
||||||
|
@ -82,6 +84,13 @@ const getExperimentListItem = (val) => {
|
||||||
watch(() => props.expObj.fileurl, (newVal, oldVal) => {
|
watch(() => props.expObj.fileurl, (newVal, oldVal) => {
|
||||||
console.log(props.expObj,'科学实验科目')
|
console.log(props.expObj,'科学实验科目')
|
||||||
activeExp.value = props.expObj;
|
activeExp.value = props.expObj;
|
||||||
|
|
||||||
|
//
|
||||||
|
nextTick(() => {
|
||||||
|
selectClassRef.value.updateCheckList();
|
||||||
|
selectExperimentRef.value.updateLabel(props.expObj.label);
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -68,7 +68,6 @@
|
||||||
</div>
|
</div>
|
||||||
<div v-if="(currentRow.worktype == '课堂展示' || classWorkForm.worktype == '课堂展示') && currentRow.id>0" class="page-center">
|
<div v-if="(currentRow.worktype == '课堂展示' || classWorkForm.worktype == '课堂展示') && currentRow.id>0" class="page-center">
|
||||||
<div v-loading="boardLoading" class="board-wrap" style="height: 100%; flex: 1; overflow: hidden;">
|
<div v-loading="boardLoading" class="board-wrap" style="height: 100%; flex: 1; overflow: hidden;">
|
||||||
<!-- <whiteboard v-if="isShowBoard" ref="boardref" :height="mainHeight - 150" :isShowSave="false" :data="whiteboardObj"/> -->
|
|
||||||
<whiteboard ref="boardref" height="100%" width="100%" :isShowSave="false" :data="classWorkForm.whiteboardObj" />
|
<whiteboard ref="boardref" height="100%" width="100%" :isShowSave="false" :data="classWorkForm.whiteboardObj" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -600,7 +599,8 @@ const handleClassWorkFormQuizRemove = (index) =>{
|
||||||
}
|
}
|
||||||
else if(classWorkForm.worktype === "科学实验"){
|
else if(classWorkForm.worktype === "科学实验"){
|
||||||
if (classWorkForm.fileHomeworkList.length == 0) return ElMessage({ type: 'warning', message: '请选择科学实验的课程!'});
|
if (classWorkForm.fileHomeworkList.length == 0) return ElMessage({ type: 'warning', message: '请选择科学实验的课程!'});
|
||||||
cform.workcodes = JSON.stringify(classWorkForm.fileHomeworkList);
|
cform.worktag = useClassTaskStores.experimentObj.updateEduInfo; // 当前实验的学段学科, 格式为[小学-数学]
|
||||||
|
cform.workcodes = JSON.stringify(classWorkForm.fileHomeworkList); // 实验信息
|
||||||
cform.entpcourseworklist = JSON.stringify([{'id':-3, 'score': '10'}]);
|
cform.entpcourseworklist = JSON.stringify([{'id':-3, 'score': '10'}]);
|
||||||
try {
|
try {
|
||||||
console.log(cform,'科学实验')
|
console.log(cform,'科学实验')
|
||||||
|
@ -807,12 +807,14 @@ const editWork = async (cform) =>{
|
||||||
else if (classWorkForm.worktype=='科学实验') { //TODO 注意,fileHomeworkList字段与常规作业共用
|
else if (classWorkForm.worktype=='科学实验') { //TODO 注意,fileHomeworkList字段与常规作业共用
|
||||||
// 1.更新作业任务下的课堂展示内容 (这里未做校验, 直接将当前文件对象更新过去)
|
// 1.更新作业任务下的课堂展示内容 (这里未做校验, 直接将当前文件对象更新过去)
|
||||||
cform.workcodes = JSON.stringify(classWorkForm.fileHomeworkList);
|
cform.workcodes = JSON.stringify(classWorkForm.fileHomeworkList);
|
||||||
|
cform.worktag = useClassTaskStores.experimentObj.updateEduInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3.更新作业任务本身
|
// 3.更新作业任务本身
|
||||||
let res = await updateClasswork(cform);
|
let res = await updateClasswork(cform);
|
||||||
if (res.code == 200) {
|
if (res.code == 200) {
|
||||||
ElMessage.success('更新成功');
|
ElMessage.success('更新成功');
|
||||||
|
taskList.value = []
|
||||||
// 清空左侧 选中的布置列表 并刷新列表
|
// 清空左侧 选中的布置列表 并刷新列表
|
||||||
if(isShow.value){
|
if(isShow.value){
|
||||||
currentRow.value.id = 1;
|
currentRow.value.id = 1;
|
||||||
|
|
|
@ -129,6 +129,7 @@ import examDetailsDrawer from '@/components/exam-question/examDetailsDrawer.vue'
|
||||||
import QuesItem from "@/views/classTask/newClassTaskAssign/questionUpload/quesItem/index.vue";
|
import QuesItem from "@/views/classTask/newClassTaskAssign/questionUpload/quesItem/index.vue";
|
||||||
import { useHandleData } from "@/hooks/useHandleData";
|
import { useHandleData } from "@/hooks/useHandleData";
|
||||||
import { processList } from '@/hooks/useProcessList';
|
import { processList } from '@/hooks/useProcessList';
|
||||||
|
import { isJson } from "@/utils/comm";
|
||||||
|
|
||||||
|
|
||||||
import { debounce } from '@/utils/comm'
|
import { debounce } from '@/utils/comm'
|
||||||
|
@ -254,6 +255,7 @@ function Apis(key) {
|
||||||
const client = new Apis('/paht');
|
const client = new Apis('/paht');
|
||||||
const t = function(name, time) {
|
const t = function(name, time) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
const evalId = props.bookobj.levelSecondId=='' ? props.bookobj.levelFirstId : props.bookobj.levelSecondId;
|
||||||
const queryForm = {
|
const queryForm = {
|
||||||
// 题类
|
// 题类
|
||||||
worktype: entpCourseWorkQueryParams.worktype.label,
|
worktype: entpCourseWorkQueryParams.worktype.label,
|
||||||
|
@ -266,7 +268,7 @@ const t = function(name, time) {
|
||||||
// 课程相关参数
|
// 课程相关参数
|
||||||
edustage: userStore.edustage, // this.userStore.edustage,
|
edustage: userStore.edustage, // this.userStore.edustage,
|
||||||
edusubject: userStore.edusubject, // this.userStore.edusubject,
|
edusubject: userStore.edusubject, // this.userStore.edusubject,
|
||||||
eid: props.bookobj.levelSecondId, // this.activeParams.lession.id,
|
eid: evalId, // 当前单元或章节id
|
||||||
status: "1",
|
status: "1",
|
||||||
editUserId: userStore.userId,
|
editUserId: userStore.userId,
|
||||||
//orderby: 'concat(worktype,timestamp) DESC',
|
//orderby: 'concat(worktype,timestamp) DESC',
|
||||||
|
@ -326,10 +328,13 @@ const handleQueryFromEntpCourseWork= async (queryType) => {
|
||||||
}
|
}
|
||||||
//console.log("clueres.rows[i].childlist",clueres.rows[i].childlist);
|
//console.log("clueres.rows[i].childlist",clueres.rows[i].childlist);
|
||||||
if (clueres.rows[i].childlist != '') {
|
if (clueres.rows[i].childlist != '') {
|
||||||
clueres.rows[i].childArray = JSON.parse('['+clueres.rows[i].childlist+']');
|
const tmpJson = '['+clueres.rows[i].childlist+']';
|
||||||
|
if (isJson(tmpJson)){
|
||||||
|
clueres.rows[i].childArray = JSON.parse(tmpJson);
|
||||||
for (var j=0; j<clueres.rows[i].childArray.length; j++) {
|
for (var j=0; j<clueres.rows[i].childArray.length; j++) {
|
||||||
clueres.rows[i].childArray[j].title = clueres.rows[i].childArray[j].title.replace(/(<([^>]+)>)/ig, '');
|
clueres.rows[i].childArray[j].title = clueres.rows[i].childArray[j].title.replace(/(<([^>]+)>)/ig, '');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
clueres.rows[i].childArray = {};
|
clueres.rows[i].childArray = {};
|
||||||
}
|
}
|
||||||
|
@ -482,8 +487,16 @@ const debounceQueryData = debounce(() => {
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
|
|
||||||
watch(() => props.bookobj.levelSecondId, (newVal, oldVal) => {
|
watch([
|
||||||
|
() => props.bookobj.levelFirstId,
|
||||||
|
() => props.bookobj.levelSecondId
|
||||||
|
], ([newLevelSecondId, newLevelFirstId], [oldLevelSecondId, oldLevelFirstId]) => {
|
||||||
console.log(props.bookobj,'课程选择')
|
console.log(props.bookobj,'课程选择')
|
||||||
|
// 默认选择一级单元时, 不自动获取试题, 需手动按钮获取试题
|
||||||
|
if (props.bookobj.levelSecondId == '') {
|
||||||
|
workResource.entpCourseWorkList = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
debounceQueryData();
|
debounceQueryData();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- orc 使用说明 -->
|
<!-- orc 使用说明 -->
|
||||||
<div class="import-manual-explain">
|
<div class="import-manual-explain">
|
||||||
<p>orc 使用说明</p>
|
<p>orc 使用说明(填空题暂无法整题识别)</p>
|
||||||
<p>1、本地浏览 </p>
|
<p>1、本地浏览 </p>
|
||||||
<p>2、获取剪贴板图片 </p>
|
<p>2、获取剪贴板图片 </p>
|
||||||
<p>3、整题识别:可识别整张图片,自动填充到对应内容。 </p>
|
<p>3、整题识别:可识别整张图片,自动填充到对应内容。 </p>
|
||||||
|
@ -127,7 +127,7 @@ const courseObj = reactive({
|
||||||
const activeAptTab = ref("人工录入");
|
const activeAptTab = ref("人工录入");
|
||||||
|
|
||||||
// false - 正式百度api true - 本地json测试
|
// false - 正式百度api true - 本地json测试
|
||||||
const OCR_WORK_TEST = false;
|
const OCR_WORK_TEST = true;
|
||||||
// [裁剪]参数
|
// [裁剪]参数
|
||||||
const cropOption = reactive({
|
const cropOption = reactive({
|
||||||
img: '', // 裁剪图片的地址 url 地址, base64, blob
|
img: '', // 裁剪图片的地址 url 地址, base64, blob
|
||||||
|
|
|
@ -2,7 +2,8 @@ import { ElMessageBox, ElMessage } from "element-plus";
|
||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
import { pyOCRAPI } from "@/api/education/entpcoursework";
|
import { pyOCRAPI, getOcrContent } from "@/api/education/entpcoursework";
|
||||||
|
import useClassTaskStore from '@/store/modules/classTask'
|
||||||
|
|
||||||
|
|
||||||
const EXAM_JUDGED_DICTIONARY = ["正确", "对", "√", "T", "错误", "错", "×", "F"];
|
const EXAM_JUDGED_DICTIONARY = ["正确", "对", "√", "T", "错误", "错", "×", "F"];
|
||||||
|
@ -17,13 +18,10 @@ const baidubceConfig = {
|
||||||
'client_secret': 'oWb0M0YWMmZPMQIhIUkJX99ddr7h61qf',
|
'client_secret': 'oWb0M0YWMmZPMQIhIUkJX99ddr7h61qf',
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getOcrContent(data) {
|
|
||||||
return request({
|
const {
|
||||||
url: '/ocr/exam',
|
entpCourseWorkTypeList
|
||||||
method: 'post',
|
} = useClassTaskStore();
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -45,7 +43,7 @@ export const ocrImg2ItemByManualUpl = async (isLocalTest = false, imgBase64 = ''
|
||||||
|
|
||||||
if (isLocalTest) {
|
if (isLocalTest) {
|
||||||
// 临时本地测试(json格式跟百度ocr一致)
|
// 临时本地测试(json格式跟百度ocr一致)
|
||||||
const response = await fetch('/cropImgTest/single.json');
|
const response = await fetch('/cropImgTest/single2.json');
|
||||||
const resOcr = await response.json();
|
const resOcr = await response.json();
|
||||||
ocrJson = resOcr.results;
|
ocrJson = resOcr.results;
|
||||||
// 识别内容拼接
|
// 识别内容拼接
|
||||||
|
@ -115,7 +113,6 @@ export const ocrImg2ItemByManualUpl = async (isLocalTest = false, imgBase64 = ''
|
||||||
examItem.params.push(obj);
|
examItem.params.push(obj);
|
||||||
});
|
});
|
||||||
return examItem;
|
return examItem;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (examType.includes('单选题') || examType.includes('多选题')) {
|
else if (examType.includes('单选题') || examType.includes('多选题')) {
|
||||||
/** 单选题/多选题 - 选项 */
|
/** 单选题/多选题 - 选项 */
|
||||||
|
@ -150,10 +147,10 @@ export const ocrImg2ItemByManualUpl = async (isLocalTest = false, imgBase64 = ''
|
||||||
}
|
}
|
||||||
else if (curItem === 'workanswer') {
|
else if (curItem === 'workanswer') {
|
||||||
// 该类型下只做[主观题]和[复合题]的处理
|
// 该类型下只做[主观题]和[复合题]的处理
|
||||||
if (examType.includes('主观题')) {
|
|
||||||
ocrTxt = ocrTxt.replace(/<br \/>/g, '');
|
ocrTxt = ocrTxt.replace(/<br \/>/g, '');
|
||||||
examItem = ocrTxt;
|
examItem = ocrTxt;
|
||||||
}
|
} else {
|
||||||
|
examItem = ocrTxt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回转换格式后的识别内容
|
// 返回转换格式后的识别内容
|
||||||
|
@ -174,7 +171,7 @@ export const ocrImg2ExamByManualUpl = async (isLocalTest = false, imgBase64 = ''
|
||||||
|
|
||||||
if (isLocalTest) {
|
if (isLocalTest) {
|
||||||
// 临时本地测试(json格式跟百度ocr一致)
|
// 临时本地测试(json格式跟百度ocr一致)
|
||||||
const response = await fetch('/cropImgTest/single.json');
|
const response = await fetch('/cropImgTest/single1.json');
|
||||||
const resOcr = await response.json();
|
const resOcr = await response.json();
|
||||||
ocrJson = resOcr.results;
|
ocrJson = resOcr.results;
|
||||||
// 识别内容拼接
|
// 识别内容拼接
|
||||||
|
@ -234,12 +231,14 @@ const ocrImg2Json = async (urlBase64) => {
|
||||||
ElMessage.error("未检测到截图图片, 请截取图片后再识别");
|
ElMessage.error("未检测到截图图片, 请截取图片后再识别");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let base64Code = urlBase64.split(",")[1];
|
let base64Code = urlBase64.split(",")[1];
|
||||||
const resOcr = await getOcrContent({ base64Code: base64Code });
|
const resOcr = await getOcrContent({ base64Code: base64Code });
|
||||||
if (resOcr.code !== 200) {
|
if (resOcr.code !== 200) {
|
||||||
ElMessage.error("图片识别错误");
|
ElMessage.error("图片识别错误");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const resToken = await bdyAPI_getToken();
|
// const resToken = await bdyAPI_getToken();
|
||||||
// if (resToken.status !== 200) {
|
// if (resToken.status !== 200) {
|
||||||
// ElMessage.error("百度智能云用户标识有误");
|
// ElMessage.error("百度智能云用户标识有误");
|
||||||
|
@ -394,8 +393,8 @@ const assembleExam = (eachSub) => {
|
||||||
}
|
}
|
||||||
// 第一部分[题干-选项] 处理
|
// 第一部分[题干-选项] 处理
|
||||||
titleAndWorkDesc = tmpList[0];
|
titleAndWorkDesc = tmpList[0];
|
||||||
// 将4个以上连续的下划线统一替换为5个
|
// 将3个以上连续的下划线统一替换为5个
|
||||||
titleAndWorkDesc = titleAndWorkDesc.replace(/_{4,}/g, '_____');
|
titleAndWorkDesc = titleAndWorkDesc.replace(/_{3,}/g, '_____');
|
||||||
|
|
||||||
// 第二部分[分析-答案] 处理
|
// 第二部分[分析-答案] 处理
|
||||||
let answerAndAnswer = {};
|
let answerAndAnswer = {};
|
||||||
|
@ -456,32 +455,35 @@ const assembleExam = (eachSub) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let tmpExam = null;
|
// 目前暂屏蔽无[复合题], 故所有都算基础题
|
||||||
if (answer === '') {
|
let tmpExam = processExamSingle(titleAndWorkDesc, answer);
|
||||||
/**
|
|
||||||
* 基础题型 - [单选题] [多选题] [填空题] [判断题] [主观题]
|
// let tmpExam = null;
|
||||||
*/
|
// if (answer === '') {
|
||||||
tmpExam = processExamSingle(titleAndWorkDesc, answer);
|
// /**
|
||||||
}
|
// * 基础题型 - [单选题] [多选题] [填空题] [判断题] [主观题]
|
||||||
else {
|
// */
|
||||||
// 匹配是否存在 1. (1) (1)的存在, 题目与答案都存在则说明题型为复合题(嵌套题)
|
// tmpExam = processExamSingle(titleAndWorkDesc, answer);
|
||||||
regex = /^(\d+[..。]|\(\d+\)|(\d+))/;
|
// }
|
||||||
let answerFind = regex.test(answer);
|
// else {
|
||||||
regex = /(\d+[..。]|\(\d+\)|(\d+))/;
|
// // 匹配是否存在 1. (1) (1)的存在, 题目与答案都存在则说明题型为复合题(嵌套题)
|
||||||
let titleFind = regex.test(titleAndWorkDesc);
|
// regex = /^(\d+[..。]|\(\d+\)|(\d+))/;
|
||||||
if (titleFind && answerFind) {
|
// let answerFind = regex.test(answer);
|
||||||
/**
|
// regex = /(\d+[..。]|\(\d+\)|(\d+))/;
|
||||||
* [复合题] - 处理逻辑
|
// let titleFind = regex.test(titleAndWorkDesc);
|
||||||
*/
|
// if (titleFind && answerFind) {
|
||||||
tmpExam = processExamMulti(titleAndWorkDesc, answer);
|
// /**
|
||||||
}
|
// * [复合题] - 处理逻辑
|
||||||
else {
|
// */
|
||||||
/**
|
// tmpExam = processExamMulti(titleAndWorkDesc, answer);
|
||||||
* 基础题型 - [单选题] [多选题] [填空题] [判断题] [主观题]
|
// }
|
||||||
*/
|
// else {
|
||||||
tmpExam = processExamSingle(titleAndWorkDesc, answer);
|
// /**
|
||||||
}
|
// * 基础题型 - [单选题] [多选题] [填空题] [判断题] [主观题]
|
||||||
}
|
// */
|
||||||
|
// tmpExam = processExamSingle(titleAndWorkDesc, answer);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
if (tmpExam) {
|
if (tmpExam) {
|
||||||
// 错误信息
|
// 错误信息
|
||||||
|
@ -607,13 +609,21 @@ const processExamSingle = function (titleAndWorkDesc, answer) {
|
||||||
* 主观题
|
* 主观题
|
||||||
*/
|
*/
|
||||||
// [题型] - 格式化
|
// [题型] - 格式化
|
||||||
examSingle.workType = "主观题";
|
const flagDict = ['单选题', '多选题', '判断题', '填空题'];
|
||||||
|
const another = entpCourseWorkTypeList.filter(item => !flagDict.includes(item.label));
|
||||||
|
if (another.length > 0) {
|
||||||
|
examSingle.workType = another[another.length-1].label;
|
||||||
// [题干]-格式化
|
// [题干]-格式化
|
||||||
examSingle.title = titleAndWorkDesc;
|
examSingle.title = titleAndWorkDesc;
|
||||||
|
}
|
||||||
|
|
||||||
// [选项] - 格式化 --- 主观题无选项
|
// examSingle.workType = "主观题";
|
||||||
//examSingle.arrWorkDesc = [];
|
|
||||||
|
// // [题干]-格式化
|
||||||
|
// examSingle.title = titleAndWorkDesc;
|
||||||
|
|
||||||
|
// // [选项] - 格式化 --- 主观题无选项
|
||||||
|
// //examSingle.arrWorkDesc = [];
|
||||||
|
|
||||||
// [题目答案] - 处理 --- ['qweasd123']
|
// [题目答案] - 处理 --- ['qweasd123']
|
||||||
if (answer !== '') {
|
if (answer !== '') {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<el-form ref="questFormRef" :model="questForm" :rules="MainRules" label-width="80px">
|
<el-form ref="questFormRef" :model="questForm" :rules="MainRules" label-width="80px">
|
||||||
<el-form-item label="题型" prop="worktype">
|
<el-form-item label="题型" prop="worktype">
|
||||||
<el-select v-model="questForm.worktype" placeholder="请选择题型" style="width:20%" :disabled="questForm.id==0?false:true">
|
<el-select v-model="questForm.worktype" placeholder="请选择题型" style="width:20%" :disabled="questForm.id==0?false:true">
|
||||||
<el-option v-for="item in fromOptions.type" :key="item.value" :label="item.label" :value="item.label"></el-option>
|
<el-option v-for="item in fromOptions.type" :key="item.value" :label="item.label" :value="item.label" :disabled="item.label=='不限'"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-tag v-if="questForm.worktype=='填空题'" type="danger" style=" margin-left: 10px ">温馨提示:填空题题目的填空位置,下划线请连续输入3-10个 _
|
<el-tag v-if="questForm.worktype=='填空题'" type="danger" style=" margin-left: 10px ">温馨提示:填空题题目的填空位置,下划线请连续输入3-10个 _
|
||||||
符号。eg:今天___好日子。</el-tag>
|
符号。eg:今天___好日子。</el-tag>
|
||||||
|
@ -103,7 +103,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 多选题 -->
|
<!-- 多选题 -->
|
||||||
<div v-if="questForm.worktype=='多选题'" class="questForm-item-cover">
|
<div v-else-if="questForm.worktype=='多选题'" class="questForm-item-cover">
|
||||||
<div v-for="(item,index) in questForm.list" :key='index'>
|
<div v-for="(item,index) in questForm.list" :key='index'>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
:label=Options(1,index)
|
:label=Options(1,index)
|
||||||
|
@ -134,7 +134,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 填空题 -->
|
<!-- 填空题 -->
|
||||||
<div v-if="questForm.worktype=='填空题'" class="questForm-item-cover">
|
<div v-else-if="questForm.worktype=='填空题'" class="questForm-item-cover">
|
||||||
<div v-for="(item,index) in questForm.list" :key='index'>
|
<div v-for="(item,index) in questForm.list" :key='index'>
|
||||||
<el-form-item :label=Options(3,index) :prop="`list.${index}.text`"
|
<el-form-item :label=Options(3,index) :prop="`list.${index}.text`"
|
||||||
:rules="{required: true, message: '填空选项不能为空', trigger: 'blur'}">
|
:rules="{required: true, message: '填空选项不能为空', trigger: 'blur'}">
|
||||||
|
@ -157,7 +157,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 判断题 -->
|
<!-- 判断题 -->
|
||||||
<div v-if="questForm.worktype=='判断题'" class="questForm-item-cover">
|
<div v-else-if="questForm.worktype=='判断题'" class="questForm-item-cover">
|
||||||
<div v-for="(item,index) in questForm.list" :key='index'>
|
<div v-for="(item,index) in questForm.list" :key='index'>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-if="index==0"
|
v-if="index==0"
|
||||||
|
@ -176,7 +176,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 主观题 -->
|
<!-- 主观题 -->
|
||||||
<div v-if="questForm.worktype.indexOf('主观题') != -1" class="questForm-item-cover">
|
<div v-else-if="questForm.worktype.indexOf('主观题') != -1" class="questForm-item-cover">
|
||||||
<el-form-item label="答案">
|
<el-form-item label="答案">
|
||||||
<Tinymce v-model="questForm.workanswer" :upFileParams="{
|
<Tinymce v-model="questForm.workanswer" :upFileParams="{
|
||||||
lessionId: lessionid,
|
lessionId: lessionid,
|
||||||
|
@ -239,7 +239,7 @@
|
||||||
|
|
||||||
|
|
||||||
<!-- 复合题 -->
|
<!-- 复合题 -->
|
||||||
<div v-if="questForm.worktype=='复合题'" class="questForm-item-cover">
|
<div v-else-if="questForm.worktype=='复合题'" class="questForm-item-cover">
|
||||||
<el-form-item label="单项题型" :prop="worktype">
|
<el-form-item label="单项题型" :prop="worktype">
|
||||||
<el-select v-model="questForm.mulList.worktype" placeholder="请选择题型" style="width:20%">
|
<el-select v-model="questForm.mulList.worktype" placeholder="请选择题型" style="width:20%">
|
||||||
<!-- <el-option key="1" label="单选题" value="单选题"></el-option> -->
|
<!-- <el-option key="1" label="单选题" value="单选题"></el-option> -->
|
||||||
|
@ -350,6 +350,19 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 非统一标准名称的解答题 -->
|
||||||
|
<div v-else class="questForm-item-cover">
|
||||||
|
<el-form-item label="答案">
|
||||||
|
<Tinymce v-model="questForm.workanswer" :upFileParams="{
|
||||||
|
lessionId: lessionid,
|
||||||
|
fileAlias: '单题上传',
|
||||||
|
}" />
|
||||||
|
</el-form-item>
|
||||||
|
<div class="item-cropper-btn">
|
||||||
|
<el-button v-show="isCropper" circle @click="cropperFormItem('workanswer')"><el-icon><Search /></el-icon></el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 答案分析 -->
|
<!-- 答案分析 -->
|
||||||
<div class="questForm-item-cover">
|
<div class="questForm-item-cover">
|
||||||
<el-form-item label="答案分析" prop="method">
|
<el-form-item label="答案分析" prop="method">
|
||||||
|
@ -623,8 +636,9 @@ onMounted(() => {
|
||||||
|
|
||||||
// 更新第三方题型、题源
|
// 更新第三方题型、题源
|
||||||
if (entpCourseWorkTypeList.length>0) {
|
if (entpCourseWorkTypeList.length>0) {
|
||||||
const flagDict = ['单选题', '多选题', '判断题', '填空题'];
|
//const flagDict = ['单选题', '多选题', '判断题', '填空题'];
|
||||||
fromOptions.type = entpCourseWorkTypeList.filter(item => flagDict.includes(item.label));
|
//fromOptions.type = entpCourseWorkTypeList.filter(item => flagDict.includes(item.label));
|
||||||
|
fromOptions.type = entpCourseWorkTypeList
|
||||||
}
|
}
|
||||||
if (entpCourseWorkGroupList.length>0) {
|
if (entpCourseWorkGroupList.length>0) {
|
||||||
fromOptions.flag = entpCourseWorkGroupList;
|
fromOptions.flag = entpCourseWorkGroupList;
|
||||||
|
@ -748,8 +762,8 @@ const resetForm = () =>{
|
||||||
const updateForm= async(item, submitIndex=0, submitType=1) =>{
|
const updateForm= async(item, submitIndex=0, submitType=1) =>{
|
||||||
console.log(item,'item');
|
console.log(item,'item');
|
||||||
// 当不存在[状态],默认为1
|
// 当不存在[状态],默认为1
|
||||||
if (!item.hasOwnProperty('stutus')) {
|
if (!item.hasOwnProperty('status')) {
|
||||||
item.stutus = '1';
|
item.status = '1';
|
||||||
}
|
}
|
||||||
// 当不存在[知识点], 默认为空
|
// 当不存在[知识点], 默认为空
|
||||||
if (!item.hasOwnProperty('evalnodeid')) {
|
if (!item.hasOwnProperty('evalnodeid')) {
|
||||||
|
@ -765,7 +779,6 @@ const updateForm= async(item, submitIndex=0, submitType=1) =>{
|
||||||
// 将菁优网的填空下划线标签转为下划线(上传时需再重新替换回来)
|
// 将菁优网的填空下划线标签转为下划线(上传时需再重新替换回来)
|
||||||
item.title = item.title.replace(/<!--BA--><div class="quizPutTag" contenteditable="true">(?: )?<\/div><!--EA-->/g, '_____');
|
item.title = item.title.replace(/<!--BA--><div class="quizPutTag" contenteditable="true">(?: )?<\/div><!--EA-->/g, '_____');
|
||||||
|
|
||||||
|
|
||||||
if(item.worktype == '复合题') {
|
if(item.worktype == '复合题') {
|
||||||
// 同步更新[基础题]的初始结构
|
// 同步更新[基础题]的初始结构
|
||||||
newList = [{text:""}];
|
newList = [{text:""}];
|
||||||
|
@ -902,11 +915,14 @@ const updateForm= async(item, submitIndex=0, submitType=1) =>{
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
newList = [];
|
|
||||||
|
// 默认显示一个空选项
|
||||||
|
newList = [{text:""}];
|
||||||
|
|
||||||
|
|
||||||
// 兼容题型[主观题]
|
// 兼容题型[主观题]
|
||||||
item.worktype = item.worktype.replace(/\(主观题\)/g, '');
|
//item.worktype = item.worktype.replace(/\(主观题\)/g, '');
|
||||||
item.worktype = `${item.worktype}(主观题)`;
|
//item.worktype = `${item.worktype}(主观题)`;
|
||||||
// 无选项
|
// 无选项
|
||||||
// 选项答案处理下
|
// 选项答案处理下
|
||||||
if(isJson(item.workanswer)){
|
if(isJson(item.workanswer)){
|
||||||
|
@ -1008,9 +1024,8 @@ const updateForm= async(item, submitIndex=0, submitType=1) =>{
|
||||||
|
|
||||||
lessionid.value = props.bookobj.levelSecondId? props.bookobj.levelSecondId : props.bookobj.levelFirstId;
|
lessionid.value = props.bookobj.levelSecondId? props.bookobj.levelSecondId : props.bookobj.levelFirstId;
|
||||||
console.log('lessionid', lessionid.value);
|
console.log('lessionid', lessionid.value);
|
||||||
|
|
||||||
// 拿到当前章节下得所有知识点
|
// 拿到当前章节下得所有知识点
|
||||||
if( props.bookobj.node.edustage == '高中' && (props.bookobj.node.edusubject == '语文' || props.bookobj.node.edusubject == '英语') ){
|
if( props.bookobj.node.edusubject == '语文' || props.bookobj.node.edusubject == '英语' ){
|
||||||
const res = await listEvaluation({ edusubject: props.bookobj.node.edusubject, edustage: props.bookobj.node.edustage, itemkey: "subject", pageSize: 10 });
|
const res = await listEvaluation({ edusubject: props.bookobj.node.edusubject, edustage: props.bookobj.node.edustage, itemkey: "subject", pageSize: 10 });
|
||||||
const id = res.rows[0]?.id;
|
const id = res.rows[0]?.id;
|
||||||
if (id) {
|
if (id) {
|
||||||
|
@ -1083,6 +1098,7 @@ const updateForm= async(item, submitIndex=0, submitType=1) =>{
|
||||||
// status = 1,
|
// status = 1,
|
||||||
// }
|
// }
|
||||||
// emit('update-exam-single', updateStatus);
|
// emit('update-exam-single', updateStatus);
|
||||||
|
console.log('updateFormone->', questForm)
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateFormone=(item, submitIndex, submitType, formdataitem)=>{
|
const updateFormone=(item, submitIndex, submitType, formdataitem)=>{
|
||||||
|
@ -1437,14 +1453,9 @@ const submitForm=(formName) =>{
|
||||||
//param.workdesc = questForm.list.map(item => item.text).join('#&');
|
//param.workdesc = questForm.list.map(item => item.text).join('#&');
|
||||||
param.workdesc = JSON.stringify(questForm.list.map(item => item.text));
|
param.workdesc = JSON.stringify(questForm.list.map(item => item.text));
|
||||||
|
|
||||||
// 针对[单选题]和[多选题]重新格式化信息
|
// 重新格式化信息
|
||||||
if (questForm.worktype === '单选题' || questForm.worktype === '多选题') {
|
|
||||||
//param.workanswer = questForm.checkAnswer.map(item => item).join('#&');
|
|
||||||
param.workanswer = JSON.stringify(questForm.checkAnswer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 针对[复合题]重新格式化信息
|
|
||||||
if(questForm.worktype === '复合题') {
|
if(questForm.worktype === '复合题') {
|
||||||
|
// 针对[复合题]重新格式化信息
|
||||||
let workdesc = [];
|
let workdesc = [];
|
||||||
let answer = [];
|
let answer = [];
|
||||||
// 1.题目: 背景材料(不再需要处理, 直接使用form.title)
|
// 1.题目: 背景材料(不再需要处理, 直接使用form.title)
|
||||||
|
@ -1501,9 +1512,33 @@ const submitForm=(formName) =>{
|
||||||
param.workdesc = JSON.stringify(workdesc);
|
param.workdesc = JSON.stringify(workdesc);
|
||||||
param.workanswer = JSON.stringify(answer);
|
param.workanswer = JSON.stringify(answer);
|
||||||
}
|
}
|
||||||
|
else if (questForm.worktype === '单选题' || questForm.worktype === '多选题') {
|
||||||
|
// 针对[单选题]和[多选题]重新格式化信息
|
||||||
|
//param.workanswer = questForm.checkAnswer.map(item => item).join('#&');
|
||||||
|
param.workanswer = JSON.stringify(questForm.checkAnswer);
|
||||||
|
}
|
||||||
|
// 针对[填空题]重新格式化信息 "<div>什么</div>#&<div>什么哟</div>".replace(/<[^>]*>/g, "")
|
||||||
|
else if(questForm.worktype === '填空题'){
|
||||||
|
//填空答案: 这里填入选项的值(填空值)
|
||||||
|
//param.workanswer = questForm.list.map(item => item.text).join('#&').replace(/<[^>]*>/g, "");
|
||||||
|
|
||||||
// 针对[主观题]重新格式化信息 ([单题上传]时默认为主观题。 [单题纠错]时会在原题型后面增加标识[(主观题)], 故此处更改为判断是否存在 )
|
// 填空选项为空,避免后面多次判断,这里只根据正确答案来分析
|
||||||
if(questForm.worktype.indexOf('主观题') !== -1) {
|
param.workdesc = '';
|
||||||
|
param.workanswer = JSON.stringify(questForm.list.map(item => item.text));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 针对[判断题]重新格式化信息
|
||||||
|
else if(questForm.worktype === '判断题'){
|
||||||
|
//判断题答案: 这里填入选项的值(判断值)
|
||||||
|
//param.workanswer = questForm.list.map(item => item.text).join('#&').replace(/<[^>]*>/g, "");
|
||||||
|
|
||||||
|
// 填空选项为空,避免后面多次判断,这里只根据正确答案来分析
|
||||||
|
param.workdesc = '';
|
||||||
|
param.workanswer = JSON.stringify(questForm.checkAnswer);
|
||||||
|
}
|
||||||
|
else if(questForm.worktype.indexOf('主观题') !== -1) {
|
||||||
|
// warn: 针对[主观题]重新格式化信息 ([单题上传]时默认为主观题。 [单题纠错]时会在原题型后面增加标识[(主观题)], 故此处更改为判断是否存在 )
|
||||||
// 主观题:只有答案跟题目,答案还不是唯一的,一个具体参考答案类似
|
// 主观题:只有答案跟题目,答案还不是唯一的,一个具体参考答案类似
|
||||||
param.workdesc = ''; // 主观题选项为空
|
param.workdesc = ''; // 主观题选项为空
|
||||||
// 主观题 答案直接用的 workanswer 存的时候用数组
|
// 主观题 答案直接用的 workanswer 存的时候用数组
|
||||||
|
@ -1533,27 +1568,16 @@ const submitForm=(formName) =>{
|
||||||
// param.workdesc = ''; // 填空选项为空,避免后面多次判断,这里只根据正确答案来分析
|
// param.workdesc = ''; // 填空选项为空,避免后面多次判断,这里只根据正确答案来分析
|
||||||
// param.workanswer = JSON.stringify(answer).replace(/<[^>]*>/g, "");
|
// param.workanswer = JSON.stringify(answer).replace(/<[^>]*>/g, "");
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
// 针对[填空题]重新格式化信息 "<div>什么</div>#&<div>什么哟</div>".replace(/<[^>]*>/g, "")
|
// 非统一标准解答题(主观题), 统一以[主观题]的格式来处理, 主要用于兼容ocr识别解答题及菁优网第三方非同一解答题
|
||||||
if(questForm.worktype === '填空题'){
|
param.workdesc = ''; // 主观题选项为空
|
||||||
//填空答案: 这里填入选项的值(填空值)
|
// 主观题 答案直接用的 workanswer 存的时候用数组
|
||||||
//param.workanswer = questForm.list.map(item => item.text).join('#&').replace(/<[^>]*>/g, "");
|
if (questForm.workanswer && questForm.workanswer != '') {
|
||||||
|
param.workanswer = JSON.stringify([questForm.workanswer]);
|
||||||
// 填空选项为空,避免后面多次判断,这里只根据正确答案来分析
|
}
|
||||||
param.workdesc = '';
|
|
||||||
param.workanswer = JSON.stringify(questForm.list.map(item => item.text));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 针对[判断题]重新格式化信息
|
|
||||||
if(questForm.worktype === '判断题'){
|
|
||||||
//判断题答案: 这里填入选项的值(判断值)
|
|
||||||
//param.workanswer = questForm.list.map(item => item.text).join('#&').replace(/<[^>]*>/g, "");
|
|
||||||
|
|
||||||
// 填空选项为空,避免后面多次判断,这里只根据正确答案来分析
|
|
||||||
param.workdesc = '';
|
|
||||||
param.workanswer = JSON.stringify(questForm.checkAnswer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 针对不同上传方式, 需要做不同的状态处理(目前只用处理3的情况)
|
// 针对不同上传方式, 需要做不同的状态处理(目前只用处理3的情况)
|
||||||
if (questForm.submitType === 3) {
|
if (questForm.submitType === 3) {
|
||||||
|
@ -1703,37 +1727,40 @@ const myMessageShow=(title, msg, status)=>{
|
||||||
* @return: {*}
|
* @return: {*}
|
||||||
* @param {*} list
|
* @param {*} list
|
||||||
*/
|
*/
|
||||||
const updateKnowledgePoint = (list) => {
|
const formatKnowledgePoint = (list) => {
|
||||||
list.forEach(item => {
|
list.forEach(item => {
|
||||||
if (item.title && item.title != '') {
|
if (item.title && item.title != '') {
|
||||||
item.knowTitle = item.title;
|
item.knowTitle = item.title;
|
||||||
}
|
}
|
||||||
if (item.children && Array.isArray(item.children)) {
|
if (item.children && Array.isArray(item.children)) {
|
||||||
updateKnowledgePoint(item.children);
|
formatKnowledgePoint(item.children);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return list;
|
return list;
|
||||||
};
|
};
|
||||||
|
|
||||||
watch(() => props.bookobj.levelSecondId, async (newVal, oldVal) => {
|
watch([
|
||||||
|
() => props.bookobj.levelFirstId,
|
||||||
|
() => props.bookobj.levelSecondId
|
||||||
|
], async([newLevelSecondId, newLevelFirstId], [oldLevelSecondId, oldLevelFirstId]) => {
|
||||||
console.log(props.bookobj,'课程选择')
|
console.log(props.bookobj,'课程选择')
|
||||||
// props.bookobj.levelSecondId? props.bookobj.levelSecondId : props.bookobj.levelFirstId
|
// props.bookobj.levelSecondId? props.bookobj.levelSecondId : props.bookobj.levelFirstId
|
||||||
lessionid.value = props.bookobj.levelSecondId? props.bookobj.levelSecondId : props.bookobj.levelFirstId;
|
lessionid.value = props.bookobj.levelSecondId!='' ? props.bookobj.levelSecondId : props.bookobj.levelFirstId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 格式化知识点: 分两种情况
|
* 格式化知识点: 分两种情况
|
||||||
* 1. 语文/英语: 获取学科下的所有知识点(该学科对应无章节与知识点绑定, 故只获取全知识点)
|
* 1. 语文/英语: 获取学科下的所有知识点(该学科对应无章节与知识点绑定, 故只获取全知识点)
|
||||||
* 2. 其他: 获取当前章节下的所有知识点
|
* 2. 其他: 获取当前章节下的所有知识点
|
||||||
*/
|
*/
|
||||||
let id = props.bookobj.levelSecondId;
|
let id = lessionid.value;
|
||||||
if( props.bookobj.node.edustage == '高中' && (props.bookobj.node.edusubject == '语文' || props.bookobj.node.edusubject == '英语') ){
|
if( props.bookobj.node.edusubject == '语文' || props.bookobj.node.edusubject == '英语'){
|
||||||
id = props.bookobj.node.rootid;
|
id = props.bookobj.node.rootid;
|
||||||
const res = await listEvaluation({ edusubject: props.bookobj.node.edusubject, edustage: props.bookobj.node.edustage, itemkey: "subject", pageSize: 10 });
|
const res = await listEvaluation({ edusubject: props.bookobj.node.edusubject, edustage: props.bookobj.node.edustage, itemkey: "subject", pageSize: 10 });
|
||||||
id = res.rows[0]?.id;
|
id = res.rows[0]?.id;
|
||||||
if (id) {
|
if (id) {
|
||||||
listKnowlegepointFormat({evalId: id, pageNum: 1, pageSize: 5000,}).then(res => {
|
listKnowlegepointFormat({evalId: id, pageNum: 1, pageSize: 5000,}).then(res => {
|
||||||
//console.log('listKnowlegepointFormat->', res.rows);
|
//console.log('listKnowlegepointFormat->', res.rows);
|
||||||
curKnowledgePointList.value = updateKnowledgePoint(res.rows);
|
curKnowledgePointList.value = formatKnowledgePoint(res.rows);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
|
|
|
@ -117,6 +117,8 @@ import { listKnowledgePoint } from "@/api/knowledge/knowledgePoint";
|
||||||
import { getBindlist } from '@/api/education/knowledgePoint'
|
import { getBindlist } from '@/api/education/knowledgePoint'
|
||||||
import examDetailsDrawer from '@/components/exam-question/examDetailsDrawer.vue'
|
import examDetailsDrawer from '@/components/exam-question/examDetailsDrawer.vue'
|
||||||
import { processList } from '@/hooks/useProcessList'
|
import { processList } from '@/hooks/useProcessList'
|
||||||
|
import { isJson } from "@/utils/comm";
|
||||||
|
|
||||||
import { useGetHomework } from '@/hooks/useGetHomework'
|
import { useGetHomework } from '@/hooks/useGetHomework'
|
||||||
import { sessionStore } from '@/utils/store'
|
import { sessionStore } from '@/utils/store'
|
||||||
import {throttle,debounce } from '@/utils/comm'
|
import {throttle,debounce } from '@/utils/comm'
|
||||||
|
@ -190,6 +192,8 @@ const workResource = reactive({
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
console.log('entpCourseWorkTypeList', entpCourseWorkTypeList);
|
console.log('entpCourseWorkTypeList', entpCourseWorkTypeList);
|
||||||
|
// 知识点 (仅用更新一次)
|
||||||
|
getEntpCourseWorkPointList();
|
||||||
debounceQueryData(); // 查询习题列表
|
debounceQueryData(); // 查询习题列表
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -235,12 +239,13 @@ function Apis(key) {
|
||||||
const client = new Apis('/paht');
|
const client = new Apis('/paht');
|
||||||
const t = function(name, time) {
|
const t = function(name, time) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
|
const evalId = props.bookobj.levelSecondId=='' ? props.bookobj.levelFirstId : props.bookobj.levelSecondId;
|
||||||
const queryForm = {
|
const queryForm = {
|
||||||
// 分页参数
|
// 分页参数
|
||||||
currentPage: paginationParams.pageNum,
|
currentPage: paginationParams.pageNum,
|
||||||
pageSize: paginationParams.pageSize,
|
pageSize: paginationParams.pageSize,
|
||||||
// 课程相关参数
|
// 课程相关参数
|
||||||
eid: props.bookobj.levelSecondId,
|
eid: evalId, // 当前单元或章节id
|
||||||
sectionName: props.bookobj.coursetitle,
|
sectionName: props.bookobj.coursetitle,
|
||||||
edusubject: userStore.edusubject,
|
edusubject: userStore.edusubject,
|
||||||
edustage: userStore.edustage,
|
edustage: userStore.edustage,
|
||||||
|
@ -329,10 +334,13 @@ const handleQueryFromEntpCourseWork= async (queryType) => {
|
||||||
}
|
}
|
||||||
//console.log("clueres.rows[i].childlist",clueres.rows[i].childlist);
|
//console.log("clueres.rows[i].childlist",clueres.rows[i].childlist);
|
||||||
if (clueres.rows[i].childlist != '') {
|
if (clueres.rows[i].childlist != '') {
|
||||||
clueres.rows[i].childArray = JSON.parse('['+clueres.rows[i].childlist+']');
|
const tmpJson = '['+clueres.rows[i].childlist+']';
|
||||||
|
if (isJson(tmpJson)){
|
||||||
|
clueres.rows[i].childArray = JSON.parse(tmpJson);
|
||||||
for (var j=0; j<clueres.rows[i].childArray.length; j++) {
|
for (var j=0; j<clueres.rows[i].childArray.length; j++) {
|
||||||
clueres.rows[i].childArray[j].title = clueres.rows[i].childArray[j].title.replace(/(<([^>]+)>)/ig, '');
|
clueres.rows[i].childArray[j].title = clueres.rows[i].childArray[j].title.replace(/(<([^>]+)>)/ig, '');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
clueres.rows[i].childArray = {};
|
clueres.rows[i].childArray = {};
|
||||||
}
|
}
|
||||||
|
@ -460,19 +468,29 @@ const captureScreenshot = (id) => {
|
||||||
// 防抖
|
// 防抖
|
||||||
const debounceQueryData = debounce(() => {
|
const debounceQueryData = debounce(() => {
|
||||||
console.log("防抖 加载数据中...")
|
console.log("防抖 加载数据中...")
|
||||||
|
console.log(props.bookobj,'课程选择')
|
||||||
// 初始化滚动加载参数
|
// 初始化滚动加载参数
|
||||||
initPageParams();
|
initPageParams();
|
||||||
// 习题资源
|
// 习题资源
|
||||||
handleQueryFromEntpCourseWork(0);
|
handleQueryFromEntpCourseWork(0);
|
||||||
// 框架梳理
|
// 框架梳理
|
||||||
getQueryFromEvaluationclue();
|
//getQueryFromEvaluationclue();
|
||||||
// 知识点
|
// 知识点
|
||||||
getEntpCourseWorkPointList();
|
//getEntpCourseWorkPointList();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
|
//watch(() => props.bookobj.levelSecondId, async (newVal, oldVal) => {
|
||||||
|
|
||||||
watch(() => props.bookobj.levelSecondId, (newVal, oldVal) => {
|
watch([
|
||||||
|
() => props.bookobj.levelFirstId,
|
||||||
|
() => props.bookobj.levelSecondId
|
||||||
|
], ([newLevelSecondId, newLevelFirstId], [oldLevelSecondId, oldLevelFirstId]) => {
|
||||||
console.log(props.bookobj,'课程选择')
|
console.log(props.bookobj,'课程选择')
|
||||||
|
// 默认选择一级单元时, 不自动获取试题, 需手动按钮获取试题
|
||||||
|
if (props.bookobj.levelSecondId == '') {
|
||||||
|
workResource.entpCourseWorkList = [];
|
||||||
|
return;
|
||||||
|
}
|
||||||
debounceQueryData();
|
debounceQueryData();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -58,10 +58,10 @@ import { useGetSubject } from '@/hooks/useGetSubject'
|
||||||
import { sessionStore } from '@/utils/store'
|
import { sessionStore } from '@/utils/store'
|
||||||
import { debounce } from 'lodash'
|
import { debounce } from 'lodash'
|
||||||
|
|
||||||
import useUserStore from '@/store/modules/user'
|
// import useUserStore from '@/store/modules/user'
|
||||||
import useClassTaskStore from '@/store/modules/classTask'
|
// import useClassTaskStore from '@/store/modules/classTask'
|
||||||
const userStore = useUserStore()
|
// const userStore = useUserStore()
|
||||||
const classTaskStore = useClassTaskStore();
|
// const classTaskStore = useClassTaskStore();
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { ipcRenderer } = window.electron || {}
|
const { ipcRenderer } = window.electron || {}
|
||||||
|
@ -217,7 +217,7 @@ onMounted(async ()=>{
|
||||||
chartInstance = echarts.init(chartDom.value)
|
chartInstance = echarts.init(chartDom.value)
|
||||||
|
|
||||||
// 更新第三方题型题类
|
// 更新第三方题型题类
|
||||||
await classTaskStore.initJYInfo(userStore.user);
|
//await classTaskStore.initJYInfo(userStore.user);
|
||||||
|
|
||||||
const option = {
|
const option = {
|
||||||
|
|
||||||
|
|
|
@ -410,8 +410,8 @@ const changeBook = async(data) => {
|
||||||
let cata = parseCataByNode(data.node)
|
let cata = parseCataByNode(data.node)
|
||||||
currentNode.value = data.node
|
currentNode.value = data.node
|
||||||
uploadData.value.levelFirstId = cata[0]
|
uploadData.value.levelFirstId = cata[0]
|
||||||
uploadData.value.levelSecondId = cata[1]
|
uploadData.value.levelSecondId = cata[1] ?? ''
|
||||||
uploadData.value.levelThirdId = cata[2]
|
uploadData.value.levelThirdId = cata[2] ?? ''
|
||||||
uploadData.value.textbookId = data.textBook.curBookId
|
uploadData.value.textbookId = data.textBook.curBookId
|
||||||
getModelInfo({cataid: currentNode.value.id}).then(res=>{
|
getModelInfo({cataid: currentNode.value.id}).then(res=>{
|
||||||
console.log(res)
|
console.log(res)
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
<c-form v-bind="classForm">
|
<c-form v-bind="classForm">
|
||||||
<template #item_classid="{prop, form}">
|
<template #item_classid="{prop, form}">
|
||||||
<span v-if="dt.ctCourse">{{ dt.ctCourse?.caption }}</span>
|
<span v-if="dt.ctCourse">{{ dt.ctCourse?.caption }}</span>
|
||||||
<el-select v-else v-model="form[prop]" placeholder="请选择班级">
|
<el-select v-else v-model="form[prop]" placeholder="请选择班级" clearable>
|
||||||
<el-option v-for="item in listData.classList" :value="item.id"
|
<el-option v-for="item in listData.classList" :value="item.id"
|
||||||
:label="`${item.caption} (${item.classstudentcount}人)`" />
|
:label="`${item.caption} (${item.classstudentcount}人)`" />
|
||||||
</el-select>
|
</el-select>
|
||||||
|
@ -60,8 +60,8 @@
|
||||||
<template #item_mobile>
|
<template #item_mobile>
|
||||||
<div>
|
<div>
|
||||||
<div v-if="myClassActive.filetype=='apt'">开始新的课堂,需要点击先创建课堂,才能显示手机二维码</div>
|
<div v-if="myClassActive.filetype=='apt'">开始新的课堂,需要点击先创建课堂,才能显示手机二维码</div>
|
||||||
<div v-else>开始新的课堂,需要点击先创建课堂</div>
|
<div v-else>开始新的课堂</div>
|
||||||
<el-button type="warning" :loading="dt.loading" @click="createClasscourse()">创建课堂</el-button>
|
<!-- <el-button type="warning" :loading="dt.loading" @click="createClasscourse()">创建课堂</el-button> -->
|
||||||
<el-button type="success" @click="createClasscourse(true)">公屏上课</el-button>
|
<el-button type="success" @click="createClasscourse(true)">公屏上课</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -139,6 +139,8 @@ onMounted(() => {
|
||||||
* @param classObj 课程对象-用于继续上课
|
* @param classObj 课程对象-用于继续上课
|
||||||
*/
|
*/
|
||||||
const open = async (id, classObj) => {
|
const open = async (id, classObj) => {
|
||||||
|
dt.loading = false
|
||||||
|
dt.loadingDel = false
|
||||||
visible.value = true
|
visible.value = true
|
||||||
if (id) {
|
if (id) {
|
||||||
// 重置数据
|
// 重置数据
|
||||||
|
@ -167,6 +169,8 @@ const handleClose = async () => {
|
||||||
// await chat?.logout()
|
// await chat?.logout()
|
||||||
// chat = null
|
// chat = null
|
||||||
dt.ctCourse = null
|
dt.ctCourse = null
|
||||||
|
dt.loading = false
|
||||||
|
dt.loadingDel = false
|
||||||
emit('close')
|
emit('close')
|
||||||
}
|
}
|
||||||
// 初始化-数据
|
// 初始化-数据
|
||||||
|
@ -249,10 +253,10 @@ const getClasscourseList = async type => {
|
||||||
// 创建课程 isPublic 公屏上课
|
// 创建课程 isPublic 公屏上课
|
||||||
const createClasscourse = async (isPublic = false) => {
|
const createClasscourse = async (isPublic = false) => {
|
||||||
const { classid } = classForm.form
|
const { classid } = classForm.form
|
||||||
if (!classid) {
|
// if (!classid) {
|
||||||
ElMessage.warning('请选择班级')
|
// ElMessage.warning('请选择班级')
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
dt.loading = true
|
dt.loading = true
|
||||||
const { entpcourseid, evalid, id, coursetitle } = myClassActive.value // 课件对象
|
const { entpcourseid, evalid, id, coursetitle } = myClassActive.value // 课件对象
|
||||||
const curDate = commUtil.getDateNow('yyyy-MM-dd')
|
const curDate = commUtil.getDateNow('yyyy-MM-dd')
|
||||||
|
@ -264,7 +268,7 @@ const createClasscourse = async (isPublic = false) => {
|
||||||
}
|
}
|
||||||
// teacherForm.form.classcourseid = 100
|
// teacherForm.form.classcourseid = 100
|
||||||
teacherForm.form.classcourseid = await Http_Classcourse.addClasscourseReturnId(params)
|
teacherForm.form.classcourseid = await Http_Classcourse.addClasscourseReturnId(params)
|
||||||
dt.loading = false
|
.finally(() => {dt.loading = false})
|
||||||
// getClasscourseList('update') // 更新列表
|
// getClasscourseList('update') // 更新列表
|
||||||
let msgEl = ElMessage.success('创建课程-成功')
|
let msgEl = ElMessage.success('创建课程-成功')
|
||||||
// 新版-pptList 打开公屏
|
// 新版-pptList 打开公屏
|
||||||
|
@ -372,9 +376,9 @@ const openPublicScreen = (classcourse, isPublic) => {
|
||||||
createWindow('open-win', {
|
createWindow('open-win', {
|
||||||
url: '/pptist', // 窗口关闭时,清除缓存
|
url: '/pptist', // 窗口关闭时,清除缓存
|
||||||
close: () => {
|
close: () => {
|
||||||
sessionStore.set('curr.resource', null) // 清除缓存
|
sessionStore.delete('curr.resource') // 清除缓存
|
||||||
sessionStore.set('curr.classcourse', null) // 清除缓存
|
sessionStore.delete('curr.classcourse') // 清除缓存
|
||||||
sessionStore.set('curr.isPublic', null) // 清除缓存
|
sessionStore.delete('curr.isPublic') // 清除缓存
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
visible.value = false // 关闭弹窗
|
visible.value = false // 关闭弹窗
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
<el-dropdown-item @click="createAIPPT">新建文枢课件</el-dropdown-item>
|
<el-dropdown-item @click="createAIPPT">新建文枢课件</el-dropdown-item>
|
||||||
<el-dropdown-item @click="aiTOPPT">AI一键生成</el-dropdown-item>
|
<el-dropdown-item @click="aiTOPPT">AI一键生成</el-dropdown-item>
|
||||||
<el-dropdown-item @click="openGridPic">打开宫格</el-dropdown-item>
|
<!-- <el-dropdown-item @click="openGridPic">打开宫格</el-dropdown-item>-->
|
||||||
<el-dropdown-item @click="openFilePicker">导入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">
|
<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>
|
||||||
|
@ -449,6 +449,7 @@ export default {
|
||||||
}
|
}
|
||||||
case 'click': { // 点击-打开课件-aippt
|
case 'click': { // 点击-打开课件-aippt
|
||||||
if (row.fileFlag === 'aippt' && !!row.fileId) {
|
if (row.fileFlag === 'aippt' && !!row.fileId) {
|
||||||
|
sessionStore.delete('curr.classcourse') // 清除上课相关信息
|
||||||
const res = await getEntpcoursefile(row.fileId)
|
const res = await getEntpcoursefile(row.fileId)
|
||||||
if (res && res.code === 200) {
|
if (res && res.code === 200) {
|
||||||
this.openPublicScreen('edit', res.data, row) // 打开公屏-窗口
|
this.openPublicScreen('edit', res.data, row) // 打开公屏-窗口
|
||||||
|
@ -497,11 +498,11 @@ export default {
|
||||||
createWindow('open-win', {
|
createWindow('open-win', {
|
||||||
url: '/pptist', // 窗口关闭时,清除缓存
|
url: '/pptist', // 窗口关闭时,清除缓存
|
||||||
close: () => {
|
close: () => {
|
||||||
sessionStore.set('curr.resource', null) // 清除缓存
|
sessionStore.delete('curr.resource') // 清除缓存
|
||||||
if (type=='edit') {
|
if (type=='edit') {
|
||||||
sessionStore.set('curr.smarttalk', null) // 清除缓存
|
sessionStore.delete('curr.smarttalk') // 清除缓存
|
||||||
this.asyncAllFile() // 刷新资源列表
|
this.asyncAllFile() // 刷新资源列表
|
||||||
} else sessionStore.set('curr.classcourse', null) // 清除缓存
|
} else sessionStore.delete('curr.classcourse') // 清除缓存
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -206,7 +206,7 @@ export default {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
position: relative;
|
position: relative;
|
||||||
left: 150px;
|
left: 100px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
append-to-body
|
append-to-body
|
||||||
@opened="modalOpened"
|
@opened="modalOpened"
|
||||||
@close="closeDialog"
|
@close="closeDialog"
|
||||||
|
width="100px"
|
||||||
>
|
>
|
||||||
<CropperImage
|
<CropperImage
|
||||||
ref="cropper"
|
ref="cropper"
|
||||||
|
|
Loading…
Reference in New Issue