Compare commits
No commits in common. "main" and "2.1.35" have entirely different histories.
|
@ -1,5 +1,5 @@
|
||||||
# 页面标题
|
# 页面标题
|
||||||
VITE_APP_TITLE = 文枢课堂
|
VITE_APP_TITLE = AIX智慧课堂
|
||||||
|
|
||||||
# 生产环境配置
|
# 生产环境配置
|
||||||
VITE_APP_ENV = 'production'
|
VITE_APP_ENV = 'production'
|
||||||
|
@ -17,5 +17,3 @@ VITE_BUILD_COMPRESS = gzip
|
||||||
VITE_APP_RES_FILE_PATH = 'https://prev.ysaix.com:7868/src/assets/textbook/booktxt/'
|
VITE_APP_RES_FILE_PATH = 'https://prev.ysaix.com:7868/src/assets/textbook/booktxt/'
|
||||||
|
|
||||||
VITE_APP_BUILD_BASE_PATH = 'https://prev.ysaix.com:7868/'
|
VITE_APP_BUILD_BASE_PATH = 'https://prev.ysaix.com:7868/'
|
||||||
|
|
||||||
VITE_SHOW_DEV_TOOLS = 'false'
|
|
|
@ -18,4 +18,4 @@ VITE_APP_RES_FILE_PATH = 'https://prev.ysaix.com:7868/src/assets/textbook/booktx
|
||||||
|
|
||||||
VITE_APP_BUILD_BASE_PATH = 'https://prev.ysaix.com:7868/'
|
VITE_APP_BUILD_BASE_PATH = 'https://prev.ysaix.com:7868/'
|
||||||
|
|
||||||
VITE_SHOW_DEV_TOOLS = 'true'
|
VITE_SHOW_DEV_TOOLS = 'false'
|
||||||
|
|
|
@ -17,5 +17,3 @@ VITE_BUILD_COMPRESS = gzip
|
||||||
VITE_APP_RES_FILE_PATH = 'https://file.ysaix.com:7868/src/assets/textbook/booktxt/'
|
VITE_APP_RES_FILE_PATH = 'https://file.ysaix.com:7868/src/assets/textbook/booktxt/'
|
||||||
|
|
||||||
VITE_APP_BUILD_BASE_PATH = 'https://file.ysaix.com:7868/'
|
VITE_APP_BUILD_BASE_PATH = 'https://file.ysaix.com:7868/'
|
||||||
|
|
||||||
VITE_SHOW_DEV_TOOLS = 'true'
|
|
||||||
|
|
21
.env.yc2
21
.env.yc2
|
@ -1,21 +0,0 @@
|
||||||
# 页面标题
|
|
||||||
VITE_APP_TITLE = 实训教学
|
|
||||||
|
|
||||||
# 生产环境配置
|
|
||||||
VITE_APP_ENV = 'production'
|
|
||||||
|
|
||||||
# AIx融合数字管理系统/生产环境
|
|
||||||
VITE_APP_BASE_API = 'https://prev.ysaix.com:7868/prod-api'
|
|
||||||
|
|
||||||
VITE_APP_DOMAIN = 'prev.ysaix.com'
|
|
||||||
|
|
||||||
VITE_APP_UPLOAD_API = 'https://prev.ysaix.com:7868/prod-api'
|
|
||||||
|
|
||||||
# 是否在打包时开启压缩,支持 gzip 和 brotli
|
|
||||||
VITE_BUILD_COMPRESS = gzip
|
|
||||||
|
|
||||||
VITE_APP_RES_FILE_PATH = 'https://prev.ysaix.com:7868/src/assets/textbook/booktxt/'
|
|
||||||
|
|
||||||
VITE_APP_BUILD_BASE_PATH = 'https://prev.ysaix.com:7868/'
|
|
||||||
|
|
||||||
VITE_SHOW_DEV_TOOLS = 'false'
|
|
|
@ -1,10 +1,10 @@
|
||||||
appId: com.electron.app
|
appId: com.electron.app
|
||||||
productName: 文枢课堂
|
productName: AIx
|
||||||
directories:
|
directories:
|
||||||
output: dist
|
output: dist
|
||||||
buildResources: build
|
buildResources: build
|
||||||
win:
|
win:
|
||||||
executableName: 文枢课堂
|
executableName: AIx
|
||||||
icon: resources/logo2.ico
|
icon: resources/logo2.ico
|
||||||
files:
|
files:
|
||||||
- '!**/.vscode/*'
|
- '!**/.vscode/*'
|
||||||
|
@ -17,7 +17,7 @@ asarUnpack:
|
||||||
nsis:
|
nsis:
|
||||||
oneClick: false
|
oneClick: false
|
||||||
allowToChangeInstallationDirectory: true
|
allowToChangeInstallationDirectory: true
|
||||||
artifactName: ${name}-yc-${version}-setup.${ext}
|
artifactName: ${name}-${version}-setup.${ext}
|
||||||
shortcutName: ${productName}
|
shortcutName: ${productName}
|
||||||
uninstallDisplayName: ${productName}
|
uninstallDisplayName: ${productName}
|
||||||
createDesktopShortcut: always
|
createDesktopShortcut: always
|
||||||
|
@ -30,7 +30,7 @@ mac:
|
||||||
- NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder.
|
- NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder.
|
||||||
notarize: false
|
notarize: false
|
||||||
dmg:
|
dmg:
|
||||||
artifactName: ${name}-yc-${version}.${ext}
|
artifactName: ${name}-${version}.${ext}
|
||||||
linux:
|
linux:
|
||||||
target:
|
target:
|
||||||
- AppImage
|
- AppImage
|
||||||
|
@ -39,11 +39,11 @@ linux:
|
||||||
maintainer: electronjs.org
|
maintainer: electronjs.org
|
||||||
category: Utility
|
category: Utility
|
||||||
appImage:
|
appImage:
|
||||||
artifactName: ${name}-yc-${version}.${ext}
|
artifactName: ${name}-${version}.${ext}
|
||||||
npmRebuild: false
|
npmRebuild: false
|
||||||
publish:
|
publish:
|
||||||
provider: generic
|
provider: generic
|
||||||
url: https://prev.ysaix.com:7868/src/assets/smarttalkyc/
|
url: https://prev.ysaix.com:7868/src/assets/smarttalk/
|
||||||
electronDownload:
|
electronDownload:
|
||||||
mirror: https://npmmirror.com/mirrors/electron/
|
mirror: https://npmmirror.com/mirrors/electron/
|
||||||
# 额外依赖打包到输出目录
|
# 额外依赖打包到输出目录
|
|
@ -1,54 +0,0 @@
|
||||||
appId: com.electron.app.yc2
|
|
||||||
productName: 实训教学
|
|
||||||
directories:
|
|
||||||
output: dist
|
|
||||||
buildResources: build
|
|
||||||
win:
|
|
||||||
executableName: 实训教学
|
|
||||||
icon: resources/logo2.ico
|
|
||||||
files:
|
|
||||||
- '!**/.vscode/*'
|
|
||||||
- '!src/*'
|
|
||||||
- '!electron.vite.config.{js,ts,mjs,cjs}'
|
|
||||||
- '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}'
|
|
||||||
- '!{.env,.env.*,.npmrc,pnpm-lock.yaml}'
|
|
||||||
asarUnpack:
|
|
||||||
- resources/**
|
|
||||||
nsis:
|
|
||||||
oneClick: false
|
|
||||||
allowToChangeInstallationDirectory: true
|
|
||||||
artifactName: ${name}-yc-${version}-setup.${ext}
|
|
||||||
shortcutName: ${productName}
|
|
||||||
uninstallDisplayName: ${productName}
|
|
||||||
createDesktopShortcut: always
|
|
||||||
mac:
|
|
||||||
entitlementsInherit: build/entitlements.mac.plist
|
|
||||||
extendInfo:
|
|
||||||
- NSCameraUsageDescription: Application requests access to the device's camera.
|
|
||||||
- NSMicrophoneUsageDescription: Application requests access to the device's microphone.
|
|
||||||
- NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder.
|
|
||||||
- NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder.
|
|
||||||
notarize: false
|
|
||||||
dmg:
|
|
||||||
artifactName: ${name}-yc-${version}.${ext}
|
|
||||||
linux:
|
|
||||||
target:
|
|
||||||
- AppImage
|
|
||||||
- snap
|
|
||||||
- deb
|
|
||||||
maintainer: electronjs.org
|
|
||||||
category: Utility
|
|
||||||
appImage:
|
|
||||||
artifactName: ${name}-yc-${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:
|
|
||||||
- '**/*'
|
|
24
package.json
24
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "aix-win",
|
"name": "aix-win",
|
||||||
"version": "2.1.37",
|
"version": "2.1.33",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "上海交大重庆人工智能研究院",
|
"author": "上海交大重庆人工智能研究院",
|
||||||
|
@ -16,12 +16,16 @@
|
||||||
"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": "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:prod": "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": "electron-vite build --mode yc && electron-builder --win --config ./electron-builder-yc.yml",
|
"build:lt": "electron-vite build --mode lt && electron-builder --win --config ./electron-builder-lt.yml",
|
||||||
"build:yc2": "electron-vite build --mode yc2 && electron-builder --win --config ./electron-builder-yc2.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"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@electron-toolkit/preload": "^3.0.1",
|
||||||
|
"@electron-toolkit/utils": "^3.0.0",
|
||||||
|
"@electron/remote": "^2.1.2",
|
||||||
|
"@element-plus/icons-vue": "^2.3.1",
|
||||||
|
"@vitejs/plugin-vue-jsx": "^4.0.0",
|
||||||
"@antv/x6": "^2.18.1",
|
"@antv/x6": "^2.18.1",
|
||||||
"@antv/x6-plugin-clipboard": "^2.1.6",
|
"@antv/x6-plugin-clipboard": "^2.1.6",
|
||||||
"@antv/x6-plugin-dnd": "^2.1.1",
|
"@antv/x6-plugin-dnd": "^2.1.1",
|
||||||
|
@ -30,11 +34,6 @@
|
||||||
"@antv/x6-plugin-selection": "^2.2.2",
|
"@antv/x6-plugin-selection": "^2.2.2",
|
||||||
"@antv/x6-plugin-snapline": "^2.1.7",
|
"@antv/x6-plugin-snapline": "^2.1.7",
|
||||||
"@antv/x6-plugin-transform": "^2.1.8",
|
"@antv/x6-plugin-transform": "^2.1.8",
|
||||||
"@electron-toolkit/preload": "^3.0.1",
|
|
||||||
"@electron-toolkit/utils": "^3.0.0",
|
|
||||||
"@electron/remote": "^2.1.2",
|
|
||||||
"@element-plus/icons-vue": "^2.3.1",
|
|
||||||
"@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",
|
||||||
|
@ -54,21 +53,20 @@
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"jsencrypt": "^3.3.2",
|
"jsencrypt": "^3.3.2",
|
||||||
"jsondiffpatch": "0.6.0",
|
"jsondiffpatch": "0.6.0",
|
||||||
"less": "^4.2.0",
|
|
||||||
"less-loader": "^7.3.0",
|
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"node-addon-api": "^8.1.0",
|
"node-addon-api": "^8.1.0",
|
||||||
"pdfjs-dist": "4.4.168",
|
"pdfjs-dist": "4.4.168",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"pinia-plugin-persistedstate": "^3.2.1",
|
"pinia-plugin-persistedstate": "^3.2.1",
|
||||||
"qs": "^6.13.1",
|
|
||||||
"spark-md5": "^3.0.2",
|
"spark-md5": "^3.0.2",
|
||||||
"vite-plugin-electron": "^0.28.8",
|
"vite-plugin-electron": "^0.28.8",
|
||||||
"vue-qr": "^4.0.9",
|
"vue-qr": "^4.0.9",
|
||||||
"vue-router": "^4.4.0",
|
"vue-router": "^4.4.0",
|
||||||
"whiteboard_lyc": "^0.1.3",
|
|
||||||
"xgplayer": "^3.0.19",
|
"xgplayer": "^3.0.19",
|
||||||
"xlsx": "^0.18.5"
|
"xlsx": "^0.18.5",
|
||||||
|
"less": "^4.2.0",
|
||||||
|
"less-loader": "^7.3.0",
|
||||||
|
"whiteboard_lyc": "^0.1.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@electron-toolkit/eslint-config": "^1.0.2",
|
"@electron-toolkit/eslint-config": "^1.0.2",
|
||||||
|
|
|
@ -284,10 +284,9 @@ export default async function ({ app, shell, BrowserWindow, ipcMain }) {
|
||||||
function downloadFiles(url,fileName) {
|
function downloadFiles(url,fileName) {
|
||||||
console.log(url,fileName)
|
console.log(url,fileName)
|
||||||
return new Promise((resolve, reject)=>{
|
return new Promise((resolve, reject)=>{
|
||||||
const browserWindow = BrowserWindow.getAllWindows()
|
const browserWindow = BrowserWindow.getFocusedWindow()
|
||||||
console.log(browserWindow)
|
|
||||||
const id = manager.download({
|
const id = manager.download({
|
||||||
window: browserWindow[0],
|
window: browserWindow,
|
||||||
url: url,
|
url: url,
|
||||||
saveAsFilename: fileName,
|
saveAsFilename: fileName,
|
||||||
directory: appTempFilePath,
|
directory: appTempFilePath,
|
||||||
|
|
|
@ -46,7 +46,7 @@ if(!gotTheLock){
|
||||||
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'?1160:888,
|
width: 888,
|
||||||
height: 520,
|
height: 520,
|
||||||
show: false,
|
show: false,
|
||||||
frame: false,
|
frame: false,
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -13097,16 +13097,15 @@ const PDFViewerApplication = {
|
||||||
}
|
}
|
||||||
if (isValidSpreadMode(spread)) {
|
if (isValidSpreadMode(spread)) {
|
||||||
//默认双页
|
//默认双页
|
||||||
this.pdfViewer.spreadMode = spread;
|
// this.pdfViewer.spreadMode = spread;
|
||||||
//默认双页
|
this.pdfViewer.spreadMode = 1;
|
||||||
// this.pdfViewer.spreadMode = 1;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.isInitialViewSet = true;
|
this.isInitialViewSet = true;
|
||||||
this.pdfSidebar?.setInitialView(sidebarView);
|
this.pdfSidebar?.setInitialView(sidebarView);
|
||||||
//默认双页
|
//默认双页
|
||||||
setViewerModes(scrollMode, spreadMode);
|
// setViewerModes(scrollMode, spreadMode);
|
||||||
// setViewerModes(scrollMode, 1);
|
setViewerModes(scrollMode, 1);
|
||||||
if (this.initialBookmark) {
|
if (this.initialBookmark) {
|
||||||
setRotation(this.initialRotation);
|
setRotation(this.initialRotation);
|
||||||
delete this.initialRotation;
|
delete this.initialRotation;
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
|
|
||||||
// 查询分析列表
|
|
||||||
export function getEvaluationclueList(params) {
|
|
||||||
return request({
|
|
||||||
url: '/education/evaluationclue/list',
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//修改分析内容
|
|
||||||
export function updateEvaluationclue(data) {
|
|
||||||
return request({
|
|
||||||
url: '/education/evaluationclue',
|
|
||||||
method: 'put',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 新增分析
|
|
||||||
export function addEvaluationclue(data) {
|
|
||||||
return request({
|
|
||||||
url: '/education/evaluationclue',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 51 KiB |
Binary file not shown.
Before Width: | Height: | Size: 1.1 MiB |
Binary file not shown.
Before Width: | Height: | Size: 520 KiB |
|
@ -139,23 +139,16 @@ const handleNodeClick = (data) => {
|
||||||
* data : 当前节点数据
|
* data : 当前节点数据
|
||||||
*/
|
*/
|
||||||
let nodeData = cloneDeep(toRaw(data));
|
let nodeData = cloneDeep(toRaw(data));
|
||||||
|
|
||||||
//增加一个label 之前取的label
|
//增加一个label 之前取的label
|
||||||
nodeData.label = nodeData.itemtitle
|
nodeData.label = nodeData.itemtitle
|
||||||
|
// 父级节点 如果当前是一级节点 父级则为null
|
||||||
let parentNode
|
let parent = {
|
||||||
// 存在children 则为一级节点
|
|
||||||
if(nodeData.children){
|
|
||||||
// 为一级节点
|
|
||||||
parentNode = null
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
parentNode = {
|
|
||||||
id: nodeData.parentid,
|
id: nodeData.parentid,
|
||||||
label: nodeData.parenttitle,
|
label: nodeData.parenttitle,
|
||||||
itemtitle: nodeData.parenttitle
|
itemtitle: nodeData.parenttitle
|
||||||
}
|
}
|
||||||
}
|
const parentNode = nodeData.parentid ? parent : null
|
||||||
|
|
||||||
nodeData.parentNode = parentNode
|
nodeData.parentNode = parentNode
|
||||||
let curData = {
|
let curData = {
|
||||||
textBook: {
|
textBook: {
|
||||||
|
|
|
@ -8,10 +8,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { ElMessageBox } from 'element-plus'
|
import { ElMessageBox } from 'element-plus'
|
||||||
import useUserStore from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
const Remote = require('@electron/remote')
|
|
||||||
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const { ipcRenderer } = window.electron || {}
|
const { ipcRenderer } = window.electron || {}
|
||||||
|
@ -38,7 +37,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(() => {
|
||||||
|
@ -49,16 +47,8 @@ const closeWindow = () => {
|
||||||
})
|
})
|
||||||
}).catch(() => { });
|
}).catch(() => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() =>{
|
|
||||||
isMaxSize.value = Remote.getCurrentWindow().isMaximized()
|
|
||||||
})
|
|
||||||
</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%;
|
||||||
|
|
|
@ -127,10 +127,7 @@ export const removePropertyOf = function(obj){
|
||||||
export function removeTree(list) {
|
export function removeTree(list) {
|
||||||
var this_ = this
|
var this_ = this
|
||||||
for (var i in list) {
|
for (var i in list) {
|
||||||
if (list[i].children == null) {
|
if (list[i].children.length == 0) {
|
||||||
delete list[i].children;
|
|
||||||
}
|
|
||||||
else if (list[i].children.length == 0) {
|
|
||||||
list[i].children = undefined
|
list[i].children = undefined
|
||||||
} else {
|
} else {
|
||||||
this_.removeTree(list[i].children)
|
this_.removeTree(list[i].children)
|
||||||
|
|
|
@ -1,224 +0,0 @@
|
||||||
import request from '@/utils/request'
|
|
||||||
import axios from 'axios';
|
|
||||||
import { ElMessage, ElMessageBox, ElNotification } from "element-plus";
|
|
||||||
import qs from 'qs';
|
|
||||||
import { uploadServer, getJSONFile } from '@/utils/common';
|
|
||||||
import { getEvaluationclueList, updateEvaluationclue, addEvaluationclue } from '@/api/pdf';
|
|
||||||
|
|
||||||
export const pdfCallBack = (pdfInfo) => {
|
|
||||||
if(pdfInfo.toString() !== '{}' || pdfInfo !== null){
|
|
||||||
if(pdfInfo.storageInfo){
|
|
||||||
//圈点勾画操作返回
|
|
||||||
// saveJSON(pdfInfo.storageInfo)
|
|
||||||
saveAnnotationStorage(pdfInfo.storageInfo)
|
|
||||||
return 'draw'
|
|
||||||
}else if(pdfInfo.quoteInfo){
|
|
||||||
//引用文本操作返回
|
|
||||||
quoteWords(pdfInfo.quoteInfo)
|
|
||||||
return 'quote'
|
|
||||||
}else if(pdfInfo.imgInfo){
|
|
||||||
//OCR截图返回
|
|
||||||
ocrCallBack(pdfInfo.imgInfo)
|
|
||||||
return 'ocr'
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//百度OCR识别配置
|
|
||||||
const baidubceConfig = {
|
|
||||||
// Header
|
|
||||||
'Content-Type': "application/x-www-form-urlencoded",
|
|
||||||
// 格式
|
|
||||||
'Accept' : 'application/json',
|
|
||||||
// id(临时测试)
|
|
||||||
'client_id': "U0DrGBE6X92IXgV6cJMNON8F",
|
|
||||||
// 密钥(临时测试)
|
|
||||||
'client_secret': 'oWb0M0YWMmZPMQIhIUkJX99ddr7h61qf',
|
|
||||||
};
|
|
||||||
|
|
||||||
//获取百度token
|
|
||||||
const getBaiduToken = async () => {
|
|
||||||
let config = {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': `${baidubceConfig['Content-Type']}`
|
|
||||||
},
|
|
||||||
url: `/baidubce/oauth/2.0/token?grant_type=client_credentials&client_id=${baidubceConfig['client_id']}&client_secret=${baidubceConfig['client_secret']}`,
|
|
||||||
method: 'POST'
|
|
||||||
}
|
|
||||||
return await axios(config)
|
|
||||||
}
|
|
||||||
//图片识别方法
|
|
||||||
const getBaiduOCR = async (token,params) => {
|
|
||||||
let config = {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': `${baidubceConfig['Content-Type']}`,
|
|
||||||
'Accept': `${baidubceConfig['Accept']}`,
|
|
||||||
},
|
|
||||||
method: 'POST',
|
|
||||||
url: `/baidubce/rest/2.0/ocr/v1/doc_analysis?access_token=${token}`,
|
|
||||||
data: qs.stringify(params),
|
|
||||||
}
|
|
||||||
try{
|
|
||||||
return await axios(config)
|
|
||||||
}catch{
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const ocrCallBack = async (ocrInfo) => {
|
|
||||||
ElMessage({
|
|
||||||
type: 'info',
|
|
||||||
message: '正在识别请稍后',
|
|
||||||
grouping: true,
|
|
||||||
duration: 3000
|
|
||||||
})
|
|
||||||
const baseUrl = ocrInfo.base64;
|
|
||||||
const imgurl = baseUrl.split(",")[1];
|
|
||||||
//获取百度智能云token
|
|
||||||
const tokenData = await getBaiduToken();
|
|
||||||
console.log('----tokenData',tokenData);
|
|
||||||
if(tokenData.status !== 200){
|
|
||||||
ElMessage({
|
|
||||||
type: 'error',
|
|
||||||
message: '文字识别获取用户标识失败',
|
|
||||||
grouping: true,
|
|
||||||
showClose: true,
|
|
||||||
duration: 5000
|
|
||||||
})
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//获取到的token
|
|
||||||
const token = tokenData.data?.access_token;
|
|
||||||
const query = {
|
|
||||||
image: imgurl, //图片地址(base64)
|
|
||||||
line_probability: false, //是否返回每行识别结果的置信度。默认为false
|
|
||||||
disp_line_poly: false, //是否返回每行的四角点坐标。默认为false
|
|
||||||
words_type: 'handprint_mix', //文字类型。 默认:印刷文字识别 = handwring_only:手写文字识别 = handprint_mix: 手写印刷混排识别
|
|
||||||
layout_analysis: false, //是否分析文档版面:包括layout(图、表、标题、段落、目录);attribute(栏、页眉、页脚、页码、脚注)的分析输出
|
|
||||||
recg_long_division: false, //是否检测并识别手写竖式
|
|
||||||
recg_formula: true, //控制是否检测并识别公式,默认为false
|
|
||||||
}
|
|
||||||
const ocrData = await getBaiduOCR(token,query);
|
|
||||||
if(ocrData && ocrData.status === 200){
|
|
||||||
const ocrList = ocrData.data?.words_result;
|
|
||||||
let words = '';
|
|
||||||
ocrList.map(item => {
|
|
||||||
words += item.words
|
|
||||||
})
|
|
||||||
ElMessageBox.alert(words, '识别结果', {
|
|
||||||
confirmButtonText: '引用文本',
|
|
||||||
type: 'info',
|
|
||||||
cancelButtonText: '取消'
|
|
||||||
}).then(() => {
|
|
||||||
window.navigator.clipboard.writeText(words).then(() => {
|
|
||||||
ElMessage({
|
|
||||||
type: 'success',
|
|
||||||
message: '已复制到粘贴板',
|
|
||||||
grouping: true,
|
|
||||||
duration: 3000
|
|
||||||
})
|
|
||||||
}).catch(() => {
|
|
||||||
ElMessage({
|
|
||||||
type: 'error',
|
|
||||||
message: '复制信息出错',
|
|
||||||
grouping: true,
|
|
||||||
duration: 3000
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
ElMessage({
|
|
||||||
type: 'error',
|
|
||||||
message: '识别信息出错',
|
|
||||||
grouping: true,
|
|
||||||
duration: 3000
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const saveAnnotationStorage = (storage) => {
|
|
||||||
localStorage.setItem('PDFJS_Annotation', JSON.stringify(storage));
|
|
||||||
}
|
|
||||||
//保存json文件
|
|
||||||
export const saveJSON = (data) => {
|
|
||||||
let filename = ''
|
|
||||||
if (!data) {
|
|
||||||
console.log('传入的data数据为null');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!filename) {
|
|
||||||
filename = `json${Date.now()}.json`
|
|
||||||
console.log('未传入文件名,采用默认文件名' + filename);
|
|
||||||
}
|
|
||||||
let newdata = null;
|
|
||||||
if (typeof data === 'object') {
|
|
||||||
newdata = JSON.stringify(data, undefined, 4)
|
|
||||||
}
|
|
||||||
// 创建json文件blob流
|
|
||||||
const blob = new Blob([newdata], { type: 'text/json' });
|
|
||||||
// 创建file文件
|
|
||||||
const file = new File([blob],filename, {type: blob.type})
|
|
||||||
// 创建上传文件流
|
|
||||||
const formdata = new FormData();
|
|
||||||
formdata.append('file', file);
|
|
||||||
//其他参数待添加
|
|
||||||
|
|
||||||
//上传
|
|
||||||
uploadServer(formdata).then(res => {
|
|
||||||
console.log('+++++++++++++');
|
|
||||||
console.log(res.data);
|
|
||||||
})
|
|
||||||
//下载json文件
|
|
||||||
// let e = document.createEvent('MouseEvents');
|
|
||||||
// let a = document.createElement('a');
|
|
||||||
// a.download = filename;
|
|
||||||
// a.href = window.URL.createObjectURL(blob);
|
|
||||||
// a.dataset.downloadurl = ['text/json', a.download, a.href].join(':');
|
|
||||||
// e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
|
||||||
// a.dispatchEvent(e);
|
|
||||||
}
|
|
||||||
//引用文本
|
|
||||||
const quoteWords = (quoteInfo) => {
|
|
||||||
const { textStr, StartStr, EndStr } = quoteInfo;
|
|
||||||
if(textStr === StartStr || textStr === EndStr){
|
|
||||||
ElNotification({
|
|
||||||
title: '引用内容',
|
|
||||||
message: textStr,
|
|
||||||
duration: 0,
|
|
||||||
type: 'info',
|
|
||||||
offset: 120
|
|
||||||
})
|
|
||||||
//如果开头和结尾的文字跟内容相同,那么它要么是开头,要么是整段,不需要替换操作
|
|
||||||
console.log('无需替换------',textStr);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let midStr = ''
|
|
||||||
if(StartStr === '' && EndStr === '' && textStr === '') return
|
|
||||||
if(StartStr === '' && EndStr !== '') {
|
|
||||||
midStr = textStr.replace(EndStr,'eeeeee').split('eeeeee')[0]
|
|
||||||
}else if(StartStr !== '' && EndStr === ''){
|
|
||||||
midStr = textStr.replace(StartStr,'ssssss').split('ssssss')[1]
|
|
||||||
}else{
|
|
||||||
midStr = textStr.replace(StartStr, 'ssssss').replace(EndStr,'eeeeee').split('ssssss')[1].split('eeeeee')[0];
|
|
||||||
}
|
|
||||||
ElNotification({
|
|
||||||
title: '引用内容',
|
|
||||||
message: StartStr + midStr + EndStr,
|
|
||||||
duration: 0,
|
|
||||||
type: 'info',
|
|
||||||
offset: 120
|
|
||||||
})
|
|
||||||
console.log('中间文字------',midStr);
|
|
||||||
console.log('转换后整体文字------',StartStr + midStr + EndStr);
|
|
||||||
}
|
|
||||||
//获取分析列表
|
|
||||||
export const getAnalysisList = async (params) => {
|
|
||||||
return await getEvaluationclueList(params)
|
|
||||||
}
|
|
||||||
//新增分析数据
|
|
||||||
export const addAnalysis = async (params) => {
|
|
||||||
return await addEvaluationclue(params);
|
|
||||||
}
|
|
||||||
//修改分析数据
|
|
||||||
export const updateAnalusis = async (params) => {
|
|
||||||
return await updateEvaluationclue(params);
|
|
||||||
}
|
|
|
@ -96,34 +96,5 @@ const getProgress = async (id) => {
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const getBackGroundV2 = async () => {
|
|
||||||
try {
|
|
||||||
const response = await req("/api/aipptV2/themeListV2", "GET");
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("请求失败:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const createPPTV2 = async (data) => {
|
|
||||||
try {
|
|
||||||
const response = await req("/api/aipptV2/createV2", "POST", data);
|
|
||||||
console.log("createOutline response:", response);
|
|
||||||
|
|
||||||
return response.data;
|
export { createOutline, getBackGround, createPPT, getProgress, createByOutline };
|
||||||
} catch (error) {
|
|
||||||
console.error("请求失败:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const getProgressV2 = async (id) => {
|
|
||||||
try {
|
|
||||||
const response = await req(`/api/aipptV2/progressV2?sid=${id}`, "GET");
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("请求失败:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export { createOutline, getBackGround, createPPT, getProgress, getBackGroundV2, createPPTV2, getProgressV2, createByOutline };
|
|
||||||
|
|
|
@ -286,7 +286,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'
|
||||||
|
@ -484,13 +483,12 @@ function Apis(key) {
|
||||||
*/
|
*/
|
||||||
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,
|
eid: props.bookobj.levelSecondId,
|
||||||
sectionName: props.bookobj.coursetitle,
|
sectionName: props.bookobj.coursetitle,
|
||||||
edusubject: userStore.edusubject,
|
edusubject: userStore.edusubject,
|
||||||
edustage: userStore.edustage,
|
edustage: userStore.edustage,
|
||||||
|
@ -585,14 +583,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 = {};
|
||||||
}
|
}
|
||||||
|
@ -1068,27 +1062,9 @@ watch(() => props.propsformobj.uniquekey, (newVal) => {
|
||||||
classWorkForm.uniquekey = props.propsformobj.uniquekey?cloneDeep(props.propsformobj.uniquekey):''; // 作业唯一标识 作业名称
|
classWorkForm.uniquekey = props.propsformobj.uniquekey?cloneDeep(props.propsformobj.uniquekey):''; // 作业唯一标识 作业名称
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
watch(
|
watch(() => props.bookobj.levelSecondId, (newVal, oldVal) => {
|
||||||
[
|
|
||||||
() => props.bookobj.levelSecondId,
|
|
||||||
() => props.bookobj.levelFirstId
|
|
||||||
],
|
|
||||||
([newLevelSecondId, newLevelFirstId], [oldLevelSecondId, oldLevelFirstId]) => {
|
|
||||||
if(props.bookobj.node.edusubject == '英语' && props.bookobj.node.edustage == '高中'){
|
|
||||||
if(newLevelFirstId != oldLevelFirstId){
|
|
||||||
console.log(props.bookobj,'高中英语-课程选择')
|
|
||||||
debounceQueryData();
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
// 习题清空
|
|
||||||
workResource.entpCourseWorkList = [];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
console.log(props.bookobj,'课程选择')
|
console.log(props.bookobj,'课程选择')
|
||||||
debounceQueryData();
|
debounceQueryData();
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -184,7 +184,7 @@ const chooseVedio = (item) => {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
// justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content:hover {
|
.content:hover {
|
||||||
|
@ -192,7 +192,7 @@ const chooseVedio = (item) => {
|
||||||
// box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.15);
|
// box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.15);
|
||||||
}
|
}
|
||||||
.content-list{
|
.content-list{
|
||||||
height: 150px;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center
|
align-items: center
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,264 +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">
|
|
||||||
<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="RegisterModel(1)">注册账号</a>
|
|
||||||
|
|
|
||||||
<a class="hover:text-sky-500" style="margin-left: 10px;" @click="RegisterModel(2)">忘记密码</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>
|
|
||||||
<!--选择学科-->
|
|
||||||
<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'
|
|
||||||
|
|
||||||
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 loginForm = reactive({
|
|
||||||
username: '',
|
|
||||||
password: '',
|
|
||||||
rememberMe: false
|
|
||||||
})
|
|
||||||
|
|
||||||
//表单规则
|
|
||||||
const rules = reactive({
|
|
||||||
username: [{ required: true, trigger: 'blur', message: '请输入您的账号' }],
|
|
||||||
password: [{ 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 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) {
|
|
||||||
ElMessage.success('登录成功')
|
|
||||||
ipcRenderer && ipcRenderer.send('openMainWindow')
|
|
||||||
} else {
|
|
||||||
isSubject.value = true
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
btnLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
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,264 @@
|
||||||
<template>
|
<template>
|
||||||
<ycLogin v-if="buildMode === 'yc'">
|
<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">
|
||||||
|
<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="RegisterModel(1)">注册账号</a>
|
||||||
|
|
|
||||||
|
<a class="hover:text-sky-500" style="margin-left: 10px;" @click="RegisterModel(2)">忘记密码</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>
|
||||||
|
<!--选择学科-->
|
||||||
|
<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'
|
||||||
|
|
||||||
|
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 loginForm = reactive({
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
rememberMe: false
|
||||||
|
})
|
||||||
|
|
||||||
|
//表单规则
|
||||||
|
const rules = reactive({
|
||||||
|
username: [{ required: true, trigger: 'blur', message: '请输入您的账号' }],
|
||||||
|
password: [{ 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 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) {
|
||||||
|
ElMessage.success('登录成功')
|
||||||
|
ipcRenderer && ipcRenderer.send('openMainWindow')
|
||||||
|
} else {
|
||||||
|
isSubject.value = true
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
btnLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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,287 +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">
|
|
||||||
<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="RegisterModel(1)">注册账号</a>
|
|
||||||
|
|
|
||||||
<a class="hover:text-sky-500" style="margin-left: 10px;" @click="RegisterModel(2)">忘记密码</a>
|
|
||||||
</div>
|
|
||||||
<div class="title-bottom">
|
|
||||||
重庆市永川区教育委员会
|
|
||||||
</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>
|
|
||||||
<!--选择学科-->
|
|
||||||
<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 yclogo from '@/assets/images/login/yc-logo.png'
|
|
||||||
import leftBg1 from '@/assets/images/login/ycpeitu.png'
|
|
||||||
import leftBg2 from '@/assets/images/login/ycpeitu2.jpg'
|
|
||||||
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'
|
|
||||||
const buildMode = import.meta.env.MODE
|
|
||||||
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 loginForm = reactive({
|
|
||||||
username: '',
|
|
||||||
password: '',
|
|
||||||
rememberMe: false
|
|
||||||
})
|
|
||||||
|
|
||||||
//表单规则
|
|
||||||
const rules = reactive({
|
|
||||||
username: [{ required: true, trigger: 'blur', message: '请输入您的账号' }],
|
|
||||||
password: [{ required: true, trigger: 'blur', message: '请输入您的密码' }]
|
|
||||||
})
|
|
||||||
|
|
||||||
let curWinUrl = import.meta.env.VITE_APP_BUILD_BASE_PATH
|
|
||||||
ipcRenderer.on('update-app-progress', (e, prop) => {
|
|
||||||
downloadProp.value = prop
|
|
||||||
showDownLoading.value = prop !== 100
|
|
||||||
})
|
|
||||||
// 打开弹窗
|
|
||||||
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) {
|
|
||||||
ElMessage.success('登录成功')
|
|
||||||
ipcRenderer && ipcRenderer.send('openMainWindow')
|
|
||||||
} else {
|
|
||||||
isSubject.value = true
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
btnLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
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: 444px;
|
|
||||||
height: 520px;
|
|
||||||
|
|
||||||
&.desc {
|
|
||||||
background: #ffffff;
|
|
||||||
border-radius: 12px 0px 0px 12px;
|
|
||||||
box-shadow: 0px 16px 73px 8px rgba(203, 203, 203, 0.2);
|
|
||||||
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 15px;
|
|
||||||
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: 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,389 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="ai-container">
|
|
||||||
<el-steps style="max-width:100% " :active="activeStep" align-center>
|
|
||||||
<el-step title="生成大纲" />
|
|
||||||
<el-step title="选择模板" />
|
|
||||||
<el-step title="制作PPT" />
|
|
||||||
</el-steps>
|
|
||||||
<div class="card-box">
|
|
||||||
<el-card class="card2" v-if="activeStep === 0">
|
|
||||||
<div class="paragraphs">
|
|
||||||
{{ outputText }}
|
|
||||||
</div>
|
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" @click="addMessage">从新生成</el-button>
|
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" @click="activeStep = 1">下一步</el-button>
|
|
||||||
</el-card>
|
|
||||||
<el-card v-if="activeStep === 1">
|
|
||||||
<div style="padding-bottom: 10px">ppt模板选择</div>
|
|
||||||
<div class="themes">
|
|
||||||
<div v-for="item in backGroundList" :key="item.templateIndexId" :style="{
|
|
||||||
padding: '5px',
|
|
||||||
paddingRight: '5px',
|
|
||||||
paddingLeft: '5px',
|
|
||||||
margin: '5px',
|
|
||||||
backgroundColor: getBackgroundColor(item.templateIndexId),
|
|
||||||
borderRadius: '10px',
|
|
||||||
borderBlock: '10px solid #e6e6e6'
|
|
||||||
}" @click="chooseBackground(item.templateIndexId)" @mouseenter="changeCursor('pointer')" @mouseleave="changeCursor('default')">
|
|
||||||
{{ item.name }}
|
|
||||||
<img style="width: 150px; height: auto" :src="getBackGroundImg(item.detailImage)" alt="" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-row class="el-row">
|
|
||||||
<!-- <el-col :span="6" class="el-col">
|
|
||||||
<div class="grid-content-1">
|
|
||||||
<div>演讲备注</div>
|
|
||||||
<el-switch v-model="outlineData.is_card_note" />
|
|
||||||
</div>
|
|
||||||
</el-col>-->
|
|
||||||
<!-- <el-col :span="6" class="el-col">
|
|
||||||
<div class="grid-content-2">
|
|
||||||
<div>生成封面</div>
|
|
||||||
<el-switch v-model="outlineData.is_cover_img" />
|
|
||||||
</div>
|
|
||||||
</el-col>-->
|
|
||||||
<el-col :span="6" class="el-col">
|
|
||||||
<div class="grid-content-1">
|
|
||||||
<div>自动配图</div>
|
|
||||||
<el-switch v-model="outlineData.isFigure" />
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="6" class="el-col">
|
|
||||||
<div class="grid-content-2">
|
|
||||||
<div>PPT作者名:</div>
|
|
||||||
<el-input v-model="outlineData.author" style="width: 50%" />
|
|
||||||
</div>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<div>
|
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" @click="activeStep = 0">上一步</el-button>
|
|
||||||
<el-button style="margin-bottom: 5px;" type="primary" v-loading="createPPTLoading" @click="outlineCreatePPT()">生成PPT</el-button>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
<el-card v-if="activeStep === 2">
|
|
||||||
<el-progress :percentage="percentage" type="circle"></el-progress>
|
|
||||||
</el-card>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, onMounted } from "vue";
|
|
||||||
import { ElMessage } from 'element-plus'
|
|
||||||
import {
|
|
||||||
getBackGroundV2,
|
|
||||||
createPPTV2,
|
|
||||||
getProgressV2,
|
|
||||||
} from "@/utils/ppt-request.js";
|
|
||||||
import CryptoJS from "crypto-js"
|
|
||||||
|
|
||||||
import { getSignature } from "@/utils/index.js";
|
|
||||||
import {sessionStore} from "@/utils/store";
|
|
||||||
|
|
||||||
let appId = "01ec9aa3";
|
|
||||||
let secret = "M2QxMDAxMjYyYTEzODMwMGRkZTQ4NmUy";
|
|
||||||
let apikey = "39d05b269fa229f431a56c21794a8ea5"
|
|
||||||
let timestamp = Math.floor(Date.now() / 1000);
|
|
||||||
let signature = getSignature(appId, secret, timestamp);
|
|
||||||
const { ipcRenderer } = window.electron || {}
|
|
||||||
|
|
||||||
|
|
||||||
const outputText = ref(""); // 用于展示的大纲数据
|
|
||||||
const stagingData = ref([]); //储存的对话数据,用于多轮对话
|
|
||||||
const stagOutputText = ref(""); // 暂存大纲用于拆分
|
|
||||||
let extractedParts = ref([]) // 初步拆分
|
|
||||||
|
|
||||||
let firstArray = ref([]); //大纲的大纲等级数字部分
|
|
||||||
let secondArray = ref([]); //大纲的文字部分
|
|
||||||
|
|
||||||
|
|
||||||
const backGroundList = ref([]);
|
|
||||||
let subjectdata = sessionStore.get('subject.curNode')
|
|
||||||
const inputTheme = ref(subjectdata.edustage + subjectdata.edusubject + "《" + subjectdata.itemtitle + "》的授课课件"); // 输入的主题
|
|
||||||
const inputRequire = ref("") // 输入的需求
|
|
||||||
const activeStep = ref(0); // 上方进度条
|
|
||||||
const combined = ref('') // 修改完毕的大纲数据,准备传入ppt生成模型
|
|
||||||
|
|
||||||
const treeData = ref([]);
|
|
||||||
const status = ref("init");
|
|
||||||
|
|
||||||
const percentage = ref(0);
|
|
||||||
|
|
||||||
const createPPTLoading = ref(false);
|
|
||||||
|
|
||||||
const getBackgrounds = () => {
|
|
||||||
treeData.value = [];
|
|
||||||
getBackGroundV2().then((res) => {
|
|
||||||
console.log(res);
|
|
||||||
backGroundList.value = res.records;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const getBackGroundImg = (imgUrlStr) => {
|
|
||||||
return JSON.parse(imgUrlStr).titleCoverImage
|
|
||||||
};
|
|
||||||
|
|
||||||
const outlineData = ref({
|
|
||||||
query: '', // 用户要求(最多8000字)
|
|
||||||
// templateId: 'auto', // ppt生成主题
|
|
||||||
author: 'AIX平台',
|
|
||||||
isFigure: false, // 是否自动配图
|
|
||||||
search: true,
|
|
||||||
language: "cn"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const emit = defineEmits(['addSuccess'])
|
|
||||||
const props = defineProps({
|
|
||||||
dataList: {
|
|
||||||
type: Array,
|
|
||||||
default: () => []
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 将输入数据或返回数据存入记忆中
|
|
||||||
function updateStagingData(role, newData) {
|
|
||||||
stagingData.value.push({ role: role, content: newData });
|
|
||||||
}
|
|
||||||
//大纲直接生成ppt
|
|
||||||
const outlineCreatePPT = () => {
|
|
||||||
const newOutlineData = { ...outlineData.value, };
|
|
||||||
newOutlineData.query = outputText.value;
|
|
||||||
createPPTLoading.value = true;
|
|
||||||
createPPTV2(newOutlineData).then((res) => {
|
|
||||||
console.log(res, "正在生成中");
|
|
||||||
createPPTLoading.value = false;
|
|
||||||
activeStep.value = 2
|
|
||||||
|
|
||||||
const checkProgress = () => {
|
|
||||||
getProgressV2(res.sid).then(response => {
|
|
||||||
percentage.value = Math.round(response?.donePages*100/response?.totalPages);
|
|
||||||
if (response.pptStatus === "done") {
|
|
||||||
emit('addSuccess',{...res,url:response.pptUrl})
|
|
||||||
ElMessage.success("生成成功");
|
|
||||||
} else {
|
|
||||||
const sleepTime = 2000;
|
|
||||||
let remainingTime = sleepTime;
|
|
||||||
const intervalId = setInterval(() => {
|
|
||||||
remainingTime -= 100;
|
|
||||||
if (remainingTime <= 0) {
|
|
||||||
clearInterval(intervalId);
|
|
||||||
checkProgress();
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
checkProgress();
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
//初次对话
|
|
||||||
const addMessage = () => {
|
|
||||||
const themeValue = inputTheme.value;
|
|
||||||
const requireValue = inputRequire.value;
|
|
||||||
firstArray.value = []
|
|
||||||
secondArray.value = []
|
|
||||||
extractedParts.value = []
|
|
||||||
stagOutputText.value = ''
|
|
||||||
const combinedString = `请帮我生成一个ppt大纲,主题为:${themeValue}。具体内容要求为:${requireValue}。注意,用三个等级大纲展示,如1. 1.1 1.1.2 2. 2.1这种类型,且按照这种顺序,不要有完全相同数字等级的大纲,不要有目录`
|
|
||||||
updateStagingData("user", combinedString);
|
|
||||||
connectWebSocket(stagingData.value);
|
|
||||||
// activeStep.value = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
let ttsWS
|
|
||||||
function connectWebSocket(data) {
|
|
||||||
outputText.value = ""; //清楚展示部分内容
|
|
||||||
status.value = "ttsing";
|
|
||||||
return getWebsocketUrl().then((url) => {
|
|
||||||
ttsWS = new WebSocket(url);
|
|
||||||
ttsWS.onopen = () => {
|
|
||||||
webSocketSend(ttsWS, data);
|
|
||||||
};
|
|
||||||
ttsWS.onmessage = (e) => {
|
|
||||||
result1(e.data);
|
|
||||||
};
|
|
||||||
ttsWS.onerror = (e) => {
|
|
||||||
status.value = "error";
|
|
||||||
console.log("WebSocket error:", e);
|
|
||||||
};
|
|
||||||
ttsWS.onclose = () => {
|
|
||||||
status.value = "init";
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const getBackgroundColor = (key) => {
|
|
||||||
return outlineData.value.templateId === key ? '#83e2b6' : '#f5f5f5';
|
|
||||||
};
|
|
||||||
|
|
||||||
function getWebsocketUrl() {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
var apiKey = apikey;
|
|
||||||
var apiSecret = secret;
|
|
||||||
var url = "wss://spark-api.xf-yun.com/v4.0/chat";
|
|
||||||
|
|
||||||
var host = "spark-api.xf-yun.com";
|
|
||||||
var date = new Date().toGMTString();
|
|
||||||
var algorithm = "hmac-sha256";
|
|
||||||
var headers = "host date request-line";
|
|
||||||
var signatureOrigin = `host: ${host}\ndate: ${date}\nGET /v4.0/chat HTTP/1.1`;
|
|
||||||
var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret);
|
|
||||||
var signature = CryptoJS.enc.Base64.stringify(signatureSha);
|
|
||||||
|
|
||||||
var authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`;
|
|
||||||
var authorization = CryptoJS.enc.Base64.stringify(
|
|
||||||
CryptoJS.enc.Utf8.parse(authorizationOrigin)
|
|
||||||
);
|
|
||||||
|
|
||||||
url = `${url}?authorization=${authorization}&date=${date}&host=${host}`;
|
|
||||||
console.log(url);
|
|
||||||
resolve(url);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function webSocketSend(ws, data) {
|
|
||||||
const params = {
|
|
||||||
header: {
|
|
||||||
app_id: appId,
|
|
||||||
},
|
|
||||||
parameter: {
|
|
||||||
chat: {
|
|
||||||
domain: "4.0Ultra",
|
|
||||||
temperature: 0.5,
|
|
||||||
max_tokens: 1024,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
payload: {
|
|
||||||
message: {
|
|
||||||
text: data,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
ws.send(JSON.stringify(params));
|
|
||||||
}
|
|
||||||
|
|
||||||
function result1(resultData) {
|
|
||||||
let jsonData = JSON.parse(resultData);
|
|
||||||
outputText.value += jsonData.payload.choices.text[0].content;
|
|
||||||
const div = document.querySelector('.paragraphs');
|
|
||||||
if (div) {
|
|
||||||
div.scrollTop = div.scrollHeight;
|
|
||||||
}
|
|
||||||
if (jsonData.payload && jsonData.payload.usage) {
|
|
||||||
updateStagingData("assistant", outputText.value) //返回数据存入记忆池
|
|
||||||
}
|
|
||||||
if (jsonData.header.code !== 0) {
|
|
||||||
alert(`提问失败: ${jsonData.header.code}:${jsonData.header.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const chooseBackground = (data) => {
|
|
||||||
outlineData.value.templateId = data
|
|
||||||
}
|
|
||||||
|
|
||||||
const changeCursor = (cursorStyle) => {
|
|
||||||
document.documentElement.style.cursor = cursorStyle;
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
// let pptUrl = "https://bjcdn.openstorage.cn/xinghuo-privatedata/zhiwen/2024-12-06/23754754-b5bb-494a-b96d-7a5dc78820eb/89c1aefc634a4566a1779b2bc8ffa943.pptx";
|
|
||||||
// emit('addSuccess',{url:pptUrl})
|
|
||||||
props.dataList.filter(item => {
|
|
||||||
inputRequire.value += item.answer
|
|
||||||
})
|
|
||||||
getBackgrounds();
|
|
||||||
// addMessage()
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.ai-container {
|
|
||||||
width: 100%;
|
|
||||||
background-color: #f5f7f6;
|
|
||||||
padding: 20px
|
|
||||||
}
|
|
||||||
|
|
||||||
.card-box {
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card1 {
|
|
||||||
padding: 0;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.paragraphs {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
text-align: left;
|
|
||||||
max-height: 60vh;
|
|
||||||
overflow-y: auto;
|
|
||||||
border: 1px solid #409EFF;
|
|
||||||
padding: 10px;
|
|
||||||
margin: 5px
|
|
||||||
}
|
|
||||||
|
|
||||||
.themes {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
height: 250px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.outline {
|
|
||||||
white-space: pre-wrap;
|
|
||||||
text-align: left;
|
|
||||||
|
|
||||||
border: 1px solid #409EFF;
|
|
||||||
padding: 10px;
|
|
||||||
outline-style: none;
|
|
||||||
/* margin: 5px */
|
|
||||||
}
|
|
||||||
|
|
||||||
.outline-row {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.outline-row>.el-col {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column
|
|
||||||
}
|
|
||||||
|
|
||||||
.outline-row>.el-col>div,
|
|
||||||
.outline-row>.el-col>div>.el-input {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-with-dash {
|
|
||||||
margin-left: 100px
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-with-dash::after {
|
|
||||||
content: "";
|
|
||||||
border-bottom: 1px dashed #000;
|
|
||||||
flex-grow: 1;
|
|
||||||
margin-left: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-content-1 {
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: #c2dbf3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.grid-content-2 {
|
|
||||||
border-radius: 4px;
|
|
||||||
background-color: #f5f5f5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-row {
|
|
||||||
padding: 20px
|
|
||||||
}
|
|
||||||
:deep(.el-card__body){
|
|
||||||
padding: 10px 15px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -347,7 +347,7 @@ export default {
|
||||||
Object.assign(items, item)
|
Object.assign(items, item)
|
||||||
asyncLocalFile(items).then(() => {
|
asyncLocalFile(items).then(() => {
|
||||||
ipcRenderer.send('open-path-app', item.fileNewName)
|
ipcRenderer.send('open-path-app', item.fileNewName)
|
||||||
if (this.listenList?.indexOf(item.fileNewName) === -1) {
|
if (this.listenList.indexOf(item.fileNewName) === -1) {
|
||||||
this.listenList.push(item.fileNewName)
|
this.listenList.push(item.fileNewName)
|
||||||
let cookie = localStorage.getItem('Admin-Token')
|
let cookie = localStorage.getItem('Admin-Token')
|
||||||
ipcRenderer.send('listen-file-change', {
|
ipcRenderer.send('listen-file-change', {
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import AiPpt from './ai-pptV2.vue';
|
import AiPpt from './ai-ppt.vue';
|
||||||
const model = defineModel()
|
const model = defineModel()
|
||||||
const emit = defineEmits(['addSuccess'])
|
const emit = defineEmits(['addSuccess'])
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|
|
@ -162,7 +162,7 @@ import KjListItem from '@/views/prepare/container/kj-list-item.vue'
|
||||||
import { getSmarttalkPage, moveSmarttalk, creatAPT } from '@/api/file'
|
import { getSmarttalkPage, moveSmarttalk, creatAPT } from '@/api/file'
|
||||||
import { toTimeText } from '@/utils/date'
|
import { toTimeText } from '@/utils/date'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { parseCataByNode, creatPPT, asyncLocalFile, creatAIPPT } from '@/utils/talkFile'
|
import { parseCataByNode, creatPPT, asyncLocalFile } from '@/utils/talkFile'
|
||||||
import FileOperBatch from '@/views/prepare/container/file-oper-batch.vue'
|
import FileOperBatch from '@/views/prepare/container/file-oper-batch.vue'
|
||||||
import SetHomework from '@/components/set-homework/index.vue'
|
import SetHomework from '@/components/set-homework/index.vue'
|
||||||
import outLink from '@/utils/linkConfig'
|
import outLink from '@/utils/linkConfig'
|
||||||
|
@ -293,12 +293,9 @@ export default {
|
||||||
// },
|
// },
|
||||||
methods: {
|
methods: {
|
||||||
addAiPPT(item) {
|
addAiPPT(item) {
|
||||||
console.log(this.currentNode.itemtitle + '.pptx',item.url, {...this.uploadData,fileShowName: this.currentNode.itemtitle + '.pptx'})
|
this.currentFileList.unshift(item.resData)
|
||||||
creatAIPPT(this.currentNode.itemtitle + '.pptx',item.url, {...this.uploadData,fileShowName: this.currentNode.itemtitle + '.pptx'}).then((res) => {
|
KjListItem.methods.openFileWin(item.resData);
|
||||||
this.currentFileList.unshift(res.resData)
|
|
||||||
KjListItem.methods.openFileWin(res.resData);
|
|
||||||
this.pptDialog = false
|
this.pptDialog = false
|
||||||
})
|
|
||||||
},
|
},
|
||||||
// test() {
|
// test() {
|
||||||
// toolStore.resetDef() // 重置状态
|
// toolStore.resetDef() // 重置状态
|
||||||
|
|
|
@ -84,11 +84,11 @@ import PDF from '@/components/PdfJs/index.vue'
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import useResoureStore from '../../resource/store'
|
import useResoureStore from '../../resource/store'
|
||||||
import { listEvaluationclue } from '@/api/teaching/classwork'
|
import { listEvaluationclue } from '@/api/teaching/classwork'
|
||||||
|
import { uploadServer, getJSONFile } from '@/utils/common'
|
||||||
import { ElNotification } from 'element-plus'
|
import { ElNotification } from 'element-plus'
|
||||||
import ChooseTextbook from "@/components/choose-textbook/index.vue";
|
import ChooseTextbook from "@/components/choose-textbook/index.vue";
|
||||||
import { listEvaluation } from '@/api/classManage/index'
|
import { listEvaluation } from '@/api/classManage/index'
|
||||||
import useUserStore from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
import { pdfCallBack } from '@/utils/pdftools'
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const sourceStore = useResoureStore()
|
const sourceStore = useResoureStore()
|
||||||
// import { getStaticUrl } from '@/utils/tool'
|
// import { getStaticUrl } from '@/utils/tool'
|
||||||
|
@ -171,6 +171,52 @@ const selectHandel = (value) => {
|
||||||
const filterData = searchInp.value !== '' ? showData.value : standList.value
|
const filterData = searchInp.value !== '' ? showData.value : standList.value
|
||||||
showData.value = filterList(filterData);
|
showData.value = filterList(filterData);
|
||||||
}
|
}
|
||||||
|
//保存json文件
|
||||||
|
const saveJSON = (data) => {
|
||||||
|
|
||||||
|
let filename = ''
|
||||||
|
// const data = {
|
||||||
|
// name: 'txt',
|
||||||
|
// class: '五年级2班',
|
||||||
|
// school: '重庆市酉阳二中',
|
||||||
|
// time: '2024-08-09'
|
||||||
|
// }
|
||||||
|
// saveJSON(jsonStr);
|
||||||
|
if (!data) {
|
||||||
|
console.log('传入的data数据为null');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!filename) {
|
||||||
|
filename = `json${Date.now()}.json`
|
||||||
|
console.log('未传入文件名,采用默认文件名' + filename);
|
||||||
|
}
|
||||||
|
let newdata = null;
|
||||||
|
if (typeof data === 'object') {
|
||||||
|
newdata = JSON.stringify(data, undefined, 4)
|
||||||
|
}
|
||||||
|
// 创建json文件blob流
|
||||||
|
const blob = new Blob([newdata], { type: 'text/json' });
|
||||||
|
// 创建file文件
|
||||||
|
// const file = new File([blob],filename, {type: blob.type})
|
||||||
|
// 创建上传文件流
|
||||||
|
// const formdata = new FormData();
|
||||||
|
// formdata.append('file', file);
|
||||||
|
//其他参数待添加
|
||||||
|
|
||||||
|
//上传
|
||||||
|
// uploadServer(formdata).then(res => {
|
||||||
|
// console.log('+++++++++++++');
|
||||||
|
// console.log(res.data);
|
||||||
|
// })
|
||||||
|
|
||||||
|
let e = document.createEvent('MouseEvents');
|
||||||
|
let a = document.createElement('a');
|
||||||
|
a.download = filename;
|
||||||
|
a.href = window.URL.createObjectURL(blob);
|
||||||
|
a.dataset.downloadurl = ['text/json', a.download, a.href].join(':');
|
||||||
|
e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||||
|
a.dispatchEvent(e);
|
||||||
|
}
|
||||||
// 查询
|
// 查询
|
||||||
const getData = (data) => {
|
const getData = (data) => {
|
||||||
const { textBook, node } = data
|
const { textBook, node } = data
|
||||||
|
@ -249,9 +295,53 @@ onMounted(async () => {
|
||||||
window.addEventListener('message',(event) => {
|
window.addEventListener('message',(event) => {
|
||||||
// console.log('------------');
|
// console.log('------------');
|
||||||
const iframeMes = event.data;
|
const iframeMes = event.data;
|
||||||
//监听pdf返回事件,在pdf工具类中统一处理
|
if(iframeMes.storageInfo){
|
||||||
pdfCallBack(iframeMes)
|
// saveJSON(iframeMes.storageInfo);
|
||||||
|
// console.log(JSON.stringify(iframeMes.storageInfo));
|
||||||
|
}
|
||||||
|
if(iframeMes.quoteInfo){
|
||||||
|
console.log(iframeMes.quoteInfo);
|
||||||
|
const { textStr, StartStr, EndStr } = iframeMes.quoteInfo;
|
||||||
|
if(textStr === StartStr || textStr === EndStr){
|
||||||
|
ElNotification({
|
||||||
|
title: '引用内容',
|
||||||
|
message: textStr,
|
||||||
|
duration: 0,
|
||||||
|
type: 'info',
|
||||||
|
offset: 120
|
||||||
})
|
})
|
||||||
|
//如果开头和结尾的文字跟内容相同,那么它要么是开头,要么是整段,不需要替换操作
|
||||||
|
console.log('无需替换------',textStr);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let midStr = ''
|
||||||
|
if(StartStr === '' && EndStr === '' && textStr === '') return
|
||||||
|
if(StartStr === '' && EndStr !== '') {
|
||||||
|
midStr = textStr.replace(EndStr,'eeeeee').split('eeeeee')[0]
|
||||||
|
}else if(StartStr !== '' && EndStr === ''){
|
||||||
|
midStr = textStr.replace(StartStr,'ssssss').split('ssssss')[1]
|
||||||
|
}else{
|
||||||
|
midStr = textStr.replace(StartStr, 'ssssss').replace(EndStr,'eeeeee').split('ssssss')[1].split('eeeeee')[0];
|
||||||
|
}
|
||||||
|
ElNotification({
|
||||||
|
title: '引用内容',
|
||||||
|
message: StartStr + midStr + EndStr,
|
||||||
|
duration: 0,
|
||||||
|
type: 'info',
|
||||||
|
offset: 120
|
||||||
|
})
|
||||||
|
console.log('中间文字------',midStr);
|
||||||
|
console.log('转换后整体文字------',StartStr + midStr + EndStr);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// const isDev = process.env.NODE_ENV == 'development'
|
||||||
|
// if (isDev)
|
||||||
|
// pdfUrl.value = '/'+getStaticUrl('aaa.pdf', 'user', 'selfFile', true)
|
||||||
|
// else
|
||||||
|
// pdfUrl.value = getStaticUrl(route.query.path, 'user', 'selfFile', true)
|
||||||
|
|
||||||
|
// console.log('页面',pdfUrl.value);
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|
|
@ -83,15 +83,17 @@ import { onMounted, ref } from 'vue'
|
||||||
import PDF from '@/components/PdfJs/index.vue'
|
import PDF from '@/components/PdfJs/index.vue'
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import useResoureStore from '../resource/store'
|
import useResoureStore from '../resource/store'
|
||||||
|
import { listEvaluationclue } from '@/api/teaching/classwork'
|
||||||
|
// import { uploadServer, getJSONFile } from '@/utils/common'
|
||||||
import { ElNotification } from 'element-plus'
|
import { ElNotification } from 'element-plus'
|
||||||
import ChooseTextbook from "@/components/choose-textbook/index.vue";
|
import ChooseTextbook from "@/components/choose-textbook/index.vue";
|
||||||
import { listEvaluation } from '@/api/classManage/index'
|
import { listEvaluation } from '@/api/classManage/index'
|
||||||
import useUserStore from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
import { sessionStore } from '@/utils/store'
|
import { sessionStore } from '@/utils/store'
|
||||||
import { useGetSubject } from '@/hooks/useGetSubject'
|
import { useGetSubject } from '@/hooks/useGetSubject'
|
||||||
import { pdfCallBack, getAnalysisList, addAnalysis, updateAnalusis } from '@/utils/pdftools'
|
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const sourceStore = useResoureStore()
|
const sourceStore = useResoureStore()
|
||||||
|
// import { getStaticUrl } from '@/utils/tool'
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const pdfUrl = ref('');
|
const pdfUrl = ref('');
|
||||||
|
@ -109,6 +111,7 @@ const bookInfo = ref(null);
|
||||||
const booksel = ref(0);
|
const booksel = ref(0);
|
||||||
const bookList = ref([])
|
const bookList = ref([])
|
||||||
|
|
||||||
|
|
||||||
const searchOptions = [{
|
const searchOptions = [{
|
||||||
value: '0',
|
value: '0',
|
||||||
label: '按时间',
|
label: '按时间',
|
||||||
|
@ -119,6 +122,17 @@ const searchOptions = [{
|
||||||
const standList = ref([]);
|
const standList = ref([]);
|
||||||
const showData = ref([]);
|
const showData = ref([]);
|
||||||
|
|
||||||
|
//查询课标分析列表
|
||||||
|
const getlistEvaluationclue = (firstid, levelid) => {
|
||||||
|
const newid = firstid ? firstid : levelid;
|
||||||
|
listEvaluationclue({evalid: newid, parentid: 0, cluegroup: 'teachresource', orderby: "timestamp desc", pageSize: 100}).then((res) => {
|
||||||
|
if(res.code === 200){
|
||||||
|
const newData = formaterTime(res.rows)
|
||||||
|
standList.value = newData
|
||||||
|
showData.value = filterList(newData)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
const formaterTime = (data) => {
|
const formaterTime = (data) => {
|
||||||
return data.map(item => {
|
return data.map(item => {
|
||||||
return {
|
return {
|
||||||
|
@ -159,7 +173,75 @@ const selectHandel = (value) => {
|
||||||
const filterData = searchInp.value !== '' ? showData.value : standList.value
|
const filterData = searchInp.value !== '' ? showData.value : standList.value
|
||||||
showData.value = filterList(filterData);
|
showData.value = filterList(filterData);
|
||||||
}
|
}
|
||||||
|
//保存json文件
|
||||||
|
const saveJSON = (data) => {
|
||||||
|
|
||||||
|
let filename = ''
|
||||||
|
// const data = {
|
||||||
|
// name: 'txt',
|
||||||
|
// class: '五年级2班',
|
||||||
|
// school: '重庆市酉阳二中',
|
||||||
|
// time: '2024-08-09'
|
||||||
|
// }
|
||||||
|
// saveJSON(jsonStr);
|
||||||
|
if (!data) {
|
||||||
|
console.log('传入的data数据为null');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!filename) {
|
||||||
|
filename = `json${Date.now()}.json`
|
||||||
|
console.log('未传入文件名,采用默认文件名' + filename);
|
||||||
|
}
|
||||||
|
let newdata = null;
|
||||||
|
if (typeof data === 'object') {
|
||||||
|
newdata = JSON.stringify(data, undefined, 4)
|
||||||
|
}
|
||||||
|
// 创建json文件blob流
|
||||||
|
const blob = new Blob([newdata], { type: 'text/json' });
|
||||||
|
// 创建file文件
|
||||||
|
// const file = new File([blob],filename, {type: blob.type})
|
||||||
|
// 创建上传文件流
|
||||||
|
// const formdata = new FormData();
|
||||||
|
// formdata.append('file', file);
|
||||||
|
//其他参数待添加
|
||||||
|
|
||||||
|
//上传
|
||||||
|
// uploadServer(formdata).then(res => {
|
||||||
|
// console.log('+++++++++++++');
|
||||||
|
// console.log(res.data);
|
||||||
|
// })
|
||||||
|
|
||||||
|
let e = document.createEvent('MouseEvents');
|
||||||
|
let a = document.createElement('a');
|
||||||
|
a.download = filename;
|
||||||
|
a.href = window.URL.createObjectURL(blob);
|
||||||
|
a.dataset.downloadurl = ['text/json', a.download, a.href].join(':');
|
||||||
|
e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||||
|
a.dispatchEvent(e);
|
||||||
|
}
|
||||||
|
// 查询
|
||||||
|
const getData = (data) => {
|
||||||
|
const { textBook, node } = data
|
||||||
|
let textbookId = textBook.curBookId
|
||||||
|
let levelSecondId = node.id
|
||||||
|
let levelFirstId
|
||||||
|
if (node.parentNode) {
|
||||||
|
levelFirstId = node.parentNode.id
|
||||||
|
} else {
|
||||||
|
levelFirstId = node.id
|
||||||
|
levelSecondId = ''
|
||||||
|
}
|
||||||
|
sourceStore.query.levelFirstId = levelFirstId
|
||||||
|
sourceStore.query.levelSecondId = levelSecondId
|
||||||
|
sourceStore.query.textbookId = textbookId
|
||||||
|
sourceStore.nodeData = {
|
||||||
|
textbookId, //版本
|
||||||
|
levelFirstId, //单元
|
||||||
|
levelSecondId //单元课程
|
||||||
|
}
|
||||||
|
sourceStore.handleQuery()
|
||||||
|
getlistEvaluationclue(levelFirstId, levelSecondId)
|
||||||
|
}
|
||||||
// 获取学科
|
// 获取学科
|
||||||
const getAllSubject = async () => {
|
const getAllSubject = async () => {
|
||||||
const { edustage, edusubject } = userStore.user;
|
const { edustage, edusubject } = userStore.user;
|
||||||
|
@ -177,7 +259,6 @@ const getAllSubject = async () => {
|
||||||
bookList.value = dataList
|
bookList.value = dataList
|
||||||
const session = sessionStore.get('subject.curNode')
|
const session = sessionStore.get('subject.curNode')
|
||||||
console.log('session',session);
|
console.log('session',session);
|
||||||
console.log('datalist',dataList[0]);
|
|
||||||
let filePath = import.meta.env.VITE_APP_RES_FILE_PATH;
|
let filePath = import.meta.env.VITE_APP_RES_FILE_PATH;
|
||||||
if(session.rootid){
|
if(session.rootid){
|
||||||
const idx = dataList.findIndex(item => item.id === session.rootid)
|
const idx = dataList.findIndex(item => item.id === session.rootid)
|
||||||
|
@ -188,11 +269,11 @@ const getAllSubject = async () => {
|
||||||
bookInfo.value = {...dataList[0]}
|
bookInfo.value = {...dataList[0]}
|
||||||
filePath += dataList[0].fileurl.replace('.txt','.pdf')
|
filePath += dataList[0].fileurl.replace('.txt','.pdf')
|
||||||
}
|
}
|
||||||
|
await loadPdfAnimation(filePath)
|
||||||
}else{
|
}else{
|
||||||
bookInfo.value = {...dataList[0]}
|
bookInfo.value = {...dataList[0]}
|
||||||
filePath += dataList[0].fileurl.replace('.txt','.pdf')
|
filePath += dataList[0].fileurl.replace('.txt','.pdf')
|
||||||
}
|
}
|
||||||
await loadPdfAnimation(filePath)
|
|
||||||
}
|
}
|
||||||
const bookChange = async (item, idx) => {
|
const bookChange = async (item, idx) => {
|
||||||
booksel.value = idx
|
booksel.value = idx
|
||||||
|
@ -212,14 +293,6 @@ const loadPdfAnimation = (path) => {
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await useGetSubject();
|
await useGetSubject();
|
||||||
await getAllSubject();
|
await getAllSubject();
|
||||||
await getAnalysisList({evalid: bookInfo.value.id, parentid: 0, cluegroup: 'textbookAnalysis', orderby: "timestamp desc", pageSize: 100}).then((res) => {
|
|
||||||
if(res.code === 200){
|
|
||||||
const newData = formaterTime(res.rows)
|
|
||||||
standList.value = newData
|
|
||||||
// showData.value = filterList(newData)
|
|
||||||
showData.value = newData
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if(cardref.value && headref.value){
|
if(cardref.value && headref.value){
|
||||||
const cardH = cardref.value.offsetHeight;
|
const cardH = cardref.value.offsetHeight;
|
||||||
const headh = headref.value.offsetHeight;
|
const headh = headref.value.offsetHeight;
|
||||||
|
@ -236,10 +309,46 @@ onMounted(async () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
window.addEventListener('message',(event) => {
|
window.addEventListener('message',(event) => {
|
||||||
console.log('------------');
|
// console.log('------------');
|
||||||
const iframeMes = event.data;
|
const iframeMes = event.data;
|
||||||
console.log('------------',iframeMes);
|
if(iframeMes.storageInfo){
|
||||||
pdfCallBack(iframeMes)
|
// saveJSON(iframeMes.storageInfo);
|
||||||
|
// console.log(JSON.stringify(iframeMes.storageInfo));
|
||||||
|
}
|
||||||
|
if(iframeMes.quoteInfo){
|
||||||
|
console.log(iframeMes.quoteInfo);
|
||||||
|
const { textStr, StartStr, EndStr } = iframeMes.quoteInfo;
|
||||||
|
if(textStr === StartStr || textStr === EndStr){
|
||||||
|
ElNotification({
|
||||||
|
title: '引用内容',
|
||||||
|
message: textStr,
|
||||||
|
duration: 0,
|
||||||
|
type: 'info',
|
||||||
|
offset: 120
|
||||||
|
})
|
||||||
|
//如果开头和结尾的文字跟内容相同,那么它要么是开头,要么是整段,不需要替换操作
|
||||||
|
console.log('无需替换------',textStr);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let midStr = ''
|
||||||
|
if(StartStr === '' && EndStr === '' && textStr === '') return
|
||||||
|
if(StartStr === '' && EndStr !== '') {
|
||||||
|
midStr = textStr.replace(EndStr,'eeeeee').split('eeeeee')[0]
|
||||||
|
}else if(StartStr !== '' && EndStr === ''){
|
||||||
|
midStr = textStr.replace(StartStr,'ssssss').split('ssssss')[1]
|
||||||
|
}else{
|
||||||
|
midStr = textStr.replace(StartStr, 'ssssss').replace(EndStr,'eeeeee').split('ssssss')[1].split('eeeeee')[0];
|
||||||
|
}
|
||||||
|
ElNotification({
|
||||||
|
title: '引用内容',
|
||||||
|
message: StartStr + midStr + EndStr,
|
||||||
|
duration: 0,
|
||||||
|
type: 'info',
|
||||||
|
offset: 120
|
||||||
|
})
|
||||||
|
console.log('中间文字------',midStr);
|
||||||
|
console.log('转换后整体文字------',StartStr + midStr + EndStr);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// const isDev = process.env.NODE_ENV == 'development'
|
// const isDev = process.env.NODE_ENV == 'development'
|
||||||
|
|
Loading…
Reference in New Issue