This commit is contained in:
zdg 2024-12-11 17:17:01 +08:00
commit 8990ffdc58
22 changed files with 491 additions and 409 deletions

View File

@ -12,6 +12,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import 'animate.css'
import { ref, onMounted, watch, onBeforeMount } from 'vue' import { ref, onMounted, watch, onBeforeMount } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useScreenStore, useMainStore, useSnapshotStore, useSlidesStore } from './store' import { useScreenStore, useMainStore, useSnapshotStore, useSlidesStore } from './store'

View File

@ -30,7 +30,7 @@ let params = {
levelSecondId: null, levelSecondId: null,
fileSource: '个人', fileSource: '个人',
fileRoot: '备课', fileRoot: '备课',
orderByColumn: 'uploadTime', orderByColumn: 'createTime',
isAsc: 'desc', isAsc: 'desc',
pageSize: 500 pageSize: 500
} }

View File

@ -245,7 +245,6 @@ const runAnimation = (elId: string, effect: string, duration: number) => {
const animationName = `${ANIMATION_CLASS_PREFIX}${effect}` const animationName = `${ANIMATION_CLASS_PREFIX}${effect}`
document.documentElement.style.setProperty('--animate-duration', `${duration}ms`) document.documentElement.style.setProperty('--animate-duration', `${duration}ms`)
elRef.classList.add(`${ANIMATION_CLASS_PREFIX}animated`, animationName) elRef.classList.add(`${ANIMATION_CLASS_PREFIX}animated`, animationName)
const handleAnimationEnd = () => { const handleAnimationEnd = () => {
document.documentElement.style.removeProperty('--animate-duration') document.documentElement.style.removeProperty('--animate-duration')
elRef.classList.remove(`${ANIMATION_CLASS_PREFIX}animated`, animationName) elRef.classList.remove(`${ANIMATION_CLASS_PREFIX}animated`, animationName)

View File

@ -34,7 +34,10 @@
<IconLeftTwo class="tool-btn" theme="two-tone" :fill="['#111', '#fff']" @click="execPrev()" /> <IconLeftTwo class="tool-btn" theme="two-tone" :fill="['#111', '#fff']" @click="execPrev()" />
<IconRightTwo class="tool-btn" theme="two-tone" :fill="['#111', '#fff']" @click="execNext()" /> <IconRightTwo class="tool-btn" theme="two-tone" :fill="['#111', '#fff']" @click="execNext()" />
</div> </div>
<!-- 点赞组件 -->
<div style="z-index: 999;position: absolute;top:10px">
<upvote-vue ref="upvoteRef" :test='true' type="2"></upvote-vue>
</div>
<div <div
class="tools-right" :class="{ 'visible': rightToolsVisible }" class="tools-right" :class="{ 'visible': rightToolsVisible }"
@mouseleave="rightToolsVisible = false" @mouseleave="rightToolsVisible = false"
@ -69,7 +72,7 @@ import ScreenSlideList from './ScreenSlideList.vue'
import SlideThumbnails from './SlideThumbnails.vue' import SlideThumbnails from './SlideThumbnails.vue'
import WritingBoardTool from './WritingBoardTool.vue' import WritingBoardTool from './WritingBoardTool.vue'
import CountdownTimer from './CountdownTimer.vue' import CountdownTimer from './CountdownTimer.vue'
import upvoteVue from '@/views/tool/components/upvote.vue' // -
const props = defineProps<{ const props = defineProps<{
changeViewMode: (mode: 'base' | 'presenter') => void changeViewMode: (mode: 'base' | 'presenter') => void
}>() }>()

View File

@ -35,7 +35,7 @@ const getFileTypeIcon = () => {
txt: 'icon-txt', txt: 'icon-txt',
rar: 'icon-rar', rar: 'icon-rar',
apt: 'icon-A', apt: 'icon-A',
aippt: 'icon-A', aippt: 'icon-a-ziyuan91',
aiyuyin: 'icon-yuyin', // aiyuyin: 'icon-yuyin', //
aivideo: 'icon-dianying', // aivideo: 'icon-dianying', //
airobot: 'icon-jiqirenfushi', // airobot: 'icon-jiqirenfushi', //

View File

@ -15,10 +15,10 @@
</template> </template>
</el-dropdown> </el-dropdown>
<div> <div>
<el-button type="danger" link @click="removeItem(curTemplate, false)"> <el-button type="danger" link :disabled="!(templateList.length)" @click="removeItem(curTemplate, false)">
删除 删除
</el-button> </el-button>
<el-button type="primary" link @click="onAdd"> <el-button type="primary" link :disabled="!(templateList.length)" @click="onAdd">
<i class="iconfont icon-jiahao"></i> <i class="iconfont icon-jiahao"></i>
添加提示词 添加提示词
</el-button> </el-button>
@ -137,15 +137,17 @@ const curTemplate = reactive({ name: '', id: '' })
const templateList = ref([]) const templateList = ref([])
const childTempList = ref([]) const childTempList = ref([])
const getTemplateList = () => { const getTemplateList = () => {
modelList({ model: props.type, type: 1, pageNum: 1, pageSize: 10000 }).then(res => { modelList({ model: props.type, type: 1, pageNum: 1, pageSize: 10000, ex1: curNode.edustage, ex2: curNode.edusubject }).then(res => {
templateList.value = res.rows templateList.value = res.rows
Object.assign(curTemplate, res.rows[0]); if(res.rows.length > 0){
getChildTemplate() Object.assign(curTemplate, res.rows[0]);
getChildTemplate()
}
}) })
} }
const getChildTemplate = () => { const getChildTemplate = () => {
tempLoading.value = true tempLoading.value = true
modelList({ model: props.type, type: 2, parentId: curTemplate.id }).then(res => { modelList({ model: props.type, type: 2, parentId: curTemplate.id, ex1: curNode.edustage, ex2: curNode.edusubject }).then(res => {
childTempList.value = res.rows childTempList.value = res.rows
if(childTempList.value.length){ if(childTempList.value.length){
childTempList.value.forEach(item => item.answer = '') childTempList.value.forEach(item => item.answer = '')
@ -398,9 +400,9 @@ emitter.on('onGetMain', () => {
const curNode = reactive({}) const curNode = reactive({})
onMounted(() => { onMounted(() => {
getTemplateList()
let data = sessionStore.get('subject.curNode') let data = sessionStore.get('subject.curNode')
Object.assign(curNode, data); Object.assign(curNode, data);
getTemplateList()
let jsonKey = `${modeType.value}-${data.edustage}-${data.edusubject}` let jsonKey = `${modeType.value}-${data.edustage}-${data.edusubject}`
params.dataset_id = dataSetJson[jsonKey] params.dataset_id = dataSetJson[jsonKey]
}) })

View File

@ -93,6 +93,12 @@ const headerMenus = [
icon: 'icon-jiaoxueshijian', icon: 'icon-jiaoxueshijian',
path: '/prepare' path: '/prepare'
}, },
{
name: '教学活动',
id: 5,
icon: 'icon-zuoyepigai',
path: '/classTask'
},
{ {
name: '资源中心', name: '资源中心',
id: 3, id: 3,

View File

@ -44,9 +44,9 @@ const breadList = ref([])
watch( watch(
() => router.currentRoute.value, () => router.currentRoute.value,
(newValue) => { (newValue) => {
let path = newValue.path console.log(newValue)
const { showBread } = newValue.meta
if (path.includes('/model') && path !== ('/model/index')) { if (showBread) {
isShowBack.value = true isShowBack.value = true
breadList.value = newValue.matched.map(item => item.meta) breadList.value = newValue.matched.map(item => item.meta)
let data = sessionStore.get('subject.curNode') let data = sessionStore.get('subject.curNode')

View File

@ -8,8 +8,8 @@
<el-header> <el-header>
<Header/> <Header/>
</el-header> </el-header>
<el-main :style="{ 'padding-top' : isShowBread ? 0 : '20px'}"> <el-main style="padding-top : 20px">
<template v-if="isShowBread"> <!-- <template v-if="isShowBread">
<div class="bread-row"> <div class="bread-row">
<div class="back" @click="onBack"> <div class="back" @click="onBack">
<i class="iconfont icon-fanhui"></i> <i class="iconfont icon-fanhui"></i>
@ -19,8 +19,8 @@
<el-breadcrumb-item v-for="item in breadList"> {{ item.title }} </el-breadcrumb-item> <el-breadcrumb-item v-for="item in breadList"> {{ item.title }} </el-breadcrumb-item>
</el-breadcrumb> </el-breadcrumb>
</div> </div>
</template> </template> -->
<AppMain :style="{ height: isShowBread ? 'calc(100% - 45px)' : '100%' }" /> <AppMain />
</el-main> </el-main>
</el-container> </el-container>
<Uploader v-if="uploaderStore.uploadList && uploaderStore.uploadList.length > 0" /> <Uploader v-if="uploaderStore.uploadList && uploaderStore.uploadList.length > 0" />

View File

@ -47,19 +47,19 @@ export const constantRoutes = [
path: 'curriculum', path: 'curriculum',
component: () => import('@/views/curriculum-standards/index.vue'), component: () => import('@/views/curriculum-standards/index.vue'),
name: 'curriculum-standard', name: 'curriculum-standard',
meta: { title: '课标研读' } meta: { title: '课标研读', showBread: true }
}, },
{ {
path: 'teaching', path: 'teaching',
component: () => import('@/views/teaching-material/index.vue'), component: () => import('@/views/teaching-material/index.vue'),
name: 'teaching-material', name: 'teaching-material',
meta: { title: '教材研读' } meta: { title: '教材研读', showBread: true }
}, },
{ {
path: 'examination', path: 'examination',
component: () => import('@/views/examination-analysis/index.vue'), component: () => import('@/views/examination-analysis/index.vue'),
name: 'examination-analysis', name: 'examination-analysis',
meta: { title: '考试分析' } meta: { title: '考试分析', showBread: true }
}, },
{ {
path: 'management', path: 'management',
@ -71,13 +71,13 @@ export const constantRoutes = [
path: 'design', path: 'design',
component: () => import('@/views/teachingDesign/index.vue'), component: () => import('@/views/teachingDesign/index.vue'),
name: 'teaching-design', name: 'teaching-design',
meta: { title: '教学框架设计' }, meta: { title: '教学框架设计' , showBread: true},
}, },
{ {
path: 'newClassTaskAssign', path: 'newClassTaskAssign',
component: () => import('@/views/classTask/newClassTaskAssign/index.vue'), component: () => import('@/views/classTask/newClassTaskAssign/index.vue'),
name: 'newClassTaskAssign', name: 'newClassTaskAssign',
meta: { title: '作业管理' } meta: { title: '作业设计', showBread: true }
}, },
{ {
path: 'questionUpload', path: 'questionUpload',
@ -89,7 +89,7 @@ export const constantRoutes = [
path: 'aiKolors', path: 'aiKolors',
component: () => import('@/components/ai-kolors/index.vue'), component: () => import('@/components/ai-kolors/index.vue'),
name: 'aiKolors', name: 'aiKolors',
meta: { title: '文生图片' } meta: { title: '文生图片', showBread: true }
}, },
] ]
}, },
@ -132,7 +132,7 @@ const dynamicRoutes = [
path: 'prepare', path: 'prepare',
component: () => import('@/views/prepare/index.vue'), component: () => import('@/views/prepare/index.vue'),
name: 'prepare', name: 'prepare',
meta: { title: '教学实践', showBread: true } meta: { title: '教学实践' }
}, },
{ {
path: 'newClassTask', path: 'newClassTask',
@ -152,13 +152,6 @@ const dynamicRoutes = [
name: 'classCorrect', name: 'classCorrect',
meta: { title: '作业批改', showBread: true } meta: { title: '作业批改', showBread: true }
}, },
{
path: '/teach',
component: () => import('@/views/teach/index.vue'),
name: 'teach',
meta: { title: '授课' }
},
{ {
path: '/profile', path: '/profile',
component: () => import('@/views/profile/index.vue'), component: () => import('@/views/profile/index.vue'),

View File

@ -461,7 +461,6 @@ watch(tabActive, (newVal,oldVal)=>{
height: 100%; height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 15px 30px;
.class-reserv-tabs { .class-reserv-tabs {
width: 30%; width: 30%;
text-align: left; text-align: left;

View File

@ -703,6 +703,7 @@ const handleClassWorkSave = async () => {
entpcourseworklist: '', // list entpcourseworklist: '', // list
}; };
if(cform.uniquekey.trim() == '') return ElMessage({ type: 'warning', message: '作业名称不能为空!'});
// [] newWorkSpaceEdit true // [] newWorkSpaceEdit true
if(classWorkForm.id != '' ) {// id if(classWorkForm.id != '' ) {// id
@ -741,6 +742,7 @@ const handleClassWorkSave = async () => {
} }
} }
else if(classWorkForm.worktype === "常规作业"){ else if(classWorkForm.worktype === "常规作业"){
if (classWorkForm.fileHomeworkList.length == 0) return ElMessage({ type: 'warning', message: '请上传常规作业附件!'});
fileLoading.value = true fileLoading.value = true
cform.workcodes = JSON.stringify(classWorkForm.fileHomeworkList); cform.workcodes = JSON.stringify(classWorkForm.fileHomeworkList);
cform.entpcourseworklist = JSON.stringify([{'id':-2, 'score': '10'}]); cform.entpcourseworklist = JSON.stringify([{'id':-2, 'score': '10'}]);
@ -832,7 +834,12 @@ const editWork = async (cform) =>{
} }
}else if (classWorkForm.worktype == '课堂展示' || classWorkForm.worktype == '常规作业') { }else if (classWorkForm.worktype == '课堂展示' || classWorkForm.worktype == '常规作业') {
// //
//
if(classWorkForm.worktype == '课堂展示'){
//
}else{
if (classWorkForm.fileHomeworkList.length == 0) return ElMessage({ type: 'warning', message: '请上传常规作业附件!'});
}
}else { }else {
if (classWorkForm.chooseWorkLists.length == 0) { if (classWorkForm.chooseWorkLists.length == 0) {
// //

View File

@ -134,7 +134,6 @@ onMounted(() => {
<style lang="scss" scoped> <style lang="scss" scoped>
.page-newcalsetask { .page-newcalsetask {
padding-top: 10px;
height: 100%; height: 100%;
overflow: hidden; overflow: hidden;

View File

@ -489,6 +489,7 @@ const handleClassWorkFormQuizRemove = (index) =>{
entpcourseworklist: '', // list entpcourseworklist: '', // list
}; };
if(cform.uniquekey.trim() == '') return ElMessage({ type: 'warning', message: '作业名称不能为空!'});
// [] newWorkSpaceEdit true // [] newWorkSpaceEdit true
if(isShow.value === false){ if(isShow.value === false){
@ -530,6 +531,7 @@ const handleClassWorkFormQuizRemove = (index) =>{
} }
} }
else if(classWorkForm.worktype === "常规作业"){ else if(classWorkForm.worktype === "常规作业"){
if (classWorkForm.fileHomeworkList.length == 0) return ElMessage({ type: 'warning', message: '请上传常规作业附件!'});
fileLoading.value = true fileLoading.value = true
cform.workcodes = JSON.stringify(classWorkForm.fileHomeworkList); cform.workcodes = JSON.stringify(classWorkForm.fileHomeworkList);
cform.entpcourseworklist = JSON.stringify([{'id':-2, 'score': '10'}]); cform.entpcourseworklist = JSON.stringify([{'id':-2, 'score': '10'}]);
@ -634,7 +636,11 @@ const editWork = async (cform) =>{
} }
}else if (classWorkForm.worktype == '课堂展示' || classWorkForm.worktype == '常规作业') { }else if (classWorkForm.worktype == '课堂展示' || classWorkForm.worktype == '常规作业') {
// //
if(classWorkForm.worktype == '课堂展示'){
//
}else{
if (classWorkForm.fileHomeworkList.length == 0) return ElMessage({ type: 'warning', message: '请上传常规作业附件!'});
}
}else { }else {
if (classWorkForm.chooseWorkLists.length == 0) { if (classWorkForm.chooseWorkLists.length == 0) {
// //

View File

@ -1,388 +1,461 @@
<template> <template>
<div class="page-resource flex mb-4"> <el-row class="model-wrap">
<!-- 左侧 教材 目录 -->
<!-- <ChooseTextbook @change-book="getData" @node-click="getData" /> -->
<div class="page-right">
<div class="button-container">
<el-button type="primary" @click="onchange('/model/curriculum')">课标研读</el-button>
<!-- <el-button type="primary" @click="onchange('/model/management')">作业管理1</el-button> -->
<el-button type="primary" @click="onchange('/model/newClassTaskAssign')">作业管理</el-button>
<el-button type="success" @click="onchange('/model/teaching')">教材研读</el-button>
<el-button type="info" @click="onchange('/model/design')">教学框架设计</el-button>
<!-- <el-button type="success" @click="openPPTist">打开PPTist</el-button>-->
<el-button type="info" @click="onchange('/model/examination')">考试分析</el-button>
<el-button type="primary" v-menus="dt.menus">测试</el-button>
<el-button type="success" @click="onchange('/model/aiKolors')">文生图片</el-button>
</div>
</div>
</div>
<el-row class="container">
<!-- 左侧 选择教材 目录 --> <!-- 左侧 选择教材 目录 -->
<ChooseTextbook @change-book="changeBook" @node-click="changeBook" /> <ChooseTextbook @change-book="changeBook" @node-click="changeBook" />
<!-- 中间 展示内容 --> <!-- 右侧 展示内容 -->
<el-col :span="10"> <div class="right-content">
<div class="c-item mb-4 mx-4"> <div class="content-header-wrap">
<div class="flex justify-between pb-2"> <div v-for="(item,index) in tags" :key="index" :style="{'background-color':item.bgcolor}" @click="onchange(item)">
<h3>教师资源</h3> <el-icon class="item-icon"><Flag /></el-icon>
<span class="c-btns"> <div class="content-header-title">{{item.name}}</div>
<template v-for="item in resourBtns"> <div class="content-header-body">
<el-button :size="item.size" text :icon="item.icon" @click="handleAll(item.prop)">{{ item.name }}</el-button> <div class="content-header-num">6</div>
</template> <div class="content-header-text">分析结果</div>
</span> </div>
</div> </div>
<c-table ref="resourRef" v-bind="sourceOpt" t-class="rounded">
<template #title="{row,value}">
<el-link :underline="false" @click="handleAll('open', row)">
<svg class="icon svg-icon" aria-hidden="true">
<use :xlink:href="`#icon-${getIcon(row)}`"></use>
</svg>
<b class="ml-1">{{ value }}</b>
</el-link>
</template>
</c-table>
</div> </div>
</el-col> <div class="content-body-wrap">
<div class="content-body-left">
<div class="content-body-left-title">
文枢课件
<el-button class="add-btn" size="small" type="primary" @click="createAIPPT">新建</el-button>
</div>
<div class="content-body-left-body">
<kj-list-item
v-for="(item, index) in currentFileList"
:key="index"
:ref="collectRef('kjItemRef'+item.id)"
:item="item"
:show-tool="false"
:index="index"
:curNode="currentNode"
@on-delete="deleteTalk"
@change="changeClass"
>
</kj-list-item>
<!-- <div class="content-body-left-item" v-for="item in 5">
<div class="content-body-left-item-img">
<FileImage :size="50" :file-name="'aaa.aippt'" />
</div>
<div class="content-body-left-item-text">
<div class="content-body-left-item-title">沁园春*长沙</div>
<div class="content-body-left-item-info">21 访问 100 引用 50 点赞 20 更新时间 2022-01-01 15:20</div>
</div>
<div></div>
</div>-->
</div>
</div>
<div class="content-body-right">
<div class="content-body-right-title">模型辅助工具</div>
<div class="content-body-right-body">
<div class="content-body-right-item" v-for="(item,index) in tools" :key="index" @click="gotoRoute(item)">
<div class="content-body-right-item-img">
<FileImage :fileName="item.img"/>
</div>
<div class="content-body-right-item-text">{{item.name}}</div>
</div>
</div>
</div>
</div>
</div>
</el-row> </el-row>
</template> </template>
<script setup> <script setup>
import { onMounted, ref, watch, reactive } from 'vue' import { onMounted, reactive, ref, nextTick } from 'vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { Plus, Refresh, Upload, Files, UploadFilled } from '@element-plus/icons-vue'
import useUserStore from '@/store/modules/user' // import useUserStore from '@/store/modules/user' //
import msgUtils from '@/plugins/modal' //
import { createWindow } from '@/utils/tool' //
import * as API_smarttalk from '@/api/file' // api
import * as API_entpcourse from '@/api/education/entpcourse' // api
import * as API_entpcoursefile from '@/api/education/entpcoursefile' // api
import { dataSetJson } from '@/utils/comm' // id
import { sessionStore } from '@/utils/store' //
// //
import ChooseTextbook from '@/components/choose-textbook/index.vue' import ChooseTextbook from '@/components/choose-textbook/index.vue'
import { menusEvent } from '@/plugins/vue3-menus' // import KjListItem from '@/views/prepare/container/kj-list-item.vue'
import FileImage from '@/components/file-image/index.vue'
import {creatAPT, getSmarttalkPage} from '@/api/file'
import {Flag, Position} from '@element-plus/icons-vue'
import {asyncLocalFile, parseCataByNode} from "@/utils/talkFile";
import { dataSetJson } from '@/utils/comm' // id
import { sessionStore } from '@/utils/store'
import {listEntpcourse} from "@/api/teaching/classwork";
import {addEntpcoursefileReturnId, getEntpcoursefile} from "@/api/education/entpcoursefile";
import {createWindow, ipcMsgSend} from "@/utils/tool";
import {ElMessage} from "element-plus"; //
const router = useRouter() const router = useRouter()
const userStore = useUserStore() // const userStore = useUserStore().user //
const currentNode = ref({})
const refs = ref([]);
const courseObj = reactive({ const collectRef = (key) => {
// : id,id,id, return (el) => {
textbookId: '', refs.value[key] = el;
levelFirstId: '', };
levelSecondId: '', };
coursetitle: '',
node: null, //
entp: null, //
})
const dt = reactive({
curRow: null, //
menus: [ //
{ label: '打开', click: (_, args) => handleAll('open', args) },
{ label: '删除', click: (_, args) => handleAll('delete', args) },
],
})
// ref
const resourRef = ref() // ref
//
const resourBtns = [
{ name: '刷新', prop: 'refresh', size: 'small', icon: Refresh },
{ name: '资源库', prop:'resource', size:'small', icon: Files },
{ name: '上传', prop:'upload', size:'small', icon: UploadFilled },
{ name: '添加', prop:'add', size:'small', icon: Plus },
]
// -cTable
const sourceOpt = reactive({
data: [], //
option: [ //
{ label: '名称', prop: 'title', align: 'left' },
{ label: '类型', prop: 'filetype', width: 80, },
{ label: '时间', prop: 'timestamp', width: 160, sortable: true },
],
noPage: true, //
isMain: false, //
highlightCurrentRow: true, //
rowClick: (r, c, e) => { // -()
if (dt.curRow == r) { // -
resourRef.value.$refs.table.setCurrentRow()
dt.curRow = null
} else dt.curRow = r
},
rowContextmenu: (r, c, e) => { //
dt.menus.forEach(item => {
if(item.label == '打开') item.icon = getIcon(r, 'svg')
else if(item.label == '删除') item.icon = getIcon('icon-shanchu', 'class')
})
menusEvent(e, dt.menus, r)
},
})
const tags = reactive([{
name: '课标分析',
path: '/model/curriculum',
bgcolor: 'rgb(241,65,108)'
},{
name: '教材分析',
path: '/model/teaching',
bgcolor: 'rgb(114,57,234)'
},{
name: '考试分析',
path: '/model/examination',
bgcolor: 'rgb(251,132,4)'
},{
name: '素材设计',
path: '/model/aiKolors',
bgcolor: 'rgb(25,123,237)'
},{
name: '作业设计',
path: '/model/newClassTaskAssign',
bgcolor: 'rgb(23,198,83)'
},{
name: '框架设计',
path: '/model/design',
bgcolor: 'rgb(34,35,43)'
}])
const tools = reactive([{
name: '数字人生成',
path: '',
img: 'airobot'
},{
name: '语音生成',
path: '',
img: 'aiyuyin'
},{
name: '文生图片',
path: '/model/aiKolors',
img: 'aiimg'
},{
name: '文生连环画',
path: '',
img: 'aidraw'
},{
name: '视频生成',
path: '',
img: 'aivideo'
}])
const uploadData = ref({
textbookId: null,
levelFirstId: null,
levelSecondId: null,
fileSource: '个人',
fileRoot: '备课'
})
const currentFileList = ref([])
// //
onMounted(() => { onMounted(() => {
}) })
// -methods const gotoRoute = (item) => {
if (item.path) {
if (item.path === '/model/aiKolors') {
gotoAiKolors(item.path)
}else {
router.push(item.path)
}
}
}
const createAIPPT = () => {
console.log(userStore)
listEntpcourse({
evalid: currentNode.value.id,
edituserid: userStore.userId,
pageSize: 500
}).then((response) => {
if (response.rows.length <= 0) return
let resCourse = response.rows[0]
//
let form = {
parentid: 0,
entpid: userStore.deptId,
entpcourseid: resCourse.id,
ppttype: 'file',
title: resCourse.coursetitle,
fileurl: '',
filetype: 'aippt',
datacontent: '',
filekey: '',
filetag: '',
fileidx: 0,
dflag: 0,
status: '',
edituserid: userStore.userId
}
addEntpcoursefileReturnId(form).then((slideid) => {
//
var form = {
parentid: slideid,
entpid: resCourse.entpid,
entpcourseid: resCourse.id,
title: '第一页',
filetype: 'slide',
datacontent: '{"elements":[],"background":{"type":"solid","color":"#fff"}}',
edituserid: userStore.userId
}
addEntpcoursefileReturnId(form).then((res) => {
creatAPT({
...uploadData.value,
fileId: slideid,
fileFlag: 'aippt',
fileShowName: currentNode.value.itemtitle + '.aippt'
}).then(async (res) => {
currentFileList.value.unshift(res.resData)
await nextTick();
refs.value['kjItemRef'+res.resData.id].openFileWin(res.resData);
})
})
})
})
}
const deleteTalk = (item) => {
let index = currentFileList.value.indexOf(item)
currentFileList.value.splice(index, 1)
}
// //
const changeBook = async(data) => { const changeBook = async(data) => {
// console.log(data) console.log(data)
const { textBook, node } = data let cata = parseCataByNode(data.node)
let textbookId = textBook.curBookId currentNode.value = data.node
let levelSecondId = node.id uploadData.value.levelFirstId = cata[0]
let levelFirstId uploadData.value.levelSecondId = cata[1]
if (node.parentNode) { uploadData.value.levelThirdId = cata[2]
levelFirstId = node.parentNode.id uploadData.value.textbookId = data.textBook.curBookId
} else { getSmarttalkPage({
levelFirstId = node.id ...uploadData.value,
levelSecondId = '' orderByColumn: 'createTime',
} fileFlags: "'aippt'",
isAsc: 'desc',
courseObj.textbookId = textbookId // pageSize: 500
courseObj.levelFirstId = levelFirstId // }).then((res) => {
courseObj.levelSecondId = levelSecondId // currentFileList.value = [...res.rows]
courseObj.coursetitle = node.itemtitle // (/) })
courseObj.node = node; //
// ID
localStorage.setItem('unitId', JSON.stringify({ levelFirstId, levelSecondId }))
//
const params = { evalid: node.id, edituserid: userStore.id, pageSize: 1 }
const res = await HTTP_SERVER_API('getCourseList', params)
courseObj.entp = res?.rows?.[0] || null
sessionStore.set('curr.entp', courseObj.entp) //
// -
getResourceList()
} }
const onchange = (item) => {
const openPPTist = () => { let path = item.path
createWindow('open-win', { url: '/pptist' })
}
const onchange = (path) => {
if (path == '/model/newClassTaskAssign') { if (path == '/model/newClassTaskAssign') {
uploadData.value.coursetitle = currentNode.value.itemtitle // (/)
uploadData.value.node = currentNode.value; //
// //
router.push({ path, query: { courseObj: JSON.stringify(courseObj) } }) router.push({ path, query: { courseObj: JSON.stringify(uploadData.value) } })
} else if (path == '/model/aiKolors') { } else if (path == '/model/aiKolors') {
// ai gotoAiKolors(path)
let subjectdata = sessionStore.get('subject.curNode')
let datasubject = `课标-${subjectdata.edustage}-${subjectdata.edusubject}`
console.log(subjectdata)
router.push({
path,
query: {
datasetId: dataSetJson[datasubject],
coursetitle: courseObj.coursetitle,
levelFirstId: subjectdata.parentid,
levelSecondId: subjectdata.id,
textbookId: subjectdata.rootid,
}
});
} else { } else {
router.push(path) router.push(path)
} }
} }
//
const getResourceList = async () => { const gotoAiKolors = (path)=> {
const entpcourseidarray = courseObj?.entp?.id // ai
if (!entpcourseidarray) return msgUtils.msgWarning('请选择章节?') let subjectdata = sessionStore.get('subject.curNode')
const params = { let datasubject = `课标-${subjectdata.edustage}-${subjectdata.edusubject}`
pageSize: 100, parentid: 0, entpcourseidarray, console.log(subjectdata)
orderByColumn: 'timestamp', isAsc: 'desc', router.push({
} path,
const res = await HTTP_SERVER_API('getCourseFileList', params) query: {
if (res?.code == 200) { datasetId: dataSetJson[datasubject],
sourceOpt.data = res?.rows || [] coursetitle: currentNode.value.itemtitle,
} else { levelFirstId: subjectdata.parentid,
msgUtils.msgWarning('获取资源列表, 请重试') levelSecondId: subjectdata.id,
} textbookId: subjectdata.rootid,
}
});
} }
// HTTP
const HTTP_SERVER_API = (type, params = {}) => { const changeClass = async (type, row, other) => {
switch (type) { switch(type) {
case 'addSmarttalk': { // case 'click': { // --aippt
const def = { if (row.fileFlag === 'aippt' && !!row.fileId) {
fileId: '', // id - Entpcoursefile id const res = await getEntpcoursefile(row.fileId)
fileFlag: 'aippt', if (res && res.code === 200) {
fileShowName: courseObj.coursetitle + '.aippt', sessionStore.set('curr.resource', res.data) //
textbookId: courseObj.textbookId, sessionStore.set('curr.smarttalk', row) // smarttalk
levelFirstId: courseObj.levelFirstId, createWindow('open-win', {
levelSecondId: courseObj.levelSecondId, url: '/pptist', //
fileSource: '个人', close: () => {
fileRoot: '备课' sessionStore.set('curr.resource', null) //
} sessionStore.set('curr.smarttalk', null) //
return API_smarttalk.creatAPT({...def, ...params}) getSmarttalkPage({
} ...uploadData.value,
case 'addEntpcourse': { // orderByColumn: 'createTime',
const node = courseObj.node || {} fileFlags: "'aippt'",
if (!node) return msgUtils.msgWarning('请选择章节?') isAsc: 'desc',
const def = { // pageSize: 500
entpid: userStore.user.deptId, // id }).then((res) => {
level: 1, // currentFileList.value = [...res.rows]
parentid: 0, // id })
dictid: 0, // id }
evalid: node.id, // id })
evalparentid: node.parentid, // id(id) } else {
edusubject: node.edusubject, // ElMessage.warning(res.msg||'文件获取异常!')
edudegree: node.edudegree, //
edustage: node.edustage, //
coursetype: '课标学科', //
coursetitle: node.itemtitle, //
coursedesc: '', //
status: '', //
dflag: 0, //
edituserid: userStore.id, // id
createblankfile: 'no', //
}
courseObj.entp = def
return API_entpcourse.addEntpcourse(def)
}
case 'addEntpcoursefile': { //
const enpt = courseObj.entp
const def = {
parentid: 0,
entpid: userStore.user.deptId,
entpcourseid: enpt.id,
ppttype: 'file',
title: enpt.coursetitle,
fileurl: '',
filetype: 'aippt',
datacontent: '',
filekey: '',
filetag: '',
fileidx: 0,
dflag: 0,
status: '',
edituserid: userStore.id
}
// return Promise.resolve(1)
return API_entpcoursefile.addEntpcoursefileReturnId({...def,...params})
}
case 'getCourseList': { //
return API_entpcourse.listEntpcourse(params)
}
case 'getCourseFileList':{ //
return API_entpcoursefile.listEntpcoursefileNew(params)
}
}
}
//
const handleAll = async(type, row) =>{
// console.log(type)
switch (type) {
case 'refresh': //
getResourceList()
break;
case 'resource': //
break;
case 'upload': //
break;
case 'add':{ // PPT-list -
const enpt = courseObj.entp //
if (!enpt) { //
const resid = await HTTP_SERVER_API('addEntpcourse')
courseObj.entp.id = resid
}
// ppt-
const p_params = {parentContent: '{"width":1000,"ratio":0.5625}'}
const id = await HTTP_SERVER_API('addEntpcoursefile', p_params)
if (!!id??null) { //
const params = {
parentid: id,
title: '第一页',
filetype: 'slide',
datacontent: '{"elements":[],"background":{"type":"solid","color":"#fff"}}' // json
} }
// ppt-(slide) return
await HTTP_SERVER_API('addEntpcoursefile', params)
// -Smarttalk
await HTTP_SERVER_API('addSmarttalk',{fileId: id})
//
await getResourceList()
} else {
msgUtils.msgWarning('添加失败!')
} }
break; ElMessage.warning('该功能暂未开放!')
}
case 'open': { // -pptist
if (row.filetype != 'aippt') return msgUtils.msgWarning('暂不支持该类型文件操作!')
sessionStore.set('curr.resource', row) //
createWindow('open-win', {
url: '/pptist', //
close: () => {
sessionStore.set('curr.resource', null) //
getResourceList() //
}
})
break break
} }
case 'delete':{ // default:
if (!(row && row.id)) return msgUtils.msgWarning('请选择要删除的资源!') break
await msgUtils.confirm(`是否确认删除【${row.title}】课程课件?`)
await API_entpcoursefile.delEntpcoursefileNew(row.id)
msgUtils.msgSuccess('删除成功!')
//
await getResourceList()
break;
}
} }
} }
// icons type svg
const getIcon = (o, type) => {
let icon = typeof o == 'string' ? o : o?.filetype
if (['aippt'].includes(o?.filetype)) icon = 'pptx'
if (!!type) { // icon
switch(type) {
case 'svg': // svg
return `<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-${icon}"></use>
</svg>`
case 'class': // class
return `<span class="icon iconfont ${icon}"></span>`
case 'unicode': // unicode
return `<span class="icon iconfont">${icon}</span>`
default: // icon-class
return `icon-${icon}`
}
}
return icon
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.page-resource { .model-wrap{
// height: 100%; width: 100%;
// padding: 10px 15px 0; height: 100%;
display: flex;
.page-right { flex-direction: row;
min-width: 0; .right-content{
flex: 1;
margin-left: 20px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 1;
// margin-left: 20px;
height: 100%; height: 100%;
background: #ffffff; .content-header-wrap{
border-radius: 10px; display: flex;
box-shadow: 0px 0px 20px 0px rgba(99, 99, 99, 0.06); flex-direction: row;
} justify-content: space-between;
align-items: center;
.button-container { width: 100%;
display: flex; //height: 215px;
flex-wrap: wrap; &>div{
gap: 10px; &:hover{
margin: 1rem; cursor: pointer;
justify-content: flex-start; }
width: calc(100%/6 - 10px);
.el-button { aspect-ratio: 0.718 / 1;
flex: 1 1 15%; border-radius: 10px;
max-width: 15%; color: white;
min-width: 15%; text-align: left;
box-sizing: border-box; background-color: #999999;
position: relative;
.item-icon{
position: absolute;
top: 10px;
left: 20px;
font-size: calc(1.8vw);
}
.content-header-title{
position: absolute;
bottom: 50%;
width: 100%;
font-size: calc(1.8vw);
padding-left: 20px;
}
.content-header-body{
position: absolute;
bottom: 0;
background-color: rgba(0, 0, 0, 0.27);
width: 100%;
height: 25%;
padding-left: 20px;
display: flex;
flex-direction: column;
justify-content: center;
font-size: calc(1vw);
border-radius: 0 0 10px 10px;
.content-header-num{
}
.content-header-text{
}
}
}
} }
} .content-body-wrap{
} display: flex;
.container{ flex-direction: row;
height: calc(100% - 32px - 3rem); justify-content: space-between;
.c-item{ margin-top: 20px;
.c-btns{ flex: 1;
.el-button{margin: 0;} overflow: auto;
height: 100%;
border-radius: 10px;
.content-body-left{
width: calc(50% - 7px);
background-color: white;
border-radius: 10px;
display: flex;
flex-direction: column;
.content-body-left-title{
text-align: left;
padding: 10px;
font-weight: bold;
position: relative;
height: 40px;
.add-btn{
position: absolute;
right: 10px;
}
}
.content-body-left-body{
flex: 1;
overflow: auto;
.content-body-left-item{
display: flex;
flex-direction: row;
border-bottom: 1px solid rgba(153, 153, 153, 0.29);
padding: 10px 0;
.content-body-left-item-img{
padding: 0 10px;
}
.content-body-left-item-text{
text-align: left;
.content-body-left-item-title{
font-weight: bold;
font-size: 16px;
}
.content-body-left-item-info{
font-size: 14px;
}
}
}
}
}
.content-body-right{
width: calc(50% - 8px);
background-color: white;
border-radius: 10px;
.content-body-right-title{
text-align: left;
padding: 10px;
font-weight: bold;
}
.content-body-right-body{
display: flex;
.content-body-right-item{
&:hover{
cursor: pointer;
}
height: 80px;
width: 100px;
display: flex;
flex-direction: column;
align-items: center;
.content-body-right-item-img{
display: flex;
justify-content: center;
align-items: center;
width: 50px;
height: 50px;
border-radius: 25px;
border: 1px solid rgba(153, 153, 153, 0.18);
img{
border-radius: 25px;
width: 25px;
}
}
.content-body-right-item-text{
font-size: 14px;
}
}
}
}
} }
} }
} }

View File

@ -61,7 +61,7 @@
">{{formatDate(item.createTime, 'yyyy-MM-dd hh:mm:ss')}}</div> ">{{formatDate(item.createTime, 'yyyy-MM-dd hh:mm:ss')}}</div>
</div> </div>
</div> </div>
<div class="prepare-body-main-item-btn"> <div class="prepare-body-main-item-btn" v-if="showTool">
<!-- <el-button v-if="activeClassId==item.id" type="success" @click="clickStartClass(item)">上课中</el-button> --> <!-- <el-button v-if="activeClassId==item.id" type="success" @click="clickStartClass(item)">上课中</el-button> -->
<el-button type="primary" @click="clickStartClass(item)">上课</el-button> <el-button type="primary" @click="clickStartClass(item)">上课</el-button>
</div> </div>
@ -145,6 +145,10 @@ export default {
activeClassId: { // id activeClassId: { // id
type: String, type: String,
default: '' default: ''
},
showTool: { //
type: Boolean,
default: true
} }
}, },
expose: ['openFileWin'], expose: ['openFileWin'],
@ -414,6 +418,11 @@ export default {
width: 100% !important; width: 100% !important;
} }
} }
.prepare-popper{
width: 80px !important;
min-width: 80px !important;
padding: 5px !important;
}
</style> </style>
<style scoped lang="scss"> <style scoped lang="scss">
.prepare-body-main-item { .prepare-body-main-item {

View File

@ -104,10 +104,10 @@
</file-list-item> </file-list-item>
</el-checkbox-group> </el-checkbox-group>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="作业" name="作业"> <el-tab-pane label="教学活动" name="教学活动">
<div class="prepare-body-header"> <div class="prepare-body-header">
<div> <div>
<label style="font-size: 15px">{{ currentWorkList.length }}作业</label>&nbsp; <label style="font-size: 15px">{{ currentWorkList.length }}教学活动</label>&nbsp;
<!-- <el-button size="small" @click="handleOutLink('homeWork')">作业设计</el-button> --> <!-- <el-button size="small" @click="handleOutLink('homeWork')">作业设计</el-button> -->
<el-button size="small" @click="goNewClassTask()">作业设计</el-button> <el-button size="small" @click="goNewClassTask()">作业设计</el-button>
</div> </div>
@ -249,7 +249,7 @@ export default {
activeAptTab: "教学课件", activeAptTab: "教学课件",
uploadData: { uploadData: {
textbookId: null, textbookId: null,
levelFirstId: 39103, levelFirstId: null,
levelSecondId: null, levelSecondId: null,
fileSource: '个人', fileSource: '个人',
fileRoot: '备课' fileRoot: '备课'
@ -898,7 +898,7 @@ export default {
this.isLoading = true this.isLoading = true
return getSmarttalkPage({ return getSmarttalkPage({
...this.uploadData, ...this.uploadData,
orderByColumn: 'uploadTime', orderByColumn: 'createTime',
isAsc: 'desc', isAsc: 'desc',
pageSize: 500 pageSize: 500
}) })

View File

@ -53,7 +53,7 @@ export default defineStore('resource', {
fileFlags: resourceType[0].value, fileFlags: resourceType[0].value,
fileRoot: '资源', fileRoot: '资源',
fileName: '', fileName: '',
orderByColumn: 'uploadTime', orderByColumn: 'createTime',
isAsc: 'desc', isAsc: 'desc',
...structQuery ...structQuery
}, },

View File

@ -1,13 +0,0 @@
<template>
<div>
授课Page
</div>
</template>
<script setup>
</script>
<style lang="scss" scoped>
</style>

View File

@ -346,7 +346,6 @@ onMounted(async () => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.page-con { .page-con {
padding-top: 20px;
height: 100%; height: 100%;
&-left{ &-left{
width: 300px; width: 300px;

View File

@ -362,7 +362,6 @@ onMounted(async () => {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.page-con { .page-con {
padding-top: 20px;
height: 100%; height: 100%;
&-left{ &-left{
width: 300px; width: 300px;

View File

@ -203,7 +203,7 @@ const openFileLink = async (item) =>{
// //
const getResource = () => { const getResource = () => {
let querySearch = toRaw(toolStore.curSubjectNode).querySearch let querySearch = toRaw(toolStore.curSubjectNode).querySearch
querySearch.orderByColumn = 'uploadTime' querySearch.orderByColumn = 'createTime'
querySearch.isAsc = 'desc' querySearch.isAsc = 'desc'
querySearch.pageSize = 500 querySearch.pageSize = 500