zxl #212
|
@ -42,6 +42,7 @@
|
|||
"@vue-office/excel": "^1.7.11",
|
||||
"@vue-office/pdf": "^2.0.2",
|
||||
"@vueuse/core": "^10.11.0",
|
||||
"aix-plugins-aitools": "^1.0.9",
|
||||
"animate.css": "^4.1.1",
|
||||
"circular-json": "^0.5.9",
|
||||
"clipboard": "^2.0.11",
|
||||
|
|
|
@ -79,3 +79,19 @@ export const getModelInfo = (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
|
||||
})
|
||||
}
|
|
@ -0,0 +1,243 @@
|
|||
<template>
|
||||
<div>
|
||||
<div style="height: auto; display: flex">
|
||||
<div style="flex: 1">
|
||||
<div>
|
||||
<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"
|
||||
>
|
||||
</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'
|
||||
import CryptoJS from 'crypto-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: {
|
||||
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 = false
|
||||
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.fileNewName,
|
||||
fileFlag: '素材',
|
||||
fileId: this.filedata.id
|
||||
}
|
||||
addFileToSC(saveObj)
|
||||
.then((resone) => {
|
||||
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
|
||||
},
|
||||
// 删除作业
|
||||
delhomework(item) {
|
||||
this.isLoading = true
|
||||
delClasswork(item.id)
|
||||
.then(async (res) => {
|
||||
ElMessage.success('操作成功')
|
||||
this.isLoading = false
|
||||
await this.asyncAllFile()
|
||||
this.initHomeWork()
|
||||
})
|
||||
.catch(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
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;
|
||||
}
|
||||
</style>
|
|
@ -26,6 +26,9 @@ import log from 'electron-log/renderer' // 渲染进程日志-文件记录
|
|||
import customComponent from '@/components/common' // 自定义组件
|
||||
import plugins from './plugins' // plugins插件
|
||||
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') { // 非开发环境,将日志打印到日志文件
|
||||
Object.assign(console, log.functions) // 渲染进程日志-控制台替换
|
||||
|
@ -59,6 +62,7 @@ app.use(router)
|
|||
.use(plugins)
|
||||
.use(Icon)
|
||||
.use(Directive)
|
||||
.use(aiAudio)
|
||||
.use(VMdPreview)
|
||||
.mount('#app')
|
||||
|
||||
|
|
|
@ -96,6 +96,12 @@ export const constantRoutes = [
|
|||
name: 'aiKolors',
|
||||
meta: { title: '文生图片', showBread: true }
|
||||
},
|
||||
{
|
||||
path: 'aiVoice',
|
||||
component: () => import('@/components/ai-voice/index.vue'),
|
||||
name: 'aiVoice',
|
||||
meta: { title: '语音生成', showBread: true }
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ const tools = reactive([{
|
|||
img: 'airobot'
|
||||
},{
|
||||
name: '语音生成',
|
||||
path: '',
|
||||
path: '/model/aiVoice',
|
||||
img: 'aiyuyin'
|
||||
},{
|
||||
name: '文生图片',
|
||||
|
@ -211,6 +211,19 @@ const gotoRoute = (item) => {
|
|||
if (item.path) {
|
||||
if (item.path === '/model/aiKolors') {
|
||||
gotoAiKolors(item.path)
|
||||
}else if(item.path == '/model/aiVoice'){
|
||||
console.log('aiVoice',uploadData.value)
|
||||
const path = '/model/aiVoice'
|
||||
let subjectdata = sessionStore.get('subject.curNode')
|
||||
let datasubject = `课标-${subjectdata.edustage}-${subjectdata.edusubject}`
|
||||
router.push({
|
||||
path,
|
||||
query: {
|
||||
datasetId: dataSetJson[datasubject],
|
||||
coursetitle: currentNode.value.itemtitle,
|
||||
...uploadData.value
|
||||
}
|
||||
});
|
||||
}else {
|
||||
router.push(item.path)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue