Merge branch 'main' into zouyf_dev
This commit is contained in:
commit
35c088c25a
|
@ -34,7 +34,7 @@ export default defineConfig({
|
|||
'/dev-api': {
|
||||
target: 'http://27.128.240.72:7865',
|
||||
// target: 'http://36.134.181.164:7863',
|
||||
// target: 'http://192.168.2.52:7863',
|
||||
// target: 'http://192.168.0.102:7865',
|
||||
changeOrigin: true,
|
||||
rewrite: (p) => p.replace(/^\/dev-api/, '')
|
||||
},
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
"file-saver": "^2.0.5",
|
||||
"hfmath": "^0.0.2",
|
||||
"html-to-image": "^1.11.11",
|
||||
"html2canvas": "^1.4.1",
|
||||
"im_electron_sdk": "^8.0.5904",
|
||||
"js-cookie": "^3.0.5",
|
||||
"jsencrypt": "^3.3.2",
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:"
|
||||
/> -->
|
||||
<meta http-equiv="Content-Security-Policy" content="connect-src * blob: data:; default-src 'self'; script-src 'self' 'unsafe-eval' http://www.wiris.net 'unsafe-inline'; style-src 'self' 'unsafe-inline' http://www.wiris.net; media-src * blob:;img-src * 'self' data: blob:;font-src 'self' http://www.wiris.net;" />
|
||||
<meta http-equiv="Content-Security-Policy" content="connect-src * blob: data:; default-src 'self' https://wzyzoss.eos-chongqing-3.cmecloud.cn/; script-src 'self' 'unsafe-eval' http://www.wiris.net 'unsafe-inline'; style-src 'self' 'unsafe-inline' http://www.wiris.net; media-src * blob:;img-src * 'self' data: blob:;font-src 'self' http://www.wiris.net;" />
|
||||
|
||||
</head>
|
||||
|
||||
|
|
|
@ -60,14 +60,6 @@ window.addEventListener('unload', () => {
|
|||
const newDiscardedDB = JSON.stringify(discardedDBList)
|
||||
localStorage.setItem(LOCALSTORAGE_KEY_DISCARDED_DB, newDiscardedDB)
|
||||
})
|
||||
/** 接口类型 */
|
||||
interface Result {
|
||||
code?: number,
|
||||
msg?: string,
|
||||
data?: any
|
||||
rows?: Array<any>,
|
||||
total?: number
|
||||
}
|
||||
// 获取参数
|
||||
const initLoad: Function = () => {
|
||||
// 获取缓存的ppt 资源数据
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
* @date 2024-11-26
|
||||
*/
|
||||
import { toRaw } from 'vue'
|
||||
import type { Result } from './types' // 接口类型
|
||||
import msgUtils from '@/plugins/modal' // 消息工具
|
||||
import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api
|
||||
import * as API_smarttalk from '@/api/file' // 相关api
|
||||
import * as useStore from '../store' // pptist-状态管理
|
||||
import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
||||
import useUserStore from '@/store/modules/user' // 外部-用户信息
|
||||
|
@ -53,6 +55,7 @@ export class PPTApi {
|
|||
return new Promise(async (resolve, reject) => {
|
||||
const params: object = { parentid, orderByColumn: 'fileidx', isAsc: 'asc', pageSize: 9999 }
|
||||
const res: Result = await API_entpcoursefile.listEntpcoursefileNew(params)
|
||||
console.log(res.rows,'res.rows');
|
||||
if (res.code === 200) {
|
||||
const slides = (res.rows || []).map(o => {
|
||||
if (!!o.datacontent) {
|
||||
|
@ -63,8 +66,15 @@ export class PPTApi {
|
|||
// 如果没有数据,默认空白页
|
||||
return {id: o.id,elements:[],background:{type:"solid",color:"#fff"}}
|
||||
})
|
||||
// 活动列表处理
|
||||
const workList = (res.rows || []).map(o => o.activityContent)
|
||||
const workItem = [...res.rows]
|
||||
slidesStore.updateSlideIndex(0) // 下标0 为第一页
|
||||
slidesStore.setSlides(slides) // 写入数据
|
||||
// 写入作业列表数据
|
||||
slidesStore.setWorkList(workList)
|
||||
// 获取所有的pptlist的数据
|
||||
slidesStore.setWorkItem(workItem)
|
||||
resolve(true)
|
||||
} else msgUtils.msgError(res.msg || '获取数据失败');resolve(false)
|
||||
})
|
||||
|
@ -166,6 +176,14 @@ export class PPTApi {
|
|||
} else msgUtils.msgError(res.msg || '删除失败');resolve(false)
|
||||
})
|
||||
}
|
||||
|
||||
// 更新-备课资源 标题
|
||||
static updateSmarttalk(data: object): Promise<Boolean> {
|
||||
return API_smarttalk.updateSmarttalk(data).then(res => {
|
||||
if (res.code === 200) return true
|
||||
else msgUtils.msgError(res.msg || '更新失败');return false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default PPTApi
|
|
@ -2,6 +2,7 @@
|
|||
* @description api 无store循环引用
|
||||
* @author zdg
|
||||
*/
|
||||
import type { Result } from './types' // 接口类型
|
||||
import msgUtils from '@/plugins/modal' // 消息工具
|
||||
import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
/** 返回-接口类型 */
|
||||
export interface Result {
|
||||
code?: number,
|
||||
msg?: string,
|
||||
data?: any
|
||||
rows?: Array<any>,
|
||||
total?: number
|
||||
}
|
|
@ -7,7 +7,8 @@ import { PPTApi } from './index'
|
|||
import * as store from '../store'
|
||||
import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
||||
const slidesStore = store.useSlidesStore()
|
||||
const resource = sessionStore.get('curr.resource')
|
||||
const resource = sessionStore.get('curr.resource') // apt 资源
|
||||
const smarttalk = sessionStore.get('curr.smarttalk') // 备课资源
|
||||
/**
|
||||
* @description 监听器
|
||||
*/
|
||||
|
@ -28,4 +29,11 @@ const updatePPT = async (data) => {
|
|||
data.id = resource.id
|
||||
await PPTApi.updateSlide(data) // 更新ppt内容
|
||||
sessionStore.set('curr.resource.title', data.title)
|
||||
// 更新smarttalk内容
|
||||
if (!!smarttalk && !!data.title) {
|
||||
const {id, fileFlag} = smarttalk
|
||||
const params = { id, fileShowName: `${data.title}.${fileFlag}` }
|
||||
await PPTApi.updateSmarttalk(params) // 更新ppt内容
|
||||
sessionStore.set('curr.smarttalk.fileShowName', params.fileShowName)
|
||||
}
|
||||
}
|
|
@ -31,6 +31,8 @@ export interface SlidesState {
|
|||
slideIndex: number
|
||||
viewportSize: number
|
||||
viewportRatio: number
|
||||
workList:Object[],
|
||||
workItem:Object[],
|
||||
}
|
||||
|
||||
export const useSlidesStore = defineStore('slides', {
|
||||
|
@ -41,6 +43,8 @@ export const useSlidesStore = defineStore('slides', {
|
|||
slideIndex: 0, // 当前页面索引
|
||||
viewportSize: 1000, // 可视区域宽度基数
|
||||
viewportRatio: 0.5625, // 可视区域比例,默认16:9
|
||||
workList:[],// 活动的列表
|
||||
workItem:[],// 获取到的所有pptlist
|
||||
}),
|
||||
|
||||
getters: {
|
||||
|
@ -131,6 +135,13 @@ export const useSlidesStore = defineStore('slides', {
|
|||
setSlides(slides: Slide[]) {
|
||||
this.slides = slides
|
||||
},
|
||||
// 更新活动列表
|
||||
setWorkList(list: Object[]) {
|
||||
this.workList = list
|
||||
},
|
||||
setWorkItem(list: Object[]) {
|
||||
this.workItem = list
|
||||
},
|
||||
|
||||
addSlide(slide: Slide | Slide[]) {
|
||||
const slides = Array.isArray(slide) ? slide : [slide]
|
||||
|
|
|
@ -6,4 +6,5 @@ export const enum ToolbarStates {
|
|||
SLIDE_DESIGN = 'slideDesign',
|
||||
SLIDE_ANIMATION = 'slideAnimation',
|
||||
MULTI_POSITION = 'multiPosition',
|
||||
EL_ACTIVE = 'elActive',
|
||||
}
|
|
@ -81,6 +81,7 @@
|
|||
</template>
|
||||
<IconVideoTwo class="handler-item" v-tooltip="'插入音视频'" />
|
||||
</Popover>
|
||||
<IconPreviewOpen class="handler-item" v-tooltip="'插入试题'" @click="classWorkTaskVisible = true" />
|
||||
</div>
|
||||
|
||||
<div class="right-handler">
|
||||
|
@ -110,6 +111,18 @@
|
|||
@update="data => { createLatexElement(data); latexEditorVisible = false }"
|
||||
/>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
v-model:visible="classWorkTaskVisible"
|
||||
:width="880"
|
||||
>
|
||||
<QuestToPPTist
|
||||
class="class-work-task-modal"
|
||||
@close="classWorkTaskVisible = false"
|
||||
@update="data => { onhtml2canvas(data); classWorkTaskVisible = false }"
|
||||
/>
|
||||
</Modal>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -135,6 +148,7 @@ import Modal from '../../../components/Modal.vue'
|
|||
import Divider from '../../../components/Divider.vue'
|
||||
import Popover from '../../../components/Popover.vue'
|
||||
import PopoverMenuItem from '../../../components/PopoverMenuItem.vue'
|
||||
import QuestToPPTist from '@/views/classTask/newClassTaskAssign/questToPPTist/index.vue'
|
||||
|
||||
const mainStore = useMainStore()
|
||||
const { creatingElement, creatingCustomShape, showSelectPanel, showSearchPanel, showNotesPanel } = storeToRefs(mainStore)
|
||||
|
@ -172,12 +186,17 @@ const insertImageElement = (files: FileList) => {
|
|||
getImageDataURL(imageFile).then(dataURL => createImageElement(dataURL))
|
||||
}
|
||||
|
||||
const onhtml2canvas = (imgbs64: string) => {
|
||||
createImageElement(imgbs64)
|
||||
}
|
||||
|
||||
const shapePoolVisible = ref(false)
|
||||
const linePoolVisible = ref(false)
|
||||
const chartPoolVisible = ref(false)
|
||||
const tableGeneratorVisible = ref(false)
|
||||
const mediaInputVisible = ref(false)
|
||||
const latexEditorVisible = ref(false)
|
||||
const classWorkTaskVisible = ref(false)
|
||||
const textTypeSelectVisible = ref(false)
|
||||
const shapeMenuVisible = ref(false)
|
||||
const moreVisible = ref(false)
|
||||
|
@ -343,6 +362,9 @@ const toggleNotesPanel = () => {
|
|||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
.class-work-task-modal{
|
||||
height: 80vh;
|
||||
}
|
||||
|
||||
@media screen and (width <= 1200px) {
|
||||
.right-handler .text {
|
||||
|
|
|
@ -66,6 +66,9 @@
|
|||
</Draggable>
|
||||
|
||||
<div class="page-number">幻灯片 {{slideIndex + 1}} / {{slides.length}}</div>
|
||||
|
||||
<!-- 引入活动的列表页面 -->
|
||||
<Active ref="activeRef" v-show="false"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -85,12 +88,13 @@ import ThumbnailSlide from '../../../views/components/ThumbnailSlide/index.vue'
|
|||
import LayoutPool from './LayoutPool.vue'
|
||||
import Popover from '../../../components/Popover.vue'
|
||||
import Draggable from 'vuedraggable'
|
||||
import Active from '../Toolbar/ElementStylePanel/Active/index.vue'
|
||||
|
||||
const mainStore = useMainStore()
|
||||
const slidesStore = useSlidesStore()
|
||||
const keyboardStore = useKeyboardStore()
|
||||
const { selectedSlidesIndex: _selectedSlidesIndex, thumbnailsFocus } = storeToRefs(mainStore)
|
||||
const { slides, slideIndex, currentSlide } = storeToRefs(slidesStore)
|
||||
const { slides, slideIndex, currentSlide, workList, workItem } = storeToRefs(slidesStore)
|
||||
const { ctrlKeyState, shiftKeyState } = storeToRefs(keyboardStore)
|
||||
|
||||
const { slidesLoadLimit } = useLoadSlides()
|
||||
|
@ -123,6 +127,8 @@ const {
|
|||
updateSectionTitle,
|
||||
} = useSectionHandler()
|
||||
|
||||
const activeRef = ref()
|
||||
|
||||
// 页面被切换时
|
||||
const thumbnailsRef = ref<InstanceType<typeof Draggable>>()
|
||||
watch(() => slideIndex.value, () => {
|
||||
|
@ -145,6 +151,9 @@ watch(() => slideIndex.value, () => {
|
|||
|
||||
// 切换页面
|
||||
const changeSlideIndex = (index: number) => {
|
||||
console.log(workItem.value[index],'hasSection');
|
||||
activeRef.value.clickPPTList(workItem.value[index])
|
||||
|
||||
mainStore.setActiveElementIdList([])
|
||||
|
||||
if (slideIndex.value === index) return
|
||||
|
|
|
@ -0,0 +1,291 @@
|
|||
<template>
|
||||
<div>
|
||||
<div style="display: flex;flex-wrap: wrap;">
|
||||
<el-button size="small" title="活动引用" text style="height: 54px" @click="openList()">
|
||||
<div class="buttonDiv">
|
||||
<svg width="26" height="26" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="#646473"><path d="M133.36576 308.12842667v407.74314666c0 96.39253333 78.31552 174.76266667 174.76266667 174.76266667h407.74314666c96.39253333 0 174.76266667-78.31552 174.76266667-174.76266667V308.12842667c0-96.39253333-78.31552-174.76266667-174.76266667-174.76266667H308.12842667a174.87189333 174.87189333 0 0 0-174.76266667 174.76266667zM75.09333333 308.12842667A233.19893333 233.19893333 0 0 1 308.12842667 75.09333333h407.74314666A233.19893333 233.19893333 0 0 1 948.90666667 308.12842667v407.74314666A233.19893333 233.19893333 0 0 1 715.87157333 948.90666667H308.12842667A233.19893333 233.19893333 0 0 1 75.09333333 715.87157333V308.12842667z m706.9696 192.07509333c0 24.46677333-5.67978667 48.22357333-16.98474666 71.21578667-11.35957333 22.99221333-26.76053333 43.52682667-46.25749334 61.54922666-19.44234667 18.0224-42.05226667 32.44032-67.61130666 43.25376a207.20298667 207.20298667 0 0 1-81.21002667 16.16554667h-26.54208c-10.37653333 0-21.62688 0.10922667-33.64181333 0.27306667-12.01493333 0.21845333-23.86602667 0.32768-35.66250667 0.32768h-31.9488c-13.1072 0-23.53834667 1.25610667-31.23882667 3.71370666-7.70048 2.51221333-11.35957333 7.91893333-10.92266666 16.16554667 0 6.22592-0.10922667 13.38026667-0.32768 21.46304-0.21845333 8.08277333-0.32768 15.45557333-0.32768 22.06378667 0 10.81344-3.16757333 17.74933333-9.50272 20.86229333-6.33514667 3.11296-14.7456 0.92842667-25.12213334-6.5536-10.92266667-7.42741333-23.37450667-16.27477333-37.41013333-26.43285333a36528.56490667 36528.56490667 0 0 0-126.42986667-91.09504c-10.37653333-7.42741333-15.72864-14.47253333-15.94709333-21.13536-0.27306667-6.60821333 4.36906667-13.65333333 13.9264-21.13536 9.93962667-7.48202667 21.62688-16.27477333 34.95253333-26.43285334 13.38026667-10.15808 27.30666667-20.58922667 41.83381334-31.40266666l42.81685333-31.67573334c14.03562667-10.37653333 26.48746667-19.71541333 37.41013333-28.01664 11.74186667-9.12042667 21.62688-12.61568 29.4912-10.54037333 7.97354667 2.07530667 11.96032 8.73813333 11.96032 19.87925333 0 3.2768 0.10922667 7.3728 0.32768 12.12416a2794.40042667 2794.40042667 0 0 1 1.69301334 43.85450667c0 7.86432 2.62144 12.72490667 7.80970666 14.58176 5.24288 1.85685333 12.34261333 2.83989333 21.40842667 2.83989333 20.42538667-0.43690667 43.30837333-0.65536 68.64896-0.65536h70.66965333c10.43114667 0 20.86229333-2.18453333 31.29344-6.5536 10.37653333-4.36906667 19.93386667-10.10346667 28.56277334-17.36704 8.57429333-7.26357333 15.61941333-15.67402667 21.02613333-25.17674666 5.46133333-9.55733333 8.192-19.6608 8.192-30.47424v-43.52682667c0-16.60245333-0.10922667-32.65877333-0.32768-48.22357333a2840.00256 2840.00256 0 0 1-0.38229333-40.68693334V341.6064c0-9.12042667 3.05834667-16.65706667 9.17504-22.66453333 6.11669333-6.00746667 13.81717333-10.59498667 23.10144-13.70794667 9.28426667-3.11296 19.38773333-4.64213333 30.25578666-4.64213333 10.92266667 0 20.97152 1.41994667 30.25578667 4.36906666 9.28426667 2.83989333 16.98474667 7.09973333 23.10144 12.72490667 6.11669333 5.57056 9.17504 12.56106667 9.17504 20.80768v46.03904c0 10.75882667 0.10922667 22.28224 0.32768 34.51562667 0.27306667 12.23338667 0.38229333 23.92064 0.38229333 35.11637333V500.20352z" p-id="7882"></path></svg>
|
||||
<div style="margin-top: 10px">活动引用</div>
|
||||
</div>
|
||||
</el-button>
|
||||
<el-button size="small" title="习题训练" text style="height: 54px" @click="showDialog('习题训练')">
|
||||
<div class="buttonDiv">
|
||||
<svg width="26" height="26" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="#646473"><path d="M473.6 204.8c21.2 0 38.4 17.2 38.4 38.4s-17.2 38.4-38.4 38.4H243.2c-21.2 0-38.4-17.2-38.4-38.4s17.2-38.4 38.4-38.4h230.4z m-51.2 153.6c21.2 0 38.4 17.2 38.4 38.4s-17.2 38.4-38.4 38.4H243.2c-21.2 0-38.4-17.2-38.4-38.4s17.2-38.4 38.4-38.4h179.2zM371.2 512c21.2 0 38.4 17.2 38.4 38.4s-17.2 38.4-38.4 38.4h-128c-21.2 0-38.4-17.2-38.4-38.4S222 512 243.2 512h128z m192-384H153.6c-12.6 0-23 9.1-25.2 21l-0.4 4.6v512c0 12.6 9.1 23 21 25.2l4.6 0.4h257.1c-0.7-8.5-1.1-17-1.1-25.6 0-124 73.5-230.8 179.2-279.4V153.6c0-12.6-9.1-23-21-25.2l-4.6-0.4zM768 460.8H665.6v153.6H512v102.4h153.6v153.6H768V716.8h153.6V614.4H768V460.8zM563.2 51.2c56.6 0 102.4 45.8 102.4 102.4v209c16.6-2.8 33.7-4.2 51.2-4.2 169.7 0 307.2 137.5 307.2 307.2S886.5 972.8 716.8 972.8c-133.7 0-247.5-85.5-289.7-204.8H153.6C97 768 51.2 722.2 51.2 665.6v-512C51.2 97 97 51.2 153.6 51.2h409.6z" p-id="13225"></path></svg>
|
||||
<div style="margin-top: 10px">习题训练</div>
|
||||
</div>
|
||||
</el-button>
|
||||
<el-button size="small" title="课堂展示" text style="height: 54px" @click="showDialog('课堂展示')">
|
||||
<div class="buttonDiv">
|
||||
<svg width="26" height="26" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="#646473"><path d="M741.75298 604.605763l3.836774 0.697596 17.43988 3.767014c154.656857 35.089039 260.133252 103.732407 260.133252 194.070985 0 88.455072-101.360583 156.261326-251.134274 191.838682l-9.068737 2.092785-17.370121 3.836774-17.788678 3.487976c-23.927515 4.39485-48.831664 8.092104-74.642686 11.022004l-19.462907 2.023026-24.69487 2.092786-5.022685 0.348797-20.090742 1.325431-10.18489 0.488317-10.25465 0.418557-20.579058 0.697595c-10.324409 0.209279-20.788337 0.348798-31.322025 0.348798l-15.695892-0.139519-15.556373-0.279038-20.648818-0.627836-10.18489-0.418557-10.18489-0.488317-20.160501-1.325431-9.975612-0.697595-19.741944-1.743988a1100.665713 1100.665713 0 0 1-75.968118-9.905852l-18.137475-3.139178-17.788678-3.487976-17.37012-3.767014C105.406635 961.983786 0 893.410178 0 803.141358c0-88.594591 101.360583-156.261326 251.134273-191.9782l8.998979-2.092785 17.43988-3.767014 3.767014-0.697596v93.756796l-10.952245 2.581102-15.207575 3.906533-14.6495 4.046052-13.951904 4.185572c-75.340282 23.857756-121.660604 61.946454-121.660603 89.989781 0 27.206213 43.250903 61.527897 114.196335 85.036855l7.394509 2.371824 14.021663 4.255331 14.6495 4.046052 15.207575 3.906533c8.580421 2.092786 17.43988 4.115812 26.578377 5.999319l13.951904 2.790381 17.021323 3.139178 8.7897 1.39519 17.788678 2.790381 9.068737 1.255672 18.556033 2.302064 14.161182 1.604469 14.370462 1.39519 19.532665 1.53471a1139.731044 1139.731044 0 0 0 142.867498 1.255671l19.881463-1.255671 19.532666-1.53471c8.580421-0.767355 17.021323-1.674228 25.392466-2.581102l12.417194-1.53471 18.276995-2.441583 17.858437-2.790381 8.71994-1.39519 17.091082-3.139178c9.417535-1.813748 18.486273-3.697255 27.415492-5.720281l13.11479-3.069419 15.207575-3.906533 14.649499-4.046052 13.951904-4.185572c75.340282-23.857756 121.590844-59.365352 121.590845-87.408679 0-27.206213-43.250903-64.178759-114.196335-87.617957l-7.39451-2.371824-14.021663-4.255331-14.649499-4.115811-15.207576-3.836774-10.952245-2.581102V604.605763zM451.204578 588.072757l121.660604 69.82928-131.078139 86.153008 9.417535-155.982288z m280.921589-484.131072l121.660603 69.82928-257.552149 443.810069-121.590844-69.899039 257.48239-443.74031zM842.904285 6.278357l40.530281 23.22992a46.459841 46.459841 0 0 1 17.160842 63.690442l-23.439198 40.321003L755.565365 63.620683l23.36944-40.321003a46.948157 46.948157 0 0 1 63.96948-17.021323z" p-id="59383"></path></svg>
|
||||
<div style="margin-top: 10px">课堂展示</div>
|
||||
</div>
|
||||
</el-button>
|
||||
<el-button size="small" title="常规作业" text style="height: 54px;margin-left: 0" @click="showDialog('常规作业')">
|
||||
<div class="buttonDiv">
|
||||
<svg width="26" height="26" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="#646473"><path d="M901.705143 511.926857h-55.954286a8.045714 8.045714 0 0 1-8.045714-8.045714V183.881143H181.686857v656.091428H501.76c4.388571 0 8.045714 3.510857 8.045714 7.899429v56.027429c0 4.388571-3.657143 8.045714-8.045714 8.045714H141.750857a31.963429 31.963429 0 0 1-32.036571-32.036572V143.872c0-17.627429 14.336-31.963429 32.036571-31.963429H877.714286c17.700571 0 32.036571 14.336 32.036571 31.963429V503.954286c0 4.388571-3.657143 8.045714-8.045714 8.045714zM731.428571 911.945143a36.571429 36.571429 0 0 1-36.571428-36.571429v-109.714285H585.142857a36.571429 36.571429 0 0 1 0-73.142858h109.714286v-109.714285a36.571429 36.571429 0 0 1 73.142857 0v109.714285H877.714286a36.571429 36.571429 0 1 1 0 73.142858h-109.714286v109.714285a36.571429 36.571429 0 0 1-36.571429 36.571429z" p-id="22184"></path></svg>
|
||||
<div style="margin-top: 10px">常规作业</div>
|
||||
</div>
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
|
||||
<!-- 作业列表 -->
|
||||
<div class="c-apt-r">
|
||||
<!-- 显示-作业内容 -->
|
||||
<template v-for="(item, index) in workList">
|
||||
<div class="item">
|
||||
<div class="item-title">
|
||||
<el-tag :type="getTagType(item.worktype) || 'primary'">{{item.worktype}}</el-tag>
|
||||
<el-tooltip :content="item.title||item.uniquekey" placement="top">
|
||||
<div class="tt">{{item.title||item.uniquekey}}</div>
|
||||
</el-tooltip>
|
||||
<el-button class="btn-del" type="danger" link @click="handleRemoveDemoActivityClassWork(item)">删除</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<!-- // 推送作业 -->
|
||||
<el-dialog v-model="dialogVisible" append-to-body :show-close="false" width="80%">
|
||||
<NewClassTsakAssign :currentCourse='currentCourse'/>
|
||||
</el-dialog>
|
||||
<!-- 活动引用 -->
|
||||
<el-dialog
|
||||
v-loading="tasklist_loading"
|
||||
v-model="activeVisible"
|
||||
append-to-body
|
||||
:show-close="false"
|
||||
width="40%"
|
||||
@selection-change="handleSelectionChange">
|
||||
<el-table :data="taskList" style="width: 100%" height="500">
|
||||
<el-table-column type="selection" :selectable="selectable" width="55" />
|
||||
<el-table-column prop="evaltitle" label="活动名称" width="150" />
|
||||
<el-table-column prop="worktype" label="活动类型" width="120" sortable>
|
||||
<template #default="scope">
|
||||
<el-tag :type="getTagType(scope.row.worktype) || 'primary'">{{ scope.row.worktype }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="timestamp" label="创建时间" sortable/>
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<el-button @click="activeVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="save">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, onBeforeMount, defineExpose } from 'vue'
|
||||
import Divider from '../../../../../components/Divider.vue'
|
||||
import {listEntpcoursefile} from '@/api/education/entpcoursefile'
|
||||
import {homeworklist} from '@/api/teaching/classwork'
|
||||
import { processList } from "@/hooks/useProcessList";
|
||||
import { listEntpcoursework } from "@/api/classTask/index";
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import NewClassTsakAssign from '@/views/classTask/newClassTaskAssign/index.vue'
|
||||
import { sessionStore } from '@/utils/store'
|
||||
import { useGetHomework } from '@/hooks/useGetHomework'
|
||||
const currentCourse = reactive({
|
||||
textbookId:0,
|
||||
levelFirstId:0,
|
||||
levelSecondId:0,
|
||||
coursetitle:'',
|
||||
node:{},
|
||||
id:1,
|
||||
worktype:'',
|
||||
})
|
||||
const dataList = ref([])
|
||||
const dialogVisible = ref(false)
|
||||
const tasklist_loading = ref(false)
|
||||
// 活动列表
|
||||
const taskList = ref([])
|
||||
// 活动引用的弹窗
|
||||
const activeVisible = ref(false)
|
||||
const params = reactive({
|
||||
parentid:14766,
|
||||
pageSize:500,
|
||||
orderby:'fileidx'
|
||||
})
|
||||
const type = ref([
|
||||
{
|
||||
label:'习题训练',
|
||||
value:'danger'
|
||||
},
|
||||
{
|
||||
label:'课堂展示',
|
||||
value:'success'
|
||||
},
|
||||
{
|
||||
label:'常规作业',
|
||||
value:'primary'
|
||||
},
|
||||
])
|
||||
// 作业列表
|
||||
const workList = ref([])
|
||||
const selectable = (row,index) => {
|
||||
console.log(row,index,'row,index');
|
||||
return true
|
||||
}
|
||||
|
||||
const clickPPTList = (item) => {
|
||||
console.log(item,'点击了')
|
||||
workList.value = []
|
||||
let datacontent = item.datacontent;
|
||||
let pptJson = "";
|
||||
if(typeof datacontent === 'string') pptJson = JSON.parse(datacontent)
|
||||
if(pptJson&&pptJson[0]&&pptJson[0].classworkList) {
|
||||
homeworklist({ids:pptJson[0].classworkList, pageSize: 100}).then( async res => {
|
||||
await formatClassWorkFile(res.rows)
|
||||
})
|
||||
}
|
||||
}
|
||||
const formatClassWorkFile = async (postData) => {
|
||||
return new Promise(async (resolve, reject)=>{
|
||||
for (let i = 0; i < postData.length; i++) {
|
||||
let item = postData[i];
|
||||
switch (item.worktype) {
|
||||
case '框架梳理': {
|
||||
}
|
||||
break;
|
||||
case '习题训练': {
|
||||
item.entpcourseworklistarray = item.entpcourseworklist?JSON.parse('['+item.entpcourseworklist+']'):[];
|
||||
let workIds = item.entpcourseworklistarray.map(items=>items.id).join(',')
|
||||
let ress = await listEntpcoursework({ids:workIds})
|
||||
processList(ress.rows)
|
||||
item.workShowList = ress.rows
|
||||
}
|
||||
break;
|
||||
case '课堂展示': {
|
||||
item.base64 = JSON.parse(item.workcodes).base64
|
||||
}
|
||||
break;
|
||||
case '常规作业': {
|
||||
item.prevData = JSON.parse(item.workcodes)
|
||||
}
|
||||
}
|
||||
workList.value.push(item)
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
}
|
||||
// 删除作业
|
||||
const handleRemoveDemoActivityClassWork = (item) => {
|
||||
ElMessageBox.confirm('是否确认删除?')
|
||||
.then(function () {
|
||||
workList.value.splice(workList.value.indexOf(item), 1);
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
// 获取tag的样式
|
||||
const getTagType = (worktype) => {
|
||||
return type.value.find(item => item.label == worktype).value
|
||||
}
|
||||
// 获取活动引用的列表数据
|
||||
const initHomeWork = async()=> {
|
||||
tasklist_loading.value = true;
|
||||
const { res, chapterId } = await useGetHomework(sessionStore.get('subject.curNode'));
|
||||
taskList.value = res;
|
||||
tasklist_loading.value = false;
|
||||
}
|
||||
// 多选活动引用
|
||||
const handleSelectionChange = (val) => {
|
||||
console.log(val,'多选')
|
||||
}
|
||||
// 打开添加作业活动
|
||||
const showDialog = (item) => {
|
||||
currentCourse.worktype = item
|
||||
dialogVisible.value = true
|
||||
}
|
||||
const openList = () => {
|
||||
activeVisible.value = true
|
||||
initHomeWork()
|
||||
}
|
||||
// 添加活动引用列表作业
|
||||
const save = () => {
|
||||
console.log('添加了')
|
||||
activeVisible.value = false
|
||||
}
|
||||
onMounted(() => {
|
||||
// console.log(sessionStore.get('subject.curBook'),'curBook');
|
||||
// console.log(sessionStore.get('subject.subjectTree'),'subjectTree');
|
||||
// console.log(sessionStore.get('subject.bookList'),'bookList');
|
||||
console.log(sessionStore.get('subject.curNode'),'curNode');
|
||||
const curNode = sessionStore.get('subject.curNode')
|
||||
currentCourse.textbookId = curNode.rootid
|
||||
currentCourse.levelFirstId = curNode.parentNode.id
|
||||
currentCourse.levelSecondId = curNode.id
|
||||
currentCourse.coursetitle = curNode.itemtitle,
|
||||
currentCourse.node = curNode
|
||||
listEntpcoursefile(params).then((res) => {
|
||||
dataList.value = [...res.rows]
|
||||
})
|
||||
})
|
||||
defineExpose({
|
||||
clickPPTList
|
||||
})
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.buttonDiv{
|
||||
margin-top: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
}
|
||||
// (apt)编辑区-右侧
|
||||
.c-apt-r{
|
||||
flex:1;
|
||||
overflow: auto;
|
||||
.item{
|
||||
position: relative;
|
||||
margin-top: 5px;
|
||||
.item-title{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.tt{
|
||||
flex: 1;
|
||||
padding-left: 10px;
|
||||
cursor: default;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
}
|
||||
.btn-del{
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
.item-body{
|
||||
position: relative;
|
||||
border: 1px solid silver;
|
||||
padding: 10px;
|
||||
background: #fff;
|
||||
border-radius: 3px;
|
||||
margin: 5px 10px;
|
||||
cursor: default;
|
||||
&:hover{
|
||||
border-color: var(--el-color-primary);
|
||||
.el-text{
|
||||
--el-text-color: var(--el-color-primary);
|
||||
}
|
||||
.el-tag{
|
||||
--el-tag-bg-color: var(--el-color-primary);
|
||||
--el-tag-border-color: var(--el-color-primary);
|
||||
--el-tag-text-color: var(--el-color-white);
|
||||
}
|
||||
}
|
||||
.c-icon-info{
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
right: -5px;
|
||||
}
|
||||
}
|
||||
.item-divider{
|
||||
margin: 5px 0;
|
||||
margin-left: 10px;
|
||||
width: calc(100% - 20px);
|
||||
--el-border-color: var(--current-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -25,6 +25,8 @@ import SlideDesignPanel from './SlideDesignPanel.vue'
|
|||
import SlideAnimationPanel from './SlideAnimationPanel.vue'
|
||||
import MultiPositionPanel from './MultiPositionPanel.vue'
|
||||
import SymbolPanel from './SymbolPanel.vue'
|
||||
// 新增的活动页面
|
||||
import SymbolActivePanel from './ElementStylePanel/Active/index.vue'
|
||||
import Tabs from '../../../components/Tabs.vue'
|
||||
|
||||
interface ElementTabs {
|
||||
|
@ -54,6 +56,7 @@ const slideTabs = [
|
|||
{ label: '设计', key: ToolbarStates.SLIDE_DESIGN },
|
||||
{ label: '切换', key: ToolbarStates.SLIDE_ANIMATION },
|
||||
{ label: '动画', key: ToolbarStates.EL_ANIMATION },
|
||||
{ label: '活动', key: ToolbarStates.EL_ACTIVE },
|
||||
]
|
||||
const multiSelectTabs = [
|
||||
{ label: '样式', key: ToolbarStates.EL_STYLE },
|
||||
|
@ -86,6 +89,7 @@ const currentPanelComponent = computed(() => {
|
|||
[ToolbarStates.SLIDE_ANIMATION]: SlideAnimationPanel,
|
||||
[ToolbarStates.MULTI_POSITION]: MultiPositionPanel,
|
||||
[ToolbarStates.SYMBOL]: SymbolPanel,
|
||||
[ToolbarStates.EL_ACTIVE]: SymbolActivePanel,// 新增的活动页面
|
||||
}
|
||||
return panelMap[toolbarState.value] || null
|
||||
})
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
import axios from 'axios'
|
||||
import request from '@/utils/request'
|
||||
import { getToken } from "@/utils/auth";
|
||||
|
||||
// 文生图片
|
||||
export function convertTextToPicture(data) {
|
||||
return axios({
|
||||
url: 'https://ai.ysaix.com:7853/prompt',
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': '*/*'
|
||||
},
|
||||
data: data
|
||||
})
|
||||
}
|
||||
// 获取任务列表
|
||||
export function getQueue() {
|
||||
return axios({
|
||||
url: `https://ai.ysaix.com:7853/queue`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
// 获取生图任务id
|
||||
export function getPromptId(id) {
|
||||
return axios({
|
||||
url: `https://ai.ysaix.com:7853/history/${id}`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
// 获取生成图片路径
|
||||
export function getPicture(data) {
|
||||
return axios({
|
||||
url: 'https://ai.ysaix.com:7853/view',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
// 大模型对话生成prompt模板
|
||||
export function chattoprompt(dataset_id,prompt) {
|
||||
return axios({
|
||||
url: '/api/v1/parse/docs',
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Authorization': 'Bearer ragflow-IwMDI1MGU2YTU3NjExZWZiNWEzMDI0Mm',
|
||||
},
|
||||
data: {
|
||||
'dataset_id': dataset_id,
|
||||
'prompt': prompt
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// prompt敏感词校验
|
||||
export function textSensitiveWord(data) {
|
||||
return request({
|
||||
url: '/verify/text',
|
||||
method: 'post',
|
||||
data: {
|
||||
'text' : data
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 图片上传资源库
|
||||
export function uploadPicture(data) {
|
||||
return axios({
|
||||
url: '/dev-api/smarttalk/file/upload',
|
||||
method: 'post',
|
||||
headers: {
|
||||
'Accept': '*/*',
|
||||
'Content-Type': 'multipart/form-data',
|
||||
'Authorization': "Bearer " + getToken()
|
||||
},
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,627 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-row :gutter="40" style="height:auto">
|
||||
<el-col :span="8">
|
||||
<div>
|
||||
<div style="text-align: left">反面提示词</div>
|
||||
<br>
|
||||
<el-input v-model="formData.prompt[12].inputs.negative_prompt" placeholder="试试在这里输入你不想其进入图画的词"
|
||||
type="textarea"></el-input>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<div style="text-align: left">可选提示词</div>
|
||||
<br>
|
||||
<div style="font-size: 14px;text-align: left">风格特点</div>
|
||||
<el-checkbox-group v-model="checkList">
|
||||
<el-checkbox v-for="(prompt, index) in promptOption1" :key="index" :label="prompt" :value="prompt" />
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size: 14px;text-align: left">主体对象</div>
|
||||
<el-checkbox-group v-model="checkList">
|
||||
<el-checkbox v-for="(prompt, index) in promptOption2" :key="index" :label="prompt" :value="prompt" />
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-size: 14px;text-align: left">场景</div>
|
||||
<el-checkbox-group v-model="checkList">
|
||||
<el-checkbox v-for="(prompt, index) in promptOption3" :key="index" :label="prompt" :value="prompt" />
|
||||
</el-checkbox-group>
|
||||
</div>
|
||||
<div style="text-align: right">
|
||||
<el-button type="primary" @click="addCheckListToPrompt">添加</el-button>
|
||||
<el-button type="primary" @click="deletePrompt">清空</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 具体参数相关内容 -->
|
||||
<el-form label-position="top" size="small">
|
||||
<el-form-item label="图片尺寸" style=" margin-bottom: 0px">
|
||||
<el-row class="ratio-options" :gutter="10" style="margin-bottom: -15px;margin-top: -25px">
|
||||
<el-col v-for="ratio in ratioOptions" :key="ratio.value" :span="4">
|
||||
<el-button :type="form.ratio === ratio.value ? 'primary' : 'default'" @click="setRatio(ratio.value)"
|
||||
class="ratio-option" block>
|
||||
{{ ratio.label }}
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item label="图片比例" style=" margin-bottom: 0px">
|
||||
<el-row class="ratio-options" :gutter="10" style="margin-bottom: -15px;margin-top: -25px">
|
||||
<el-col v-for="ratio in ratioOptions2" :key="ratio.value" :span="4">
|
||||
<el-button :type="form.ratios2 === ratio.value ? 'primary' : 'default'" @click="setRatio2(ratio.value)"
|
||||
class="ratio-option" block>
|
||||
{{ ratio.label }}
|
||||
</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item label="图片数量" style=" margin-bottom: 0px">
|
||||
<el-row style="margin-bottom: -15px;margin-top: -25px">
|
||||
<el-button style="width: 10%" :type="num_picture === 1 ? 'primary' : 'default'" @click="changePicture(1)">
|
||||
1
|
||||
</el-button>
|
||||
<el-button style="width: 10%" :type="num_picture === 2 ? 'primary' : 'default'" @click="changePicture(2)">
|
||||
2
|
||||
</el-button>
|
||||
<el-button style="width: 10%" :type="num_picture === 3 ? 'primary' : 'default'" @click="changePicture(3)">
|
||||
3
|
||||
</el-button>
|
||||
<el-button style="width: 10%" :type="num_picture === 4 ? 'primary' : 'default'" @click="changePicture(4)">
|
||||
4
|
||||
</el-button>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item label="随机种子">
|
||||
<el-slider v-model="formData.prompt[14].inputs.seed" :min="1" :max="10000000" show-input />
|
||||
</el-form-item>
|
||||
<el-form-item label="cfg (数值越高,生图过程与提示词越相关)">
|
||||
<el-slider v-model="formData.prompt[14].inputs.cfg" :max="20" show-input />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<div
|
||||
:style="{ height: divHeight + 'px', 'overflow-y': 'auto', 'margin-bottom': '10px', 'background-color': '#f5f5f5', 'padding': '10px' }">
|
||||
<div v-for="(resultItem, resultIndex) in resultList" :key="resultIndex">
|
||||
<div style="display: flex; flex-wrap: wrap; justify-content: flex-end;">
|
||||
<el-card style="max-width: 50%; margin-right: 10px; display: inline-block;background-color: lightblue;">
|
||||
<div>
|
||||
<p style="word-wrap: break-word; overflow-wrap: break-word;text-align: left">{{ resultItem }}</p>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
<el-row :gutter="10" justify="center">
|
||||
<el-col :span="6" v-for="(url, index) in pictureurl[resultIndex]" :key="index">
|
||||
<el-card style="margin-bottom: 5%;height:95%">
|
||||
<el-image style="width: 100%;" fit="cover" :src="url" :preview-src-list="pictureurl"
|
||||
:initial-index="index" class="equal-size-image"></el-image>
|
||||
<div style="text-align: center; margin-top: 15px">
|
||||
<el-button :disabled="buttonStates[resultIndex][index].disabled" size="small" type="primary"
|
||||
@click="saveImage(resultIndex, index, url, resultItem)">{{ buttonStates[resultIndex][index].text
|
||||
}}</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<el-row :gutter="10" justify="center">
|
||||
<el-col v-if="pictureLoading" :span="6" v-for="n in generateArray(this.skeletonNumber)" :key="n">
|
||||
<el-card>
|
||||
<el-skeleton class="custom-skeleton-item" animated>
|
||||
<template #template>
|
||||
<el-skeleton-item variant="image" class="custom-skeleton-item"></el-skeleton-item>
|
||||
</template>
|
||||
</el-skeleton>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="10" justify="center">
|
||||
<el-col :span="12">
|
||||
<el-card v-for="(item, index) in resultData" :key="index"
|
||||
style="display: flex;flex-direction: column;align-items: center;margin-bottom: 10px" justify="center"
|
||||
@click="handleCardClick(item)" :class="{ 'card-hover': !pictureLoading }">
|
||||
<p style="word-wrap: break-word; overflow-wrap: break-word;">{{ item }}</p>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div style="text-align: center">
|
||||
<el-input style="width: 70%;" v-model="promptData" placeholder="试试输入你心中的画面,尽量描述具体点哦,可以按照这个格式来写: 提示词=主体+风格+场景"
|
||||
type="textarea">
|
||||
</el-input>
|
||||
<el-button type="primary" :disabled="pictureLoading" @click="fetchData">
|
||||
{{ !pictureLoading ? "生成图片" : "请等待" }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { convertTextToPicture, getQueue, getPromptId, getPicture, chattoprompt, textSensitiveWord, uploadPicture } from "@/api/aiGeneratedImage/index.js";
|
||||
import CryptoJS from 'crypto-js'
|
||||
import { useRoute } from 'vue-router'
|
||||
export default {
|
||||
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
ratio: "512",
|
||||
ratios2: "1/1",
|
||||
},
|
||||
ratioOptions: [
|
||||
{ value: "512", label: "512" },
|
||||
{ value: "768", label: "768" },
|
||||
{ value: "1024", label: "1024" },
|
||||
{ value: "1280", label: "1280" },
|
||||
{ value: "2048", label: "2048" },
|
||||
],
|
||||
ratioOptions2: [
|
||||
{ value: "1/1", label: "1:1" },
|
||||
{ value: "4/3", label: "4:3" },
|
||||
{ value: "3/4", label: "3:4" },
|
||||
{ value: "9/16", label: "9:16" },
|
||||
{ value: "16/9", label: "16:9" },
|
||||
],
|
||||
//图片数据
|
||||
imageData: {
|
||||
imageUrls: [],
|
||||
prompt: [],
|
||||
time: [],
|
||||
id: [],
|
||||
},
|
||||
promptOption1: ["赛博朋克", "水墨风", "莫奈风格", "二次元", "中国风", "写实风格", "水彩风格", "工笔画", "素描风", "未来主义", "超现实主义", "映像派"],
|
||||
promptOption2: ["男生", "女生", "老年人", "船舶", "蝴蝶", "狮子", "兔子", "飞机", "中年人", "大树", "长江", "坦克"],
|
||||
promptOption3: ["雨林", "沙漠", "湖泊", "天空", "城市", "乡村", "太空", "教室"],
|
||||
promptData: "",
|
||||
|
||||
//模型参数
|
||||
formData: {
|
||||
client_id: "533ef3a3-39c0-4e39-9ced-37d290f371f8",
|
||||
prompt: {
|
||||
3: {
|
||||
inputs: {
|
||||
images: ["10", 0],
|
||||
},
|
||||
class_type: "PreviewImage",
|
||||
_meta: {
|
||||
title: "Preview Image",
|
||||
},
|
||||
},
|
||||
6: {
|
||||
inputs: {
|
||||
model: "Kwai-Kolors/Kolors",
|
||||
precision: "fp16",
|
||||
},
|
||||
class_type: "DownloadAndLoadKolorsModel",
|
||||
_meta: {
|
||||
title: "(Down)load Kolors Model",
|
||||
},
|
||||
},
|
||||
10: {
|
||||
inputs: {
|
||||
samples: ["14", 0],
|
||||
vae: ["11", 0],
|
||||
},
|
||||
class_type: "VAEDecode",
|
||||
_meta: {
|
||||
title: "VAE Decode",
|
||||
},
|
||||
},
|
||||
11: {
|
||||
inputs: {
|
||||
vae_name: "sdxl.vae.safetensors",
|
||||
},
|
||||
class_type: "VAELoader",
|
||||
_meta: {
|
||||
title: "Load VAE",
|
||||
},
|
||||
},
|
||||
12: {
|
||||
inputs: {
|
||||
prompt: "",
|
||||
negative_prompt: "",
|
||||
num_images_per_prompt: 1,
|
||||
chatglm3_model: ["13", 0],
|
||||
},
|
||||
class_type: "KolorsTextEncode",
|
||||
_meta: {
|
||||
title: "Kolors Text Encode",
|
||||
},
|
||||
},
|
||||
13: {
|
||||
inputs: {
|
||||
precision: "quant8",
|
||||
},
|
||||
class_type: "DownloadAndLoadChatGLM3",
|
||||
_meta: {
|
||||
title: "(Down)load ChatGLM3 Model",
|
||||
},
|
||||
},
|
||||
14: {
|
||||
inputs: {
|
||||
width: 1024,
|
||||
height: 1024,
|
||||
seed: 1000102404233412,
|
||||
steps: 25,
|
||||
cfg: 5,
|
||||
scheduler: "EulerDiscreteScheduler",
|
||||
denoise_strength: 1,
|
||||
kolors_model: ["6", 0],
|
||||
kolors_embeds: ["12", 0],
|
||||
},
|
||||
class_type: "KolorsSampler",
|
||||
_meta: {
|
||||
title: "Kolors Sampler",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
picture: {
|
||||
filename: "",
|
||||
type: "temp",
|
||||
subfolder: "",
|
||||
preview: "",
|
||||
channel: "",
|
||||
},
|
||||
buttonStates: [], // 用于存储按钮状态的二维数组,初始为空
|
||||
resultList: [],
|
||||
pictureurl: [],
|
||||
percentage: 50,
|
||||
num_picture: 1,
|
||||
skeletonNumber: 0,
|
||||
cfg_value: 5,
|
||||
pictureLoading: false,
|
||||
QueueNumber: 0, //前方排队任务数量
|
||||
userIdInComponent: '',
|
||||
activeName: '1',
|
||||
checkList: [], //prompt生成
|
||||
totalData: 0,
|
||||
// deleteImageSrc: deletebutton,
|
||||
timer: null,
|
||||
isTimerPaused: false,
|
||||
resultData: [],
|
||||
divHeight: 0,
|
||||
dataset_id: '',
|
||||
courseName: '',
|
||||
levelFirstId: '',
|
||||
levelSecondId: '',
|
||||
textbookId: '',
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
//生图占位图数量
|
||||
generateArray(length) {
|
||||
return Array.from({ length }, (_, index) => index);
|
||||
},
|
||||
|
||||
//随机种子
|
||||
Randomseed() {
|
||||
this.formData.prompt[14].inputs.seed = Math.floor(
|
||||
Math.random() * 10000001
|
||||
);
|
||||
},
|
||||
sleep(ms) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
},
|
||||
|
||||
//生成图片
|
||||
async fetchData() {
|
||||
|
||||
// 判断prompt是否为空
|
||||
if (this.promptData == "") {
|
||||
this.$message.error("prompt不能为空");
|
||||
return;
|
||||
}
|
||||
|
||||
const prompt = this.promptData
|
||||
//敏感词校验
|
||||
await textSensitiveWord(prompt)
|
||||
|
||||
this.setRatio(this.form.ratio)
|
||||
this.changeSize()
|
||||
this.resultList.push(this.promptData)
|
||||
this.skeletonNumber = this.num_picture
|
||||
const skeletonItemNumber = this.num_picture
|
||||
// const userId = this.userIdInComponent
|
||||
// const model = 'kolors'
|
||||
|
||||
// 处理prompt生成多张图片
|
||||
let temp = "";
|
||||
if (skeletonItemNumber > 1) {
|
||||
for (let i = 1; i < skeletonItemNumber; i++) {
|
||||
temp += "|" + this.promptData;
|
||||
}
|
||||
this.formData.prompt[12].inputs.prompt = this.promptData + temp;
|
||||
} else {
|
||||
this.formData.prompt[12].inputs.prompt = this.promptData;
|
||||
}
|
||||
// 将数据转成json
|
||||
const transformedData = {
|
||||
client_id: this.formData.client_id,
|
||||
prompt: Object.fromEntries(
|
||||
Object.entries(this.formData.prompt).map(([key, value]) => [
|
||||
key,
|
||||
{
|
||||
inputs: value.inputs,
|
||||
class_type: value.class_type,
|
||||
_meta: value._meta,
|
||||
},
|
||||
])
|
||||
),
|
||||
};
|
||||
|
||||
const jsonData = JSON.stringify(transformedData, null, 2);
|
||||
|
||||
|
||||
|
||||
//生图过程
|
||||
try {
|
||||
this.pictureLoading = true;
|
||||
const response = await convertTextToPicture(jsonData); //发起生图任务
|
||||
const pictureId = response.data.prompt_id;
|
||||
const queue_Number = response.data.number
|
||||
let queue;
|
||||
do {
|
||||
queue = await getQueue(); //查询生图队列
|
||||
if (this.hasId(queue, pictureId)) {
|
||||
this.QueueNumber = queue_Number - queue.data.queue_running[0][0] // 计算队列剩余数量
|
||||
await this.sleep(500);
|
||||
}
|
||||
} while (this.hasId(queue, pictureId));
|
||||
|
||||
const pictureData = await getPromptId(pictureId); //生图任务id查询结果
|
||||
|
||||
const jsonString = JSON.parse(pictureData.request.responseText);
|
||||
const urls = []
|
||||
const buttonState = [];
|
||||
for (let i = 0; i < skeletonItemNumber; i++) {
|
||||
this.picture.filename = jsonString[pictureId].outputs[3].images[i].filename;
|
||||
const pictureURL = await getPicture(this.picture); //获得生成图片的url
|
||||
const url0 = pictureURL.request.responseURL;
|
||||
urls.push(url0)
|
||||
buttonState.push({
|
||||
disabled: false,
|
||||
text: "插入本课素材资源库",
|
||||
})
|
||||
}
|
||||
this.skeletonNumber = 0
|
||||
this.pictureurl.push(urls)
|
||||
this.buttonStates.push(buttonState)
|
||||
this.pictureLoading = false;
|
||||
|
||||
} catch (error) {
|
||||
this.pictureLoading = false;
|
||||
console.error("Error fetching data:", error);
|
||||
}
|
||||
},
|
||||
//生图队列的查询
|
||||
hasId(obj, id) {
|
||||
if (typeof obj !== "object" || obj === null) {
|
||||
return false;
|
||||
}
|
||||
if (Object.values(obj).includes(id)) {
|
||||
return true;
|
||||
}
|
||||
return Object.values(obj).some((value) => this.hasId(value, id));
|
||||
},
|
||||
|
||||
setRatio(ratio) {
|
||||
this.form.ratio = ratio;
|
||||
switch (ratio) {
|
||||
case "512":
|
||||
this.formData.prompt[14].inputs.width = this.formData.prompt[14].inputs.height = 512;
|
||||
break;
|
||||
case "768":
|
||||
this.formData.prompt[14].inputs.width = this.formData.prompt[14].inputs.height = 768;
|
||||
break;
|
||||
case "1024":
|
||||
this.formData.prompt[14].inputs.width = this.formData.prompt[14].inputs.height = 1024;
|
||||
break;
|
||||
case "1280":
|
||||
this.formData.prompt[14].inputs.width = this.formData.prompt[14].inputs.height = 1280;
|
||||
break;
|
||||
case "2048":
|
||||
this.formData.prompt[14].inputs.width = this.formData.prompt[14].inputs.height = 2048;
|
||||
break;
|
||||
default:
|
||||
this.formData.prompt[14].inputs.width = this.formData.prompt[14].inputs.height = 512;
|
||||
}
|
||||
},
|
||||
setRatio2(ratio) {
|
||||
this.form.ratios2 = ratio;
|
||||
},
|
||||
changeSize() {
|
||||
const a = this.form.ratios2
|
||||
if (a == "1/1") {
|
||||
this.formData.prompt[14].inputs.width = this.formData.prompt[14].inputs.height
|
||||
} else if (a == "4/3") {
|
||||
this.formData.prompt[14].inputs.height = (this.formData.prompt[14].inputs.width) * 3 / 4
|
||||
} else if (a == "3/4") {
|
||||
this.formData.prompt[14].inputs.width = (this.formData.prompt[14].inputs.height) * 3 / 4
|
||||
} else if (a == "9/16") {
|
||||
this.formData.prompt[14].inputs.width = (this.formData.prompt[14].inputs.height) * 9 / 16
|
||||
} else {
|
||||
this.formData.prompt[14].inputs.height = (this.formData.prompt[14].inputs.width) * 9 / 16
|
||||
}
|
||||
},
|
||||
changePicture(num) {
|
||||
this.num_picture = num;
|
||||
},
|
||||
|
||||
// 生成提示词模板
|
||||
async createPrompt() {
|
||||
const dataset_id = this.dataset_id
|
||||
const courseName = this.courseName
|
||||
const prompt = `结合${courseName},给我三句详细的提示词用于生成图片,以1.2.3的形式`
|
||||
const response = await chattoprompt(dataset_id, prompt)
|
||||
const resultData = response.data.answer
|
||||
const promptData = []
|
||||
|
||||
for (let i = 1; i <= 3; i++) {
|
||||
const startIndex = resultData.indexOf(`${i}.`) + `${i}.`.length;
|
||||
const endIndex = resultData.indexOf("。", startIndex);
|
||||
promptData.push(resultData.substring(startIndex, endIndex).trim());
|
||||
}
|
||||
this.resultData = promptData
|
||||
},
|
||||
|
||||
handleCardClick(item) {
|
||||
this.promptData = item
|
||||
this.fetchData()
|
||||
},
|
||||
|
||||
|
||||
//保存图片到素材库
|
||||
async saveImage(resultIndex, index, url, resultItem) {
|
||||
this.buttonStates[resultIndex][index].disabled = true;
|
||||
this.buttonStates[resultIndex][index].text = "正在保存...";
|
||||
const numberIndex = url.indexOf('filename=');
|
||||
const path = url.substring(numberIndex + 9);
|
||||
const pngIndex = path.indexOf('.png');
|
||||
const finalPath = path.substring(0, pngIndex + 4);
|
||||
try {
|
||||
const blob = await this.getImageBlob(`https://ai.ysaix.com:7853/view?filename=${finalPath}&type=temp`);
|
||||
|
||||
const hash = CryptoJS.MD5(blob).toString();
|
||||
|
||||
const formData = new FormData();
|
||||
|
||||
let file = new File([blob], `${resultItem}.png`, {
|
||||
type: 'image/png'
|
||||
})
|
||||
|
||||
// 添加参数
|
||||
formData.append('md5', hash);
|
||||
formData.append('file', file);
|
||||
formData.append('textbookId', this.textbookId);
|
||||
formData.append('levelFirstId', this.levelFirstId);
|
||||
formData.append('levelSecondId', this.levelSecondId);
|
||||
formData.append('fileSource', '个人');
|
||||
formData.append('fileRoot', '备课');
|
||||
formData.append('fileShowName', `${resultItem}.png`);
|
||||
formData.append('fileFlag', '素材');
|
||||
const responsedata = uploadPicture(formData);
|
||||
responsedata.then((response) => {
|
||||
if (response.data && response.data.code === 200) {
|
||||
// 若上传成功,更新对应按钮的状态
|
||||
this.buttonStates[resultIndex][index].text = "已保存";
|
||||
this.buttonStates[resultIndex][index].disabled = true;
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.error(error);
|
||||
this.buttonStates[resultIndex][index].disabled = false;
|
||||
this.buttonStates[resultIndex][index].text = "插入本课素材资源库";
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
|
||||
getImageBlob(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url, true);
|
||||
xhr.responseType = 'blob';
|
||||
xhr.onload = function () {
|
||||
if (this.status === 200) {
|
||||
resolve(this.response);
|
||||
} else {
|
||||
reject(new Error(`图片获取失败,状态码:${this.status}`));
|
||||
}
|
||||
};
|
||||
xhr.onerror = function () {
|
||||
reject(new Error('图片获取发生网络错误'));
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
},
|
||||
|
||||
// convertImageToBase64(url) {
|
||||
// return request({
|
||||
// url: '/common/convertImageToBase64',
|
||||
// method: 'get',
|
||||
// params: {
|
||||
// url: url
|
||||
// }
|
||||
// })
|
||||
// },
|
||||
// handleSaveImage(url) {
|
||||
// this.convertImageToBase64(url).then(res => {
|
||||
// this.$emit("saveImage", res)
|
||||
// }, err => {
|
||||
// this.$message.error(err);
|
||||
// })
|
||||
// },
|
||||
|
||||
//prompt生成器的勾选内容添加到输入框
|
||||
addCheckListToPrompt() {
|
||||
const joinedString = this.checkList.join(',');
|
||||
this.promptData = ''
|
||||
this.promptData += joinedString;
|
||||
},
|
||||
|
||||
//清空prompt
|
||||
deletePrompt() {
|
||||
this.promptData = '',
|
||||
this.checkList = []
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
const route = useRoute();
|
||||
this.dataset_id = route.query.datasetId;
|
||||
this.courseName = route.query.coursetitle;
|
||||
this.levelFirstId = route.query.levelFirstId;
|
||||
this.levelSecondId = route.query.levelSecondId;
|
||||
this.textbookId = route.query.textbookId;
|
||||
this.createPrompt()
|
||||
this.Randomseed();
|
||||
this.divHeight = window.innerHeight * 0.80;
|
||||
window.addEventListener('resize', () => {
|
||||
this.divHeight = window.innerHeight * 0.85;
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('resize', () => {
|
||||
this.divHeight = window.innerHeight * 0.85;
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.el-row {
|
||||
padding: 20px
|
||||
}
|
||||
|
||||
.count-option,
|
||||
.ratio-option {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.custom-skeleton-item {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.time-display p {
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
|
||||
.equal-size-image img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.card-hover:hover {
|
||||
background-color: #f0f0f0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.disabled-cursor {
|
||||
cursor: not-allowed !important;
|
||||
}
|
||||
</style>
|
|
@ -142,13 +142,19 @@ const handleNodeClick = (data) => {
|
|||
|
||||
//增加一个label 之前取的label
|
||||
nodeData.label = nodeData.itemtitle
|
||||
// 父级节点 如果当前是一级节点 父级则为null
|
||||
let parent = {
|
||||
let parentNode
|
||||
// 存在children 则为一级节点
|
||||
if(nodeData.children){
|
||||
// 为一级节点
|
||||
parentNode = null
|
||||
}
|
||||
else{
|
||||
parentNode = {
|
||||
id: nodeData.parentid,
|
||||
label: nodeData.parenttitle,
|
||||
itemtitle: nodeData.parenttitle
|
||||
}
|
||||
const parentNode = nodeData.parentid ? parent : null
|
||||
}
|
||||
nodeData.parentNode = parentNode
|
||||
let curData = {
|
||||
textBook: {
|
||||
|
|
|
@ -34,7 +34,8 @@ const getFileTypeIcon = () => {
|
|||
gif: 'icon-gif',
|
||||
txt: 'icon-txt',
|
||||
rar: 'icon-rar',
|
||||
apt: 'icon-A'
|
||||
apt: 'icon-A',
|
||||
aptist: 'icon-A',
|
||||
}
|
||||
if (iconObj[name]) {
|
||||
return '#' + iconObj[name]
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<!--List-->
|
||||
<div class="container-right-list">
|
||||
<div class="container-right-list" ref="listRef">
|
||||
<template v-for="(item, index) in childTempList">
|
||||
<div class="template-item" v-loading="item.loading">
|
||||
<div class="item-header">
|
||||
|
@ -52,7 +52,7 @@
|
|||
<i class="iconfont icon-ai"></i>
|
||||
</div>
|
||||
<div class="item-answer">
|
||||
<TypingEffect :text="item.oldAnswer" :delay="10" :aiShow="item.aiShow" @complete="onSaveTemp(item)" />
|
||||
<TypingEffect v-if="isStarted[index]" :text="item.answer" :delay="10" :aiShow="item.aiShow" @complete="handleCompleteText($event,index)" @updateScroll="scrollToBottom($event,index)" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="ai-btn" v-if="item.answer">
|
||||
|
@ -83,7 +83,7 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, watch, onUnmounted } from 'vue'
|
||||
import { ref, reactive, onMounted, watch, onUnmounted, nextTick } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { tempSave, completion, modelList, removeChildTemp, tempResult, editTempResult } from '@/api/mode/index'
|
||||
import { sessionStore } from '@/utils/store'
|
||||
|
@ -146,14 +146,16 @@ const getChildTemplate = () => {
|
|||
tempLoading.value = true
|
||||
modelList({ model: props.type, type: 2, parentId: curTemplate.id }).then(res => {
|
||||
childTempList.value = res.rows
|
||||
|
||||
if(childTempList.value.length){
|
||||
childTempList.value.forEach(item => item.answer = '')
|
||||
}
|
||||
getTempResult()
|
||||
}).finally(() => {
|
||||
tempLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const isStarted = ref([]);
|
||||
const listRef = ref()
|
||||
// 查询模板结果
|
||||
const getTempResult = () => {
|
||||
tempResult({ mainModelId: curTemplate.id, pageNum: 1, pageSize: 10000 }).then(res => {
|
||||
|
@ -161,14 +163,40 @@ const getTempResult = () => {
|
|||
childTempList.value.forEach(item => {
|
||||
rows.forEach(el => {
|
||||
if (item.id == el.modelId) {
|
||||
item.answer = el.content
|
||||
item.answer = getResult(el.content)
|
||||
item.resultId = el.id
|
||||
}
|
||||
})
|
||||
})
|
||||
if(rows.length > 0){
|
||||
isStarted.value = new Array(rows.length).fill(true)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
const scrollToBottom = (height,index) =>{
|
||||
|
||||
if (listRef.value) {
|
||||
let sum = 0
|
||||
let listDom = listRef.value.children
|
||||
|
||||
if(index == 0){
|
||||
// 220 去掉头部
|
||||
let screenHeight = window.innerHeight - 220
|
||||
if(height > screenHeight){
|
||||
listRef.value.scrollTop = (height - screenHeight + 50)
|
||||
}
|
||||
}
|
||||
else{
|
||||
for(let i = 0; i < index; i++){
|
||||
sum += listDom[i].clientHeight
|
||||
}
|
||||
listRef.value.scrollTop = sum + height
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 模板切换
|
||||
const changeTemplate = (val) => {
|
||||
ElMessageBox.confirm(
|
||||
|
@ -203,11 +231,11 @@ const removeItem = async (item, isChild) => {
|
|||
).then(() => {
|
||||
removeChildTemp(item.id).then(res => {
|
||||
ElMessage.success('操作成功')
|
||||
if(isChild){
|
||||
if (isChild) {
|
||||
// 获取子模板
|
||||
getChildTemplate()
|
||||
}
|
||||
else{
|
||||
else {
|
||||
// 获取主模板
|
||||
getTemplateList()
|
||||
}
|
||||
|
@ -215,7 +243,7 @@ const removeItem = async (item, isChild) => {
|
|||
})
|
||||
}
|
||||
else {
|
||||
editKeyWord(item,!isChild)
|
||||
editKeyWord(item, !isChild)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,19 +268,18 @@ const onEdit = (index, item) => {
|
|||
|
||||
const modeType = ref('课标')
|
||||
watch(() => props.type, (newVal) => {
|
||||
if (newVal == 1){
|
||||
if (newVal == 1) {
|
||||
modeType.value = '课标'
|
||||
}
|
||||
if (newVal == 2){
|
||||
if (newVal == 2) {
|
||||
modeType.value = '教材'
|
||||
}
|
||||
if (newVal == 2){
|
||||
if (newVal == 3) {
|
||||
modeType.value = '考试'
|
||||
}
|
||||
|
||||
}, { immediate: false })
|
||||
|
||||
|
||||
// 重新研读
|
||||
const params = reactive(
|
||||
{
|
||||
|
@ -260,76 +287,102 @@ const params = reactive(
|
|||
dataset_id: ''
|
||||
}
|
||||
)
|
||||
|
||||
// 重新研读
|
||||
const isAgain = ref(false)
|
||||
const againResult = async (index, item) => {
|
||||
isAgain.value = true
|
||||
isStarted.value[index] = false
|
||||
childTempList.value[index].answer = ''
|
||||
|
||||
if(index == 0){
|
||||
listRef.value.scrollTop = 0
|
||||
|
||||
}else{
|
||||
scrollToBottom(50, index)
|
||||
}
|
||||
|
||||
try {
|
||||
await nextTick()
|
||||
childTempList.value[index].loading = true
|
||||
item.aiShow = true
|
||||
childTempList.value[index].oldAnswer = ''
|
||||
params.prompt = `按照${item.name}的要求,针对${curNode.edustage}${curNode.edusubject}${modeType.value} 对${curNode.itemtitle}进行教学分析`
|
||||
const { data } = await completion(params)
|
||||
let answer = data.answer
|
||||
childTempList.value[index].oldAnswer = answer
|
||||
childTempList.value[index].answer = getResult(answer);
|
||||
// onEditSave(item)
|
||||
childTempList.value[index].answer = getResult(data.answer);
|
||||
isStarted.value[index] = true
|
||||
|
||||
} finally {
|
||||
childTempList.value[index].loading = false
|
||||
}
|
||||
}
|
||||
// 一键研读
|
||||
const getCompletion = async () => {
|
||||
isStarted.value = new Array(childTempList.length).fill(false)
|
||||
isStarted.value[0] = true
|
||||
|
||||
childTempList.value.forEach(item =>{
|
||||
if(item.answer){
|
||||
item.answer = ''
|
||||
}
|
||||
})
|
||||
|
||||
for (let item of childTempList.value) {
|
||||
try {
|
||||
item.loading = true
|
||||
item.aiShow = true
|
||||
params.prompt = `按照${item.name}的要求,针对${curNode.edustage}${curNode.edusubject}${modeType.value} 对${curNode.itemtitle}进行教学分析`
|
||||
const { data } = await completion(params)
|
||||
let answer = data.answer
|
||||
item.oldAnswer = answer
|
||||
item.answer = getResult(answer);
|
||||
|
||||
item.answer = getResult(data.answer)
|
||||
onSaveTemp(item)
|
||||
} finally {
|
||||
item.loading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleCompleteText = async (answer, index) =>{
|
||||
if (index < childTempList.value.length - 1) {
|
||||
isStarted.value[index + 1] = true; // 开始显示下一个文本
|
||||
}
|
||||
if(isAgain.value){
|
||||
try{
|
||||
await editTempResult({ id: childTempList.value[index].resultId, content: answer })
|
||||
}finally{
|
||||
isAgain.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 替换分析结果
|
||||
emitter.on('onSaveAdjust', (item) => {
|
||||
childTempList.value[curIndex.value].oldAnswer = item
|
||||
let answer = getResult(item);
|
||||
childTempList.value[curIndex.value].oldAnswer = item
|
||||
childTempList.value[curIndex.value].answer = answer
|
||||
childTempList.value[curIndex.value].answer = item
|
||||
onEditSave(childTempList.value[curIndex.value])
|
||||
})
|
||||
|
||||
|
||||
// 保存 重新研读后的结果
|
||||
const onEditSave = async (item) =>{
|
||||
const { res } = await editTempResult({id: item.resultId, content: item.oldAnswer})
|
||||
const onEditSave = async (item) => {
|
||||
const { res } = await editTempResult({ id: item.resultId, content: item.answer })
|
||||
ElMessage.success(res)
|
||||
getChildTemplate()
|
||||
}
|
||||
|
||||
// 保存模板
|
||||
const onSaveTemp = (item) => {
|
||||
if(item.oldAnswer == '') return
|
||||
if (item.answer == '') return
|
||||
|
||||
const data = {
|
||||
mainModelId: curTemplate.id,
|
||||
modelId: item.id,
|
||||
examDocld: '',
|
||||
content: item.oldAnswer
|
||||
content: item.answer
|
||||
}
|
||||
tempSave(data).then(res => {})
|
||||
tempSave(data).then(res => { })
|
||||
}
|
||||
|
||||
// 分析获取课标对话结果
|
||||
let getResult = (text) => {
|
||||
text = text.replace(/^\n\n(.*?)\n\n$/s, '<div>$1</div>');
|
||||
text = text.replace(/^\n(.*?)\n$/s, '<p>$1</p>');
|
||||
text = text.replace(/\*\*(.*?)\*\*/g, "<div class='text-tit'>$1</div>");
|
||||
text = text.replace(/(\d+\..*?)\n/g, "<div class='text-num'>$1</div>\n");
|
||||
return text
|
||||
// 去掉字符串中的 ### **
|
||||
let getResult = (str) => {
|
||||
let newStr = str.replace(/#+|(\*\*)/g, '');
|
||||
return newStr
|
||||
}
|
||||
|
||||
// 操作之后获取字模板
|
||||
|
@ -381,8 +434,6 @@ onUnmounted(() => {
|
|||
padding: 5px 15px;
|
||||
box-sizing: border-box;
|
||||
|
||||
|
||||
|
||||
.template-item {
|
||||
background: #fff;
|
||||
padding: 10px;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="typing-effect">
|
||||
<div class="typing-effect" ref="typingEffectRef">
|
||||
<!-- <span v-html="displayedText"></span> -->
|
||||
<el-input
|
||||
v-model="displayedText"
|
||||
|
@ -14,11 +14,11 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import { ref, onMounted, watch, nextTick } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
text: {
|
||||
type: String,
|
||||
type: [String, Object],
|
||||
required: true
|
||||
},
|
||||
delay: {
|
||||
|
@ -26,35 +26,48 @@ const props = defineProps({
|
|||
default: 100 // 默认每个字符出现的延迟时间,单位是毫秒
|
||||
},
|
||||
aiShow: {
|
||||
type: [Boolean]
|
||||
type: [Boolean] // 为true 只展示
|
||||
}
|
||||
});
|
||||
const emit = defineEmits(['complete']);
|
||||
const typingEffectRef = ref(null);
|
||||
const emit = defineEmits(['complete', 'updateScroll']);
|
||||
const displayedText = ref('');
|
||||
const index = ref(0);
|
||||
|
||||
const type = () => {
|
||||
if(!props.aiShow) return
|
||||
const type = async () => {
|
||||
await nextTick()
|
||||
if(!props.aiShow) {
|
||||
displayedText.value = props.text
|
||||
return
|
||||
}
|
||||
if (index.value <= props.text.length) {
|
||||
displayedText.value += props.text.charAt(index.value);
|
||||
index.value++;
|
||||
setTimeout(() => type(), props.delay);
|
||||
setTimeout(() => {
|
||||
type();
|
||||
emit('updateScroll', typingEffectRef.value.clientHeight); // 每次添加新字符后滚动到底部
|
||||
}, props.delay);
|
||||
} else {
|
||||
// 当所有字符都显示完毕时,触发 complete 事件
|
||||
emit('complete');
|
||||
emit('complete',displayedText.value);
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
type();
|
||||
resetAndType();
|
||||
});
|
||||
|
||||
// 监听 props 的变化,以便当传入的 text 或 delay 发生改变时重新开始打字机效果
|
||||
watch([() => props.text, () => props.delay], () => {
|
||||
const resetAndType = () =>{
|
||||
displayedText.value = '';
|
||||
index.value = 0;
|
||||
type();
|
||||
});
|
||||
}
|
||||
|
||||
// 监听 props 的变化,以便当传入的 text 或 delay 发生改变时重新开始打字机效果
|
||||
watch([() => props.text, () => props.delay], resetAndType);
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -85,6 +85,12 @@ export const constantRoutes = [
|
|||
name: 'questionUpload',
|
||||
meta: { title: '习题上传' }
|
||||
},
|
||||
{
|
||||
path: 'aiKolors',
|
||||
component: () => import('@/components/ai-kolors/index.vue'),
|
||||
name: 'aiKolors',
|
||||
meta: { title: '文生图片' }
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
|
|
|
@ -395,5 +395,6 @@ export const dataSetJson = {
|
|||
"课标-高中-英语": "e889fcac9fd011efb22a0242ac140006",
|
||||
"课标-高中-数学": "e03aa4fe9fd011ef91270242ac140006",
|
||||
"课标-高中-地理": "270516829fd111efb13c0242ac140006",
|
||||
"课标-高中-政治": "a7df2b01aafd11ef8bb40242ac140002",
|
||||
"鉴权": "ragflow-IwMDI1MGU2YTU3NjExZWZiNWEzMDI0Mm"
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="page">
|
||||
<div class="page-top">
|
||||
<div class="page-top" v-if="!isShow">
|
||||
<div class="page-top-left">
|
||||
<el-button type="danger" :icon="Delete" @click="handleDelete">删除</el-button>
|
||||
<el-button type="success" @click="handleTaskAssignToAllClass()">批量推送</el-button>
|
||||
|
@ -10,7 +10,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="page-resource">
|
||||
<div class="page-left">
|
||||
<div class="page-left" v-if="!isShow">
|
||||
<el-table
|
||||
ref="taskTable"
|
||||
v-loading="tasklist_loading"
|
||||
|
@ -154,7 +154,9 @@ const route = useRoute();
|
|||
const router = useRouter()
|
||||
const { proxy } = getCurrentInstance()
|
||||
const props = defineProps({
|
||||
currentCourse: Object,
|
||||
})
|
||||
const isShow = ref(false)
|
||||
|
||||
const propsQueryCourseObj = route.query.courseObj;//作业布置的内容对象
|
||||
const courseObj = reactive({
|
||||
|
@ -186,16 +188,48 @@ const fileLoading = ref(false); // 常规作业loading
|
|||
|
||||
onMounted(() => {
|
||||
currentRow.value = {id:0};
|
||||
console.log('propsQueryCourseObj', JSON.parse(propsQueryCourseObj));
|
||||
if(propsQueryCourseObj&&JSON.parse(propsQueryCourseObj)){
|
||||
if(propsQueryCourseObj){
|
||||
if(JSON.parse(propsQueryCourseObj)){
|
||||
courseObj.textbookId = JSON.parse(propsQueryCourseObj).bookObj // 版本
|
||||
courseObj.levelFirstId = JSON.parse(propsQueryCourseObj).levelFirstId // 单元
|
||||
courseObj.levelSecondId = JSON.parse(propsQueryCourseObj).levelSecondId // 章节
|
||||
courseObj.coursetitle = JSON.parse(propsQueryCourseObj).coursetitle // (单元/章节) 名称
|
||||
courseObj.node = JSON.parse(propsQueryCourseObj).node; // 保存当前节点
|
||||
}
|
||||
}else{
|
||||
if(props.currentCourse){
|
||||
courseObj.textbookId = props.currentCourse.textbookId // 版本
|
||||
courseObj.levelFirstId = props.currentCourse.levelFirstId // 单元
|
||||
courseObj.levelSecondId = props.currentCourse.levelSecondId // 章节
|
||||
courseObj.coursetitle = props.currentCourse.coursetitle // (单元/章节) 名称
|
||||
courseObj.node = props.currentCourse.node; // 保存当前节点
|
||||
classWorkForm.worktype = props.currentCourse.worktype
|
||||
currentRow.value = {
|
||||
id:props.currentCourse.id,
|
||||
worktype:props.currentCourse.worktype
|
||||
}
|
||||
isShow.value = true;
|
||||
}else{
|
||||
isShow.value = false;
|
||||
}
|
||||
}
|
||||
initHomeWork();
|
||||
})
|
||||
watch(() => props.currentCourse, (newVal, oldVal) => {
|
||||
if(newVal){
|
||||
courseObj.textbookId = newVal.textbookId // 版本
|
||||
courseObj.levelFirstId = newVal.levelFirstId // 单元
|
||||
courseObj.levelSecondId = newVal.levelSecondId // 章节
|
||||
courseObj.coursetitle = newVal.coursetitle // (单元/章节) 名称
|
||||
courseObj.node = newVal.node; // 保存当前节点
|
||||
classWorkForm.worktype = newVal.worktype
|
||||
currentRow.value = {
|
||||
id:props.currentCourse.id,
|
||||
worktype:props.currentCourse.worktype
|
||||
}
|
||||
}
|
||||
console.log(newVal,'newval');
|
||||
},{deep:true})
|
||||
//---------作业设计---
|
||||
const handleItemClick = (itemName) => {
|
||||
console.log('itemName', itemName);
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<el-button @click="handleQueryParamFromEntpCourseWork(1)"><el-icon><Search /></el-icon> 查找</el-button>
|
||||
</el-col>
|
||||
<el-col :span="5">
|
||||
<el-button type="primary" @click="goToQuestUpload()">添加习题</el-button>
|
||||
<el-button v-if="!props.isHtml2canvas" type="primary" @click="goToQuestUpload()">添加习题</el-button>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 习题表格 -->
|
||||
|
@ -58,9 +58,9 @@
|
|||
</div>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<div @click="showExamAnalyseDrawer(scope.row)">
|
||||
<div style="overflow: hidden; text-overflow: ellipsis" v-html="scope.row.titleFormat"></div>
|
||||
<div style="overflow: hidden; text-overflow: ellipsis; font-size: 0.9em; margin-top: 6px;" v-html="scope.row.workdescFormat"></div>
|
||||
<div @click="showExamAnalyseDrawer(scope.row)" :id=" `screenshot-target-${scope.row.id}` " style="padding: 5px;">
|
||||
<div style="overflow: hidden; text-overflow: ellipsis; padding: 2px;" v-html="scope.row.titleFormat"></div>
|
||||
<div style="overflow: hidden; text-overflow: ellipsis; font-size: 0.9em; margin-top: 6px; padding: 2px;" v-html="scope.row.workdescFormat"></div>
|
||||
<el-col :span="24" style="display: flex">
|
||||
<div style="font-size: 1em; color: silver; padding-top: 5px">{{ scope.row.entpname }} {{ scope.row.editusername }}</div>
|
||||
<div style="margin-left: 30px; font-size: 1em; color: silver; padding-top: 5px">{{ scope.row.worktag }}</div>
|
||||
|
@ -70,7 +70,8 @@
|
|||
</el-table-column>
|
||||
<el-table-column width="100">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
<el-button v-if="props.isHtml2canvas" type="primary" @click="captureScreenshot(scope.row.id)">选取该题</el-button>
|
||||
<div v-else>
|
||||
<el-button type="primary" @click="handleClassWorkQuizAdd('entpcourseworklist', scope.row.id)">添加</el-button>
|
||||
<div style="padding: 2px;"></div>
|
||||
<el-button type="warning" @click="handleImportSingleDlg(scope.row)">纠错</el-button>
|
||||
|
@ -117,6 +118,7 @@
|
|||
import { Search } from '@element-plus/icons-vue'
|
||||
import { onMounted, ref,watch, reactive, getCurrentInstance,nextTick } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import html2canvas from 'html2canvas';
|
||||
|
||||
import { listEntpcoursework, listEntpcourseworkLocal } from '@/api/education/entpCourseWork'
|
||||
import { listEvaluationclue } from '@/api/classTask'
|
||||
|
@ -136,7 +138,7 @@ const router = useRouter()
|
|||
|
||||
|
||||
// 定义要发送的emit事件
|
||||
const emit = defineEmits(['addQuiz'])
|
||||
let emit = defineEmits(['addQuiz', 'addQuizImgBs64'])
|
||||
const { proxy } = getCurrentInstance()
|
||||
const userStore = useUserStore().user
|
||||
const {
|
||||
|
@ -150,6 +152,10 @@ const props = defineProps({
|
|||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
isHtml2canvas: {// 是否截屏
|
||||
type: Boolean,
|
||||
default: () => false
|
||||
},
|
||||
})
|
||||
|
||||
const knowledgePointProps = ref({value: 'thirdId', label: 'title'});
|
||||
|
@ -440,6 +446,22 @@ const handleDelete = async(item, index) => {
|
|||
// ElMessage('试题已经存在')
|
||||
// }
|
||||
};
|
||||
|
||||
/**
|
||||
* 把该题区域id 获取为截屏区域
|
||||
* @param id 试题id
|
||||
*/
|
||||
const captureScreenshot = (id) => {
|
||||
const targetElement = document.getElementById('screenshot-target-' + id);
|
||||
html2canvas(targetElement).then(canvas => {
|
||||
// 将canvas转换为图像URL
|
||||
const screenshotUrl = canvas.toDataURL('image/png');
|
||||
// 在这里可以将截图保存到本地或上传到服务器
|
||||
// console.log(screenshotUrl);
|
||||
emit('addQuizImgBs64', screenshotUrl);
|
||||
});
|
||||
}
|
||||
|
||||
// 防抖
|
||||
const debounceQueryData = debounce(() => {
|
||||
console.log("防抖 加载数据中...")
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
<template>
|
||||
<div class="page">
|
||||
<div class="page-resource">
|
||||
<div class="page-center">
|
||||
<el-tabs v-model="activeAptTab" style="height: 100%;">
|
||||
<el-tab-pane label="自主搜题" name="自主搜题" class="prepare-center-zzst">
|
||||
<SearchQuestion :bookobj="courseObj" :isHtml2canvas="true" @addQuizImgBs64="handleaddQuizImgBs64" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="校本题库" name="校本题库" class="prepare-center-xbtk">
|
||||
<SchoolQuestion />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="个人题库" name="个人题库" class="prepare-center-grst">
|
||||
<MyQuestion :bookobj="courseObj" :isHtml2canvas="true" @addQuizImgBs64="handleaddQuizImgBs64"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { onMounted, ref, watch, reactive, getCurrentInstance, nextTick } from 'vue'
|
||||
|
||||
import MyQuestion from '@/views/classTask/newClassTaskAssign/myQuestion/index.vue'
|
||||
import SchoolQuestion from '@/views/classTask/newClassTaskAssign/schoolQuestion/index.vue'
|
||||
import SearchQuestion from '@/views/classTask/newClassTaskAssign/searchQuestion/index.vue'
|
||||
|
||||
import { sessionStore } from '@/utils/store'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
const userStore = useUserStore().user
|
||||
|
||||
|
||||
const emit = defineEmits(['update']);
|
||||
const courseObj = reactive({
|
||||
// 课程相关参数: 教材id,单元id,章节id,课程名称
|
||||
textbookId: '',
|
||||
levelFirstId: '',
|
||||
levelSecondId: '',
|
||||
coursetitle:'',
|
||||
node: null, // 选择的课程节点
|
||||
//
|
||||
})
|
||||
|
||||
const activeAptTab = ref("自主搜题");
|
||||
|
||||
onMounted(() => {
|
||||
const curNode = sessionStore.get('subject.curNode')
|
||||
courseObj.textbookId = curNode.rootid
|
||||
courseObj.levelFirstId = curNode.parentNode.id
|
||||
courseObj.levelSecondId = curNode.id
|
||||
courseObj.coursetitle = curNode.itemtitle,
|
||||
courseObj.node = curNode
|
||||
})
|
||||
|
||||
|
||||
const handleaddQuizImgBs64 = (quizbs64) => {
|
||||
emit('update', quizbs64)
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
|
||||
})
|
||||
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.page {
|
||||
height: 100%;
|
||||
|
||||
.page-resource {
|
||||
user-select: none;
|
||||
height: calc(100% - 55px);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
flex: 1;
|
||||
:deep(.el-tabs__nav) {
|
||||
.el-tabs__item{
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.page-center{
|
||||
flex: 1;
|
||||
//min-width: calc(100% - 675px);
|
||||
height: 100%;
|
||||
padding: 0 5px;
|
||||
margin: 0 5px;
|
||||
overflow: hidden;
|
||||
border-radius: 10px;
|
||||
background-color: white;
|
||||
|
||||
.prepare-center-zzst{
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
|
||||
}
|
||||
.prepare-center-xbtk{
|
||||
height: 100%;
|
||||
}
|
||||
.prepare-center-grst{
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
.upload-homework{
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -71,9 +71,9 @@
|
|||
</div>
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<div @click="showExamAnalyseDrawer(scope.row)">
|
||||
<div style="overflow: hidden; text-overflow: ellipsis" v-html="scope.row.titleFormat"></div>
|
||||
<div style="overflow: hidden; text-overflow: ellipsis; font-size: 0.9em; margin-top: 6px;" v-html="scope.row.workdescFormat"></div>
|
||||
<div @click="showExamAnalyseDrawer(scope.row)" :id=" `screenshot-target-${scope.row.id}` " style="padding: 5px;">
|
||||
<div style="overflow: hidden; text-overflow: ellipsis; padding: 2px;" v-html="scope.row.titleFormat"></div>
|
||||
<div style="overflow: hidden; text-overflow: ellipsis; font-size: 0.9em; margin-top: 6px; padding: 2px;" v-html="scope.row.workdescFormat"></div>
|
||||
<el-col :span="24" style="display: flex">
|
||||
<div style="font-size: 1em; color: silver; padding-top: 5px">{{ scope.row.entpname }} {{ scope.row.editusername }}</div>
|
||||
<div style="margin-left: 30px; font-size: 1em; color: silver; padding-top: 5px">{{ scope.row.worktag }}</div>
|
||||
|
@ -83,7 +83,8 @@
|
|||
</el-table-column>
|
||||
<el-table-column align="left" width="100">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" @click="handleClassWorkQuizAdd('entpcourseworklist', scope.row.id)">添加</el-button>
|
||||
<el-button v-if="props.isHtml2canvas" type="primary" @click="captureScreenshot(scope.row.id)">选取该题</el-button>
|
||||
<el-button v-else type="primary" @click="handleClassWorkQuizAdd('entpcourseworklist', scope.row.id)">添加</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
@ -104,7 +105,7 @@
|
|||
</template>
|
||||
<script setup>
|
||||
import { Search } from '@element-plus/icons-vue'
|
||||
|
||||
import html2canvas from 'html2canvas';
|
||||
import { onMounted, ref,watch, reactive, getCurrentInstance,nextTick } from 'vue'
|
||||
|
||||
import {listEntpcoursework, listEntpcourseworkNew, getEntpcoursework} from '@/api/education/entpCourseWork'
|
||||
|
@ -122,7 +123,7 @@ import useUserStore from '@/store/modules/user'
|
|||
import useClassTaskStore from '@/store/modules/classTask'
|
||||
|
||||
// 定义要发送的emit事件
|
||||
const emit = defineEmits(['addQuiz'])
|
||||
let emit = defineEmits(['addQuiz', 'addQuizImgBs64'])
|
||||
const { proxy } = getCurrentInstance()
|
||||
const userStore = useUserStore().user
|
||||
const {
|
||||
|
@ -136,6 +137,10 @@ const props = defineProps({
|
|||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
isHtml2canvas: {// 是否截屏
|
||||
type: Boolean,
|
||||
default: () => false
|
||||
},
|
||||
})
|
||||
|
||||
const entpCourseWorkPointList = ref([
|
||||
|
@ -427,6 +432,20 @@ const getPaginationList = ( page, limit ) => {
|
|||
// ElMessage('试题已经存在')
|
||||
// }
|
||||
};
|
||||
/**
|
||||
* 把该题区域id 获取为截屏区域
|
||||
* @param id 试题id
|
||||
*/
|
||||
const captureScreenshot = (id) => {
|
||||
const targetElement = document.getElementById('screenshot-target-' + id);
|
||||
html2canvas(targetElement).then(canvas => {
|
||||
// 将canvas转换为图像URL
|
||||
const screenshotUrl = canvas.toDataURL('image/png');
|
||||
// 在这里可以将截图保存到本地或上传到服务器
|
||||
// console.log(screenshotUrl);
|
||||
emit('addQuizImgBs64', screenshotUrl);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 防抖
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<el-dialog v-model="isDialog" :show-close="false" width="900" destroy-on-close>
|
||||
<el-dialog v-model="isDialog" :show-close="false" width="900" append-to-body destroy-on-close>
|
||||
<template #header>
|
||||
<div class="custom-header flex">
|
||||
<span>选择{{ title }}</span>
|
||||
|
@ -15,8 +15,10 @@
|
|||
</div>
|
||||
<div class="content-list">
|
||||
<ul>
|
||||
<li v-for="(item, index) in fileList" :class="activeIndex == index ? 'li-active' : ''" @click="clickItem(index, item)">
|
||||
<li v-for="(item, index) in fileList" :class="activeIndex == index ? 'li-active' : ''"
|
||||
@click="clickItem(index, item)">
|
||||
<el-image class="img" :src="url" />
|
||||
<el-button type="primary" class="prev-btn" @click.stop="onPrevItem(item)">预览</el-button>
|
||||
<el-text truncated>{{ item.fileName }}</el-text>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -24,8 +26,8 @@
|
|||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-upload class="upload-demo" :action="uploadFileUrl" :limit="1" :show-file-list="false"
|
||||
:headers="headers" :on-success="onSuccess">
|
||||
<el-upload class="upload-demo" :action="uploadFileUrl" :limit="1" :show-file-list="false" :headers="headers"
|
||||
:on-success="onSuccess">
|
||||
<el-button type="primary">上传</el-button>
|
||||
</el-upload>
|
||||
<div>
|
||||
|
@ -37,6 +39,31 @@
|
|||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog v-model="prevVisible" fullscreen :show-close="false" class="prev-dialog">
|
||||
<template #header>
|
||||
<div class="custom-header flex">
|
||||
<span>预览</span>
|
||||
<i class="iconfont icon-guanbi" @click="prevVisible = false"></i>
|
||||
</div>
|
||||
</template>
|
||||
<div style="height: calc(100vh - 120px);">
|
||||
<template v-if="getFileSuffix(prevItem.fileUrl) == 'pdf'">
|
||||
<iframe :src="prevItem.fileUrl"
|
||||
frameborder="0" width="100%" height="100%"></iframe>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-image :src="prevItem.fileUrl" style="height:100%"/>
|
||||
</template>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<div></div>
|
||||
<el-button type="primary" @click="prevVisible = false">
|
||||
关闭
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
@ -47,6 +74,7 @@ import { sessionStore } from '@/utils/store'
|
|||
import { dataSetJson } from '@/utils/comm.js'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import useUserStore from '@/store/modules/user'
|
||||
import { getFileSuffix } from '@/utils/ruoyi.js'
|
||||
import emitter from '@/utils/mitt';
|
||||
|
||||
const userInfo = useUserStore().user
|
||||
|
@ -56,6 +84,7 @@ const headers = ref({ Authorization: "Bearer " + getToken() });
|
|||
const url = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F11044b08-04c1-41a0-a453-1fd20b58a614%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1732953359&t=7ab1d1b3a903db85b1149914407aea35'
|
||||
|
||||
const isDialog = defineModel()
|
||||
const prevVisible = ref(false)
|
||||
|
||||
const props = defineProps({
|
||||
modeType: {
|
||||
|
@ -99,15 +128,14 @@ const activeIndex = ref(0)
|
|||
const dataset_id = ref('')
|
||||
|
||||
// 上传成功
|
||||
const onSuccess = async (response) =>{
|
||||
console.log(response,'response')
|
||||
const onSuccess = async (response) => {
|
||||
let data = {
|
||||
url: response.url,
|
||||
dataset_id: dataset_id.value
|
||||
}
|
||||
const res = await completion(data)
|
||||
|
||||
if(res.data.code != 200) return
|
||||
if (res.data.code != 200) return
|
||||
let docData = {
|
||||
fileUrl: response.url,
|
||||
fileId: response.file.id,
|
||||
|
@ -127,11 +155,11 @@ const curNode = reactive({})
|
|||
|
||||
const fileList = ref([])
|
||||
const curFile = reactive({})
|
||||
const getList = () =>{
|
||||
const getList = () => {
|
||||
docList({
|
||||
userId: userInfo.userId,
|
||||
dataset_id: dataset_id.value
|
||||
}).then( res =>{
|
||||
}).then(res => {
|
||||
fileList.value = [...res.rows]
|
||||
Object.assign(curFile, fileList.value[0])
|
||||
})
|
||||
|
@ -140,12 +168,16 @@ const getList = () =>{
|
|||
const clickItem = (index, item) => {
|
||||
activeIndex.value = index
|
||||
Object.assign(curFile, item)
|
||||
emitter.emit('curFile',item)
|
||||
emitter.emit('curFile', item)
|
||||
}
|
||||
|
||||
const prevItem = reactive({})
|
||||
const onPrevItem = (item) => {
|
||||
Object.assign(prevItem, item)
|
||||
prevVisible.value = true
|
||||
}
|
||||
|
||||
|
||||
onMounted(() =>{
|
||||
onMounted(() => {
|
||||
let data = sessionStore.get('subject.curNode')
|
||||
Object.assign(curNode, data);
|
||||
|
||||
|
@ -155,7 +187,6 @@ onMounted(() =>{
|
|||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.custom-header {
|
||||
justify-content: space-between;
|
||||
|
@ -192,9 +223,11 @@ onMounted(() =>{
|
|||
overflow: hidden;
|
||||
margin-right: 20px;
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
.img {
|
||||
width: 100px;
|
||||
width: 100%;
|
||||
height: 130px;
|
||||
border: solid #ccc 1px;
|
||||
margin-bottom: 10px;
|
||||
|
@ -203,6 +236,10 @@ onMounted(() =>{
|
|||
&:hover {
|
||||
background: #E0EAFF;
|
||||
}
|
||||
|
||||
&:hover .prev-btn {
|
||||
transform: translate(-50%, -50%)
|
||||
}
|
||||
}
|
||||
|
||||
.li-active {
|
||||
|
@ -212,9 +249,20 @@ onMounted(() =>{
|
|||
}
|
||||
}
|
||||
}
|
||||
.dialog-footer{
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.prev-btn {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%) translateY(-110px);
|
||||
/* 按钮初始位置在容器外 */
|
||||
transition: transform 0.3s ease-in-out;
|
||||
/* 设置过渡效果 */
|
||||
}
|
||||
</style>
|
|
@ -14,8 +14,14 @@ const pdfUrl = ref('')
|
|||
|
||||
onMounted(async () =>{
|
||||
await nextTick()
|
||||
const { fileurl } = sessionStore.get('subject.curBook')
|
||||
pdfUrl.value = import.meta.env.VITE_APP_RES_FILE_PATH + fileurl.replace('.txt','.pdf')
|
||||
|
||||
let data = sessionStore.get('subject.curBook')
|
||||
let fileurl = data.fileurl
|
||||
|
||||
if(fileurl == ''){
|
||||
fileurl = `${data.edustage}-${data.edusubject}-课标.txt`
|
||||
}
|
||||
pdfUrl.value = import.meta.env.VITE_APP_RES_FILE_PATH + fileurl.replace('.txt', '.pdf')
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
<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>
|
||||
|
@ -51,9 +52,12 @@ import { useRouter } from 'vue-router'
|
|||
import { Plus, Refresh, Upload, Files, UploadFilled } from '@element-plus/icons-vue'
|
||||
import useUserStore from '@/store/modules/user' // 用户信息
|
||||
import msgUtils from '@/plugins/modal' // 消息工具
|
||||
import { createWindow, sessionStore } from '@/utils/tool' // 相关工具
|
||||
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 { menusEvent } from '@/plugins/vue3-menus' // 右键菜单
|
||||
|
@ -156,6 +160,21 @@ const onchange = (path) => {
|
|||
if (path == '/model/newClassTaskAssign') {
|
||||
// 作业管理
|
||||
router.push({ path, query: { courseObj: JSON.stringify(courseObj) } })
|
||||
} else if (path == '/model/aiKolors') {
|
||||
// ai生图
|
||||
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 {
|
||||
router.push(path)
|
||||
}
|
||||
|
|
|
@ -57,11 +57,11 @@
|
|||
</el-row>
|
||||
<div>
|
||||
<el-button style="margin-bottom: 5px;" type="primary" @click="activeStep = 0">上一步</el-button>
|
||||
<el-button style="margin-bottom: 5px;" type="primary" @click="outlineCreatePPT()">生成PPT</el-button>
|
||||
<el-button style="margin-bottom: 5px;" type="primary" v-loading="createPPTLoading" @click="outlineCreatePPT()">生成PPT</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card v-if="activeStep === 2">
|
||||
<el-progress :percentage="30" type="circle" v-if="percentage === 30"></el-progress>
|
||||
<el-progress :percentage="percentage" type="circle"></el-progress>
|
||||
</el-card>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -79,6 +79,7 @@ import {
|
|||
import CryptoJS from "crypto-js"
|
||||
|
||||
import { getSignature } from "@/utils/index.js";
|
||||
import {sessionStore} from "@/utils/store";
|
||||
|
||||
let appId = "01ec9aa3";
|
||||
let secret = "M2QxMDAxMjYyYTEzODMwMGRkZTQ4NmUy";
|
||||
|
@ -98,8 +99,8 @@ let secondArray = ref([]); //大纲的文字部分
|
|||
|
||||
|
||||
const backGroundList = ref([]);
|
||||
|
||||
const inputTheme = ref("高中语文《沁园春雪》的授课课件"); // 输入的主题
|
||||
let subjectdata = sessionStore.get('subject.curNode')
|
||||
const inputTheme = ref(subjectdata.edustage + subjectdata.edusubject + "《" + subjectdata.itemtitle + "》的授课课件"); // 输入的主题
|
||||
const inputRequire = ref("") // 输入的需求
|
||||
const activeStep = ref(0); // 上方进度条
|
||||
const combined = ref('') // 修改完毕的大纲数据,准备传入ppt生成模型
|
||||
|
@ -109,6 +110,8 @@ const status = ref("init");
|
|||
|
||||
const percentage = ref(0);
|
||||
|
||||
const createPPTLoading = ref(false);
|
||||
|
||||
const getBackgrounds = () => {
|
||||
treeData.value = [];
|
||||
getBackGroundV2().then((res) => {
|
||||
|
@ -126,6 +129,8 @@ const outlineData = ref({
|
|||
// templateId: 'auto', // ppt生成主题
|
||||
author: 'AIX平台',
|
||||
isFigure: false, // 是否自动配图
|
||||
search: true,
|
||||
language: "cn"
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -145,20 +150,17 @@ function updateStagingData(role, newData) {
|
|||
const outlineCreatePPT = () => {
|
||||
const newOutlineData = { ...outlineData.value, };
|
||||
newOutlineData.query = outputText.value;
|
||||
|
||||
createPPTLoading.value = true;
|
||||
createPPTV2(newOutlineData).then((res) => {
|
||||
console.log(res, "正在生成中");
|
||||
createPPTLoading.value = false;
|
||||
activeStep.value = 2
|
||||
|
||||
const checkProgress = () => {
|
||||
getProgressV2(res.sid).then((response) => {
|
||||
percentage.value = response.process;
|
||||
if (response && response.pptUrl && response.pptUrl.length > 4) {
|
||||
console.log('PPT',response)
|
||||
// window.location.href = response.data.pptUrl;
|
||||
//发消息到主进程,携带名称和URL,将URL下载下来后复制到文件列表并上传到服务
|
||||
// let url = "https://bjcdn.openstorage.cn/xinghuo-privatedata/%2Ftmp/apiTempFiledf28bf990a4c40ffb7477ed4b65392c27232357022409613439/%E3%80%8A%E9%9D%99%E5%A5%B3%E3%80%8B%E6%B7%B1%E5%BA%A6%E8%A7%A3%E8%AF%BB%E4%B8%8E%E7%A0%94%E7%A9%B6.pptx"
|
||||
emit('addSuccess',res)
|
||||
getProgressV2(res.sid).then(response => {
|
||||
percentage.value = Math.round(response?.donePages/response?.totalPages)*100;
|
||||
if (response.pptStatus === "done") {
|
||||
emit('addSuccess',{...res,url:response.pptUrl})
|
||||
ElMessage.success("生成成功");
|
||||
} else {
|
||||
const sleepTime = 2000;
|
||||
|
|
|
@ -59,14 +59,16 @@
|
|||
<!-- 手机登录 -->
|
||||
<template #item_mobile>
|
||||
<div>
|
||||
<div>开始新的课堂,需要点击先创建课堂,才能显示手机二维码</div>
|
||||
<div v-if="myClassActive.filetype=='apt'">开始新的课堂,需要点击先创建课堂,才能显示手机二维码</div>
|
||||
<div v-else>开始新的课堂,需要点击先创建课堂</div>
|
||||
<el-button type="warning" :loading="dt.loading" @click="createClasscourse">创建课堂</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 故障备用 -->
|
||||
<template #item_backup>
|
||||
<div>
|
||||
<div>如果手机扫码后进入课堂,但本页面没自动跳转,请点击下面按钮</div>
|
||||
<div v-if="myClassActive.filetype=='apt'">如果手机扫码后进入课堂,但本页面没自动跳转,请点击下面按钮</div>
|
||||
<div v-else>本页面没自动跳转,请点击下面按钮</div>
|
||||
<el-button type="primary" plain @click="classTeachingStart">开始上课</el-button>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -81,7 +83,7 @@
|
|||
|
||||
<script setup>
|
||||
// 功能说明:课程开始
|
||||
import { onMounted, reactive, ref, watchEffect, watch, nextTick } from 'vue' // vue
|
||||
import { onMounted, reactive, ref, watchEffect, watch, nextTick, toRaw } from 'vue' // vue
|
||||
import { Refresh } from '@element-plus/icons-vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus' // ui框架: 消息提示
|
||||
import vueQr from 'vue-qr/src/packages/vue-qr.vue' // 插件: 二维码
|
||||
|
@ -149,9 +151,9 @@ const open = async (id, classObj) => {
|
|||
teacherForm.form.classcourseid = classObj.id
|
||||
}
|
||||
// 初始化im-chat
|
||||
nextTick(async() => {
|
||||
chat = await imChatRef.value?.initImChat()
|
||||
})
|
||||
// nextTick(async() => {
|
||||
// chat = await imChatRef.value?.initImChat()
|
||||
// })
|
||||
}
|
||||
}
|
||||
// 关闭弹窗
|
||||
|
@ -259,7 +261,15 @@ const createClasscourse = async () => {
|
|||
dt.loading = false
|
||||
// getClasscourseList('update') // 更新列表
|
||||
ElMessage.success('创建课程-成功')
|
||||
|
||||
// 新版-pptList 打开公屏
|
||||
if (myClassActive.value.filetype == 'aptist') {
|
||||
const msgEl = ElMessage.warning({message:'正在打开公屏,请稍后...',duration: 0})
|
||||
setTimeout(() => {
|
||||
msgEl.close()
|
||||
const classcourse = {...params, id: teacherForm.form.classcourseid}
|
||||
openPublicScreen(classcourse)
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
// 删除课程
|
||||
const removeClasscourse = async () => {
|
||||
|
@ -323,6 +333,21 @@ const getQrUrl = async() => {
|
|||
}
|
||||
teacherForm.form.qrUrl = baseUrl + qrCodeUrl
|
||||
}
|
||||
|
||||
// 打开公屏
|
||||
const openPublicScreen = (classcourse) => {
|
||||
const resource = toRaw(myClassActive.value)
|
||||
sessionStore.set('curr.resource', resource) // 缓存当前资源信息
|
||||
sessionStore.set('curr.classcourse', classcourse) // 缓存当前当前上课
|
||||
createWindow('open-win', {
|
||||
url: '/pptist', // 窗口关闭时,清除缓存
|
||||
close: () => {
|
||||
sessionStore.set('curr.resource', null) // 清除缓存
|
||||
sessionStore.set('curr.classcourse', null) // 清除缓存
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 定时器监听
|
||||
|
||||
// ================== 监听 =======================
|
||||
|
|
|
@ -341,6 +341,8 @@ export default {
|
|||
cookieData: { ...configObj.data }
|
||||
})
|
||||
return
|
||||
} else if(items.fileFlag === 'aptist') { // aptist 被点击 打开PPT-List 课件
|
||||
return this.$emit('change', 'click', items)
|
||||
}
|
||||
if (!items||!items.fileSuffix) return;
|
||||
getPrepareById(items.id).then((item) => {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import AiPptist from './ai-pptist.vue';
|
||||
import AiPptist from './ai-pptistV2.vue';
|
||||
const model = defineModel()
|
||||
const emit = defineEmits(['addSuccess'])
|
||||
const props = defineProps({
|
||||
|
|
|
@ -175,8 +175,9 @@ import { updateClasscourse } from '@/api/teaching/classcourse'
|
|||
import { getClassInfo, getSelfReserv, endClass } from '@/api/classManage'
|
||||
import { useGetHomework } from '@/hooks/useGetHomework'
|
||||
import { editListItem } from '@/hooks/useClassTask'
|
||||
import { addEntpcoursefileReturnId } from '@/api/education/entpcoursefile'
|
||||
import { addEntpcoursefileReturnId, getEntpcoursefile } from '@/api/education/entpcoursefile'
|
||||
import ClassReserv from '@/views/classManage/classReserv.vue'
|
||||
import TreeLog from '@/views/prepare/components/treeLog.vue'
|
||||
import classStart from './container/class-start.vue' // 预备上课
|
||||
import MsgEnum from '@/plugins/imChat/msgEnum' // im 消息枚举
|
||||
import Chat from '@/utils/chat' // im 登录初始化
|
||||
|
@ -239,7 +240,9 @@ export default {
|
|||
activeClass: null,
|
||||
pptDialog: false,
|
||||
// 打开章节的弹窗
|
||||
treelogRef:null
|
||||
treelogRef:null,
|
||||
// 获取当前章节对应的课程信息 Entpcourse
|
||||
entp: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -249,10 +252,12 @@ export default {
|
|||
)
|
||||
},
|
||||
currentKJFileList() {
|
||||
return this.currentFileList.filter((item) => item.fileFlag === 'apt' || item.fileFlag === '课件')
|
||||
// return this.currentFileList.filter((item) => item.fileFlag === 'apt' || item.fileFlag === '课件')
|
||||
return this.currentFileList.filter((item) => ['apt','aptist','课件'].includes(item.fileFlag))
|
||||
},
|
||||
currentSCFileList() {
|
||||
return this.currentFileList.filter((item) => item.fileFlag !== 'apt' && item.fileFlag !== '课件')
|
||||
// return this.currentFileList.filter((item) => item.fileFlag !== 'apt' && item.fileFlag !== '课件')
|
||||
return this.currentFileList.filter((item) => !['apt','aptist','课件'].includes(item.fileFlag))
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -305,8 +310,8 @@ export default {
|
|||
// 开始上课
|
||||
startClass(item, classObj) {
|
||||
// 关闭状态,打开上课相关功能(已打开,忽略)
|
||||
const id = sessionStore.has('activeClass.id') ? sessionStore.get('activeClass.id') : null
|
||||
if (id && id == item.id) return ElMessage.warning('当前正在上课,请勿重复操作')
|
||||
// const id = sessionStore.has('activeClass.id') ? sessionStore.get('activeClass.id') : null
|
||||
// if (id && id == item.id) return ElMessage.warning('当前正在上课,请勿重复操作')
|
||||
// 当前上课-store
|
||||
sessionStore.set('activeClass', item)
|
||||
this.activeClass = item
|
||||
|
@ -316,6 +321,9 @@ export default {
|
|||
if(item.fileFlag === 'apt') {
|
||||
this.$refs.calssRef.open(item.fileId, classObj)
|
||||
}
|
||||
if(item.fileFlag === 'aptist') {
|
||||
this.$refs.calssRef.open(item.fileId, classObj)
|
||||
}
|
||||
},
|
||||
// 继续上课-apt
|
||||
async changeClass(type, row, other) {
|
||||
|
@ -370,6 +378,28 @@ export default {
|
|||
}, 1000)
|
||||
break
|
||||
}
|
||||
case 'click': { // 点击-打开课件-aptist
|
||||
if (row.fileFlag === 'aptist' && !!row.fileId) {
|
||||
const res = await getEntpcoursefile(row.fileId)
|
||||
if (res && res.code === 200) {
|
||||
sessionStore.set('curr.resource', res.data) // 缓存当前资源信息
|
||||
sessionStore.set('curr.smarttalk', row) // 缓存当前文件smarttalk
|
||||
createWindow('open-win', {
|
||||
url: '/pptist', // 窗口关闭时,清除缓存
|
||||
close: () => {
|
||||
sessionStore.set('curr.resource', null) // 清除缓存
|
||||
sessionStore.set('curr.smarttalk', null) // 清除缓存
|
||||
this.asyncAllFile() // 刷新资源列表
|
||||
}
|
||||
})
|
||||
} else {
|
||||
ElMessage.warning(res.msg||'文件获取异常!')
|
||||
}
|
||||
return
|
||||
}
|
||||
ElMessage.warning('该功能暂未开放!')
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
@ -623,6 +653,7 @@ export default {
|
|||
for (let i = 0; i < this.currentFileList.length; i++) {
|
||||
let item = this.currentFileList[i]
|
||||
if (item.fileFlag === 'apt') continue;
|
||||
if (item.fileFlag === 'aptist') continue;
|
||||
await asyncLocalFile(item)
|
||||
}
|
||||
this.asyncAllFileVisiable = false
|
||||
|
@ -651,6 +682,11 @@ export default {
|
|||
toolStore.curSubjectNode.querySearch = this.uploadData
|
||||
this.initHomeWork()
|
||||
await this.asyncAllFile()
|
||||
// 获取当前章节对应的课程信息
|
||||
const params = { evalid: this.currentNode.id, edituserid: this.userStore.userId, pageSize: 1 }
|
||||
const res = await listEntpcourse(params)
|
||||
this.entp = res?.rows?.[0] || null
|
||||
sessionStore.set('curr.entp', this.entp) // 缓存当前课程信息
|
||||
},
|
||||
// 获取作业
|
||||
async initHomeWork() {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<div class="info">
|
||||
<div class="info-name">{{ state.user.nickName }}</div>
|
||||
<div class="infomation">
|
||||
<selectClass/>
|
||||
<selectClass v-if="!isSubject"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -46,8 +46,10 @@ const state = reactive({
|
|||
postGroup: {}
|
||||
})
|
||||
|
||||
const isSubject = ref(false)
|
||||
async function getUser() {
|
||||
getUserProfile().then((response) => {
|
||||
isSubject.value = response.roleGroup.indexOf('场馆管理员') != -1
|
||||
// response.data.avatar = import.meta.env.VITE_APP_BASE_API + response.data.avatar
|
||||
Object.assign(state.user,response.data)
|
||||
state.roleGroup = response.roleGroup
|
||||
|
|
|
@ -68,6 +68,7 @@ import {PPTXFileToJson} from '@/AixPPTist/src/hooks/useImport' // ppt转json
|
|||
import * as API_entpcourse from '@/api/education/entpcourse' // 相关api
|
||||
import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api
|
||||
import * as Api_server from '@/api/apiService' // 相关api
|
||||
import * as API_smarttalk from '@/api/file' // 文件相关api
|
||||
import msgUtils from '@/plugins/modal' // 消息工具
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
@ -136,6 +137,8 @@ const addAiPPT = async(res) => {
|
|||
const p_params = {parentContent: JSON.stringify(content)}
|
||||
const parentid = await HTTP_SERVER_API('addEntpcoursefile', p_params)
|
||||
if (!!parentid??null) { // 生成内容幻灯片
|
||||
// 生成备课资源-Smarttalk
|
||||
HTTP_SERVER_API('addSmarttalk',{fileId: parentid})
|
||||
if (slides.length > 0) {
|
||||
const resSlides = slides.map(({id, ...slide}) => JSON.stringify(slide))
|
||||
const params = {parentid, filetype: 'slide', title: '', slides: resSlides }
|
||||
|
@ -206,6 +209,20 @@ emitter.on('changeResult', (item) => {
|
|||
// 统一HTTP处理
|
||||
const HTTP_SERVER_API = (type, params = {}) => {
|
||||
switch (type) {
|
||||
case 'addSmarttalk': { // 获取课程
|
||||
const node = courseObj.node || {}
|
||||
const def = {
|
||||
fileId: '', // 文件id - Entpcoursefile 对应id
|
||||
fileFlag: 'aptist',
|
||||
fileShowName: node.itemtitle + '.aptist',
|
||||
textbookId: node.rootid,
|
||||
levelFirstId: node.parentid||node.id,
|
||||
levelSecondId: node.parentid && node.id,
|
||||
fileSource: '个人',
|
||||
fileRoot: '备课'
|
||||
}
|
||||
return API_smarttalk.creatAPT({...def, ...params})
|
||||
}
|
||||
case 'addEntpcourse': { // 添加课程
|
||||
const node = courseObj.node || {}
|
||||
if (!node) return msgUtils.msgWarning('请选择章节?')
|
||||
|
@ -298,6 +315,7 @@ const toRousrceUrl = async(o) => {
|
|||
const curNode = reactive({})
|
||||
onMounted(() => {
|
||||
let data = sessionStore.get('subject.curNode')
|
||||
console.log('data', sessionStore)
|
||||
Object.assign(curNode, data);
|
||||
courseObj.node = data
|
||||
|
||||
|
|
Loading…
Reference in New Issue