Merge branch 'main' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk_WS into baigl
This commit is contained in:
commit
4af7220d1d
|
@ -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.0.102:7865',
|
// target: 'http://192.168.2.237:7865',
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
rewrite: (p) => p.replace(/^\/dev-api/, '')
|
rewrite: (p) => p.replace(/^\/dev-api/, '')
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "aix-win-ws",
|
"name": "aix-win-ws",
|
||||||
"version": "2.5.14",
|
"version": "2.5.15",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "./out/main/index.js",
|
"main": "./out/main/index.js",
|
||||||
"author": "上海交大重庆人工智能研究院",
|
"author": "上海交大重庆人工智能研究院",
|
||||||
|
@ -35,12 +35,14 @@
|
||||||
"@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",
|
||||||
|
|
|
@ -359,6 +359,11 @@ 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()
|
||||||
|
|
|
@ -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;" />
|
<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:;" />
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
|
@ -38,12 +38,12 @@ export class Classcourse {
|
||||||
if (isCourse) {
|
if (isCourse) {
|
||||||
// 连接socket
|
// 连接socket
|
||||||
ChatWs.id = classcourse.timgroupid // 群组id
|
ChatWs.id = classcourse.timgroupid // 群组id
|
||||||
if (!ChatWs.ws) {
|
// if (!ChatWs.ws) {
|
||||||
ChatWs.init().then(_ => {
|
// ChatWs.init().then(_ => {
|
||||||
isPublic && ChatWs.sendMsg('open', {id: classcourse.id})
|
// isPublic && ChatWs.sendMsg('open', {id: classcourse.id})
|
||||||
// isPublic && console.log('socket-开课消息-已发送')
|
// // isPublic && console.log('socket-开课消息-已发送')
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
this.classcourse = classcourse // 课堂信息
|
this.classcourse = classcourse // 课堂信息
|
||||||
this.id = classcourse.id // 课堂id
|
this.id = classcourse.id // 课堂id
|
||||||
// 如果课堂信息有paging,则更新当前页码
|
// 如果课堂信息有paging,则更新当前页码
|
||||||
|
|
|
@ -5,14 +5,21 @@
|
||||||
</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">
|
<div class="flex material-item">
|
||||||
<el-image :src="fileUrl(item)" class="img" />
|
<el-image v-if="item.fileType.indexOf('image')!=-1" :src="fileUrl(item)" class="img" />
|
||||||
<el-text truncated>{{ item.fileShowName }}</el-text>
|
<svg v-if="item.fileType.indexOf('video')!=-1" class="icon file-icon" aria-hidden="true" :style="{ 'font-size': 100 + 'px' }">
|
||||||
|
<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 type="primary" @click="onInsert(item)">插入</el-button>
|
<el-button style="margin-left: 10px;" 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>
|
||||||
|
@ -37,7 +44,7 @@ let params = {
|
||||||
pageSize: 500
|
pageSize: 500
|
||||||
}
|
}
|
||||||
|
|
||||||
const suffixAry = [ 'jpeg','jpg','png','gif','mp3','mp4','avi','mov']
|
const suffixAry = [ 'jpeg','jpg','png','gif','mp3','mp4','avi','mov',"wav"]
|
||||||
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)
|
||||||
|
@ -48,6 +55,7 @@ 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)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -64,16 +72,19 @@ const fileUrl = computed(() => (item) =>{
|
||||||
// 插入
|
// 插入
|
||||||
const onInsert = async (item) =>{
|
const onInsert = async (item) =>{
|
||||||
loading.value = true
|
loading.value = true
|
||||||
const res = await fetch(item.fileFullPath)
|
|
||||||
const bolb = await res.blob()
|
// const res = await fetch(item.fileFullPath)
|
||||||
const file = commUtils.blobToFile(bolb, item.fileShowName)
|
// const bolb = await res.blob()
|
||||||
|
// const file = commUtils.blobToFile(bolb, item.fileShowName)
|
||||||
|
const data=item.fileFullPath
|
||||||
try {
|
try {
|
||||||
const data = await PPTApi.toRousrceUrl(file)
|
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', data })
|
||||||
}
|
}else if(item.fileType.indexOf('audio') != -1){
|
||||||
else{
|
emit('insertMaterial',{ type: 'audio', data })
|
||||||
|
}else{
|
||||||
emit('insertMaterial',{ type: 'img', data })
|
emit('insertMaterial',{ type: 'img', data })
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -125,11 +136,17 @@ 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>
|
||||||
|
|
|
@ -287,6 +287,8 @@ const insertMaterial = async (item: MaterialParams) =>{
|
||||||
const { type, data } = item
|
const { type, data } = item
|
||||||
if(type == 'video'){
|
if(type == 'video'){
|
||||||
createVideoElement(data)
|
createVideoElement(data)
|
||||||
|
}else if(type == 'audio'){
|
||||||
|
createAudioElement(data)
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
createImageElement(data)
|
createImageElement(data)
|
||||||
|
|
|
@ -79,3 +79,19 @@ 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,6 +118,14 @@ export function docList(params) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 删除 doc ai文档
|
||||||
|
export function removeDoc(id) {
|
||||||
|
return request({
|
||||||
|
url: '/education/doc/' + id,
|
||||||
|
method: 'delete',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 保存教学大纲
|
// 保存教学大纲
|
||||||
export function addSyllabus(data) {
|
export function addSyllabus(data) {
|
||||||
return request({
|
return request({
|
||||||
|
|
|
@ -0,0 +1,240 @@
|
||||||
|
<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>
|
|
@ -26,6 +26,7 @@ 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',
|
||||||
|
|
|
@ -2,34 +2,45 @@
|
||||||
<el-dialog v-model="isDialog" :show-close="false" width="900" append-to-body destroy-on-close>
|
<el-dialog v-model="isDialog" :show-close="false" width="900" append-to-body destroy-on-close>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="custom-header flex">
|
<div class="custom-header flex">
|
||||||
<span>选择{{ title }}</span>
|
<span>选择</span>
|
||||||
<i class="iconfont icon-guanbi" @click="isDialog = false"></i>
|
<i class="iconfont icon-guanbi" @click="isDialog = false"></i>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="dialog-content">
|
<div class="dialog-content" v-loading="loading">
|
||||||
|
|
||||||
<div class="content-list">
|
<div class="content-list">
|
||||||
<ul>
|
<el-empty description="暂无数据" v-if="!fileList.length" />
|
||||||
<li v-for="(item, index) in fileList" :class="activeIndex == index ? 'li-active' : ''"
|
<el-radio-group v-model="curFileId">
|
||||||
@click="clickItem(index, item)">
|
<el-row>
|
||||||
<el-image class="img" :src="url" />
|
<el-col :span="12" v-for="item in fileList" :key="item.id">
|
||||||
<el-button type="primary" class="prev-btn" @click.stop="onPrevItem(item)">预览</el-button>
|
<el-radio :value="item.id">
|
||||||
<el-text truncated>{{ item.fileName }}</el-text>
|
<el-text class="w-50" truncated>{{ item.fileName }}</el-text>
|
||||||
</li>
|
<div class="flex items-center">
|
||||||
</ul>
|
<el-button type="primary" link v-if="isPrev(item).value" @click="onPrevItem(item)"
|
||||||
|
>预览</el-button
|
||||||
|
>
|
||||||
|
<el-button type="danger" link @click="removeItem(item)">删除</el-button>
|
||||||
|
</div>
|
||||||
|
</el-radio>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-radio-group>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<el-upload class="upload-demo" :action="uploadFileUrl" :limit="1" :show-file-list="false" :headers="headers"
|
<el-upload
|
||||||
:on-success="onSuccess">
|
class="upload-demo"
|
||||||
|
:action="uploadFileUrl"
|
||||||
|
:limit="1"
|
||||||
|
:show-file-list="false"
|
||||||
|
:headers="headers"
|
||||||
|
:on-success="onSuccess"
|
||||||
|
>
|
||||||
<el-button type="primary">上传</el-button>
|
<el-button type="primary">上传</el-button>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
<div>
|
<div>
|
||||||
<el-button @click="isDialog = false">取消</el-button>
|
<el-button @click="isDialog = false">取消</el-button>
|
||||||
<el-button type="primary" @click="isDialog = false">
|
<el-button type="primary" @click="handleDialog"> 确定 </el-button>
|
||||||
确定
|
|
||||||
</el-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
@ -41,21 +52,18 @@
|
||||||
<i class="iconfont icon-guanbi" @click="prevVisible = false"></i>
|
<i class="iconfont icon-guanbi" @click="prevVisible = false"></i>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div style="height: calc(100vh - 120px);">
|
<div style="height: calc(100vh - 120px); text-align: center;">
|
||||||
<template v-if="getFileSuffix(prevItem.fileUrl) == 'pdf'">
|
<template v-if="getFileSuffix(prevItem.fileUrl) == 'pdf'">
|
||||||
<iframe :src="prevItem.fileUrl"
|
<iframe :src="prevItem.fileUrl" frameborder="0" width="100%" height="100%"></iframe>
|
||||||
frameborder="0" width="100%" height="100%"></iframe>
|
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<el-image :src="prevItem.fileUrl" style="height:100%"/>
|
<el-image :src="prevItem.fileUrl" style="height: 100%" />
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer">
|
<div class="dialog-footer">
|
||||||
<div></div>
|
<div></div>
|
||||||
<el-button type="primary" @click="prevVisible = false">
|
<el-button type="primary" @click="prevVisible = false"> 关闭 </el-button>
|
||||||
关闭
|
|
||||||
</el-button>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
@ -63,20 +71,19 @@
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onMounted, reactive } from 'vue'
|
import { ref, computed, onMounted, reactive } from 'vue'
|
||||||
import { completion, addDoc, docList } from '@/api/mode/index.js'
|
import { completion, addDoc, docList, removeDoc } from '@/api/mode/index.js'
|
||||||
import { getToken } from "@/utils/auth";
|
import { getToken } from '@/utils/auth'
|
||||||
import { sessionStore } from '@/utils/store'
|
import { sessionStore } from '@/utils/store'
|
||||||
import { dataSetJson } from '@/utils/comm.js'
|
import { dataSetJson } from '@/utils/comm.js'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import useUserStore from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
import { getFileSuffix } from '@/utils/ruoyi.js'
|
import { getFileSuffix } from '@/utils/ruoyi.js'
|
||||||
import emitter from '@/utils/mitt';
|
import emitter from '@/utils/mitt'
|
||||||
|
import { cloneDeep } from 'lodash'
|
||||||
|
|
||||||
const userInfo = useUserStore().user
|
const userInfo = useUserStore().user
|
||||||
const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload");
|
const uploadFileUrl = ref(import.meta.env.VITE_APP_BASE_API + '/common/upload')
|
||||||
const headers = ref({ Authorization: "Bearer " + getToken() });
|
const headers = ref({ Authorization: 'Bearer ' + getToken() })
|
||||||
|
|
||||||
const url = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F11044b08-04c1-41a0-a453-1fd20b58a614%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1732953359&t=7ab1d1b3a903db85b1149914407aea35'
|
|
||||||
|
|
||||||
const isDialog = defineModel()
|
const isDialog = defineModel()
|
||||||
const prevVisible = ref(false)
|
const prevVisible = ref(false)
|
||||||
|
@ -88,36 +95,14 @@ const props = defineProps({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const title = computed(() => {
|
|
||||||
if (props.modeType == 1) return '课标';
|
|
||||||
if (props.modeType == 2) return '教材';
|
|
||||||
if (props.modeType == 3) return '考试';
|
|
||||||
})
|
|
||||||
|
|
||||||
const radio = ref(1)
|
const isPrev = (item) => {
|
||||||
const radioList = ref([
|
return computed(() => {
|
||||||
{ label: '浏览研读', value: 1 },
|
return ['pdf', 'png', 'jpg', 'jpeg', 'gif', 'webp'].includes(getFileSuffix(item.fileUrl))
|
||||||
{ label: '跨学科研读', value: 2 },
|
})
|
||||||
{ label: '跨学段研读', value: 3 },
|
|
||||||
{ label: '课标修订研读', value: 4 },
|
|
||||||
{ label: '自由研读', value: 5 },
|
|
||||||
])
|
|
||||||
const list = ref([
|
|
||||||
{
|
|
||||||
name: '高中语文课程标准',
|
|
||||||
url
|
|
||||||
}
|
|
||||||
])
|
|
||||||
const changeRadio = () => {
|
|
||||||
list.value = []
|
|
||||||
for (let i = 0; i < Math.floor(Math.random() * 5) + 1; i++) {
|
|
||||||
list.value.push({
|
|
||||||
name: '高中语文课程标准',
|
|
||||||
url
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const activeIndex = ref(0)
|
|
||||||
|
const curFileId = ref(0)
|
||||||
|
|
||||||
const dataset_id = ref('')
|
const dataset_id = ref('')
|
||||||
|
|
||||||
|
@ -143,43 +128,79 @@ const onSuccess = async (response) => {
|
||||||
const { msg } = await addDoc(docData)
|
const { msg } = await addDoc(docData)
|
||||||
ElMessage.success(msg)
|
ElMessage.success(msg)
|
||||||
getList()
|
getList()
|
||||||
|
|
||||||
}
|
}
|
||||||
const curNode = reactive({})
|
const curNode = reactive({})
|
||||||
|
|
||||||
|
// 获取doc ai 文档列表
|
||||||
const fileList = ref([])
|
const fileList = ref([])
|
||||||
const curFile = reactive({})
|
const curFile = reactive({})
|
||||||
const getList = () => {
|
const getList = () => {
|
||||||
docList({
|
docList({
|
||||||
userId: userInfo.userId,
|
createUser: userInfo.userId,
|
||||||
dataset_id: dataset_id.value
|
datasetId: dataset_id.value
|
||||||
}).then(res => {
|
}).then((res) => {
|
||||||
fileList.value = [...res.rows]
|
fileList.value = [...res.rows]
|
||||||
Object.assign(curFile, fileList.value[0])
|
if(res.rows.length){
|
||||||
|
Object.assign(curFile, fileList.value[0])
|
||||||
|
curFileId.value = fileList.value[0].id
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const clickItem = (index, item) => {
|
|
||||||
activeIndex.value = index
|
// 删除
|
||||||
Object.assign(curFile, item)
|
const loading = ref(false)
|
||||||
emitter.emit('changeCurFile', item)
|
const removeItem = (item) => {
|
||||||
|
ElMessageBox.confirm('确定要删除?', '温馨提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
loading.value = true
|
||||||
|
removeDoc(item.id)
|
||||||
|
.then(() => {
|
||||||
|
ElMessage.success('操作成功')
|
||||||
|
getList()
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
loading.value = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 预览
|
||||||
const prevItem = reactive({})
|
const prevItem = reactive({})
|
||||||
const onPrevItem = (item) => {
|
const onPrevItem = (item) => {
|
||||||
Object.assign(prevItem, item)
|
Object.assign(prevItem, item)
|
||||||
prevVisible.value = true
|
prevVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//确定选择
|
||||||
|
const handleDialog = () => {
|
||||||
|
isDialog.value = false
|
||||||
|
|
||||||
|
const item = fileList.value.find((item) => item.id == curFileId.value)
|
||||||
|
|
||||||
|
Object.assign(curFile, item)
|
||||||
|
emitter.emit('changeCurFile', item)
|
||||||
|
|
||||||
|
// 改变左侧 pdf
|
||||||
|
if (getFileSuffix(curFile.fileUrl) == 'pdf') {
|
||||||
|
let data = cloneDeep(curFile)
|
||||||
|
emitter.emit('changePdfUrl', data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
let data = sessionStore.get('subject.curNode')
|
let data = sessionStore.get('subject.curNode')
|
||||||
Object.assign(curNode, data);
|
Object.assign(curNode, data)
|
||||||
// 暂时写死"考试-" 目前只有考试分析才会弹出来
|
// 暂时写死"考试-" 目前只有考试分析才会弹出来
|
||||||
let jsonKey = `考试-${curNode.edustage}-${curNode.edusubject}`
|
let jsonKey = `考试-${curNode.edustage}-${curNode.edusubject}`
|
||||||
dataset_id.value = dataSetJson[jsonKey]
|
dataset_id.value = dataSetJson[jsonKey]
|
||||||
getList()
|
getList()
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.custom-header {
|
.custom-header {
|
||||||
|
@ -198,45 +219,6 @@ onMounted(() => {
|
||||||
.content-list {
|
.content-list {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
|
|
||||||
ul {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
|
|
||||||
li {
|
|
||||||
width: 130px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
font-size: 13px;
|
|
||||||
padding: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 5px;
|
|
||||||
overflow: hidden;
|
|
||||||
margin-right: 20px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
.img {
|
|
||||||
width: 100%;
|
|
||||||
height: 130px;
|
|
||||||
border: solid #ccc 1px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: #E0EAFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover .prev-btn {
|
|
||||||
transform: translate(-50%, -40px)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.li-active {
|
|
||||||
background: #E0EAFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,13 +228,7 @@ onMounted(() => {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prev-btn {
|
:deep(.el-radio__label) {
|
||||||
position: absolute;
|
display: flex;
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%) translateY(-110px);
|
|
||||||
/* 按钮初始位置在容器外 */
|
|
||||||
transition: transform 0.3s ease-in-out;
|
|
||||||
/* 设置过渡效果 */
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
<div class="container-left-page flex">
|
<div class="container-left-page flex">
|
||||||
<div class="container-left-header flex">
|
<div class="container-left-header flex">
|
||||||
<el-button link @click="onClick">
|
<el-button link @click="onClick">
|
||||||
{{ curNode.edustage }}{{ curNode.edusubject }}{{ type == 1 ? '课标研读' : type == 2 ? '教材分析' : '考试分析' }}<i
|
{{ curNode.edustage }}{{ curNode.edusubject
|
||||||
class="iconfont icon-xiangxia"></i>
|
}}{{ type == 1 ? '课标研读' : type == 2 ? '教材分析' : '考试分析'
|
||||||
|
}}<i v-if="type == 3" class="iconfont icon-xiangxia"></i>
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="container-left-pdf">
|
<div class="container-left-pdf">
|
||||||
|
@ -20,6 +21,7 @@ import { ref, onMounted, nextTick, reactive } from 'vue'
|
||||||
import { sessionStore } from '@/utils/store'
|
import { sessionStore } from '@/utils/store'
|
||||||
import PDF from '@/components/PdfJs/index.vue'
|
import PDF from '@/components/PdfJs/index.vue'
|
||||||
import LeftDialog from './left-dialog.vue'
|
import LeftDialog from './left-dialog.vue'
|
||||||
|
import emitter from '@/utils/mitt'
|
||||||
|
|
||||||
const props = defineProps(['type'])
|
const props = defineProps(['type'])
|
||||||
|
|
||||||
|
@ -29,6 +31,12 @@ const onClick = () => {
|
||||||
showDialog.value = true
|
showDialog.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emitter.on('changePdfUrl', async (data) => {
|
||||||
|
pdfUrl.value = ''
|
||||||
|
await nextTick()
|
||||||
|
pdfUrl.value = data.fileUrl
|
||||||
|
})
|
||||||
|
|
||||||
// 加载PDF
|
// 加载PDF
|
||||||
const pdfUrl = ref('')
|
const pdfUrl = ref('')
|
||||||
const curNode = reactive({})
|
const curNode = reactive({})
|
||||||
|
@ -36,16 +44,15 @@ onMounted(async () => {
|
||||||
await nextTick()
|
await nextTick()
|
||||||
// 当前节点
|
// 当前节点
|
||||||
let nodeData = sessionStore.get('subject.curNode')
|
let nodeData = sessionStore.get('subject.curNode')
|
||||||
Object.assign(curNode, nodeData);
|
Object.assign(curNode, nodeData)
|
||||||
|
|
||||||
let data = sessionStore.get('subject.curBook')
|
let data = sessionStore.get('subject.curBook')
|
||||||
let fileurl = data.fileurl
|
let fileurl = data.fileurl
|
||||||
if(props.type == 1){
|
if (props.type == 1) {
|
||||||
fileurl = `${data.edustage}-${data.edusubject}-课标.txt`
|
fileurl = `${data.edustage}-${data.edusubject}-课标.txt`
|
||||||
}
|
}
|
||||||
if(fileurl == '') return
|
if (fileurl == '') return
|
||||||
pdfUrl.value = import.meta.env.VITE_APP_RES_FILE_PATH + fileurl.replace('.txt', '.pdf')
|
pdfUrl.value = import.meta.env.VITE_APP_RES_FILE_PATH + fileurl.replace('.txt', '.pdf')
|
||||||
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -53,6 +60,7 @@ onMounted(async () => {
|
||||||
.container-left-page {
|
.container-left-page {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
.container-left-header {
|
.container-left-header {
|
||||||
height: 45px;
|
height: 45px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
@ -70,4 +78,4 @@ onMounted(async () => {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<el-select v-model="curMode" placeholder="Select" class="mr-4 w-30">
|
<el-select v-model="curMode" placeholder="Select" class="mr-4 w-30">
|
||||||
<el-option v-for="item in modeOptions" :key="item.value" :label="item.label" :value="item.value" />
|
<el-option v-for="item in modeOptions" :key="item.value" :disabled="item.disabled" :label="item.label" :value="item.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
<el-button type="danger" link :disabled="!(templateList.length)" @click="removeItem(curTemplate, false)">
|
<el-button type="danger" link :disabled="!(templateList.length)" @click="removeItem(curTemplate, false)">
|
||||||
删除
|
删除
|
||||||
|
@ -104,6 +104,12 @@ import { cloneDeep } from 'lodash'
|
||||||
const props = defineProps(['type'])
|
const props = defineProps(['type'])
|
||||||
const { user } = useUserStore()
|
const { user } = useUserStore()
|
||||||
|
|
||||||
|
const params = reactive(
|
||||||
|
{
|
||||||
|
prompt: '',
|
||||||
|
dataset_id: ''
|
||||||
|
}
|
||||||
|
)
|
||||||
const curMode = ref(2)
|
const curMode = ref(2)
|
||||||
const modeOptions = ref([
|
const modeOptions = ref([
|
||||||
{
|
{
|
||||||
|
@ -112,7 +118,8 @@ const modeOptions = ref([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '知识库模型',
|
label: '知识库模型',
|
||||||
value: 2
|
value: 2,
|
||||||
|
disabled: false
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -288,12 +295,7 @@ const onEdit = (index, item) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重新研读
|
// 重新研读
|
||||||
const params = reactive(
|
|
||||||
{
|
|
||||||
prompt: '',
|
|
||||||
dataset_id: ''
|
|
||||||
}
|
|
||||||
)
|
|
||||||
const prompt = ref('')
|
const prompt = ref('')
|
||||||
|
|
||||||
// 重新研读
|
// 重新研读
|
||||||
|
@ -483,7 +485,18 @@ onMounted(() => {
|
||||||
|
|
||||||
getTemplateList()
|
getTemplateList()
|
||||||
let jsonKey = `${modeType.value}-${data.edustage}-${data.edusubject}`
|
let jsonKey = `${modeType.value}-${data.edustage}-${data.edusubject}`
|
||||||
|
|
||||||
|
|
||||||
params.dataset_id = dataSetJson[jsonKey]
|
params.dataset_id = dataSetJson[jsonKey]
|
||||||
|
if(!params.dataset_id){
|
||||||
|
curMode.value = 1
|
||||||
|
modeOptions.value.forEach(item => {
|
||||||
|
if(item.value == 2){
|
||||||
|
item.disabled = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 获取百度千帆会话ID
|
// 获取百度千帆会话ID
|
||||||
conversation_id.value = localStorage.getItem('conversation_id')
|
conversation_id.value = localStorage.getItem('conversation_id')
|
||||||
if (!conversation_id.value) {
|
if (!conversation_id.value) {
|
||||||
|
|
|
@ -10,6 +10,15 @@ 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'
|
||||||
|
@ -17,6 +26,9 @@ 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) // 渲染进程日志-控制台替换
|
||||||
|
@ -39,6 +51,10 @@ 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 })
|
||||||
|
@ -46,6 +62,8 @@ 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) => {
|
||||||
|
|
|
@ -102,6 +102,12 @@ 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 }
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,8 @@
|
||||||
<div style="font-size: 16px;font-weight: bold;color: #000;text-align: left;margin-bottom: 5px">可用分组</div>
|
<div style="font-size: 16px;font-weight: bold;color: #000;text-align: left;margin-bottom: 5px">可用分组</div>
|
||||||
<div class="groupList">
|
<div class="groupList">
|
||||||
<template v-for="(item,index) in groupList" :key="index">
|
<template v-for="(item,index) in groupList" :key="index">
|
||||||
<el-card style="width: 20%;
|
<el-card
|
||||||
margin-right: 10px;
|
class="card_div"
|
||||||
margin-bottom: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;"
|
|
||||||
v-if="item.parentid === 0"
|
v-if="item.parentid === 0"
|
||||||
@mouseenter="cardEnter(item,index)"
|
@mouseenter="cardEnter(item,index)"
|
||||||
@mouseleave="cardLeave(item,index)"
|
@mouseleave="cardLeave(item,index)"
|
||||||
|
@ -391,6 +388,7 @@ watch(()=> props.classId,()=> {
|
||||||
.groupList{
|
.groupList{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
gap:10px;
|
||||||
}
|
}
|
||||||
.card-row {
|
.card-row {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
@ -415,4 +413,10 @@ watch(()=> props.classId,()=> {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
.card_div{
|
||||||
|
width: calc(20% - 10px);
|
||||||
|
margin-bottom: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,14 +1,69 @@
|
||||||
<template>
|
<template>
|
||||||
<el-card style="width: 100%;height: 100%">
|
<el-card style="width: 100%;height: 100%">
|
||||||
<el-descriptions :column="1">
|
<el-descriptions
|
||||||
<el-descriptions-item label="班级名称">{{ classInfo.caption }}</el-descriptions-item>
|
class="margin-top"
|
||||||
<el-descriptions-item label="教师">
|
:column="6"
|
||||||
|
:size="size"
|
||||||
|
border
|
||||||
|
>
|
||||||
|
<el-descriptions-item :span="2" :width="120">
|
||||||
|
<template #label>
|
||||||
|
<div class="cell-item">
|
||||||
|
<el-icon :style="iconStyle">
|
||||||
|
<user />
|
||||||
|
</el-icon>
|
||||||
|
班级名称
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
{{ classInfo.caption }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :span="2" :width="120">
|
||||||
|
<template #label>
|
||||||
|
<div class="cell-item">
|
||||||
|
<el-icon :style="iconStyle">
|
||||||
|
<tickets />
|
||||||
|
</el-icon>
|
||||||
|
学段
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
{{ currentGrade }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :span="2" :width="120">
|
||||||
|
<template #label>
|
||||||
|
<div class="cell-item">
|
||||||
|
<el-icon :style="iconStyle">
|
||||||
|
<location />
|
||||||
|
</el-icon>
|
||||||
|
年级
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
{{ currentGradeName }}
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :span="2" :width="120">
|
||||||
|
<template #label>
|
||||||
|
<div class="cell-item">
|
||||||
|
<el-icon :style="iconStyle">
|
||||||
|
<iphone />
|
||||||
|
</el-icon>
|
||||||
|
学生人数
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
{{ classInfo.classstudentcount || 0 }}人
|
||||||
|
</el-descriptions-item>
|
||||||
|
<el-descriptions-item :span="4" :width="120">
|
||||||
|
<template #label>
|
||||||
|
<div class="cell-item">
|
||||||
|
<el-icon :style="iconStyle">
|
||||||
|
<office-building />
|
||||||
|
</el-icon>
|
||||||
|
教师
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
<template v-if="classInfo.teacher.length > 0">
|
<template v-if="classInfo.teacher.length > 0">
|
||||||
<el-tag style="margin-right: 5px;margin-bottom: 5px;" type="primary" v-for="(item, index) in classInfo.teacher" :key="index">{{item.name}}</el-tag>
|
<el-tag style="margin-right: 5px;margin-bottom: 5px;" type="primary" v-for="(item, index) in classInfo.teacher" :key="index">{{item.name}}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>{{ classInfo.teachername }}</template>
|
<template v-else>{{ classInfo.teachername }}</template>
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item label="学生人数">{{ classInfo.classstudentcount || 0 }}人</el-descriptions-item>
|
|
||||||
</el-descriptions>
|
</el-descriptions>
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
@ -17,7 +72,7 @@
|
||||||
import {ElMessage, ElMessageBox} from "element-plus";
|
import {ElMessage, ElMessageBox} from "element-plus";
|
||||||
import { getClassmain,listClassuser,leaveClass} from '@/api/classManage/index'
|
import { getClassmain,listClassuser,leaveClass} from '@/api/classManage/index'
|
||||||
import useUserStore from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
import {reactive,onMounted,nextTick,watch} from 'vue'
|
import {reactive,onMounted,nextTick,watch,ref} from 'vue'
|
||||||
import delClassDemo from '@/store/modules/delClass'
|
import delClassDemo from '@/store/modules/delClass'
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
classId: {
|
classId: {
|
||||||
|
@ -31,6 +86,36 @@
|
||||||
})
|
})
|
||||||
const isDelClass = delClassDemo()
|
const isDelClass = delClassDemo()
|
||||||
const userStore = useUserStore().user
|
const userStore = useUserStore().user
|
||||||
|
// 当前年级
|
||||||
|
const currentGradeName = ref('')
|
||||||
|
// 当前学段
|
||||||
|
const currentGrade = ref('')
|
||||||
|
// 获取年级
|
||||||
|
const gradeDataList = reactive([
|
||||||
|
[
|
||||||
|
{ label: '一年级', agekey: 1, checked: false, current: 1 },
|
||||||
|
{ label: '二年级', agekey: 2, checked: false, current: 1 },
|
||||||
|
{ label: '三年级', agekey: 3, checked: false, current: 1 },
|
||||||
|
{ label: '四年级', agekey: 4, checked: false, current: 1 },
|
||||||
|
{ label: '五年级', agekey: 5, checked: false, current: 1 },
|
||||||
|
{ label: '六年级', agekey: 6, checked: false, current: 1 },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ label: '初一', agekey: 7, checked: false, current: 2 },
|
||||||
|
{ label: '初二', agekey: 8, checked: false, current: 2 },
|
||||||
|
{ label: '初三', agekey: 9, checked: false, current: 2 },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ label: '高一', agekey: 10, checked: false, current: 3 },
|
||||||
|
{ label: '高二', agekey: 11, checked: false, current: 3 },
|
||||||
|
{ label: '高三', agekey: 12, checked: false, current: 3 },
|
||||||
|
],
|
||||||
|
])
|
||||||
|
const gradeData = reactive([
|
||||||
|
{current:1, label:'小学',},
|
||||||
|
{current:2, label:'初中',},
|
||||||
|
{current:3, label:'高中',},
|
||||||
|
])
|
||||||
//删除教室
|
//删除教室
|
||||||
const deleteClassRoom = () => {
|
const deleteClassRoom = () => {
|
||||||
ElMessageBox.alert('确认删除该班级?', {
|
ElMessageBox.alert('确认删除该班级?', {
|
||||||
|
@ -53,6 +138,14 @@
|
||||||
if(props.classId){
|
if(props.classId){
|
||||||
getClassmain(props.classId).then(response => {
|
getClassmain(props.classId).then(response => {
|
||||||
Object.assign(classInfo,response.data)
|
Object.assign(classInfo,response.data)
|
||||||
|
//先把二级数组转化为一级数组,用于筛选
|
||||||
|
const flatGradeDataList = gradeDataList.flat();
|
||||||
|
//学段和年级的回显处理
|
||||||
|
const currentIndex = flatGradeDataList.findIndex(item => item.agekey === Number(response.data.agekey));
|
||||||
|
currentGradeName.value = flatGradeDataList[currentIndex].label
|
||||||
|
const current = flatGradeDataList[currentIndex].current
|
||||||
|
currentGrade.value = gradeData.find(item => item.current === current).label
|
||||||
|
console.log(classInfo,'classInfo');
|
||||||
listClassuser({classid:props.classId,pageSize:100}).then(res => {
|
listClassuser({classid:props.classId,pageSize:100}).then(res => {
|
||||||
classInfo.teacher = res.rows.filter(item => item.inrole === 'teacher')
|
classInfo.teacher = res.rows.filter(item => item.inrole === 'teacher')
|
||||||
classInfo.student = res.rows.filter(item => item.inrole === 'student')
|
classInfo.student = res.rows.filter(item => item.inrole === 'student')
|
||||||
|
@ -71,5 +164,14 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.el-descriptions {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.cell-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.margin-top {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -84,8 +84,7 @@
|
||||||
<div v-if="(currentRow.worktype == '科学实验' || classWorkForm.worktype == '科学实验') && currentRow.id > 0"
|
<div v-if="(currentRow.worktype == '科学实验' || classWorkForm.worktype == '科学实验') && currentRow.id > 0"
|
||||||
class="page-center">
|
class="page-center">
|
||||||
<div class="experiment-homework">
|
<div class="experiment-homework">
|
||||||
<ExperimentQuestion :expObj="classWorkForm.fileHomeworkList && classWorkForm.fileHomeworkList[0]"
|
<ExperimentQuestion :expObj="classWorkForm.fileHomeworkList&&classWorkForm.fileHomeworkList[0]" @clickExpObj="getExpObj" />
|
||||||
@clickExpObj="getExpObj" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1029,4 +1028,8 @@ const handlePrint = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
::v-deep img {
|
||||||
|
display: inline-block !important;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -153,7 +153,7 @@ const tools = reactive([{
|
||||||
img: 'airobot'
|
img: 'airobot'
|
||||||
},{
|
},{
|
||||||
name: '语音生成',
|
name: '语音生成',
|
||||||
path: '',
|
path: '/model/aiVoice',
|
||||||
img: 'aiyuyin'
|
img: 'aiyuyin'
|
||||||
},{
|
},{
|
||||||
name: '文生图片',
|
name: '文生图片',
|
||||||
|
@ -211,7 +211,20 @@ 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 {
|
}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 {
|
||||||
router.push(item.path)
|
router.push(item.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,8 @@
|
||||||
const percentage = ref(0);
|
const percentage = ref(0);
|
||||||
const outlineCreatePPT = () => {
|
const outlineCreatePPT = () => {
|
||||||
const newOutlineData = { ...outlineData.value, };
|
const newOutlineData = { ...outlineData.value, };
|
||||||
newOutlineData.outline = props.dataList.outline;
|
let outline = JSON.parse(props.dataList.outline).json
|
||||||
|
newOutlineData.outline = JSON.stringify(outline);
|
||||||
newOutlineData.query = "通过传入大纲帮我生成相应的PPT课件"
|
newOutlineData.query = "通过传入大纲帮我生成相应的PPT课件"
|
||||||
createPPTLoading.value = true;
|
createPPTLoading.value = true;
|
||||||
createPptByOutline(newOutlineData).then((res) => {
|
createPptByOutline(newOutlineData).then((res) => {
|
||||||
|
|
|
@ -22,13 +22,11 @@
|
||||||
|
|
||||||
<!-- 裁剪按钮-->
|
<!-- 裁剪按钮-->
|
||||||
<div class="btn">
|
<div class="btn">
|
||||||
<el-button style="margin-right: 20px">选择</el-button>
|
<label for="submit">
|
||||||
<input
|
<div class="lBut"><span>选择</span></div>
|
||||||
class="upload"
|
</label>
|
||||||
type="file"
|
<input class="upload" id="submit" accept=".png, .jpg, .jpeg" type="file" style="display: none;" @change="uploadImg" />
|
||||||
accept=".png, .jpg, .jpeg"
|
<!-- <el-button style="margin-right: 20px;cursor:pointer">选择</el-button> -->
|
||||||
@change="uploadImg"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<el-button @click="cancle">取消</el-button>
|
<el-button @click="cancle">取消</el-button>
|
||||||
<el-button @click="sureSava">提交</el-button>
|
<el-button @click="sureSava">提交</el-button>
|
||||||
|
@ -216,6 +214,7 @@ export default {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
|
cursor: pointer;
|
||||||
> .upload {
|
> .upload {
|
||||||
display: block;
|
display: block;
|
||||||
width: 60px;
|
width: 60px;
|
||||||
|
@ -224,6 +223,7 @@ export default {
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -265,4 +265,22 @@ export default {
|
||||||
background-color: rgba(43, 43, 43, 0.7215686275);
|
background-color: rgba(43, 43, 43, 0.7215686275);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.lBut{
|
||||||
|
width: 87px;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 1.15;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
transition: all 0.5s;
|
||||||
|
white-space: nowrap;
|
||||||
|
background-color: #409eff;
|
||||||
|
color: white;
|
||||||
|
border: 1px solid #409eff;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -16,51 +16,30 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="center-con" v-loading="loading">
|
<div class="center-con" v-loading="loading">
|
||||||
<template v-if="answer.title">
|
<!-- <v-md-editor v-if="markeDownAnswer" :model-value="markeDownAnswer" mode="preview"></v-md-editor> -->
|
||||||
<div class="flex justify-between">
|
<v-md-preview v-if="markeDownAnswer" :text="markeDownAnswer"></v-md-preview>
|
||||||
<span style="font-size: 18px;color: #409eff;">封面页</span>
|
|
||||||
<el-button type="primary" link @click="onEdit(item, -1)">编辑</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="con-item mb-5">
|
|
||||||
<div class="item-name">标题:{{ answer.title }}</div>
|
|
||||||
<div class="item-name">副标题:{{ answer.subTitle }}</div>
|
|
||||||
</div>
|
|
||||||
<div style="font-size: 18px;color: #409eff;">目录页</div>
|
|
||||||
<div class="con-item" v-for="(item, index) in answer.chapters">
|
|
||||||
<div class="item-name">
|
|
||||||
<span>{{ index + 1 }}:{{ item.chapterTitle }}</span>
|
|
||||||
<el-button type="primary" link @click="onEdit(item, index)">编辑</el-button>
|
|
||||||
</div>
|
|
||||||
<div class="item-text">
|
|
||||||
<p v-for="(el, i) in item.chapterContents">{{ index + 1 }} - {{ i + 1 }} : {{ el.chapterTitle }}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<el-empty v-else description="请选择符合您需要的教学模式,生成教学大纲" />
|
<el-empty v-else description="请选择符合您需要的教学模式,生成教学大纲" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<EditDialog v-model="isEdit" :item="editItem" :index="editIndex" />
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, onMounted, onUnmounted } from 'vue'
|
import { ref, reactive, onMounted, onUnmounted } from 'vue'
|
||||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||||
import { sessionStore } from '@/utils/store'
|
import { sessionStore } from '@/utils/store'
|
||||||
import EditDialog from './edit-dialog.vue'
|
|
||||||
import emitter from '@/utils/mitt'
|
import emitter from '@/utils/mitt'
|
||||||
import * as commUtils from '@/utils/comm.js'
|
import * as commUtils from '@/utils/comm.js'
|
||||||
import { createChart, sendChart } from '@/api/ai/index'
|
import { createChart, sendChart } from '@/api/ai/index'
|
||||||
import { completion, addSyllabus, removeSyllabus, editSyllabus } from '@/api/mode/index.js'
|
import { completion, addSyllabus, removeSyllabus, modelList } from '@/api/mode/index.js'
|
||||||
import { createOutlineV2 } from '@/utils/ppt-request.js'
|
import { createOutlineV2 } from '@/utils/ppt-request.js'
|
||||||
import useUserStore from '@/store/modules/user'
|
import useUserStore from '@/store/modules/user'
|
||||||
import { cloneDeep } from 'lodash'
|
import { cloneDeep } from 'lodash'
|
||||||
|
|
||||||
const curMode = ref(2)
|
const curMode = ref(2)
|
||||||
const isEdit = ref(false)
|
|
||||||
|
|
||||||
const { user } = useUserStore()
|
const { user } = useUserStore()
|
||||||
const aiShow = ref(false)
|
|
||||||
|
|
||||||
const modeOptions = ref([
|
const modeOptions = ref([
|
||||||
{
|
{
|
||||||
|
@ -69,7 +48,8 @@ const modeOptions = ref([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '知识库模型',
|
label: '知识库模型',
|
||||||
value: 2
|
value: 2,
|
||||||
|
disabled: false
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -81,12 +61,10 @@ emitter.on('selected', (data) => {
|
||||||
// 回显大纲
|
// 回显大纲
|
||||||
const curItem = reactive({})
|
const curItem = reactive({})
|
||||||
emitter.on('onShow', (data) => {
|
emitter.on('onShow', (data) => {
|
||||||
aiShow.value = false
|
let outline = cloneDeep(JSON.parse(data.outline))
|
||||||
Object.assign(answer, JSON.parse(data.outline))
|
markeDownAnswer.value = outline.markdown
|
||||||
|
emitter.emit('onResult', cloneDeep(data))
|
||||||
Object.assign(curItem, data)
|
Object.assign(curItem, data)
|
||||||
curItem.outline = JSON.parse(curItem.outline)
|
|
||||||
emitter.emit('onResult',curItem)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
@ -100,7 +78,8 @@ const params = reactive(
|
||||||
|
|
||||||
// 研读
|
// 研读
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const answer = reactive({})
|
// const answer = reactive({})
|
||||||
|
const markeDownAnswer = ref('')
|
||||||
|
|
||||||
const createAi = async () => {
|
const createAi = async () => {
|
||||||
if (selectedData.value.length == 0) {
|
if (selectedData.value.length == 0) {
|
||||||
|
@ -109,12 +88,13 @@ const createAi = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
let str = selectedData.value.map( item => item.name).join('、')
|
let str = selectedData.value.map( item => item.name).join('、')
|
||||||
let bookV = curNode.roottitle.split('-')[1] + '版'
|
// let bookV = curNode.roottitle.split('-')[1] + '版'
|
||||||
loading.value = true
|
loading.value = true
|
||||||
aiShow.value = true
|
|
||||||
try {
|
|
||||||
|
|
||||||
params.prompt = `针对${curNode.edustage}${curNode.edusubject}${bookV}${curNode.itemtitle}这一课,根据以下教学环节:${str},进行课件教学PPT内容设计`
|
try {
|
||||||
|
params.prompt = prompt.value.replace(/{模板名称}/g, str)
|
||||||
|
|
||||||
|
//params.prompt = `针对${curNode.edustage}${curNode.edusubject}${bookV}${curNode.itemtitle}这一课,根据以下教学环节:${str},进行课件教学PPT内容设计,按照幻灯片1、幻灯片2、...的格式`
|
||||||
// params.template = item.prompt
|
// params.template = item.prompt
|
||||||
|
|
||||||
// 教学大模型
|
// 教学大模型
|
||||||
|
@ -133,65 +113,32 @@ const createAi = async () => {
|
||||||
|
|
||||||
data = res.data
|
data = res.data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const res = await createOutlineV2({ query: data.answer })
|
const res = await createOutlineV2({ query: data.answer })
|
||||||
|
|
||||||
Object.assign(answer, res.outline)
|
markeDownAnswer.value = data.answer
|
||||||
curItem.outline = res.outline
|
let outline = JSON.stringify({
|
||||||
|
json: res.outline,
|
||||||
|
markdown: data.answer
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
Object.assign(curItem, {...curItem, outline})
|
||||||
|
|
||||||
emitter.emit('onResult', curItem)
|
emitter.emit('onResult', curItem)
|
||||||
onSaveTemp(JSON.stringify(res.outline))
|
onSaveTemp(outline)
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 编辑大纲
|
|
||||||
const editItem = reactive({})
|
|
||||||
const editIndex = ref(0)
|
|
||||||
const onEdit = (item, index)=>{
|
|
||||||
|
|
||||||
let obj = null
|
|
||||||
if(index == -1){
|
|
||||||
obj = {
|
|
||||||
title: answer.title,
|
|
||||||
subTitle: answer.subTitle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
obj = cloneDeep(item)
|
|
||||||
}
|
|
||||||
editIndex.value = index
|
|
||||||
isEdit.value = true
|
|
||||||
Object.assign(editItem, obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
emitter.on('editItem', (item) =>{
|
|
||||||
if(editIndex.value == -1){
|
|
||||||
answer.title = item.title
|
|
||||||
answer.subTitle = item.subTitle
|
|
||||||
}else{
|
|
||||||
answer.chapters[editIndex.value] = item
|
|
||||||
}
|
|
||||||
let data = cloneDeep(curItem)
|
|
||||||
|
|
||||||
data.outline = JSON.stringify(cloneDeep(answer))
|
|
||||||
loading.value = true
|
|
||||||
|
|
||||||
editSyllabus(data).then( res =>{
|
|
||||||
curItem.outline = answer
|
|
||||||
emitter.emit('onResult', curItem)
|
|
||||||
ElMessage.success('操作成功')
|
|
||||||
}).finally( ()=>{
|
|
||||||
loading.value = false
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// 保存模板
|
// 保存模板
|
||||||
const onSaveTemp = async (answer) => {
|
const onSaveTemp = async (outline) => {
|
||||||
if (answer == '') return
|
|
||||||
let modelIds = selectedData.value.map(item => item.id).join(',')
|
let modelIds = selectedData.value.map(item => item.id).join(',')
|
||||||
const data = {
|
const data = {
|
||||||
eduId: curNode.id,
|
eduId: curNode.id,
|
||||||
outline: answer,
|
outline,
|
||||||
outlineType: curMode.value == 1 ? 0 : 1,
|
outlineType: curMode.value == 1 ? 0 : 1,
|
||||||
modelIds,
|
modelIds,
|
||||||
sourceType: 1,
|
sourceType: 1,
|
||||||
|
@ -199,10 +146,12 @@ const onSaveTemp = async (answer) => {
|
||||||
createUserName: user.nickName
|
createUserName: user.nickName
|
||||||
}
|
}
|
||||||
await addSyllabus(data)
|
await addSyllabus(data)
|
||||||
|
emitter.emit('getLastInfo')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除大纲
|
// 删除大纲
|
||||||
const delAnswer = () => {
|
const delAnswer = () => {
|
||||||
|
if(!curItem.id) return
|
||||||
ElMessageBox.confirm(
|
ElMessageBox.confirm(
|
||||||
'确定要删除大纲吗?',
|
'确定要删除大纲吗?',
|
||||||
'温馨提示',
|
'温馨提示',
|
||||||
|
@ -215,7 +164,8 @@ const delAnswer = () => {
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
await removeSyllabus(curItem.id)
|
await removeSyllabus(curItem.id)
|
||||||
ElMessage.success('操作成功')
|
ElMessage.success('操作成功')
|
||||||
answer.value = ''
|
markeDownAnswer.value = ''
|
||||||
|
|
||||||
emitter.emit('resetSelect')
|
emitter.emit('resetSelect')
|
||||||
})
|
})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
|
@ -232,13 +182,24 @@ const getChartId = () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onUnmounted(() => {
|
// 查询prompt 替换
|
||||||
emitter.off('selected')
|
const prompt = ref('')
|
||||||
emitter.off('onShow')
|
const getPrompt = async () => {
|
||||||
emitter.off('editItem')
|
const { rows } = await modelList({ model: 5 })
|
||||||
|
|
||||||
|
let str = rows.find(item => item.name.indexOf('框架设计') != -1).prompt
|
||||||
|
|
||||||
|
str = str.replace('{学段}', curNode.edustage)
|
||||||
|
str = str.replace('{学科}', curNode.edusubject)
|
||||||
|
let bookV = curNode.roottitle + '版'
|
||||||
|
str = str.replace('{教材版本}', bookV)
|
||||||
|
str = str.replace('{课程名称}', `《${curNode.itemtitle}》`)
|
||||||
|
|
||||||
|
prompt.value = str
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
const curNode = reactive({})
|
const curNode = reactive({})
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
@ -247,6 +208,14 @@ onMounted(() => {
|
||||||
// 框架设计 用课标的dataset_id
|
// 框架设计 用课标的dataset_id
|
||||||
let jsonKey = `课标-${data.edustage}-${data.edusubject}`
|
let jsonKey = `课标-${data.edustage}-${data.edusubject}`
|
||||||
params.dataset_id = commUtils.dataSetJson[jsonKey]
|
params.dataset_id = commUtils.dataSetJson[jsonKey]
|
||||||
|
if(!params.dataset_id){
|
||||||
|
curMode.value = 1
|
||||||
|
modeOptions.value.forEach(item => {
|
||||||
|
if(item.value == 2){
|
||||||
|
item.disabled = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 获取百度千帆会话ID
|
// 获取百度千帆会话ID
|
||||||
conversation_id.value = localStorage.getItem('conversation_id')
|
conversation_id.value = localStorage.getItem('conversation_id')
|
||||||
|
@ -254,6 +223,16 @@ onMounted(() => {
|
||||||
getChartId();
|
getChartId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPrompt()
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
emitter.off('selected')
|
||||||
|
emitter.off('onShow')
|
||||||
|
emitter.off('editItem')
|
||||||
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,10 @@ const resetSelect = () => {
|
||||||
|
|
||||||
emitter.on('resetSelect', () => {
|
emitter.on('resetSelect', () => {
|
||||||
resetSelect()
|
resetSelect()
|
||||||
|
getSyllabus()
|
||||||
|
})
|
||||||
|
emitter.on('getLastInfo',() =>{
|
||||||
|
getSyllabus()
|
||||||
})
|
})
|
||||||
|
|
||||||
// 点击教学模式
|
// 点击教学模式
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="container-right flex">
|
<div class="container-right flex">
|
||||||
<div class="right-header flex">
|
<div class="right-header flex">
|
||||||
<span>课件预览</span>
|
<span>预览</span>
|
||||||
<div>
|
<div>
|
||||||
<el-button type="danger" @click="onCreate">一键生成</el-button>
|
<el-button :disabled="!result?.outline" type="danger" @click="onCreate">一键生成</el-button>
|
||||||
<el-button :disabled="!result?.parentId" @click="openAiPPT">编辑课件</el-button>
|
<el-button :disabled="!result?.parentId" @click="openAiPPT">编辑</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right-con">
|
<div class="right-con">
|
||||||
|
@ -64,6 +64,7 @@ const pgDialog = reactive({ // 弹窗-进度条
|
||||||
const pptSlides = ref([])
|
const pptSlides = ref([])
|
||||||
|
|
||||||
emitter.on('onResult', (data)=>{
|
emitter.on('onResult', (data)=>{
|
||||||
|
console.log(data)
|
||||||
result.value = data
|
result.value = data
|
||||||
if (!!result.value.parentId) {
|
if (!!result.value.parentId) {
|
||||||
listEntpcoursefileNew({parentid: result.value.parentId}).then(res=>{
|
listEntpcoursefileNew({parentid: result.value.parentId}).then(res=>{
|
||||||
|
@ -152,8 +153,12 @@ const openAiPPT = async () =>{
|
||||||
let parentid = result.value.parentId
|
let parentid = result.value.parentId
|
||||||
const res = await getEntpcoursefile(parentid)
|
const res = await getEntpcoursefile(parentid)
|
||||||
if (res && res.code === 200) {
|
if (res && res.code === 200) {
|
||||||
const smarttalk = getSmarttalkPage({fileId: parentid})
|
const smarttalk = await getSmarttalkPage({fileId: parentid})
|
||||||
openPublicScreen('edit', res.data, smarttalk.resData) // 打开公屏-窗口
|
if (smarttalk && smarttalk.rows.length>0) {
|
||||||
|
openPublicScreen('edit', res.data, smarttalk.rows[0]) // 打开公屏-窗口
|
||||||
|
}else {
|
||||||
|
ElMessage.warning(res.msg||'没有查询到课件!')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ElMessage.warning(res.msg||'文件获取异常!')
|
ElMessage.warning(res.msg||'文件获取异常!')
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
<el-col :span="5">
|
<el-col :span="5">
|
||||||
<Left />
|
<Left />
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="14">
|
<el-col :span="15">
|
||||||
<Center />
|
<Center />
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="5">
|
<el-col :span="4">
|
||||||
<Right />
|
<Right />
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
Loading…
Reference in New Issue