Compare commits
No commits in common. "main" and "2.5.7" have entirely different histories.
|
@ -17,7 +17,6 @@ VITE_APP_RES_FILE_PATH = 'https://file.ysaix.com:7868/src/assets/textbook/booktx
|
||||||
VITE_APP_BUILD_BASE_PATH = 'https://file.ysaix.com:7868/'
|
VITE_APP_BUILD_BASE_PATH = 'https://file.ysaix.com:7868/'
|
||||||
|
|
||||||
# websocket 地址
|
# websocket 地址
|
||||||
# VITE_APP_WS_URL = 'wss://prev.ysaix.com:7868'
|
|
||||||
VITE_APP_WS_URL = 'wss://file.ysaix.com:7868'
|
VITE_APP_WS_URL = 'wss://file.ysaix.com:7868'
|
||||||
# VITE_APP_WS_URL = 'ws://192.168.2.16:7865'
|
# VITE_APP_WS_URL = 'ws://192.168.2.16:7865'
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
# 页面标题
|
# 页面标题
|
||||||
VITE_APP_TITLE = 文枢课堂
|
VITE_APP_TITLE = 文枢课堂
|
||||||
|
|
||||||
VITE_APP_ID = 'aix-win-ws'
|
|
||||||
|
|
||||||
# 生产环境配置
|
# 生产环境配置
|
||||||
VITE_APP_ENV = 'production'
|
VITE_APP_ENV = 'production'
|
||||||
|
|
||||||
|
|
27
.env.yc
|
@ -1,27 +0,0 @@
|
||||||
# 页面标题
|
|
||||||
VITE_APP_TITLE = 永川中小学AI教学系统
|
|
||||||
|
|
||||||
VITE_APP_ID = 'aix-win-ws-yc'
|
|
||||||
|
|
||||||
# 生产环境配置
|
|
||||||
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'
|
|
27
.env.yc2
|
@ -1,27 +0,0 @@
|
||||||
# 页面标题
|
|
||||||
VITE_APP_TITLE = 实训教学
|
|
||||||
|
|
||||||
VITE_APP_ID = 'aix-win-ws-yc2'
|
|
||||||
|
|
||||||
# 生产环境配置
|
|
||||||
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'
|
|
|
@ -1,54 +0,0 @@
|
||||||
appId: com.electron.app.yc
|
|
||||||
productName: 永川中小学AI教学系统
|
|
||||||
directories:
|
|
||||||
output: dist
|
|
||||||
buildResources: build
|
|
||||||
win:
|
|
||||||
executableName: 永川中小学AI教学系统
|
|
||||||
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}-${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:
|
|
||||||
- '**/*'
|
|
|
@ -1,54 +0,0 @@
|
||||||
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}-${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:
|
|
||||||
- '**/*'
|
|
|
@ -35,7 +35,7 @@ export default defineConfig({
|
||||||
target: 'http://27.128.240.72:7865',
|
target: 'http://27.128.240.72:7865',
|
||||||
// target: 'https://prev.ysaix.com:7868/prod-api/',
|
// target: 'https://prev.ysaix.com:7868/prod-api/',
|
||||||
// target: 'http://36.134.181.164:7863',
|
// target: 'http://36.134.181.164:7863',
|
||||||
// target: 'http://192.168.2.237:7865',
|
// target: 'http://192.168.0.102:7865',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (p) => p.replace(/^\/dev-api/, '')
|
rewrite: (p) => p.replace(/^\/dev-api/, '')
|
||||||
},
|
},
|
||||||
|
|
11
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "aix-win-ws",
|
"name": "aix-win-ws",
|
||||||
"version": "2.5.15",
|
"version": "2.5.6",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "上海交大重庆人工智能研究院",
|
"author": "上海交大重庆人工智能研究院",
|
||||||
|
@ -10,13 +10,12 @@
|
||||||
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix",
|
"lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix",
|
||||||
"start": "electron-vite preview",
|
"start": "electron-vite preview",
|
||||||
"dev": "electron-vite dev",
|
"dev": "electron-vite dev",
|
||||||
|
"build": "electron-vite build",
|
||||||
"postinstall": "electron-builder install-app-deps",
|
"postinstall": "electron-builder install-app-deps",
|
||||||
"build:unpack": "npm run build && electron-builder --dir",
|
"build:unpack": "npm run build && electron-builder --dir",
|
||||||
"build:dev": "npm run build && electron-builder --win --config ./electron-builder-test.yml",
|
"build:dev": "npm run build && electron-builder --win --config ./electron-builder-test.yml",
|
||||||
"build:test": "node updatePackageJsonName.js && electron-vite build --mode test && electron-builder --win --config ./electron-builder.yml",
|
"build:test": "electron-vite build --mode test && electron-builder --win --config ./electron-builder.yml",
|
||||||
"build": "node updatePackageJsonName.js && electron-vite build --mode production && electron-builder --win --config ./electron-builder-prod.yml",
|
"build:prod": "electron-vite build --mode production && electron-builder --win --config ./electron-builder-prod.yml",
|
||||||
"build:yc": "node updatePackageJsonName.js && electron-vite build --mode yc && electron-builder --win --config ./electron-builder-yc.yml",
|
|
||||||
"build:yc2": "node updatePackageJsonName.js && 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: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:mac": "electron-vite build --mode production && electron-builder --mac --config ./electron-builder-prod.yml",
|
||||||
"build:linux": "npm run build && electron-builder --linux"
|
"build:linux": "npm run build && electron-builder --linux"
|
||||||
|
@ -35,14 +34,12 @@
|
||||||
"@electron/remote": "^2.1.2",
|
"@electron/remote": "^2.1.2",
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
"@icon-park/vue-next": "^1.4.2",
|
"@icon-park/vue-next": "^1.4.2",
|
||||||
"@kangc/v-md-editor": "^2.3.18",
|
|
||||||
"@tinymce/tinymce-vue": "5.1.1",
|
"@tinymce/tinymce-vue": "5.1.1",
|
||||||
"@vitejs/plugin-vue-jsx": "^4.0.0",
|
"@vitejs/plugin-vue-jsx": "^4.0.0",
|
||||||
"@vue-office/docx": "^1.6.2",
|
"@vue-office/docx": "^1.6.2",
|
||||||
"@vue-office/excel": "^1.7.11",
|
"@vue-office/excel": "^1.7.11",
|
||||||
"@vue-office/pdf": "^2.0.2",
|
"@vue-office/pdf": "^2.0.2",
|
||||||
"@vueuse/core": "^10.11.0",
|
"@vueuse/core": "^10.11.0",
|
||||||
"aix-plugins-aitools": "^1.1.0",
|
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"circular-json": "^0.5.9",
|
"circular-json": "^0.5.9",
|
||||||
"clipboard": "^2.0.11",
|
"clipboard": "^2.0.11",
|
||||||
|
|
Before Width: | Height: | Size: 51 KiB |
|
@ -13,34 +13,6 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
|
||||||
const appTempFilePath = userDataPath + '\\tempFile\\'
|
const appTempFilePath = userDataPath + '\\tempFile\\'
|
||||||
let Spark = new SparkMD5.ArrayBuffer()
|
let Spark = new SparkMD5.ArrayBuffer()
|
||||||
|
|
||||||
ipcMain.on('remove-local-file-list', (e, list) => {
|
|
||||||
let filePath = appRootFilePath
|
|
||||||
for (let i = 0; i < list.length; i++) {
|
|
||||||
let item = list[i];
|
|
||||||
if (!isAccess(filePath + item.fileNewName)) {
|
|
||||||
e.reply('remove-local-file-list-not', item)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
fs.unlinkSync(filePath + item.fileNewName);
|
|
||||||
console.log(`${filePath} 已成功删除`);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(`删除文件时出错:`, err);
|
|
||||||
e.reply('remove-local-file-list-error', item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
e.reply('remove-local-file-list-reply')
|
|
||||||
})
|
|
||||||
|
|
||||||
const isAccess = (filePath) => {
|
|
||||||
try {
|
|
||||||
fs.accessSync(filePath);
|
|
||||||
return true
|
|
||||||
} catch (err) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ipcMain.on('upload-file-change', (e, { id, fileNewName, cookie, fileType }) => {
|
ipcMain.on('upload-file-change', (e, { id, fileNewName, cookie, fileType }) => {
|
||||||
let filePath = appRootFilePath + fileNewName
|
let filePath = appRootFilePath + fileNewName
|
||||||
//执行更新,上传文件
|
//执行更新,上传文件
|
||||||
|
@ -86,6 +58,7 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
|
||||||
}
|
}
|
||||||
//倒数十秒提交更改,十秒之内有继续修改则重置倒数
|
//倒数十秒提交更改,十秒之内有继续修改则重置倒数
|
||||||
uploadId = setTimeout(() => {
|
uploadId = setTimeout(() => {
|
||||||
|
console.log(223)
|
||||||
//执行更新,上传文件
|
//执行更新,上传文件
|
||||||
let formData = new FormData()
|
let formData = new FormData()
|
||||||
formData.append('id', id)
|
formData.append('id', id)
|
||||||
|
@ -116,12 +89,8 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
|
||||||
|
|
||||||
function getFileMsg(path) {
|
function getFileMsg(path) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
|
||||||
const stats = fs.statSync(path)
|
const stats = fs.statSync(path)
|
||||||
resolve(stats.mtime.getTime())
|
return resolve(stats.mtime.getTime())
|
||||||
}catch (e) {
|
|
||||||
reject(e)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,20 +303,17 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
|
||||||
},
|
},
|
||||||
onDownloadCancelled: async () => {
|
onDownloadCancelled: async () => {
|
||||||
console.log("取消")
|
console.log("取消")
|
||||||
resolve({type:"取消了下载"})
|
reject({type:"取消了下载"})
|
||||||
},
|
},
|
||||||
onDownloadInterrupted: async () => {
|
onDownloadInterrupted: async () => {
|
||||||
console.log('中断')
|
console.log('中断')
|
||||||
resolve({type:"下载被中断"})
|
reject({type:"下载被中断"})
|
||||||
},
|
},
|
||||||
onError: (err, data) => {
|
onError: (err, data) => {
|
||||||
console.log(err.toString())
|
console.log(err.toString())
|
||||||
resolve({type:"下载出错",err})
|
reject({type:"下载出错",err})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).catch(err=>{
|
|
||||||
console.log(err)
|
|
||||||
resolve({type:"下载出错",err})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -359,11 +325,6 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
|
||||||
|
|
||||||
//下载文件
|
//下载文件
|
||||||
ipcMain.on('download-file-default', (e, { url, fileName }) => {
|
ipcMain.on('download-file-default', (e, { url, fileName }) => {
|
||||||
console.log(url, fileName)
|
|
||||||
if (!url) {
|
|
||||||
e.reply('download-file-default' + fileName, false)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
createFolder('selfFile')
|
createFolder('selfFile')
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
const browserWindow = BrowserWindow.getFocusedWindow()
|
const browserWindow = BrowserWindow.getFocusedWindow()
|
||||||
|
@ -399,7 +360,6 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log(error)
|
|
||||||
e.reply('download-file-default' + fileName, false)
|
e.reply('download-file-default' + fileName, false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,7 +7,6 @@ import Logger from './logger' // 日志封装
|
||||||
import chat from './chat' // chat封装
|
import chat from './chat' // chat封装
|
||||||
import Store from './store' // Store封装
|
import Store from './store' // Store封装
|
||||||
import updateInit from './update'
|
import updateInit from './update'
|
||||||
|
|
||||||
// 代理 electron/remote
|
// 代理 electron/remote
|
||||||
// 第一步:引入remote
|
// 第一步:引入remote
|
||||||
import remote from '@electron/remote/main'
|
import remote from '@electron/remote/main'
|
||||||
|
@ -42,19 +41,19 @@ if(!gotTheLock){
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
let logoIco = import.meta.env.MODE==='yc'||import.meta.env.MODE==='yc2'?'../../resources/yc-logo.png':'../../resources/logo2.ico'
|
|
||||||
//登录窗口
|
//登录窗口
|
||||||
function createLoginWindow() {
|
function createLoginWindow() {
|
||||||
if (loginWindow) return
|
if (loginWindow) return
|
||||||
loginWindow = new BrowserWindow({
|
loginWindow = new BrowserWindow({
|
||||||
width: import.meta.env.MODE==='yc'||import.meta.env.MODE==='yc2'?1060:888,
|
width: 888,
|
||||||
height: 520,
|
height: 520,
|
||||||
show: false,
|
show: false,
|
||||||
frame: false,
|
frame: false,
|
||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
maximizable: false,
|
maximizable: false,
|
||||||
resizable: false,
|
resizable: false,
|
||||||
icon: join(__dirname, logoIco),
|
icon: join(__dirname, '../../resources/logo2.ico'),
|
||||||
...(process.platform === 'linux' ? { icon } : {}),
|
...(process.platform === 'linux' ? { icon } : {}),
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
defaultEncoding: 'utf-8',
|
defaultEncoding: 'utf-8',
|
||||||
|
@ -96,7 +95,7 @@ function createMainWindow() {
|
||||||
frame: false, // 无边框
|
frame: false, // 无边框
|
||||||
autoHideMenuBar: true,
|
autoHideMenuBar: true,
|
||||||
maximizable: false,
|
maximizable: false,
|
||||||
icon: join(__dirname, logoIco),
|
icon: join(__dirname, '../../resources/logo2.ico'),
|
||||||
...(process.platform === 'linux' ? { icon } : {}),
|
...(process.platform === 'linux' ? { icon } : {}),
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
defaultEncoding: 'utf-8',
|
defaultEncoding: 'utf-8',
|
||||||
|
@ -244,13 +243,6 @@ app.on('ready', () => {
|
||||||
loginWindow.show()
|
loginWindow.show()
|
||||||
loginWindow.focus()
|
loginWindow.focus()
|
||||||
})
|
})
|
||||||
// 打印窗口
|
|
||||||
ipcMain.on('printPage', (event, printOptions) => {
|
|
||||||
//console.log("ipcMain-print-page")
|
|
||||||
mainWindow.webContents.print(printOptions, (success, failureReason) => {
|
|
||||||
if (!success) console.error(failureReason);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
//打开作业窗口
|
//打开作业窗口
|
||||||
ipcMain.on('openWindow', (e, data) => {
|
ipcMain.on('openWindow', (e, data) => {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
http-equiv="Content-Security-Policy"
|
http-equiv="Content-Security-Policy"
|
||||||
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:"
|
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:; frame-src 'self' *; 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 data:;" />
|
<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>
|
</head>
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
<svg style="width: 1em;height: 1em;vertical-align: middle;fill: currentColor;overflow: hidden;" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6511">
|
|
||||||
<path d="M512 34.133333c263.466667 0 477.866667 214.4 477.866667 477.866667S775.466667 989.866667 512 989.866667 34.133333 775.466667 34.133333 512 248.533333 34.133333 512 34.133333M512 0C229.333333 0 0 229.333333 0 512s229.333333 512 512 512 512-229.333333 512-512S794.666667 0 512 0z" fill="#87C1FF" p-id="6512"></path><path d="M505.173333 611.62666667c100.053333 0 181.333333-80.64 181.333334-180.053333 0-99.2-81.28-180.053333-181.333334-180.053334-100.053333 0-181.333333 80.64-181.333333 180.053334s81.28 180.053333 181.333333 180.053333zM579.84 661.54666667h-135.893333c-126.293333 0-229.12 102.4-229.12 228.053333v13.44c0 65.706667 101.12 65.706667 229.12 65.706667h135.893333c122.88 0 229.12 0 229.12-65.706667v-13.44c0-125.653333-102.826667-228.053333-229.12-228.053333z" fill="#87C1FF" p-id="6513"></path>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 1006 B |
|
@ -1 +0,0 @@
|
||||||
<svg viewBox="0 0 58 44" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path id="path" d="M57.25 3.64C56.64 3.33 56.37 3.91 56.01 4.21C55.89 4.3 55.79 4.43 55.68 4.54C54.79 5.52 53.74 6.16 52.37 6.08C50.38 5.97 48.67 6.61 47.16 8.16C46.84 6.24 45.77 5.1 44.15 4.36C43.3 3.98 42.45 3.6 41.85 2.77C41.44 2.17 41.32 1.51 41.12 0.86C40.98 0.47 40.85 0.07 40.41 0C39.93 -0.07 39.74 0.34 39.55 0.68C38.8 2.09 38.5 3.64 38.53 5.2C38.6 8.73 40.06 11.54 42.96 13.54C43.29 13.76 43.38 13.99 43.27 14.33C43.08 15.02 42.84 15.68 42.63 16.37C42.5 16.81 42.3 16.91 41.84 16.72C40.25 16.04 38.87 15.04 37.65 13.82C35.59 11.79 33.72 9.54 31.39 7.78C30.85 7.37 30.3 6.99 29.73 6.63C27.36 4.28 30.05 2.35 30.67 2.12C31.32 1.88 30.89 1.06 28.79 1.06C26.69 1.07 24.77 1.79 22.31 2.75C21.96 2.89 21.58 3 21.19 3.08C18.97 2.65 16.66 2.56 14.24 2.83C9.7 3.35 6.07 5.54 3.4 9.27C0.19 13.76 -0.56 18.87 0.36 24.19C1.33 29.8 4.14 34.44 8.46 38.07C12.94 41.84 18.1 43.68 23.98 43.33C27.56 43.12 31.54 42.63 36.02 38.76C37.16 39.33 38.34 39.56 40.31 39.74C41.83 39.88 43.29 39.66 44.43 39.42C46.2 39.04 46.08 37.37 45.43 37.06C40.24 34.6 41.38 35.6 40.34 34.79C42.98 31.6 46.96 28.3 48.52 17.59C48.64 16.74 48.54 16.2 48.52 15.51C48.51 15.09 48.6 14.93 49.07 14.88C50.38 14.73 51.64 14.37 52.8 13.72C56.16 11.84 57.52 8.77 57.84 5.08C57.89 4.51 57.83 3.93 57.25 3.64ZM27.91 36.83C22.88 32.8 20.44 31.47 19.43 31.53C18.49 31.59 18.65 32.68 18.86 33.4C19.08 34.11 19.36 34.6 19.76 35.22C20.03 35.63 20.22 36.24 19.48 36.7C17.86 37.72 15.04 36.35 14.91 36.29C11.63 34.32 8.89 31.72 6.95 28.16C5.09 24.74 4 21.07 3.82 17.16C3.78 16.21 4.05 15.88 4.97 15.7C6.19 15.48 7.44 15.43 8.66 15.61C13.8 16.37 18.17 18.71 21.84 22.42C23.94 24.53 25.52 27.06 27.15 29.52C28.89 32.14 30.75 34.63 33.13 36.68C33.97 37.4 34.64 37.94 35.28 38.34C33.35 38.56 30.12 38.61 27.91 36.83ZM30.33 21.02C30.33 20.6 30.66 20.26 31.07 20.26C31.17 20.26 31.25 20.28 31.33 20.31C31.43 20.35 31.53 20.41 31.6 20.49C31.73 20.63 31.81 20.82 31.81 21.02C31.81 21.44 31.48 21.77 31.06 21.77C30.65 21.77 30.33 21.44 30.33 21.02ZM37.82 24.93C37.34 25.14 36.86 25.31 36.4 25.33C35.68 25.36 34.9 25.07 34.48 24.71C33.82 24.14 33.35 23.83 33.15 22.84C33.06 22.42 33.11 21.77 33.19 21.4C33.36 20.6 33.17 20.08 32.61 19.61C32.16 19.23 31.58 19.12 30.95 19.12C30.72 19.12 30.5 19.02 30.34 18.93C30.07 18.8 29.86 18.47 30.06 18.05C30.13 17.92 30.45 17.6 30.53 17.54C31.38 17.04 32.37 17.2 33.29 17.58C34.14 17.93 34.78 18.58 35.7 19.5C36.65 20.61 36.82 20.91 37.35 21.74C37.78 22.39 38.16 23.06 38.43 23.83C38.59 24.3 38.38 24.7 37.82 24.93Z" fill="#4D6BFE" fill-opacity="1.000000" fill-rule="nonzero"></path></svg>
|
|
Before Width: | Height: | Size: 2.6 KiB |
|
@ -1,8 +0,0 @@
|
||||||
<?xml version="1.0" standalone="no"?>
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="body_1" width="96" height="97">
|
|
||||||
|
|
||||||
<g transform="matrix(1.3333334 0 0 1.3333334 0 0)">
|
|
||||||
<image x="0" y="0" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGAAAABhCAYAAAApxKSdAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAT2SURBVHhe7Z0/stowEMYp04UuZahSZqjSZYYmXQqKpEtBn+IxSZcm3ABuQG7wuAFH4AgcgSMQfcp7xDYf9uKVZOt5d+bXyJYt76c/K9mIkdlwbOyYOKaOmWPuWBRYOlaJwL2K90ZZUCaAMqKs2RoKj4daOx4dR8fJcc4MlPngwDNANIgEcXppqNW/HXA2e5iXBERB5eqFGGiyewcr6BDAs8MHyQ3qD9nxVbaOZC3iwZFjn54CdMPRDIOr1fpmMGgHbw244BAG2FDAV8FEQIRjzr+fICJYzdeBsbK1COb8MLRuCeb8cGDydtfyBmZ67EJGe+BTkWEdh13A0COaNVvXEw/4trYrwkyOZTTCgZVVahb1pAGhKW0F1veng7YCq/3pQFhaMiw3sBONeJQiIrwjZScZ8YDPL2bLzOmBzy9mL1jSA597Q0jEThgm48k/2LHw+EU6DAbs4LD48HAe/TydR7/O//m2jy0GPnWx+H/0aV12fJEfTpS3M55PD3zvJwXsYGvm8/m5yXa7Hc3bluPx+HTlehuPx+W87xfc8UW+H8t5wuEnZH8KCUFYLBZPj3vb9nvXvEneNkjuB9tut9f5vz5yp1d5M73Oqwefs/i3+Oxga1ILIK39kwnpz9HPM4dXQUup5tXjBQg+B0gpgKr2A3QvzOFV4gjg5wJZC4DrSIzWfiDtgt7NeX4dXoDgi3CpBIBTJXaz9oOPK+7wKq+jhKPwfb4CwLESm81qwshXLiqqxv9VPtcIqCNfAaS1X3SfulaAQRoisXx68hVAWvtRFpb/Ama6xRaAQRl8cWNDnIG3iBeAHVCRQgBJ6IlzWN4S6NshQrxa3gRNVBFbAMn1YY21vx/QRBWxBQhW+/sBTVQRU4AXVvsBTVQRUwDka7KMaj+giSpiCSANPafTKAtnsaCJKmIJIAk9VysX05O8PYYmqoghgKT2bzYbmrfn0EQVMQSoq/2Hw8Hfk+XLAJqoQiLA6XTyIkjB+beMnQ/W63UO4wFNVCERIKWh9dxcju4emqiibwLAEJr2tDXQRBV9FACGbqyHLYEmquhagLqlCowNrMwdQhNVdCkAnI+5QJ3VvqBJD01U0aUAuHeTAD1rBTRRRVcCLJdLf/8mATAWVMvcITRRRUoB4EzMgIuDa5MAsB4NxjRRhUQAzF7RF7cFIeXVZ4ZPSATANVjeDqCJKiQCxOyHTQAT4B5oogoT4C5oogoT4C5oogoT4C5oooquBcB8oMlMgIgCSO5vApgAz+T5bWgdGQmQ78e5dZgAJoAUE6BjvABZ/0aMkZEA+f9Ij5GbANn/ULtKRgLsHCZAh/gfagffK8IEEOP3igi+W4oJIMbvloI9a9jB1pgAYvzGfdi1iR004nPZwNX2jEvPZc84WPC5gNGInwM8m+0bmp7SvqG2cV96sFtxybCfMTvRCI9fhKta8AmZcRMf/1cNIZFFQ/FB7b/5r0rWCuLjlx9uGVpB8Bc0xgXa91fNIqJ40L6f2cbBLmC0Bz4VG7oiC0vDIep6qmb/qhSG2qinyZDRQtP2qJz/bNYS2gGfXS03tDUT4T6C1Pyq4YLBd1p/gWCZ+fKiJYbZbJmDsbK0xBzT0BqCf86SMaj1wbsciWHWPOS3aXh2/2K9a4P6mOkNYfKGARbdcLAIJ7RBDHzqgkJi0IYoOc4lUGY4G8+AyoV1nMCD62j0F2POfFZ8DMaTAAAAAElFTkSuQmCC" preserveAspectRatio="none" width="72" height="72.75"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 220 KiB |
|
@ -74,6 +74,8 @@ const initLoad: Function = () => {
|
||||||
!!(opt.ratio??null) && slidesStore.setViewportRatio(opt.ratio)// 有比例配置项
|
!!(opt.ratio??null) && slidesStore.setViewportRatio(opt.ratio)// 有比例配置项
|
||||||
}
|
}
|
||||||
return PPTApi.getSlideList(resource.id)
|
return PPTApi.getSlideList(resource.id)
|
||||||
|
// PPTApi.updateWorkList()
|
||||||
|
// return Promise.resolve()
|
||||||
}
|
}
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,7 @@ export default () => {
|
||||||
const courseId = classcourse?.id // 课堂id
|
const courseId = classcourse?.id // 课堂id
|
||||||
const timgroupid = classcourse?.timgroupid // 群组id
|
const timgroupid = classcourse?.timgroupid // 群组id
|
||||||
const classcourseStore = useClasscourseStore() // 课堂信息-状态管理
|
const classcourseStore = useClasscourseStore() // 课堂信息-状态管理
|
||||||
// 上课状态才-初始化socket
|
if (!ChatWs.ws) ChatWs.init()
|
||||||
if (!ChatWs.ws && !!courseId) ChatWs.init()
|
|
||||||
// 开课消息
|
// 开课消息
|
||||||
const startCourse = async() => {
|
const startCourse = async() => {
|
||||||
// await API_classcourse.updateClasscourse({ id: classcourse.id, status: 'open' })
|
// await API_classcourse.updateClasscourse({ id: classcourse.id, status: 'open' })
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
export default class gridPic {
|
|
||||||
private static Instance: gridPic | null = null;
|
|
||||||
private gridPicRef: any = null;
|
|
||||||
|
|
||||||
constructor(elRef?: any) {
|
|
||||||
if (elRef) {
|
|
||||||
this.gridPicRef = elRef;
|
|
||||||
}
|
|
||||||
if (!gridPic.Instance) {
|
|
||||||
gridPic.Instance = this;
|
|
||||||
}
|
|
||||||
return gridPic.Instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化
|
|
||||||
init(elRef) {
|
|
||||||
if (elRef) {
|
|
||||||
this.gridPicRef = elRef;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
addPIc(data) {
|
|
||||||
if (this.gridPicRef && this.gridPicRef.value && typeof this.gridPicRef.value.addPic === 'function') {
|
|
||||||
this.gridPicRef.value.addPic(data);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 静态方法 - 初始化
|
|
||||||
static init(elRef) {
|
|
||||||
if (!gridPic.Instance) {
|
|
||||||
gridPic.Instance = new gridPic(elRef);
|
|
||||||
} else {
|
|
||||||
gridPic.Instance.init(elRef);
|
|
||||||
}
|
|
||||||
return gridPic.Instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 静态方法 - 打开推图上屏幕
|
|
||||||
static addPIc(data) {
|
|
||||||
if (gridPic.Instance) {
|
|
||||||
return gridPic.Instance.addPIc(data);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -50,8 +50,6 @@ export class Utils {
|
||||||
}, delay)
|
}, delay)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 延时
|
|
||||||
static sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** ppt相关后端接口处理 */
|
/** ppt相关后端接口处理 */
|
||||||
|
@ -61,7 +59,6 @@ export class PPTApi {
|
||||||
|
|
||||||
// 获取所有幻灯片列表 isUpdate为true不更新
|
// 获取所有幻灯片列表 isUpdate为true不更新
|
||||||
static getSlideList(parentid: (Number | String),isUpdate?:Boolean): Promise<Boolean> {
|
static getSlideList(parentid: (Number | String),isUpdate?:Boolean): Promise<Boolean> {
|
||||||
const classcourse = sessionStore.get('curr.classcourse') // 课堂信息
|
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
const params: object = { parentid, orderByColumn: 'fileidx', isAsc: 'asc', pageSize: 9999 }
|
const params: object = { parentid, orderByColumn: 'fileidx', isAsc: 'asc', pageSize: 9999 }
|
||||||
const res: Result = await API_entpcoursefile.listEntpcoursefileNew(params)
|
const res: Result = await API_entpcoursefile.listEntpcoursefileNew(params)
|
||||||
|
@ -82,45 +79,25 @@ export class PPTApi {
|
||||||
// 活动列表处理
|
// 活动列表处理
|
||||||
// const workList = (res.rows || []).map(o => o.activityContent)
|
// const workList = (res.rows || []).map(o => o.activityContent)
|
||||||
const workItem = res.rows ? [...res.rows] : []
|
const workItem = res.rows ? [...res.rows] : []
|
||||||
|
// 写入作业列表数据
|
||||||
|
// slidesStore.setWorkList(workList)
|
||||||
// 获取所有的pptlist的数据
|
// 获取所有的pptlist的数据
|
||||||
slidesStore.setWorkItem(workItem)
|
slidesStore.setWorkItem(workItem)
|
||||||
// 没有上课时调用-作业列表
|
|
||||||
if(!classcourse) this.updateWorkList()
|
this.updateWorkList()
|
||||||
// 没有上课时调用-批量更新缩略图
|
|
||||||
if(!classcourse) {
|
|
||||||
Utils.sleep(1500).then(() => {
|
|
||||||
this.batchUpdateThumUrl()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
resolve(true)
|
resolve(true)
|
||||||
} else msgUtils.msgError(res.msg || '获取数据失败');resolve(false)
|
} else msgUtils.msgError(res.msg || '获取数据失败');resolve(false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @description 批量插入slide
|
|
||||||
* @param slides 批量新增的幻灯片
|
|
||||||
* @param slideAll 所有幻灯片
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
static async addSlideServer(slides: object[], slideAll: object[]) {
|
|
||||||
const resource = sessionStore.get('curr.resource')||{}
|
|
||||||
for(const slide of slides){
|
|
||||||
slide.id = resource.id // 覆盖默认随机id
|
|
||||||
await this.addSlide(slide)
|
|
||||||
}
|
|
||||||
await this.batchUpdateSlides(slideAll, true) // 批量更新-排序
|
|
||||||
return PPTApi.getSlideList(resource.id) // 更新幻灯片列表以及活动相关
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增幻灯片
|
// 新增幻灯片
|
||||||
static addSlide(data: object): Promise<Boolean> {
|
static addSlide(data: object): Promise<Boolean> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
const enpt = sessionStore.get('curr.entp')||{}
|
const enpt = sessionStore.get('curr.entp')||{}
|
||||||
// const resource = sessionStore.get('curr.resource')||{}
|
const resource = sessionStore.get('curr.resource')||{}
|
||||||
const {id, ...content} = data
|
const {id, ...content} = data
|
||||||
const params = {
|
const params = {
|
||||||
parentid: id,
|
parentid: resource.id,
|
||||||
entpid: userStore.user.deptId,
|
entpid: userStore.user.deptId,
|
||||||
entpcourseid: enpt.id,
|
entpcourseid: enpt.id,
|
||||||
ppttype: 'file',
|
ppttype: 'file',
|
||||||
|
@ -142,7 +119,7 @@ export class PPTApi {
|
||||||
// msgUtils.msgSuccess('新增成功')
|
// msgUtils.msgSuccess('新增成功')
|
||||||
this.isUpdate = false // 新增后会触发监听,不再更新数据
|
this.isUpdate = false // 新增后会触发监听,不再更新数据
|
||||||
resolve(true)
|
resolve(true)
|
||||||
} else msgUtils.msgError('新增失败');reject(false)
|
} else msgUtils.msgError('新增失败');resolve(false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -163,8 +140,12 @@ export class PPTApi {
|
||||||
const currInd = toRaw(slidesStore.slideIndex) // 当前页索引-new
|
const currInd = toRaw(slidesStore.slideIndex) // 当前页索引-new
|
||||||
const oldInd = oldData.findIndex(o => o.id == currentSlide.id) // 当前页索引-old
|
const oldInd = oldData.findIndex(o => o.id == currentSlide.id) // 当前页索引-old
|
||||||
const isBatch = oldVal && oldVal.length && currInd != oldInd // 是否批量更新-排序
|
const isBatch = oldVal && oldVal.length && currInd != oldInd // 是否批量更新-排序
|
||||||
if (isAdd) return // 新增-这里不处理 状态管理-处理
|
if (isAdd) { // 新增的幻灯片(id 为非数字,说明是新增的幻灯片)
|
||||||
// 防抖-更新
|
const bool = await this.addSlide(currentSlide)
|
||||||
|
bool && await this.batchUpdateSlides(newData, true) // 批量更新-排序
|
||||||
|
const resource = sessionStore.get('curr.resource')||{}
|
||||||
|
await PPTApi.getSlideList(resource.id)
|
||||||
|
} else { // 防抖-更新
|
||||||
if (!this.isUpdate) return this.isUpdate = true // 下次更新数据
|
if (!this.isUpdate) return this.isUpdate = true // 下次更新数据
|
||||||
if (isBatch) { // 批量更新-排序
|
if (isBatch) { // 批量更新-排序
|
||||||
this.batchUpdateSlides(newData, true)
|
this.batchUpdateSlides(newData, true)
|
||||||
|
@ -176,6 +157,7 @@ export class PPTApi {
|
||||||
Utils.mxThrottle(() => {this.updateSlide(params)}, 200, 2)
|
Utils.mxThrottle(() => {this.updateSlide(params)}, 200, 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// 更新幻灯片 isThum 是否更新缩略图
|
// 更新幻灯片 isThum 是否更新缩略图
|
||||||
static updateSlide(data: object, isThum = true): Promise<Boolean> {
|
static updateSlide(data: object, isThum = true): Promise<Boolean> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
|
@ -250,29 +232,10 @@ 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 缩略图
|
// thumbnail-slide thumbnail 缩略图
|
||||||
static getSlideThumUrl(index?:number): Promise<Boolean> {
|
static getSlideThumUrl(): Promise<Boolean> {
|
||||||
return nextTick().then(async() => {
|
return nextTick().then(async() => {
|
||||||
const slideIndex = index ?? slidesStore.slideIndex
|
const slideIndex = slidesStore.slideIndex
|
||||||
const elements = document.querySelectorAll('.thumbnail-slide')
|
const elements = document.querySelectorAll('.thumbnail-slide')
|
||||||
if (elements.length && slideIndex >= 0) {
|
if (elements.length && slideIndex >= 0) {
|
||||||
const element = elements[slideIndex]
|
const element = elements[slideIndex]
|
||||||
|
@ -285,7 +248,6 @@ export class PPTApi {
|
||||||
static toRousrceUrl =async (o:any) => {
|
static toRousrceUrl =async (o:any) => {
|
||||||
const formData = new FormData()
|
const formData = new FormData()
|
||||||
formData.append('file', o)
|
formData.append('file', o)
|
||||||
formData.append('ral', true)
|
|
||||||
const res = await Api_server.Other.uploadFile(formData)
|
const res = await Api_server.Other.uploadFile(formData)
|
||||||
if (res && res.code == 200){
|
if (res && res.code == 200){
|
||||||
const url = res?.url
|
const url = res?.url
|
||||||
|
|
|
@ -126,14 +126,10 @@ export class MsgEnum {
|
||||||
MSG_homework : 'HOMEWORK',
|
MSG_homework : 'HOMEWORK',
|
||||||
/** @desc: 公屏 - 课堂作业|活动 */
|
/** @desc: 公屏 - 课堂作业|活动 */
|
||||||
MSG_pushSreen_work : 'pushSreen_work',
|
MSG_pushSreen_work : 'pushSreen_work',
|
||||||
/** @desc: 公屏 - 实验 */
|
|
||||||
MSG_pushSreen_experiment : 'pushSreen_experiment',
|
|
||||||
/** @desc: 点赞 */
|
/** @desc: 点赞 */
|
||||||
MSG_dz : 'dz',
|
MSG_dz : 'dz',
|
||||||
/** @desc: 疑惑 */
|
/** @desc: 疑惑 */
|
||||||
MSG_yh : 'yh',
|
MSG_yh : 'yh',
|
||||||
/** @desc: 推图片上屏 */
|
|
||||||
MSG_pushSreen_ImgList : 'pushSreen_ImgList',
|
|
||||||
// === 新定义-消息头 ===
|
// === 新定义-消息头 ===
|
||||||
/** @desc: 课程创建-待开课 */
|
/** @desc: 课程创建-待开课 */
|
||||||
MSG_0000: 0x0000,
|
MSG_0000: 0x0000,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* @description 公共监听器
|
* @description 公共监听器
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { watch, render } from 'vue'
|
import { watch } from 'vue'
|
||||||
import { PPTApi } from './index'
|
import { PPTApi } from './index'
|
||||||
import * as store from '../store'
|
import * as store from '../store'
|
||||||
import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
||||||
|
@ -10,12 +10,10 @@ import { MsgEnum } from './types' // 消息枚举
|
||||||
import ChatWs from '@/plugins/socket' // 聊天socket
|
import ChatWs from '@/plugins/socket' // 聊天socket
|
||||||
import Classcourse from './classcourse' // 课程相关
|
import Classcourse from './classcourse' // 课程相关
|
||||||
import msgUtils from '@/plugins/modal' // 消息工具
|
import msgUtils from '@/plugins/modal' // 消息工具
|
||||||
import * as dialogUtils from '@/utils/dialog' // 弹窗-函数
|
|
||||||
import { Homework } from './index' // api-作业相关
|
import { Homework } from './index' // api-作业相关
|
||||||
import emitter from '@/utils/mitt' //mitt 事件总线
|
// import emitter from '@/utils/mitt' //mitt 事件总线
|
||||||
import useExecPlay from '../views/Screen/hooks/useExecPlay' // 播放控制
|
import useExecPlay from '../views/Screen/hooks/useExecPlay' // 播放控制
|
||||||
import hooksUpvote from './upvote' // 点赞-工具
|
import hooksUpvote from './upvote' // 点赞-工具
|
||||||
import gridPic from './gridPic' // 上屏-工具
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 监听器
|
* @description 监听器
|
||||||
|
@ -99,8 +97,6 @@ export default () => {
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case MsgEnum.HEADS.MSG_slideFlapping: // 幻灯片翻页
|
case MsgEnum.HEADS.MSG_slideFlapping: // 幻灯片翻页
|
||||||
render(null, document.body) //移除弹窗
|
|
||||||
emitter.emit('closegridPic') //如果有推图片窗口 就关闭
|
|
||||||
const slideIndex = content?.current || 0
|
const slideIndex = content?.current || 0
|
||||||
const type = content?.animation // 上下动作
|
const type = content?.animation // 上下动作
|
||||||
const steps = content?.animationSteps // 动画步骤
|
const steps = content?.animationSteps // 动画步骤
|
||||||
|
@ -118,10 +114,6 @@ export default () => {
|
||||||
if (!content.id) return
|
if (!content.id) return
|
||||||
Homework.showHomework(content.id)
|
Homework.showHomework(content.id)
|
||||||
break
|
break
|
||||||
case MsgEnum.HEADS.MSG_pushSreen_experiment: // 打开实验:
|
|
||||||
if (!content.url) return
|
|
||||||
dialogUtils.openLink(content.url)
|
|
||||||
break
|
|
||||||
case MsgEnum.HEADS.MSG_closed: // 下课:
|
case MsgEnum.HEADS.MSG_closed: // 下课:
|
||||||
close()
|
close()
|
||||||
break
|
break
|
||||||
|
@ -131,10 +123,6 @@ export default () => {
|
||||||
case MsgEnum.HEADS.MSG_yh: // 疑惑
|
case MsgEnum.HEADS.MSG_yh: // 疑惑
|
||||||
hooksUpvote.trigger(2)
|
hooksUpvote.trigger(2)
|
||||||
break
|
break
|
||||||
case MsgEnum.HEADS.MSG_pushSreen_ImgList: // 推图片上屏
|
|
||||||
const imgArray = content.ImgList.map((obj) => obj.url);
|
|
||||||
emitter.emit('opengridPic',{arr:imgArray}) // 打开推图片上屏窗口
|
|
||||||
break
|
|
||||||
case MsgEnum.HEADS.MSG_0010: // 备用
|
case MsgEnum.HEADS.MSG_0010: // 备用
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { useScreenStore, useSlidesStore, useClasscourseStore } from '../store'
|
import { useScreenStore, useSlidesStore, useClasscourseStore } from '../store'
|
||||||
import { enterFullscreen, exitFullscreen, isFullscreen } from '../utils/fullscreen'
|
import { enterFullscreen, exitFullscreen, isFullscreen } from '../utils/fullscreen'
|
||||||
import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
|
||||||
import ChatWs from '@/plugins/socket' // 聊天socket
|
import ChatWs from '@/plugins/socket' // 聊天socket
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
|
@ -26,9 +25,6 @@ export default () => {
|
||||||
if (!!classcourse) { //DOTO 有课堂,执行退相关操作
|
if (!!classcourse) { //DOTO 有课堂,执行退相关操作
|
||||||
console.log('退出放映状态')
|
console.log('退出放映状态')
|
||||||
ChatWs?.close() // 关闭ws
|
ChatWs?.close() // 关闭ws
|
||||||
sessionStore.delete('curr.classcourse') // 清除课堂信息
|
|
||||||
sessionStore.delete('curr.resource') // 清除课件信息
|
|
||||||
sessionStore.delete('curr.isPublic') // 清除公屏状态
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.close() // 关闭窗口
|
window.close() // 关闭窗口
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
|
|
@ -148,8 +148,7 @@ export const useSlidesStore = defineStore('slides', {
|
||||||
this.workItem = list
|
this.workItem = list
|
||||||
},
|
},
|
||||||
|
|
||||||
async addSlide(slide: Slide | Slide[]) {
|
addSlide(slide: Slide | Slide[]) {
|
||||||
const { PPTApi } = await import('../api/index')
|
|
||||||
const slides = Array.isArray(slide) ? slide : [slide]
|
const slides = Array.isArray(slide) ? slide : [slide]
|
||||||
for (const slide of slides) {
|
for (const slide of slides) {
|
||||||
if (slide.sectionTag) delete slide.sectionTag
|
if (slide.sectionTag) delete slide.sectionTag
|
||||||
|
@ -157,8 +156,6 @@ export const useSlidesStore = defineStore('slides', {
|
||||||
const addIndex = this.slideIndex + 1
|
const addIndex = this.slideIndex + 1
|
||||||
this.slides.splice(addIndex, 0, ...slides)
|
this.slides.splice(addIndex, 0, ...slides)
|
||||||
this.slideIndex = addIndex
|
this.slideIndex = addIndex
|
||||||
// 添加到服务器
|
|
||||||
PPTApi.addSlideServer(slides, this.slides)
|
|
||||||
},
|
},
|
||||||
updateSlide(props: Partial<Slide>, slideId?: string) {
|
updateSlide(props: Partial<Slide>, slideId?: string) {
|
||||||
const slideIndex = slideId ? this.slides.findIndex(item => item.id === slideId) : this.slideIndex
|
const slideIndex = slideId ? this.slides.findIndex(item => item.id === slideId) : this.slideIndex
|
||||||
|
|
|
@ -5,21 +5,14 @@
|
||||||
</header>
|
</header>
|
||||||
<div class="flex material-list" v-loading="loading">
|
<div class="flex material-list" v-loading="loading">
|
||||||
<div class="flex material-item" v-for="item in list" :key="item.id" >
|
<div class="flex material-item" v-for="item in list" :key="item.id" >
|
||||||
<div class="flex material-item">
|
<div class="flex">
|
||||||
<el-image v-if="item.fileType.indexOf('image')!=-1" :src="fileUrl(item)" class="img" />
|
<el-image :src="fileUrl(item)" class="img" />
|
||||||
<svg v-if="item.fileType.indexOf('video')!=-1" class="icon file-icon" aria-hidden="true" :style="{ 'font-size': 100 + 'px' }">
|
<el-text truncated>{{ item.fileShowName }}</el-text>
|
||||||
<use :xlink:href="'#icon-video'"></use>
|
|
||||||
</svg>
|
|
||||||
<svg class="icon file-icon" v-if="item.fileType.indexOf('audio')!=-1" aria-hidden="true" :style="{ 'font-size': 100 + 'px' }">
|
|
||||||
<use :xlink:href="'#icon-mp'"></use>
|
|
||||||
</svg>
|
|
||||||
<div class="texts">{{ item.fileShowName }}</div>
|
|
||||||
<!-- <el-text truncated>{{ item.fileShowName }}</el-text> -->
|
|
||||||
</div>
|
</div>
|
||||||
<el-button style="margin-left: 10px;" type="primary" @click="onInsert(item)">插入</el-button>
|
<el-button type="primary" @click="onInsert(item)">插入</el-button>
|
||||||
</div>
|
</div>
|
||||||
<el-empty description="暂无素材" v-if="!list.length" />
|
<el-empty description="暂无素材" v-if="!list.length" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
@ -28,7 +21,6 @@ import { sessionStore } from '@/utils/store'
|
||||||
import { getSmarttalkPage } from '@/api/file'
|
import { getSmarttalkPage } from '@/api/file'
|
||||||
import * as commUtils from '@/utils/comm.js'
|
import * as commUtils from '@/utils/comm.js'
|
||||||
import { getFileSuffix } from '@/utils/ruoyi.js'
|
import { getFileSuffix } from '@/utils/ruoyi.js'
|
||||||
import { PPTApi } from '../../../api'
|
|
||||||
|
|
||||||
const emit = defineEmits(['insertMaterial', 'close'])
|
const emit = defineEmits(['insertMaterial', 'close'])
|
||||||
|
|
||||||
|
@ -44,7 +36,7 @@ let params = {
|
||||||
pageSize: 500
|
pageSize: 500
|
||||||
}
|
}
|
||||||
|
|
||||||
const suffixAry = [ 'jpeg','jpg','png','gif','mp3','mp4','avi','mov',"wav"]
|
const suffixAry = [ 'jpeg','jpg','png','gif','mp3','mp4','avi','mov']
|
||||||
const videoSuffix = ['mp3','mp4','avi','mov']
|
const videoSuffix = ['mp3','mp4','avi','mov']
|
||||||
const list = ref([])
|
const list = ref([])
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
@ -55,7 +47,6 @@ const init = () => {
|
||||||
if(res.rows && res.rows.length){
|
if(res.rows && res.rows.length){
|
||||||
// 过滤出图片和视频
|
// 过滤出图片和视频
|
||||||
list.value = res.rows.filter( item => suffixAry.indexOf(getFileSuffix(item.fileShowName)) != -1)
|
list.value = res.rows.filter( item => suffixAry.indexOf(getFileSuffix(item.fileShowName)) != -1)
|
||||||
console.log(list.value)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -69,34 +60,73 @@ const fileUrl = computed(() => (item) =>{
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
// 插入
|
// 插入
|
||||||
const onInsert = async (item) =>{
|
const onInsert = async (item) =>{
|
||||||
loading.value = true
|
const res = await fetch(item.fileFullPath)
|
||||||
|
const bolb = await res.blob()
|
||||||
|
const file = commUtils.blobToFile(bolb, item.fileShowName)
|
||||||
|
|
||||||
// const res = await fetch(item.fileFullPath)
|
|
||||||
// const bolb = await res.blob()
|
|
||||||
// const file = commUtils.blobToFile(bolb, item.fileShowName)
|
|
||||||
const data=item.fileFullPath
|
|
||||||
try {
|
|
||||||
console.log('item', item)
|
|
||||||
// const data = await PPTApi.toRousrceUrl(file)
|
|
||||||
if(videoSuffix.indexOf(getFileSuffix(item.fileShowName)) != -1){
|
if(videoSuffix.indexOf(getFileSuffix(item.fileShowName)) != -1){
|
||||||
emit('insertMaterial',{ type: 'video', data })
|
emit('insertMaterial',{ type: 'video', file })
|
||||||
}else if(item.fileType.indexOf('audio') != -1){
|
|
||||||
emit('insertMaterial',{ type: 'audio', data })
|
|
||||||
}else{
|
|
||||||
emit('insertMaterial',{ type: 'img', data })
|
|
||||||
}
|
}
|
||||||
} finally {
|
else{
|
||||||
loading.value = false
|
emit('insertMaterial',{ type: 'img', file })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const GetUrlParameters = (parameters) => {
|
||||||
|
let resData = "";
|
||||||
|
|
||||||
|
let url = document.location.toString();
|
||||||
|
let arrUrl = url.split("?");
|
||||||
|
// 判断是否有参数
|
||||||
|
if (arrUrl.length > 1) {
|
||||||
|
// 拆分参数字符串
|
||||||
|
let parametersArr = arrUrl[1].split("&");
|
||||||
|
// 循环查找参数
|
||||||
|
for (let i = 0; i <= parametersArr.length; i++) {
|
||||||
|
if (parametersArr[i]) {
|
||||||
|
// 拆分参数的键和值
|
||||||
|
let parameterStr = parametersArr[i].split("=");
|
||||||
|
if (parameters == parameterStr[0]) {
|
||||||
|
resData = parameterStr[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resData;
|
||||||
|
}
|
||||||
|
|
||||||
|
const proxyToBase64 = (url)=> {
|
||||||
|
const dourl = GetUrlParameters(url)
|
||||||
|
console.log(dourl,'dourl')
|
||||||
|
return
|
||||||
|
axios({
|
||||||
|
url: "/api/logo.png",
|
||||||
|
method: "get",
|
||||||
|
responseType: "blob",
|
||||||
|
}).then((res) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsDataURL(res.data);
|
||||||
|
reader.onload = () => {
|
||||||
|
console.log(reader.result);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 关闭
|
// 关闭
|
||||||
const onClose = () =>{
|
const onClose = () =>{
|
||||||
emit('close')
|
emit('close')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
let data = sessionStore.get('subject.curNode')
|
let data = sessionStore.get('subject.curNode')
|
||||||
Object.assign(curNode, data);
|
Object.assign(curNode, data);
|
||||||
|
@ -136,17 +166,11 @@ onMounted(() => {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
justify-content: space-between;
|
||||||
.img{
|
.img{
|
||||||
width: 100px;
|
width: 100px;
|
||||||
height: 100px;
|
height: 100px;
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.texts{
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
max-width: 600px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -281,19 +281,20 @@ const toggleNotesPanel = () => {
|
||||||
// 插入素材
|
// 插入素材
|
||||||
interface MaterialParams {
|
interface MaterialParams {
|
||||||
type: string,
|
type: string,
|
||||||
data: string
|
file: any
|
||||||
}
|
}
|
||||||
const insertMaterial = async (item: MaterialParams) =>{
|
const insertMaterial = (item: MaterialParams) =>{
|
||||||
const { type, data } = item
|
const { type, file } = item
|
||||||
|
PPTApi.toRousrceUrl(file).then(data=>{
|
||||||
if(type == 'video'){
|
if(type == 'video'){
|
||||||
createVideoElement(data)
|
createVideoElement(data)
|
||||||
}else if(type == 'audio'){
|
|
||||||
createAudioElement(data)
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
createImageElement(data)
|
createImageElement(data)
|
||||||
}
|
}
|
||||||
materiaVisible.value = false
|
materiaVisible.value = false
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 文生图
|
// 文生图
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<Popover trigger="click" placement="bottom-start" v-model:value="mainMenuVisible">
|
<Popover trigger="click" placement="bottom-start" v-model:value="mainMenuVisible">
|
||||||
<template #content>
|
<template #content>
|
||||||
<!-- <FileInput accept=".pptist" @change="files => {
|
<FileInput accept=".pptist" @change="files => {
|
||||||
importSpecificFile(files)
|
importSpecificFile(files)
|
||||||
mainMenuVisible = false
|
mainMenuVisible = false
|
||||||
}">
|
}">
|
||||||
|
@ -15,8 +15,8 @@
|
||||||
}">
|
}">
|
||||||
<PopoverMenuItem>导入 pptx 文件</PopoverMenuItem>
|
<PopoverMenuItem>导入 pptx 文件</PopoverMenuItem>
|
||||||
</FileInput>
|
</FileInput>
|
||||||
<PopoverMenuItem @click="setDialogForExport('pptx')">导出文件</PopoverMenuItem> -->
|
<PopoverMenuItem @click="setDialogForExport('pptx')">导出文件</PopoverMenuItem>
|
||||||
<!-- <PopoverMenuItem @click="resetSlides(); mainMenuVisible = false">重置幻灯片</PopoverMenuItem> -->
|
<PopoverMenuItem @click="resetSlides(); mainMenuVisible = false">重置幻灯片</PopoverMenuItem>
|
||||||
<!-- <PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/issues')">意见反馈</PopoverMenuItem> -->
|
<!-- <PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/issues')">意见反馈</PopoverMenuItem> -->
|
||||||
<!-- <PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/blob/master/doc/Q&A.md')">常见问题</PopoverMenuItem> -->
|
<!-- <PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/blob/master/doc/Q&A.md')">常见问题</PopoverMenuItem> -->
|
||||||
<PopoverMenuItem @click="mainMenuVisible = false; hotkeyDrawerVisible = true">快捷操作</PopoverMenuItem>
|
<PopoverMenuItem @click="mainMenuVisible = false; hotkeyDrawerVisible = true">快捷操作</PopoverMenuItem>
|
||||||
|
@ -54,9 +54,9 @@
|
||||||
<div class="arrow-btn"><IconDown class="arrow" /></div>
|
<div class="arrow-btn"><IconDown class="arrow" /></div>
|
||||||
</Popover>
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="menu-item" v-tooltip="'导出'" @click="setDialogForExport('pptx')">
|
<div class="menu-item" v-tooltip="'导出'" @click="setDialogForExport('pptx')">
|
||||||
<IconDownload class="icon" />
|
<IconDownload class="icon" />
|
||||||
</div> -->
|
</div>
|
||||||
<div class="menu-item" v-tooltip="`${userStore.user.parentDeptName}-${userStore.user.nickName}`">
|
<div class="menu-item" v-tooltip="`${userStore.user.parentDeptName}-${userStore.user.nickName}`">
|
||||||
<el-avatar size="small" :src="avatar" />
|
<el-avatar size="small" :src="avatar" />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -95,8 +95,8 @@
|
||||||
style="width: 65%;"
|
style="width: 65%;"
|
||||||
:options="[
|
:options="[
|
||||||
{ label: '主动触发', value: 'click' },
|
{ label: '主动触发', value: 'click' },
|
||||||
// { label: '与上一动画同时', value: 'meantime' },
|
{ label: '与上一动画同时', value: 'meantime' },
|
||||||
// { label: '上一动画之后', value: 'auto' },
|
{ label: '上一动画之后', value: 'auto' },
|
||||||
]"
|
]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -25,12 +25,6 @@
|
||||||
<div style="margin-top: 10px">常规作业</div>
|
<div style="margin-top: 10px">常规作业</div>
|
||||||
</div>
|
</div>
|
||||||
</el-button>
|
</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>
|
</div>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
@ -163,10 +157,6 @@ const type = ref<WorkType[]>([
|
||||||
{
|
{
|
||||||
label: '框架梳理',
|
label: '框架梳理',
|
||||||
value: 'primary'
|
value: 'primary'
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '科学实验',
|
|
||||||
value: 'primary'
|
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
|
@ -88,7 +88,7 @@ import Button from '../../../../components/Button.vue'
|
||||||
import ButtonGroup from '../../../../components/ButtonGroup.vue'
|
import ButtonGroup from '../../../../components/ButtonGroup.vue'
|
||||||
import Popover from '../../../../components/Popover.vue'
|
import Popover from '../../../../components/Popover.vue'
|
||||||
import NumberInput from '../../../../components/NumberInput.vue'
|
import NumberInput from '../../../../components/NumberInput.vue'
|
||||||
import { PPTApi } from '../../../../api'
|
|
||||||
const shapeClipPathOptions = CLIPPATHS
|
const shapeClipPathOptions = CLIPPATHS
|
||||||
const ratioClipOptions = [
|
const ratioClipOptions = [
|
||||||
{
|
{
|
||||||
|
@ -221,14 +221,10 @@ const presetImageClip = (shape: string, ratio = 0) => {
|
||||||
const replaceImage = (files: FileList) => {
|
const replaceImage = (files: FileList) => {
|
||||||
const imageFile = files[0]
|
const imageFile = files[0]
|
||||||
if (!imageFile) return
|
if (!imageFile) return
|
||||||
PPTApi.toRousrceUrl(imageFile).then(data=>{
|
getImageDataURL(imageFile).then(dataURL => {
|
||||||
const props = { src: data }
|
const props = { src: dataURL }
|
||||||
updateImage(props)
|
updateImage(props)
|
||||||
})
|
})
|
||||||
// getImageDataURL(imageFile).then(dataURL => {
|
|
||||||
// const props = { src: dataURL }
|
|
||||||
// updateImage(props)
|
|
||||||
// })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置图片:清除全部样式
|
// 重置图片:清除全部样式
|
||||||
|
|
|
@ -36,8 +36,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="tools-right" :class="{ 'visible': rightToolsVisible }"
|
class="tools-right" :class="{ 'visible': rightToolsVisible }"
|
||||||
@mouseleave="toolTrigger('leave')"
|
@mouseleave="rightToolsVisible = false"
|
||||||
@mouseenter="toolTrigger('enter')"
|
@mouseenter="rightToolsVisible = true"
|
||||||
>
|
>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="tool-btn page-number" @click="slideThumbnailModelVisible = true">幻灯片 {{slideIndex + 1}} / {{slides.length}}</div>
|
<div class="tool-btn page-number" @click="slideThumbnailModelVisible = true">幻灯片 {{slideIndex + 1}} / {{slides.length}}</div>
|
||||||
|
@ -47,14 +47,8 @@
|
||||||
<IconListView class="tool-btn" v-tooltip="'演讲者视图'" @click="changeViewMode('presenter')" />
|
<IconListView class="tool-btn" v-tooltip="'演讲者视图'" @click="changeViewMode('presenter')" />
|
||||||
<IconOffScreenOne class="tool-btn" v-tooltip="'退出全屏'" v-if="fullscreenState" @click="manualExitFullscreen()" />
|
<IconOffScreenOne class="tool-btn" v-tooltip="'退出全屏'" v-if="fullscreenState" @click="manualExitFullscreen()" />
|
||||||
<IconFullScreenOne class="tool-btn" v-tooltip="'进入全屏'" v-else @click="enterFullscreen()" />
|
<IconFullScreenOne class="tool-btn" v-tooltip="'进入全屏'" v-else @click="enterFullscreen()" />
|
||||||
<Hands class="tool-btn" v-if="classcourse" v-tooltip="'课堂点名'" @click="ToolHandle('named')" />
|
<IconPower class="tool-btn" v-tooltip="'结束放映'" @click="exitScreening()" />
|
||||||
<Share class="tool-btn" v-if="classcourse" v-tooltip="'分享'" @click="ShareCode()" />
|
<IconPower class="tool-btn close" v-if="chat.groupid" v-tooltip="'结束课堂'" @click="exitCourse()" />
|
||||||
<IconPower class="tool-btn" v-if="!classcourse" v-tooltip="'结束放映'" @click="exitScreening()" />
|
|
||||||
<IconPower class="tool-btn" v-else v-tooltip="'结束课堂'" @click="exitCourse()" size="30" fill="#d0021b" strokeLinecap="butt" />
|
|
||||||
</div>
|
|
||||||
<div :class="['tools-icon',{opacity:iconHide}]" @click.stop="toolTrigger('icon')">
|
|
||||||
<circle-double-down v-if="rightToolsVisible" theme="outline" size="30" fill="#409EFF"/>
|
|
||||||
<circle-double-up v-else="!rightToolsVisible" theme="outline" size="30" fill="#E6A23C"/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -77,8 +71,6 @@ import WritingBoardTool from './WritingBoardTool.vue'
|
||||||
import CountdownTimer from './CountdownTimer.vue'
|
import CountdownTimer from './CountdownTimer.vue'
|
||||||
import emitter from '@/utils/mitt';
|
import emitter from '@/utils/mitt';
|
||||||
import Chat from '../../api/chat' // 聊天
|
import Chat from '../../api/chat' // 聊天
|
||||||
import { CircleDoubleDown, CircleDoubleUp, Share, Hands } from '@icon-park/vue-next' // icon-park 图标库
|
|
||||||
import { ShareCode, ToolHandle } from '@/utils/ppt' // ppt相关
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
changeViewMode: (mode: 'base' | 'presenter') => void
|
changeViewMode: (mode: 'base' | 'presenter') => void
|
||||||
|
@ -105,22 +97,18 @@ const {
|
||||||
execPrev,
|
execPrev,
|
||||||
execNext,
|
execNext,
|
||||||
animationIndex,
|
animationIndex,
|
||||||
turning,
|
|
||||||
} = useExecPlay()
|
} = useExecPlay()
|
||||||
const { slideWidth, slideHeight } = useSlideSize()
|
const { slideWidth, slideHeight } = useSlideSize()
|
||||||
const { exitScreening } = useScreening()
|
const { exitScreening } = useScreening()
|
||||||
const { fullscreenState, manualExitFullscreen } = useFullscreen()
|
const { fullscreenState, manualExitFullscreen } = useFullscreen()
|
||||||
const chat:any = Chat() // 聊天室
|
const chat:any = Chat() // 聊天室
|
||||||
|
|
||||||
const screenStore =useScreenStore()
|
|
||||||
const rightToolsVisible = ref(false)
|
const rightToolsVisible = ref(false)
|
||||||
const writingBoardToolVisible = ref(false)
|
const writingBoardToolVisible = ref(false)
|
||||||
const timerlVisible = ref(false)
|
const timerlVisible = ref(false)
|
||||||
const slideThumbnailModelVisible = ref(false)
|
const slideThumbnailModelVisible = ref(false)
|
||||||
const laserPen = ref(false)
|
const laserPen = ref(false)
|
||||||
const timer = ref(0) // 记录操作时间
|
const screenStore =useScreenStore()
|
||||||
const iconHide = ref(false) // 工具栏图标是否显示
|
|
||||||
const timerId = ref(null) // 定时器id
|
|
||||||
const contextmenus = (): ContextmenuItem[] => {
|
const contextmenus = (): ContextmenuItem[] => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
@ -202,31 +190,7 @@ 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 () => {
|
const exitCourse = async () => {
|
||||||
// console.log('下课', chat)
|
// console.log('下课', chat)
|
||||||
|
@ -289,18 +253,6 @@ const exitCourse = async () => {
|
||||||
top: -66px;
|
top: -66px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tools-icon{
|
|
||||||
position: absolute;
|
|
||||||
right: 8px;
|
|
||||||
top: -35px;
|
|
||||||
z-index: 1;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: opacity $transitionDelay;
|
|
||||||
&.opacity{
|
|
||||||
opacity: .35;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
@ -10,13 +10,9 @@
|
||||||
<IconOffScreenOne class="tool-icon" v-else />
|
<IconOffScreenOne class="tool-icon" v-else />
|
||||||
<span>{{ fullscreenState ? '退出全屏' : '全屏' }}</span>
|
<span>{{ fullscreenState ? '退出全屏' : '全屏' }}</span>
|
||||||
</div>
|
</div>
|
||||||
<template v-if="classcourse">
|
|
||||||
<div class="tool-btn" @click="ToolHandle('named')"><Hands class="tool-icon" /><span>课堂点名</span></div>
|
|
||||||
<div class="tool-btn" @click="ShareCode()"><Share class="tool-icon" /><span>分享</span></div>
|
|
||||||
</template>
|
|
||||||
<Divider class="divider" />
|
<Divider class="divider" />
|
||||||
<div class="tool-btn" v-if="!classcourse" @click="exitScreening()"><IconPower class="tool-icon" /><span>结束放映</span></div>
|
<div class="tool-btn" @click="exitScreening()"><IconPower class="tool-icon" /><span>结束放映</span></div>
|
||||||
<div class="tool-btn" v-else @click="exitCourse()" size="30" fill="#d0021b" strokeLinecap="butt"><IconPower class="tool-icon" /><span>结束课堂</span></div>
|
<div class="tool-btn close" @click="exitCourse()" v-if="chat.groupid"><IconPower class="tool-icon" /><span>结束课堂</span></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
@ -82,7 +78,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Share, Hands } from '@icon-park/vue-next' // icon-park 图标库
|
|
||||||
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { useSlidesStore, useClasscourseStore } from '../../store'
|
import { useSlidesStore, useClasscourseStore } from '../../store'
|
||||||
|
@ -102,7 +97,6 @@ import CountdownTimer from './CountdownTimer.vue'
|
||||||
import Divider from '../../components/Divider.vue'
|
import Divider from '../../components/Divider.vue'
|
||||||
import emitter from '@/utils/mitt';
|
import emitter from '@/utils/mitt';
|
||||||
import Chat from '../../api/chat' // 聊天
|
import Chat from '../../api/chat' // 聊天
|
||||||
import { ShareCode, ToolHandle } from '@/utils/ppt' // ppt相关
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
changeViewMode: (mode: 'base' | 'presenter') => void
|
changeViewMode: (mode: 'base' | 'presenter') => void
|
||||||
|
@ -131,7 +125,7 @@ const { slideWidth, slideHeight } = useSlideSize(slideListWrapRef)
|
||||||
const { exitScreening } = useScreening()
|
const { exitScreening } = useScreening()
|
||||||
const { slidesLoadLimit } = useLoadSlides()
|
const { slidesLoadLimit } = useLoadSlides()
|
||||||
const { fullscreenState, manualExitFullscreen } = useFullscreen()
|
const { fullscreenState, manualExitFullscreen } = useFullscreen()
|
||||||
const chatApi:any = Chat() // 聊天室
|
const chat:any = Chat() // 聊天室
|
||||||
|
|
||||||
const remarkFontSize = ref(16)
|
const remarkFontSize = ref(16)
|
||||||
const currentSlideRemark = computed(() => {
|
const currentSlideRemark = computed(() => {
|
||||||
|
@ -140,20 +134,15 @@ const currentSlideRemark = computed(() => {
|
||||||
|
|
||||||
// 切换到指定的幻灯片
|
// 切换到指定的幻灯片
|
||||||
const turnSlideTo = (index: number, e: PointerEvent) => {
|
const turnSlideTo = (index: number, e: PointerEvent) => {
|
||||||
const preInd = slideIndex.value
|
// 课堂信息存在时,不允许翻页
|
||||||
|
console.log('课堂信息', classcourse, index)
|
||||||
|
if (!!classcourse.value) return
|
||||||
turnSlideToIndex(index)
|
turnSlideToIndex(index)
|
||||||
if (!!classcourse.value) {// 上课中
|
|
||||||
if (preInd == index) return
|
|
||||||
const animationSteps = 0
|
|
||||||
const animation = index > preInd?'Nextsteps':'Previoustep'
|
|
||||||
const msg = { current:index, animation, animationSteps}
|
|
||||||
chatApi.slideFlapping(msg)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// 下课
|
// 下课
|
||||||
const exitCourse = async () => {
|
const exitCourse = async () => {
|
||||||
// console.log('下课', chat)
|
// console.log('下课', chat)
|
||||||
await chatApi.exitCourse() // 下课消息
|
await chat.exitCourse() // 下课消息
|
||||||
exitScreening() // 结束放映
|
exitScreening() // 结束放映
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,9 +28,8 @@ export default (isLoader?: boolean = true) => {
|
||||||
|
|
||||||
// 执行元素动画 isAsync 为 true 时,异步执行,否则同步执行
|
// 执行元素动画 isAsync 为 true 时,异步执行,否则同步执行
|
||||||
const runAnimation = (isAsync: boolean) => {
|
const runAnimation = (isAsync: boolean) => {
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
// 正在执行动画时,禁止其他新的动画开始
|
// 正在执行动画时,禁止其他新的动画开始
|
||||||
if (inAnimation.value && !isAsync) return resolve()
|
if (inAnimation.value && !isAsync) return
|
||||||
|
|
||||||
const { animations, autoNext } = formatedAnimations.value[animationIndex.value]
|
const { animations, autoNext } = formatedAnimations.value[animationIndex.value]
|
||||||
animationIndex.value += 1
|
animationIndex.value += 1
|
||||||
|
@ -61,7 +60,7 @@ export default (isLoader?: boolean = true) => {
|
||||||
elRef.classList.add(animationName, `${ANIMATION_CLASS_PREFIX}animated`)
|
elRef.classList.add(animationName, `${ANIMATION_CLASS_PREFIX}animated`)
|
||||||
|
|
||||||
// 执行动画结束,将“退场”以外的动画状态清除
|
// 执行动画结束,将“退场”以外的动画状态清除
|
||||||
const handleAnimationEnd = async() => {
|
const handleAnimationEnd = () => {
|
||||||
if (animation.type !== 'out') {
|
if (animation.type !== 'out') {
|
||||||
elRef.style.removeProperty('--animate-duration')
|
elRef.style.removeProperty('--animate-duration')
|
||||||
elRef.classList.remove(animationName, `${ANIMATION_CLASS_PREFIX}animated`)
|
elRef.classList.remove(animationName, `${ANIMATION_CLASS_PREFIX}animated`)
|
||||||
|
@ -71,13 +70,11 @@ export default (isLoader?: boolean = true) => {
|
||||||
endAnimationCount += 1
|
endAnimationCount += 1
|
||||||
if (endAnimationCount === animations.length) {
|
if (endAnimationCount === animations.length) {
|
||||||
inAnimation.value = false
|
inAnimation.value = false
|
||||||
if (autoNext) await runAnimation()
|
if (autoNext) runAnimation()
|
||||||
resolve() // 执行完成
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elRef.addEventListener('animationend', handleAnimationEnd, { once: true })
|
elRef.addEventListener('animationend', handleAnimationEnd, { once: true })
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if (isLoader) { // 加载相关钩子
|
if (isLoader) { // 加载相关钩子
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
@ -150,7 +147,7 @@ export default (isLoader?: boolean = true) => {
|
||||||
}
|
}
|
||||||
inAnimation.value = false
|
inAnimation.value = false
|
||||||
}
|
}
|
||||||
const execNext = async(isAsync: boolean) => {
|
const execNext = (isAsync: boolean) => {
|
||||||
if (formatedAnimations.value.length && animationIndex.value < formatedAnimations.value.length) {
|
if (formatedAnimations.value.length && animationIndex.value < formatedAnimations.value.length) {
|
||||||
runAnimation(isAsync)
|
runAnimation(isAsync)
|
||||||
}
|
}
|
||||||
|
@ -219,17 +216,9 @@ export default (isLoader?: boolean = true) => {
|
||||||
// 向上翻页/向下翻页
|
// 向上翻页/向下翻页
|
||||||
const turning = async (e, type) => {
|
const turning = async (e, type) => {
|
||||||
e.preventDefault() // 阻止默认事件
|
e.preventDefault() // 阻止默认事件
|
||||||
window.scrollTo(0, 0) // 滚动到顶部
|
if (type === 'prev') execPrev()
|
||||||
const isCourse = !!classcourseStore.classcourse
|
else if (type === 'next') execNext()
|
||||||
if (type === 'prev') {
|
if (classcourseStore.classcourse) { // 上课中
|
||||||
if (!isCourse) execPrev() // 上一步
|
|
||||||
else { // 上课状态: 上一步 动作变成 上一页
|
|
||||||
const current = slideIndex.value
|
|
||||||
if (current <= 0) return throttleMassage('已经是第一页了')
|
|
||||||
turnSlideToIndex(current - 1) // 翻页: 上一页
|
|
||||||
}
|
|
||||||
} else if (type === 'next') execNext()
|
|
||||||
if (isCourse) { // 上课中
|
|
||||||
const current = slideIndex.value
|
const current = slideIndex.value
|
||||||
const animationSteps = animationIndex.value
|
const animationSteps = animationIndex.value
|
||||||
const animation = type == 'next'?'Nextsteps':'Previoustep'
|
const animation = type == 'next'?'Nextsteps':'Previoustep'
|
||||||
|
@ -296,6 +285,5 @@ export default (isLoader?: boolean = true) => {
|
||||||
execPrev,
|
execPrev,
|
||||||
execNext,
|
execNext,
|
||||||
animationIndex,
|
animationIndex,
|
||||||
turning,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,22 +4,13 @@
|
||||||
<PresenterView :changeViewMode="changeViewMode" v-else-if="viewMode === 'presenter'" />
|
<PresenterView :changeViewMode="changeViewMode" v-else-if="viewMode === 'presenter'" />
|
||||||
<!-- 点赞组件 -->
|
<!-- 点赞组件 -->
|
||||||
<upvote-vue ref="upvoteRef" type="2"></upvote-vue>
|
<upvote-vue ref="upvoteRef" type="2"></upvote-vue>
|
||||||
|
<!-- <div style="z-index: 999;position: absolute;top:10px">
|
||||||
<!-- 推图上屏弹窗 -->
|
</div> -->
|
||||||
<el-dialog
|
|
||||||
v-model="dialogVisible"
|
|
||||||
:fullscreen="true"
|
|
||||||
class="gridPicRefdiv"
|
|
||||||
style="overflow: hidden;"
|
|
||||||
:show-close="false"
|
|
||||||
>
|
|
||||||
<grid-pic ref="gridPicRef" style="height:100%;" @clear="clearchidrenPic"></grid-pic>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, onUnmounted, ref , nextTick} from 'vue'
|
import { onMounted, onUnmounted, ref } from 'vue'
|
||||||
import { KEYS } from '../../configs/hotkey'
|
import { KEYS } from '../../configs/hotkey'
|
||||||
import useScreening from '../../hooks/useScreening'
|
import useScreening from '../../hooks/useScreening'
|
||||||
import hooksUpvote from '../../api/upvote' // 点赞-工具
|
import hooksUpvote from '../../api/upvote' // 点赞-工具
|
||||||
|
@ -27,13 +18,9 @@ import hooksUpvote from '../../api/upvote' // 点赞-工具
|
||||||
import BaseView from './BaseView.vue'
|
import BaseView from './BaseView.vue'
|
||||||
import PresenterView from './PresenterView.vue'
|
import PresenterView from './PresenterView.vue'
|
||||||
import upvoteVue from '@/views/tool/components/upvote.vue' // 点赞-子组件
|
import upvoteVue from '@/views/tool/components/upvote.vue' // 点赞-子组件
|
||||||
import gridPic from '@/components/grid-pic/index.vue' // 推图上屏弹子组件
|
|
||||||
|
|
||||||
import emitter from '@/utils/mitt' //mitt 事件总线
|
|
||||||
|
|
||||||
const viewMode = ref<'base' | 'presenter'>('base')
|
const viewMode = ref<'base' | 'presenter'>('base')
|
||||||
const dialogVisible = ref(false)
|
|
||||||
const gridPicRef:any= ref(null)
|
|
||||||
const changeViewMode = (mode: 'base' | 'presenter') => {
|
const changeViewMode = (mode: 'base' | 'presenter') => {
|
||||||
viewMode.value = mode
|
viewMode.value = mode
|
||||||
}
|
}
|
||||||
|
@ -48,23 +35,6 @@ const keydownListener = (e: KeyboardEvent) => {
|
||||||
if (key === KEYS.ESC) exitScreening()
|
if (key === KEYS.ESC) exitScreening()
|
||||||
}
|
}
|
||||||
|
|
||||||
const clearchidrenPic= ()=> {
|
|
||||||
dialogVisible.value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 开启推图上屏幕
|
|
||||||
emitter.on('opengridPic', async (data:object)=> {
|
|
||||||
if(gridPicRef.value) gridPicRef.value.clearPic()
|
|
||||||
dialogVisible.value = true
|
|
||||||
await nextTick();
|
|
||||||
gridPicRef.value.addPic(data.arr)
|
|
||||||
});
|
|
||||||
// 关闭推图
|
|
||||||
emitter.on('closegridPic', ()=> {
|
|
||||||
if(!gridPicRef.value) return
|
|
||||||
gridPicRef.value.clearPic()
|
|
||||||
dialogVisible.value = false
|
|
||||||
});
|
|
||||||
onMounted(() => document.addEventListener('keydown', keydownListener))
|
onMounted(() => document.addEventListener('keydown', keydownListener))
|
||||||
onUnmounted(() => document.removeEventListener('keydown', keydownListener))
|
onUnmounted(() => document.removeEventListener('keydown', keydownListener))
|
||||||
</script>
|
</script>
|
||||||
|
@ -76,8 +46,4 @@ onUnmounted(() => document.removeEventListener('keydown', keydownListener))
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.gridPicRefdiv .el-dialog__body){
|
|
||||||
height: 100% !important;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
|
@ -15,7 +15,7 @@ const size = ref('default')
|
||||||
font-family: Avenir, Helvetica, Arial, sans-serif;
|
font-family: Avenir, Helvetica, Arial, sans-serif;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
/* text-align: center; */
|
text-align: center;
|
||||||
color: #2c3e50;
|
color: #2c3e50;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ import axios from 'axios'
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
import { getToken } from "@/utils/auth";
|
import { getToken } from "@/utils/auth";
|
||||||
|
|
||||||
let rootPath = import.meta.env.VITE_APP_ENV === 'production' ? 'https://ai.ysaix.com:7864' : ''
|
|
||||||
|
|
||||||
// 文生图片
|
// 文生图片
|
||||||
export function convertTextToPicture(data) {
|
export function convertTextToPicture(data) {
|
||||||
return axios({
|
return axios({
|
||||||
|
@ -44,7 +42,7 @@ export function getPicture(data) {
|
||||||
// 大模型对话生成prompt模板
|
// 大模型对话生成prompt模板
|
||||||
export function chattoprompt(dataset_id,prompt) {
|
export function chattoprompt(dataset_id,prompt) {
|
||||||
return axios({
|
return axios({
|
||||||
url: rootPath + '/api/v1/parse/docs',
|
url: '/api/v1/parse/docs',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': 'Bearer ragflow-IwMDI1MGU2YTU3NjExZWZiNWEzMDI0Mm',
|
'Authorization': 'Bearer ragflow-IwMDI1MGU2YTU3NjExZWZiNWEzMDI0Mm',
|
||||||
|
@ -70,7 +68,7 @@ export function textSensitiveWord(data) {
|
||||||
// 图片上传资源库
|
// 图片上传资源库
|
||||||
export function uploadPicture(data) {
|
export function uploadPicture(data) {
|
||||||
return axios({
|
return axios({
|
||||||
url: import.meta.env.VITE_APP_BASE_API + '/smarttalk/file/upload',
|
url: '/dev-api/smarttalk/file/upload',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': '*/*',
|
'Accept': '*/*',
|
||||||
|
|
|
@ -71,14 +71,6 @@ export function updateClassworkeval(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateClassworkevalList(data) {
|
|
||||||
return request({
|
|
||||||
url: '/education/classworkeval/updateList',
|
|
||||||
method: 'put',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改classworkdata
|
// 修改classworkdata
|
||||||
export function updateClassworkdata(data) {
|
export function updateClassworkdata(data) {
|
||||||
return request({
|
return request({
|
||||||
|
@ -88,15 +80,6 @@ export function updateClassworkdata(data) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 批阅后, 待所有学生都批改完成后自动结束当前作业为[已完成]
|
|
||||||
export function updateClassWorkDataAutoFinish(data) {
|
|
||||||
return request({
|
|
||||||
url: '/education/classworkdata/updAutoFinish',
|
|
||||||
method: 'put',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改classwork
|
// 修改classwork
|
||||||
export function updateClasswork(data) {
|
export function updateClasswork(data) {
|
||||||
return request({
|
return request({
|
||||||
|
|
|
@ -136,17 +136,3 @@ export function getJYPath(url,config) {
|
||||||
params: config.params
|
params: config.params
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @desc: 百度识图转发
|
|
||||||
* @return: {*}
|
|
||||||
* @param {*} data
|
|
||||||
*/
|
|
||||||
export function getOcrContent(data) {
|
|
||||||
return request({
|
|
||||||
url: '/ocr/exam',
|
|
||||||
method: 'post',
|
|
||||||
data: data
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -79,19 +79,3 @@ export const getModelInfo = (params) => {
|
||||||
params
|
params
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 上传tts语音
|
|
||||||
export const aitts = (data) => {
|
|
||||||
return request({
|
|
||||||
url: '/aitts/createTts',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 语音关联课
|
|
||||||
export const addFileToSC = (params) => {
|
|
||||||
return request({
|
|
||||||
url: '/smarttalk/file/addFileToSC',
|
|
||||||
method: 'post',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -118,36 +118,4 @@ export function docList(params) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存教学大纲
|
|
||||||
export function addSyllabus(data) {
|
|
||||||
return request({
|
|
||||||
url: '/education/generate',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取保存的大纲列表
|
|
||||||
export function syllabusList(params) {
|
|
||||||
return request({
|
|
||||||
url: '/education/generate/list',
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除大纲
|
|
||||||
export function removeSyllabus(id) {
|
|
||||||
return request({
|
|
||||||
url: '/education/generate/' + id,
|
|
||||||
method: 'delete',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function editSyllabus(data) {
|
|
||||||
return request({
|
|
||||||
url: '/education/generate',
|
|
||||||
method: 'put',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
@ -102,28 +102,4 @@ export function setPaging(data) {
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* 获取分享码(邀请码)
|
|
||||||
* @param {*} id 课堂id
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export function getShareCode(id) {
|
|
||||||
return request({
|
|
||||||
url: '/education/classcourse/refresh/code',
|
|
||||||
method: 'post',
|
|
||||||
data: { id }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 课堂点名
|
|
||||||
* @param {*} timgroupid 群id
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export function rollCall(timgroupid) {
|
|
||||||
return request({
|
|
||||||
url: '/education/classcourse/roll/call',
|
|
||||||
method: 'post',
|
|
||||||
data: { timgroupid }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 4723712 */
|
font-family: "iconfont"; /* Project id 4723712 */
|
||||||
src: url('iconfont.woff2?t=1735483000546') format('woff2'),
|
src: url('iconfont.woff2?t=1734337029245') format('woff2'),
|
||||||
url('iconfont.woff?t=1735483000546') format('woff'),
|
url('iconfont.woff?t=1734337029245') format('woff'),
|
||||||
url('iconfont.ttf?t=1735483000546') format('truetype');
|
url('iconfont.ttf?t=1734337029245') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
|
@ -13,10 +13,6 @@
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-chuangzuo:before {
|
|
||||||
content: "\e6cc";
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-yinle:before {
|
.icon-yinle:before {
|
||||||
content: "\e6c9";
|
content: "\e6c9";
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,6 @@
|
||||||
"css_prefix_text": "icon-",
|
"css_prefix_text": "icon-",
|
||||||
"description": "",
|
"description": "",
|
||||||
"glyphs": [
|
"glyphs": [
|
||||||
{
|
|
||||||
"icon_id": "39170417",
|
|
||||||
"name": "创作",
|
|
||||||
"font_class": "chuangzuo",
|
|
||||||
"unicode": "e6cc",
|
|
||||||
"unicode_decimal": 59084
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"icon_id": "11819186",
|
"icon_id": "11819186",
|
||||||
"name": "音乐",
|
"name": "音乐",
|
||||||
|
|
Before Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 520 KiB |
|
@ -1,240 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div style="height: auto; display: flex">
|
|
||||||
<div style="flex: 1">
|
|
||||||
<div class="audio-container">
|
|
||||||
<aiAudio
|
|
||||||
@saveClick="saveClick"
|
|
||||||
ref="audioRef"
|
|
||||||
:audioSrc="audioSrc"
|
|
||||||
@auditionClick="auditionClick"
|
|
||||||
></aiAudio>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="background: #fff; height: 85vh; min-width: 364px; margin-left: 20px;overflow: hidden;">
|
|
||||||
<div style="padding: 0 20px; height: 100%;">
|
|
||||||
<el-tabs v-model="activeTab" class="prepare-tabs">
|
|
||||||
<el-tab-pane label="素材" name="素材">
|
|
||||||
<div class="prepare-body-header">
|
|
||||||
<div>
|
|
||||||
<label style="font-size: 15px"
|
|
||||||
>共{{
|
|
||||||
currentFileList.filter(
|
|
||||||
(ite) => ite.fileFlag !== 'apt' && ite.fileFlag !== '课件'
|
|
||||||
).length
|
|
||||||
}}个文件</label
|
|
||||||
>
|
|
||||||
<!-- <el-popover placement="top-start" :width="250" trigger="hover">
|
|
||||||
<template #default>
|
|
||||||
<div>
|
|
||||||
<el-button
|
|
||||||
v-if="lastAsyncAllTime"
|
|
||||||
type="success"
|
|
||||||
size="small"
|
|
||||||
:icon="Check"
|
|
||||||
circle
|
|
||||||
/>
|
|
||||||
{{ lastAsyncAllTime ? toTimeText(lastAsyncAllTime) + '同步成功' : '' }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #reference>
|
|
||||||
<el-button size="small" text @click="asyncAllFile">
|
|
||||||
<el-icon v-loading="asyncAllFileVisiable">
|
|
||||||
<Refresh />
|
|
||||||
</el-icon>
|
|
||||||
{{ asyncAllFileVisiable ? '同步中' : '云同步' }}
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-popover> -->
|
|
||||||
<!-- <el-button size="small" @click="isDialogOpen = true">上传资料</el-button>
|
|
||||||
<el-button size="small" @click="reloadFiles">资源重载</el-button> -->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-checkbox-group
|
|
||||||
v-model="checkFileList"
|
|
||||||
class="prepare-body-main"
|
|
||||||
:style="{ 'margin-bottom': checkFileList.length > 0 ? '40px' : '0' }"
|
|
||||||
>
|
|
||||||
<file-list-item
|
|
||||||
v-for="(item, index) in currentSCFileList"
|
|
||||||
:key="index"
|
|
||||||
:item="item"
|
|
||||||
:index="index"
|
|
||||||
@on-delete="deleteSuccess"
|
|
||||||
>
|
|
||||||
</file-list-item>
|
|
||||||
</el-checkbox-group>
|
|
||||||
</el-tab-pane>
|
|
||||||
</el-tabs>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { useRoute } from 'vue-router'
|
|
||||||
import { getSmarttalkPage, moveSmarttalk, creatAPT } from '@/api/file'
|
|
||||||
import FileListItem from '@/views/prepare/container/file-list-item.vue'
|
|
||||||
import { parseCataByNode, creatPPT, asyncLocalFile, removeLocalFiles } from '@/utils/talkFile'
|
|
||||||
import { uploadPicture } from '@/api/aiGeneratedImage/index.js'
|
|
||||||
import { aitts, addFileToSC } from '@/api/file/index.js'
|
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
FileListItem
|
|
||||||
},
|
|
||||||
props: {},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
activeTab: '素材',
|
|
||||||
currentFileList: [],
|
|
||||||
uploadData: {},
|
|
||||||
checkFileList: [],
|
|
||||||
isLoading: false,
|
|
||||||
lastAsyncAllTime: '',
|
|
||||||
audioSrc: null,
|
|
||||||
filedata: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
isCheckAll() {
|
|
||||||
return (
|
|
||||||
this.checkFileList.length > 0 && this.checkFileList.length === this.currentSCFileList.length
|
|
||||||
)
|
|
||||||
},
|
|
||||||
currentSCFileList() {
|
|
||||||
// return this.currentFileList.filter((item) => item.fileFlag !== 'apt' && item.fileFlag !== '课件')
|
|
||||||
return this.currentFileList.filter((item) => !['apt', 'aippt'].includes(item.fileFlag))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
deleteSuccess(item) {
|
|
||||||
this.asyncAllFile() // 刷新资源列表
|
|
||||||
},
|
|
||||||
auditionClick(requestData) {
|
|
||||||
this.$refs.audioRef.startLoading = true
|
|
||||||
aitts(requestData)
|
|
||||||
.then((res) => {
|
|
||||||
console.log(res)
|
|
||||||
if (res.code == 200) {
|
|
||||||
this.audioSrc = res.data.fullUrl
|
|
||||||
this.filedata = res.data
|
|
||||||
this.$refs.audioRef.startLoading = false
|
|
||||||
} else {
|
|
||||||
this.$message.error(res.msg)
|
|
||||||
this.$refs.audioRef.startLoading = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
this.$refs.audioRef.startLoading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
saveClick(requestData) {
|
|
||||||
this.$refs.audioRef.saveLoading = true
|
|
||||||
aitts(requestData)
|
|
||||||
.then((res) => {
|
|
||||||
if (res.code == 200) {
|
|
||||||
this.filedata = res.data
|
|
||||||
const saveObj = {
|
|
||||||
textbookId: this.uploadData.textbookId,
|
|
||||||
levelFirstId: this.uploadData.levelFirstId,
|
|
||||||
levelSecondId: this.uploadData.levelSecondId,
|
|
||||||
fileSource: this.uploadData.fileSource,
|
|
||||||
fileRoot: this.uploadData.fileRoot,
|
|
||||||
fileShowName: this.filedata.uploadTime+'音频.' + this.filedata.fileSuffix,
|
|
||||||
fileFlag: '素材',
|
|
||||||
fileId: this.filedata.id
|
|
||||||
}
|
|
||||||
addFileToSC(saveObj)
|
|
||||||
.then((resone) => {
|
|
||||||
this.$message.success('上传成功')
|
|
||||||
this.asyncAllFile()
|
|
||||||
this.$refs.audioRef.saveLoading = false
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
this.$refs.audioRef.saveLoading = false
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.$message.error(res.msg)
|
|
||||||
this.$refs.audioRef.saveLoading = false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.log(err)
|
|
||||||
this.$refs.audioRef.saveLoading = false
|
|
||||||
})
|
|
||||||
|
|
||||||
},
|
|
||||||
asyncAllFile() {
|
|
||||||
this.isLoading = true
|
|
||||||
return getSmarttalkPage({
|
|
||||||
...this.uploadData,
|
|
||||||
orderByColumn: 'createTime',
|
|
||||||
isAsc: 'desc',
|
|
||||||
pageSize: 500
|
|
||||||
})
|
|
||||||
.then(async (res) => {
|
|
||||||
this.currentFileList = [...res.rows].filter((item) => item.fileType === 'audio/wav')
|
|
||||||
this.isLoading = false
|
|
||||||
this.lastAsyncAllTime = new Date()
|
|
||||||
localStorage.setItem('lastAsyncAllTime', this.lastAsyncAllTime)
|
|
||||||
this.asyncAllFileVisiable = true
|
|
||||||
for (let i = 0; i < this.currentFileList.length; i++) {
|
|
||||||
let item = this.currentFileList[i]
|
|
||||||
if (item.fileFlag === 'apt') continue
|
|
||||||
if (item.fileFlag === 'aippt') continue
|
|
||||||
await asyncLocalFile(item)
|
|
||||||
}
|
|
||||||
this.asyncAllFileVisiable = false
|
|
||||||
return Promise.resolve()
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
this.isLoading = false
|
|
||||||
return Promise.resolve()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
onMoveSingleFile(item) {
|
|
||||||
this.moveFile = [item]
|
|
||||||
this.isMoveDialogOpen = true
|
|
||||||
},
|
|
||||||
deleteTalk(item) {
|
|
||||||
let index = this.currentFileList.indexOf(item)
|
|
||||||
this.currentFileList.splice(index, 1)
|
|
||||||
},
|
|
||||||
// 打开布置作业窗口
|
|
||||||
openSet(row) {
|
|
||||||
// 布置推送:row 这里是单个,转为list
|
|
||||||
this.rows = [row]
|
|
||||||
this.setDialog = true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
const route = useRoute()
|
|
||||||
this.uploadData = route.query
|
|
||||||
// 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.asyncAllFile() // 刷新资源列表
|
|
||||||
},
|
|
||||||
beforeDestroy() {}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped scss>
|
|
||||||
:deep(.prepare-item-info-title) {
|
|
||||||
line-height: 30px;
|
|
||||||
}
|
|
||||||
.prepare-body-main{
|
|
||||||
overflow-y: auto;
|
|
||||||
height: 74vh;
|
|
||||||
}
|
|
||||||
:deep(.audio-container .content-main){
|
|
||||||
height: 85vh !important ;
|
|
||||||
}
|
|
||||||
:deep(.audio-container .content-main div:nth-of-type(1)){
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -10,23 +10,8 @@
|
||||||
<el-tree :data="treeData" accordion :props="defaultProps" node-key="id"
|
<el-tree :data="treeData" accordion :props="defaultProps" node-key="id"
|
||||||
:default-expanded-keys="defaultExpandedKeys" :current-node-key="curNode.data.id" highlight-current
|
:default-expanded-keys="defaultExpandedKeys" :current-node-key="curNode.data.id" highlight-current
|
||||||
@node-click="handleNodeClick">
|
@node-click="handleNodeClick">
|
||||||
<template #default="{ node, data }">
|
<template #default="{ node }">
|
||||||
<div v-if="props.isClassTask && (data.bookId == '' || data.bookId == '0')" class="tree-label-wrap">
|
<span :title="node.label" class="tree-label">{{ node.label }}</span>
|
||||||
<el-tooltip effect="light" placement="right" >
|
|
||||||
<template #content> {{ node.label }}<br /><span style="color: red;">-该单元章节无自主试题-</span> </template>
|
|
||||||
<div class="tree-label" style="color: #A5B3CA" >
|
|
||||||
{{ node.label }}
|
|
||||||
</div>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
<div v-else class="tree-label-wrap">
|
|
||||||
<el-tooltip effect="light" placement="right" >
|
|
||||||
<template #content> {{ node.label }}</template>
|
|
||||||
<div class="tree-label">
|
|
||||||
{{ node.label }}
|
|
||||||
</div>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</el-tree>
|
</el-tree>
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,9 +29,8 @@
|
||||||
|
|
||||||
<div class="textbook-container">
|
<div class="textbook-container">
|
||||||
<el-scrollbar height="450px">
|
<el-scrollbar height="450px">
|
||||||
<div
|
<div class="textbook-item flex" v-for="item in subjectList" :class="curBook.data.id == item.id ? 'active-item' : ''"
|
||||||
v-for="item in subjectList" :key="item.id" class="textbook-item flex"
|
:key="item.id" @click="changeBook(item)">
|
||||||
:class="curBook.data.id == item.id ? 'active-item' : ''" @click="changeBook(item)">
|
|
||||||
<img v-if="item.avartar" :src="item.avartar.indexOf('http') === 0 ? item.avartar : BaseUrl + item.avartar" class="textbook-img" alt="">
|
<img v-if="item.avartar" :src="item.avartar.indexOf('http') === 0 ? item.avartar : BaseUrl + item.avartar" class="textbook-img" alt="">
|
||||||
<div v-else class="textbook-img">
|
<div v-else class="textbook-img">
|
||||||
<i class="iconfont icon-jiaocaixuanze" style="font-size: 40px;"></i>
|
<i class="iconfont icon-jiaocaixuanze" style="font-size: 40px;"></i>
|
||||||
|
@ -67,13 +51,6 @@ import useUserStore from '@/store/modules/user'
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
|
|
||||||
const BaseUrl = import.meta.env.VITE_APP_BUILD_BASE_PATH
|
const BaseUrl = import.meta.env.VITE_APP_BUILD_BASE_PATH
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
// 是否为[教学大模型]中使用(作业设计中对应该章节是否存在第三方试题)
|
|
||||||
isClassTask: {
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
})
|
|
||||||
const isStadium = () => {
|
const isStadium = () => {
|
||||||
let roles = userStore.user.roles
|
let roles = userStore.user.roles
|
||||||
return roles.some(item => item.roleKey === 'stadium')
|
return roles.some(item => item.roleKey === 'stadium')
|
||||||
|
@ -201,7 +178,6 @@ const handleNodeClick = (data) => {
|
||||||
sessionStore.set('subject.curNode', nodeData)
|
sessionStore.set('subject.curNode', nodeData)
|
||||||
emit('nodeClick', curData)
|
emit('nodeClick', curData)
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted( async () => {
|
onMounted( async () => {
|
||||||
treeLoading.value = true
|
treeLoading.value = true
|
||||||
try{
|
try{
|
||||||
|
@ -341,8 +317,7 @@ onMounted( async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tree-label-wrap, .tree-label {
|
.tree-label {
|
||||||
max-width: 100%;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
|
|
@ -26,7 +26,6 @@ const getFileTypeIcon = () => {
|
||||||
doc: 'icon-word',
|
doc: 'icon-word',
|
||||||
docx: 'icon-word',
|
docx: 'icon-word',
|
||||||
mp4: 'icon-video',
|
mp4: 'icon-video',
|
||||||
wav: 'icon-mp',
|
|
||||||
mov: 'icon-mov',
|
mov: 'icon-mov',
|
||||||
avi: 'icon-avi',
|
avi: 'icon-avi',
|
||||||
jpeg: 'icon-jpeg',
|
jpeg: 'icon-jpeg',
|
||||||
|
|
|
@ -1,42 +1,24 @@
|
||||||
<!--
|
|
||||||
依赖: vuedraggable、v-viewer
|
|
||||||
属性: showToolbar //是否显示工具栏 默认:false
|
|
||||||
工具栏 添加图片:默认6个测试图片,不输入框添加则添加默认,输入图片链接,展示图片链接的图片
|
|
||||||
清空图片:清空图片
|
|
||||||
事件: clear 清空时触发
|
|
||||||
outIndex 超出九个图片时触发
|
|
||||||
方法: addPic //添加图片
|
|
||||||
参数: src 图片链接
|
|
||||||
clearPic //清空图片
|
|
||||||
参数: 无
|
|
||||||
使用方法: 加载组件后,通过ref调用addPic方法添加图片即可
|
|
||||||
-->
|
|
||||||
<template>
|
<template>
|
||||||
<div style="position: relative;height: 100%;width: 100%;">
|
<div style="position: relative;height: 100%;width: 100%;">
|
||||||
<draggable handle=".header-btn" :draggable="false" item-key="backgroundColor" v-model="gridPicList" class="grid-pic-wrap" :style="getGrid">
|
<draggable handle=".header-btn" :draggable="false" item-key="backgroundColor" v-model="gridPicList" class="grid-pic-wrap" :style="getGrid">
|
||||||
<template #item="{ element, index }">
|
<template #item="{ element, index }">
|
||||||
<div class="grid-pic-item" :key="element.backgroundColor" :style="getWH(element,index)">
|
<div class="grid-pic-item" :key="element.backgroundColor" :style="getWH(element,index)">
|
||||||
<div class="delete-btn" @click="()=>{gridPicList.splice(index,1);if(!gridPicList.length) emits('clear')} ">X</div>
|
<div class="delete-btn" @click="gridPicList.splice(index,1)">X</div>
|
||||||
<div class="header-btn"></div>
|
<div class="header-btn"></div>
|
||||||
<ViewerItem :gridPicList="gridPicList" :index="index" :images="element"></ViewerItem>
|
<ViewerItem :gridPicList="gridPicList" :index="index" :images="element"></ViewerItem>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</draggable>
|
</draggable>
|
||||||
<div class="grid-pic-toolbar">
|
<el-input style="position:fixed;bottom: 20px;right: 180px;width: 1000px" v-model="inputValue" type="text" />
|
||||||
<el-input v-if="showToolbar" style="width: 500px" v-model="inputValue" type="text" />
|
<el-button class="add-btn" @click="addPic">
|
||||||
<el-button v-if="showToolbar" class="add-btn" @click="pushPic">
|
|
||||||
添加
|
添加
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button class="add-btn" @click="clearPic">
|
<el-button style="position:fixed;bottom: 20px;right: 80px;" @click="startPencil">
|
||||||
清空
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
<!-- <el-button style="position:fixed;bottom: 20px;right: 80px;" @click="startPencil">
|
|
||||||
画笔
|
画笔
|
||||||
</el-button>-->
|
</el-button>
|
||||||
<!-- <div class="modal-mode">
|
<div class="modal-mode">
|
||||||
<canvas id="canvas_pic_001" style="position: absolute;top: 0;left: 0;width: 100%;height: 100%;"></canvas>
|
<canvas id="canvas_pic_001" style="position: absolute;top: 0;left: 0;width: 100%;height: 100%;"></canvas>
|
||||||
</div>-->
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -44,18 +26,10 @@
|
||||||
import {ref, computed, onMounted} from 'vue'
|
import {ref, computed, onMounted} from 'vue'
|
||||||
import Draggable from 'vuedraggable'
|
import Draggable from 'vuedraggable'
|
||||||
import ViewerItem from "./viewer-item.vue";
|
import ViewerItem from "./viewer-item.vue";
|
||||||
// import Fabric from 'fabric';
|
import Fabric from 'fabric';
|
||||||
const gridPicList = ref([])
|
const gridPicList = ref([])
|
||||||
const inputValue = ref('')
|
const inputValue = ref('')
|
||||||
const isShow = ref(false)
|
const isShow = ref(false)
|
||||||
const emits = defineEmits(['clear','outIndex']);
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
showToolbar: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// 获取图片样式
|
// 获取图片样式
|
||||||
const getWH = (item,index)=>{
|
const getWH = (item,index)=>{
|
||||||
return {
|
return {
|
||||||
|
@ -144,38 +118,21 @@
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const pushPic = () => {
|
|
||||||
let src = inputValue.value||picList[gridPicList.value.length]
|
|
||||||
addPic(src)
|
|
||||||
}
|
|
||||||
// 添加图片
|
// 添加图片
|
||||||
const addPic = (data) => {
|
const addPic = () => {
|
||||||
let list = Array.isArray(data)?data:[data]
|
if (gridPicList.value.length >= 9) {
|
||||||
if (gridPicList.value.length + list.length > 9) {
|
|
||||||
console.log("超出九个图片")
|
|
||||||
emits('outIndex')
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let listArr = [];
|
let src = inputValue.value||picList[gridPicList.value.length]
|
||||||
for (let i = 0; i < list.length; i++) {
|
|
||||||
let src = list[i]
|
|
||||||
if (!src) {
|
if (!src) {
|
||||||
console.log("图片链接不能为空")
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
listArr.push({
|
gridPicList.value.push({
|
||||||
src: src,
|
src: src,
|
||||||
backgroundColor: getRandomColor()
|
backgroundColor: getRandomColor()
|
||||||
})
|
})
|
||||||
}
|
|
||||||
gridPicList.value.push(...listArr)
|
|
||||||
inputValue.value = ''
|
inputValue.value = ''
|
||||||
}
|
}
|
||||||
// 清空图片
|
|
||||||
const clearPic = () => {
|
|
||||||
gridPicList.value = []
|
|
||||||
emits('clear')
|
|
||||||
}
|
|
||||||
//开始画笔
|
//开始画笔
|
||||||
const startPencil = () => {
|
const startPencil = () => {
|
||||||
isShow.value = !isShow.value
|
isShow.value = !isShow.value
|
||||||
|
@ -191,7 +148,7 @@
|
||||||
b = b.length === 1? '0' + b : b;
|
b = b.length === 1? '0' + b : b;
|
||||||
return `#${r}${g}${b}`;
|
return `#${r}${g}${b}`;
|
||||||
}
|
}
|
||||||
/* //初始化画笔
|
//初始化画笔
|
||||||
const initPend = () => {
|
const initPend = () => {
|
||||||
let canvas = new Fabric.fabric.Canvas('canvas_pic_001',{
|
let canvas = new Fabric.fabric.Canvas('canvas_pic_001',{
|
||||||
interactive: false,
|
interactive: false,
|
||||||
|
@ -205,11 +162,10 @@
|
||||||
canvas.freeDrawingBrush = new Fabric.fabric.PencilBrush(canvas)
|
canvas.freeDrawingBrush = new Fabric.fabric.PencilBrush(canvas)
|
||||||
canvas.freeDrawingBrush.width = 1//设置画笔粗细
|
canvas.freeDrawingBrush.width = 1//设置画笔粗细
|
||||||
canvas.freeDrawingBrush.color = "red"//设置画笔颜色
|
canvas.freeDrawingBrush.color = "red"//设置画笔颜色
|
||||||
}*/
|
}
|
||||||
/*onMounted(() => {
|
onMounted(() => {
|
||||||
initPend()
|
initPend()
|
||||||
})*/
|
})
|
||||||
defineExpose({addPic,clearPic})
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.modal-mode{
|
.modal-mode{
|
||||||
|
@ -248,13 +204,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.grid-pic-toolbar{
|
.add-btn{
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
bottom: 20px;
|
bottom: 20px;
|
||||||
display: flex;
|
|
||||||
.add-btn{
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@keyframes fadeIn {
|
@keyframes fadeIn {
|
||||||
from {
|
from {
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import {ref, watch, nextTick, onMounted} from "vue";
|
import {ref, watch, nextTick, onMounted} from "vue";
|
||||||
import { component as Viewer } from 'v-viewer'
|
import { component as Viewer } from 'v-viewer'
|
||||||
// import Fabric from 'fabric';
|
import Fabric from 'fabric';
|
||||||
import 'viewerjs/dist/viewer.css'
|
import 'viewerjs/dist/viewer.css'
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
images: {
|
images: {
|
||||||
|
@ -36,13 +36,16 @@ const inited = (viewer) => {
|
||||||
}
|
}
|
||||||
//缩放时
|
//缩放时
|
||||||
const zoomed = (e) => {
|
const zoomed = (e) => {
|
||||||
// setImgStyle()
|
setImgStyle()
|
||||||
|
// console.log('zoomed', e)
|
||||||
}
|
}
|
||||||
//移动时
|
//移动时
|
||||||
const moved = (e) => {
|
const moved = (e) => {
|
||||||
// setImgStyle()
|
setImgStyle()
|
||||||
|
// console.log('moved',e)
|
||||||
}
|
}
|
||||||
const move = (e) => {
|
const move = (e) => {
|
||||||
|
// console.log('move', e)
|
||||||
}
|
}
|
||||||
const appendCanvasToShow = () => {
|
const appendCanvasToShow = () => {
|
||||||
initImgStyle()
|
initImgStyle()
|
||||||
|
@ -89,7 +92,7 @@ const optins = ref({
|
||||||
"tooltip": true,
|
"tooltip": true,
|
||||||
"zoomable": true,
|
"zoomable": true,
|
||||||
"rotatable": true,
|
"rotatable": true,
|
||||||
"movable": true,
|
"movable": false,
|
||||||
"scalable": true,
|
"scalable": true,
|
||||||
"transition": true,
|
"transition": true,
|
||||||
"fullscreen": true,
|
"fullscreen": true,
|
||||||
|
@ -97,9 +100,9 @@ const optins = ref({
|
||||||
})
|
})
|
||||||
const initViewers = () => {
|
const initViewers = () => {
|
||||||
refs.value['viewerRef'+props.index]?.rebuildViewer()
|
refs.value['viewerRef'+props.index]?.rebuildViewer()
|
||||||
/*setTimeout(()=>{
|
setTimeout(()=>{
|
||||||
initImgStyle()
|
initImgStyle()
|
||||||
},300)*/
|
},300)
|
||||||
}
|
}
|
||||||
//初始化画笔
|
//初始化画笔
|
||||||
const initPend = () => {
|
const initPend = () => {
|
||||||
|
@ -130,18 +133,15 @@ watch(props.images, (newValue, oldValue) => {
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*onMounted(()=>{
|
onMounted(()=>{
|
||||||
setTimeout(()=>{
|
setTimeout(()=>{
|
||||||
appendCanvasToShow()
|
appendCanvasToShow()
|
||||||
}, 300)
|
}, 300)
|
||||||
})*/
|
})
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.viewer-item-wrap{
|
.viewer-item-wrap{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
:deep(.viewer-canvas img) {
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -83,7 +83,7 @@
|
||||||
<!--AI 对话调整-->
|
<!--AI 对话调整-->
|
||||||
<AdjustDialog v-model="isAdjust" :type="type" :item="editItem" :curMode="curMode" :conversation_id="conversation_id"/>
|
<AdjustDialog v-model="isAdjust" :type="type" :item="editItem" :curMode="curMode" :conversation_id="conversation_id"/>
|
||||||
<!--添加、编辑提示词-->
|
<!--添加、编辑提示词-->
|
||||||
<keywordDialog v-model="isWordDialog" :item="editItem" :modeType="type" />
|
<keywordDialog v-model="isWordDialog" :item="editItem" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
@ -104,7 +104,7 @@ import { cloneDeep } from 'lodash'
|
||||||
const props = defineProps(['type'])
|
const props = defineProps(['type'])
|
||||||
const { user } = useUserStore()
|
const { user } = useUserStore()
|
||||||
|
|
||||||
const curMode = ref(2)
|
const curMode = ref(1)
|
||||||
const modeOptions = ref([
|
const modeOptions = ref([
|
||||||
{
|
{
|
||||||
label: '教学大模型',
|
label: '教学大模型',
|
||||||
|
@ -344,8 +344,6 @@ const againResult = async (index, item) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
||||||
// 一键研读
|
// 一键研读
|
||||||
const getCompletion = async () => {
|
const getCompletion = async () => {
|
||||||
isStarted.value = new Array(childTempList.length).fill(false)
|
isStarted.value = new Array(childTempList.length).fill(false)
|
||||||
|
@ -374,7 +372,6 @@ const getCompletion = async () => {
|
||||||
conversationId: conversation_id.value,
|
conversationId: conversation_id.value,
|
||||||
stream: false
|
stream: false
|
||||||
})
|
})
|
||||||
await delay(1000); // 每个请求之间延迟 1 秒
|
|
||||||
data = res.data
|
data = res.data
|
||||||
}
|
}
|
||||||
// 知识库模型
|
// 知识库模型
|
||||||
|
@ -418,7 +415,7 @@ const onEditSave = async (item) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 保存模板
|
// 保存模板
|
||||||
const onSaveTemp = async (item) => {
|
const onSaveTemp = (item) => {
|
||||||
if (item.answer == '') return
|
if (item.answer == '') return
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
|
@ -428,10 +425,7 @@ const onSaveTemp = async (item) => {
|
||||||
content: item.answer,
|
content: item.answer,
|
||||||
ex1: curNode.id
|
ex1: curNode.id
|
||||||
}
|
}
|
||||||
const res = await tempSave(data)
|
tempSave(data).then(res => { })
|
||||||
if(!item.resultId){
|
|
||||||
item.resultId = res.data
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 去掉字符串中的 ### **
|
// 去掉字符串中的 ### **
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="whiteboart-container" :style="{ height: height + 'px' }">
|
<div class="whiteboart-container" :style="{ height: height + 'px' }">
|
||||||
<div class="canvasBox" ref="box" @mouseenter.capture="handleMouseEnter" @mouseleave.capture="handleMouseLeave"></div>
|
<div class="canvasBox" ref="box"></div>
|
||||||
|
|
||||||
<div class="footerLeft" @click.stop
|
<div class="footerLeft" @click.stop
|
||||||
:style="type == 'design' ? ['top: 10px', 'justify-content: space-between'] : ['bottom: 10px', 'justify-content: center']">
|
:style="type == 'design' ? ['top: 10px', 'justify-content: space-between'] : ['bottom: 10px', 'justify-content: center']">
|
||||||
|
@ -123,7 +123,7 @@
|
||||||
<!-- 边框样式 -->
|
<!-- 边框样式 -->
|
||||||
<div class="blockBox">
|
<div class="blockBox">
|
||||||
<el-dropdown @command="updateStyle('lineDash', $event)" placement="top">
|
<el-dropdown @command="updateStyle('lineDash', $event)" placement="top">
|
||||||
<el-button><el-image :src="borderStyleImg"
|
<el-button><el-image src="../../../src/assets/images/borderstyle.png"
|
||||||
style="width: 14px; height: 14px"></el-image></el-button>
|
style="width: 14px; height: 14px"></el-image></el-button>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
|
@ -278,7 +278,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, onBeforeUnmount, ref, getCurrentInstance, watch, toRaw, nextTick, computed, reactive, defineProps, defineEmits } from 'vue'
|
import { onMounted, ref, watch, toRaw, nextTick, computed, reactive, defineProps, defineEmits } from 'vue'
|
||||||
import TinyWhiteboard from 'whiteboard_lyc'
|
import TinyWhiteboard from 'whiteboard_lyc'
|
||||||
import ColorPicker from './components/ColorPicker.vue'
|
import ColorPicker from './components/ColorPicker.vue'
|
||||||
import {
|
import {
|
||||||
|
@ -303,10 +303,8 @@ import {
|
||||||
import Contextmenu from './components/Contextmenu.vue'
|
import Contextmenu from './components/Contextmenu.vue'
|
||||||
import { fontFamilyList, fontSizeList } from './constants'
|
import { fontFamilyList, fontSizeList } from './constants'
|
||||||
|
|
||||||
const borderStyleImg = new URL('../../../src/assets/images/borderstyle.png', import.meta.url).href
|
|
||||||
const borderImg = new URL('../../../src/assets/images/borderwidth.png', import.meta.url).href
|
const borderImg = new URL('../../../src/assets/images/borderwidth.png', import.meta.url).href
|
||||||
const pointerImg = new URL('../../../src/assets/images/mouse-pointer.png', import.meta.url).href
|
const pointerImg = new URL('../../../src/assets/images/mouse-pointer.png', import.meta.url).href
|
||||||
const { proxy } = getCurrentInstance()
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
modelValue: {
|
modelValue: {
|
||||||
|
@ -509,7 +507,6 @@ const backToCenter = () => {
|
||||||
app.scrollToCenter()
|
app.scrollToCenter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 显示全部
|
// 显示全部
|
||||||
const showFit = () => {
|
const showFit = () => {
|
||||||
let elementList = app.elements.elementList
|
let elementList = app.elements.elementList
|
||||||
|
@ -703,6 +700,8 @@ const getCanvasBlob = async () =>{
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
watch(() => props.data, (newVal) => {
|
watch(() => props.data, (newVal) => {
|
||||||
if (newVal) {
|
if (newVal) {
|
||||||
setCanvasData(newVal)
|
setCanvasData(newVal)
|
||||||
|
@ -714,13 +713,6 @@ watch(() => props.data, (newVal) => {
|
||||||
|
|
||||||
// dom元素挂载完成
|
// dom元素挂载完成
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
init();
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化画布内容
|
|
||||||
*/
|
|
||||||
const init = () => {
|
|
||||||
// 创建实例
|
// 创建实例
|
||||||
app = new TinyWhiteboard({
|
app = new TinyWhiteboard({
|
||||||
container: box.value,
|
container: box.value,
|
||||||
|
@ -742,7 +734,6 @@ const init = () => {
|
||||||
})
|
})
|
||||||
// 监听元素激活事件
|
// 监听元素激活事件
|
||||||
app.on('activeElementChange', element => {
|
app.on('activeElementChange', element => {
|
||||||
console.log('点击元素 监听 activeElementChange-----------')
|
|
||||||
if (activeElement.value) {
|
if (activeElement.value) {
|
||||||
activeElement.value.off('elementRotateChange', onElementRotateChange)
|
activeElement.value.off('elementRotateChange', onElementRotateChange)
|
||||||
}
|
}
|
||||||
|
@ -790,39 +781,7 @@ const init = () => {
|
||||||
app.resize()
|
app.resize()
|
||||||
}, 300)
|
}, 300)
|
||||||
})
|
})
|
||||||
}
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const isMyCanvas = ref(false); // 鼠标 是否进入画布判断
|
|
||||||
const handleKeyDown=(event)=> {
|
|
||||||
// console.log('键盘按键被按下:', event.key);
|
|
||||||
// console.log(isMyCanvas.value,'??????????')
|
|
||||||
if(isMyCanvas.value == false){
|
|
||||||
event.stopPropagation();
|
|
||||||
// console.log('键盘事件被捕获,已阻止冒泡:', event.key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 鼠标进入事件
|
|
||||||
*/
|
|
||||||
const handleMouseEnter = () => {
|
|
||||||
console.log('进入白板')
|
|
||||||
isMyCanvas.value = true;
|
|
||||||
document.addEventListener('keydown', handleKeyDown, true);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 课堂展示-鼠标离开白板监听事件:该事件是避免,选中状态,在其他地方点击、后退、删除等事件,会删除白板内选中的元素
|
|
||||||
*/
|
|
||||||
const handleMouseLeave = () => {
|
|
||||||
console.log('离开白板')
|
|
||||||
// 清除激活项--点击事件的激活项
|
|
||||||
app.cancelActiveElement()
|
|
||||||
// 阻止 点击拖动范围的取消激活项……
|
|
||||||
isMyCanvas.value = false;
|
|
||||||
// 确保事件处理函数在组件挂载后绑定
|
|
||||||
document.addEventListener('keydown', handleKeyDown, true);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 暴露方法
|
// 暴露方法
|
||||||
defineExpose({
|
defineExpose({
|
||||||
|
@ -832,7 +791,7 @@ defineExpose({
|
||||||
getCanvasJson,
|
getCanvasJson,
|
||||||
getCanvasBase64,
|
getCanvasBase64,
|
||||||
setCanvasData,
|
setCanvasData,
|
||||||
getCanvasBlob,
|
getCanvasBlob
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,6 @@ const closeWindow = () => {
|
||||||
ElMessageBox.confirm('确认退出系统吗?', '提示', {
|
ElMessageBox.confirm('确认退出系统吗?', '提示', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
customClass: 'login-close-tool',
|
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
userStore.logOut().then(() => {
|
userStore.logOut().then(() => {
|
||||||
|
@ -55,11 +54,7 @@ onMounted(() =>{
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
|
||||||
.login-close-tool {
|
|
||||||
-webkit-app-region: no-drag;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.header-tool {
|
.header-tool {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { listEntpcoursework,getEvaluationclue } from '@/api/classTask';
|
import { listEntpcoursework,getEvaluationclue } from '@/api/classTask';
|
||||||
import { processList } from '@/hooks/useProcessList';
|
import { processList } from '@/hooks/useProcessList';
|
||||||
import useClassTaskStore from '@/store/modules/classTask'
|
|
||||||
const useClassTaskStores = useClassTaskStore();
|
|
||||||
|
|
||||||
const isJson = (str) => {
|
const isJson = (str) => {
|
||||||
if (typeof str == 'string') {
|
if (typeof str == 'string') {
|
||||||
|
@ -34,7 +32,7 @@ export const editListItem = (row, courseObj) => {
|
||||||
worktype: '', // 设计中的作业类型
|
worktype: '', // 设计中的作业类型
|
||||||
quizlist: [], // 设计中的试题列表
|
quizlist: [], // 设计中的试题列表
|
||||||
chooseWorkLists: [],// 设计中的框架梳理list
|
chooseWorkLists: [],// 设计中的框架梳理list
|
||||||
fileHomeworkList: [],//TODO 暂时共用这个字段(新增了 科学实验) 设计中的常规作业list
|
fileHomeworkList: [],// 设计中的常规作业list
|
||||||
whiteboardObj: '',// 设计中的课堂展示对象
|
whiteboardObj: '',// 设计中的课堂展示对象
|
||||||
question: '', // 设计中的[课堂展示]的问题
|
question: '', // 设计中的[课堂展示]的问题
|
||||||
};
|
};
|
||||||
|
@ -114,24 +112,6 @@ export const editListItem = (row, courseObj) => {
|
||||||
return resolve(classtaskObj);
|
return resolve(classtaskObj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (row.worktype == '科学实验') {
|
|
||||||
if(isJson(row.workcodes)){
|
|
||||||
// 同步更新实验内部的科目信息
|
|
||||||
if (row.worktag && row.worktag.indexOf('-') > -1){
|
|
||||||
const eduInfo = row.worktag.split('-');
|
|
||||||
useClassTaskStores.experimentObj.edustage = eduInfo[0];
|
|
||||||
useClassTaskStores.experimentObj.edusubject = eduInfo[1];
|
|
||||||
useClassTaskStores.experimentObj.updateEduInfo = row.worktag;
|
|
||||||
}
|
|
||||||
// 更新科学实验内容
|
|
||||||
classtaskObj.fileHomeworkList = JSON.parse(row.workcodes);
|
|
||||||
//
|
|
||||||
// console.log('科学实验', classtaskObj);
|
|
||||||
// 更新默认的科学实验( 学段 学科 以及实验科目)
|
|
||||||
console.log('科学实验', classtaskObj);
|
|
||||||
return resolve(classtaskObj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,15 +87,13 @@ const getHomeWorkList = async () => {
|
||||||
// } else
|
// } else
|
||||||
// 课标研读 目标设定 教材研读 框架梳理 学科定位 TODO 后续接入在添加
|
// 课标研读 目标设定 教材研读 框架梳理 学科定位 TODO 后续接入在添加
|
||||||
if (res.rows[i].worktype == '课堂展示') {
|
if (res.rows[i].worktype == '课堂展示') {
|
||||||
res.rows[i].workclass = 'success';
|
res.rows[i].workclass = 'primary';
|
||||||
} else if (res.rows[i].worktype == '框架梳理') {
|
} else if (res.rows[i].worktype == '框架梳理') {
|
||||||
res.rows[i].workclass = 'warning';
|
res.rows[i].workclass = 'warning';
|
||||||
} else if (res.rows[i].worktype == '常规作业') {
|
} else if (res.rows[i].worktype == '常规作业') {
|
||||||
res.rows[i].workclass = 'info';
|
res.rows[i].workclass = 'info';
|
||||||
} else if (res.rows[i].worktype == '习题训练') {
|
} else if (res.rows[i].worktype == '习题训练') {
|
||||||
res.rows[i].workclass = 'danger';
|
res.rows[i].workclass = 'danger';
|
||||||
} else if (res.rows[i].worktype == '科学实验') {
|
|
||||||
res.rows[i].workclass = 'primary';
|
|
||||||
} else {
|
} else {
|
||||||
res.rows[i].workclass = 'primary';
|
res.rows[i].workclass = 'primary';
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,28 +299,21 @@ export const processList = (row, aloneOption=false) => {
|
||||||
if(!aloneOption && j%2== 0){
|
if(!aloneOption && j%2== 0){
|
||||||
tmp += '</div>';
|
tmp += '</div>';
|
||||||
}
|
}
|
||||||
row[i].workdescFormat = tmp;
|
row[i].workdescFormat = tmp
|
||||||
|
|
||||||
// 处理[答案显示] - 转换ABCD
|
// 处理[答案显示] - 转换ABCD
|
||||||
let arr2Char = workAnswerArr
|
let arr2Char = workAnswerArr
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
return String.fromCharCode(65 + Number(item))
|
return String.fromCharCode(65 + Number(item))
|
||||||
})
|
})
|
||||||
.join('');
|
.join('')
|
||||||
row[i].workanswerFormat = arr2Char;
|
row[i].workanswerFormat = arr2Char
|
||||||
} else if (row[i].worktype == '填空题') {
|
} else if (row[i].worktype == '填空题') {
|
||||||
// 处理[选项显示] - 填空题中无选项, 故置空
|
// 处理[选项显示] - 填空题中无选项, 故置空
|
||||||
row[i].workdescFormat = '';
|
row[i].workdescFormat = ''
|
||||||
|
|
||||||
// 处理[答案显示] - 逗号连接
|
// 处理[答案显示] - 逗号连接
|
||||||
|
row[i].workanswerFormat = workAnswerArr.join('、')
|
||||||
// 当[答案显示]为 [<div] 开头时,不再需逗号连接(一般为自主上传, 当前答案每个自带div标签)
|
|
||||||
let linkChar = '、';
|
|
||||||
if (workAnswerArr.length != 0 && workAnswerArr[0].indexOf('<div') == 0) {
|
|
||||||
linkChar = '';
|
|
||||||
}
|
|
||||||
row[i].workanswerFormat = workAnswerArr.join(linkChar);
|
|
||||||
|
|
||||||
} else if (row[i].worktype == '判断题') {
|
} else if (row[i].worktype == '判断题') {
|
||||||
// 处理[选项显示] - 判断题中无选项, 故置空
|
// 处理[选项显示] - 判断题中无选项, 故置空
|
||||||
row[i].workdescFormat = ''
|
row[i].workdescFormat = ''
|
||||||
|
@ -328,7 +321,7 @@ export const processList = (row, aloneOption=false) => {
|
||||||
// 处理[答案显示] - 1-正常 0-错误
|
// 处理[答案显示] - 1-正常 0-错误
|
||||||
const answer = workAnswerArr
|
const answer = workAnswerArr
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
return DICT_TRUE_OR_FALSE.TRUE.includes(item) ? '正确' : DICT_TRUE_OR_FALSE.FALSE.includes(item)?'错误':item;
|
return item === '1' ? '正确' : '错误'
|
||||||
})
|
})
|
||||||
.join('、')
|
.join('、')
|
||||||
row[i].workanswerFormat = answer
|
row[i].workanswerFormat = answer
|
||||||
|
@ -341,8 +334,3 @@ export const processList = (row, aloneOption=false) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const DICT_TRUE_OR_FALSE = {
|
|
||||||
TRUE: ['正确', '对', '√', '1'],
|
|
||||||
FALSE: ['错误', '错', '×', '0'],
|
|
||||||
};
|
|
|
@ -60,7 +60,6 @@ import useUserStore from '@/store/modules/user'
|
||||||
import pkc from "../../../../../package.json"
|
import pkc from "../../../../../package.json"
|
||||||
import defaultUserImg from '@/assets/images/img-avatar.png'
|
import defaultUserImg from '@/assets/images/img-avatar.png'
|
||||||
import { sessionStore } from '@/utils/store'
|
import { sessionStore } from '@/utils/store'
|
||||||
import {toLinkLeftWeb} from "@/utils/tool"
|
|
||||||
|
|
||||||
|
|
||||||
const { ipcRenderer } = window.electron || {}
|
const { ipcRenderer } = window.electron || {}
|
||||||
|
@ -85,7 +84,7 @@ const isStadium = () => {
|
||||||
|
|
||||||
const headerMenus = isStadium() ?[{
|
const headerMenus = isStadium() ?[{
|
||||||
name: '教学实践',
|
name: '教学实践',
|
||||||
id: 6,
|
id: 4,
|
||||||
icon: 'icon-jiaoxueshijian',
|
icon: 'icon-jiaoxueshijian',
|
||||||
path: '/prepare'
|
path: '/prepare'
|
||||||
},]:[
|
},]:[
|
||||||
|
@ -95,12 +94,12 @@ const headerMenus = isStadium() ?[{
|
||||||
icon: 'icon-shouye',
|
icon: 'icon-shouye',
|
||||||
path: '/model/index'
|
path: '/model/index'
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// name: '教学工作台',
|
name: '教学工作台',
|
||||||
// id: 2,
|
id: 2,
|
||||||
// icon: 'icon-gongzuotai',
|
icon: 'icon-gongzuotai',
|
||||||
// path: '/desktop'
|
path: '/desktop'
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
name: '教学实践',
|
name: '教学实践',
|
||||||
id: 4,
|
id: 4,
|
||||||
|
@ -119,14 +118,6 @@ const headerMenus = isStadium() ?[{
|
||||||
icon: 'icon-kechengziyuan1',
|
icon: 'icon-kechengziyuan1',
|
||||||
path: '/resource/index'
|
path: '/resource/index'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: '科学',
|
|
||||||
id: 4,
|
|
||||||
icon: 'icon-kechengziyuan1',
|
|
||||||
path: '/scientific/index',
|
|
||||||
// path: 'https://res.bakclass.com/resource/laboratoryIndex',
|
|
||||||
// type: 'webview', // 应用内置浏览器
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
const sideBottomMenu = [
|
const sideBottomMenu = [
|
||||||
|
@ -167,17 +158,10 @@ const computedregistertype = computed(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
const clickMenu = (item) => {
|
const clickMenu = ({ id, disabled, path }) => {
|
||||||
const { id, disabled, path, type } = item
|
|
||||||
if (disabled) return
|
if (disabled) return
|
||||||
if (type == 'webview') { // 应用内置浏览器
|
|
||||||
toLinkLeftWeb(item.path)
|
|
||||||
} else if (type == 'link') {
|
|
||||||
window.open(path)
|
|
||||||
} else {
|
|
||||||
activeId.value = id
|
activeId.value = id
|
||||||
router.push(path)
|
router.push(path)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const onUserTo = (path) =>{
|
const onUserTo = (path) =>{
|
||||||
|
@ -345,7 +329,6 @@ onMounted(() => {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
text-align: center;
|
|
||||||
}
|
}
|
||||||
.pointer-events{
|
.pointer-events{
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
|
@ -10,15 +10,6 @@ import './assets/iconfont/iconfont'
|
||||||
import 'virtual:windi.css'
|
import 'virtual:windi.css'
|
||||||
import request from "@/utils/request";
|
import request from "@/utils/request";
|
||||||
|
|
||||||
//v-md-editor
|
|
||||||
import VMdPreview from '@kangc/v-md-editor/lib/preview';
|
|
||||||
import '@kangc/v-md-editor/lib/style/preview.css';
|
|
||||||
// 引入你所使用的主题 此处以 github 主题为例
|
|
||||||
import githubTheme from '@kangc/v-md-editor/lib/theme/github';
|
|
||||||
import '@kangc/v-md-editor/lib/theme/style/github.css';
|
|
||||||
// highlightjs
|
|
||||||
import hljs from 'highlight.js';
|
|
||||||
|
|
||||||
import { store } from '@/store'
|
import { store } from '@/store'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
|
@ -26,9 +17,6 @@ import log from 'electron-log/renderer' // 渲染进程日志-文件记录
|
||||||
import customComponent from '@/components/common' // 自定义组件
|
import customComponent from '@/components/common' // 自定义组件
|
||||||
import plugins from './plugins' // plugins插件
|
import plugins from './plugins' // plugins插件
|
||||||
import useUserStore from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
import aiAudio from 'aix-plugins-aitools' // 文字转语音插件
|
|
||||||
import '../../../node_modules/aix-plugins-aitools/aitools.css'
|
|
||||||
|
|
||||||
|
|
||||||
if(process.env.NODE_ENV != 'development') { // 非开发环境,将日志打印到日志文件
|
if(process.env.NODE_ENV != 'development') { // 非开发环境,将日志打印到日志文件
|
||||||
Object.assign(console, log.functions) // 渲染进程日志-控制台替换
|
Object.assign(console, log.functions) // 渲染进程日志-控制台替换
|
||||||
|
@ -51,10 +39,6 @@ app.config.globalProperties.$requestGetJYW = (url,config)=>{
|
||||||
import Icon from '@/AixPPTist/src/plugins/icon'
|
import Icon from '@/AixPPTist/src/plugins/icon'
|
||||||
import Directive from '@/AixPPTist/src/plugins/directive'
|
import Directive from '@/AixPPTist/src/plugins/directive'
|
||||||
|
|
||||||
VMdPreview.use(githubTheme, {
|
|
||||||
Hljs: hljs,
|
|
||||||
});
|
|
||||||
|
|
||||||
app.use(router)
|
app.use(router)
|
||||||
.use(store)
|
.use(store)
|
||||||
.use(ElementPlus, { locale: zhLocale })
|
.use(ElementPlus, { locale: zhLocale })
|
||||||
|
@ -62,8 +46,6 @@ app.use(router)
|
||||||
.use(plugins)
|
.use(plugins)
|
||||||
.use(Icon)
|
.use(Icon)
|
||||||
.use(Directive)
|
.use(Directive)
|
||||||
.use(aiAudio)
|
|
||||||
.use(VMdPreview)
|
|
||||||
.mount('#app')
|
.mount('#app')
|
||||||
|
|
||||||
const isStadium = (user) => {
|
const isStadium = (user) => {
|
||||||
|
|
|
@ -100,8 +100,6 @@ export class MsgEnum {
|
||||||
MSG_homework : 'HOMEWORK',
|
MSG_homework : 'HOMEWORK',
|
||||||
/** @desc: 公屏 - 课堂作业|活动 */
|
/** @desc: 公屏 - 课堂作业|活动 */
|
||||||
MSG_pushSreen_work : 'pushSreen_work',
|
MSG_pushSreen_work : 'pushSreen_work',
|
||||||
/** @desc: 公屏 - 实验 */
|
|
||||||
MSG_pushSreen_experiment : 'pushSreen_experiment',
|
|
||||||
/** @desc: 点赞 */
|
/** @desc: 点赞 */
|
||||||
MSG_dz : 'dz',
|
MSG_dz : 'dz',
|
||||||
/** @desc: 疑惑 */
|
/** @desc: 疑惑 */
|
||||||
|
|
|
@ -96,12 +96,6 @@ export const constantRoutes = [
|
||||||
name: 'aiKolors',
|
name: 'aiKolors',
|
||||||
meta: { title: '文生图片', showBread: true }
|
meta: { title: '文生图片', showBread: true }
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: 'aiVoice',
|
|
||||||
component: () => import('@/components/ai-voice/index.vue'),
|
|
||||||
name: 'aiVoice',
|
|
||||||
meta: { title: '语音生成', showBread: true }
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -221,18 +215,6 @@ const dynamicRoutes = [
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: '/scientific',
|
|
||||||
component: Layout,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'index',
|
|
||||||
component: () => import('@/views/scientific/index.vue'),
|
|
||||||
name: 'scientific',
|
|
||||||
meta: { title: '科学' },
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/hashrate',
|
path: '/hashrate',
|
||||||
component: Layout,
|
component: Layout,
|
||||||
|
|
|
@ -2,17 +2,9 @@ import { defineStore } from 'pinia'
|
||||||
import { } from '@/api/classTask/index.js'
|
import { } from '@/api/classTask/index.js'
|
||||||
import { listClassmain } from '@/api/classManage/index'
|
import { listClassmain } from '@/api/classManage/index'
|
||||||
import { JYApiListCT, JYApiListOriginYear, JYApiListSO} from "@/utils/examQuestion/jyeoo"
|
import { JYApiListCT, JYApiListOriginYear, JYApiListSO} from "@/utils/examQuestion/jyeoo"
|
||||||
import { listEvaluation } from '@/api/subject'
|
|
||||||
import { getBindlist, listKnowlegepointFormat } from '@/api/education/knowledgePoint'
|
|
||||||
|
|
||||||
const useClassTaskStore = defineStore('classTask',{
|
const useClassTaskStore = defineStore('classTask',{
|
||||||
state: () => ({
|
state: () => ({
|
||||||
experimentObj:{
|
|
||||||
edustage: '小学', // 教育阶段
|
|
||||||
edusubject: '数学', // 学科
|
|
||||||
experimentList: [], // 实验科目列表
|
|
||||||
updateEduInfo: '小学-数学', //实际需上传的学段+学科信息(用于上传及回显实验内的学段学科)
|
|
||||||
},
|
|
||||||
isOpenQuestUploadView: false, // 是否打开习题上传的页面
|
isOpenQuestUploadView: false, // 是否打开习题上传的页面
|
||||||
classListIds: [],
|
classListIds: [],
|
||||||
entpCourseWorkTypeList: [
|
entpCourseWorkTypeList: [
|
||||||
|
@ -40,7 +32,6 @@ const useClassTaskStore = defineStore('classTask',{
|
||||||
{label: '2021', value: '2021'},
|
{label: '2021', value: '2021'},
|
||||||
{label: '2020', value: '2020'},
|
{label: '2020', value: '2020'},
|
||||||
], // 习题查询条件 - 年份
|
], // 习题查询条件 - 年份
|
||||||
entpCourseWorkPointList: [], // 习题查询条件 - 知识点
|
|
||||||
}),
|
}),
|
||||||
actions: {
|
actions: {
|
||||||
listClassmain(params) {
|
listClassmain(params) {
|
||||||
|
@ -72,36 +63,6 @@ const useClassTaskStore = defineStore('classTask',{
|
||||||
console.error('更新第三方题源+题型err:', error);
|
console.error('更新第三方题源+题型err:', error);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// 根据学科和学段获取知识点
|
|
||||||
initJYPoint(params) {
|
|
||||||
/**
|
|
||||||
* 格式化知识点: 分两种情况
|
|
||||||
* 1. 语文/英语: 获取学科下的所有知识点(该学科对应无章节与知识点绑定, 故只获取全知识点)
|
|
||||||
* 2. 其他: 获取当前章节下的所有知识点
|
|
||||||
*/
|
|
||||||
this.entpCourseWorkPointList = [];
|
|
||||||
let id = params.levelSecondId!='' ? params.levelSecondId : params.levelFirstId;
|
|
||||||
if( params.edusubject == '语文' || params.edusubject == '英语'){
|
|
||||||
id = params.textbookId;
|
|
||||||
listEvaluation({ edusubject: params.edusubject, edustage: params.edustage, itemkey: "subject", pageSize: 10 }).then((res => {
|
|
||||||
id = res.rows[0]?.id;
|
|
||||||
if (id) {
|
|
||||||
listKnowlegepointFormat({evalId: id, pageNum: 1, pageSize: 5000,}).then(res => {
|
|
||||||
this.entpCourseWorkPointList = formatKnowledgePoint(res.rows);
|
|
||||||
console.log('1.entpCourseWorkPointList->', this.entpCourseWorkPointList);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}else{
|
|
||||||
getBindlist({ eid: id }).then(res => {
|
|
||||||
if (res.data && res.data.length > 0) {
|
|
||||||
this.entpCourseWorkPointList = res.data;
|
|
||||||
console.log('2.entpCourseWorkPointList->', this.entpCourseWorkPointList);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
persist: true
|
persist: true
|
||||||
})
|
})
|
||||||
|
@ -142,20 +103,3 @@ const getJYCT = (params) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @desc: 遍历原知识点数据, 将title字段转为knowTitle以供knowledgePointProps进行tree的格式转换显示
|
|
||||||
* @return: {*}
|
|
||||||
* @param {*} list
|
|
||||||
*/
|
|
||||||
const formatKnowledgePoint = (list) => {
|
|
||||||
list.forEach(item => {
|
|
||||||
if (item.title && item.title != '') {
|
|
||||||
item.knowTitle = item.title;
|
|
||||||
}
|
|
||||||
if (item.children && Array.isArray(item.children)) {
|
|
||||||
formatKnowledgePoint(item.children);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return list;
|
|
||||||
};
|
|
|
@ -395,11 +395,7 @@ export const dataSetJson = {
|
||||||
"课标-高中-英语": "e889fcac9fd011efb22a0242ac140006",
|
"课标-高中-英语": "e889fcac9fd011efb22a0242ac140006",
|
||||||
"课标-高中-数学": "e03aa4fe9fd011ef91270242ac140006",
|
"课标-高中-数学": "e03aa4fe9fd011ef91270242ac140006",
|
||||||
"课标-高中-地理": "270516829fd111efb13c0242ac140006",
|
"课标-高中-地理": "270516829fd111efb13c0242ac140006",
|
||||||
"课标-高中-物理": "3865b5afc68211ef90890242ac140002",
|
|
||||||
"课标-高中-化学": "013d0c52c68311ef84220242ac140002",
|
|
||||||
"课标-高中-政治": "a2f0b247b85d11ef84290242ac140005",
|
"课标-高中-政治": "a2f0b247b85d11ef84290242ac140005",
|
||||||
"教材-高中-物理": "3865b5afc68211ef90890242ac140002",
|
|
||||||
"教材-高中-化学": "013d0c52c68311ef84220242ac140002",
|
|
||||||
"教材-高中-语文": "cee3062a9fcf11efa6910242ac140006",
|
"教材-高中-语文": "cee3062a9fcf11efa6910242ac140006",
|
||||||
"教材-高中-生物": "fb5d01d59fd011ef9bb90242ac140006",
|
"教材-高中-生物": "fb5d01d59fd011ef9bb90242ac140006",
|
||||||
"教材-高中-历史": "f2f6c1fb9fd011ef98740242ac140006",
|
"教材-高中-历史": "f2f6c1fb9fd011ef98740242ac140006",
|
||||||
|
@ -407,52 +403,5 @@ export const dataSetJson = {
|
||||||
"教材-高中-数学": "e03aa4fe9fd011ef91270242ac140006",
|
"教材-高中-数学": "e03aa4fe9fd011ef91270242ac140006",
|
||||||
"教材-高中-地理": "270516829fd111efb13c0242ac140006",
|
"教材-高中-地理": "270516829fd111efb13c0242ac140006",
|
||||||
"教材-高中-政治": "a2f0b247b85d11ef84290242ac140005",
|
"教材-高中-政治": "a2f0b247b85d11ef84290242ac140005",
|
||||||
|
|
||||||
"考试-小学-语文": "570f7ed2cc9d11ef9e070242ac140002",
|
|
||||||
"考试-小学-数学": "983270b8cc9d11efbbd80242ac140002",
|
|
||||||
"考试-小学-英语": "d5f80e4ccc9d11ef96fa0242ac140002",
|
|
||||||
"课标-小学-科学": "935cfec8bf6a11ef98950242ac140006",
|
|
||||||
"课标-小学-数学": "3c4e298fbf7911ef8e8b0242ac140002",
|
|
||||||
"课标-小学-语文": "f76f1aa5bf7111ef90c80242ac140002",
|
|
||||||
"课标-小学-道德": "8da87869cbd711ef92280242ac140002",
|
|
||||||
"课标-小学-英语": "dc963316cbd811ef8d820242ac140002",
|
|
||||||
"课标-小学-劳动": "fc047d81cbdc11efa1740242ac140002",
|
|
||||||
"教材-小学-科学": "935cfec8bf6a11ef98950242ac140006",
|
|
||||||
"教材-小学-数学": "3c4e298fbf7911ef8e8b0242ac140002",
|
|
||||||
"教材-小学-语文": "f76f1aa5bf7111ef90c80242ac140002",
|
|
||||||
"教材-小学-道德": "8da87869cbd711ef92280242ac140002",
|
|
||||||
"教材-小学-英语": "dc963316cbd811ef8d820242ac140002",
|
|
||||||
"教材-小学-劳动": "fc047d81cbdc11efa1740242ac140002",
|
|
||||||
|
|
||||||
"教材-初中-道德与法治": "df9f3ccccbdd11ef9e550242ac140002",
|
|
||||||
"教材-初中-语文": "3770ad18cbde11efadaa0242ac140002",
|
|
||||||
"教材-初中-数学": "8cc0a799cbde11ef8b440242ac140002",
|
|
||||||
"教材-初中-英语": "07b58ca2cbdf11efaa180242ac140002",
|
|
||||||
"教材-初中-物理": "86f2c018cbf211ef9d6a0242ac140002",
|
|
||||||
"教材-初中-化学": "c7b34790cbf211ef92350242ac140002",
|
|
||||||
"教材-初中-生物": "083ac3edcbf311efaad30242ac140002",
|
|
||||||
"教材-初中-地理": "7ee584e1cbf311efbd270242ac140002",
|
|
||||||
"教材-初中-历史": "8ae07971cbf411ef81e70242ac140002",
|
|
||||||
"教材-初中-信息技术": "ca476233cbf411efa9860242ac140002",
|
|
||||||
"课标-初中-道德与法治": "df9f3ccccbdd11ef9e550242ac140002",
|
|
||||||
"课标-初中-语文": "3770ad18cbde11efadaa0242ac140002",
|
|
||||||
"课标-初中-数学": "8cc0a799cbde11ef8b440242ac140002",
|
|
||||||
"课标-初中-英语": "07b58ca2cbdf11efaa180242ac140002",
|
|
||||||
"课标-初中-物理": "86f2c018cbf211ef9d6a0242ac140002",
|
|
||||||
"课标-初中-化学": "c7b34790cbf211ef92350242ac140002",
|
|
||||||
"课标-初中-生物": "083ac3edcbf311efaad30242ac140002",
|
|
||||||
"课标-初中-地理": "7ee584e1cbf311efbd270242ac140002",
|
|
||||||
"课标-初中-历史": "8ae07971cbf411ef81e70242ac140002",
|
|
||||||
"课标-初中-信息技术": "ca476233cbf411efa9860242ac140002",
|
|
||||||
|
|
||||||
"考试-初中-语文": "6be6d201cc0111ef89100242ac140002",
|
|
||||||
"考试-初中-数学": "d764b539cc0111ef8f1b0242ac140002",
|
|
||||||
"考试-初中-英语": "3477cff7cc9911efbfa50242ac140002",
|
|
||||||
"考试-初中-政治": "7ac981d8cc9a11efa5dc0242ac140002",
|
|
||||||
"考试-初中-历史": "c058a33acc9a11efb7f00242ac140002",
|
|
||||||
"考试-初中-地理": "5548224ecc9b11efa76d0242ac140002",
|
|
||||||
"考试-初中-生物": "206c5fd3cc9c11ef990f0242ac140002",
|
|
||||||
"考试-初中-物理": "93039442cc9c11ef89b10242ac140002",
|
|
||||||
"考试-初中-化学": "f8d78002cc9c11efbbf60242ac140002",
|
|
||||||
"鉴权": "ragflow-IwMDI1MGU2YTU3NjExZWZiNWEzMDI0Mm"
|
"鉴权": "ragflow-IwMDI1MGU2YTU3NjExZWZiNWEzMDI0Mm"
|
||||||
}
|
}
|
|
@ -1,49 +0,0 @@
|
||||||
/**
|
|
||||||
* 弹窗-函数
|
|
||||||
*/
|
|
||||||
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',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,734 +0,0 @@
|
||||||
{
|
|
||||||
"title": "实验",
|
|
||||||
"data": {
|
|
||||||
"primary":[
|
|
||||||
{
|
|
||||||
"label": "数量比较",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/number-compare/latest/number-compare_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "数字游戏",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/number-play/latest/number-play_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "数轴:距离",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/number-line-distance/latest/number-line-distance_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "比率和比例",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/ratio-and-proportion/latest/ratio-and-proportion_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "数轴:运算",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/number-line-operations/latest/number-line-operations_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "数轴:整数",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/number-line-integers/latest/number-line-integers_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "向量的和:等式",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/vector-addition-equations/latest/vector-addition-equations_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "向量相加",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/vector-addition/latest/vector-addition_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "曲线拟合",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/curve-fitting/latest/curve-fitting_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "分数:带分数",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/fractions-mixed-numbers/latest/fractions-mixed-numbers_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "分数:入门",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/fractions-intro/latest/fractions-intro_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "构建一个分数",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/build-a-fraction/latest/build-a-fraction_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "分数:等式",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/fractions-equality/latest/fractions-equality_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "单位价格",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/unit-rates/latest/unit-rates_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "获得一个10",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/make-a-ten/latest/make-a-ten_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "木棒的计算问题",
|
|
||||||
"fileurl": "https://www.netpad.net.cn/resource_web/course/?pack_id=6dc2ab05-cb06-4716-92ca-e00fb89ad1e6#/20808",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "几何光学",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/geometric-optics/latest/geometric-optics_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "密度",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/density/latest/density_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "能量滑板竞技场: 基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/energy-skate-park-basics/latest/energy-skate-park-basics_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "法拉第定律",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/faradays-law/latest/faradays-law_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "绳波",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/wave-on-a-string/latest/wave-on-a-string_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "光的混合",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/color-vision/latest/color-vision_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "平衡探究实验",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/balancing-act/latest/balancing-act_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "受到压力",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/under-pressure/latest/under-pressure_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "摩擦力",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/friction/latest/friction_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "力和运动:基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/forces-and-motion-basics/latest/forces-and-motion-basics_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "静电电压",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/john-travoltage/latest/john-travoltage_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "万有引力实验",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/gravity-force-lab/latest/gravity-force-lab_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "气球和静电(摩擦起电)",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/balloons-and-static-electricity/latest/balloons-and-static-electricity_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "密度",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/density/latest/density_zh_CN.html",
|
|
||||||
"subject": "biology"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "基因表达基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/gene-expression-essentials/latest/gene-expression-essentials_zh_CN.html",
|
|
||||||
"subject": "biology"
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "密度",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/density/latest/density_zh_CN.html",
|
|
||||||
"subject": "sciences"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "PH值",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/ph-scale/latest/ph-scale_zh_CN.html",
|
|
||||||
"subject": "sciences"
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "密度",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/density/latest/density_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "创造一个分子",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/build-a-molecule/latest/build-a-molecule_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "扩散",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/diffusion/latest/diffusion_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"junior": [
|
|
||||||
{
|
|
||||||
"label": "二项分布弹珠台几率",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/plinko-probability/latest/plinko-probability_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "建立方程",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/function-builder/latest/function-builder_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "三角函数之旅",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/trig-tour/latest/trig-tour_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "四则运算",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/arithmetic/latest/arithmetic_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "二次函数图像",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/graphing-quadratics/latest/graphing-quadratics_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "质量和弹簧",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/masses-and-springs/latest/masses-and-springs_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "等式探索:两个变量",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/equality-explorer-two-variables/latest/equality-explorer-two-variables_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "等式探索:基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/equality-explorer-basics/latest/equality-explorer-basics_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "等式探索",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/equality-explorer/latest/equality-explorer_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "面积模型代数",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/area-model-algebra/latest/area-model-algebra_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "面积模型:小数",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/area-model-decimals/latest/area-model-decimals_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "面积模型乘法",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/area-model-multiplication/latest/area-model-multiplication_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "面积模型入门",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/area-model-introduction/latest/area-model-introduction_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "钟摆实验",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/pendulum-lab/latest/pendulum-lab_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "斜抛运动",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/projectile-motion/latest/projectile-motion_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "表达式变换",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/expression-exchange/latest/expression-exchange_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "电路建设工具包:交流",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/circuit-construction-kit-ac/latest/circuit-construction-kit-ac_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "交流虚拟实验室",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/circuit-construction-kit-ac-virtual-lab/latest/circuit-construction-kit-ac-virtual-lab_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "碰撞实验室",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/collision-lab/latest/collision-lab_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "能量滑板竞技场",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/energy-skate-park/latest/energy-skate-park_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "向量相加",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/vector-addition/latest/vector-addition_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "曲线拟合",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/curve-fitting/latest/curve-fitting_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "引力实验室:基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/gravity-force-lab-basics/latest/gravity-force-lab-basics_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "波动入门",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/waves-intro/latest/waves-intro_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "扩散",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/diffusion/latest/diffusion_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "气体基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/gases-intro/latest/gases-intro_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "气体性质",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/gas-properties/latest/gas-properties_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "质量与弹簧:基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/masses-and-springs-basics/latest/masses-and-springs-basics_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "黑体辐射",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/blackbody-spectrum/latest/blackbody-spectrum_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "能量的形式和转换",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/energy-forms-and-changes/latest/energy-forms-and-changes_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "波的干涉",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/wave-interference/latest/wave-interference_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "库仑定律",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/coulombs-law/latest/coulombs-law_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "质量和弹簧",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/masses-and-springs/latest/masses-and-springs_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "电容器实验:基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/capacitor-lab-basics/latest/capacitor-lab-basics_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "电路组建实验:直流虚拟实验室",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/circuit-construction-kit-dc-virtual-lab/latest/circuit-construction-kit-dc-virtual-lab_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "电路组建实验:直流",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/circuit-construction-kit-dc/latest/circuit-construction-kit-dc_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "钟摆实验",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/pendulum-lab/latest/pendulum-lab_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "斜抛运动",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/projectile-motion/latest/projectile-motion_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "物质状态:基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/states-of-matter-basics/latest/states-of-matter-basics_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "物质状态",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/states-of-matter/latest/states-of-matter_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "重力和轨道",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/gravity-and-orbits/latest/gravity-and-orbits_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "分子与光",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/molecules-and-light/latest/molecules-and-light_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "PH值",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/ph-scale/latest/ph-scale_zh_CN.html",
|
|
||||||
"subject": "biology"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "光的混合",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/color-vision/latest/color-vision_zh_CN.html",
|
|
||||||
"subject": "biology"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "自然选择",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/natural-selection/latest/natural-selection_zh_CN.html",
|
|
||||||
"subject": "biology"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "受到压力",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/under-pressure/latest/under-pressure_zh_CN.html",
|
|
||||||
"subject": "sciences"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "万有引力实验",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/gravity-force-lab/latest/gravity-force-lab_zh_CN.html",
|
|
||||||
"subject": "sciences"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "气球和静电(摩擦起电)",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/balloons-and-static-electricity/latest/balloons-and-static-electricity_zh_CN.html",
|
|
||||||
"subject": "sciences"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "气体基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/gases-intro/latest/gases-intro_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "气体性质",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/gas-properties/latest/gas-properties_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "黑体辐射",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/blackbody-spectrum/latest/blackbody-spectrum_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "能量的形式和转换",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/energy-forms-and-changes/latest/energy-forms-and-changes_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "库仑定律",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/coulombs-law/latest/coulombs-law_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "分子极性",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/molecule-polarity/latest/molecule-polarity_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "物质状态:基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/states-of-matter-basics/latest/states-of-matter-basics_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "物质状态",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/states-of-matter/latest/states-of-matter_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "原子的相互作用",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/atomic-interactions/latest/atomic-interactions_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "卢瑟福散射",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/rutherford-scattering/latest/rutherford-scattering_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "原子的相互作用",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/atomic-interactions/latest/atomic-interactions_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"senior": [
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "一次线性函数的拟合",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/least-squares-regression/latest/least-squares-regression_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "区域建造者",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/area-builder/latest/area-builder_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "绳波",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/wave-on-a-string/latest/wave-on-a-string_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "直线图形",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/graphing-lines/latest/graphing-lines_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "分数配对",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/fraction-matcher/latest/fraction-matcher_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "平衡探究实验",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/balancing-act/latest/balancing-act_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "绘图:斜率与截距",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/graphing-slope-intercept/latest/graphing-slope-intercept_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "函数构造器:基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/function-builder-basics/latest/function-builder-basics_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "比例游乐场",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/proportion-playground/latest/proportion-playground_zh_CN.html",
|
|
||||||
"subject": "math"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "二项分布弹珠台几率",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/plinko-probability/latest/plinko-probability_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "原子的相互作用",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/atomic-interactions/latest/atomic-interactions_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "电荷与电场",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/charges-and-fields/latest/charges-and-fields_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "卢瑟福散射",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/rutherford-scattering/latest/rutherford-scattering_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "光的折射",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/bending-light/latest/bending-light_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "胡克定律",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/hookes-law/latest/hookes-law_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "部分电路欧姆定律",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/ohms-law/latest/ohms-law_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "电线的电阻",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/resistance-in-a-wire/latest/resistance-in-a-wire_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "原子模型",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/build-an-atom/latest/build-an-atom_zh_CN.html",
|
|
||||||
"subject": "physics"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "分子极性",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/molecule-polarity/latest/molecule-polarity_zh_CN.html",
|
|
||||||
"subject": "biology"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "神经元",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/neuron/latest/neuron_zh_CN.html",
|
|
||||||
"subject": "biology"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "引力实验室:基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/gravity-force-lab-basics/latest/gravity-force-lab-basics_zh_CN.html",
|
|
||||||
"subject": "sciences"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "波动入门",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/waves-intro/latest/waves-intro_zh_CN.html",
|
|
||||||
"subject": "sciences"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "扩散",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/diffusion/latest/diffusion_zh_CN.html",
|
|
||||||
"subject": "sciences"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "气体基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/gases-intro/latest/gases-intro_zh_CN.html",
|
|
||||||
"subject": "sciences"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "气体性质",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/gas-properties/latest/gas-properties_zh_CN.html",
|
|
||||||
"subject": "sciences"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "分子与光",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/molecules-and-light/latest/molecules-and-light_zh_CN.html",
|
|
||||||
"subject": "sciences"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "绳波",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/wave-on-a-string/latest/wave-on-a-string_zh_CN.html",
|
|
||||||
"subject": "sciences"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "黑体辐射",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/blackbody-spectrum/latest/blackbody-spectrum_zh_CN.html",
|
|
||||||
"subject": "sciences"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "波的干涉",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/wave-interference/latest/wave-interference_zh_CN.html",
|
|
||||||
"subject": "sciences"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "重力和轨道",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/gravity-and-orbits/latest/gravity-and-orbits_zh_CN.html",
|
|
||||||
"subject": "sciences"
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
"label": "同位素和原子的质量",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/isotopes-and-atomic-mass/latest/isotopes-and-atomic-mass_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "分子与光",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/molecules-and-light/latest/molecules-and-light_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "分子形状",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/molecule-shapes/latest/molecule-shapes_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "分子形状:基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/molecule-shapes-basics/latest/molecule-shapes-basics_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "反应物,生成物及未反应物",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/reactants-products-and-leftovers/latest/reactants-products-and-leftovers_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "pH值:基础",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/ph-scale-basics/latest/ph-scale-basics_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "绳波",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/wave-on-a-string/latest/wave-on-a-string_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "PH值",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/ph-scale/latest/ph-scale_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "配平化学方程式",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/balancing-chemical-equations/latest/balancing-chemical-equations_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "酸碱溶度",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/acid-base-solutions/latest/acid-base-solutions_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "浓度",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/concentration/latest/concentration_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "气球和静电(摩擦起电)",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/balloons-and-static-electricity/latest/balloons-and-static-electricity_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "比尔定律实验",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/beers-law-lab/latest/beers-law-lab_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},{
|
|
||||||
"label": "摩尔浓度",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/molarity/latest/molarity_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "原子模型",
|
|
||||||
"fileurl": "https://phet.colorado.edu/sims/html/build-an-atom/latest/build-an-atom_zh_CN.html",
|
|
||||||
"subject": "chemistry"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -106,22 +106,6 @@ const getBackGroundV2 = async () => {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const createOutlineV2 = async (data) => {
|
|
||||||
try {
|
|
||||||
const response = await request({
|
|
||||||
url:"/api/aipptV2/createOutlineV2",
|
|
||||||
method: "POST",
|
|
||||||
data
|
|
||||||
});
|
|
||||||
console.log("createOutline response:", response);
|
|
||||||
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("请求失败:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const createPPTV2 = async (data) => {
|
const createPPTV2 = async (data) => {
|
||||||
try {
|
try {
|
||||||
const response = await req("/api/aipptV2/createV2", "POST", data);
|
const response = await req("/api/aipptV2/createV2", "POST", data);
|
||||||
|
@ -133,18 +117,6 @@ const createPPTV2 = async (data) => {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const createPptByOutline = async (data) => {
|
|
||||||
try {
|
|
||||||
const response = await req("/api/aipptV2/createPptByOutline", "POST", data);
|
|
||||||
console.log("createOutline response:", response);
|
|
||||||
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("请求失败:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const getProgressV2 = async (id) => {
|
const getProgressV2 = async (id) => {
|
||||||
try {
|
try {
|
||||||
const response = await req(`/api/aipptV2/progressV2?sid=${id}`, "GET");
|
const response = await req(`/api/aipptV2/progressV2?sid=${id}`, "GET");
|
||||||
|
@ -155,4 +127,4 @@ const getProgressV2 = async (id) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export { createOutline, getBackGround, createPPT, getProgress, getBackGroundV2, createOutlineV2, createPPTV2, getProgressV2, createByOutline, createPptByOutline };
|
export { createOutline, getBackGround, createPPT, getProgress, getBackGroundV2, createPPTV2, getProgressV2, createByOutline };
|
||||||
|
|
|
@ -1,210 +0,0 @@
|
||||||
/**
|
|
||||||
* ppt 相关方法
|
|
||||||
*/
|
|
||||||
import { h, render, getCurrentInstance } from 'vue'
|
|
||||||
import { toPng, toJpeg } from 'html-to-image' // 引入html-to-image库
|
|
||||||
import { PPTXFileToJson } from "@/AixPPTist/src/hooks/useImport"
|
|
||||||
import ThumbnailSlide from '@/AixPPTist/src/views/components/ThumbnailSlide/index.vue'
|
|
||||||
import { useSlidesStore } from '@/AixPPTist/src/store'
|
|
||||||
import * as ElementPlus from 'element-plus'
|
|
||||||
import { sessionStore } from '@/utils/store' // electron-store 状态管理
|
|
||||||
import { getStaticUrl } from '@/utils/tool' // 工具类
|
|
||||||
import * as Http_Classcourse from '@/api/teaching/classcourse' // api接口
|
|
||||||
|
|
||||||
// 延时
|
|
||||||
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description: 渲染组件
|
|
||||||
* @param {*} node 节点或属性
|
|
||||||
* @param {*} props 属性
|
|
||||||
* @param {*} children 子元素
|
|
||||||
* @param {*} container 容器
|
|
||||||
*/
|
|
||||||
const renderComponent = (node, props = {}, children, container) => {
|
|
||||||
let vNode, body
|
|
||||||
if (!node) throw new Error('vNode is required')
|
|
||||||
if (typeof container == 'string') {
|
|
||||||
if (node == 'slide') {
|
|
||||||
vNode = h(ThumbnailSlide, props, children)
|
|
||||||
} else throw new Error('vNode has no corresponding component')
|
|
||||||
} else {
|
|
||||||
vNode = h(node, props, children)
|
|
||||||
}
|
|
||||||
if (!container) body = document.body // 默认为body
|
|
||||||
else { // 判断是否为字符串
|
|
||||||
if (typeof container == 'string') {
|
|
||||||
body = document.querySelector(container)
|
|
||||||
} else {
|
|
||||||
body = container
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return render(vNode, body)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description: 幻灯片转换为图片
|
|
||||||
* 提示:icon组件找不到是应为 h() 渲染是底层创建的虚拟节点,找不到全局组件
|
|
||||||
* @param {*} slides 幻灯片数据
|
|
||||||
* @param {*} options 配置 number 为幻灯片宽度 | object 为配置项
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export const slidesToImg = (slides = [], options) => {
|
|
||||||
let width, option, ispng = true
|
|
||||||
if (typeof options =='number'){width = options; option = {}}
|
|
||||||
else {const { width: w, isPng, ...opt } = options;width = w; ispng=isPng; option = opt}
|
|
||||||
const slidesStore = useSlidesStore()
|
|
||||||
!!width && slidesStore.setViewportSize(width) // 设置幻灯片宽度
|
|
||||||
return new Promise(async(resolve) => {
|
|
||||||
const instance = getCurrentInstance()
|
|
||||||
console.log('instance', instance)
|
|
||||||
const slidesDom = []
|
|
||||||
for(const slide of slides) {
|
|
||||||
const props = { class: 'c-thumbnail', slide, size: 120, ...option }
|
|
||||||
const node = h(ThumbnailSlide, props)
|
|
||||||
slidesDom.push(node)
|
|
||||||
}
|
|
||||||
// 渲染组件到body
|
|
||||||
const props = { class: 'c-thumbnails', style:{position:'absolute',top:0,left:'-200vw'}}
|
|
||||||
renderComponent('div', props, slidesDom)
|
|
||||||
let imgs = []
|
|
||||||
const toImag = ispng? toPng : toJpeg
|
|
||||||
for(const slide of slidesDom) {
|
|
||||||
const img = await toImag(slide.el)
|
|
||||||
imgs.push(img)
|
|
||||||
}
|
|
||||||
// console.log('ppt生成图片: ', imgs)
|
|
||||||
// console.log('图片已生成,正在卸载组件')
|
|
||||||
!!width && slidesStore.setViewportSize(1000) // 设置幻灯片宽度-恢复
|
|
||||||
render(null, document.body) // 卸载组件
|
|
||||||
resolve(imgs)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* description: ppt 文件转换为图片
|
|
||||||
* @param {*} file file 为文件对象| arrayBuffer 为数组
|
|
||||||
* @param {*} options 配置 number 为幻灯片宽度 | object 为配置项
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export const pptToImg = async(file, options) => {
|
|
||||||
const { slides } = await PPTXFileToJson(file)
|
|
||||||
return slidesToImg(slides, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 课堂-分享码
|
|
||||||
*/
|
|
||||||
export const ShareCode = async(code, cb) => {
|
|
||||||
let shareCode
|
|
||||||
if (typeof code =='string') shareCode = code
|
|
||||||
else { // 自动获取邀请码
|
|
||||||
const classcourse = sessionStore.get('curr.classcourse') // 课堂信息
|
|
||||||
if (!classcourse) return ElementPlus.ElMessage.warning('没有课堂信息')
|
|
||||||
const isRefresh = typeof code == 'boolean' && code // 是否刷新邀请码
|
|
||||||
shareCode = classcourse.shareCode
|
|
||||||
if (!shareCode || isRefresh) { // 获取邀请码
|
|
||||||
const res = await Http_Classcourse.getShareCode(classcourse.id)
|
|
||||||
shareCode = res.msg
|
|
||||||
// 更新邀请码
|
|
||||||
sessionStore.set('curr.classcourse.shareCode', shareCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const msg = h('div', [
|
|
||||||
h('h1', [`我的邀请码:`, h('b',{style:{color:'#F56C6C',fontSize:'1.5em'}}, shareCode)]),
|
|
||||||
h('div', {style:{color:'#E6A23C',fontSize:'13px'}}, `该邀请码1小时内有效,请在学生端填写邀请码后即可进入课堂。`)
|
|
||||||
])
|
|
||||||
return ElementPlus.ElMessageBox.alert(msg, '分享课程', {
|
|
||||||
confirmButtonText: '更新',
|
|
||||||
cancelButtonText: '关闭',
|
|
||||||
showCancelButton: true,
|
|
||||||
|
|
||||||
beforeClose: (action, instance, done) => {
|
|
||||||
if (action =='confirm') { // 更新
|
|
||||||
if (!!cb) { // 回调
|
|
||||||
cb({ h, instance, action, done }, done) && done()
|
|
||||||
} else { // 默认更新
|
|
||||||
ShareCode(true)
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
} else done()
|
|
||||||
}
|
|
||||||
}).catch(() => {})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 提示框
|
|
||||||
* @param {*} msg 内容
|
|
||||||
* @param {*} title 标题
|
|
||||||
* @param {*} option 配置
|
|
||||||
* @param {*} cb 关闭前回调 ({ h, instance, action, done }, done)
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
export const Alert = async (msg, title, option, cb) => {
|
|
||||||
try {
|
|
||||||
if (typeof msg == 'function') msg = await msg(h)
|
|
||||||
return await ElementPlus.ElMessageBox.alert(msg, title, {
|
|
||||||
confirmButtonText: '确认',
|
|
||||||
cancelButtonText: '关闭',
|
|
||||||
showCancelButton: true,
|
|
||||||
beforeClose: (action, instance, done) => {
|
|
||||||
if (action == 'confirm') { // 确认
|
|
||||||
if (!!cb) { // 回调
|
|
||||||
cb({ h, instance, action, done }, done) && done()
|
|
||||||
} else { // 默认确认
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
} else done()
|
|
||||||
},
|
|
||||||
...option,
|
|
||||||
})
|
|
||||||
} catch { }
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 课堂工具栏-钩子
|
|
||||||
*/
|
|
||||||
export const ToolType = {
|
|
||||||
/** 分享码 */
|
|
||||||
SHARE_CODE: 'shareCode',
|
|
||||||
/** 课堂点名 */
|
|
||||||
NAMED: 'named',
|
|
||||||
}
|
|
||||||
export const ToolHandle = async(type, data, cb) => {
|
|
||||||
const classcourse = sessionStore.get('curr.classcourse') // 课堂信息
|
|
||||||
switch (type) {
|
|
||||||
case ToolType.SHARE_CODE:
|
|
||||||
return ShareCode(data, cb)
|
|
||||||
case ToolType.NAMED: {
|
|
||||||
if (!classcourse) return ElementPlus.ElMessage.warning('没有课堂信息!')
|
|
||||||
const avatar = getStaticUrl('/icon/avatar.svg')
|
|
||||||
const timgroupid = classcourse.timgroupid
|
|
||||||
if (!timgroupid) return ElementPlus.ElMessage.warning('没有课堂群信息!')
|
|
||||||
// 课堂点名
|
|
||||||
const res = await Http_Classcourse.rollCall(timgroupid)
|
|
||||||
if (!(res && res.code == 200 && res.data)) return ElementPlus.ElMessage.warning('点名失败!')
|
|
||||||
const userList = res?.data || []
|
|
||||||
const refresh = () => { ToolHandle(ToolType.NAMED); return true }
|
|
||||||
Alert(h => {
|
|
||||||
const attr_0 = {style:{display:'flex',gap:'10px', cursor:'pointer'}}
|
|
||||||
const attr_1 = { style:{display:'inline-flex',alignItems:'center',gap:'10px',padding:'5px 10px'}}
|
|
||||||
const attr_2 = { src: avatar, style: { width: '50px', height: '50px' }}
|
|
||||||
const attr_3 = { style: { fontSize: '20px', fontWeight: 'bold', color: '#409EFF' }}
|
|
||||||
const attr_4 = { style: { fontSize: '12px' }}
|
|
||||||
const userList_H = userList.map(o => {
|
|
||||||
attr_1.title = o.name
|
|
||||||
attr_4.style.color = o.online ? '#67C23A' : '#F56C6C'
|
|
||||||
return h('div', attr_1, [
|
|
||||||
h('img', attr_2),
|
|
||||||
h('div', [
|
|
||||||
h('p', attr_3, o.name),
|
|
||||||
h('span', attr_4, o.online?'在线':'离线')
|
|
||||||
])
|
|
||||||
])
|
|
||||||
})
|
|
||||||
return h('div', attr_0, userList_H)
|
|
||||||
}, '课堂点名', { confirmButtonText: '刷新' }, refresh)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,3 @@
|
||||||
import {ElMessage} from "element-plus";
|
|
||||||
|
|
||||||
const { ipcRenderer } = window.electron || {}
|
const { ipcRenderer } = window.electron || {}
|
||||||
|
|
||||||
export const asyncLocalFile = (item) => {
|
export const asyncLocalFile = (item) => {
|
||||||
|
@ -11,15 +9,12 @@ export const asyncLocalFile = (item) => {
|
||||||
if (isAsync === true) {
|
if (isAsync === true) {
|
||||||
item.async = 'on'
|
item.async = 'on'
|
||||||
if (type === 'down') {
|
if (type === 'down') {
|
||||||
// console.log(item)
|
console.log(item)
|
||||||
ipcRenderer.send('download-file-default', {
|
ipcRenderer.send('download-file-default', {
|
||||||
url: item.fileFullPath,
|
url: item.fileFullPath,
|
||||||
fileName: item.fileNewName
|
fileName: item.fileNewName
|
||||||
})
|
})
|
||||||
ipcRenderer.once('download-file-default' + item.fileNewName, (e, isSuccess) => {
|
ipcRenderer.once('download-file-default' + item.fileNewName, (e, isSuccess) => {
|
||||||
if (isSuccess == false) {
|
|
||||||
ElMessage.error(`${item.fileShowName}下载失败!`)
|
|
||||||
}
|
|
||||||
item.async = isSuccess
|
item.async = isSuccess
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
|
@ -117,24 +112,3 @@ export const creatAIPPT = (name, url, uploadData) => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const removeLocalFiles = async (list) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
ipcRenderer.send('remove-local-file-list', JSON.parse(JSON.stringify(list)))
|
|
||||||
ipcRenderer.removeListener('remove-local-file-list-error', removeLocalFileListError)
|
|
||||||
ipcRenderer.removeListener('remove-local-file-list-not', removeLocalFileListNot)
|
|
||||||
ipcRenderer.on('remove-local-file-list-error', removeLocalFileListError)
|
|
||||||
ipcRenderer.on('remove-local-file-list-not', removeLocalFileListNot)
|
|
||||||
ipcRenderer.once('remove-local-file-list-reply', (e, res) => {
|
|
||||||
resolve(res)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeLocalFileListError(e, item) {
|
|
||||||
ElMessage.error(`${item.fileShowName}删除失败`)
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeLocalFileListNot(e, item) {
|
|
||||||
ElMessage.error(`${item.fileShowName}删除失败,并没有该文件!`)
|
|
||||||
}
|
|
||||||
|
|
|
@ -248,11 +248,10 @@ export function toolWindow(type, {url, isConsole, isWeb=true, option={}}) {
|
||||||
const devUrl = `${BaseUrl}${url}`
|
const devUrl = `${BaseUrl}${url}`
|
||||||
const buildUrl = path.join(__dirname, 'index.html')
|
const buildUrl = path.join(__dirname, 'index.html')
|
||||||
const urlAll = isDev ? devUrl : buildUrl
|
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) => {
|
return new Promise(async(resolve) => {
|
||||||
const config = {
|
const config = {
|
||||||
width, height,
|
width, height,
|
||||||
icon: path.join(appPath, logoIco),
|
icon: path.join(appPath, '/resources/logo2.ico'),
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
preload: path.join(API.preloadPath, '/index.js'),
|
preload: path.join(API.preloadPath, '/index.js'),
|
||||||
sandbox: false,
|
sandbox: false,
|
||||||
|
|
|
@ -154,14 +154,14 @@ const getClassWorkList = async () => {
|
||||||
|
|
||||||
// ----------------------------------------------
|
// ----------------------------------------------
|
||||||
// 处理任务类型的UI
|
// 处理任务类型的UI
|
||||||
if (list[i].worktype == '课堂展示') {
|
if (list[i].worktype == '学习目标定位') {
|
||||||
list[i].workclass = 'success'
|
list[i].workclass = 'success'
|
||||||
list[i].workcodesList = JSON.parse(list[i].workcodes)
|
list[i].workcodesList = JSON.parse(list[i].workcodes)
|
||||||
} else if (list[i].worktype == '科学实验') {
|
} else if (list[i].worktype == '教材研读') {
|
||||||
list[i].workclass = 'primary'
|
list[i].workclass = 'primary'
|
||||||
} else if (list[i].worktype == '框架梳理') {
|
} else if (list[i].worktype == '框架梳理') {
|
||||||
list[i].workclass = 'warning'
|
list[i].workclass = 'warning'
|
||||||
} else if (list[i].worktype == '常规作业') {
|
} else if (list[i].worktype == '学科定位') {
|
||||||
list[i].workclass = 'info'
|
list[i].workclass = 'info'
|
||||||
} else if (list[i].worktype == '习题训练') {
|
} else if (list[i].worktype == '习题训练') {
|
||||||
list[i].workclass = 'danger'
|
list[i].workclass = 'danger'
|
||||||
|
|
|
@ -437,15 +437,13 @@ const queryPushRecords = (row) => {
|
||||||
// } else
|
// } else
|
||||||
// 课标研读 目标设定 教材研读 框架梳理 学科定位 TODO 后续接入在添加
|
// 课标研读 目标设定 教材研读 框架梳理 学科定位 TODO 后续接入在添加
|
||||||
if (res.rows[i].worktype == '课堂展示') {
|
if (res.rows[i].worktype == '课堂展示') {
|
||||||
res.rows[i].workclass = 'success';
|
res.rows[i].workclass = 'primary';
|
||||||
} else if (res.rows[i].worktype == '框架梳理') {
|
} else if (res.rows[i].worktype == '框架梳理') {
|
||||||
res.rows[i].workclass = 'warning';
|
res.rows[i].workclass = 'warning';
|
||||||
} else if (res.rows[i].worktype == '常规作业') {
|
} else if (res.rows[i].worktype == '常规作业') {
|
||||||
res.rows[i].workclass = 'info';
|
res.rows[i].workclass = 'info';
|
||||||
} else if (res.rows[i].worktype == '习题训练') {
|
} else if (res.rows[i].worktype == '习题训练') {
|
||||||
res.rows[i].workclass = 'danger';
|
res.rows[i].workclass = 'danger';
|
||||||
} else if (res.rows[i].worktype == '科学实验') {
|
|
||||||
res.rows[i].workclass = 'primary';
|
|
||||||
} else {
|
} else {
|
||||||
res.rows[i].workclass = 'primary';
|
res.rows[i].workclass = 'primary';
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,8 +141,7 @@
|
||||||
v-if="
|
v-if="
|
||||||
dialogProps.studentObj.worktype == '常规作业' ||
|
dialogProps.studentObj.worktype == '常规作业' ||
|
||||||
dialogProps.studentObj.worktype == '课堂展示' ||
|
dialogProps.studentObj.worktype == '课堂展示' ||
|
||||||
dialogProps.studentObj.worktype == '框架梳理' ||
|
dialogProps.studentObj.worktype == '框架梳理'
|
||||||
dialogProps.studentObj.worktype == '科学实验'
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div v-for="(stuItem, sIndex) in dialogProps.studentQuizAllList" :key="stuItem.id">
|
<div v-for="(stuItem, sIndex) in dialogProps.studentQuizAllList" :key="stuItem.id">
|
||||||
|
@ -158,8 +157,7 @@
|
||||||
v-if="
|
v-if="
|
||||||
dialogProps.studentObj.worktype == '常规作业' ||
|
dialogProps.studentObj.worktype == '常规作业' ||
|
||||||
dialogProps.studentObj.worktype == '课堂展示' ||
|
dialogProps.studentObj.worktype == '课堂展示' ||
|
||||||
dialogProps.studentObj.worktype == '框架梳理' ||
|
dialogProps.studentObj.worktype == '框架梳理'
|
||||||
dialogProps.studentObj.worktype == '科学实验'
|
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<!-- 文件内容格式:mp3/mp4/doc/docx/excel/pdf/ppt/pptx/jpg/jpeg/gif/png/txt ->
|
<!-- 文件内容格式:mp3/mp4/doc/docx/excel/pdf/ppt/pptx/jpg/jpeg/gif/png/txt ->
|
||||||
|
@ -212,13 +210,7 @@
|
||||||
|
|
||||||
<!-- 学生答题展示 -->
|
<!-- 学生答题展示 -->
|
||||||
<div v-if="feedContentList.length > 0">
|
<div v-if="feedContentList.length > 0">
|
||||||
<div
|
<div v-if="dialogProps.studentObj.worktype == '常规作业' && stuItem.rightanswer != ''&& stuItem.rightanswer != null">
|
||||||
v-if="
|
|
||||||
(dialogProps.studentObj.worktype == '常规作业' || dialogProps.studentObj.worktype == '科学实验') &&
|
|
||||||
stuItem.rightanswer != '' &&
|
|
||||||
stuItem.rightanswer != null
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<!-- 常规作业:学生有的会答复 -->
|
<!-- 常规作业:学生有的会答复 -->
|
||||||
<p style="padding: 10px 0;text-align: left;">学生答复内容</p>
|
<p style="padding: 10px 0;text-align: left;">学生答复内容</p>
|
||||||
<div style="padding: 0 20px;text-align: left;">{{stuItem.rightanswer}}</div>
|
<div style="padding: 0 20px;text-align: left;">{{stuItem.rightanswer}}</div>
|
||||||
|
@ -435,7 +427,7 @@ import useUserStore from '@/store/modules/user'
|
||||||
import { ref, reactive } from 'vue'
|
import { ref, reactive } from 'vue'
|
||||||
// import { Plus } from '@element-plus/icons-vue'
|
// import { Plus } from '@element-plus/icons-vue'
|
||||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||||
import { getClassworkdata, updateClassworkevalList, updateClassWorkDataAutoFinish } from '@/api/classTask'
|
import { updateClassworkeval, updateClassworkdata, getClassworkdata } from '@/api/classTask'
|
||||||
import { getTimeDate } from '@/utils/date'
|
import { getTimeDate } from '@/utils/date'
|
||||||
import ReFilePreview from '@/components/refile-preview/index.vue'
|
import ReFilePreview from '@/components/refile-preview/index.vue'
|
||||||
import { quizStrToList } from '@/utils/comm';
|
import { quizStrToList } from '@/utils/comm';
|
||||||
|
@ -708,8 +700,7 @@ const acceptParams = async (params) => {
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// 学生回答
|
// 学生回答
|
||||||
if (params.studentObj.worktype == '常规作业' || params.studentObj.worktype == '科学实验') {
|
if (params.studentObj.worktype == '常规作业') {
|
||||||
if(params.studentObj.worktype == '常规作业'){
|
|
||||||
try {
|
try {
|
||||||
// 老师布置的附件 datacontent TODO:常规作业、其他类型还未接入
|
// 老师布置的附件 datacontent TODO:常规作业、其他类型还未接入
|
||||||
const res = await getClassworkdata(params.studentObj.id);
|
const res = await getClassworkdata(params.studentObj.id);
|
||||||
|
@ -734,9 +725,6 @@ const acceptParams = async (params) => {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Invalid JSON:', error)
|
console.error('Invalid JSON:', error)
|
||||||
}
|
}
|
||||||
}else{
|
|
||||||
// TODO 科学实验 老师布置的活动 暂时不在批改中显示 2024-12-20
|
|
||||||
}
|
|
||||||
|
|
||||||
params.studentQuizAllList.forEach((item) => {
|
params.studentQuizAllList.forEach((item) => {
|
||||||
classWorkFormScore.teacherRating.push({
|
classWorkFormScore.teacherRating.push({
|
||||||
|
@ -890,12 +878,12 @@ const onSubmit = () => {
|
||||||
updatedate: getTimeDate(),// = year+'-'+month+'-'+day+' '+hh+':'+mm;
|
updatedate: getTimeDate(),// = year+'-'+month+'-'+day+' '+hh+':'+mm;
|
||||||
};
|
};
|
||||||
// 更新作业批改状态
|
// 更新作业批改状态
|
||||||
updateClassWorkDataAutoFinish(formd).then(res => {
|
updateClassworkdata(formd).then(res => {
|
||||||
})
|
})
|
||||||
|
|
||||||
// 更新题目批改
|
// 更新题目批改
|
||||||
const queryList = [];
|
classWorkFormScore.teacherRating &&
|
||||||
classWorkFormScore.teacherRating && classWorkFormScore.teacherRating.map((item, index) => {
|
classWorkFormScore.teacherRating.map((item, index) => {
|
||||||
const queryParams = {
|
const queryParams = {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
teacherRating: item.score, // 教师评分
|
teacherRating: item.score, // 教师评分
|
||||||
|
@ -903,32 +891,13 @@ const onSubmit = () => {
|
||||||
teacherremark: classWorkFormScore.teacherremark, //评分说明
|
teacherremark: classWorkFormScore.teacherremark, //评分说明
|
||||||
timestamp: getTimeDate() // 时间
|
timestamp: getTimeDate() // 时间
|
||||||
}
|
}
|
||||||
queryList.push(queryParams)
|
console.log(queryParams)
|
||||||
})
|
updateClassworkeval(queryParams).then((res) => {
|
||||||
//console.log('queryList->', queryList)
|
|
||||||
updateClassworkevalList(queryList).then((res) => {
|
|
||||||
// if(res.code == 200){
|
// if(res.code == 200){
|
||||||
// 循环提交能干个啥
|
// 循环提交能干个啥
|
||||||
// }
|
// }
|
||||||
})
|
})
|
||||||
|
})
|
||||||
// 更新题目批改
|
|
||||||
// classWorkFormScore.teacherRating &&
|
|
||||||
// classWorkFormScore.teacherRating.map((item, index) => {
|
|
||||||
// const queryParams = {
|
|
||||||
// id: item.id,
|
|
||||||
// teacherRating: item.score, // 教师评分
|
|
||||||
// rating: classWorkFormScore.rating, // 评价
|
|
||||||
// teacherremark: classWorkFormScore.teacherremark, //评分说明
|
|
||||||
// timestamp: getTimeDate() // 时间
|
|
||||||
// }
|
|
||||||
// console.log(queryParams)
|
|
||||||
// updateClassworkeval(queryParams).then((res) => {
|
|
||||||
// // if(res.code == 200){
|
|
||||||
// // 循环提交能干个啥
|
|
||||||
// // }
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
ElMessage({
|
ElMessage({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: '提交成功!'
|
message: '提交成功!'
|
||||||
|
|
|
@ -55,7 +55,6 @@
|
||||||
<el-col :span="11">
|
<el-col :span="11">
|
||||||
<el-form-item label="知识点" label-width="70">
|
<el-form-item label="知识点" label-width="70">
|
||||||
<el-cascader
|
<el-cascader
|
||||||
disabled
|
|
||||||
v-model="entpCourseWorkQueryParams.point"
|
v-model="entpCourseWorkQueryParams.point"
|
||||||
clearable
|
clearable
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
|
@ -173,7 +172,7 @@
|
||||||
<!-- 非习题训练:常规作业、 -->
|
<!-- 非习题训练:常规作业、 -->
|
||||||
<div v-if="classWorkForm.worktype!='习题训练'">
|
<div v-if="classWorkForm.worktype!='习题训练'">
|
||||||
<div :style="{ 'overflow': 'auto'}">
|
<div :style="{ 'overflow': 'auto'}">
|
||||||
<!-- <template v-if="classWorkForm.worktype!='常规作业'">
|
<template v-if="classWorkForm.worktype!='常规作业'">
|
||||||
<template v-for="(item, index) in workResource.teachResourceList" :key="item">
|
<template v-for="(item, index) in workResource.teachResourceList" :key="item">
|
||||||
<div v-if="item.worktype==classWorkForm.worktype" style="border-bottom: 1px dotted;display: flex;justify-content: space-between;">
|
<div v-if="item.worktype==classWorkForm.worktype" style="border-bottom: 1px dotted;display: flex;justify-content: space-between;">
|
||||||
<div style="margin-bottom: 5px; padding-left: 15px;display: flex;flex-direction: row;align-items: center;">
|
<div style="margin-bottom: 5px; padding-left: 15px;display: flex;flex-direction: row;align-items: center;">
|
||||||
|
@ -194,7 +193,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</template> -->
|
</template>
|
||||||
<template v-if="classWorkForm.worktype =='常规作业'">
|
<template v-if="classWorkForm.worktype =='常规作业'">
|
||||||
<div v-loading="fileLoading" class="upload-homework">
|
<div v-loading="fileLoading" class="upload-homework">
|
||||||
<FileUpload v-model="classWorkForm.fileHomeworkList" :fileSize="800" :fileType="['mp3','mp4','doc','docx','xlsx','xls','pdf','ppt','pptx','jpg','jpeg','gif','png','txt']"/>
|
<FileUpload v-model="classWorkForm.fileHomeworkList" :fileSize="800" :fileType="['mp3','mp4','doc','docx','xlsx','xls','pdf','ppt','pptx','jpg','jpeg','gif','png','txt']"/>
|
||||||
|
@ -286,7 +285,6 @@ import { updateClasswork, listEvaluationclue, listClassworkeval,delClassworkeval
|
||||||
import { listEvaluation } from '@/api/subject'
|
import { listEvaluation } from '@/api/subject'
|
||||||
import { listEntpcoursefile } from '@/api/education/entpcoursefile'
|
import { listEntpcoursefile } from '@/api/education/entpcoursefile'
|
||||||
import { listKnowledgePoint } from "@/api/knowledge/knowledgePoint";
|
import { listKnowledgePoint } from "@/api/knowledge/knowledgePoint";
|
||||||
import { isJson } from "@/utils/comm";
|
|
||||||
|
|
||||||
|
|
||||||
import { useGetHomework } from '@/hooks/useGetHomework'
|
import { useGetHomework } from '@/hooks/useGetHomework'
|
||||||
|
@ -461,13 +459,12 @@ const client = new Apis('/paht');
|
||||||
*/
|
*/
|
||||||
const t = function(name, time) {
|
const t = function(name, time) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const evalId = props.bookobj.levelSecondId=='' ? props.bookobj.levelFirstId : props.bookobj.levelSecondId;
|
|
||||||
const queryForm = {
|
const queryForm = {
|
||||||
// 分页参数
|
// 分页参数
|
||||||
currentPage: paginationParams.pageNum,
|
currentPage: paginationParams.pageNum,
|
||||||
pageSize: paginationParams.pageSize,
|
pageSize: paginationParams.pageSize,
|
||||||
// 课程相关参数
|
// 课程相关参数
|
||||||
eid: evalId, // 当前单元或章节id
|
eid: props.bookobj.levelSecondId,
|
||||||
sectionName: props.bookobj.coursetitle,
|
sectionName: props.bookobj.coursetitle,
|
||||||
edusubject: userStore.edusubject,
|
edusubject: userStore.edusubject,
|
||||||
edustage: userStore.edustage,
|
edustage: userStore.edustage,
|
||||||
|
@ -560,13 +557,10 @@ const getQueryFromEvaluationclue = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clueres.rows[i].childlist != '') {
|
if (clueres.rows[i].childlist != '') {
|
||||||
const tmpJson = '['+clueres.rows[i].childlist+']';
|
clueres.rows[i].childArray = JSON.parse('['+clueres.rows[i].childlist+']');
|
||||||
if (isJson(tmpJson)){
|
|
||||||
clueres.rows[i].childArray = JSON.parse(tmpJson);
|
|
||||||
for (var j=0; j<clueres.rows[i].childArray.length; j++) {
|
for (var j=0; j<clueres.rows[i].childArray.length; j++) {
|
||||||
clueres.rows[i].childArray[j].title = clueres.rows[i].childArray[j].title.replace(/(<([^>]+)>)/ig, '');
|
clueres.rows[i].childArray[j].title = clueres.rows[i].childArray[j].title.replace(/(<([^>]+)>)/ig, '');
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
clueres.rows[i].childArray = {};
|
clueres.rows[i].childArray = {};
|
||||||
}
|
}
|
||||||
|
@ -996,8 +990,6 @@ const initPageParams = () => {
|
||||||
|
|
||||||
|
|
||||||
onMounted(async() => {
|
onMounted(async() => {
|
||||||
// 知识点
|
|
||||||
getEntpCourseWorkPointList();
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// const refreshData = () => {
|
// const refreshData = () => {
|
||||||
|
@ -1024,9 +1016,9 @@ const debounceQueryData = debounce(() => {
|
||||||
// 习题资源
|
// 习题资源
|
||||||
handleQueryFromEntpCourseWork(0);
|
handleQueryFromEntpCourseWork(0);
|
||||||
// 框架梳理
|
// 框架梳理
|
||||||
//getQueryFromEvaluationclue();
|
getQueryFromEvaluationclue();
|
||||||
// 知识点
|
// 知识点
|
||||||
//getEntpCourseWorkPointList();
|
getEntpCourseWorkPointList();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
watch(() => props.propsformobj.uniquekey, (newVal) => {
|
watch(() => props.propsformobj.uniquekey, (newVal) => {
|
||||||
|
@ -1035,20 +1027,8 @@ watch(() => props.propsformobj.uniquekey, (newVal) => {
|
||||||
classWorkForm.uniquekey = props.propsformobj.uniquekey?cloneDeep(props.propsformobj.uniquekey):''; // 作业唯一标识 作业名称
|
classWorkForm.uniquekey = props.propsformobj.uniquekey?cloneDeep(props.propsformobj.uniquekey):''; // 作业唯一标识 作业名称
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
watch(() => props.bookobj.levelSecondId, (newVal, oldVal) => {
|
||||||
|
|
||||||
//watch(() => props.bookobj.levelSecondId, async (newVal, oldVal) => {
|
|
||||||
|
|
||||||
watch([
|
|
||||||
() => props.bookobj.levelFirstId,
|
|
||||||
() => props.bookobj.levelSecondId
|
|
||||||
], ([newLevelSecondId, newLevelFirstId], [oldLevelSecondId, oldLevelFirstId]) => {
|
|
||||||
console.log(props.bookobj,'课程选择')
|
console.log(props.bookobj,'课程选择')
|
||||||
// 默认选择一级单元时, 不自动获取试题, 需手动按钮获取试题
|
|
||||||
if (props.bookobj.levelSecondId == '') {
|
|
||||||
workResource.entpCourseWorkList = [];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
debounceQueryData();
|
debounceQueryData();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -29,15 +29,14 @@ import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
const emit = defineEmits(['itemClick'])
|
const emit = defineEmits(['itemClick'])
|
||||||
const items = shallowRef([
|
const items = shallowRef([
|
||||||
{ title: '自主搜题', description: '上千万高质量习题资源,历届考试真题,每道题均有习题解析', icon: '#icon-soutibao-',type:'danger' },
|
{ title: '自主搜题', description: '上千万高质量习题资源,历届考试真题,每道题均有习题解析', icon: '#icon-soutibao-',type:'primary' },
|
||||||
// { title: '校本题库', description: '本校公共题库资源。', icon: '#icon-soutibao-',type:'danger' },
|
{ title: '校本题库', description: '本校公共题库资源。', icon: '#icon-soutibao-',type:'primary' },
|
||||||
{ title: '个人题库', description: '老师上传维护自己的个人题库。', icon: '#icon-soutibao-',type:'danger' },
|
{ title: '个人题库', description: '老师上传维护自己的个人题库。', icon: '#icon-soutibao-',type:'primary' },
|
||||||
// { title: '智能推荐', description: '通过对学生的薄弱知识点分析,推送不同难度的习题进行强化训练。', icon: '#icon-tubiao_wuxing-',type:'primary' },
|
{ title: '智能推荐', description: '通过对学生的薄弱知识点分析,推送不同难度的习题进行强化训练。', icon: '#icon-tubiao_wuxing-',type:'primary' },
|
||||||
{ title: '课堂展示', description: '通过课堂白板绘制作业,提升学生的创作思维能力。', icon: '#icon-huaban',type:'success' },
|
{ title: '课堂展示', description: '通过课堂白板绘制作业,提升学生的创作思维能力。', icon: '#icon-huaban',type:'danger' },
|
||||||
{ title: '常规作业', description: '推送pdf、视频、音频、图片,学生可以拍照上传。', icon: '#icon-zhaoxiangji',type:'info' },
|
{ title: '常规作业', description: '推送pdf、视频、音频、图片,学生可以拍照上传。', icon: '#icon-zhaoxiangji',type:'danger' },
|
||||||
// { title: 'AI设计作业', description: '通过AI助手,根据课标、教材、考试等分析结果,智能创建作业。', icon: '#icon-jiqiren_o',type:'danger' },
|
{ title: 'AI设计作业', description: '通过AI助手,根据课标、教材、考试等分析结果,智能创建作业。', icon: '#icon-jiqiren_o',type:'danger' },
|
||||||
{ title: '习题上传', description: '自己上传个人题库。', icon: '#icon-shangchuan',type:'danger' },
|
{ title: '习题上传', description: '自己上传个人题库。', icon: '#icon-shangchuan',type:'danger' },
|
||||||
{ title: '科学实验', description: '学生完成虚拟仿真实验,并提交实验结果。', icon: '#icon-shangchuan',type:'primary' },
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const handleClick = (item) => {
|
const handleClick = (item) => {
|
||||||
|
|
|
@ -1,62 +0,0 @@
|
||||||
<template>
|
|
||||||
<div style="display: flex;">
|
|
||||||
<el-select
|
|
||||||
v-model="value"
|
|
||||||
placeholder="请选择实验课程"
|
|
||||||
size="large"
|
|
||||||
style="width: 240px"
|
|
||||||
@change="onSelectOption"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item in classTaskStore.experimentList"
|
|
||||||
:key="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.label"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import useUserStore from '@/store/modules/user'
|
|
||||||
import {ArrowDown} from '@element-plus/icons-vue'
|
|
||||||
import { onMounted,ref } from 'vue';
|
|
||||||
import useClassTaskStore from '@/store/modules/classTask'
|
|
||||||
const userStore = useUserStore().user
|
|
||||||
const subjectList = ref([])
|
|
||||||
const classTaskStore = useClassTaskStore().experimentObj
|
|
||||||
|
|
||||||
// 定义要发送的emit事件
|
|
||||||
let emit = defineEmits(['selectItem'])
|
|
||||||
const props = defineProps({
|
|
||||||
list: {
|
|
||||||
type: Array,
|
|
||||||
default: () => ([])
|
|
||||||
},
|
|
||||||
})
|
|
||||||
const value = ref('')
|
|
||||||
|
|
||||||
const updateLabel = (val) => {
|
|
||||||
value.value = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
const onSelectOption = (option) => {
|
|
||||||
classTaskStore.updateEduInfo = `${classTaskStore.edustage}-${classTaskStore.edusubject}`;
|
|
||||||
console.log('updateEduInfo->', classTaskStore.updateEduInfo);
|
|
||||||
console.log(option,'选择的实验课-------')
|
|
||||||
emit('selectItem', classTaskStore.experimentList.filter(item => item.label === option)[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
})
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
updateLabel
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -1,259 +0,0 @@
|
||||||
<template>
|
|
||||||
<div style="display: flex;">
|
|
||||||
<div style="margin-left: 15px">
|
|
||||||
<el-dropdown @command="handleUserEduStage">
|
|
||||||
<span class="el-dropdown-link">
|
|
||||||
<el-button class="custom-button" type="default" round >{{ useClassTaskStore().experimentObj.edustage }}
|
|
||||||
<el-icon><ArrowDown /></el-icon>
|
|
||||||
</el-button>
|
|
||||||
</span>
|
|
||||||
<template #dropdown>
|
|
||||||
<el-dropdown-menu>
|
|
||||||
<!-- <el-dropdown-item command="幼儿园">幼儿园</el-dropdown-item> -->
|
|
||||||
<el-dropdown-item command="小学">小学</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="初中">初中</el-dropdown-item>
|
|
||||||
<el-dropdown-item command="高中">高中</el-dropdown-item>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</template>
|
|
||||||
</el-dropdown>
|
|
||||||
</div>
|
|
||||||
<div style="margin-left: 15px">
|
|
||||||
<el-dropdown @command="handleUserEduSubject">
|
|
||||||
<span class="el-dropdown-link">
|
|
||||||
<el-button class="custom-button" type="default" round>{{ useClassTaskStore().experimentObj.edusubject }}
|
|
||||||
<el-icon><ArrowDown /></el-icon>
|
|
||||||
</el-button>
|
|
||||||
</span>
|
|
||||||
<template #dropdown>
|
|
||||||
<el-dropdown-menu>
|
|
||||||
<template v-for="(item, index) in subjectList">
|
|
||||||
<el-dropdown-item v-if="item.edustage == useClassTaskStore().experimentObj.edustage && isExpList(item.itemtitle)" :command="item.itemtitle">{{
|
|
||||||
item.itemtitle }}</el-dropdown-item>
|
|
||||||
</template>
|
|
||||||
</el-dropdown-menu>
|
|
||||||
</template>
|
|
||||||
</el-dropdown>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import useUserStore from '@/store/modules/user'
|
|
||||||
import {ArrowDown} from '@element-plus/icons-vue'
|
|
||||||
import { onMounted,ref } from 'vue';
|
|
||||||
import { listEvaluation } from '@/api/subject/index'
|
|
||||||
import jsonData from "@/utils/phetData.json";
|
|
||||||
import useClassTaskStore from '@/store/modules/classTask'
|
|
||||||
const userStore = useUserStore().user
|
|
||||||
|
|
||||||
// 定义要发送的emit事件
|
|
||||||
// let emit = defineEmits(['experlist'])
|
|
||||||
// const expObj = ref({
|
|
||||||
// edustage: useClassTaskStore().experimentObj.edustage,
|
|
||||||
// edusubject: useClassTaskStore().experimentObj.edusubject,
|
|
||||||
// })
|
|
||||||
const subjectList = ref([])
|
|
||||||
const chooseGrade= ref({})
|
|
||||||
const expList = ref([]) // 当前年级的所有课程
|
|
||||||
const checkList = ref([])// 当前年级对应学科的课程,
|
|
||||||
const isLoaded = ref(false);
|
|
||||||
|
|
||||||
// 获取基础的学科
|
|
||||||
const getSubject = () => {
|
|
||||||
//没有学科则不进行下面的步骤
|
|
||||||
// if(!userStore.subject) return
|
|
||||||
// listEvaluation({ itemkey: 'subject', pageSize: 500 }).then((res) => {
|
|
||||||
// const arr = userStore.subject.split(',')
|
|
||||||
// subjectList.value = res.rows.filter(item => arr.includes(String(item.id))).map(items => items)
|
|
||||||
// console.log(subjectList,'subjectList');
|
|
||||||
// })
|
|
||||||
//这里获取死数据 学科list
|
|
||||||
const edustageList = ['小学','初中','高中'];
|
|
||||||
const subList = ['数学','物理','化学','生物','科学'];
|
|
||||||
edustageList.forEach((item) => {
|
|
||||||
subList.forEach((subItems) => {
|
|
||||||
subjectList.value.push({
|
|
||||||
edustage: item,
|
|
||||||
edusubject: subItems,
|
|
||||||
itemtitle: subItems
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
console.log(subjectList,'subjectList');
|
|
||||||
|
|
||||||
// 默认读取一个学科
|
|
||||||
const edusubject = useClassTaskStore().experimentObj.edusubject;
|
|
||||||
handleUserEduStage(useClassTaskStore().experimentObj.edustage);
|
|
||||||
// 这里确保第一次初始化时, 该任务是从左侧作业列表中进来而存在指定的学科时, 重新赋值回来.
|
|
||||||
useClassTaskStore().experimentObj.edusubject = edusubject;
|
|
||||||
// 执行完毕后标志位[置位]
|
|
||||||
isLoaded.value = true;
|
|
||||||
//console.log('初始化执行完毕----');
|
|
||||||
}
|
|
||||||
// 展示有 实验科目的学科
|
|
||||||
const isExpList = (edusubject) => {
|
|
||||||
let list = [];
|
|
||||||
switch (edusubject){
|
|
||||||
case '数学':
|
|
||||||
list = expList.value.filter(item => item.subject === 'math')
|
|
||||||
break;
|
|
||||||
case '物理':
|
|
||||||
list = expList.value.filter(item => item.subject === 'physics')
|
|
||||||
break;
|
|
||||||
case '化学':
|
|
||||||
checkList.value = expList.value.filter(item => item.subject === 'chemistry')
|
|
||||||
break;
|
|
||||||
case '生物':
|
|
||||||
list = expList.value.filter(item => item.subject === 'biology')
|
|
||||||
break;
|
|
||||||
case '科学':
|
|
||||||
list = expList.value.filter(item => item.subject === 'sciences')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return list.length > 0
|
|
||||||
}
|
|
||||||
// 选择学段
|
|
||||||
const handleUserEduStage = (item) => {
|
|
||||||
// userStore.edustage = item
|
|
||||||
useClassTaskStore().experimentObj.edustage = item;
|
|
||||||
|
|
||||||
//清空操作
|
|
||||||
expList.value = []
|
|
||||||
if(item === '小学'){
|
|
||||||
chooseGrade.value = jsonData.data.primary
|
|
||||||
expList.value = chooseGrade.value
|
|
||||||
const newSubjectList = subjectList.value.filter(item => item.edustage === '小学');
|
|
||||||
for(let i in newSubjectList){
|
|
||||||
const name = newSubjectList[i].itemtitle
|
|
||||||
if(isExpList(name) && useClassTaskStore().experimentObj.edusubject===name){
|
|
||||||
//useClassTaskStore().experimentObj.edusubject = name;
|
|
||||||
// 更改学科默认与学科下的实验科目
|
|
||||||
handleUserEduSubject(name)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else if(item === '初中'){
|
|
||||||
chooseGrade.value = jsonData.data.junior
|
|
||||||
expList.value = chooseGrade.value
|
|
||||||
const newSubjectList = subjectList.value.filter(item => item.edustage === '初中');
|
|
||||||
for(let i in newSubjectList){
|
|
||||||
const name = newSubjectList[i].itemtitle
|
|
||||||
if(isExpList(name) && useClassTaskStore().experimentObj.edusubject===name){
|
|
||||||
//useClassTaskStore().experimentObj.edusubject = name;
|
|
||||||
// 更改学科默认与学科下的实验科目
|
|
||||||
handleUserEduSubject(name)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}else if(item === '高中'){
|
|
||||||
chooseGrade.value = jsonData.data.senior
|
|
||||||
expList.value = chooseGrade.value
|
|
||||||
const newSubjectList = subjectList.value.filter(item => item.edustage === '高中');
|
|
||||||
for(let i in newSubjectList){
|
|
||||||
const name = newSubjectList[i].itemtitle
|
|
||||||
if(isExpList(name) && useClassTaskStore().experimentObj.edusubject===name){
|
|
||||||
//useClassTaskStore().experimentObj.edusubject = name;
|
|
||||||
// 更改学科默认与学科下的实验科目
|
|
||||||
handleUserEduSubject(name)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 选择学科
|
|
||||||
const handleUserEduSubject = (item) => {
|
|
||||||
// userStore.edusubject = item;
|
|
||||||
useClassTaskStore().experimentObj.edusubject = item;
|
|
||||||
console.log(item,'选择的学科-------')
|
|
||||||
checkList.value = []
|
|
||||||
switch (item){
|
|
||||||
case '数学':
|
|
||||||
checkList.value = expList.value.filter(item => item.subject === 'math')
|
|
||||||
break;
|
|
||||||
case '物理':
|
|
||||||
checkList.value = expList.value.filter(item => item.subject === 'physics')
|
|
||||||
break;
|
|
||||||
case '化学':
|
|
||||||
checkList.value = expList.value.filter(item => item.subject === 'chemistry')
|
|
||||||
break;
|
|
||||||
case '生物':
|
|
||||||
checkList.value = expList.value.filter(item => item.subject === 'biology')
|
|
||||||
break;
|
|
||||||
case '科学':
|
|
||||||
checkList.value = expList.value.filter(item => item.subject === 'sciences')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
console.log(checkList.value,'checkList')
|
|
||||||
useClassTaskStore().experimentObj.experimentList = checkList.value;
|
|
||||||
// emit('experlist',checkList.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateCheckList = async () => {
|
|
||||||
try {
|
|
||||||
await waitForSubjectData();
|
|
||||||
|
|
||||||
//console.log('父组件执行开始-------', );
|
|
||||||
//console.log('experimentObj-> ', useClassTaskStore().experimentObj);
|
|
||||||
// 再执行更新逻辑
|
|
||||||
const edustage = useClassTaskStore().experimentObj.edustage;
|
|
||||||
if(edustage === '小学'){
|
|
||||||
chooseGrade.value = jsonData.data.primary
|
|
||||||
}else if(edustage === '初中'){
|
|
||||||
chooseGrade.value = jsonData.data.junior
|
|
||||||
}else if(edustage === '高中'){
|
|
||||||
chooseGrade.value = jsonData.data.senior
|
|
||||||
}
|
|
||||||
expList.value = chooseGrade.value
|
|
||||||
const edusubject = useClassTaskStore().experimentObj.edusubject;
|
|
||||||
handleUserEduSubject(edusubject);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const waitForSubjectData = () => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let timeoutId;
|
|
||||||
let intervalId;
|
|
||||||
|
|
||||||
const checkIsLoaded = () => {
|
|
||||||
if (isLoaded.value) {
|
|
||||||
clearInterval(intervalId);
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
intervalId = setInterval(checkIsLoaded, 100);
|
|
||||||
timeoutId = setTimeout(() => {
|
|
||||||
clearInterval(intervalId);
|
|
||||||
reject(new Error('该作业-等待[科学实验]学科学段初始化超时'));
|
|
||||||
}, 5000);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
getSubject()
|
|
||||||
})
|
|
||||||
|
|
||||||
defineExpose({
|
|
||||||
updateCheckList
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style scoped>
|
|
||||||
.custom-button {
|
|
||||||
width: auto;
|
|
||||||
border: 1px solid rgb(59, 130, 246);
|
|
||||||
outline: none;
|
|
||||||
outline-offset: none;
|
|
||||||
padding: 0 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.custom-button i {
|
|
||||||
margin-left: 8px; /* 调整图标与文字之间的间距 */
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
|
@ -1,114 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="experiment-page">
|
|
||||||
<div class="activeExp-header">
|
|
||||||
<div class="infomation" v-if="isStadium() !== true" >
|
|
||||||
<!-- <selectClass v-if="!isSubject" @experlist="getExperimentList" /> -->
|
|
||||||
<selectClass ref="selectClassRef"/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<selectExperiment ref="selectExperimentRef" @selectItem="getExperimentListItem" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div ref="mainDiv" class="activeExp-main" style="overflow: auto">
|
|
||||||
<div v-if="!activeExp.fileurl"><el-empty description="暂无学科实验"></el-empty></div>
|
|
||||||
<iframe v-else :src="activeExp.fileurl" ref="myuunity" width="100%" height="100%" scrolling="no" frameborder="0"></iframe>
|
|
||||||
<!-- <phet/>-->
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script setup>
|
|
||||||
import { Search } from '@element-plus/icons-vue'
|
|
||||||
//import html2canvas from 'html2canvas';
|
|
||||||
import { onMounted, ref, watch, reactive, getCurrentInstance, nextTick } from 'vue'
|
|
||||||
import useUserStore from '@/store/modules/user'
|
|
||||||
import useClassTaskStore from '@/store/modules/classTask'
|
|
||||||
import selectClass from './components/selectClass.vue' //选择学校和班级
|
|
||||||
import selectExperiment from './components/experimentList.vue' // 选择的 学科实验
|
|
||||||
|
|
||||||
|
|
||||||
// 定义要发送的emit事件
|
|
||||||
let emit = defineEmits(['clickExpObj'])
|
|
||||||
const { proxy } = getCurrentInstance()
|
|
||||||
const userStore = useUserStore().user
|
|
||||||
|
|
||||||
const props = defineProps({
|
|
||||||
bookobj: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({})
|
|
||||||
},
|
|
||||||
expObj: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// 学科的 实验列
|
|
||||||
// const experimentList = ref([]);
|
|
||||||
const activeExp = ref({});
|
|
||||||
const selectExperimentRef = ref();
|
|
||||||
const selectClassRef = ref();
|
|
||||||
|
|
||||||
const isStadium = () => {
|
|
||||||
let roles = userStore.roles
|
|
||||||
return roles.some(item => item.roleKey === 'stadium')
|
|
||||||
}
|
|
||||||
|
|
||||||
// const mainLeftBarHeight = ref(0);
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// var mainLeftBar = document.getElementById("mainLeftBar");
|
|
||||||
// mainLeftBarHeight.value = document.documentElement.clientHeight-50-mainLeftBar.offsetParent.offsetTop - 10;
|
|
||||||
|
|
||||||
// getDivHeight()
|
|
||||||
// window.addEventListener('resize', getDivHeight)
|
|
||||||
})
|
|
||||||
// const getDivHeight = () => {
|
|
||||||
// const screenheight = window.innerHeight;
|
|
||||||
// proxy.$refs.mainDiv.style.height = screenheight-140 > 320 ? screenheight-140+'px' : 320+'px';
|
|
||||||
// console.log("height", proxy.$refs.mainDiv.style.height);
|
|
||||||
// // 704 为 头部组件高度 + 底部组件高度
|
|
||||||
// // mainDiv 为需控制高度自适应盒子,通过 ref="mainDiv" 绑定
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 选择的学科 获取实验课程信息
|
|
||||||
// const getExperimentList = (val) => {
|
|
||||||
// console.log(val,'选择的学科,获取实验课程list信息')
|
|
||||||
// // experimentList.value = val;
|
|
||||||
// }
|
|
||||||
// 选择的实验课
|
|
||||||
const getExperimentListItem = (val) => {
|
|
||||||
console.log(val,'选择的实验课程信息')
|
|
||||||
activeExp.value = val;
|
|
||||||
emit('clickExpObj', val)
|
|
||||||
}
|
|
||||||
// 监听实验课程信息
|
|
||||||
watch(() => props.expObj.fileurl, (newVal, oldVal) => {
|
|
||||||
console.log(props.expObj,'科学实验科目')
|
|
||||||
activeExp.value = props.expObj;
|
|
||||||
|
|
||||||
//
|
|
||||||
nextTick(() => {
|
|
||||||
selectClassRef.value.updateCheckList();
|
|
||||||
selectExperimentRef.value.updateLabel(props.expObj.label);
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.experiment-page {
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.activeExp-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.activeExp-main{
|
|
||||||
flex: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
|
@ -58,9 +58,9 @@
|
||||||
<el-tab-pane label="自主搜题" name="自主搜题" class="prepare-center-zzst">
|
<el-tab-pane label="自主搜题" name="自主搜题" class="prepare-center-zzst">
|
||||||
<SearchQuestion :bookobj="courseObj" @addQuiz="handleClassWorkQuizAdd" />
|
<SearchQuestion :bookobj="courseObj" @addQuiz="handleClassWorkQuizAdd" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<!-- <el-tab-pane label="校本题库" name="校本题库" class="prepare-center-xbtk">
|
<el-tab-pane label="校本题库" name="校本题库" class="prepare-center-xbtk">
|
||||||
<SchoolQuestion />
|
<SchoolQuestion />
|
||||||
</el-tab-pane> -->
|
</el-tab-pane>
|
||||||
<el-tab-pane label="个人题库" name="个人题库" class="prepare-center-grst">
|
<el-tab-pane label="个人题库" name="个人题库" class="prepare-center-grst">
|
||||||
<MyQuestion :bookobj="courseObj" @addQuiz="handleClassWorkQuizAdd"/>
|
<MyQuestion :bookobj="courseObj" @addQuiz="handleClassWorkQuizAdd"/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
@ -68,7 +68,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div v-if="(currentRow.worktype == '课堂展示' || classWorkForm.worktype == '课堂展示') && currentRow.id>0" class="page-center">
|
<div v-if="(currentRow.worktype == '课堂展示' || classWorkForm.worktype == '课堂展示') && currentRow.id>0" class="page-center">
|
||||||
<div v-loading="boardLoading" class="board-wrap" style="height: 100%; flex: 1; overflow: hidden;">
|
<div v-loading="boardLoading" class="board-wrap" style="height: 100%; flex: 1; overflow: hidden;">
|
||||||
<whiteboard ref="boardref" height="100%" width="100%" :isShowSave="false" :data="classWorkForm.whiteboardObj" />
|
<!-- <whiteboard v-if="isShowBoard" ref="boardref" :height="mainHeight - 150" :isShowSave="false" :data="whiteboardObj"/> -->
|
||||||
|
<whiteboard ref="boardref" height="100%" width="100%" :isShowSave="false" :data="classWorkForm.whiteboardObj"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="(currentRow.worktype == '常规作业' || classWorkForm.worktype == '常规作业')&& currentRow.id>0" class="page-center">
|
<div v-if="(currentRow.worktype == '常规作业' || classWorkForm.worktype == '常规作业')&& currentRow.id>0" class="page-center">
|
||||||
|
@ -76,11 +77,6 @@
|
||||||
<FileUpload v-model="classWorkForm.fileHomeworkList" :fileSize="800" :fileType="['mp3','mp4','doc','docx','xlsx','xls','pdf','ppt','pptx','jpg','jpeg','gif','png','txt']"/>
|
<FileUpload v-model="classWorkForm.fileHomeworkList" :fileSize="800" :fileType="['mp3','mp4','doc','docx','xlsx','xls','pdf','ppt','pptx','jpg','jpeg','gif','png','txt']"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="(currentRow.worktype == '科学实验' || classWorkForm.worktype == '科学实验')&& currentRow.id>0" class="page-center">
|
|
||||||
<div class="experiment-homework">
|
|
||||||
<ExperimentQuestion :expObj="classWorkForm.fileHomeworkList&&classWorkForm.fileHomeworkList[0]" @clickExpObj="getExpObj" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="currentRow.id>0 " class="page-right">
|
<div v-if="currentRow.id>0 " class="page-right">
|
||||||
<div class="prepare-top" >
|
<div class="prepare-top" >
|
||||||
|
@ -144,7 +140,6 @@ import { editListItem } from '@/hooks/useClassTask'
|
||||||
import MyQuestion from '@/views/classTask/newClassTaskAssign/myQuestion/index.vue'
|
import MyQuestion from '@/views/classTask/newClassTaskAssign/myQuestion/index.vue'
|
||||||
import SchoolQuestion from '@/views/classTask/newClassTaskAssign/schoolQuestion/index.vue'
|
import SchoolQuestion from '@/views/classTask/newClassTaskAssign/schoolQuestion/index.vue'
|
||||||
import SearchQuestion from '@/views/classTask/newClassTaskAssign/searchQuestion/index.vue'
|
import SearchQuestion from '@/views/classTask/newClassTaskAssign/searchQuestion/index.vue'
|
||||||
import ExperimentQuestion from "@/views/classTask/newClassTaskAssign/experimentQuestion/index.vue";
|
|
||||||
import whiteboard from '@/components/whiteboard/whiteboard.vue'
|
import whiteboard from '@/components/whiteboard/whiteboard.vue'
|
||||||
import FileUpload from "@/components/FileUpload/index.vue";
|
import FileUpload from "@/components/FileUpload/index.vue";
|
||||||
import Right from './Right/index.vue'
|
import Right from './Right/index.vue'
|
||||||
|
@ -161,7 +156,6 @@ const route = useRoute();
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { proxy } = getCurrentInstance()
|
const { proxy } = getCurrentInstance()
|
||||||
const useClassTaskStores = useClassTaskStore();
|
const useClassTaskStores = useClassTaskStore();
|
||||||
const { ipcRenderer } = require('electron')
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
currentCourse: Object,
|
currentCourse: Object,
|
||||||
|
@ -170,10 +164,6 @@ const emits = defineEmits(['getData'])
|
||||||
// 这个代表的是是否从ppt里面添加的作业
|
// 这个代表的是是否从ppt里面添加的作业
|
||||||
const isShow = ref(false)
|
const isShow = ref(false)
|
||||||
|
|
||||||
const propsQueryTask = {
|
|
||||||
id: route.query.classTaskId, // 需编辑的作业任务id
|
|
||||||
isInit: false, // 是否已编辑
|
|
||||||
}
|
|
||||||
const propsQueryCourseObj = route.query.courseObj;//作业布置的内容对象
|
const propsQueryCourseObj = route.query.courseObj;//作业布置的内容对象
|
||||||
const courseObj = reactive({
|
const courseObj = reactive({
|
||||||
// 课程相关参数: 教材id,单元id,章节id,课程名称
|
// 课程相关参数: 教材id,单元id,章节id,课程名称
|
||||||
|
@ -203,8 +193,8 @@ const boardLoading = ref(false);
|
||||||
const fileLoading = ref(false); // 常规作业loading
|
const fileLoading = ref(false); // 常规作业loading
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
//console.log("----onMounted-------");
|
console.log("----onMounted-------")
|
||||||
currentRow.value.id = 0
|
currentRow.value = {id:0};
|
||||||
if(propsQueryCourseObj){
|
if(propsQueryCourseObj){
|
||||||
if(JSON.parse(propsQueryCourseObj)){
|
if(JSON.parse(propsQueryCourseObj)){
|
||||||
courseObj.textbookId = JSON.parse(propsQueryCourseObj).bookObj // 版本
|
courseObj.textbookId = JSON.parse(propsQueryCourseObj).bookObj // 版本
|
||||||
|
@ -239,7 +229,7 @@ const isInToMyQuestion = () => {
|
||||||
if(useClassTaskStores.isOpenQuestUploadView){
|
if(useClassTaskStores.isOpenQuestUploadView){
|
||||||
useClassTaskStores.isOpenQuestUploadView = false;
|
useClassTaskStores.isOpenQuestUploadView = false;
|
||||||
|
|
||||||
currentRow.value.id = 1; // 作业设计
|
currentRow.value = {id:1}; // 作业设计
|
||||||
activeAptTab.value = "个人题库";
|
activeAptTab.value = "个人题库";
|
||||||
//提交内容清空 重置
|
//提交内容清空 重置
|
||||||
classWorkForm.id = 0;
|
classWorkForm.id = 0;
|
||||||
|
@ -268,16 +258,6 @@ watch(() => props.currentCourse, (newVal, oldVal) => {
|
||||||
}
|
}
|
||||||
console.log(newVal,'newval');
|
console.log(newVal,'newval');
|
||||||
},{deep:true})
|
},{deep:true})
|
||||||
|
|
||||||
// ------------科学实验
|
|
||||||
const getExpObj = (obj)=>{
|
|
||||||
// obj:{
|
|
||||||
// fileurl: "https://phet.colorado.edu/sims/html/number-compare/latest/number-compare_zh_CN.html"
|
|
||||||
// label: "数量比较"
|
|
||||||
// subject: "math"
|
|
||||||
// }
|
|
||||||
classWorkForm.fileHomeworkList = [obj];
|
|
||||||
}
|
|
||||||
//---------作业设计---
|
//---------作业设计---
|
||||||
const handleItemClick = (itemName) => {
|
const handleItemClick = (itemName) => {
|
||||||
console.log('itemName', itemName);
|
console.log('itemName', itemName);
|
||||||
|
@ -286,7 +266,7 @@ const handleItemClick = (itemName) => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentRow.value.id = 1; // 作业设计
|
currentRow.value = {id:1}; // 作业设计
|
||||||
/**
|
/**
|
||||||
* 智能推荐?AI设计作业?
|
* 智能推荐?AI设计作业?
|
||||||
* 习题训练: 自主搜题 校本题库 个人题库
|
* 习题训练: 自主搜题 校本题库 个人题库
|
||||||
|
@ -316,7 +296,7 @@ const selectable=(row, index)=>{
|
||||||
/**
|
/**
|
||||||
* 获取 entpcourseid 获取作业列表
|
* 获取 entpcourseid 获取作业列表
|
||||||
*/
|
*/
|
||||||
const initHomeWork = async ()=> {
|
const initHomeWork = async()=> {
|
||||||
tasklist_loading.value = true;
|
tasklist_loading.value = true;
|
||||||
// const { res, chapterId } = await useGetHomework(courseObj.node);
|
// const { res, chapterId } = await useGetHomework(courseObj.node);
|
||||||
const { res, chapterId } = await useGetHomework(sessionStore.get('subject.curNode'));
|
const { res, chapterId } = await useGetHomework(sessionStore.get('subject.curNode'));
|
||||||
|
@ -324,22 +304,12 @@ const initHomeWork = async ()=> {
|
||||||
console.log('res', res);
|
console.log('res', res);
|
||||||
entpcourseid.value = chapterId;
|
entpcourseid.value = chapterId;
|
||||||
taskList.value = res;
|
taskList.value = res;
|
||||||
// 判断当前是否存在其他页面跳转编辑, 如果初次且存在id,则选中该任务
|
|
||||||
const taskId = propsQueryTask?.id ?? 0;
|
|
||||||
if (!propsQueryTask.isInit && taskId!=0){
|
|
||||||
const activeRow = taskList.value.find(o => o.id == taskId);
|
|
||||||
if (activeRow){
|
|
||||||
propsQueryTask.isInit = true; // 清空避免重新保存后再次选中该任务
|
|
||||||
taskTable.value.setCurrentRow(activeRow);
|
|
||||||
handleCurrentChange(activeRow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tasklist_loading.value = false;
|
tasklist_loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleNewAllClass = () => {
|
const handleNewAllClass = () => {
|
||||||
taskTable.value.setCurrentRow({});// 清除表格选中项背景色
|
taskTable.value.setCurrentRow({});// 清除表格选中项背景色
|
||||||
currentRow.value.id = 0; // 作业设计
|
currentRow.value = {id:0}; // 作业设计
|
||||||
//--------
|
//--------
|
||||||
classWorkForm.id = 0;
|
classWorkForm.id = 0;
|
||||||
classWorkForm.uniquekey = ""; // 作业唯一标识 作业名称
|
classWorkForm.uniquekey = ""; // 作业唯一标识 作业名称
|
||||||
|
@ -366,7 +336,7 @@ const handleDelete =() => {
|
||||||
return delClasswork(ids.join(','));
|
return delClasswork(ids.join(','));
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
taskTable.value.setCurrentRow({});// 清除表格选中项背景色
|
taskTable.value.setCurrentRow({});// 清除表格选中项背景色
|
||||||
currentRow.value.id = 0; // 作业设计
|
currentRow.value = {id:0}; // 作业设计
|
||||||
taskList.value = [];
|
taskList.value = [];
|
||||||
// initHomeWork();
|
// initHomeWork();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -429,6 +399,7 @@ const successHomework = () => {
|
||||||
initHomeWork();
|
initHomeWork();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------作业编辑
|
// --------------------作业编辑
|
||||||
let classWorkForm = reactive({
|
let classWorkForm = reactive({
|
||||||
id: '',// cloneDeep(props.propsformobj.id),
|
id: '',// cloneDeep(props.propsformobj.id),
|
||||||
|
@ -459,7 +430,7 @@ const handleCurrentChange = (val) => {
|
||||||
|
|
||||||
console.log(val,'???????????')
|
console.log(val,'???????????')
|
||||||
if(val && val.id >0 ) {
|
if(val && val.id >0 ) {
|
||||||
currentRow.value.id = 1;
|
currentRow.value = val;
|
||||||
classWorkForm.worktype = val.worktype; //作业类型
|
classWorkForm.worktype = val.worktype; //作业类型
|
||||||
editListItem(val, courseObj).then((obj) => {
|
editListItem(val, courseObj).then((obj) => {
|
||||||
if(obj){
|
if(obj){
|
||||||
|
@ -611,33 +582,6 @@ const handleClassWorkFormQuizRemove = (index) =>{
|
||||||
fileLoading.value = false
|
fileLoading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(classWorkForm.worktype === "科学实验"){
|
|
||||||
if (classWorkForm.fileHomeworkList.length == 0) return ElMessage({ type: 'warning', message: '请选择科学实验的课程!'});
|
|
||||||
cform.worktag = useClassTaskStores.experimentObj.updateEduInfo; // 当前实验的学段学科, 格式为[小学-数学]
|
|
||||||
cform.workcodes = JSON.stringify(classWorkForm.fileHomeworkList); // 实验信息
|
|
||||||
cform.entpcourseworklist = JSON.stringify([{'id':-3, 'score': '10'}]);
|
|
||||||
try {
|
|
||||||
console.log(cform,'科学实验')
|
|
||||||
addClassworkReturnId(cform).then((res) => {
|
|
||||||
ElMessage({ type: 'success', message: '作业设计成功!'});
|
|
||||||
// 重置提交表单
|
|
||||||
classWorkForm.worktype = "科学实验";
|
|
||||||
classWorkForm.uniquekey = ''; // props.propsformobj.uniquekey, // 作业唯一标识 作业名称
|
|
||||||
classWorkForm.title = "";
|
|
||||||
classWorkForm.quizlist = [], // 作业习题列表内容
|
|
||||||
|
|
||||||
// 情况选择的资源缓存
|
|
||||||
classWorkForm.chooseWorkLists = []; // 框架梳理list
|
|
||||||
classWorkForm.whiteboardObj = ''; // ? // 清空白板
|
|
||||||
classWorkForm.fileHomeworkList = []; // 常规作业list
|
|
||||||
classWorkForm.id = res
|
|
||||||
emits('getData',classWorkForm)
|
|
||||||
// TODO 科学实验 待完善
|
|
||||||
})
|
|
||||||
} finally{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
// 正常新任务
|
// 正常新任务
|
||||||
var ll = [];
|
var ll = [];
|
||||||
|
@ -684,9 +628,9 @@ const handleClassWorkFormQuizRemove = (index) =>{
|
||||||
console.log('该清空左侧列表数据了');
|
console.log('该清空左侧列表数据了');
|
||||||
// 清空左侧 选中的布置列表 并刷新列表
|
// 清空左侧 选中的布置列表 并刷新列表
|
||||||
if(isShow.value){
|
if(isShow.value){
|
||||||
currentRow.value.id = 1;
|
currentRow.value = {id:1};
|
||||||
}else{
|
}else{
|
||||||
currentRow.value.id = 0;
|
currentRow.value = {id:0};
|
||||||
}
|
}
|
||||||
initHomeWork();
|
initHomeWork();
|
||||||
|
|
||||||
|
@ -723,10 +667,7 @@ const editWork = async (cform) =>{
|
||||||
}else{
|
}else{
|
||||||
if (classWorkForm.fileHomeworkList.length == 0) return ElMessage({ type: 'warning', message: '请上传常规作业附件!'});
|
if (classWorkForm.fileHomeworkList.length == 0) return ElMessage({ type: 'warning', message: '请上传常规作业附件!'});
|
||||||
}
|
}
|
||||||
}else if( classWorkForm.worktype == '科学实验') {
|
}else {
|
||||||
if (classWorkForm.fileHomeworkList.length == 0) return ElMessage({ type: 'warning', message: '请选择科学实验科目!'});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (classWorkForm.chooseWorkLists.length == 0) {
|
if (classWorkForm.chooseWorkLists.length == 0) {
|
||||||
// 框架梳理
|
// 框架梳理
|
||||||
ElMessage.error('请先添加作业资源!');
|
ElMessage.error('请先添加作业资源!');
|
||||||
|
@ -818,46 +759,19 @@ const editWork = async (cform) =>{
|
||||||
// 1.更新作业任务下的课堂展示内容 (这里未做校验, 直接将当前文件对象更新过去)
|
// 1.更新作业任务下的课堂展示内容 (这里未做校验, 直接将当前文件对象更新过去)
|
||||||
cform.workcodes = JSON.stringify(classWorkForm.fileHomeworkList);
|
cform.workcodes = JSON.stringify(classWorkForm.fileHomeworkList);
|
||||||
}
|
}
|
||||||
else if (classWorkForm.worktype=='科学实验') { //TODO 注意,fileHomeworkList字段与常规作业共用
|
|
||||||
// 1.更新作业任务下的课堂展示内容 (这里未做校验, 直接将当前文件对象更新过去)
|
|
||||||
cform.workcodes = JSON.stringify(classWorkForm.fileHomeworkList);
|
|
||||||
cform.worktag = useClassTaskStores.experimentObj.updateEduInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3.更新作业任务本身
|
// 3.更新作业任务本身
|
||||||
let res = await updateClasswork(cform);
|
let res = await updateClasswork(cform);
|
||||||
if (res.code == 200) {
|
if (res.code == 200) {
|
||||||
ElMessage.success('更新成功');
|
ElMessage.success('更新成功');
|
||||||
taskList.value = [];
|
|
||||||
// 清空左侧 选中的布置列表 并刷新列表
|
// 清空左侧 选中的布置列表 并刷新列表
|
||||||
if(isShow.value){
|
currentRow.value = {id:0};
|
||||||
currentRow.value.id = 1;
|
|
||||||
}else{
|
|
||||||
handleNewAllClass();
|
|
||||||
currentRow.value.id = 0;
|
|
||||||
}
|
|
||||||
initHomeWork();
|
initHomeWork();
|
||||||
// // 返回上一页
|
// // 返回上一页
|
||||||
// router.back()
|
// router.back()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试, 未实装
|
|
||||||
const handlePrint = () => {
|
|
||||||
const printOptions = {
|
|
||||||
silent: false, // 是否静默打印
|
|
||||||
printBackground: true, // 是否打印背景颜色和图像
|
|
||||||
color: false, // 是否打印为黑白
|
|
||||||
marginsType: 0, // 边距类型,0: 默认边距,1: 无边距,2: 最小边距
|
|
||||||
pageSize: 'A4', // 纸张大小
|
|
||||||
// 其他选项可以根据需要配置
|
|
||||||
};
|
|
||||||
|
|
||||||
console.log("print-page-click");
|
|
||||||
ipcRenderer.send('printPage', printOptions);
|
|
||||||
};
|
|
||||||
|
|
||||||
//----
|
//----
|
||||||
|
|
||||||
|
|
||||||
|
@ -951,11 +865,6 @@ const handlePrint = () => {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.experiment-homework{
|
|
||||||
padding: 15px;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.page-right {
|
.page-right {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -994,8 +903,5 @@ const handlePrint = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
::v-deep img {
|
|
||||||
display: inline-block !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -17,13 +17,6 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="4" :offset="2">
|
|
||||||
<el-button v-if="!props.isHtml2canvas" type="primary" @click="goToQuestUpload()">添加习题</el-button>
|
|
||||||
</el-col>
|
|
||||||
|
|
||||||
</el-row>
|
|
||||||
<!-- 习题筛选2 -->
|
|
||||||
<el-row style="width: 100%; height: 50px;">
|
|
||||||
<el-col :span="7">
|
<el-col :span="7">
|
||||||
<el-form-item label="年份" label-width="70">
|
<el-form-item label="年份" label-width="70">
|
||||||
<el-select v-model="entpCourseWorkQueryParams.yearStr" placeholder="请选择">
|
<el-select v-model="entpCourseWorkQueryParams.yearStr" placeholder="请选择">
|
||||||
|
@ -31,6 +24,9 @@
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<!-- 习题筛选2 -->
|
||||||
|
<el-row style="width: 100%; height: 50px;">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="关键词" label-width="70">
|
<el-form-item label="关键词" label-width="70">
|
||||||
<el-input
|
<el-input
|
||||||
|
@ -43,6 +39,9 @@
|
||||||
<el-col :span="5">
|
<el-col :span="5">
|
||||||
<el-button @click="handleQueryParamFromEntpCourseWork(1)"><el-icon><Search /></el-icon> 查找</el-button>
|
<el-button @click="handleQueryParamFromEntpCourseWork(1)"><el-icon><Search /></el-icon> 查找</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
<el-col :span="5">
|
||||||
|
<el-button v-if="!props.isHtml2canvas" type="primary" @click="goToQuestUpload()">添加习题</el-button>
|
||||||
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<!-- 习题表格 -->
|
<!-- 习题表格 -->
|
||||||
<div class="page-table" >
|
<div class="page-table" >
|
||||||
|
@ -130,7 +129,6 @@ import examDetailsDrawer from '@/components/exam-question/examDetailsDrawer.vue'
|
||||||
import QuesItem from "@/views/classTask/newClassTaskAssign/questionUpload/quesItem/index.vue";
|
import QuesItem from "@/views/classTask/newClassTaskAssign/questionUpload/quesItem/index.vue";
|
||||||
import { useHandleData } from "@/hooks/useHandleData";
|
import { useHandleData } from "@/hooks/useHandleData";
|
||||||
import { processList } from '@/hooks/useProcessList';
|
import { processList } from '@/hooks/useProcessList';
|
||||||
import { isJson } from "@/utils/comm";
|
|
||||||
|
|
||||||
|
|
||||||
import { debounce } from '@/utils/comm'
|
import { debounce } from '@/utils/comm'
|
||||||
|
@ -256,7 +254,6 @@ function Apis(key) {
|
||||||
const client = new Apis('/paht');
|
const client = new Apis('/paht');
|
||||||
const t = function(name, time) {
|
const t = function(name, time) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const evalId = props.bookobj.levelSecondId=='' ? props.bookobj.levelFirstId : props.bookobj.levelSecondId;
|
|
||||||
const queryForm = {
|
const queryForm = {
|
||||||
// 题类
|
// 题类
|
||||||
worktype: entpCourseWorkQueryParams.worktype.label,
|
worktype: entpCourseWorkQueryParams.worktype.label,
|
||||||
|
@ -269,7 +266,7 @@ const t = function(name, time) {
|
||||||
// 课程相关参数
|
// 课程相关参数
|
||||||
edustage: userStore.edustage, // this.userStore.edustage,
|
edustage: userStore.edustage, // this.userStore.edustage,
|
||||||
edusubject: userStore.edusubject, // this.userStore.edusubject,
|
edusubject: userStore.edusubject, // this.userStore.edusubject,
|
||||||
eid: evalId, // 当前单元或章节id
|
eid: props.bookobj.levelSecondId, // this.activeParams.lession.id,
|
||||||
status: "1",
|
status: "1",
|
||||||
editUserId: userStore.userId,
|
editUserId: userStore.userId,
|
||||||
//orderby: 'concat(worktype,timestamp) DESC',
|
//orderby: 'concat(worktype,timestamp) DESC',
|
||||||
|
@ -329,13 +326,10 @@ const handleQueryFromEntpCourseWork= async (queryType) => {
|
||||||
}
|
}
|
||||||
//console.log("clueres.rows[i].childlist",clueres.rows[i].childlist);
|
//console.log("clueres.rows[i].childlist",clueres.rows[i].childlist);
|
||||||
if (clueres.rows[i].childlist != '') {
|
if (clueres.rows[i].childlist != '') {
|
||||||
const tmpJson = '['+clueres.rows[i].childlist+']';
|
clueres.rows[i].childArray = JSON.parse('['+clueres.rows[i].childlist+']');
|
||||||
if (isJson(tmpJson)){
|
|
||||||
clueres.rows[i].childArray = JSON.parse(tmpJson);
|
|
||||||
for (var j=0; j<clueres.rows[i].childArray.length; j++) {
|
for (var j=0; j<clueres.rows[i].childArray.length; j++) {
|
||||||
clueres.rows[i].childArray[j].title = clueres.rows[i].childArray[j].title.replace(/(<([^>]+)>)/ig, '');
|
clueres.rows[i].childArray[j].title = clueres.rows[i].childArray[j].title.replace(/(<([^>]+)>)/ig, '');
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
clueres.rows[i].childArray = {};
|
clueres.rows[i].childArray = {};
|
||||||
}
|
}
|
||||||
|
@ -488,16 +482,8 @@ const debounceQueryData = debounce(() => {
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
|
|
||||||
watch([
|
watch(() => props.bookobj.levelSecondId, (newVal, oldVal) => {
|
||||||
() => props.bookobj.levelFirstId,
|
|
||||||
() => props.bookobj.levelSecondId
|
|
||||||
], ([newLevelSecondId, newLevelFirstId], [oldLevelSecondId, oldLevelFirstId]) => {
|
|
||||||
console.log(props.bookobj,'课程选择')
|
console.log(props.bookobj,'课程选择')
|
||||||
// 默认选择一级单元时, 不自动获取试题, 需手动按钮获取试题
|
|
||||||
if (props.bookobj.levelSecondId == '') {
|
|
||||||
workResource.entpCourseWorkList = [];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
debounceQueryData();
|
debounceQueryData();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
<el-tab-pane label="自主搜题" name="自主搜题" class="prepare-center-zzst">
|
<el-tab-pane label="自主搜题" name="自主搜题" class="prepare-center-zzst">
|
||||||
<SearchQuestion :bookobj="courseObj" :isHtml2canvas="true" @addQuizImgBs64="handleaddQuizImgBs64" />
|
<SearchQuestion :bookobj="courseObj" :isHtml2canvas="true" @addQuizImgBs64="handleaddQuizImgBs64" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<!-- <el-tab-pane label="校本题库" name="校本题库" class="prepare-center-xbtk">
|
<el-tab-pane label="校本题库" name="校本题库" class="prepare-center-xbtk">
|
||||||
<SchoolQuestion />
|
<SchoolQuestion />
|
||||||
</el-tab-pane> -->
|
</el-tab-pane>
|
||||||
<el-tab-pane label="个人题库" name="个人题库" class="prepare-center-grst">
|
<el-tab-pane label="个人题库" name="个人题库" class="prepare-center-grst">
|
||||||
<MyQuestion :bookobj="courseObj" :isHtml2canvas="true" @addQuizImgBs64="handleaddQuizImgBs64"/>
|
<MyQuestion :bookobj="courseObj" :isHtml2canvas="true" @addQuizImgBs64="handleaddQuizImgBs64"/>
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- orc 使用说明 -->
|
<!-- orc 使用说明 -->
|
||||||
<div class="import-manual-explain">
|
<div class="import-manual-explain">
|
||||||
<p>orc 使用说明(填空题暂无法整题识别)</p>
|
<p>orc 使用说明</p>
|
||||||
<p>1、本地浏览 </p>
|
<p>1、本地浏览 </p>
|
||||||
<p>2、获取剪贴板图片 </p>
|
<p>2、获取剪贴板图片 </p>
|
||||||
<p>3、整题识别:可识别整张图片,自动填充到对应内容。 </p>
|
<p>3、整题识别:可识别整张图片,自动填充到对应内容。 </p>
|
||||||
|
@ -127,7 +127,7 @@ const courseObj = reactive({
|
||||||
const activeAptTab = ref("人工录入");
|
const activeAptTab = ref("人工录入");
|
||||||
|
|
||||||
// false - 正式百度api true - 本地json测试
|
// false - 正式百度api true - 本地json测试
|
||||||
const OCR_WORK_TEST = true;
|
const OCR_WORK_TEST = false;
|
||||||
// [裁剪]参数
|
// [裁剪]参数
|
||||||
const cropOption = reactive({
|
const cropOption = reactive({
|
||||||
img: '', // 裁剪图片的地址 url 地址, base64, blob
|
img: '', // 裁剪图片的地址 url 地址, base64, blob
|
||||||
|
|
|
@ -2,8 +2,7 @@ import { ElMessageBox, ElMessage } from "element-plus";
|
||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
import { pyOCRAPI, getOcrContent } from "@/api/education/entpcoursework";
|
import { pyOCRAPI } from "@/api/education/entpcoursework";
|
||||||
import useClassTaskStore from '@/store/modules/classTask'
|
|
||||||
|
|
||||||
|
|
||||||
const EXAM_JUDGED_DICTIONARY = ["正确", "对", "√", "T", "错误", "错", "×", "F"];
|
const EXAM_JUDGED_DICTIONARY = ["正确", "对", "√", "T", "错误", "错", "×", "F"];
|
||||||
|
@ -18,10 +17,13 @@ const baidubceConfig = {
|
||||||
'client_secret': 'oWb0M0YWMmZPMQIhIUkJX99ddr7h61qf',
|
'client_secret': 'oWb0M0YWMmZPMQIhIUkJX99ddr7h61qf',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function getOcrContent(data) {
|
||||||
const {
|
return request({
|
||||||
entpCourseWorkTypeList
|
url: '/ocr/exam',
|
||||||
} = useClassTaskStore();
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,7 +45,7 @@ export const ocrImg2ItemByManualUpl = async (isLocalTest = false, imgBase64 = ''
|
||||||
|
|
||||||
if (isLocalTest) {
|
if (isLocalTest) {
|
||||||
// 临时本地测试(json格式跟百度ocr一致)
|
// 临时本地测试(json格式跟百度ocr一致)
|
||||||
const response = await fetch('/cropImgTest/single2.json');
|
const response = await fetch('/cropImgTest/single.json');
|
||||||
const resOcr = await response.json();
|
const resOcr = await response.json();
|
||||||
ocrJson = resOcr.results;
|
ocrJson = resOcr.results;
|
||||||
// 识别内容拼接
|
// 识别内容拼接
|
||||||
|
@ -113,6 +115,7 @@ export const ocrImg2ItemByManualUpl = async (isLocalTest = false, imgBase64 = ''
|
||||||
examItem.params.push(obj);
|
examItem.params.push(obj);
|
||||||
});
|
});
|
||||||
return examItem;
|
return examItem;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (examType.includes('单选题') || examType.includes('多选题')) {
|
else if (examType.includes('单选题') || examType.includes('多选题')) {
|
||||||
/** 单选题/多选题 - 选项 */
|
/** 单选题/多选题 - 选项 */
|
||||||
|
@ -147,10 +150,10 @@ export const ocrImg2ItemByManualUpl = async (isLocalTest = false, imgBase64 = ''
|
||||||
}
|
}
|
||||||
else if (curItem === 'workanswer') {
|
else if (curItem === 'workanswer') {
|
||||||
// 该类型下只做[主观题]和[复合题]的处理
|
// 该类型下只做[主观题]和[复合题]的处理
|
||||||
|
if (examType.includes('主观题')) {
|
||||||
ocrTxt = ocrTxt.replace(/<br \/>/g, '');
|
ocrTxt = ocrTxt.replace(/<br \/>/g, '');
|
||||||
examItem = ocrTxt;
|
examItem = ocrTxt;
|
||||||
} else {
|
}
|
||||||
examItem = ocrTxt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回转换格式后的识别内容
|
// 返回转换格式后的识别内容
|
||||||
|
@ -171,7 +174,7 @@ export const ocrImg2ExamByManualUpl = async (isLocalTest = false, imgBase64 = ''
|
||||||
|
|
||||||
if (isLocalTest) {
|
if (isLocalTest) {
|
||||||
// 临时本地测试(json格式跟百度ocr一致)
|
// 临时本地测试(json格式跟百度ocr一致)
|
||||||
const response = await fetch('/cropImgTest/single1.json');
|
const response = await fetch('/cropImgTest/single.json');
|
||||||
const resOcr = await response.json();
|
const resOcr = await response.json();
|
||||||
ocrJson = resOcr.results;
|
ocrJson = resOcr.results;
|
||||||
// 识别内容拼接
|
// 识别内容拼接
|
||||||
|
@ -231,14 +234,12 @@ const ocrImg2Json = async (urlBase64) => {
|
||||||
ElMessage.error("未检测到截图图片, 请截取图片后再识别");
|
ElMessage.error("未检测到截图图片, 请截取图片后再识别");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let base64Code = urlBase64.split(",")[1];
|
let base64Code = urlBase64.split(",")[1];
|
||||||
const resOcr = await getOcrContent({ base64Code: base64Code });
|
const resOcr = await getOcrContent({ base64Code: base64Code });
|
||||||
if (resOcr.code !== 200) {
|
if (resOcr.code !== 200) {
|
||||||
ElMessage.error("图片识别错误");
|
ElMessage.error("图片识别错误");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// const resToken = await bdyAPI_getToken();
|
// const resToken = await bdyAPI_getToken();
|
||||||
// if (resToken.status !== 200) {
|
// if (resToken.status !== 200) {
|
||||||
// ElMessage.error("百度智能云用户标识有误");
|
// ElMessage.error("百度智能云用户标识有误");
|
||||||
|
@ -393,8 +394,8 @@ const assembleExam = (eachSub) => {
|
||||||
}
|
}
|
||||||
// 第一部分[题干-选项] 处理
|
// 第一部分[题干-选项] 处理
|
||||||
titleAndWorkDesc = tmpList[0];
|
titleAndWorkDesc = tmpList[0];
|
||||||
// 将3个以上连续的下划线统一替换为5个
|
// 将4个以上连续的下划线统一替换为5个
|
||||||
titleAndWorkDesc = titleAndWorkDesc.replace(/_{3,}/g, '_____');
|
titleAndWorkDesc = titleAndWorkDesc.replace(/_{4,}/g, '_____');
|
||||||
|
|
||||||
// 第二部分[分析-答案] 处理
|
// 第二部分[分析-答案] 处理
|
||||||
let answerAndAnswer = {};
|
let answerAndAnswer = {};
|
||||||
|
@ -455,35 +456,32 @@ const assembleExam = (eachSub) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 目前暂屏蔽无[复合题], 故所有都算基础题
|
let tmpExam = null;
|
||||||
let tmpExam = processExamSingle(titleAndWorkDesc, answer);
|
if (answer === '') {
|
||||||
|
/**
|
||||||
// let tmpExam = null;
|
* 基础题型 - [单选题] [多选题] [填空题] [判断题] [主观题]
|
||||||
// if (answer === '') {
|
*/
|
||||||
// /**
|
tmpExam = processExamSingle(titleAndWorkDesc, answer);
|
||||||
// * 基础题型 - [单选题] [多选题] [填空题] [判断题] [主观题]
|
}
|
||||||
// */
|
else {
|
||||||
// tmpExam = processExamSingle(titleAndWorkDesc, answer);
|
// 匹配是否存在 1. (1) (1)的存在, 题目与答案都存在则说明题型为复合题(嵌套题)
|
||||||
// }
|
regex = /^(\d+[..。]|\(\d+\)|(\d+))/;
|
||||||
// else {
|
let answerFind = regex.test(answer);
|
||||||
// // 匹配是否存在 1. (1) (1)的存在, 题目与答案都存在则说明题型为复合题(嵌套题)
|
regex = /(\d+[..。]|\(\d+\)|(\d+))/;
|
||||||
// regex = /^(\d+[..。]|\(\d+\)|(\d+))/;
|
let titleFind = regex.test(titleAndWorkDesc);
|
||||||
// let answerFind = regex.test(answer);
|
if (titleFind && answerFind) {
|
||||||
// regex = /(\d+[..。]|\(\d+\)|(\d+))/;
|
/**
|
||||||
// let titleFind = regex.test(titleAndWorkDesc);
|
* [复合题] - 处理逻辑
|
||||||
// if (titleFind && answerFind) {
|
*/
|
||||||
// /**
|
tmpExam = processExamMulti(titleAndWorkDesc, answer);
|
||||||
// * [复合题] - 处理逻辑
|
}
|
||||||
// */
|
else {
|
||||||
// tmpExam = processExamMulti(titleAndWorkDesc, answer);
|
/**
|
||||||
// }
|
* 基础题型 - [单选题] [多选题] [填空题] [判断题] [主观题]
|
||||||
// else {
|
*/
|
||||||
// /**
|
tmpExam = processExamSingle(titleAndWorkDesc, answer);
|
||||||
// * 基础题型 - [单选题] [多选题] [填空题] [判断题] [主观题]
|
}
|
||||||
// */
|
}
|
||||||
// tmpExam = processExamSingle(titleAndWorkDesc, answer);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (tmpExam) {
|
if (tmpExam) {
|
||||||
// 错误信息
|
// 错误信息
|
||||||
|
@ -609,21 +607,13 @@ const processExamSingle = function (titleAndWorkDesc, answer) {
|
||||||
* 主观题
|
* 主观题
|
||||||
*/
|
*/
|
||||||
// [题型] - 格式化
|
// [题型] - 格式化
|
||||||
const flagDict = ['单选题', '多选题', '判断题', '填空题'];
|
examSingle.workType = "主观题";
|
||||||
const another = entpCourseWorkTypeList.filter(item => !flagDict.includes(item.label));
|
|
||||||
if (another.length > 0) {
|
|
||||||
examSingle.workType = another[another.length-1].label;
|
|
||||||
// [题干]-格式化
|
// [题干]-格式化
|
||||||
examSingle.title = titleAndWorkDesc;
|
examSingle.title = titleAndWorkDesc;
|
||||||
}
|
|
||||||
|
|
||||||
// examSingle.workType = "主观题";
|
// [选项] - 格式化 --- 主观题无选项
|
||||||
|
//examSingle.arrWorkDesc = [];
|
||||||
// // [题干]-格式化
|
|
||||||
// examSingle.title = titleAndWorkDesc;
|
|
||||||
|
|
||||||
// // [选项] - 格式化 --- 主观题无选项
|
|
||||||
// //examSingle.arrWorkDesc = [];
|
|
||||||
|
|
||||||
// [题目答案] - 处理 --- ['qweasd123']
|
// [题目答案] - 处理 --- ['qweasd123']
|
||||||
if (answer !== '') {
|
if (answer !== '') {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<el-form ref="questFormRef" :model="questForm" :rules="MainRules" label-width="80px">
|
<el-form ref="questFormRef" :model="questForm" :rules="MainRules" label-width="80px">
|
||||||
<el-form-item label="题型" prop="worktype">
|
<el-form-item label="题型" prop="worktype">
|
||||||
<el-select v-model="questForm.worktype" placeholder="请选择题型" style="width:20%" :disabled="questForm.id==0?false:true">
|
<el-select v-model="questForm.worktype" placeholder="请选择题型" style="width:20%" :disabled="questForm.id==0?false:true">
|
||||||
<el-option v-for="item in fromOptions.type" :key="item.value" :label="item.label" :value="item.label" :disabled="item.label=='不限'"></el-option>
|
<el-option v-for="item in fromOptions.type" :key="item.value" :label="item.label" :value="item.label"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-tag v-if="questForm.worktype=='填空题'" type="danger" style=" margin-left: 10px ">温馨提示:填空题题目的填空位置,下划线请连续输入3-10个 _
|
<el-tag v-if="questForm.worktype=='填空题'" type="danger" style=" margin-left: 10px ">温馨提示:填空题题目的填空位置,下划线请连续输入3-10个 _
|
||||||
符号。eg:今天___好日子。</el-tag>
|
符号。eg:今天___好日子。</el-tag>
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
<el-form-item label="知识点" prop="knowledgePointIdArr">
|
<el-form-item label="知识点" prop="knowledgePointIdArr">
|
||||||
<el-cascader
|
<el-cascader
|
||||||
v-model="questForm.knowledgePointIdArr"
|
v-model="questForm.knowledgePointIdArr"
|
||||||
:options="entpCourseWorkPointList"
|
:options="curKnowledgePointList"
|
||||||
:props="knowledgePointProps"
|
:props="knowledgePointProps"
|
||||||
popper-class="my-popper"
|
popper-class="my-popper"
|
||||||
@change="onchange"
|
@change="onchange"
|
||||||
|
@ -103,7 +103,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 多选题 -->
|
<!-- 多选题 -->
|
||||||
<div v-else-if="questForm.worktype=='多选题'" class="questForm-item-cover">
|
<div v-if="questForm.worktype=='多选题'" class="questForm-item-cover">
|
||||||
<div v-for="(item,index) in questForm.list" :key='index'>
|
<div v-for="(item,index) in questForm.list" :key='index'>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
:label=Options(1,index)
|
:label=Options(1,index)
|
||||||
|
@ -134,7 +134,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 填空题 -->
|
<!-- 填空题 -->
|
||||||
<div v-else-if="questForm.worktype=='填空题'" class="questForm-item-cover">
|
<div v-if="questForm.worktype=='填空题'" class="questForm-item-cover">
|
||||||
<div v-for="(item,index) in questForm.list" :key='index'>
|
<div v-for="(item,index) in questForm.list" :key='index'>
|
||||||
<el-form-item :label=Options(3,index) :prop="`list.${index}.text`"
|
<el-form-item :label=Options(3,index) :prop="`list.${index}.text`"
|
||||||
:rules="{required: true, message: '填空选项不能为空', trigger: 'blur'}">
|
:rules="{required: true, message: '填空选项不能为空', trigger: 'blur'}">
|
||||||
|
@ -157,7 +157,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 判断题 -->
|
<!-- 判断题 -->
|
||||||
<div v-else-if="questForm.worktype=='判断题'" class="questForm-item-cover">
|
<div v-if="questForm.worktype=='判断题'" class="questForm-item-cover">
|
||||||
<div v-for="(item,index) in questForm.list" :key='index'>
|
<div v-for="(item,index) in questForm.list" :key='index'>
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-if="index==0"
|
v-if="index==0"
|
||||||
|
@ -176,7 +176,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 主观题 -->
|
<!-- 主观题 -->
|
||||||
<div v-else-if="questForm.worktype.indexOf('主观题') != -1" class="questForm-item-cover">
|
<div v-if="questForm.worktype.indexOf('主观题') != -1" class="questForm-item-cover">
|
||||||
<el-form-item label="答案">
|
<el-form-item label="答案">
|
||||||
<Tinymce v-model="questForm.workanswer" :upFileParams="{
|
<Tinymce v-model="questForm.workanswer" :upFileParams="{
|
||||||
lessionId: lessionid,
|
lessionId: lessionid,
|
||||||
|
@ -239,7 +239,7 @@
|
||||||
|
|
||||||
|
|
||||||
<!-- 复合题 -->
|
<!-- 复合题 -->
|
||||||
<div v-else-if="questForm.worktype=='复合题'" class="questForm-item-cover">
|
<div v-if="questForm.worktype=='复合题'" class="questForm-item-cover">
|
||||||
<el-form-item label="单项题型" :prop="worktype">
|
<el-form-item label="单项题型" :prop="worktype">
|
||||||
<el-select v-model="questForm.mulList.worktype" placeholder="请选择题型" style="width:20%">
|
<el-select v-model="questForm.mulList.worktype" placeholder="请选择题型" style="width:20%">
|
||||||
<!-- <el-option key="1" label="单选题" value="单选题"></el-option> -->
|
<!-- <el-option key="1" label="单选题" value="单选题"></el-option> -->
|
||||||
|
@ -350,19 +350,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 非统一标准名称的解答题 -->
|
|
||||||
<div v-else class="questForm-item-cover">
|
|
||||||
<el-form-item label="答案">
|
|
||||||
<Tinymce v-model="questForm.workanswer" :upFileParams="{
|
|
||||||
lessionId: lessionid,
|
|
||||||
fileAlias: '单题上传',
|
|
||||||
}" />
|
|
||||||
</el-form-item>
|
|
||||||
<div class="item-cropper-btn">
|
|
||||||
<el-button v-show="isCropper" circle @click="cropperFormItem('workanswer')"><el-icon><Search /></el-icon></el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 答案分析 -->
|
<!-- 答案分析 -->
|
||||||
<div class="questForm-item-cover">
|
<div class="questForm-item-cover">
|
||||||
<el-form-item label="答案分析" prop="method">
|
<el-form-item label="答案分析" prop="method">
|
||||||
|
@ -432,8 +419,7 @@ const userStore = useUserStore().user
|
||||||
const {
|
const {
|
||||||
entpCourseWorkTypeList,
|
entpCourseWorkTypeList,
|
||||||
entpCourseWorkGroupList,
|
entpCourseWorkGroupList,
|
||||||
entpCourseWorkYearList,
|
entpCourseWorkYearList
|
||||||
entpCourseWorkPointList
|
|
||||||
} = useClassTaskStore();
|
} = useClassTaskStore();
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance()
|
const { proxy } = getCurrentInstance()
|
||||||
|
@ -490,9 +476,9 @@ const fromOptions = reactive({
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
// 单题纠错时是否需要重新获取知识点的标识(目前仅用于UpdateForm中)
|
// 单题纠错时是否需要重新获取知识点的标识(目前仅用于UpdateForm中)
|
||||||
//const initKonwPointFlagByUpdateForm = ref(true);
|
const initKonwPointFlagByUpdateForm = ref(true);
|
||||||
// 表单[知识点]显示内容集合
|
// 表单[知识点]显示内容集合
|
||||||
//const curKnowledgePointList = ref([]);
|
const curKnowledgePointList = ref([]);
|
||||||
// 表单数据参数
|
// 表单数据参数
|
||||||
const questForm = reactive({
|
const questForm = reactive({
|
||||||
id: 0,
|
id: 0,
|
||||||
|
@ -637,9 +623,8 @@ onMounted(() => {
|
||||||
|
|
||||||
// 更新第三方题型、题源
|
// 更新第三方题型、题源
|
||||||
if (entpCourseWorkTypeList.length>0) {
|
if (entpCourseWorkTypeList.length>0) {
|
||||||
//const flagDict = ['单选题', '多选题', '判断题', '填空题'];
|
const flagDict = ['单选题', '多选题', '判断题', '填空题'];
|
||||||
//fromOptions.type = entpCourseWorkTypeList.filter(item => flagDict.includes(item.label));
|
fromOptions.type = entpCourseWorkTypeList.filter(item => flagDict.includes(item.label));
|
||||||
fromOptions.type = entpCourseWorkTypeList
|
|
||||||
}
|
}
|
||||||
if (entpCourseWorkGroupList.length>0) {
|
if (entpCourseWorkGroupList.length>0) {
|
||||||
fromOptions.flag = entpCourseWorkGroupList;
|
fromOptions.flag = entpCourseWorkGroupList;
|
||||||
|
@ -763,8 +748,8 @@ const resetForm = () =>{
|
||||||
const updateForm= async(item, submitIndex=0, submitType=1) =>{
|
const updateForm= async(item, submitIndex=0, submitType=1) =>{
|
||||||
console.log(item,'item');
|
console.log(item,'item');
|
||||||
// 当不存在[状态],默认为1
|
// 当不存在[状态],默认为1
|
||||||
if (!item.hasOwnProperty('status')) {
|
if (!item.hasOwnProperty('stutus')) {
|
||||||
item.status = '1';
|
item.stutus = '1';
|
||||||
}
|
}
|
||||||
// 当不存在[知识点], 默认为空
|
// 当不存在[知识点], 默认为空
|
||||||
if (!item.hasOwnProperty('evalnodeid')) {
|
if (!item.hasOwnProperty('evalnodeid')) {
|
||||||
|
@ -780,6 +765,7 @@ const updateForm= async(item, submitIndex=0, submitType=1) =>{
|
||||||
// 将菁优网的填空下划线标签转为下划线(上传时需再重新替换回来)
|
// 将菁优网的填空下划线标签转为下划线(上传时需再重新替换回来)
|
||||||
item.title = item.title.replace(/<!--BA--><div class="quizPutTag" contenteditable="true">(?: )?<\/div><!--EA-->/g, '_____');
|
item.title = item.title.replace(/<!--BA--><div class="quizPutTag" contenteditable="true">(?: )?<\/div><!--EA-->/g, '_____');
|
||||||
|
|
||||||
|
|
||||||
if(item.worktype == '复合题') {
|
if(item.worktype == '复合题') {
|
||||||
// 同步更新[基础题]的初始结构
|
// 同步更新[基础题]的初始结构
|
||||||
newList = [{text:""}];
|
newList = [{text:""}];
|
||||||
|
@ -916,14 +902,11 @@ const updateForm= async(item, submitIndex=0, submitType=1) =>{
|
||||||
}],
|
}],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
newList = [];
|
||||||
// 默认显示一个空选项
|
|
||||||
newList = [{text:""}];
|
|
||||||
|
|
||||||
|
|
||||||
// 兼容题型[主观题]
|
// 兼容题型[主观题]
|
||||||
//item.worktype = item.worktype.replace(/\(主观题\)/g, '');
|
item.worktype = item.worktype.replace(/\(主观题\)/g, '');
|
||||||
//item.worktype = `${item.worktype}(主观题)`;
|
item.worktype = `${item.worktype}(主观题)`;
|
||||||
// 无选项
|
// 无选项
|
||||||
// 选项答案处理下
|
// 选项答案处理下
|
||||||
if(isJson(item.workanswer)){
|
if(isJson(item.workanswer)){
|
||||||
|
@ -1019,41 +1002,42 @@ const updateForm= async(item, submitIndex=0, submitType=1) =>{
|
||||||
|
|
||||||
|
|
||||||
// 更新表单[知识点]回显
|
// 更新表单[知识点]回显
|
||||||
// if (initKonwPointFlagByUpdateForm.value) {
|
if (initKonwPointFlagByUpdateForm.value) {
|
||||||
// // 避免重复调用
|
// 避免重复调用
|
||||||
// initKonwPointFlagByUpdateForm.value = false;
|
initKonwPointFlagByUpdateForm.value = false;
|
||||||
|
|
||||||
// lessionid.value = props.bookobj.levelSecondId? props.bookobj.levelSecondId : props.bookobj.levelFirstId;
|
lessionid.value = props.bookobj.levelSecondId? props.bookobj.levelSecondId : props.bookobj.levelFirstId;
|
||||||
// console.log('lessionid', lessionid.value);
|
console.log('lessionid', lessionid.value);
|
||||||
// // 拿到当前章节下得所有知识点
|
|
||||||
// if( props.bookobj.node.edusubject == '语文' || props.bookobj.node.edusubject == '英语' ){
|
// 拿到当前章节下得所有知识点
|
||||||
// const res = await listEvaluation({ edusubject: props.bookobj.node.edusubject, edustage: props.bookobj.node.edustage, itemkey: "subject", pageSize: 10 });
|
if( props.bookobj.node.edustage == '高中' && (props.bookobj.node.edusubject == '语文' || props.bookobj.node.edusubject == '英语') ){
|
||||||
// const id = res.rows[0]?.id;
|
const res = await listEvaluation({ edusubject: props.bookobj.node.edusubject, edustage: props.bookobj.node.edustage, itemkey: "subject", pageSize: 10 });
|
||||||
// if (id) {
|
const id = res.rows[0]?.id;
|
||||||
// const res = await listKnowlegepointFormat({evalId: id, pageNum: 1, pageSize: 5000,});
|
if (id) {
|
||||||
// curKnowledgePointList.value = formatKnowledgePoint(res.rows);
|
const res = await listKnowlegepointFormat({evalId: id, pageNum: 1, pageSize: 5000,});
|
||||||
// console.log('updateKnowledgePoint->', curKnowledgePointList.value);
|
curKnowledgePointList.value = updateKnowledgePoint(res.rows);
|
||||||
// }
|
//console.log('updateKnowledgePoint->', res.rows);
|
||||||
// } else {
|
}
|
||||||
// const res = await getBindlist({ eid: lessionid.value })
|
} else {
|
||||||
// if (!res.data || res.data.length < 1) {
|
const res = await getBindlist({ eid: lessionid.value })
|
||||||
// ElMessage.warning('当前章节下未绑定知识点,暂不更新该试题知识点!');
|
if (!res.data || res.data.length < 1) {
|
||||||
// curKnowledgePointList.value = [];
|
ElMessage.warning('当前章节下未绑定知识点,暂不更新该试题知识点!');
|
||||||
// }
|
curKnowledgePointList.value = [];
|
||||||
// else {
|
}
|
||||||
// curKnowledgePointList.value = res.data;
|
else {
|
||||||
// }
|
curKnowledgePointList.value = res.data;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//item.evalnodeid = '3772b,374112,374233';
|
//item.evalnodeid = '3772b,374112,374233';
|
||||||
let knowledgePointIdArr = [];
|
let knowledgePointIdArr = [];
|
||||||
const pointArr = item.evalnodeid.split(',');
|
const pointArr = item.evalnodeid.split(',');
|
||||||
if (entpCourseWorkPointList.length > 0 && pointArr.length > 0) {
|
if (curKnowledgePointList.value.length > 0 && pointArr.length > 0) {
|
||||||
pointArr.forEach(element => {
|
pointArr.forEach(element => {
|
||||||
element = element.trim();
|
element = element.trim();
|
||||||
let point = [];
|
let point = [];
|
||||||
if (getCurKnowledgePointToForm(point, element, entpCourseWorkPointList)) {
|
if (getCurKnowledgePointToForm(point, element, curKnowledgePointList.value)) {
|
||||||
point = point.reverse();
|
point = point.reverse();
|
||||||
knowledgePointIdArr.push(point);
|
knowledgePointIdArr.push(point);
|
||||||
}
|
}
|
||||||
|
@ -1099,7 +1083,6 @@ const updateForm= async(item, submitIndex=0, submitType=1) =>{
|
||||||
// status = 1,
|
// status = 1,
|
||||||
// }
|
// }
|
||||||
// emit('update-exam-single', updateStatus);
|
// emit('update-exam-single', updateStatus);
|
||||||
console.log('updateFormone->', questForm)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateFormone=(item, submitIndex, submitType, formdataitem)=>{
|
const updateFormone=(item, submitIndex, submitType, formdataitem)=>{
|
||||||
|
@ -1454,9 +1437,14 @@ const submitForm=(formName) =>{
|
||||||
//param.workdesc = questForm.list.map(item => item.text).join('#&');
|
//param.workdesc = questForm.list.map(item => item.text).join('#&');
|
||||||
param.workdesc = JSON.stringify(questForm.list.map(item => item.text));
|
param.workdesc = JSON.stringify(questForm.list.map(item => item.text));
|
||||||
|
|
||||||
// 重新格式化信息
|
// 针对[单选题]和[多选题]重新格式化信息
|
||||||
if(questForm.worktype === '复合题') {
|
if (questForm.worktype === '单选题' || questForm.worktype === '多选题') {
|
||||||
|
//param.workanswer = questForm.checkAnswer.map(item => item).join('#&');
|
||||||
|
param.workanswer = JSON.stringify(questForm.checkAnswer);
|
||||||
|
}
|
||||||
|
|
||||||
// 针对[复合题]重新格式化信息
|
// 针对[复合题]重新格式化信息
|
||||||
|
if(questForm.worktype === '复合题') {
|
||||||
let workdesc = [];
|
let workdesc = [];
|
||||||
let answer = [];
|
let answer = [];
|
||||||
// 1.题目: 背景材料(不再需要处理, 直接使用form.title)
|
// 1.题目: 背景材料(不再需要处理, 直接使用form.title)
|
||||||
|
@ -1513,33 +1501,9 @@ const submitForm=(formName) =>{
|
||||||
param.workdesc = JSON.stringify(workdesc);
|
param.workdesc = JSON.stringify(workdesc);
|
||||||
param.workanswer = JSON.stringify(answer);
|
param.workanswer = JSON.stringify(answer);
|
||||||
}
|
}
|
||||||
else if (questForm.worktype === '单选题' || questForm.worktype === '多选题') {
|
|
||||||
// 针对[单选题]和[多选题]重新格式化信息
|
|
||||||
//param.workanswer = questForm.checkAnswer.map(item => item).join('#&');
|
|
||||||
param.workanswer = JSON.stringify(questForm.checkAnswer);
|
|
||||||
}
|
|
||||||
// 针对[填空题]重新格式化信息 "<div>什么</div>#&<div>什么哟</div>".replace(/<[^>]*>/g, "")
|
|
||||||
else if(questForm.worktype === '填空题'){
|
|
||||||
//填空答案: 这里填入选项的值(填空值)
|
|
||||||
//param.workanswer = questForm.list.map(item => item.text).join('#&').replace(/<[^>]*>/g, "");
|
|
||||||
|
|
||||||
// 填空选项为空,避免后面多次判断,这里只根据正确答案来分析
|
// 针对[主观题]重新格式化信息 ([单题上传]时默认为主观题。 [单题纠错]时会在原题型后面增加标识[(主观题)], 故此处更改为判断是否存在 )
|
||||||
param.workdesc = '';
|
if(questForm.worktype.indexOf('主观题') !== -1) {
|
||||||
param.workanswer = JSON.stringify(questForm.list.map(item => item.text));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 针对[判断题]重新格式化信息
|
|
||||||
else if(questForm.worktype === '判断题'){
|
|
||||||
//判断题答案: 这里填入选项的值(判断值)
|
|
||||||
//param.workanswer = questForm.list.map(item => item.text).join('#&').replace(/<[^>]*>/g, "");
|
|
||||||
|
|
||||||
// 填空选项为空,避免后面多次判断,这里只根据正确答案来分析
|
|
||||||
param.workdesc = '';
|
|
||||||
param.workanswer = JSON.stringify(questForm.checkAnswer);
|
|
||||||
}
|
|
||||||
else if(questForm.worktype.indexOf('主观题') !== -1) {
|
|
||||||
// warn: 针对[主观题]重新格式化信息 ([单题上传]时默认为主观题。 [单题纠错]时会在原题型后面增加标识[(主观题)], 故此处更改为判断是否存在 )
|
|
||||||
// 主观题:只有答案跟题目,答案还不是唯一的,一个具体参考答案类似
|
// 主观题:只有答案跟题目,答案还不是唯一的,一个具体参考答案类似
|
||||||
param.workdesc = ''; // 主观题选项为空
|
param.workdesc = ''; // 主观题选项为空
|
||||||
// 主观题 答案直接用的 workanswer 存的时候用数组
|
// 主观题 答案直接用的 workanswer 存的时候用数组
|
||||||
|
@ -1569,16 +1533,27 @@ const submitForm=(formName) =>{
|
||||||
// param.workdesc = ''; // 填空选项为空,避免后面多次判断,这里只根据正确答案来分析
|
// param.workdesc = ''; // 填空选项为空,避免后面多次判断,这里只根据正确答案来分析
|
||||||
// param.workanswer = JSON.stringify(answer).replace(/<[^>]*>/g, "");
|
// param.workanswer = JSON.stringify(answer).replace(/<[^>]*>/g, "");
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// 非统一标准解答题(主观题), 统一以[主观题]的格式来处理, 主要用于兼容ocr识别解答题及菁优网第三方非同一解答题
|
// 针对[填空题]重新格式化信息 "<div>什么</div>#&<div>什么哟</div>".replace(/<[^>]*>/g, "")
|
||||||
param.workdesc = ''; // 主观题选项为空
|
if(questForm.worktype === '填空题'){
|
||||||
// 主观题 答案直接用的 workanswer 存的时候用数组
|
//填空答案: 这里填入选项的值(填空值)
|
||||||
if (questForm.workanswer && questForm.workanswer != '') {
|
//param.workanswer = questForm.list.map(item => item.text).join('#&').replace(/<[^>]*>/g, "");
|
||||||
param.workanswer = JSON.stringify([questForm.workanswer]);
|
|
||||||
}
|
// 填空选项为空,避免后面多次判断,这里只根据正确答案来分析
|
||||||
|
param.workdesc = '';
|
||||||
|
param.workanswer = JSON.stringify(questForm.list.map(item => item.text));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 针对[判断题]重新格式化信息
|
||||||
|
if(questForm.worktype === '判断题'){
|
||||||
|
//判断题答案: 这里填入选项的值(判断值)
|
||||||
|
//param.workanswer = questForm.list.map(item => item.text).join('#&').replace(/<[^>]*>/g, "");
|
||||||
|
|
||||||
|
// 填空选项为空,避免后面多次判断,这里只根据正确答案来分析
|
||||||
|
param.workdesc = '';
|
||||||
|
param.workanswer = JSON.stringify(questForm.checkAnswer);
|
||||||
|
}
|
||||||
|
|
||||||
// 针对不同上传方式, 需要做不同的状态处理(目前只用处理3的情况)
|
// 针对不同上传方式, 需要做不同的状态处理(目前只用处理3的情况)
|
||||||
if (questForm.submitType === 3) {
|
if (questForm.submitType === 3) {
|
||||||
|
@ -1728,53 +1703,50 @@ const myMessageShow=(title, msg, status)=>{
|
||||||
* @return: {*}
|
* @return: {*}
|
||||||
* @param {*} list
|
* @param {*} list
|
||||||
*/
|
*/
|
||||||
const formatKnowledgePoint = (list) => {
|
const updateKnowledgePoint = (list) => {
|
||||||
list.forEach(item => {
|
list.forEach(item => {
|
||||||
if (item.title && item.title != '') {
|
if (item.title && item.title != '') {
|
||||||
item.knowTitle = item.title;
|
item.knowTitle = item.title;
|
||||||
}
|
}
|
||||||
if (item.children && Array.isArray(item.children)) {
|
if (item.children && Array.isArray(item.children)) {
|
||||||
formatKnowledgePoint(item.children);
|
updateKnowledgePoint(item.children);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return list;
|
return list;
|
||||||
};
|
};
|
||||||
|
|
||||||
watch([
|
watch(() => props.bookobj.levelSecondId, async (newVal, oldVal) => {
|
||||||
() => props.bookobj.levelFirstId,
|
|
||||||
() => props.bookobj.levelSecondId
|
|
||||||
], async([newLevelSecondId, newLevelFirstId], [oldLevelSecondId, oldLevelFirstId]) => {
|
|
||||||
console.log(props.bookobj,'课程选择')
|
console.log(props.bookobj,'课程选择')
|
||||||
// props.bookobj.levelSecondId? props.bookobj.levelSecondId : props.bookobj.levelFirstId
|
// props.bookobj.levelSecondId? props.bookobj.levelSecondId : props.bookobj.levelFirstId
|
||||||
lessionid.value = props.bookobj.levelSecondId!='' ? props.bookobj.levelSecondId : props.bookobj.levelFirstId;
|
lessionid.value = props.bookobj.levelSecondId? props.bookobj.levelSecondId : props.bookobj.levelFirstId;
|
||||||
|
|
||||||
// /**
|
/**
|
||||||
// * 格式化知识点: 分两种情况
|
* 格式化知识点: 分两种情况
|
||||||
// * 1. 语文/英语: 获取学科下的所有知识点(该学科对应无章节与知识点绑定, 故只获取全知识点)
|
* 1. 语文/英语: 获取学科下的所有知识点(该学科对应无章节与知识点绑定, 故只获取全知识点)
|
||||||
// * 2. 其他: 获取当前章节下的所有知识点
|
* 2. 其他: 获取当前章节下的所有知识点
|
||||||
// */
|
*/
|
||||||
// let id = lessionid.value;
|
let id = props.bookobj.levelSecondId;
|
||||||
// if( props.bookobj.node.edusubject == '语文' || props.bookobj.node.edusubject == '英语'){
|
if( props.bookobj.node.edustage == '高中' && (props.bookobj.node.edusubject == '语文' || props.bookobj.node.edusubject == '英语') ){
|
||||||
// id = props.bookobj.node.rootid;
|
id = props.bookobj.node.rootid;
|
||||||
// const res = await listEvaluation({ edusubject: props.bookobj.node.edusubject, edustage: props.bookobj.node.edustage, itemkey: "subject", pageSize: 10 });
|
const res = await listEvaluation({ edusubject: props.bookobj.node.edusubject, edustage: props.bookobj.node.edustage, itemkey: "subject", pageSize: 10 });
|
||||||
// id = res.rows[0]?.id;
|
id = res.rows[0]?.id;
|
||||||
// if (id) {
|
if (id) {
|
||||||
// listKnowlegepointFormat({evalId: id, pageNum: 1, pageSize: 5000,}).then(res => {
|
listKnowlegepointFormat({evalId: id, pageNum: 1, pageSize: 5000,}).then(res => {
|
||||||
// //console.log('listKnowlegepointFormat->', res.rows);
|
//console.log('listKnowlegepointFormat->', res.rows);
|
||||||
// curKnowledgePointList.value = formatKnowledgePoint(res.rows);
|
curKnowledgePointList.value = updateKnowledgePoint(res.rows);
|
||||||
// });
|
});
|
||||||
// }
|
}
|
||||||
// }else{
|
}else{
|
||||||
// getBindlist({ eid: id }).then(res => {
|
getBindlist({ eid: id }).then(res => {
|
||||||
// if (!res.data || res.data.length < 1) {
|
if (!res.data || res.data.length < 1) {
|
||||||
// ElMessage.warning('当前章节下未绑定知识点,暂不更新该试题知识点!');
|
ElMessage.warning('当前章节下未绑定知识点,暂不更新该试题知识点!');
|
||||||
// curKnowledgePointList.value = [];
|
curKnowledgePointList.value = [];
|
||||||
// }
|
}
|
||||||
// else {
|
else {
|
||||||
// curKnowledgePointList.value = res.data;
|
curKnowledgePointList.value = res.data;
|
||||||
// }
|
}
|
||||||
// })
|
})
|
||||||
// }
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,9 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
<el-col :span="10">
|
||||||
<!-- <el-form-item label="知识点" label-width="70">
|
<el-form-item label="知识点" label-width="70">
|
||||||
<el-cascader
|
<el-cascader
|
||||||
:disabled="entpCourseWorkPointList.length==0"
|
disabled
|
||||||
v-model="entpCourseWorkQueryParams.point"
|
v-model="entpCourseWorkQueryParams.point"
|
||||||
clearable
|
clearable
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
collapse-tags
|
collapse-tags
|
||||||
collapse-tags-tooltip
|
collapse-tags-tooltip
|
||||||
/>
|
/>
|
||||||
</el-form-item> -->
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<!-- 习题筛选2 -->
|
<!-- 习题筛选2 -->
|
||||||
|
@ -117,8 +117,6 @@ import { listKnowledgePoint } from "@/api/knowledge/knowledgePoint";
|
||||||
import { getBindlist } from '@/api/education/knowledgePoint'
|
import { getBindlist } from '@/api/education/knowledgePoint'
|
||||||
import examDetailsDrawer from '@/components/exam-question/examDetailsDrawer.vue'
|
import examDetailsDrawer from '@/components/exam-question/examDetailsDrawer.vue'
|
||||||
import { processList } from '@/hooks/useProcessList'
|
import { processList } from '@/hooks/useProcessList'
|
||||||
import { isJson } from "@/utils/comm";
|
|
||||||
|
|
||||||
import { useGetHomework } from '@/hooks/useGetHomework'
|
import { useGetHomework } from '@/hooks/useGetHomework'
|
||||||
import { sessionStore } from '@/utils/store'
|
import { sessionStore } from '@/utils/store'
|
||||||
import {throttle,debounce } from '@/utils/comm'
|
import {throttle,debounce } from '@/utils/comm'
|
||||||
|
@ -132,8 +130,7 @@ const userStore = useUserStore().user
|
||||||
const {
|
const {
|
||||||
entpCourseWorkTypeList,
|
entpCourseWorkTypeList,
|
||||||
entpCourseWorkGroupList,
|
entpCourseWorkGroupList,
|
||||||
entpCourseWorkYearList,
|
entpCourseWorkYearList
|
||||||
entpCourseWorkPointList
|
|
||||||
} = useClassTaskStore();
|
} = useClassTaskStore();
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -147,11 +144,12 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// const entpCourseWorkPointList = ref([
|
const entpCourseWorkPointList = ref([
|
||||||
// {label: '不限', value: []},
|
{label: '不限', value: []},
|
||||||
// ]); // 习题查询条件 - 知识点
|
]); // 习题查询条件 - 知识点
|
||||||
const knowledgePointProps = reactive({value: 'thirdId', label: 'knowTitle'});
|
const knowledgePointProps = ref({value: 'thirdId', label: 'title'});
|
||||||
//const knowledgePointProps = ref({value: 'thirdId', label: 'title'});
|
//const knowledgePointProps = ref({value: 'thirdId', label: 'knowTitle'});
|
||||||
|
|
||||||
|
|
||||||
// 习题查询参数条件
|
// 习题查询参数条件
|
||||||
const entpCourseWorkQueryParams = reactive({
|
const entpCourseWorkQueryParams = reactive({
|
||||||
|
@ -192,8 +190,6 @@ const workResource = reactive({
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
console.log('entpCourseWorkTypeList', entpCourseWorkTypeList);
|
console.log('entpCourseWorkTypeList', entpCourseWorkTypeList);
|
||||||
// 知识点 (仅用更新一次)
|
|
||||||
//getEntpCourseWorkPointList();
|
|
||||||
debounceQueryData(); // 查询习题列表
|
debounceQueryData(); // 查询习题列表
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -239,13 +235,12 @@ function Apis(key) {
|
||||||
const client = new Apis('/paht');
|
const client = new Apis('/paht');
|
||||||
const t = function(name, time) {
|
const t = function(name, time) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const evalId = props.bookobj.levelSecondId=='' ? props.bookobj.levelFirstId : props.bookobj.levelSecondId;
|
|
||||||
const queryForm = {
|
const queryForm = {
|
||||||
// 分页参数
|
// 分页参数
|
||||||
currentPage: paginationParams.pageNum,
|
currentPage: paginationParams.pageNum,
|
||||||
pageSize: paginationParams.pageSize,
|
pageSize: paginationParams.pageSize,
|
||||||
// 课程相关参数
|
// 课程相关参数
|
||||||
eid: evalId, // 当前单元或章节id
|
eid: props.bookobj.levelSecondId,
|
||||||
sectionName: props.bookobj.coursetitle,
|
sectionName: props.bookobj.coursetitle,
|
||||||
edusubject: userStore.edusubject,
|
edusubject: userStore.edusubject,
|
||||||
edustage: userStore.edustage,
|
edustage: userStore.edustage,
|
||||||
|
@ -258,7 +253,7 @@ const t = function(name, time) {
|
||||||
// 年份
|
// 年份
|
||||||
yearStr: entpCourseWorkQueryParams.yearStr !== '-1' ? entpCourseWorkQueryParams.yearStr:'',
|
yearStr: entpCourseWorkQueryParams.yearStr !== '-1' ? entpCourseWorkQueryParams.yearStr:'',
|
||||||
// 知识点
|
// 知识点
|
||||||
thirdId: entpCourseWorkQueryParams.point&&entpCourseWorkQueryParams.point.length > 0 ? entpCourseWorkQueryParams.point[entpCourseWorkQueryParams.point.length-1]:'',
|
thirdId: entpCourseWorkQueryParams.point&&entpCourseWorkQueryParams.point.length > 0 ? entpCourseWorkQueryParams.point[0]:'',
|
||||||
// 关键字
|
// 关键字
|
||||||
keyword: entpCourseWorkQueryParams.keyWord && entpCourseWorkQueryParams.keyWord !== '' ? entpCourseWorkQueryParams.keyWord:'',
|
keyword: entpCourseWorkQueryParams.keyWord && entpCourseWorkQueryParams.keyWord !== '' ? entpCourseWorkQueryParams.keyWord:'',
|
||||||
|
|
||||||
|
@ -334,13 +329,10 @@ const handleQueryFromEntpCourseWork= async (queryType) => {
|
||||||
}
|
}
|
||||||
//console.log("clueres.rows[i].childlist",clueres.rows[i].childlist);
|
//console.log("clueres.rows[i].childlist",clueres.rows[i].childlist);
|
||||||
if (clueres.rows[i].childlist != '') {
|
if (clueres.rows[i].childlist != '') {
|
||||||
const tmpJson = '['+clueres.rows[i].childlist+']';
|
clueres.rows[i].childArray = JSON.parse('['+clueres.rows[i].childlist+']');
|
||||||
if (isJson(tmpJson)){
|
|
||||||
clueres.rows[i].childArray = JSON.parse(tmpJson);
|
|
||||||
for (var j=0; j<clueres.rows[i].childArray.length; j++) {
|
for (var j=0; j<clueres.rows[i].childArray.length; j++) {
|
||||||
clueres.rows[i].childArray[j].title = clueres.rows[i].childArray[j].title.replace(/(<([^>]+)>)/ig, '');
|
clueres.rows[i].childArray[j].title = clueres.rows[i].childArray[j].title.replace(/(<([^>]+)>)/ig, '');
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
clueres.rows[i].childArray = {};
|
clueres.rows[i].childArray = {};
|
||||||
}
|
}
|
||||||
|
@ -351,7 +343,6 @@ const handleQueryFromEntpCourseWork= async (queryType) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注意: 该方法已不再使用, 具体知识点初始化方法查看 useClassTaskStore - 241230
|
|
||||||
* 3、知识点
|
* 3、知识点
|
||||||
*/
|
*/
|
||||||
const getEntpCourseWorkPointList = async () => {
|
const getEntpCourseWorkPointList = async () => {
|
||||||
|
@ -469,29 +460,19 @@ const captureScreenshot = (id) => {
|
||||||
// 防抖
|
// 防抖
|
||||||
const debounceQueryData = debounce(() => {
|
const debounceQueryData = debounce(() => {
|
||||||
console.log("防抖 加载数据中...")
|
console.log("防抖 加载数据中...")
|
||||||
console.log(props.bookobj,'课程选择')
|
|
||||||
// 初始化滚动加载参数
|
// 初始化滚动加载参数
|
||||||
initPageParams();
|
initPageParams();
|
||||||
// 习题资源
|
// 习题资源
|
||||||
handleQueryFromEntpCourseWork(0);
|
handleQueryFromEntpCourseWork(0);
|
||||||
// 框架梳理
|
// 框架梳理
|
||||||
//getQueryFromEvaluationclue();
|
getQueryFromEvaluationclue();
|
||||||
// 知识点
|
// 知识点
|
||||||
//getEntpCourseWorkPointList();
|
getEntpCourseWorkPointList();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
//watch(() => props.bookobj.levelSecondId, async (newVal, oldVal) => {
|
|
||||||
|
|
||||||
watch([
|
watch(() => props.bookobj.levelSecondId, (newVal, oldVal) => {
|
||||||
() => props.bookobj.levelFirstId,
|
|
||||||
() => props.bookobj.levelSecondId
|
|
||||||
], ([newLevelSecondId, newLevelFirstId], [oldLevelSecondId, oldLevelFirstId]) => {
|
|
||||||
console.log(props.bookobj,'课程选择')
|
console.log(props.bookobj,'课程选择')
|
||||||
// 默认选择一级单元时, 不自动获取试题, 需手动按钮获取试题
|
|
||||||
if (props.bookobj.levelSecondId == '') {
|
|
||||||
workResource.entpCourseWorkList = [];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
debounceQueryData();
|
debounceQueryData();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -734,10 +734,6 @@ const msgHandle = (msg) => {
|
||||||
Homework.win = null
|
Homework.win = null
|
||||||
window.close() // 关闭窗口
|
window.close() // 关闭窗口
|
||||||
break
|
break
|
||||||
case MsgEnum.HEADS.MSG_pushSreen_experiment: // 实验:
|
|
||||||
Homework.win = null
|
|
||||||
window.close() // 关闭窗口
|
|
||||||
break
|
|
||||||
// case 'TIMAddRecvNewMsgCallback': // 收到新消息 data=[]
|
// case 'TIMAddRecvNewMsgCallback': // 收到新消息 data=[]
|
||||||
// {
|
// {
|
||||||
// (data||[]).forEach(o => {
|
// (data||[]).forEach(o => {
|
||||||
|
@ -821,7 +817,6 @@ onUnmounted(() => {
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.teachClassTask{
|
.teachClassTask{
|
||||||
padding: 10px;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
|
@ -59,10 +59,10 @@ const getHomework = async () => {
|
||||||
homeworkList.value = rows || [];
|
homeworkList.value = rows || [];
|
||||||
homeworkList.value.forEach((item) => {
|
homeworkList.value.forEach((item) => {
|
||||||
// 处理任务类型的UI
|
// 处理任务类型的UI
|
||||||
if (item.worktype == '课堂展示') {
|
if (item.worktype == '学习目标定位') {
|
||||||
item.workclass = 'success'
|
item.workclass = 'success'
|
||||||
item.workcodesList = JSON.parse(item.workcodes)
|
item.workcodesList = JSON.parse(item.workcodes)
|
||||||
} else if (item.worktype == '科学实验') {
|
} else if (item.worktype == '教材研读') {
|
||||||
item.workclass = 'primary'
|
item.workclass = 'primary'
|
||||||
} else if (item.worktype == '框架梳理') {
|
} else if (item.worktype == '框架梳理') {
|
||||||
item.workclass = 'warning'
|
item.workclass = 'warning'
|
||||||
|
|
|
@ -58,10 +58,10 @@ import { useGetSubject } from '@/hooks/useGetSubject'
|
||||||
import { sessionStore } from '@/utils/store'
|
import { sessionStore } from '@/utils/store'
|
||||||
import { debounce } from 'lodash'
|
import { debounce } from 'lodash'
|
||||||
|
|
||||||
// import useUserStore from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
// import useClassTaskStore from '@/store/modules/classTask'
|
import useClassTaskStore from '@/store/modules/classTask'
|
||||||
// const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
// const classTaskStore = useClassTaskStore();
|
const classTaskStore = useClassTaskStore();
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { ipcRenderer } = window.electron || {}
|
const { ipcRenderer } = window.electron || {}
|
||||||
|
@ -217,7 +217,7 @@ onMounted(async ()=>{
|
||||||
chartInstance = echarts.init(chartDom.value)
|
chartInstance = echarts.init(chartDom.value)
|
||||||
|
|
||||||
// 更新第三方题型题类
|
// 更新第三方题型题类
|
||||||
//await classTaskStore.initJYInfo(userStore.user);
|
await classTaskStore.initJYInfo(userStore.user);
|
||||||
|
|
||||||
const option = {
|
const option = {
|
||||||
|
|
||||||
|
|
|
@ -1,427 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="login-container">
|
|
||||||
<div class="box-item desc">
|
|
||||||
<div class="welcome">
|
|
||||||
<p>欢迎登录 {{ homeTitle }}</p>
|
|
||||||
</div>
|
|
||||||
<img class="welcome-img" :src="leftBg2" />
|
|
||||||
</div>
|
|
||||||
<div class="box-item login" v-if="isRegister">
|
|
||||||
<WindowTools :is-has-max="false" />
|
|
||||||
<div class="login-title">账号登录</div>
|
|
||||||
<el-form ref="formRef" class="login-form" :model="loginForm" :rules="rules" size="large">
|
|
||||||
<el-form-item prop="username">
|
|
||||||
<el-input v-model.trim="loginForm.username" placeholder="请输入用户名" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="password" style="margin-bottom: 15px">
|
|
||||||
<el-input v-model="loginForm.password" autocomplete="on" type="password" placeholder="请输入密码" />
|
|
||||||
</el-form-item>
|
|
||||||
<div class="flex mb-5">
|
|
||||||
<el-checkbox v-model="loginForm.rememberMe">记住密码</el-checkbox>
|
|
||||||
<!-- <el-checkbox >阅读并同意《xxx》</el-checkbox> -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-form-item>
|
|
||||||
<el-button :loading="btnLoading" class="btn" type="primary" @click="submitForm(formRef)">登录</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
<div class="flex mb-4" style="display: flex;justify-content: center;color: #ccc;cursor: pointer;">
|
|
||||||
<a class="hover:text-sky-500" style="margin-right: 10px;" @click="gotoreRegister">注册账号</a>
|
|
||||||
</div>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="box-item login" v-else>
|
|
||||||
<WindowTools :is-has-max="false" />
|
|
||||||
<div class="login-title">账号注册</div>
|
|
||||||
<el-form ref="ruleFormRef" class="login-form" :model="ruleForm" label-width="auto" :rules="rules" size="large">
|
|
||||||
<el-form-item label="手机号" prop="username">
|
|
||||||
<el-input v-model="ruleForm.username" placeholder="请输入手机号" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="验证码" prop="smsCode" style="display: flex">
|
|
||||||
<el-input style="width:185px" v-model="ruleForm.smsCode" placeholder="请输入验证码" /><el-button style="margin-left:10px;width:100px" :disabled="codeName=='发送验证码'?false:true" type="primary" @click="sendyzm">{{ codeName }}</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="密码" prop="password" >
|
|
||||||
<el-input autocomplete="on" type="password" v-model="ruleForm.password" placeholder="请输入密码" />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item>
|
|
||||||
<el-button class="btn" type="primary" @click="RegisterForm(ruleFormRef)">立即注册</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
<div class="flex mb-4" style="display: flex;justify-content: center;color: #ccc;cursor: pointer;">
|
|
||||||
<a class="hover:text-sky-500" style="margin-right: 10px;" @click="gotoLogin"> 《 返回登录 </a>
|
|
||||||
</div>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-dialog v-model="showDownLoading" width="500" :show-close="false" :close-on-click-modal="false"
|
|
||||||
:close-on-press-escape="false" align-center>
|
|
||||||
<el-progress :text-inside="true" :stroke-width="22" :percentage="downloadProp" :show-text="false"
|
|
||||||
status="success" />
|
|
||||||
</el-dialog>
|
|
||||||
<el-dialog
|
|
||||||
v-model="isImg"
|
|
||||||
title="人机验证"
|
|
||||||
width="500"
|
|
||||||
style=" -webkit-app-region: no-drag;"
|
|
||||||
>
|
|
||||||
<span>根据图片回答相关问题1</span>
|
|
||||||
<div style="display: flex;align-items: center;;margin-top:30px">
|
|
||||||
<img :src="isPeopleImg" style="width:200px;height:60px;cursor: pointer;" alt="" srcset="" @click="refreshImg">
|
|
||||||
<el-input v-model="ruleForm.imgCode" style="width: 250px;height:40px;margin-left:20px" placeholder="请根据图片填入答案" />
|
|
||||||
</div>
|
|
||||||
<div style="display: flex;justify-content: center;margin-top:30px">
|
|
||||||
<el-button type="primary" @click="sbmitImg">确定</el-button>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
<!--选择学科-->
|
|
||||||
<SelectSubject v-model="isSubject" :login-data="loginForm" />
|
|
||||||
<!--注册弹框-->
|
|
||||||
<Register ref="RegModel"></Register>
|
|
||||||
|
|
||||||
|
|
||||||
</template>
|
|
||||||
<script setup>
|
|
||||||
import { onMounted, reactive, ref } from 'vue'
|
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import { encrypt, decrypt } from '@/utils/jsencrypt'
|
|
||||||
import useUserStore from '@/store/modules/user'
|
|
||||||
import leftBg2 from '@/assets/images/login/left-bg2.png'
|
|
||||||
import WindowTools from '@/components/window-tools/index.vue'
|
|
||||||
import SelectSubject from '@/components/select-subject/index.vue'
|
|
||||||
import Register from './components/Register.vue'
|
|
||||||
import { sessionStore } from '@/utils/store'
|
|
||||||
import {sendcode,instructorregister,getCodeImg} from '@/api/login'
|
|
||||||
|
|
||||||
const { session } = require('@electron/remote')
|
|
||||||
const downloadProp = ref(0)
|
|
||||||
const showDownLoading = ref(false)
|
|
||||||
const { ipcRenderer } = window.electron || {}
|
|
||||||
const formRef = ref()
|
|
||||||
const userStore = useUserStore()
|
|
||||||
const btnLoading = ref(false)
|
|
||||||
const isSubject = ref(false)
|
|
||||||
const RegModel = ref(false)
|
|
||||||
const isRegister = ref(true)
|
|
||||||
const ruleFormRef = ref(null)
|
|
||||||
const codeName=ref('发送验证码')
|
|
||||||
const timer=ref(null)
|
|
||||||
const isImg=ref(false)
|
|
||||||
const isPeopleImg=ref(null)
|
|
||||||
const type=ref(1) // 1注册 2找回密码
|
|
||||||
const resImg = reactive({ imgData: {} });
|
|
||||||
|
|
||||||
//表单
|
|
||||||
const loginForm = reactive({
|
|
||||||
username: '',
|
|
||||||
password: '',
|
|
||||||
rememberMe: false
|
|
||||||
})
|
|
||||||
// 注册表单
|
|
||||||
const ruleForm = reactive({
|
|
||||||
|
|
||||||
})
|
|
||||||
//表单规则
|
|
||||||
const rules = reactive({
|
|
||||||
username: [{ required: true, trigger: 'blur', message: '请输入您的账号' }],
|
|
||||||
password: [{ required: true, trigger: 'blur', message: '请输入您的密码' }],
|
|
||||||
smsCode: [{ required: true, trigger: 'blur', message: '请输入您的验证码' }],
|
|
||||||
})
|
|
||||||
|
|
||||||
let curWinUrl = import.meta.env.VITE_APP_BUILD_BASE_PATH
|
|
||||||
let homeTitle = ref(import.meta.env.VITE_APP_TITLE)
|
|
||||||
ipcRenderer.on('update-app-progress', (e, prop) => {
|
|
||||||
downloadProp.value = prop
|
|
||||||
showDownLoading.value = prop !== 100
|
|
||||||
})
|
|
||||||
const gotoreRegister=()=>{
|
|
||||||
codeName.value='发送验证码'
|
|
||||||
if(timer.value){
|
|
||||||
clearInterval(timer.value);
|
|
||||||
}
|
|
||||||
isRegister.value=false
|
|
||||||
}
|
|
||||||
// 刷新
|
|
||||||
const refreshImg=()=>{
|
|
||||||
getCodeImg().then(res=>{
|
|
||||||
isPeopleImg.value='data:image/jpg;base64,'+res.img
|
|
||||||
resImg.imgData=res
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 提交人机验证
|
|
||||||
const sbmitImg=()=>{
|
|
||||||
if(ruleForm.imgCode){
|
|
||||||
// {mobile:ruleForm.phoneNumber,code:ruleForm.imgCode,uuid:resImg.imgData.uuid}
|
|
||||||
const { username:username,imgCode:code } = ruleForm
|
|
||||||
const params = {
|
|
||||||
username, code,
|
|
||||||
uuid: resImg.imgData.uuid,
|
|
||||||
source:4
|
|
||||||
}
|
|
||||||
sendcode(params).then(res=>{
|
|
||||||
if(res.code==200){
|
|
||||||
ElMessage.success('短信发送成功')
|
|
||||||
ruleForm.Code=res.data
|
|
||||||
isImg.value=false
|
|
||||||
codeName.value=60
|
|
||||||
timer.value=setInterval(()=>{
|
|
||||||
codeName.value--
|
|
||||||
if(codeName.value==0){
|
|
||||||
codeName.value='发送验证码'
|
|
||||||
clearInterval(timer.value);
|
|
||||||
}
|
|
||||||
},1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
ElMessage.error('请根据图片输入验证码')
|
|
||||||
}
|
|
||||||
//
|
|
||||||
}
|
|
||||||
// 发送验证码
|
|
||||||
const sendyzm=()=>{
|
|
||||||
if(ruleForm.username){
|
|
||||||
const pattern = /^1[3-9]\d{9}$/;
|
|
||||||
if( pattern.test(ruleForm.username) ){
|
|
||||||
|
|
||||||
getCodeImg().then(res=>{
|
|
||||||
if(res.code==200){
|
|
||||||
ruleForm.imgCode=null
|
|
||||||
isPeopleImg.value='data:image/jpg;base64,'+res.img
|
|
||||||
isImg.value=true
|
|
||||||
resImg.imgData=res
|
|
||||||
// codeName.value=60
|
|
||||||
// timer.value=setInterval(()=>{
|
|
||||||
// codeName.value--
|
|
||||||
// if(codeName.value==0){
|
|
||||||
// codeName.value='发送验证码'
|
|
||||||
// clearInterval(timer.value);
|
|
||||||
// }
|
|
||||||
// },1000)
|
|
||||||
}else{
|
|
||||||
ElMessage.error(res.msg)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
ElMessage.error('请输入正确的手机号码')
|
|
||||||
}
|
|
||||||
// captchaImg({mobile:ruleForm.phoneNumber}).then(res=>{
|
|
||||||
// console.log('res->', res)
|
|
||||||
// })
|
|
||||||
}else{
|
|
||||||
ElMessage.error('请输入手机号码')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 打开弹窗
|
|
||||||
const RegisterModel = type => {
|
|
||||||
RegModel.value.OpenModel(type)
|
|
||||||
}
|
|
||||||
//登录
|
|
||||||
const submitForm = async (formEl) => {
|
|
||||||
if (!formEl) return
|
|
||||||
await formEl.validate(async (valid) => {
|
|
||||||
if (valid) {
|
|
||||||
btnLoading.value = true
|
|
||||||
|
|
||||||
// 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
|
|
||||||
if (loginForm.rememberMe) {
|
|
||||||
await setCookie('username', loginForm.username)
|
|
||||||
await setCookie('password', encrypt(loginForm.password))
|
|
||||||
await setCookie('rememberMe', loginForm.rememberMe.toString())
|
|
||||||
} else {
|
|
||||||
// 否则移除
|
|
||||||
await session.defaultSession.clearStorageData({
|
|
||||||
origin: curWinUrl,
|
|
||||||
storages: ['cookies']
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await userStore.login(loginForm)
|
|
||||||
await userStore.getInfo()
|
|
||||||
if (userStore.user.edustage || userStore.user.edusubject || isStadium(userStore.user)) {
|
|
||||||
ElMessage.success('登录成功')
|
|
||||||
ipcRenderer && ipcRenderer.send('openMainWindow')
|
|
||||||
} else {
|
|
||||||
isSubject.value = true
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
btnLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const isStadium = (user) => {
|
|
||||||
let roles = user.roles
|
|
||||||
return roles.some(item => item.roleKey === 'stadium')
|
|
||||||
}
|
|
||||||
|
|
||||||
const getCookie = async () => {
|
|
||||||
const username = (await getCookieDetail('username'))[0]
|
|
||||||
const password = (await getCookieDetail('password'))[0]
|
|
||||||
const rememberMe = (await getCookieDetail('rememberMe'))[0]
|
|
||||||
loginForm.username = username ? username.value : loginForm.username
|
|
||||||
loginForm.password = password ? decrypt(password.value) : loginForm.password
|
|
||||||
loginForm.rememberMe = rememberMe ? Boolean(rememberMe.value) : false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取cookie
|
|
||||||
const getCookieDetail = (name) => {
|
|
||||||
return session.defaultSession.cookies.get({ url: curWinUrl, name })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置cookie
|
|
||||||
const setCookie = (name, value) => {
|
|
||||||
// 30天过期
|
|
||||||
let Days = 30
|
|
||||||
let times = Math.round(Date.now() / 1000) + Days * 24 * 60 * 60
|
|
||||||
const cookie = {
|
|
||||||
url: curWinUrl,
|
|
||||||
name,
|
|
||||||
value,
|
|
||||||
expirationDate: times
|
|
||||||
}
|
|
||||||
return session.defaultSession.cookies.set(cookie)
|
|
||||||
}
|
|
||||||
const gotoLogin = () => {
|
|
||||||
codeName.value='发送验证码'
|
|
||||||
if (timer.value){
|
|
||||||
clearInterval(timer.value);
|
|
||||||
}
|
|
||||||
if (ruleFormRef.value) ruleFormRef.value.resetFields()
|
|
||||||
isRegister.value = true
|
|
||||||
}
|
|
||||||
// 注册
|
|
||||||
const RegisterForm = async (formEl) => {
|
|
||||||
if (!formEl) return
|
|
||||||
await formEl.validate((valid, fields) => {
|
|
||||||
if (valid) {
|
|
||||||
instructorregister(ruleForm).then(res=>{
|
|
||||||
if(res.code==200){
|
|
||||||
ElMessage.success('您已注册成功')
|
|
||||||
if (ruleFormRef.value) ruleFormRef.value.resetFields()
|
|
||||||
gotoLogin()
|
|
||||||
}else{
|
|
||||||
ElMessage.error(res.msg)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
console.log('submit!')
|
|
||||||
} else {
|
|
||||||
console.log('error submit!', fields)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
onMounted(() => {
|
|
||||||
localStorage.clear()
|
|
||||||
sessionStore.set('subject', {
|
|
||||||
bookList: null,
|
|
||||||
curBook: null,
|
|
||||||
curNode: null,
|
|
||||||
defaultExpandedKeys: [],
|
|
||||||
subjectTree: []
|
|
||||||
})
|
|
||||||
getCookie()
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.login-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
-webkit-app-region: drag;
|
|
||||||
|
|
||||||
.box-item {
|
|
||||||
width: 444px;
|
|
||||||
height: 520px;
|
|
||||||
|
|
||||||
&.desc {
|
|
||||||
background: #ffffff;
|
|
||||||
border-radius: 12px 0px 0px 12px;
|
|
||||||
box-shadow: 0px 16px 73px 8px rgba(203, 203, 203, 0.2);
|
|
||||||
padding: 23px 25px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
background-color: #003b94;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.login {
|
|
||||||
background: #ffffff;
|
|
||||||
border-radius: 0px 12px 12px 0px;
|
|
||||||
padding: 34px 42px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome {
|
|
||||||
padding-top: 35px;
|
|
||||||
|
|
||||||
p {
|
|
||||||
color: #ffffff;
|
|
||||||
line-height: 25px;
|
|
||||||
letter-spacing: 0.26px;
|
|
||||||
text-align: center;
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 26px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome-img {
|
|
||||||
margin-top: 20px;
|
|
||||||
width: 350px;
|
|
||||||
height: 350px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-title {
|
|
||||||
font-size: 20px;
|
|
||||||
text-align: center;
|
|
||||||
color: #1e1e1e;
|
|
||||||
margin-bottom: 35px;
|
|
||||||
margin-top: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-form {
|
|
||||||
-webkit-app-region: no-drag;
|
|
||||||
|
|
||||||
.captcha-input {
|
|
||||||
width: 60%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.captcha-img {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
width: 350px;
|
|
||||||
height: 50px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 700;
|
|
||||||
text-align: center;
|
|
||||||
color: #ffffff;
|
|
||||||
line-height: 50px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-tool {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
-webkit-app-region: no-drag;
|
|
||||||
|
|
||||||
span {
|
|
||||||
padding: 5px 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-form-item {
|
|
||||||
margin-bottom: 40px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,13 +1,427 @@
|
||||||
<template>
|
<template>
|
||||||
<ycLogin v-if="buildMode === 'yc'||buildMode === 'yc2'">
|
<div class="login-container">
|
||||||
</ycLogin>
|
<div class="box-item desc">
|
||||||
<defultLogin v-else>
|
<div class="welcome">
|
||||||
</defultLogin>
|
<p>欢迎登录 {{ homeTitle }}</p>
|
||||||
|
</div>
|
||||||
|
<img class="welcome-img" :src="leftBg2" />
|
||||||
|
</div>
|
||||||
|
<div class="box-item login" v-if="isRegister">
|
||||||
|
<WindowTools :is-has-max="false" />
|
||||||
|
<div class="login-title">账号登录</div>
|
||||||
|
<el-form ref="formRef" class="login-form" :model="loginForm" :rules="rules" size="large">
|
||||||
|
<el-form-item prop="username">
|
||||||
|
<el-input v-model.trim="loginForm.username" placeholder="请输入用户名" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="password" style="margin-bottom: 15px">
|
||||||
|
<el-input v-model="loginForm.password" autocomplete="on" type="password" placeholder="请输入密码" />
|
||||||
|
</el-form-item>
|
||||||
|
<div class="flex mb-5">
|
||||||
|
<el-checkbox v-model="loginForm.rememberMe">记住密码</el-checkbox>
|
||||||
|
<!-- <el-checkbox >阅读并同意《xxx》</el-checkbox> -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button :loading="btnLoading" class="btn" type="primary" @click="submitForm(formRef)">登录</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<div class="flex mb-4" style="display: flex;justify-content: center;color: #ccc;cursor: pointer;">
|
||||||
|
<a class="hover:text-sky-500" style="margin-right: 10px;" @click="gotoreRegister">注册账号</a>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box-item login" v-else>
|
||||||
|
<WindowTools :is-has-max="false" />
|
||||||
|
<div class="login-title">账号注册</div>
|
||||||
|
<el-form ref="ruleFormRef" class="login-form" :model="ruleForm" label-width="auto" :rules="rules" size="large">
|
||||||
|
<el-form-item label="手机号" prop="username">
|
||||||
|
<el-input v-model="ruleForm.username" placeholder="请输入手机号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="验证码" prop="smsCode" style="display: flex">
|
||||||
|
<el-input style="width:185px" v-model="ruleForm.smsCode" placeholder="请输入验证码" /><el-button style="margin-left:10px;width:100px" :disabled="codeName=='发送验证码'?false:true" type="primary" @click="sendyzm">{{ codeName }}</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="密码" prop="password" >
|
||||||
|
<el-input autocomplete="on" type="password" v-model="ruleForm.password" placeholder="请输入密码" />
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button class="btn" type="primary" @click="RegisterForm(ruleFormRef)">立即注册</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
<div class="flex mb-4" style="display: flex;justify-content: center;color: #ccc;cursor: pointer;">
|
||||||
|
<a class="hover:text-sky-500" style="margin-right: 10px;" @click="gotoLogin"> 《 返回登录 </a>
|
||||||
|
</div>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<el-dialog v-model="showDownLoading" width="500" :show-close="false" :close-on-click-modal="false"
|
||||||
|
:close-on-press-escape="false" align-center>
|
||||||
|
<el-progress :text-inside="true" :stroke-width="22" :percentage="downloadProp" :show-text="false"
|
||||||
|
status="success" />
|
||||||
|
</el-dialog>
|
||||||
|
<el-dialog
|
||||||
|
v-model="isImg"
|
||||||
|
title="人机验证"
|
||||||
|
width="500"
|
||||||
|
style=" -webkit-app-region: no-drag;"
|
||||||
|
>
|
||||||
|
<span>根据图片回答相关问题1</span>
|
||||||
|
<div style="display: flex;align-items: center;;margin-top:30px">
|
||||||
|
<img :src="isPeopleImg" style="width:200px;height:60px;cursor: pointer;" alt="" srcset="" @click="refreshImg">
|
||||||
|
<el-input v-model="ruleForm.imgCode" style="width: 250px;height:40px;margin-left:20px" placeholder="请根据图片填入答案" />
|
||||||
|
</div>
|
||||||
|
<div style="display: flex;justify-content: center;margin-top:30px">
|
||||||
|
<el-button type="primary" @click="sbmitImg">确定</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
<!--选择学科-->
|
||||||
|
<SelectSubject v-model="isSubject" :login-data="loginForm" />
|
||||||
|
<!--注册弹框-->
|
||||||
|
<Register ref="RegModel"></Register>
|
||||||
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import ycLogin from './yc-login.vue'
|
import { onMounted, reactive, ref } from 'vue'
|
||||||
import defultLogin from './defult-login.vue'
|
import { ElMessage } from 'element-plus'
|
||||||
const buildMode = import.meta.env.MODE
|
import { encrypt, decrypt } from '@/utils/jsencrypt'
|
||||||
|
import useUserStore from '@/store/modules/user'
|
||||||
|
import leftBg2 from '@/assets/images/login/left-bg2.png'
|
||||||
|
import WindowTools from '@/components/window-tools/index.vue'
|
||||||
|
import SelectSubject from '@/components/select-subject/index.vue'
|
||||||
|
import Register from './components/Register.vue'
|
||||||
|
import { sessionStore } from '@/utils/store'
|
||||||
|
import {sendcode,instructorregister,getCodeImg} from '@/api/login'
|
||||||
|
|
||||||
|
const { session } = require('@electron/remote')
|
||||||
|
const downloadProp = ref(0)
|
||||||
|
const showDownLoading = ref(false)
|
||||||
|
const { ipcRenderer } = window.electron || {}
|
||||||
|
const formRef = ref()
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const btnLoading = ref(false)
|
||||||
|
const isSubject = ref(false)
|
||||||
|
const RegModel = ref(false)
|
||||||
|
const isRegister = ref(true)
|
||||||
|
const ruleFormRef = ref(null)
|
||||||
|
const codeName=ref('发送验证码')
|
||||||
|
const timer=ref(null)
|
||||||
|
const isImg=ref(false)
|
||||||
|
const isPeopleImg=ref(null)
|
||||||
|
const type=ref(1) // 1注册 2找回密码
|
||||||
|
const resImg = reactive({ imgData: {} });
|
||||||
|
|
||||||
|
//表单
|
||||||
|
const loginForm = reactive({
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
rememberMe: false
|
||||||
|
})
|
||||||
|
// 注册表单
|
||||||
|
const ruleForm = reactive({
|
||||||
|
|
||||||
|
})
|
||||||
|
//表单规则
|
||||||
|
const rules = reactive({
|
||||||
|
username: [{ required: true, trigger: 'blur', message: '请输入您的账号' }],
|
||||||
|
password: [{ required: true, trigger: 'blur', message: '请输入您的密码' }],
|
||||||
|
smsCode: [{ required: true, trigger: 'blur', message: '请输入您的验证码' }],
|
||||||
|
})
|
||||||
|
|
||||||
|
let curWinUrl = import.meta.env.VITE_APP_BUILD_BASE_PATH
|
||||||
|
let homeTitle = ref(import.meta.env.VITE_APP_TITLE)
|
||||||
|
ipcRenderer.on('update-app-progress', (e, prop) => {
|
||||||
|
downloadProp.value = prop
|
||||||
|
showDownLoading.value = prop !== 100
|
||||||
|
})
|
||||||
|
const gotoreRegister=()=>{
|
||||||
|
codeName.value='发送验证码'
|
||||||
|
if(timer.value){
|
||||||
|
clearInterval(timer.value);
|
||||||
|
}
|
||||||
|
isRegister.value=false
|
||||||
|
}
|
||||||
|
// 刷新
|
||||||
|
const refreshImg=()=>{
|
||||||
|
getCodeImg().then(res=>{
|
||||||
|
isPeopleImg.value='data:image/jpg;base64,'+res.img
|
||||||
|
resImg.imgData=res
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 提交人机验证
|
||||||
|
const sbmitImg=()=>{
|
||||||
|
if(ruleForm.imgCode){
|
||||||
|
// {mobile:ruleForm.phoneNumber,code:ruleForm.imgCode,uuid:resImg.imgData.uuid}
|
||||||
|
const { username:username,imgCode:code } = ruleForm
|
||||||
|
const params = {
|
||||||
|
username, code,
|
||||||
|
uuid: resImg.imgData.uuid,
|
||||||
|
source:4
|
||||||
|
}
|
||||||
|
sendcode(params).then(res=>{
|
||||||
|
if(res.code==200){
|
||||||
|
ElMessage.success('短信发送成功')
|
||||||
|
ruleForm.Code=res.data
|
||||||
|
isImg.value=false
|
||||||
|
codeName.value=60
|
||||||
|
timer.value=setInterval(()=>{
|
||||||
|
codeName.value--
|
||||||
|
if(codeName.value==0){
|
||||||
|
codeName.value='发送验证码'
|
||||||
|
clearInterval(timer.value);
|
||||||
|
}
|
||||||
|
},1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
ElMessage.error('请根据图片输入验证码')
|
||||||
|
}
|
||||||
|
//
|
||||||
|
}
|
||||||
|
// 发送验证码
|
||||||
|
const sendyzm=()=>{
|
||||||
|
if(ruleForm.username){
|
||||||
|
const pattern = /^1[3-9]\d{9}$/;
|
||||||
|
if( pattern.test(ruleForm.username) ){
|
||||||
|
|
||||||
|
getCodeImg().then(res=>{
|
||||||
|
if(res.code==200){
|
||||||
|
ruleForm.imgCode=null
|
||||||
|
isPeopleImg.value='data:image/jpg;base64,'+res.img
|
||||||
|
isImg.value=true
|
||||||
|
resImg.imgData=res
|
||||||
|
// codeName.value=60
|
||||||
|
// timer.value=setInterval(()=>{
|
||||||
|
// codeName.value--
|
||||||
|
// if(codeName.value==0){
|
||||||
|
// codeName.value='发送验证码'
|
||||||
|
// clearInterval(timer.value);
|
||||||
|
// }
|
||||||
|
// },1000)
|
||||||
|
}else{
|
||||||
|
ElMessage.error(res.msg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
ElMessage.error('请输入正确的手机号码')
|
||||||
|
}
|
||||||
|
// captchaImg({mobile:ruleForm.phoneNumber}).then(res=>{
|
||||||
|
// console.log('res->', res)
|
||||||
|
// })
|
||||||
|
}else{
|
||||||
|
ElMessage.error('请输入手机号码')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 打开弹窗
|
||||||
|
const RegisterModel = type => {
|
||||||
|
RegModel.value.OpenModel(type)
|
||||||
|
}
|
||||||
|
//登录
|
||||||
|
const submitForm = async (formEl) => {
|
||||||
|
if (!formEl) return
|
||||||
|
await formEl.validate(async (valid) => {
|
||||||
|
if (valid) {
|
||||||
|
btnLoading.value = true
|
||||||
|
|
||||||
|
// 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
|
||||||
|
if (loginForm.rememberMe) {
|
||||||
|
await setCookie('username', loginForm.username)
|
||||||
|
await setCookie('password', encrypt(loginForm.password))
|
||||||
|
await setCookie('rememberMe', loginForm.rememberMe.toString())
|
||||||
|
} else {
|
||||||
|
// 否则移除
|
||||||
|
await session.defaultSession.clearStorageData({
|
||||||
|
origin: curWinUrl,
|
||||||
|
storages: ['cookies']
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await userStore.login(loginForm)
|
||||||
|
await userStore.getInfo()
|
||||||
|
if (userStore.user.edustage || userStore.user.edusubject || isStadium(userStore.user)) {
|
||||||
|
ElMessage.success('登录成功')
|
||||||
|
ipcRenderer && ipcRenderer.send('openMainWindow')
|
||||||
|
} else {
|
||||||
|
isSubject.value = true
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
btnLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const isStadium = (user) => {
|
||||||
|
let roles = user.roles
|
||||||
|
return roles.some(item => item.roleKey === 'stadium')
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCookie = async () => {
|
||||||
|
const username = (await getCookieDetail('username'))[0]
|
||||||
|
const password = (await getCookieDetail('password'))[0]
|
||||||
|
const rememberMe = (await getCookieDetail('rememberMe'))[0]
|
||||||
|
loginForm.username = username ? username.value : loginForm.username
|
||||||
|
loginForm.password = password ? decrypt(password.value) : loginForm.password
|
||||||
|
loginForm.rememberMe = rememberMe ? Boolean(rememberMe.value) : false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取cookie
|
||||||
|
const getCookieDetail = (name) => {
|
||||||
|
return session.defaultSession.cookies.get({ url: curWinUrl, name })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置cookie
|
||||||
|
const setCookie = (name, value) => {
|
||||||
|
// 30天过期
|
||||||
|
let Days = 30
|
||||||
|
let times = Math.round(Date.now() / 1000) + Days * 24 * 60 * 60
|
||||||
|
const cookie = {
|
||||||
|
url: curWinUrl,
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
expirationDate: times
|
||||||
|
}
|
||||||
|
return session.defaultSession.cookies.set(cookie)
|
||||||
|
}
|
||||||
|
const gotoLogin = () => {
|
||||||
|
codeName.value='发送验证码'
|
||||||
|
if (timer.value){
|
||||||
|
clearInterval(timer.value);
|
||||||
|
}
|
||||||
|
if (ruleFormRef.value) ruleFormRef.value.resetFields()
|
||||||
|
isRegister.value = true
|
||||||
|
}
|
||||||
|
// 注册
|
||||||
|
const RegisterForm = async (formEl) => {
|
||||||
|
if (!formEl) return
|
||||||
|
await formEl.validate((valid, fields) => {
|
||||||
|
if (valid) {
|
||||||
|
instructorregister(ruleForm).then(res=>{
|
||||||
|
if(res.code==200){
|
||||||
|
ElMessage.success('您已注册成功')
|
||||||
|
if (ruleFormRef.value) ruleFormRef.value.resetFields()
|
||||||
|
gotoLogin()
|
||||||
|
}else{
|
||||||
|
ElMessage.error(res.msg)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
console.log('submit!')
|
||||||
|
} else {
|
||||||
|
console.log('error submit!', fields)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
onMounted(() => {
|
||||||
|
localStorage.clear()
|
||||||
|
sessionStore.set('subject', {
|
||||||
|
bookList: null,
|
||||||
|
curBook: null,
|
||||||
|
curNode: null,
|
||||||
|
defaultExpandedKeys: [],
|
||||||
|
subjectTree: []
|
||||||
|
})
|
||||||
|
getCookie()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.login-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
-webkit-app-region: drag;
|
||||||
|
|
||||||
|
.box-item {
|
||||||
|
width: 444px;
|
||||||
|
height: 520px;
|
||||||
|
|
||||||
|
&.desc {
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 12px 0px 0px 12px;
|
||||||
|
box-shadow: 0px 16px 73px 8px rgba(203, 203, 203, 0.2);
|
||||||
|
padding: 23px 25px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
background-color: #003b94;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.login {
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 0px 12px 12px 0px;
|
||||||
|
padding: 34px 42px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome {
|
||||||
|
padding-top: 35px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 25px;
|
||||||
|
letter-spacing: 0.26px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 26px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome-img {
|
||||||
|
margin-top: 20px;
|
||||||
|
width: 350px;
|
||||||
|
height: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-title {
|
||||||
|
font-size: 20px;
|
||||||
|
text-align: center;
|
||||||
|
color: #1e1e1e;
|
||||||
|
margin-bottom: 35px;
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-form {
|
||||||
|
-webkit-app-region: no-drag;
|
||||||
|
|
||||||
|
.captcha-input {
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.captcha-img {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
width: 350px;
|
||||||
|
height: 50px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
text-align: center;
|
||||||
|
color: #ffffff;
|
||||||
|
line-height: 50px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-tool {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
-webkit-app-region: no-drag;
|
||||||
|
|
||||||
|
span {
|
||||||
|
padding: 5px 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-form-item {
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,463 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="login-container">
|
|
||||||
<div class="login-yc">
|
|
||||||
<img class="welcome-img" :src="buildMode === 'yc2'?leftBg2:leftBg1" />
|
|
||||||
</div>
|
|
||||||
<div class="box-item login" v-if="isRegister">
|
|
||||||
<WindowTools :is-has-max="false" />
|
|
||||||
<div style="display: flex;justify-content: center;"><img class="title-logo" :src="yclogo" /></div>
|
|
||||||
<div class="login-title">永川中小学</div>
|
|
||||||
<div class="login-title2">{{buildMode === 'yc2'?'虚拟仿真AI实训教学管理系统':'人工智能赋能科学素养与劳动技能系统'}}</div>
|
|
||||||
<el-form ref="formRef" class="login-form" :model="loginForm" :rules="rules" size="large">
|
|
||||||
<el-form-item prop="username">
|
|
||||||
<el-input v-model.trim="loginForm.username" placeholder="请输入用户名" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item prop="password" style="margin-bottom: 15px">
|
|
||||||
<el-input v-model="loginForm.password" autocomplete="on" type="password" placeholder="请输入密码" />
|
|
||||||
</el-form-item>
|
|
||||||
<div class="flex mb-5">
|
|
||||||
<el-checkbox v-model="loginForm.rememberMe">记住密码</el-checkbox>
|
|
||||||
<!-- <el-checkbox >阅读并同意《xxx》</el-checkbox> -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-form-item style="margin-bottom: 20px">
|
|
||||||
<el-button :loading="btnLoading" class="btn" type="primary" @click="submitForm(formRef)">登录</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
<div class="flex mb-4" style="display: flex;justify-content: center;color: #ccc;cursor: pointer;">
|
|
||||||
<a class="hover:text-sky-500" style="margin-right: 10px;" @click="gotoreRegister">注册账号</a>
|
|
||||||
</div>
|
|
||||||
<div class="title-bottom">
|
|
||||||
重庆市永川区教育委员会
|
|
||||||
</div>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="box-item login" v-else>
|
|
||||||
<WindowTools :is-has-max="false" />
|
|
||||||
<div class="login-title">账号注册</div>
|
|
||||||
<el-form ref="ruleFormRef" class="login-form" :model="ruleForm" label-width="auto" :rules="rules" size="large">
|
|
||||||
<el-form-item label="手机号" prop="username">
|
|
||||||
<el-input v-model="ruleForm.username" placeholder="请输入手机号" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="验证码" prop="smsCode" style="display: flex">
|
|
||||||
<el-input style="width:185px" v-model="ruleForm.smsCode" placeholder="请输入验证码" /><el-button style="margin-left:10px;width:100px" :disabled="codeName=='发送验证码'?false:true" type="primary" @click="sendyzm">{{ codeName }}</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="密码" prop="password" >
|
|
||||||
<el-input autocomplete="on" type="password" v-model="ruleForm.password" placeholder="请输入密码" />
|
|
||||||
</el-form-item>
|
|
||||||
|
|
||||||
<el-form-item>
|
|
||||||
<el-button class="btn" type="primary" @click="RegisterForm(ruleFormRef)">立即注册</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
<div class="flex mb-4" style="display: flex;justify-content: center;color: #ccc;cursor: pointer;">
|
|
||||||
<a class="hover:text-sky-500" style="margin-right: 10px;" @click="gotoLogin"> 《 返回登录 </a>
|
|
||||||
</div>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-dialog v-model="showDownLoading" width="500" :show-close="false" :close-on-click-modal="false"
|
|
||||||
:close-on-press-escape="false" align-center>
|
|
||||||
<el-progress :text-inside="true" :stroke-width="22" :percentage="downloadProp" :show-text="false"
|
|
||||||
status="success" />
|
|
||||||
</el-dialog>
|
|
||||||
<el-dialog
|
|
||||||
v-model="isImg"
|
|
||||||
title="人机验证"
|
|
||||||
width="500"
|
|
||||||
style=" -webkit-app-region: no-drag;"
|
|
||||||
>
|
|
||||||
<span>根据图片回答相关问题1</span>
|
|
||||||
<div style="display: flex;align-items: center;;margin-top:30px">
|
|
||||||
<img :src="isPeopleImg" style="width:200px;height:60px;cursor: pointer;" alt="" srcset="" @click="refreshImg">
|
|
||||||
<el-input v-model="ruleForm.imgCode" style="width: 250px;height:40px;margin-left:20px" placeholder="请根据图片填入答案" />
|
|
||||||
</div>
|
|
||||||
<div style="display: flex;justify-content: center;margin-top:30px">
|
|
||||||
<el-button type="primary" @click="sbmitImg">确定</el-button>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
<!--选择学科-->
|
|
||||||
<SelectSubject v-model="isSubject" :login-data="loginForm" />
|
|
||||||
<!--注册弹框-->
|
|
||||||
<Register ref="RegModel"></Register>
|
|
||||||
|
|
||||||
|
|
||||||
</template>
|
|
||||||
<script setup>
|
|
||||||
import { onMounted, reactive, ref } from 'vue'
|
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import { encrypt, decrypt } from '@/utils/jsencrypt'
|
|
||||||
import useUserStore from '@/store/modules/user'
|
|
||||||
import WindowTools from '@/components/window-tools/index.vue'
|
|
||||||
import SelectSubject from '@/components/select-subject/index.vue'
|
|
||||||
import Register from './components/Register.vue'
|
|
||||||
import { sessionStore } from '@/utils/store'
|
|
||||||
import {sendcode,instructorregister,getCodeImg} from '@/api/login'
|
|
||||||
import yclogo from '@/assets/images/login/yc-logo.png'
|
|
||||||
import leftBg1 from '@/assets/images/login/ycpeitu.png'
|
|
||||||
import leftBg2 from '@/assets/images/login/ycpeitu2.jpg'
|
|
||||||
const { session } = require('@electron/remote')
|
|
||||||
const buildMode = import.meta.env.MODE
|
|
||||||
const downloadProp = ref(0)
|
|
||||||
const showDownLoading = ref(false)
|
|
||||||
const { ipcRenderer } = window.electron || {}
|
|
||||||
const formRef = ref()
|
|
||||||
const userStore = useUserStore()
|
|
||||||
const btnLoading = ref(false)
|
|
||||||
const isSubject = ref(false)
|
|
||||||
const RegModel = ref(false)
|
|
||||||
const isRegister = ref(true)
|
|
||||||
const ruleFormRef = ref(null)
|
|
||||||
const codeName=ref('发送验证码')
|
|
||||||
const timer=ref(null)
|
|
||||||
const isImg=ref(false)
|
|
||||||
const isPeopleImg=ref(null)
|
|
||||||
const type=ref(1) // 1注册 2找回密码
|
|
||||||
const resImg = reactive({ imgData: {} });
|
|
||||||
|
|
||||||
//表单
|
|
||||||
const loginForm = reactive({
|
|
||||||
username: '',
|
|
||||||
password: '',
|
|
||||||
rememberMe: false
|
|
||||||
})
|
|
||||||
// 注册表单
|
|
||||||
const ruleForm = reactive({
|
|
||||||
|
|
||||||
})
|
|
||||||
//表单规则
|
|
||||||
const rules = reactive({
|
|
||||||
username: [{ required: true, trigger: 'blur', message: '请输入您的账号' }],
|
|
||||||
password: [{ required: true, trigger: 'blur', message: '请输入您的密码' }],
|
|
||||||
smsCode: [{ required: true, trigger: 'blur', message: '请输入您的验证码' }],
|
|
||||||
})
|
|
||||||
|
|
||||||
let curWinUrl = import.meta.env.VITE_APP_BUILD_BASE_PATH
|
|
||||||
let homeTitle = ref(import.meta.env.VITE_APP_TITLE)
|
|
||||||
ipcRenderer.on('update-app-progress', (e, prop) => {
|
|
||||||
downloadProp.value = prop
|
|
||||||
showDownLoading.value = prop !== 100
|
|
||||||
})
|
|
||||||
const gotoreRegister=()=>{
|
|
||||||
codeName.value='发送验证码'
|
|
||||||
if(timer.value){
|
|
||||||
clearInterval(timer.value);
|
|
||||||
}
|
|
||||||
isRegister.value=false
|
|
||||||
}
|
|
||||||
// 刷新
|
|
||||||
const refreshImg=()=>{
|
|
||||||
getCodeImg().then(res=>{
|
|
||||||
isPeopleImg.value='data:image/jpg;base64,'+res.img
|
|
||||||
resImg.imgData=res
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 提交人机验证
|
|
||||||
const sbmitImg=()=>{
|
|
||||||
if(ruleForm.imgCode){
|
|
||||||
// {mobile:ruleForm.phoneNumber,code:ruleForm.imgCode,uuid:resImg.imgData.uuid}
|
|
||||||
const { username:username,imgCode:code } = ruleForm
|
|
||||||
const params = {
|
|
||||||
username, code,
|
|
||||||
uuid: resImg.imgData.uuid,
|
|
||||||
source:4
|
|
||||||
}
|
|
||||||
sendcode(params).then(res=>{
|
|
||||||
if(res.code==200){
|
|
||||||
ElMessage.success('短信发送成功')
|
|
||||||
ruleForm.Code=res.data
|
|
||||||
isImg.value=false
|
|
||||||
codeName.value=60
|
|
||||||
timer.value=setInterval(()=>{
|
|
||||||
codeName.value--
|
|
||||||
if(codeName.value==0){
|
|
||||||
codeName.value='发送验证码'
|
|
||||||
clearInterval(timer.value);
|
|
||||||
}
|
|
||||||
},1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
ElMessage.error('请根据图片输入验证码')
|
|
||||||
}
|
|
||||||
//
|
|
||||||
}
|
|
||||||
// 发送验证码
|
|
||||||
const sendyzm=()=>{
|
|
||||||
if(ruleForm.username){
|
|
||||||
const pattern = /^1[3-9]\d{9}$/;
|
|
||||||
if( pattern.test(ruleForm.username) ){
|
|
||||||
|
|
||||||
getCodeImg().then(res=>{
|
|
||||||
if(res.code==200){
|
|
||||||
ruleForm.imgCode=null
|
|
||||||
isPeopleImg.value='data:image/jpg;base64,'+res.img
|
|
||||||
isImg.value=true
|
|
||||||
resImg.imgData=res
|
|
||||||
// codeName.value=60
|
|
||||||
// timer.value=setInterval(()=>{
|
|
||||||
// codeName.value--
|
|
||||||
// if(codeName.value==0){
|
|
||||||
// codeName.value='发送验证码'
|
|
||||||
// clearInterval(timer.value);
|
|
||||||
// }
|
|
||||||
// },1000)
|
|
||||||
}else{
|
|
||||||
ElMessage.error(res.msg)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
ElMessage.error('请输入正确的手机号码')
|
|
||||||
}
|
|
||||||
// captchaImg({mobile:ruleForm.phoneNumber}).then(res=>{
|
|
||||||
// console.log('res->', res)
|
|
||||||
// })
|
|
||||||
}else{
|
|
||||||
ElMessage.error('请输入手机号码')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 打开弹窗
|
|
||||||
const RegisterModel = type => {
|
|
||||||
RegModel.value.OpenModel(type)
|
|
||||||
}
|
|
||||||
//登录
|
|
||||||
const submitForm = async (formEl) => {
|
|
||||||
if (!formEl) return
|
|
||||||
await formEl.validate(async (valid) => {
|
|
||||||
if (valid) {
|
|
||||||
btnLoading.value = true
|
|
||||||
|
|
||||||
// 勾选了需要记住密码设置在 cookie 中设置记住用户名和密码
|
|
||||||
if (loginForm.rememberMe) {
|
|
||||||
await setCookie('username', loginForm.username)
|
|
||||||
await setCookie('password', encrypt(loginForm.password))
|
|
||||||
await setCookie('rememberMe', loginForm.rememberMe.toString())
|
|
||||||
} else {
|
|
||||||
// 否则移除
|
|
||||||
await session.defaultSession.clearStorageData({
|
|
||||||
origin: curWinUrl,
|
|
||||||
storages: ['cookies']
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await userStore.login(loginForm)
|
|
||||||
await userStore.getInfo()
|
|
||||||
if (userStore.user.edustage || userStore.user.edusubject || isStadium(userStore.user)) {
|
|
||||||
ElMessage.success('登录成功')
|
|
||||||
ipcRenderer && ipcRenderer.send('openMainWindow')
|
|
||||||
} else {
|
|
||||||
isSubject.value = true
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
btnLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const isStadium = (user) => {
|
|
||||||
let roles = user.roles
|
|
||||||
return roles.some(item => item.roleKey === 'stadium')
|
|
||||||
}
|
|
||||||
|
|
||||||
const getCookie = async () => {
|
|
||||||
const username = (await getCookieDetail('username'))[0]
|
|
||||||
const password = (await getCookieDetail('password'))[0]
|
|
||||||
const rememberMe = (await getCookieDetail('rememberMe'))[0]
|
|
||||||
loginForm.username = username ? username.value : loginForm.username
|
|
||||||
loginForm.password = password ? decrypt(password.value) : loginForm.password
|
|
||||||
loginForm.rememberMe = rememberMe ? Boolean(rememberMe.value) : false
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取cookie
|
|
||||||
const getCookieDetail = (name) => {
|
|
||||||
return session.defaultSession.cookies.get({ url: curWinUrl, name })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置cookie
|
|
||||||
const setCookie = (name, value) => {
|
|
||||||
// 30天过期
|
|
||||||
let Days = 30
|
|
||||||
let times = Math.round(Date.now() / 1000) + Days * 24 * 60 * 60
|
|
||||||
const cookie = {
|
|
||||||
url: curWinUrl,
|
|
||||||
name,
|
|
||||||
value,
|
|
||||||
expirationDate: times
|
|
||||||
}
|
|
||||||
return session.defaultSession.cookies.set(cookie)
|
|
||||||
}
|
|
||||||
const gotoLogin = () => {
|
|
||||||
codeName.value='发送验证码'
|
|
||||||
if (timer.value){
|
|
||||||
clearInterval(timer.value);
|
|
||||||
}
|
|
||||||
if (ruleFormRef.value) ruleFormRef.value.resetFields()
|
|
||||||
isRegister.value = true
|
|
||||||
}
|
|
||||||
// 注册
|
|
||||||
const RegisterForm = async (formEl) => {
|
|
||||||
if (!formEl) return
|
|
||||||
await formEl.validate((valid, fields) => {
|
|
||||||
if (valid) {
|
|
||||||
instructorregister(ruleForm).then(res=>{
|
|
||||||
if(res.code==200){
|
|
||||||
ElMessage.success('您已注册成功')
|
|
||||||
if (ruleFormRef.value) ruleFormRef.value.resetFields()
|
|
||||||
gotoLogin()
|
|
||||||
}else{
|
|
||||||
ElMessage.error(res.msg)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
console.log('submit!')
|
|
||||||
} else {
|
|
||||||
console.log('error submit!', fields)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
onMounted(() => {
|
|
||||||
localStorage.clear()
|
|
||||||
sessionStore.set('subject', {
|
|
||||||
bookList: null,
|
|
||||||
curBook: null,
|
|
||||||
curNode: null,
|
|
||||||
defaultExpandedKeys: [],
|
|
||||||
subjectTree: []
|
|
||||||
})
|
|
||||||
getCookie()
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.login-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
-webkit-app-region: drag;
|
|
||||||
|
|
||||||
.login-yc{
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
img{
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.box-item {
|
|
||||||
width: 370px;
|
|
||||||
height: 520px;
|
|
||||||
|
|
||||||
&.desc {
|
|
||||||
background: #ffffff;
|
|
||||||
border-radius: 12px 0px 0px 12px;
|
|
||||||
box-shadow: 0px 16px 73px 8px rgba(203, 203, 203, 0.2);
|
|
||||||
padding: 23px 25px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
background-color: #003b94;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.login {
|
|
||||||
background: #ffffff;
|
|
||||||
border-radius: 0px 12px 12px 0px;
|
|
||||||
padding: 34px 42px;
|
|
||||||
position: relative;
|
|
||||||
.title-logo{
|
|
||||||
width: 50px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome {
|
|
||||||
padding-top: 35px;
|
|
||||||
|
|
||||||
p {
|
|
||||||
color: #ffffff;
|
|
||||||
line-height: 25px;
|
|
||||||
letter-spacing: 0.26px;
|
|
||||||
text-align: center;
|
|
||||||
font-weight: 700;
|
|
||||||
font-size: 26px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.welcome-img {
|
|
||||||
margin-top: 20px;
|
|
||||||
width: 350px;
|
|
||||||
height: 350px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-title {
|
|
||||||
font-size: 20px;
|
|
||||||
text-align: center;
|
|
||||||
color: #1e1e1e;
|
|
||||||
margin-bottom: 35px;
|
|
||||||
margin-top: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-title {
|
|
||||||
font-size: 20px;
|
|
||||||
text-align: center;
|
|
||||||
color: #1e1e1e;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
margin-top: 5px;
|
|
||||||
font-width: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-title2 {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-form {
|
|
||||||
-webkit-app-region: no-drag;
|
|
||||||
|
|
||||||
.captcha-input {
|
|
||||||
width: 60%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.captcha-img {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-bottom{
|
|
||||||
text-align: center;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 14px;
|
|
||||||
color: rgba(0, 0, 0, 0.45);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn {
|
|
||||||
width: 350px;
|
|
||||||
height: 50px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 700;
|
|
||||||
text-align: center;
|
|
||||||
color: #ffffff;
|
|
||||||
line-height: 50px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-tool {
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
top: 0;
|
|
||||||
-webkit-app-region: no-drag;
|
|
||||||
|
|
||||||
span {
|
|
||||||
padding: 5px 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-form-item {
|
|
||||||
margin-bottom: 40px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<el-row class="model-wrap">
|
<el-row class="model-wrap">
|
||||||
<!-- 左侧 选择教材 目录 -->
|
<!-- 左侧 选择教材 目录 -->
|
||||||
<ChooseTextbook :isClassTask="true" @change-book="changeBook" @node-click="changeBook" />
|
<ChooseTextbook @change-book="changeBook" @node-click="changeBook" />
|
||||||
<!-- 右侧 展示内容 -->
|
<!-- 右侧 展示内容 -->
|
||||||
<div class="right-content">
|
<div class="right-content">
|
||||||
<div class="content-header-wrap">
|
<div class="content-header-wrap">
|
||||||
|
@ -63,8 +63,7 @@
|
||||||
<div class="content-body-right-body">
|
<div class="content-body-right-body">
|
||||||
<div class="content-body-right-item" v-for="(item,index) in tools" :key="index" @click="gotoRoute(item)">
|
<div class="content-body-right-item" v-for="(item,index) in tools" :key="index" @click="gotoRoute(item)">
|
||||||
<div class="content-body-right-item-img">
|
<div class="content-body-right-item-img">
|
||||||
<img v-if="item.suffix" :src="getStaticUrl(`/icon/${item.img}.${item.suffix}`)" />
|
<FileImage :fileName="item.img"/>
|
||||||
<FileImage v-else :fileName="item.img"/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="content-body-right-item-text">{{item.name}}</div>
|
<div class="content-body-right-item-text">{{item.name}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -84,8 +83,6 @@ import useUserStore from '@/store/modules/user' // 用户信息
|
||||||
import ChooseTextbook from '@/components/choose-textbook/index.vue'
|
import ChooseTextbook from '@/components/choose-textbook/index.vue'
|
||||||
import KjListItem from '@/views/prepare/container/kj-list-item.vue'
|
import KjListItem from '@/views/prepare/container/kj-list-item.vue'
|
||||||
import FileImage from '@/components/file-image/index.vue'
|
import FileImage from '@/components/file-image/index.vue'
|
||||||
import progressDialog from '@/views/teachingDesign/container/progress-dialog.vue'
|
|
||||||
import ThumbnailSlide from '@/AixPPTist/src/views/components/ThumbnailSlide/index.vue'
|
|
||||||
import {creatAPT, getSmarttalkPage, getModelInfo} from '@/api/file'
|
import {creatAPT, getSmarttalkPage, getModelInfo} from '@/api/file'
|
||||||
import {ArrowDown, Flag, Position} from '@element-plus/icons-vue'
|
import {ArrowDown, Flag, Position} from '@element-plus/icons-vue'
|
||||||
import {asyncLocalFile, parseCataByNode} from "@/utils/talkFile";
|
import {asyncLocalFile, parseCataByNode} from "@/utils/talkFile";
|
||||||
|
@ -93,21 +90,18 @@ import { dataSetJson } from '@/utils/comm' // 数据集id文生图
|
||||||
import { sessionStore } from '@/utils/store'
|
import { sessionStore } from '@/utils/store'
|
||||||
import {listEntpcourse} from "@/api/teaching/classwork";
|
import {listEntpcourse} from "@/api/teaching/classwork";
|
||||||
import {addEntpcoursefileReturnId, getEntpcoursefile} from "@/api/education/entpcoursefile";
|
import {addEntpcoursefileReturnId, getEntpcoursefile} from "@/api/education/entpcoursefile";
|
||||||
import {createWindow, toLinkLeftWeb, getStaticUrl} from "@/utils/tool";
|
import {createWindow, toLinkLeftWeb} from "@/utils/tool";
|
||||||
import {ElMessage} from "element-plus";
|
import {ElMessage} from "element-plus";
|
||||||
import {PPTXFileToJson} from "@/AixPPTist/src/hooks/useImport";
|
import {PPTXFileToJson} from "@/AixPPTist/src/hooks/useImport";
|
||||||
import * as API_entpcoursefile from "@/api/education/entpcoursefile";
|
import * as API_entpcoursefile from "@/api/education/entpcoursefile";
|
||||||
|
import progressDialog from '@/views/teachingDesign/container/progress-dialog.vue'
|
||||||
import msgUtils from "@/plugins/modal";
|
import msgUtils from "@/plugins/modal";
|
||||||
import * as commUtils from "@/utils/comm";
|
import * as commUtils from "@/utils/comm";
|
||||||
import * as Api_server from "@/api/apiService"; // 学科名字文生图
|
import * as Api_server from "@/api/apiService"; // 学科名字文生图
|
||||||
import useClassTaskStore from '@/store/modules/classTask'
|
|
||||||
import { slidesToImg } from '@/utils/ppt' // ppt相关工具
|
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const userStore = useUserStore().user // 用户信息
|
const userStore = useUserStore().user // 用户信息
|
||||||
const currentNode = ref({})
|
const currentNode = ref({})
|
||||||
const refs = ref([]);
|
const refs = ref([]);
|
||||||
const classTaskStore = useClassTaskStore();
|
|
||||||
|
|
||||||
const collectRef = (key) => {
|
const collectRef = (key) => {
|
||||||
return (el) => {
|
return (el) => {
|
||||||
|
@ -153,7 +147,7 @@ const tools = reactive([{
|
||||||
img: 'airobot'
|
img: 'airobot'
|
||||||
},{
|
},{
|
||||||
name: '语音生成',
|
name: '语音生成',
|
||||||
path: '/model/aiVoice',
|
path: '',
|
||||||
img: 'aiyuyin'
|
img: 'aiyuyin'
|
||||||
},{
|
},{
|
||||||
name: '文生图片',
|
name: '文生图片',
|
||||||
|
@ -172,26 +166,7 @@ const tools = reactive([{
|
||||||
path: 'https://ai.ysaix.com:7845/',
|
path: 'https://ai.ysaix.com:7845/',
|
||||||
type: 'link',
|
type: 'link',
|
||||||
img: 'aiyinyue'
|
img: 'aiyinyue'
|
||||||
},{
|
}])
|
||||||
name: 'Kimi',
|
|
||||||
path: 'https://kimi.moonshot.cn',
|
|
||||||
type: 'link',
|
|
||||||
img: 'kimi',
|
|
||||||
suffix: 'svg'
|
|
||||||
},{
|
|
||||||
name: 'Deepseek',
|
|
||||||
path: 'https://chat.deepseek.com',
|
|
||||||
type: 'link',
|
|
||||||
img: 'deepseek',
|
|
||||||
suffix: 'svg'
|
|
||||||
},{
|
|
||||||
name: '通义千问',
|
|
||||||
path: 'https://tongyi.aliyun.com/qianwen',
|
|
||||||
type: 'link',
|
|
||||||
img: 'tongyi',
|
|
||||||
suffix: 'svg'
|
|
||||||
}
|
|
||||||
])
|
|
||||||
|
|
||||||
const uploadData = ref({
|
const uploadData = ref({
|
||||||
textbookId: null,
|
textbookId: null,
|
||||||
|
@ -211,19 +186,6 @@ const gotoRoute = (item) => {
|
||||||
if (item.path) {
|
if (item.path) {
|
||||||
if (item.path === '/model/aiKolors') {
|
if (item.path === '/model/aiKolors') {
|
||||||
gotoAiKolors(item.path)
|
gotoAiKolors(item.path)
|
||||||
}else if(item.path == '/model/aiVoice'){
|
|
||||||
console.log('aiVoice',uploadData.value)
|
|
||||||
const path = '/model/aiVoice'
|
|
||||||
let subjectdata = sessionStore.get('subject.curNode')
|
|
||||||
let datasubject = `课标-${subjectdata.edustage}-${subjectdata.edusubject}`
|
|
||||||
router.push({
|
|
||||||
path,
|
|
||||||
query: {
|
|
||||||
datasetId: dataSetJson[datasubject],
|
|
||||||
coursetitle: currentNode.value.itemtitle,
|
|
||||||
...uploadData.value
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}else {
|
}else {
|
||||||
router.push(item.path)
|
router.push(item.path)
|
||||||
}
|
}
|
||||||
|
@ -313,14 +275,12 @@ const handleFileChange = ()=> {
|
||||||
createAIPPTByFile(file)
|
createAIPPTByFile(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ppt文件转PPT线上数据
|
|
||||||
const createAIPPTByFile = async (file)=> {
|
const createAIPPTByFile = async (file)=> {
|
||||||
// pgDialog.value.visible = true
|
pgDialog.value.visible = true
|
||||||
// pgDialog.value.pg.percentage = 0
|
pgDialog.value.pg.percentage = 0
|
||||||
const resPptJson = await PPTXFileToJson(file)
|
const resPptJson = await PPTXFileToJson(file)
|
||||||
const { def, slides, ...content } = resPptJson
|
const { def, slides, ...content } = resPptJson
|
||||||
// 生成缩略图
|
|
||||||
const thumbnails = await slidesToImg(slides, content.width)
|
|
||||||
// 转换图片|音频|视频 为线上地址
|
// 转换图片|音频|视频 为线上地址
|
||||||
let completed = 0
|
let completed = 0
|
||||||
const total = slides.length
|
const total = slides.length
|
||||||
|
@ -372,7 +332,6 @@ const createAIPPTByFile = async (file)=> {
|
||||||
entpcourseid: resCourse.id,
|
entpcourseid: resCourse.id,
|
||||||
title: '',
|
title: '',
|
||||||
filetype: 'slide',
|
filetype: 'slide',
|
||||||
thumbnails, // 缩略图-列表
|
|
||||||
slides: resSlides,
|
slides: resSlides,
|
||||||
edituserid: userStore.userId
|
edituserid: userStore.userId
|
||||||
}
|
}
|
||||||
|
@ -443,8 +402,8 @@ const changeBook = async(data) => {
|
||||||
let cata = parseCataByNode(data.node)
|
let cata = parseCataByNode(data.node)
|
||||||
currentNode.value = data.node
|
currentNode.value = data.node
|
||||||
uploadData.value.levelFirstId = cata[0]
|
uploadData.value.levelFirstId = cata[0]
|
||||||
uploadData.value.levelSecondId = cata[1] ?? ''
|
uploadData.value.levelSecondId = cata[1]
|
||||||
uploadData.value.levelThirdId = cata[2] ?? ''
|
uploadData.value.levelThirdId = cata[2]
|
||||||
uploadData.value.textbookId = data.textBook.curBookId
|
uploadData.value.textbookId = data.textBook.curBookId
|
||||||
getModelInfo({cataid: currentNode.value.id}).then(res=>{
|
getModelInfo({cataid: currentNode.value.id}).then(res=>{
|
||||||
console.log(res)
|
console.log(res)
|
||||||
|
@ -484,14 +443,6 @@ const changeBook = async(data) => {
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
currentFileList.value = [...res.rows]
|
currentFileList.value = [...res.rows]
|
||||||
})
|
})
|
||||||
|
|
||||||
// 更新单元章节对应的知识点
|
|
||||||
const pointParams = {
|
|
||||||
...uploadData.value,
|
|
||||||
edustage: data.node.edustage,
|
|
||||||
edusubject: data.node.edusubject,
|
|
||||||
}
|
|
||||||
await classTaskStore.initJYPoint(pointParams);
|
|
||||||
}
|
}
|
||||||
const onchange = (item) => {
|
const onchange = (item) => {
|
||||||
let path = item.path
|
let path = item.path
|
||||||
|
@ -535,8 +486,8 @@ const changeClass = async (type, row, other) => {
|
||||||
createWindow('open-win', {
|
createWindow('open-win', {
|
||||||
url: '/pptist', // 窗口关闭时,清除缓存
|
url: '/pptist', // 窗口关闭时,清除缓存
|
||||||
close: () => {
|
close: () => {
|
||||||
sessionStore.delete('curr.resource') // 清除缓存
|
sessionStore.set('curr.resource', null) // 清除缓存
|
||||||
sessionStore.delete('curr.smarttalk') // 清除缓存
|
sessionStore.set('curr.smarttalk', null) // 清除缓存
|
||||||
getSmarttalkPage({
|
getSmarttalkPage({
|
||||||
...uploadData.value,
|
...uploadData.value,
|
||||||
orderByColumn: 'createTime',
|
orderByColumn: 'createTime',
|
||||||
|
@ -562,9 +513,7 @@ const changeClass = async (type, row, other) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 页面加载
|
// 页面加载
|
||||||
onMounted(async () => {
|
onMounted(() => {
|
||||||
// 更新第三方题型题类
|
|
||||||
await classTaskStore.initJYInfo(userStore);
|
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -691,15 +640,12 @@ onMounted(async () => {
|
||||||
}
|
}
|
||||||
.content-body-right-body{
|
.content-body-right-body{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 15px;
|
|
||||||
padding: 10px;
|
|
||||||
.content-body-right-item{
|
.content-body-right-item{
|
||||||
&:hover{
|
&:hover{
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
height: 80px;
|
height: 80px;
|
||||||
width: 70px;
|
width: 100px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
<div class="paragraphs">
|
<div class="paragraphs">
|
||||||
{{ outputText }}
|
{{ outputText }}
|
||||||
</div>
|
</div>
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" @click="addMessage">{{ outputText ? '重新生成' : '生成大纲' }}</el-button>
|
<el-button style="margin-bottom: 5px;" type="primary" @click="addMessage">从新生成</el-button>
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" @click="activeStep = 1" :disabled="!outputText">下一步</el-button>
|
<el-button style="margin-bottom: 5px;" type="primary" @click="activeStep = 1">下一步</el-button>
|
||||||
</el-card>
|
</el-card>
|
||||||
<el-card v-if="activeStep === 1">
|
<el-card v-if="activeStep === 1">
|
||||||
<div style="padding-bottom: 10px">ppt模板选择</div>
|
<div style="padding-bottom: 10px">ppt模板选择</div>
|
||||||
|
@ -57,7 +57,7 @@
|
||||||
</el-row>
|
</el-row>
|
||||||
<div>
|
<div>
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" @click="activeStep = 0">上一步</el-button>
|
<el-button style="margin-bottom: 5px;" type="primary" @click="activeStep = 0">上一步</el-button>
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" :loading="createPPTLoading" @click="outlineCreatePPT()">生成PPT</el-button>
|
<el-button style="margin-bottom: 5px;" type="primary" v-loading="createPPTLoading" @click="outlineCreatePPT()">生成PPT</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
<el-card v-if="activeStep === 2">
|
<el-card v-if="activeStep === 2">
|
||||||
|
@ -177,8 +177,6 @@ const outlineCreatePPT = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
checkProgress();
|
checkProgress();
|
||||||
}).finally(()=>{
|
|
||||||
createPPTLoading.value = false
|
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|