Merge branch 'main' of http://27.128.240.72:3000/zhuhao/AIx_Smarttalk_WS into baigl
This commit is contained in:
commit
464f39dac8
|
@ -125,6 +125,7 @@ import {
|
||||||
User,
|
User,
|
||||||
Switch,
|
Switch,
|
||||||
More,
|
More,
|
||||||
|
Material
|
||||||
} from '@icon-park/vue-next'
|
} from '@icon-park/vue-next'
|
||||||
|
|
||||||
export interface Icons {
|
export interface Icons {
|
||||||
|
@ -255,6 +256,7 @@ export const icons: Icons = {
|
||||||
IconUser: User,
|
IconUser: User,
|
||||||
IconSwitch: Switch,
|
IconSwitch: Switch,
|
||||||
IconMore: More,
|
IconMore: More,
|
||||||
|
IconMaterial: Material
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
|
@ -0,0 +1,173 @@
|
||||||
|
<template>
|
||||||
|
<header class="flex material-header">
|
||||||
|
<span>选择素材</span>
|
||||||
|
<i class="iconfont icon-guanbi" @click="onClose"></i>
|
||||||
|
</header>
|
||||||
|
<div class="flex material-list" v-loading="loading">
|
||||||
|
<div class="flex material-item" v-for="item in list" :key="item.id" >
|
||||||
|
<div class="flex">
|
||||||
|
<el-image :src="fileUrl(item)" class="img" />
|
||||||
|
<el-text truncated>{{ item.fileShowName }}</el-text>
|
||||||
|
</div>
|
||||||
|
<el-button type="primary" @click="onInsert(item)">插入</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, reactive, onMounted, computed } from 'vue';
|
||||||
|
import { sessionStore } from '@/utils/store'
|
||||||
|
import { getSmarttalkPage } from '@/api/file'
|
||||||
|
import { getFileSuffix, urlToBase64 } from '@/utils/ruoyi.js'
|
||||||
|
|
||||||
|
const emit = defineEmits(['insertMaterial', 'close'])
|
||||||
|
|
||||||
|
const curNode = reactive({})
|
||||||
|
let params = {
|
||||||
|
textbookId: '',
|
||||||
|
levelFirstId: '',
|
||||||
|
levelSecondId: null,
|
||||||
|
fileSource: '个人',
|
||||||
|
fileRoot: '备课',
|
||||||
|
orderByColumn: 'uploadTime',
|
||||||
|
isAsc: 'desc',
|
||||||
|
pageSize: 500
|
||||||
|
}
|
||||||
|
|
||||||
|
const suffixAry = [ 'jpeg','jpg','png','gif','mp3','mp4','avi','mov']
|
||||||
|
const videoSuffix = ['mp3','mp4','avi','mov']
|
||||||
|
const list = ref([])
|
||||||
|
const loading = ref(false)
|
||||||
|
const init = () => {
|
||||||
|
loading.value = true
|
||||||
|
getSmarttalkPage(params).then(res => {
|
||||||
|
loading.value = false
|
||||||
|
if(res.rows && res.rows.length){
|
||||||
|
// 过滤出图片和视频
|
||||||
|
list.value = res.rows.filter( item => suffixAry.indexOf(getFileSuffix(item.fileShowName)) != -1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileUrl = computed(() => (item) =>{
|
||||||
|
if(videoSuffix.indexOf(getFileSuffix(item.fileShowName)) != -1){
|
||||||
|
return item.coverPic
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return item.fileFullPath
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
// 插入
|
||||||
|
const onInsert = async (item) =>{
|
||||||
|
if(videoSuffix.indexOf(getFileSuffix(item.fileShowName)) != -1){
|
||||||
|
emit('insertMaterial',{ type: 'video', data: item.fileFullPath })
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
const base64 = await urlToBase64(item.fileFullPath)
|
||||||
|
emit('insertMaterial',{ type: 'img', data: base64 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const GetUrlParameters = (parameters) => {
|
||||||
|
let resData = "";
|
||||||
|
|
||||||
|
let url = document.location.toString();
|
||||||
|
let arrUrl = url.split("?");
|
||||||
|
// 判断是否有参数
|
||||||
|
if (arrUrl.length > 1) {
|
||||||
|
// 拆分参数字符串
|
||||||
|
let parametersArr = arrUrl[1].split("&");
|
||||||
|
// 循环查找参数
|
||||||
|
for (let i = 0; i <= parametersArr.length; i++) {
|
||||||
|
if (parametersArr[i]) {
|
||||||
|
// 拆分参数的键和值
|
||||||
|
let parameterStr = parametersArr[i].split("=");
|
||||||
|
if (parameters == parameterStr[0]) {
|
||||||
|
resData = parameterStr[1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const proxyToBase64 = (url)=> {
|
||||||
|
const dourl = GetUrlParameters(url)
|
||||||
|
console.log(dourl,'dourl')
|
||||||
|
return
|
||||||
|
axios({
|
||||||
|
url: "/api/logo.png",
|
||||||
|
method: "get",
|
||||||
|
responseType: "blob",
|
||||||
|
}).then((res) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.readAsDataURL(res.data);
|
||||||
|
reader.onload = () => {
|
||||||
|
console.log(reader.result);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 关闭
|
||||||
|
const onClose = () =>{
|
||||||
|
emit('close')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
let data = sessionStore.get('subject.curNode')
|
||||||
|
Object.assign(curNode, data);
|
||||||
|
params.textbookId = curNode.rootid
|
||||||
|
if (curNode.parentNode) {
|
||||||
|
params.levelFirstId = curNode.parentNode.id
|
||||||
|
params.levelSecondId = curNode.id
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
params.levelFirstId = curNode.id
|
||||||
|
}
|
||||||
|
init()
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.material-header {
|
||||||
|
font-size: 17px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
.icon-guanbi{
|
||||||
|
font-size: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.material-list{
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 150px;
|
||||||
|
max-height: 500px;
|
||||||
|
overflow-y: auto
|
||||||
|
}
|
||||||
|
|
||||||
|
.material-item {
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
justify-content: space-between;
|
||||||
|
.img{
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -82,6 +82,7 @@
|
||||||
<IconVideoTwo class="handler-item" v-tooltip="'插入音视频'" />
|
<IconVideoTwo class="handler-item" v-tooltip="'插入音视频'" />
|
||||||
</Popover>
|
</Popover>
|
||||||
<IconPreviewOpen class="handler-item" v-tooltip="'插入试题'" @click="classWorkTaskVisible = true" />
|
<IconPreviewOpen class="handler-item" v-tooltip="'插入试题'" @click="classWorkTaskVisible = true" />
|
||||||
|
<IconMaterial class="handler-item" v-tooltip="'插入素材'" @click="materiaVisible = true"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="right-handler">
|
<div class="right-handler">
|
||||||
|
@ -121,6 +122,13 @@
|
||||||
/>
|
/>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
v-model:visible="materiaVisible"
|
||||||
|
:width="880">
|
||||||
|
<MaterialDialog @close="materiaVisible = false" @insertMaterial="insertMaterial"/>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -147,6 +155,7 @@ import Divider from '../../../components/Divider.vue'
|
||||||
import Popover from '../../../components/Popover.vue'
|
import Popover from '../../../components/Popover.vue'
|
||||||
import PopoverMenuItem from '../../../components/PopoverMenuItem.vue'
|
import PopoverMenuItem from '../../../components/PopoverMenuItem.vue'
|
||||||
import QuestToPPTist from '@/views/classTask/newClassTaskAssign/questToPPTist/index.vue'
|
import QuestToPPTist from '@/views/classTask/newClassTaskAssign/questToPPTist/index.vue'
|
||||||
|
import MaterialDialog from './MaterialDialog.vue'
|
||||||
|
|
||||||
const mainStore = useMainStore()
|
const mainStore = useMainStore()
|
||||||
const { creatingElement, creatingCustomShape, showSelectPanel, showSearchPanel, showNotesPanel } = storeToRefs(mainStore)
|
const { creatingElement, creatingCustomShape, showSelectPanel, showSearchPanel, showNotesPanel } = storeToRefs(mainStore)
|
||||||
|
@ -198,6 +207,7 @@ const classWorkTaskVisible = ref(false)
|
||||||
const textTypeSelectVisible = ref(false)
|
const textTypeSelectVisible = ref(false)
|
||||||
const shapeMenuVisible = ref(false)
|
const shapeMenuVisible = ref(false)
|
||||||
const moreVisible = ref(false)
|
const moreVisible = ref(false)
|
||||||
|
const materiaVisible = ref(false)
|
||||||
|
|
||||||
// 绘制文字范围
|
// 绘制文字范围
|
||||||
const drawText = (vertical = false) => {
|
const drawText = (vertical = false) => {
|
||||||
|
@ -244,6 +254,23 @@ const toggleSraechPanel = () => {
|
||||||
const toggleNotesPanel = () => {
|
const toggleNotesPanel = () => {
|
||||||
mainStore.setNotesPanelState(!showNotesPanel.value)
|
mainStore.setNotesPanelState(!showNotesPanel.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 插入素材
|
||||||
|
interface MaterialParams {
|
||||||
|
type: string,
|
||||||
|
data: string
|
||||||
|
}
|
||||||
|
const insertMaterial = (item: MaterialParams) =>{
|
||||||
|
const { type, data } = item
|
||||||
|
if(type == 'video'){
|
||||||
|
createVideoElement(data)
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
createImageElement(data)
|
||||||
|
}
|
||||||
|
materiaVisible.value = false
|
||||||
|
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
@ -258,16 +258,45 @@ export const getFileName = (filename) => {
|
||||||
return filename.replace(/\.[^/.]+$/, "");
|
return filename.replace(/\.[^/.]+$/, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清除当前选中的教材 章节 相关信息
|
|
||||||
export const clearBookInfo = () =>{
|
/**
|
||||||
//当前选中的教材
|
* 根据图片的url转换对应的base64值
|
||||||
localStorage.removeItem('curBook')
|
* @param { String } url 如:http://xxxx/xxx.png
|
||||||
// 当前选中的节点
|
* @returns base64取值
|
||||||
localStorage.removeItem('curNode')
|
*/
|
||||||
// 所有章节单元数据
|
export const urlToBase64 = (url) => {
|
||||||
localStorage.removeItem('unitList')
|
|
||||||
// 所有教材数据
|
return new Promise((resolve, reject) => {
|
||||||
localStorage.removeItem('subjectList')
|
if (!url) {
|
||||||
// 展开的节点
|
reject('请传入url内容')
|
||||||
localStorage.removeItem('defaultExpandedKeys')
|
}
|
||||||
|
if (/\.(png|jpe?g|gif|svg)(\?.*)?$/.test(url)) {
|
||||||
|
// 图片地址
|
||||||
|
let image = new Image()
|
||||||
|
// 设置跨域问题
|
||||||
|
image.setAttribute('crossOrigin', 'anonymous')
|
||||||
|
// 图片地址
|
||||||
|
image.src = url +"?v=" + Math.random(); // 处理缓存,fix缓存bug,有缓存,浏览器会报错;
|
||||||
|
image.onload = () => {
|
||||||
|
let canvas = document.createElement('canvas')
|
||||||
|
const ctx = canvas.getContext('2d')
|
||||||
|
canvas.width = image.width
|
||||||
|
canvas.height = image.height
|
||||||
|
ctx.drawImage(image, 0, 0, image.width, image.height)
|
||||||
|
|
||||||
|
// 获取图片后缀
|
||||||
|
const ext = url.substring(url.lastIndexOf('.') + 1).toLowerCase()
|
||||||
|
// 转base64
|
||||||
|
const dataUrl = canvas.toDataURL(`image/${ext}`)
|
||||||
|
resolve(dataUrl || '')
|
||||||
|
canvas = null // 清除canvas元素
|
||||||
|
image = null // 清除img元素
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 非图片地址
|
||||||
|
reject('非(png/jpe?g/gif/svg等)图片地址');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue