diff --git a/electron-builder.yml b/electron-builder.yml index 46e484d..4b26cd1 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -16,7 +16,7 @@ win: nsis: oneClick: false allowToChangeInstallationDirectory: true - artifactName: ${name}-${version}-setup.${ext} + artifactName: ${name}-${version}-test.${ext} shortcutName: ${productName} uninstallDisplayName: ${productName} createDesktopShortcut: always diff --git a/electron.vite.config.mjs b/electron.vite.config.mjs index 01bf054..8e66b38 100644 --- a/electron.vite.config.mjs +++ b/electron.vite.config.mjs @@ -43,6 +43,11 @@ export default defineConfig({ changeOrigin: true, rewrite: (p) => p.replace(/^\/baidubce/, '') }, + '/parth': { + target: 'https://zwapi.xfyun.cn', // 第三方API的地址 + changeOrigin: true, // 改变请求的起源 + rewrite: (path) => path.replace(/^\/parth/, '') // 重写路径 + }, }, }, plugins: [vue(), WindiCSS()], diff --git a/package.json b/package.json index b544cec..75da1f6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "aix-win", - "version": "2.1.5", + "version": "2.1.12", "description": "", "main": "./out/main/index.js", "author": "example.com", diff --git a/src/main/file.js b/src/main/file.js index 58ee5ec..3de3333 100644 --- a/src/main/file.js +++ b/src/main/file.js @@ -243,6 +243,81 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) { }) }) + /*创建新的ppt文件*/ + ipcMain.on('creat-ai-file-default', (e, { name, url, uploadData, cookie }) => { + createFolder('tempFile').then(async () => { + let lastname = decodeURIComponent(url); + name = lastname.substring(lastname.lastIndexOf("/")+1) + let path = appTempFilePath + name.replace(/[\\/:*?"<>|]/, '') + let {type,item} = await downloadFiles(url,name) + if (type==="成功") { + let fileType = 'application/vnd.openxmlformats-officedocument.presentationml.presentation' + let formData = new FormData() + for (let key in uploadData) { + if (Object.prototype.hasOwnProperty.call(uploadData, key)) { + // 检查是否是对象自身的属性 + formData.append(key, uploadData[key]) + } + } + formData.append('fileFlag', '课件') + uploadFileByFS({ + url: uploadUrl, + path, + name, + cookie, + fileType, + formData, + success: (response) => { + e.reply('creat-ai-file-default-reply', response.data) + console.log('File uploaded successfully:', response.data) + }, + error: (err) => { + console.error('Error uploading file:', err) + } + }) + }else { + e.reply('creat-ai-file-default-reply', type) + } + }) + }) + + function downloadFiles(url,fileName) { + console.log(url,fileName) + return new Promise((resolve, reject)=>{ + const browserWindow = BrowserWindow.getFocusedWindow() + const id = manager.download({ + window: browserWindow, + url: url, + saveAsFilename: fileName, + directory: appTempFilePath, + callbacks: { + onDownloadStarted: async ({ id, item, webContents }) => { + // Do something with the download id + }, + onDownloadProgress: async ({ id, item, percentCompleted }) => { + // console.log(percentCompleted) + }, + onDownloadCompleted: async ({ id, item }) => { + console.log('完成') + resolve({type:"成功",item}) + }, + onDownloadCancelled: async () => { + console.log("取消") + reject({type:"取消了下载"}) + }, + onDownloadInterrupted: async () => { + console.log('中断') + reject({type:"下载被中断"}) + }, + onError: (err, data) => { + console.log(err.toString()) + reject({type:"下载出错",err}) + } + } + }) + }) + } + //获取应用文件目录 ipcMain.on('get-root-file-path', (e) => { e.reply('get-root-file-path-reply', appRootFilePath) diff --git a/src/renderer/src/api/classTask/index.js b/src/renderer/src/api/classTask/index.js index 56f662d..bf03614 100644 --- a/src/renderer/src/api/classTask/index.js +++ b/src/renderer/src/api/classTask/index.js @@ -18,6 +18,14 @@ export function listClassworkdataByDeadDate(query) { }) } +// 查询classworkdata详细 +export function getClassworkdata(id) { + return request({ + url: '/education/classworkdata/' + id, + method: 'get' + }) +} + // 查询classworkdata列表 班级作业列表 export function listClassworkdata(query) { return request({ diff --git a/src/renderer/src/components/set-homework/index.vue b/src/renderer/src/components/set-homework/index.vue index 380e381..17127b8 100644 --- a/src/renderer/src/components/set-homework/index.vue +++ b/src/renderer/src/components/set-homework/index.vue @@ -55,14 +55,15 @@ import { saveByClassWorkArray } from '@/api/teaching/classwork' import useUserStore from '@/store/modules/user' import { getCurrentTime } from '@/utils/date' import { uniqBy, groupBy } from 'lodash' +import { sessionStore } from '@/utils/store' const model = defineModel({ type: Boolean, default: false }) const props = defineProps({ entpcourseid: { default: '' }, - row: { - default: '' + rows: { + default: [] }, title: { type: String, @@ -211,6 +212,8 @@ const delStudent = (index) => { const onSubmit = (formEl) => { if (!formEl) return + // 课堂id + const classRoomId = sessionStore.get('curClassRoom.id') formEl.validate((valid) => { if (valid) { /** @@ -222,31 +225,34 @@ const onSubmit = (formEl) => { let ary = [] for (const value in gradeObj) { //这些参数 参照AIx web端 作业推送 - let obj = { - id: 0, - parentid: props.row.id, - classid: value, - classcourseid: 0, - entpcourseid: props.entpcourseid, - studentlist: JSON.stringify(gradeObj[value]), - feedback: form.feedback, - workkey: '', - timelength: form.timelength, - weights: 1, - deaddate: form.deaddate, - workdate: getCurrentTime('YYYY-MM-DD'), - uniquekey: props.row.uniquekey, - entpcourseworklist: '[' + props.row.entpcourseworklist + ']', - needMsgNotifine: 'false', - msgkey: 'newclasswork', - title: '作业任务', - msgcontent: '', - teachername: userInfo.nickName, - unixstamp: new Date().getTime(), - worktype: props.row.worktype, - status: '1' + for (var i = 0; i < props.rows.length; i++) { + let obj = { + id: 0, + parentid: props.rows[i].id, + classid: value, + classcourseid: 0, // 课堂id-ppt为字符串不能使用 + classReservId: classRoomId, // 课堂id + entpcourseid: props.entpcourseid, + studentlist: JSON.stringify(gradeObj[value]), + feedback: form.feedback, + workkey: '', + timelength: form.timelength, + weights: 1, + deaddate: form.deaddate, + workdate: getCurrentTime('YYYY-MM-DD'), + uniquekey: props.rows[i].uniquekey, + entpcourseworklist: '[' + props.rows[i].entpcourseworklist + ']', + needMsgNotifine: 'false', + msgkey: 'newclasswork', + title: '作业任务', + msgcontent: '', + teachername: userInfo.nickName, + unixstamp: new Date().getTime(), + worktype: props.rows[i].worktype, + status: '1' + } + ary.push(obj) } - ary.push(obj) } setLoading.value = true saveByClassWorkArray({ @@ -280,8 +286,9 @@ const cloneDialog = (formEl) => { } onMounted(() => { - // 默认当前 - form.deaddate = getCurrentTime('YYYY-MM-DD HH:mm') + // 默认当前 改为 延后3小时后截止 + // form.deaddate = getCurrentTime('YYYY-MM-DD HH:mm') + form.deaddate = `${getCurrentTime('YYYY-MM-DD')} ${getCurrentTime('HH+3')}:${getCurrentTime('mm')}`; }) diff --git a/src/renderer/src/hooks/useClassTask.js b/src/renderer/src/hooks/useClassTask.js new file mode 100644 index 0000000..85966bb --- /dev/null +++ b/src/renderer/src/hooks/useClassTask.js @@ -0,0 +1,117 @@ +import { listEntpcoursework,getEvaluationclue } from '@/api/classTask'; +import { processList } from '@/hooks/useProcessList'; + +const isJson = (str) => { + if (typeof str == 'string') { + try { + let obj = JSON.parse(str) + if (typeof obj == 'object' && obj) { + return true + } else { + return false + } + } catch (e) { + return false + } + } +} + + +/** + * @description 编辑作业配置 + * @param {*} row + */ +export const editListItem = (row, courseObj) => { + return new Promise((resolve, reject) => { + // 作业内容编辑-跳转到设计界面-传参 + let classtaskObj = { + id: '', // + bookName: '', // 课程名称 + uniquekey: '', // 设计中的标题 + title: '', // 设计中的说明 + worktype: '', // 设计中的作业类型 + quizlist: [], // 设计中的试题列表 + chooseWorkLists: [],// 设计中的框架梳理list + fileHomeworkList: [],// 设计中的常规作业list + whiteboardObj: '',// 设计中的课堂展示对象 + }; + console.log('编辑的行', row); + + //重新更新[新任务]中右侧列表数据 + var listCourseWork = []; + for (var i=0; i < row.entpcourseworklistarray.length; i++) { + listCourseWork.push(row.entpcourseworklistarray[i]); + } + + if (listCourseWork.length > 0) { + classtaskObj.id= row.id; // + classtaskObj.bookObj = courseObj; // 教材对象 + classtaskObj.bookName = row.evaltitle? row.evalparenttitle? row.evalparenttitle+'/'+row.evaltitle : row.evaltitle: row.evalparenttitle// 课程名称:单元/章节: 单元 + classtaskObj.uniquekey= row.uniquekey; // 设计中的标题 + classtaskObj.title= row.title; // 设计中的说明 + classtaskObj.worktype= row.worktype; // 设计中的作业类型 + classtaskObj.quizlist= []; // 设计中的试题列表 + classtaskObj.chooseWorkLists = []; //设计中的 框架梳理list + classtaskObj.fileHomeworkList = []; //设计中的 常规作业list + classtaskObj.whiteboardObj = ''; //设计中的 课堂展示对象 + + + if (row.worktype == '框架梳理') { + // 框架梳理对应只有一个内容 + getEvaluationclue(listCourseWork[0].id).then(res => { + if ( res.data==null || res.data==undefined ) { + return ; + } + res.data.worktype = '框架梳理'; + res.data.score = listCourseWork[0].score; + classtaskObj.chooseWorkLists.push(res.data); + // + // console.log('框架梳理', classtaskObj); + return resolve(classtaskObj); + }); + } + else if (row.worktype == '习题训练') { + const ids = listCourseWork.map(item => item.id).join(","); + listEntpcoursework({ids: ids, pageSize: 50}).then(idres => { + // for (var i=0; i]+>/g, ''); + // } + // 格式化试题 + if(idres.rows&&idres.rows.length > 0){ + processList(idres.rows); + //重新将task中的分值更新 + row.entpcourseworklistarray.forEach(item => { + const quizItem = idres.rows.find(quiz => quiz.id === item.id); + if (quizItem) { + quizItem.score = item.score; + quizItem.scoreOrigin = item.score; + } + }); + + classtaskObj.quizlist = idres.rows; + // + // console.log('习题训练', classtaskObj); + return resolve(classtaskObj); + } + }) + } + else if (row.worktype == '课堂展示') { + console.log('row.课堂展示', row.workcodes); + const workcodes = JSON.parse(row.workcodes); + classtaskObj.whiteboardObj = JSON.stringify(workcodes.json); + // + // console.log('课堂展示', classtaskObj); + return resolve(classtaskObj); + } + else if (row.worktype == '常规作业') { + if(isJson(row.workcodes)){ + classtaskObj.fileHomeworkList = JSON.parse(row.workcodes); + // + // console.log('常规作业', classtaskObj); + return resolve(classtaskObj); + } + } + } + }); +} + diff --git a/src/renderer/src/hooks/useGetHomework.js b/src/renderer/src/hooks/useGetHomework.js index c122d9f..e07a2de 100644 --- a/src/renderer/src/hooks/useGetHomework.js +++ b/src/renderer/src/hooks/useGetHomework.js @@ -71,6 +71,7 @@ const getHomeWorkList = async () => { return await homeworklist({ entpcourseid: chapterId, edituserid: userStore.user.userId, + orderby: "timestamp DESC", pageSize: 100, status: '10' }).then((res) => { @@ -79,7 +80,25 @@ const getHomeWorkList = async () => { for (var i = 0; i < res.rows.length; i++) { res.rows[i].taskconfig = [] - // 找child + // 处理任务类型的UI + // if (res.rows[i].worktype == '学习目标定位') { + // res.rows[i].workclass = 'success'; + // res.rows[i].workcodesList = JSON.parse(res.rows[i].workcodes); + // } else + // 课标研读 目标设定 教材研读 框架梳理 学科定位 TODO 后续接入在添加 + if (res.rows[i].worktype == '课堂展示') { + res.rows[i].workclass = 'primary'; + } else if (res.rows[i].worktype == '框架梳理') { + res.rows[i].workclass = 'warning'; + } else if (res.rows[i].worktype == '常规作业') { + res.rows[i].workclass = 'info'; + } else if (res.rows[i].worktype == '习题训练') { + res.rows[i].workclass = 'danger'; + } else { + res.rows[i].workclass = 'primary'; + } + + // 找child for (var j = 0; j < res.rows.length; j++) { if (res.rows[j].parentid == res.rows[i].id) { var ss = [] diff --git a/src/renderer/src/layout/components/Header.vue b/src/renderer/src/layout/components/Header.vue index 2d813af..6b3e875 100644 --- a/src/renderer/src/layout/components/Header.vue +++ b/src/renderer/src/layout/components/Header.vue @@ -10,12 +10,12 @@
  • - - + + - +
    {{ menu.name }}
  • @@ -80,6 +80,8 @@ import { updateUserInfo } from '@/api/system/user' import logoIco from '@/assets/images/logo.png' import { listEvaluation } from '@/api/classManage/index' import { sessionStore } from '@/utils/store' +// import Chat from '@/utils/chat' // im 登录初始化 +// if (!Chat.imChat) Chat.init() let homeTitle = ref(import.meta.env.VITE_APP_TITLE) const { ipcRenderer } = window.electron || {} @@ -143,6 +145,7 @@ function handleCommand(command) { break case 'logout': logout() + // Chat?.logout() // im 退出登录 break default: break @@ -158,7 +161,9 @@ function logout() { cancelButtonText: '取消', type: 'warning' }) - .then(() => { + .then(async () => { + const Chat = (await import('@/utils/chat')).default + if (!!Chat.imChat) Chat.logout() userStore .logOut() .then(() => { @@ -169,8 +174,7 @@ function logout() { // router.replace('/login') ipcRenderer && ipcRenderer.send('openLoginWindow') }) - }) - .catch(() => { }) + }).catch(()=>{}) } const emits = defineEmits(['setLayout']) @@ -180,10 +184,10 @@ function setLayout() { // 切换学科 const changeSubject = async (command) =>{ let sessionSubject = { - bookList: null, - curBook: null, - curNode: null, - defaultExpandedKeys: [], + bookList: null, + curBook: null, + curNode: null, + defaultExpandedKeys: [], subjectTree: [] } sessionStore.set( 'subject', sessionSubject) diff --git a/src/renderer/src/layout/index.vue b/src/renderer/src/layout/index.vue index 09b8df4..c09647d 100644 --- a/src/renderer/src/layout/index.vue +++ b/src/renderer/src/layout/index.vue @@ -19,8 +19,11 @@ import AppMain from './components/AppMain.vue' import Uploader from './components/Uploader.vue' import AiChart from '@/components/ai-chart/index.vue' import uploaderState from '@/store/modules/uploader' +// import Chat from '@/utils/chat' let uploaderStore = ref(uploaderState()) +// window.test = Chat +// Chat.init() diff --git a/src/renderer/src/plugins/imChat/index.js b/src/renderer/src/plugins/imChat/index.js index 6cf8934..bb2250b 100644 --- a/src/renderer/src/plugins/imChat/index.js +++ b/src/renderer/src/plugins/imChat/index.js @@ -70,7 +70,10 @@ export class ImChat { // 日志监听 this.timChat.TIMSetLogCallback({ callback: data => { - this.setConsole('%cchat-log ', data[1]) + const [type, log] = data + if (type == log_level) { // 打印对应日志 + this.setConsole('%cchat-log ', log) + } }, user_data: '' }) @@ -86,7 +89,7 @@ export class ImChat { if (code == 0) { // 初始化成功 this.setConsole('%cim-chat: init', '初始化成功') this.status.isConnect = true - this.setConfig() // 设置日志级别 + // this.setConfig() // 设置日志级别 resolve(this) } else { // 失败:具体请看code console.error('[im-chat]:初始化失败', code) @@ -227,10 +230,11 @@ export class ImChat { }) } // 删除群组 - deleteGroup() { - if (!this.timGroupId) return + deleteGroup(timGroupId) { + const groupId = timGroupId || this.timGroupId + if (!groupId) return return this.timChat.TIMGroupDelete({ - groupId: this.timGroupId, + groupId, data: '', // 用户自定义数据 }) } @@ -249,7 +253,7 @@ export class ImChat { } // 获取群组列表 getGroupList() { - return this.timChat.getGroupList().then(res => { + return this.timChat.TIMGroupGetJoinedGroupList().then(res => { console.log('获取群组列表', res) return res }).catch(error => { @@ -281,8 +285,11 @@ export class ImChat { // callback: (data) => {} } // console.log('发送消息', option) - this.setConsole('%cim-chat: 发送消息', option) - return this.timChat.TIMMsgSendMessageV2(option) + this.setConsole('%cim-chat: 发送消息【req】', conv_id, msg) + return this.timChat.TIMMsgSendMessageV2(option).then(res => { + this.setConsole('%cim-chat: 发送消息【res】', JSON.stringify(res)) + return res + }) } /** * @description 发送群消息 diff --git a/src/renderer/src/store/modules/tool.js b/src/renderer/src/store/modules/tool.js index dd17432..f2ff2b0 100644 --- a/src/renderer/src/store/modules/tool.js +++ b/src/renderer/src/store/modules/tool.js @@ -18,7 +18,7 @@ export const useToolState = defineStore('tool', { showBoardAll: false, // 全屏画板-是否显示 isPdfWin: false, // pdf窗口是否打开 isToolWin: false, // 工具窗口是否打开 - isTaskWin: false, // 批改窗口是否打开 + isTaskWin: false, // 批改窗口是否打开 curSubjectNode: { querySearch: {} // 查询资源所需参数 }, diff --git a/src/renderer/src/utils/aichat.js b/src/renderer/src/utils/aichat.js new file mode 100644 index 0000000..85dcdc5 --- /dev/null +++ b/src/renderer/src/utils/aichat.js @@ -0,0 +1,80 @@ +import axios from "axios"; +import { getSignature } from "./index"; + +let appId = "01ec9aa3"; +let secret = "M2QxMDAxMjYyYTEzODMwMGRkZTQ4NmUy"; +let timestamp = Math.floor(Date.now() / 1000); +let signature = getSignature(appId, secret, timestamp); + +export function text2Text(data) { + return axios({ + url: "v1/chat/completions", + method: "post", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer yjCwlZCeUtBYvjHAQZdk:FtWNmJSWcZMCmTBQZfoH", + Accept: "*/*", + }, + data: { + model: "4.0Ultra", + messages: data, + stream: false, + }, + }); +} +export function uploadDoc(data) { + return axios({ + url: "openapi/v1/file/upload", + method: "post", + headers: { + "Content-Type": "multipart/form-data", + appId: appId, + timestamp: timestamp, + signature: signature, + }, + data: data, + }); +} +export function queryDocStatus(data) { + return axios({ + url: "openapi/v1/file/status", + method: "post", + headers: { + "Content-Type": "application/form-data", + appId: appId, + timestamp: timestamp, + signature: signature, + }, + data: data + }); +} +export function chatByDoc(fileId, data) { + const wsUrl = `wss://chatdoc.xfyun.cn/openapi/chat?fileId=${fileId}&appId=${appId}×tamp=${timestamp}&signature=${signature}`; + + const ws = new WebSocket(wsUrl); + + ws.onopen = () => { + const messageBody = { + fileIds: [fileId], + messages: data, + chatExtends: { + wikiPromptTpl: + "请将以下内容作为已知信息:\n\n请根据以上内容回答用户的问题。\n问题:\n回答:", + wikiFilterScore: 0.82, + temperature: 0.5, + sparkWhenWithoutEmbedding: false, + }, + }; + + ws.send(JSON.stringify(messageBody)); + }; + + ws.onmessage = (event) => { + const response = JSON.parse(event.data); + console.log("WebSocket 消息:", response); + }; + + ws.onerror = (error) => { + console.error("WebSocket 错误:", error); + }; +} \ No newline at end of file diff --git a/src/renderer/src/utils/chat.js b/src/renderer/src/utils/chat.js new file mode 100644 index 0000000..b3b06a8 --- /dev/null +++ b/src/renderer/src/utils/chat.js @@ -0,0 +1,97 @@ +/** +* 实现单例模式 +*/ +import useUserStore from '@/store/modules/user' +import { ImChat } from '@/plugins/imChat' +import * as http from '@/api/apiService' // 自定义api service + +export class Chat { + instance = null; + sdkAppId = 0; // 应用id + sign = ''; // 签名 + imUserId = ''; // 用户id + imChat = null; // IM实例 + + constructor() { + if (!Chat.instance) { // 存在的时候 + Chat.instance = this; + } + return Chat.instance; + } + /** + * 初始化 获取IM签名 + * @param {*} isInit : 是否初始化IM + * @param {*} isLogin : 是否登录IM + * @param {*} callback: 监听消息回调函数 + * @returns Promise + */ + async init(isInit = true, isLogin = true, callback) { + // 特殊处理,只传1个参数且为函数,则默认为callback,isInit和isLogin默认为true + if (typeof isInit == 'function'){ + callback = isInit + isInit = true + isLogin = true + } + const userStore = useUserStore() + const { timuserid: imUserId } = userStore.user + // 获取腾讯云签名 + const res = await http.imChat.getTxCloudSign({imUserId}) + if (res && res.code == 200) { + const { sdkAppId, sign } = res.data + this.sdkAppId = sdkAppId + this.sign = sign + this.imUserId = imUserId + // 初始化IM + if (isInit) return await this.initIM(isLogin, callback) + } + } + // 初始化IM + async initIM(isLogin, callback) { + const imChat = new ImChat(this.sdkAppId, this.sign, this.imUserId) + this.imChat = imChat + await imChat.init() // 初始化IM + callback && this.listenMsg(callback) // 监听消息 + if(isLogin) await imChat.login() // 登录IM + return imChat + } + // 监听消息 + async listenMsg(callback) { + if (!callback) return + if (!this.imChat) return + await this.imChat?.watch(msg => callback(msg)) + } + // 解散群 + async dismissGroup(groupId) { + if (!this.imChat) return + await this.imChat?.deleteGroup(groupId) + } + // 退出登录 + async logout() { + if (!this.imChat) return + await this.imChat?.logout() + this.imChat = null + } + // 发群消息 + async sendMsg(conv_id, msg) { + if (!this.imChat) return + await this.imChat?.sendMsg(conv_id, msg) + } + // 发群消息 + async sendMsgGroup(msg, head, type) { + if (!this.imChat) return + this.imChat?.sendMsgGroup(msg, head, type) + } + // 发群消息 + async sendMsgGroupId(groupId, msg, head, type) { + if (!this.imChat) return + const msgObj = this.imChat?.getMsgObj(head, msg, type) + this.imChat?.sendMsg(groupId, msgObj) + } + // 获取群列表 + async getGroupList() { + if (!this.imChat) return + return await this.imChat?.getGroupList() + } +} + +export default new Chat() diff --git a/src/renderer/src/utils/index.js b/src/renderer/src/utils/index.js new file mode 100644 index 0000000..e7bf6a4 --- /dev/null +++ b/src/renderer/src/utils/index.js @@ -0,0 +1,33 @@ +import CryptoJS from 'crypto-js'; + +// 生成签名的主方法 +export function getSignature(appId, secret, ts) { + try { + const auth = md5(appId + ts); + return hmacSHA1Encrypt(auth, secret); + } catch (error) { + console.error('Error generating signature:', error); + return null; + } +} + +// MD5 加密 +function md5(cipherText) { + try { + return CryptoJS.MD5(cipherText).toString(); // 使用 CryptoJS 进行 MD5 加密 + } catch (error) { + console.error('Error in MD5 hashing:', error); + return null; + } +} + +// HMAC-SHA1 加密 +function hmacSHA1Encrypt(encryptText, encryptKey) { + try { + // 使用 CryptoJS 进行 HMAC-SHA1 加密,并转换为 Base64 格式 + return CryptoJS.HmacSHA1(encryptText, encryptKey).toString(CryptoJS.enc.Base64); + } catch (error) { + console.error('Error in HMAC-SHA1 encryption:', error); + return null; + } +} diff --git a/src/renderer/src/utils/ppt-request.js b/src/renderer/src/utils/ppt-request.js new file mode 100644 index 0000000..e456d75 --- /dev/null +++ b/src/renderer/src/utils/ppt-request.js @@ -0,0 +1,100 @@ +import axios from "axios"; +import { getSignature } from "./index"; +import { ElMessage } from "element-plus"; +import request from '@/utils/request' + +let appId = "01ec9aa3"; +let secret = "M2QxMDAxMjYyYTEzODMwMGRkZTQ4NmUy"; +let timestamp = Math.floor(Date.now() / 1000); +let signature = getSignature(appId, secret, timestamp); +let req = (url, type, data)=>{ + let config = { + headers: { + "Content-Type": "application/json", + appId: appId, + timestamp: timestamp, + signature: signature, + }, + url: url, + method: type, + } + if (type === "GET") { + config.params = data; + } else { + config.data = data; + } + return request(config) +} + +/*const instance = axios.create({ + // baseURL: import.meta.env.VITE_APP_ENV === "development"?"/parth":import.meta.env.VITE_APP_BASE_API, + baseURL: "/dev-api", + headers: { + "Content-Type": "application/json", + 'Authorization': 'Bearer ' + getToken(), + appId: appId, + timestamp: timestamp, + signature: signature, + }, +});*/ + +const createOutline = async (data) => { + console.log("createOutline data:", data); + try { + const response = await req( + "/api/aippt/createOutline", + "POST", + data + ); + console.log("createOutline response:", response); + if (response.code == 81002) { + ElMessage.error("并发数量超过限制"); + } + return response.data; + } catch (error) { + console.error("请求失败:", error); + throw error; + } +}; +const getBackGround = async () => { + try { + const response = await req("/api/aippt/themeList", "GET"); + return response.data; + } catch (error) { + console.error("请求失败:", error); + throw error; + } +}; +const createPPT = async (data) => { + try { + const response = await req("/api/aippt/create", "POST", data); + console.log("createOutline response:", response); + + return response.data; + } catch (error) { + console.error("请求失败:", error); + throw error; + } +}; +const createByOutline = async (data) => { + try { + const response = await req("/api/aippt/createByOutline","POST", data); + console.log("createByOutline response:", response); + + return response.data; + } catch (error) { + console.error("请求失败:", error); + throw error; + } +}; +const getProgress = async (id) => { + try { + const response = await req(`/api/aippt/progress?sid=${id}`, "GET"); + return response.data; + } catch (error) { + console.error("请求失败:", error); + throw error; + } +}; + +export { createOutline, getBackGround, createPPT, getProgress, createByOutline }; diff --git a/src/renderer/src/utils/talkFile/index.js b/src/renderer/src/utils/talkFile/index.js index 08c9990..ae5dfbb 100644 --- a/src/renderer/src/utils/talkFile/index.js +++ b/src/renderer/src/utils/talkFile/index.js @@ -96,3 +96,19 @@ export const creatPPT = (name, uploadData) => { }) }) } + +export const creatAIPPT = (name, url, uploadData) => { + JSON.parse(JSON.stringify(uploadData)) + return new Promise((resolve, reject) => { + let cookie = localStorage.getItem('Admin-Token') + ipcRenderer.send('creat-ai-file-default', { + name, + url, + uploadData: JSON.parse(JSON.stringify(uploadData)), + cookie + }) + ipcRenderer.once('creat-ai-file-default-reply', (e, res) => { + resolve(res) + }) + }) +} diff --git a/src/renderer/src/views/classManage/classReserv.vue b/src/renderer/src/views/classManage/classReserv.vue index b5c6e53..ccb539c 100644 --- a/src/renderer/src/views/classManage/classReserv.vue +++ b/src/renderer/src/views/classManage/classReserv.vue @@ -11,6 +11,7 @@ v-if="item.bookImg" @open-edit="reservDialog.openDialog(item)" @delete-reserv="deleteReserv(item)" + @change="(...o) => emit('change', ...o)" > @@ -34,6 +36,10 @@ import Reserv from '@/views/prepare/container/reserv.vue' import { useToolState } from '@/store/modules/tool' import useUserStore from '@/store/modules/user' import ReservItemApt from '@/views/classManage/reserv-item-apt.vue' +// import Chat from '@/utils/chat' // im 登录初始化 +// if (!Chat.imChat) Chat.init() + +const emit = defineEmits(['change']) const reservDialog = ref(null) const tabOptions = ref(['进行中', '已结束']) const tabActive = ref('进行中') diff --git a/src/renderer/src/views/classManage/reserv-item-apt.vue b/src/renderer/src/views/classManage/reserv-item-apt.vue index 879b406..59c1137 100644 --- a/src/renderer/src/views/classManage/reserv-item-apt.vue +++ b/src/renderer/src/views/classManage/reserv-item-apt.vue @@ -7,14 +7,14 @@ {{item.caption}}
    - 已结束 + 已结束 上课中 继续上课 - 下课下课{{ loading?'中...':'' }}
    @@ -25,13 +25,11 @@
    + \ No newline at end of file diff --git a/src/renderer/src/views/classTask/container/classOverview/distribution/echarts.vue b/src/renderer/src/views/classTask/container/classOverview/distribution/echarts.vue index 9f6ae08..5447495 100644 --- a/src/renderer/src/views/classTask/container/classOverview/distribution/echarts.vue +++ b/src/renderer/src/views/classTask/container/classOverview/distribution/echarts.vue @@ -15,11 +15,11 @@ const chartRef = ref(null); // 数据源 const dataList = ref([ - {name: '优', value: 0,rating:1}, - {name: '优-', value: 0,rating:2}, - {name: '良', value: 0,rating:3}, - {name: '良-', value: 0,rating:4}, - {name: '差', value: 0,rating:5}, + {name: '完美', value: 0,rating:1,max:100,min:100,}, + {name: '优秀', value: 0,rating:2,max:99,min:80,}, + {name: '良好', value: 0,rating:3,max:79,min:70,}, + {name: '及格', value: 0,rating:4,max:69,min:60,}, + {name: '不及格', value: 0,rating:5,max:59,min:0,}, ]); // 根据数据生成不同的颜色 @@ -32,6 +32,8 @@ function getColor(index) { // 初始化图表 function initChart() { const myChart = echarts.init(chartRef.value); + const total = dataList.value.reduce((acc, cur) => acc + cur.value, 0); // 计算总数 + const options = { tooltip: { trigger: 'axis', @@ -70,7 +72,11 @@ function initChart() { label: { show: true, position: 'top', - formatter: '{c}人', + formatter: params => { + const value = dataList.value[params.dataIndex].value; + const percentage = value ? ((value / total) * 100).toFixed() : 0; // 计算百分比并保留两位小数 + return `${value}人 ${percentage}%`; // 显示为百分比形式 + }, color: '#333', fontSize: 12 } @@ -81,10 +87,13 @@ function initChart() { } // 获取表的数据 const showEcharts =() => { - useOverview.tableList.forEach(item => { - const index = dataList.value.findIndex(item1 => item1.rating === item.rating) - if(index !== -1) - dataList.value[index].value ++ + useOverview.tableList.forEach((item,index) => { + if(item.rating === 0) return // 没批改不计数 + dataList.value.forEach((item1,index1) => { + if(item1.min <= Number(item.scoingRate) && Number(item.scoingRate) <= item1.max ){ + item1.value ++ + } + }) }) } watch(() => useOverview.tableList,() => { diff --git a/src/renderer/src/views/classTask/container/classOverview/distribution/stuList.vue b/src/renderer/src/views/classTask/container/classOverview/distribution/stuList.vue index df21f66..c1de098 100644 --- a/src/renderer/src/views/classTask/container/classOverview/distribution/stuList.vue +++ b/src/renderer/src/views/classTask/container/classOverview/distribution/stuList.vue @@ -1,7 +1,7 @@