diff --git a/.env.yc b/.env.yc new file mode 100644 index 0000000..c3b1489 --- /dev/null +++ b/.env.yc @@ -0,0 +1,25 @@ +# 页面标题 +VITE_APP_TITLE = 文枢课堂 + +# 生产环境配置 +VITE_APP_ENV = 'production' + +# AIx融合数字管理系统/生产环境 +VITE_APP_BASE_API = 'https://prev.ysaix.com:7868/prod-api' + +VITE_APP_DOMAIN = 'prev.ysaix.com' + +VITE_APP_UPLOAD_API = 'https://prev.ysaix.com:7868/prod-api' + +# 是否在打包时开启压缩,支持 gzip 和 brotli +VITE_BUILD_COMPRESS = gzip + +VITE_APP_RES_FILE_PATH = 'https://prev.ysaix.com:7868/src/assets/textbook/booktxt/' + +VITE_APP_BUILD_BASE_PATH = 'https://prev.ysaix.com:7868/' + +# websocket 地址 +VITE_APP_WS_URL = 'wss://prev.ysaix.com:7868' + +# 是否显示开发工具 +VITE_SHOW_DEV_TOOLS = 'false' diff --git a/.env.yc2 b/.env.yc2 new file mode 100644 index 0000000..c4a88ef --- /dev/null +++ b/.env.yc2 @@ -0,0 +1,25 @@ +# 页面标题 +VITE_APP_TITLE = 实训教学 + +# 生产环境配置 +VITE_APP_ENV = 'production' + +# AIx融合数字管理系统/生产环境 +VITE_APP_BASE_API = 'https://prev.ysaix.com:7868/prod-api' + +VITE_APP_DOMAIN = 'prev.ysaix.com' + +VITE_APP_UPLOAD_API = 'https://prev.ysaix.com:7868/prod-api' + +# 是否在打包时开启压缩,支持 gzip 和 brotli +VITE_BUILD_COMPRESS = gzip + +VITE_APP_RES_FILE_PATH = 'https://prev.ysaix.com:7868/src/assets/textbook/booktxt/' + +VITE_APP_BUILD_BASE_PATH = 'https://prev.ysaix.com:7868/' + +# websocket 地址 +VITE_APP_WS_URL = 'wss://prev.ysaix.com:7868' + +# 是否显示开发工具 +VITE_SHOW_DEV_TOOLS = 'false' diff --git a/electron-builder-yc.yml b/electron-builder-yc.yml new file mode 100644 index 0000000..385b578 --- /dev/null +++ b/electron-builder-yc.yml @@ -0,0 +1,54 @@ +appId: com.electron.app.yc +productName: 文枢课堂 +directories: + output: dist + buildResources: build +win: + executableName: 文枢课堂 + icon: resources/yc-logo.png +files: + - '!**/.vscode/*' + - '!src/*' + - '!electron.vite.config.{js,ts,mjs,cjs}' + - '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}' + - '!{.env,.env.*,.npmrc,pnpm-lock.yaml}' +asarUnpack: + - resources/** +nsis: + oneClick: false + allowToChangeInstallationDirectory: true + artifactName: ${name}-yc-${version}-setup.${ext} + shortcutName: ${productName} + uninstallDisplayName: ${productName} + createDesktopShortcut: always +mac: + entitlementsInherit: build/entitlements.mac.plist + extendInfo: + - NSCameraUsageDescription: Application requests access to the device's camera. + - NSMicrophoneUsageDescription: Application requests access to the device's microphone. + - NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder. + - NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder. + notarize: false +dmg: + artifactName: ${name}-${version}.${ext} +linux: + target: + - AppImage + - snap + - deb + maintainer: electronjs.org + category: Utility +appImage: + artifactName: ${name}-${version}.${ext} +npmRebuild: false +publish: + provider: generic + url: https://prev.ysaix.com:7868/src/assets/smarttalkyc/ +electronDownload: + mirror: https://npmmirror.com/mirrors/electron/ +# 额外依赖打包到输出目录 +extraFiles: + - from: ./node_modules/im_electron_sdk/lib/ + to: ./resources + filter: + - '**/*' diff --git a/electron-builder-yc2.yml b/electron-builder-yc2.yml new file mode 100644 index 0000000..a7bfd2f --- /dev/null +++ b/electron-builder-yc2.yml @@ -0,0 +1,54 @@ +appId: com.electron.app.yc2 +productName: 实训教学 +directories: + output: dist + buildResources: build +win: + executableName: 实训教学 + icon: resources/yc-logo.png +files: + - '!**/.vscode/*' + - '!src/*' + - '!electron.vite.config.{js,ts,mjs,cjs}' + - '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}' + - '!{.env,.env.*,.npmrc,pnpm-lock.yaml}' +asarUnpack: + - resources/** +nsis: + oneClick: false + allowToChangeInstallationDirectory: true + artifactName: ${name}-ycsx-${version}-setup.${ext} + shortcutName: ${productName} + uninstallDisplayName: ${productName} + createDesktopShortcut: always +mac: + entitlementsInherit: build/entitlements.mac.plist + extendInfo: + - NSCameraUsageDescription: Application requests access to the device's camera. + - NSMicrophoneUsageDescription: Application requests access to the device's microphone. + - NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder. + - NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder. + notarize: false +dmg: + artifactName: ${name}-${version}.${ext} +linux: + target: + - AppImage + - snap + - deb + maintainer: electronjs.org + category: Utility +appImage: + artifactName: ${name}-${version}.${ext} +npmRebuild: false +publish: + provider: generic + url: https://prev.ysaix.com:7868/src/assets/smarttalkycsx/ +electronDownload: + mirror: https://npmmirror.com/mirrors/electron/ +# 额外依赖打包到输出目录 +extraFiles: + - from: ./node_modules/im_electron_sdk/lib/ + to: ./resources + filter: + - '**/*' diff --git a/package.json b/package.json index e8adfd8..9c9774e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aix-win-ws", - "version": "2.5.7", + "version": "2.5.8", "description": "", "main": "./out/main/index.js", "author": "上海交大重庆人工智能研究院", @@ -16,6 +16,8 @@ "build:dev": "npm run build && electron-builder --win --config ./electron-builder-test.yml", "build:test": "electron-vite build --mode test && electron-builder --win --config ./electron-builder.yml", "build:prod": "electron-vite build --mode production && electron-builder --win --config ./electron-builder-prod.yml", + "build:yc": "electron-vite build --mode yc && electron-builder --win --config ./electron-builder-yc.yml", + "build:yc2": "electron-vite build --mode yc2 && electron-builder --win --config ./electron-builder-yc2.yml", "build:lt": "electron-vite build --mode lt && electron-builder --win --config ./electron-builder-lt.yml", "build:mac": "electron-vite build --mode production && electron-builder --mac --config ./electron-builder-prod.yml", "build:linux": "npm run build && electron-builder --linux" diff --git a/resources/yc-logo.png b/resources/yc-logo.png new file mode 100644 index 0000000..59db44e Binary files /dev/null and b/resources/yc-logo.png differ diff --git a/src/main/index.js b/src/main/index.js index c223604..f43c571 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -7,6 +7,7 @@ import Logger from './logger' // 日志封装 import chat from './chat' // chat封装 import Store from './store' // Store封装 import updateInit from './update' + // 代理 electron/remote // 第一步:引入remote import remote from '@electron/remote/main' @@ -41,19 +42,19 @@ if(!gotTheLock){ } }) } - +let logoIco = import.meta.env.MODE==='yc'||import.meta.env.MODE==='yc2'?'../../resources/yc-logo.png':'../../resources/logo2.ico' //登录窗口 function createLoginWindow() { if (loginWindow) return loginWindow = new BrowserWindow({ - width: 888, + width: import.meta.env.MODE==='yc'||import.meta.env.MODE==='yc2'?1060:888, height: 520, show: false, frame: false, autoHideMenuBar: true, maximizable: false, resizable: false, - icon: join(__dirname, '../../resources/logo2.ico'), + icon: join(__dirname, logoIco), ...(process.platform === 'linux' ? { icon } : {}), webPreferences: { defaultEncoding: 'utf-8', @@ -95,7 +96,7 @@ function createMainWindow() { frame: false, // 无边框 autoHideMenuBar: true, maximizable: false, - icon: join(__dirname, '../../resources/logo2.ico'), + icon: join(__dirname, logoIco), ...(process.platform === 'linux' ? { icon } : {}), webPreferences: { defaultEncoding: 'utf-8', diff --git a/src/renderer/src/AixPPTist/src/App.vue b/src/renderer/src/AixPPTist/src/App.vue index 74c4b73..7fe9cd8 100644 --- a/src/renderer/src/AixPPTist/src/App.vue +++ b/src/renderer/src/AixPPTist/src/App.vue @@ -74,8 +74,6 @@ const initLoad: Function = () => { !!(opt.ratio??null) && slidesStore.setViewportRatio(opt.ratio)// 有比例配置项 } return PPTApi.getSlideList(resource.id) - // PPTApi.updateWorkList() - // return Promise.resolve() } return Promise.resolve() } diff --git a/src/renderer/src/AixPPTist/src/api/index.ts b/src/renderer/src/AixPPTist/src/api/index.ts index 203ba3e..5e5bcb6 100644 --- a/src/renderer/src/AixPPTist/src/api/index.ts +++ b/src/renderer/src/AixPPTist/src/api/index.ts @@ -50,6 +50,8 @@ export class Utils { }, delay) } } + // 延时 + static sleep = ms => new Promise(resolve => setTimeout(resolve, ms)) } /** ppt相关后端接口处理 */ @@ -59,6 +61,7 @@ export class PPTApi { // 获取所有幻灯片列表 isUpdate为true不更新 static getSlideList(parentid: (Number | String),isUpdate?:Boolean): Promise { + const classcourse = sessionStore.get('curr.classcourse') // 课堂信息 return new Promise(async (resolve, reject) => { const params: object = { parentid, orderByColumn: 'fileidx', isAsc: 'asc', pageSize: 9999 } const res: Result = await API_entpcoursefile.listEntpcoursefileNew(params) @@ -79,12 +82,16 @@ export class PPTApi { // 活动列表处理 // const workList = (res.rows || []).map(o => o.activityContent) const workItem = res.rows ? [...res.rows] : [] - // 写入作业列表数据 - // slidesStore.setWorkList(workList) // 获取所有的pptlist的数据 slidesStore.setWorkItem(workItem) - - this.updateWorkList() + // 没有上课时调用-作业列表 + if(!classcourse) this.updateWorkList() + // 没有上课时调用-批量更新缩略图 + if(!classcourse) { + Utils.sleep(1500).then(() => { + this.batchUpdateThumUrl() + }) + } resolve(true) } else msgUtils.msgError(res.msg || '获取数据失败');resolve(false) }) @@ -232,10 +239,29 @@ export class PPTApi { }) } + // 批量更新缩略图-异步 + static batchUpdateThumUrl() { + return nextTick().then(async () => { + const list = slidesStore.workItem || [] + if (!list.length) return + const upList = [] + for (const [ind,o] of list.entries()) { + const isCreate = !o.fileurl // 是否创建 + if (isCreate) { + const thumUrl = await this.getSlideThumUrl(ind) + upList.push({ id: o.id, fileurl: thumUrl }) + } + } + if (!upList.length) return + // 批量更新 + return await API_entpcoursefile.batchUpdateNew(upList) + }) + } + // thumbnail-slide thumbnail 缩略图 - static getSlideThumUrl(): Promise { + static getSlideThumUrl(index?:number): Promise { return nextTick().then(async() => { - const slideIndex = slidesStore.slideIndex + const slideIndex = index ?? slidesStore.slideIndex const elements = document.querySelectorAll('.thumbnail-slide') if (elements.length && slideIndex >= 0) { const element = elements[slideIndex] diff --git a/src/renderer/src/AixPPTist/src/api/types.ts b/src/renderer/src/AixPPTist/src/api/types.ts index 3678ed4..0beb5ef 100644 --- a/src/renderer/src/AixPPTist/src/api/types.ts +++ b/src/renderer/src/AixPPTist/src/api/types.ts @@ -126,6 +126,8 @@ export class MsgEnum { MSG_homework : 'HOMEWORK', /** @desc: 公屏 - 课堂作业|活动 */ MSG_pushSreen_work : 'pushSreen_work', + /** @desc: 公屏 - 实验 */ + MSG_pushSreen_experiment : 'pushSreen_experiment', /** @desc: 点赞 */ MSG_dz : 'dz', /** @desc: 疑惑 */ diff --git a/src/renderer/src/AixPPTist/src/api/watcher.ts b/src/renderer/src/AixPPTist/src/api/watcher.ts index 34c3294..005aef2 100644 --- a/src/renderer/src/AixPPTist/src/api/watcher.ts +++ b/src/renderer/src/AixPPTist/src/api/watcher.ts @@ -10,6 +10,7 @@ import { MsgEnum } from './types' // 消息枚举 import ChatWs from '@/plugins/socket' // 聊天socket import Classcourse from './classcourse' // 课程相关 import msgUtils from '@/plugins/modal' // 消息工具 +import * as dialogUtils from '@/utils/dialog' // 弹窗-函数 import { Homework } from './index' // api-作业相关 // import emitter from '@/utils/mitt' //mitt 事件总线 import useExecPlay from '../views/Screen/hooks/useExecPlay' // 播放控制 @@ -114,6 +115,10 @@ export default () => { if (!content.id) return Homework.showHomework(content.id) break + case MsgEnum.HEADS.MSG_pushSreen_experiment: // 打开实验: + if (!content.url) return + dialogUtils.openLink(content.url) + break case MsgEnum.HEADS.MSG_closed: // 下课: close() break @@ -137,4 +142,4 @@ export default () => { window.close() // 关闭窗口 }, 1000) } -} +} \ No newline at end of file diff --git a/src/renderer/src/AixPPTist/src/views/Editor/Toolbar/ElementStylePanel/Active/index.vue b/src/renderer/src/AixPPTist/src/views/Editor/Toolbar/ElementStylePanel/Active/index.vue index 0354fba..9f36ccc 100644 --- a/src/renderer/src/AixPPTist/src/views/Editor/Toolbar/ElementStylePanel/Active/index.vue +++ b/src/renderer/src/AixPPTist/src/views/Editor/Toolbar/ElementStylePanel/Active/index.vue @@ -25,6 +25,12 @@
常规作业
+ +
+ +
科学实验
+
+
@@ -157,6 +163,10 @@ const type = ref([ { label: '框架梳理', value: 'primary' + }, + { + label: '科学实验', + value: 'primary' } ]) diff --git a/src/renderer/src/AixPPTist/src/views/Screen/BaseView.vue b/src/renderer/src/AixPPTist/src/views/Screen/BaseView.vue index 8e7acf0..7d24e8c 100644 --- a/src/renderer/src/AixPPTist/src/views/Screen/BaseView.vue +++ b/src/renderer/src/AixPPTist/src/views/Screen/BaseView.vue @@ -36,8 +36,8 @@
幻灯片 {{slideIndex + 1}} / {{slides.length}}
@@ -50,6 +50,10 @@
+
+ + +
@@ -71,6 +75,7 @@ import WritingBoardTool from './WritingBoardTool.vue' import CountdownTimer from './CountdownTimer.vue' import emitter from '@/utils/mitt'; import Chat from '../../api/chat' // 聊天 +import { CircleDoubleDown, CircleDoubleUp } from '@icon-park/vue-next' // icon-park 图标库 const props = defineProps<{ changeViewMode: (mode: 'base' | 'presenter') => void @@ -103,12 +108,15 @@ const { exitScreening } = useScreening() const { fullscreenState, manualExitFullscreen } = useFullscreen() const chat:any = Chat() // 聊天室 +const screenStore =useScreenStore() const rightToolsVisible = ref(false) const writingBoardToolVisible = ref(false) const timerlVisible = ref(false) const slideThumbnailModelVisible = ref(false) const laserPen = ref(false) -const screenStore =useScreenStore() +const timer = ref(0) // 记录操作时间 +const iconHide = ref(false) // 工具栏图标是否显示 +const timerId = ref(null) // 定时器id const contextmenus = (): ContextmenuItem[] => { return [ { @@ -191,6 +199,30 @@ const contextmenus = (): ContextmenuItem[] => { ] } +const toolTrigger = (type:string) => { + const curT = Date.now() + if (curT - timer.value < 200) return + iconHide.value = false // 显示图标按钮 + if (timerId.value) clearTimeout(timerId.value) // 清除定时器 + switch (type) { + case 'icon': // 点击图标 + timer.value = curT + rightToolsVisible.value = !rightToolsVisible.value + break + case 'enter': // 移入 + timer.value = curT + rightToolsVisible.value = true + break + case 'leave': // 移出 + rightToolsVisible.value = false + break + default: + break + } + timerId.value = setTimeout(() => { // 定时器 + iconHide.value = true // 隐藏图标按钮 + }, 2000) +} // 下课 const exitCourse = async () => { // console.log('下课', chat) @@ -253,6 +285,18 @@ const exitCourse = async () => { top: -66px; } + .tools-icon{ + position: absolute; + right: 8px; + top: -35px; + z-index: 1; + cursor: pointer; + transition: opacity $transitionDelay; + &.opacity{ + opacity: .35; + } + } + .content { width: 100%; height: 100%; diff --git a/src/renderer/src/api/aiGeneratedImage/index.js b/src/renderer/src/api/aiGeneratedImage/index.js index 9939c5d..eeb4211 100644 --- a/src/renderer/src/api/aiGeneratedImage/index.js +++ b/src/renderer/src/api/aiGeneratedImage/index.js @@ -2,6 +2,8 @@ import axios from 'axios' import request from '@/utils/request' import { getToken } from "@/utils/auth"; +let rootPath = import.meta.env.VITE_APP_ENV === 'production' ? 'https://ai.ysaix.com:7864' : '' + // 文生图片 export function convertTextToPicture(data) { return axios({ @@ -42,7 +44,7 @@ export function getPicture(data) { // 大模型对话生成prompt模板 export function chattoprompt(dataset_id,prompt) { return axios({ - url: '/api/v1/parse/docs', + url: rootPath + '/api/v1/parse/docs', method: 'post', headers: { 'Authorization': 'Bearer ragflow-IwMDI1MGU2YTU3NjExZWZiNWEzMDI0Mm', @@ -68,7 +70,7 @@ export function textSensitiveWord(data) { // 图片上传资源库 export function uploadPicture(data) { return axios({ - url: '/dev-api/smarttalk/file/upload', + url: import.meta.env.VITE_APP_BASE_API + '/smarttalk/file/upload', method: 'post', headers: { 'Accept': '*/*', diff --git a/src/renderer/src/assets/images/login/yc-logo.png b/src/renderer/src/assets/images/login/yc-logo.png new file mode 100644 index 0000000..59db44e Binary files /dev/null and b/src/renderer/src/assets/images/login/yc-logo.png differ diff --git a/src/renderer/src/assets/images/login/ycpeitu.png b/src/renderer/src/assets/images/login/ycpeitu.png new file mode 100644 index 0000000..433a296 Binary files /dev/null and b/src/renderer/src/assets/images/login/ycpeitu.png differ diff --git a/src/renderer/src/assets/images/login/ycpeitu2.jpg b/src/renderer/src/assets/images/login/ycpeitu2.jpg new file mode 100644 index 0000000..4cc2f71 Binary files /dev/null and b/src/renderer/src/assets/images/login/ycpeitu2.jpg differ diff --git a/src/renderer/src/components/template-study/container/right.vue b/src/renderer/src/components/template-study/container/right.vue index 2f4b93c..9343418 100644 --- a/src/renderer/src/components/template-study/container/right.vue +++ b/src/renderer/src/components/template-study/container/right.vue @@ -104,7 +104,7 @@ import { cloneDeep } from 'lodash' const props = defineProps(['type']) const { user } = useUserStore() -const curMode = ref(1) +const curMode = ref(2) const modeOptions = ref([ { label: '教学大模型', @@ -205,7 +205,7 @@ const scrollToBottom = (height, index) => { let listDom = listRef.value.children if (index == 0) { - // 220 去掉头部 + // 220 去掉头部 let screenHeight = window.innerHeight - 220 if (height > screenHeight) { listRef.value.scrollTop = (height - screenHeight + 50) @@ -240,7 +240,7 @@ const changeTemplate = (val) => { const removeItem = async (item, isChild) => { /** * item: 当前操作的模板 - * isChild: 子模板中的移除为 true + * isChild: 子模板中的移除为 true */ if (item.ex3 != '1') { ElMessageBox.confirm( @@ -320,7 +320,7 @@ const againResult = async (index, item) => { str = str.replace('{模板内容}',item.prompt) params.prompt = str params.template = item.prompt - + let data = null; // 教学大模型 if (curMode.value == 1) { @@ -606,4 +606,4 @@ onUnmounted(() => { width: 110px !important; min-width: 110px !important; } - \ No newline at end of file + diff --git a/src/renderer/src/components/window-tools/index.vue b/src/renderer/src/components/window-tools/index.vue index 2e40c52..b6b15f4 100644 --- a/src/renderer/src/components/window-tools/index.vue +++ b/src/renderer/src/components/window-tools/index.vue @@ -38,6 +38,7 @@ const closeWindow = () => { ElMessageBox.confirm('确认退出系统吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', + customClass: 'login-close-tool', type: 'warning' }).then(() => { userStore.logOut().then(() => { @@ -54,7 +55,11 @@ onMounted(() =>{ }) - + \ No newline at end of file + diff --git a/src/renderer/src/hooks/useClassTask.js b/src/renderer/src/hooks/useClassTask.js index 7e58c45..934caf6 100644 --- a/src/renderer/src/hooks/useClassTask.js +++ b/src/renderer/src/hooks/useClassTask.js @@ -58,7 +58,7 @@ export const editListItem = (row, courseObj) => { if (row.worktype == '框架梳理') { - // 框架梳理对应只有一个内容 + // 框架梳理对应只有一个内容 getEvaluationclue(listCourseWork[0].id).then(res => { if ( res.data==null || res.data==undefined ) { return ; @@ -117,6 +117,8 @@ export const editListItem = (row, courseObj) => { classtaskObj.fileHomeworkList = JSON.parse(row.workcodes); // // console.log('科学实验', classtaskObj); + // 更新默认的科学实验( 学段 学科 以及实验科目) + console.log('科学实验', classtaskObj); return resolve(classtaskObj); } } diff --git a/src/renderer/src/hooks/useGetHomework.js b/src/renderer/src/hooks/useGetHomework.js index e07a2de..0f78590 100644 --- a/src/renderer/src/hooks/useGetHomework.js +++ b/src/renderer/src/hooks/useGetHomework.js @@ -94,6 +94,8 @@ const getHomeWorkList = async () => { res.rows[i].workclass = 'info'; } else if (res.rows[i].worktype == '习题训练') { res.rows[i].workclass = 'danger'; + } else if (res.rows[i].worktype == '科学实验') { + res.rows[i].workclass = 'danger'; } else { res.rows[i].workclass = 'primary'; } diff --git a/src/renderer/src/plugins/imChat/msgEnum.js b/src/renderer/src/plugins/imChat/msgEnum.js index a83fed7..42458a2 100644 --- a/src/renderer/src/plugins/imChat/msgEnum.js +++ b/src/renderer/src/plugins/imChat/msgEnum.js @@ -100,6 +100,8 @@ export class MsgEnum { MSG_homework : 'HOMEWORK', /** @desc: 公屏 - 课堂作业|活动 */ MSG_pushSreen_work : 'pushSreen_work', + /** @desc: 公屏 - 实验 */ + MSG_pushSreen_experiment : 'pushSreen_experiment', /** @desc: 点赞 */ MSG_dz : 'dz', /** @desc: 疑惑 */ diff --git a/src/renderer/src/store/modules/classTask.js b/src/renderer/src/store/modules/classTask.js index 05a9491..e93be20 100644 --- a/src/renderer/src/store/modules/classTask.js +++ b/src/renderer/src/store/modules/classTask.js @@ -5,6 +5,11 @@ import { JYApiListCT, JYApiListOriginYear, JYApiListSO} from "@/utils/examQuesti const useClassTaskStore = defineStore('classTask',{ state: () => ({ + experimentObj:{ + edustage: '小学', // 教育阶段 + edusubject: '', // 学科 + experimentList: [], // 实验科目列表 + }, isOpenQuestUploadView: false, // 是否打开习题上传的页面 classListIds: [], entpCourseWorkTypeList: [ diff --git a/src/renderer/src/utils/comm.js b/src/renderer/src/utils/comm.js index b7d3035..1f7aa7f 100644 --- a/src/renderer/src/utils/comm.js +++ b/src/renderer/src/utils/comm.js @@ -49,10 +49,10 @@ export function blobToFile(blob, fileName, contentType) { /** * @description 计算两点直线距离 (获取直径) * (欧几里得距离公式): [ \text{distance} = \sqrt{(x2 - x1)^2 + (y2 - y1)^2} ] - * @param {*} x1 - * @param {*} y1 - * @param {*} x2 - * @param {*} y2 + * @param {*} x1 + * @param {*} y1 + * @param {*} x2 + * @param {*} y2 */ export function getDistance(x1,y1,x2,y2) { return Math.sqrt(Math.pow((x2 - x1), 2) + Math.pow((y2 - y1), 2)) @@ -62,10 +62,10 @@ export function getRadius(x1,y1,x2,y2) { return getDistance(x1,y1,x2,y2) / 2 } /** * 计算某个值在总数中所占的百分比。 - * + * * 此函数用于根据给定的值和总数,计算该值占总数的百分比。它还支持指定百分比的小数位数。 * 如果计算结果小于0,则返回0;如果大于100,则返回100,以确保百分比的合理范围。 - * + * * @param {number} v - 待计算的值。 * @param {number} total - 总数。 * @param {number} [step=2] - 百分比的小数位数,默认为2。 @@ -76,7 +76,7 @@ export function getPercent(v, total, step=2) { !total && (total = 1) // 计算百分比,保留指定的小数位,并转换为数字类型 let res = (v / total * 100).toFixed(step)-0 - + // 确保百分比在0到100之间 return res < 0 ? 0 : res > 100 ? 100 : res } @@ -89,7 +89,7 @@ export function getPercent(v, total, step=2) { * @param {*} start 前面保留几位 默认 3位 * @param {*} end 后面保留几位 默认 3位 * @param {*} rstr 替换字符 默认 **** - * @returns + * @returns */ export function phoneHideFormat(phone, start = 3, end = 4, rstr = '****') { // const reg = /^(\d{3})\d*(\d{4})$/ @@ -101,8 +101,8 @@ export function phoneHideFormat(phone, start = 3, end = 4, rstr = '****') { // ============= 习题工具--相关 =================== /** * @description 将字符串转换为数组 - * @param {*} str - * @returns + * @param {*} str + * @returns */ export function quizStrToList(str = '') { if (!str) return [] @@ -175,8 +175,8 @@ export const validateUrl = (url) => { /** * @description 时间 秒 转化 时分秒 - * @param {*} seconds - * @returns + * @param {*} seconds + * @returns */ export function formatTime(seconds) { seconds = parseInt(seconds) // 转换整数 @@ -188,9 +188,9 @@ export function formatTime(seconds) { /** * @description 时间格式化 - * @param {*} time - * @param {*} fmt - * @returns + * @param {*} time + * @param {*} fmt + * @returns */ export function formatDate(time, fmt = 'yyyy-MM-dd') { let date @@ -300,7 +300,7 @@ export function getDateStr1(num, fmt = 'yyyy-MM-dd hh:mm:ss') { } /** * 获取当前 0:0:0:0 时间 - * @param {*} [fmt] 格式 'yyyy-MM-dd hh:mm:ss' + * @param {*} [fmt] 格式 'yyyy-MM-dd hh:mm:ss' */ export function getDateNow(fmt) { const date = new Date() @@ -339,9 +339,9 @@ export function timeToStr(time,str = '时分秒', isPad = false) { * debounce(() => { console.log('Input event handled'); }, 300); - * @param {*} func - * @param {*} wait - * @returns + * @param {*} func + * @param {*} wait + * @returns */ export function debounce(func, wait) { let timeout; @@ -358,9 +358,9 @@ export function debounce(func, wait) { * throttle(() => { console.log('Scroll event handled'); }, 300); - * @param {*} func - * @param {*} wait - * @returns + * @param {*} func + * @param {*} wait + * @returns */ export function throttle(func, wait) { let lastTime = 0; @@ -376,7 +376,7 @@ export function throttle(func, wait) { } /** - * + * * 大模型对话dataset_id */ export const dataSetJson = { @@ -403,5 +403,11 @@ export const dataSetJson = { "教材-高中-数学": "e03aa4fe9fd011ef91270242ac140006", "教材-高中-地理": "270516829fd111efb13c0242ac140006", "教材-高中-政治": "a2f0b247b85d11ef84290242ac140005", + "课标-小学-科学": "935cfec8bf6a11ef98950242ac140006", + "课标-小学-数学": "3c4e298fbf7911ef8e8b0242ac140002", + "课标-小学-语文": "f76f1aa5bf7111ef90c80242ac140002", + "教材-小学-科学": "935cfec8bf6a11ef98950242ac140006", + "教材-小学-数学": "3c4e298fbf7911ef8e8b0242ac140002", + "教材-小学-语文": "f76f1aa5bf7111ef90c80242ac140002", "鉴权": "ragflow-IwMDI1MGU2YTU3NjExZWZiNWEzMDI0Mm" -} \ No newline at end of file +} diff --git a/src/renderer/src/utils/dialog.js b/src/renderer/src/utils/dialog.js new file mode 100644 index 0000000..66b41d3 --- /dev/null +++ b/src/renderer/src/utils/dialog.js @@ -0,0 +1,49 @@ +/** + * 弹窗-函数 + */ +import { h, render } from 'vue' +import { ElDialog } from 'element-plus' + +// 打开弹窗-函数 +export const openDialog = (option, content) => { + let vNode + const body = document.body + const dOpts = { + modelValue: true, + width: 800, + height: 600, + title: '添加-超连接', + draggable: true, + 'onUpdate:modelValue': val => { + if (vNode && !val) render(null, body) + }, + ...option + } + vNode = h(ElDialog, dOpts, { + default: typeof content == 'function' ? content(h) : content + }) + render(vNode, body) +} + +// 打开链接 +export const openLink = (option, title) => { + // https://phet.colorado.edu/sims/html/number-play/latest/number-play_zh_CN.html + const isStr = typeof option == 'string' + const opt = isStr ? {} : option + const url = isStr ? option : option?.url || option?.src || option?.href + const titleNew = isStr? title||'实验室' : option?.title || '添加-超连接' + openDialog({ + title: titleNew, + ...opt + }, (h) => { + return h('iframe', { + src: url, + width: '100%', + style: { + height: 'calc(80vh - 75px)', + }, + scrolling: 'no', + frameborder: '0', + }) + }) +} \ No newline at end of file diff --git a/src/renderer/src/utils/talkFile/index.js b/src/renderer/src/utils/talkFile/index.js index ae5dfbb..fa56bb2 100644 --- a/src/renderer/src/utils/talkFile/index.js +++ b/src/renderer/src/utils/talkFile/index.js @@ -9,7 +9,7 @@ export const asyncLocalFile = (item) => { if (isAsync === true) { item.async = 'on' if (type === 'down') { - console.log(item) + // console.log(item) ipcRenderer.send('download-file-default', { url: item.fileFullPath, fileName: item.fileNewName diff --git a/src/renderer/src/utils/tool.js b/src/renderer/src/utils/tool.js index 1dbc2be..a83cbd1 100644 --- a/src/renderer/src/utils/tool.js +++ b/src/renderer/src/utils/tool.js @@ -248,10 +248,11 @@ export function toolWindow(type, {url, isConsole, isWeb=true, option={}}) { const devUrl = `${BaseUrl}${url}` const buildUrl = path.join(__dirname, 'index.html') const urlAll = isDev ? devUrl : buildUrl + let logoIco = import.meta.env.MODE==='yc'||import.meta.env.MODE==='yc2'?'/resources/yc-logo.png':'/resources/logo2.ico' return new Promise(async(resolve) => { const config = { width, height, - icon: path.join(appPath, '/resources/logo2.ico'), + icon: path.join(appPath, logoIco), webPreferences: { preload: path.join(API.preloadPath, '/index.js'), sandbox: false, diff --git a/src/renderer/src/views/classTask/container/classTask/item-dialog-score.vue b/src/renderer/src/views/classTask/container/classTask/item-dialog-score.vue index a952a0d..ae02b0e 100644 --- a/src/renderer/src/views/classTask/container/classTask/item-dialog-score.vue +++ b/src/renderer/src/views/classTask/container/classTask/item-dialog-score.vue @@ -709,29 +709,33 @@ const acceptParams = async (params) => { } else { // 学生回答 if (params.studentObj.worktype == '常规作业' || params.studentObj.worktype == '科学实验') { - try { - // 老师布置的附件 datacontent TODO:常规作业、其他类型还未接入 - const res = await getClassworkdata(params.studentObj.id); - if(res.data.datacontent != ''){ - const teachWorkFileList = JSON.parse(res.data.datacontent); - console.log(teachWorkFileList, '老师filelist-------------') - teachWorkFileList && - teachWorkFileList.forEach((item) => { - if ( - item.name.indexOf('jpg') > -1 || - item.name.indexOf('jpeg') > -1 || - item.name.indexOf('png') > -1 - ) { - teachImageList.value.push(item) - } else { - teachFileList.value.push(item) - } - }) - teacherFeedContentList.value.push(teachWorkFileList) - } + if(params.studentObj.worktype == '常规作业'){ + try { + // 老师布置的附件 datacontent TODO:常规作业、其他类型还未接入 + const res = await getClassworkdata(params.studentObj.id); + if(res.data.datacontent != ''){ + const teachWorkFileList = JSON.parse(res.data.datacontent); + console.log(teachWorkFileList, '老师filelist-------------') + teachWorkFileList && + teachWorkFileList.forEach((item) => { + if ( + item.name.indexOf('jpg') > -1 || + item.name.indexOf('jpeg') > -1 || + item.name.indexOf('png') > -1 + ) { + teachImageList.value.push(item) + } else { + teachFileList.value.push(item) + } + }) + teacherFeedContentList.value.push(teachWorkFileList) + } - } catch (error) { - console.error('Invalid JSON:', error) + } catch (error) { + console.error('Invalid JSON:', error) + } + }else{ + // TODO 科学实验 老师布置的活动 暂时不在批改中显示 2024-12-20 } params.studentQuizAllList.forEach((item) => { diff --git a/src/renderer/src/views/classTask/newClassTaskAssign/experimentQuestion/components/experimentList.vue b/src/renderer/src/views/classTask/newClassTaskAssign/experimentQuestion/components/experimentList.vue index 8c0505f..9755859 100644 --- a/src/renderer/src/views/classTask/newClassTaskAssign/experimentQuestion/components/experimentList.vue +++ b/src/renderer/src/views/classTask/newClassTaskAssign/experimentQuestion/components/experimentList.vue @@ -8,7 +8,7 @@ @change="onSelectOption" > { const onSelectOption = (option) => { console.log(option,'选择的实验课-------') - emit('selectItem', props.list.filter(item => item.label === option)[0]) + emit('selectItem', classTaskStore.experimentList.filter(item => item.label === option)[0]) } diff --git a/src/renderer/src/views/classTask/newClassTaskAssign/experimentQuestion/components/selectClass.vue b/src/renderer/src/views/classTask/newClassTaskAssign/experimentQuestion/components/selectClass.vue index 87ce096..0837584 100644 --- a/src/renderer/src/views/classTask/newClassTaskAssign/experimentQuestion/components/selectClass.vue +++ b/src/renderer/src/views/classTask/newClassTaskAssign/experimentQuestion/components/selectClass.vue @@ -3,7 +3,7 @@
- {{ userStore.edustage }} + {{ useClassTaskStore().experimentObj.edustage }} @@ -20,14 +20,14 @@
- {{ userStore.edusubject }} + {{ useClassTaskStore().experimentObj.edusubject }}