ppt文件转入数据
This commit is contained in:
parent
7c3f3ea8fb
commit
a9443035c2
|
@ -28,12 +28,12 @@ const convertFontSizePtToPx = (html: string, ratio: number) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export default () => {
|
const slidesStore = useSlidesStore()
|
||||||
const slidesStore = useSlidesStore()
|
const { theme } = storeToRefs(useSlidesStore())
|
||||||
const { theme } = storeToRefs(useSlidesStore())
|
|
||||||
|
|
||||||
const { addSlidesFromData } = useAddSlidesOrElements()
|
const { addSlidesFromData } = useAddSlidesOrElements()
|
||||||
const { isEmptySlide } = useSlideHandler()
|
const { isEmptySlide } = useSlideHandler()
|
||||||
|
export default () => {
|
||||||
|
|
||||||
const exporting = ref(false)
|
const exporting = ref(false)
|
||||||
|
|
||||||
|
@ -486,9 +486,413 @@ export default () => {
|
||||||
reader.readAsArrayBuffer(file)
|
reader.readAsArrayBuffer(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
importSpecificFile,
|
importSpecificFile,
|
||||||
importPPTXFile,
|
importPPTXFile,
|
||||||
|
PPTXFileToJson,
|
||||||
exporting,
|
exporting,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导入PPTX 返回 json
|
||||||
|
export const PPTXFileToJson = (data: File|ArrayBuffer) => {
|
||||||
|
return new Promise(async(resolve, reject) => {
|
||||||
|
if (!data) return
|
||||||
|
let fileArrayBuffer: ArrayBuffer = null
|
||||||
|
let resData = {} // 返回的数据
|
||||||
|
|
||||||
|
const shapeList: ShapePoolItem[] = []
|
||||||
|
for (const item of SHAPE_LIST) {
|
||||||
|
shapeList.push(...item.children)
|
||||||
|
}
|
||||||
|
// 获取文件的 ArrayBuffer
|
||||||
|
const getArrayBuffer = () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const reader = new FileReader()
|
||||||
|
reader.onload = () => {
|
||||||
|
resolve(reader.result)
|
||||||
|
}
|
||||||
|
reader.onerror = reject
|
||||||
|
reader.readAsArrayBuffer(data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (data instanceof File) { // 文件
|
||||||
|
fileArrayBuffer = await getArrayBuffer()
|
||||||
|
} else if (data instanceof ArrayBuffer) { // ArrayBuffer
|
||||||
|
fileArrayBuffer = data
|
||||||
|
} else {
|
||||||
|
throw new Error('Invalid data type')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始解析
|
||||||
|
const json = await parse(fileArrayBuffer)
|
||||||
|
|
||||||
|
const ratio = 96 / 72
|
||||||
|
const width = json.size.width
|
||||||
|
|
||||||
|
resData.def = json // 保留原始数据
|
||||||
|
resData.width = width * ratio
|
||||||
|
resData.ratio = slidesStore.viewportRatio
|
||||||
|
|
||||||
|
const slides: Slide[] = []
|
||||||
|
for (const item of json.slides) {
|
||||||
|
const { type, value } = item.fill
|
||||||
|
let background: SlideBackground
|
||||||
|
if (type === 'image') {
|
||||||
|
background = {
|
||||||
|
type: 'image',
|
||||||
|
image: {
|
||||||
|
src: value.picBase64,
|
||||||
|
size: 'cover',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type === 'gradient') {
|
||||||
|
background = {
|
||||||
|
type: 'gradient',
|
||||||
|
gradient: {
|
||||||
|
type: 'linear',
|
||||||
|
colors: value.colors.map(item => ({
|
||||||
|
...item,
|
||||||
|
pos: parseInt(item.pos),
|
||||||
|
})),
|
||||||
|
rotate: value.rot,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
background = {
|
||||||
|
type: 'solid',
|
||||||
|
color: value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const slide: Slide = {
|
||||||
|
id: nanoid(10),
|
||||||
|
elements: [],
|
||||||
|
background,
|
||||||
|
}
|
||||||
|
|
||||||
|
const parseElements = (elements: Element[]) => {
|
||||||
|
for (const el of elements) {
|
||||||
|
const originWidth = el.width || 1
|
||||||
|
const originHeight = el.height || 1
|
||||||
|
const originLeft = el.left
|
||||||
|
const originTop = el.top
|
||||||
|
|
||||||
|
el.width = el.width * ratio
|
||||||
|
el.height = el.height * ratio
|
||||||
|
el.left = el.left * ratio
|
||||||
|
el.top = el.top * ratio
|
||||||
|
|
||||||
|
if (el.type === 'text') {
|
||||||
|
const textEl: PPTTextElement = {
|
||||||
|
type: 'text',
|
||||||
|
id: nanoid(10),
|
||||||
|
width: el.width,
|
||||||
|
height: el.height,
|
||||||
|
left: el.left,
|
||||||
|
top: el.top,
|
||||||
|
rotate: el.rotate,
|
||||||
|
defaultFontName: theme.value.fontName,
|
||||||
|
defaultColor: theme.value.fontColor,
|
||||||
|
content: convertFontSizePtToPx(el.content, ratio),
|
||||||
|
lineHeight: 1,
|
||||||
|
outline: {
|
||||||
|
color: el.borderColor,
|
||||||
|
width: el.borderWidth,
|
||||||
|
style: el.borderType,
|
||||||
|
},
|
||||||
|
fill: el.fillColor,
|
||||||
|
vertical: el.isVertical,
|
||||||
|
}
|
||||||
|
if (el.shadow) {
|
||||||
|
textEl.shadow = {
|
||||||
|
h: el.shadow.h * ratio,
|
||||||
|
v: el.shadow.v * ratio,
|
||||||
|
blur: el.shadow.blur * ratio,
|
||||||
|
color: el.shadow.color,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slide.elements.push(textEl)
|
||||||
|
}
|
||||||
|
else if (el.type === 'image') {
|
||||||
|
slide.elements.push({
|
||||||
|
type: 'image',
|
||||||
|
id: nanoid(10),
|
||||||
|
src: el.src,
|
||||||
|
width: el.width,
|
||||||
|
height: el.height,
|
||||||
|
left: el.left,
|
||||||
|
top: el.top,
|
||||||
|
fixedRatio: true,
|
||||||
|
rotate: el.rotate,
|
||||||
|
flipH: el.isFlipH,
|
||||||
|
flipV: el.isFlipV,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else if (el.type === 'audio') {
|
||||||
|
slide.elements.push({
|
||||||
|
type: 'audio',
|
||||||
|
id: nanoid(10),
|
||||||
|
src: el.blob,
|
||||||
|
width: el.width,
|
||||||
|
height: el.height,
|
||||||
|
left: el.left,
|
||||||
|
top: el.top,
|
||||||
|
rotate: 0,
|
||||||
|
fixedRatio: false,
|
||||||
|
color: theme.value.themeColor,
|
||||||
|
loop: false,
|
||||||
|
autoplay: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else if (el.type === 'video') {
|
||||||
|
slide.elements.push({
|
||||||
|
type: 'video',
|
||||||
|
id: nanoid(10),
|
||||||
|
src: (el.blob || el.src)!,
|
||||||
|
width: el.width,
|
||||||
|
height: el.height,
|
||||||
|
left: el.left,
|
||||||
|
top: el.top,
|
||||||
|
rotate: 0,
|
||||||
|
autoplay: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else if (el.type === 'shape') {
|
||||||
|
if (el.shapType === 'line' || /Connector/.test(el.shapType)) {
|
||||||
|
const lineElement = parseLineElement(el)
|
||||||
|
slide.elements.push(lineElement)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const shape = shapeList.find(item => item.pptxShapeType === el.shapType)
|
||||||
|
|
||||||
|
const vAlignMap: { [key: string]: ShapeTextAlign } = {
|
||||||
|
'mid': 'middle',
|
||||||
|
'down': 'bottom',
|
||||||
|
'up': 'top',
|
||||||
|
}
|
||||||
|
|
||||||
|
const element: PPTShapeElement = {
|
||||||
|
type: 'shape',
|
||||||
|
id: nanoid(10),
|
||||||
|
width: el.width,
|
||||||
|
height: el.height,
|
||||||
|
left: el.left,
|
||||||
|
top: el.top,
|
||||||
|
viewBox: [200, 200],
|
||||||
|
path: 'M 0 0 L 200 0 L 200 200 L 0 200 Z',
|
||||||
|
fill: el.fillColor || 'none',
|
||||||
|
fixedRatio: false,
|
||||||
|
rotate: el.rotate,
|
||||||
|
outline: {
|
||||||
|
color: el.borderColor,
|
||||||
|
width: el.borderWidth,
|
||||||
|
style: el.borderType,
|
||||||
|
},
|
||||||
|
text: {
|
||||||
|
content: convertFontSizePtToPx(el.content, ratio),
|
||||||
|
defaultFontName: theme.value.fontName,
|
||||||
|
defaultColor: theme.value.fontColor,
|
||||||
|
align: vAlignMap[el.vAlign] || 'middle',
|
||||||
|
},
|
||||||
|
flipH: el.isFlipH,
|
||||||
|
flipV: el.isFlipV,
|
||||||
|
}
|
||||||
|
if (el.shadow) {
|
||||||
|
element.shadow = {
|
||||||
|
h: el.shadow.h * ratio,
|
||||||
|
v: el.shadow.v * ratio,
|
||||||
|
blur: el.shadow.blur * ratio,
|
||||||
|
color: el.shadow.color,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shape) {
|
||||||
|
element.path = shape.path
|
||||||
|
element.viewBox = shape.viewBox
|
||||||
|
|
||||||
|
if (shape.pathFormula) {
|
||||||
|
element.pathFormula = shape.pathFormula
|
||||||
|
element.viewBox = [el.width, el.height]
|
||||||
|
|
||||||
|
const pathFormula = SHAPE_PATH_FORMULAS[shape.pathFormula]
|
||||||
|
if ('editable' in pathFormula && pathFormula.editable) {
|
||||||
|
element.path = pathFormula.formula(el.width, el.height, pathFormula.defaultValue)
|
||||||
|
element.keypoints = pathFormula.defaultValue
|
||||||
|
}
|
||||||
|
else element.path = pathFormula.formula(el.width, el.height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (el.shapType === 'custom') {
|
||||||
|
if (el.path!.indexOf('NaN') !== -1) element.path = ''
|
||||||
|
else {
|
||||||
|
element.special = true
|
||||||
|
element.path = el.path!
|
||||||
|
|
||||||
|
const { maxX, maxY } = getSvgPathRange(element.path)
|
||||||
|
element.viewBox = [maxX || originWidth, maxY || originHeight]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element.path) slide.elements.push(element)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (el.type === 'table') {
|
||||||
|
const row = el.data.length
|
||||||
|
const col = el.data[0].length
|
||||||
|
|
||||||
|
const style: TableCellStyle = {
|
||||||
|
fontname: theme.value.fontName,
|
||||||
|
color: theme.value.fontColor,
|
||||||
|
}
|
||||||
|
const data: TableCell[][] = []
|
||||||
|
for (let i = 0; i < row; i++) {
|
||||||
|
const rowCells: TableCell[] = []
|
||||||
|
for (let j = 0; j < col; j++) {
|
||||||
|
const cellData = el.data[i][j]
|
||||||
|
|
||||||
|
let textDiv: HTMLDivElement | null = document.createElement('div')
|
||||||
|
textDiv.innerHTML = cellData.text
|
||||||
|
const p = textDiv.querySelector('p')
|
||||||
|
const align = p?.style.textAlign || 'left'
|
||||||
|
|
||||||
|
const span = textDiv.querySelector('span')
|
||||||
|
const fontsize = span?.style.fontSize ? (parseInt(span?.style.fontSize) * ratio).toFixed(1) + 'px' : ''
|
||||||
|
const fontname = span?.style.fontFamily || ''
|
||||||
|
const color = span?.style.color || cellData.fontColor
|
||||||
|
|
||||||
|
rowCells.push({
|
||||||
|
id: nanoid(10),
|
||||||
|
colspan: cellData.colSpan || 1,
|
||||||
|
rowspan: cellData.rowSpan || 1,
|
||||||
|
text: textDiv.innerText,
|
||||||
|
style: {
|
||||||
|
...style,
|
||||||
|
align: ['left', 'right', 'center'].includes(align) ? (align as 'left' | 'right' | 'center') : 'left',
|
||||||
|
fontsize,
|
||||||
|
fontname,
|
||||||
|
color,
|
||||||
|
bold: cellData.fontBold,
|
||||||
|
backcolor: cellData.fillColor,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
textDiv = null
|
||||||
|
}
|
||||||
|
data.push(rowCells)
|
||||||
|
}
|
||||||
|
|
||||||
|
const colWidths: number[] = new Array(col).fill(1 / col)
|
||||||
|
|
||||||
|
slide.elements.push({
|
||||||
|
type: 'table',
|
||||||
|
id: nanoid(10),
|
||||||
|
width: el.width,
|
||||||
|
height: el.height,
|
||||||
|
left: el.left,
|
||||||
|
top: el.top,
|
||||||
|
colWidths,
|
||||||
|
rotate: 0,
|
||||||
|
data,
|
||||||
|
outline: {
|
||||||
|
width: el.borderWidth || 2,
|
||||||
|
style: el.borderType,
|
||||||
|
color: el.borderColor || '#eeece1',
|
||||||
|
},
|
||||||
|
cellMinHeight: 36,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else if (el.type === 'chart') {
|
||||||
|
let labels: string[]
|
||||||
|
let legends: string[]
|
||||||
|
let series: number[][]
|
||||||
|
|
||||||
|
if (el.chartType === 'scatterChart' || el.chartType === 'bubbleChart') {
|
||||||
|
labels = el.data[0].map((item, index) => `坐标${index + 1}`)
|
||||||
|
legends = ['X', 'Y']
|
||||||
|
series = el.data
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const data = el.data as ChartItem[]
|
||||||
|
labels = Object.values(data[0].xlabels)
|
||||||
|
legends = data.map(item => item.key)
|
||||||
|
series = data.map(item => item.values.map(v => v.y))
|
||||||
|
}
|
||||||
|
|
||||||
|
const options: ChartOptions = {}
|
||||||
|
|
||||||
|
let chartType: ChartType = 'bar'
|
||||||
|
|
||||||
|
switch (el.chartType) {
|
||||||
|
case 'barChart':
|
||||||
|
case 'bar3DChart':
|
||||||
|
chartType = 'bar'
|
||||||
|
if (el.barDir === 'bar') chartType = 'column'
|
||||||
|
if (el.grouping === 'stacked' || el.grouping === 'percentStacked') options.stack = true
|
||||||
|
break
|
||||||
|
case 'lineChart':
|
||||||
|
case 'line3DChart':
|
||||||
|
if (el.grouping === 'stacked' || el.grouping === 'percentStacked') options.stack = true
|
||||||
|
chartType = 'line'
|
||||||
|
break
|
||||||
|
case 'areaChart':
|
||||||
|
case 'area3DChart':
|
||||||
|
if (el.grouping === 'stacked' || el.grouping === 'percentStacked') options.stack = true
|
||||||
|
chartType = 'area'
|
||||||
|
break
|
||||||
|
case 'scatterChart':
|
||||||
|
case 'bubbleChart':
|
||||||
|
chartType = 'scatter'
|
||||||
|
break
|
||||||
|
case 'pieChart':
|
||||||
|
case 'pie3DChart':
|
||||||
|
chartType = 'pie'
|
||||||
|
break
|
||||||
|
case 'radarChart':
|
||||||
|
chartType = 'radar'
|
||||||
|
break
|
||||||
|
case 'doughnutChart':
|
||||||
|
chartType = 'ring'
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
slide.elements.push({
|
||||||
|
type: 'chart',
|
||||||
|
id: nanoid(10),
|
||||||
|
chartType: chartType,
|
||||||
|
width: el.width,
|
||||||
|
height: el.height,
|
||||||
|
left: el.left,
|
||||||
|
top: el.top,
|
||||||
|
rotate: 0,
|
||||||
|
themeColors: [theme.value.themeColor],
|
||||||
|
textColor: theme.value.fontColor,
|
||||||
|
data: {
|
||||||
|
labels,
|
||||||
|
legends,
|
||||||
|
series,
|
||||||
|
},
|
||||||
|
options,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else if (el.type === 'group' || el.type === 'diagram') {
|
||||||
|
const elements = el.elements.map(_el => ({
|
||||||
|
..._el,
|
||||||
|
left: _el.left + originLeft,
|
||||||
|
top: _el.top + originTop,
|
||||||
|
}))
|
||||||
|
parseElements(elements)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parseElements(item.elements)
|
||||||
|
slides.push(slide)
|
||||||
|
}
|
||||||
|
resData.slides = slides
|
||||||
|
resolve(resData)
|
||||||
|
})
|
||||||
}
|
}
|
|
@ -50,4 +50,10 @@ export class school {
|
||||||
// 获取学校管理审核
|
// 获取学校管理审核
|
||||||
static checkSchool = data => ApiService.publicHttp(`/smarttalk/audit/checkSchool`,data,'post')
|
static checkSchool = data => ApiService.publicHttp(`/smarttalk/audit/checkSchool`,data,'post')
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Other {
|
||||||
|
static baseUrl = "/common/upload"
|
||||||
|
// 测试
|
||||||
|
static uploadFile = data => ApiService.publicHttp(this.baseUrl, data, 'post', null, 'file')
|
||||||
}
|
}
|
|
@ -93,6 +93,14 @@ export function batchUpdateNew(data) {
|
||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// zdg: 批量新增pptist - 新
|
||||||
|
export function batchAddNew(data) {
|
||||||
|
return request({
|
||||||
|
url: '/education/entpcoursefile/batch/add',
|
||||||
|
method: 'post',
|
||||||
|
data: data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 修改entpcoursefile
|
// 修改entpcoursefile
|
||||||
export function updateFile2Redis(data) {
|
export function updateFile2Redis(data) {
|
||||||
|
|
|
@ -21,6 +21,29 @@ export function getFiles() {
|
||||||
}
|
}
|
||||||
return new Promise(cb)
|
return new Promise(cb)
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* base64 转 blob
|
||||||
|
*/
|
||||||
|
export function base64ToBlob(base64Data) {
|
||||||
|
const contentType = base64Data?.match(/^data:([^;]+);base64,/)?.[1]||'image/png'
|
||||||
|
// 去除Base64编码数据中的前缀(如"data:image/png;base64,")
|
||||||
|
const byteCharacters = atob(base64Data.split(',')[1]);
|
||||||
|
const byteArrays = [];
|
||||||
|
for (let i = 0; i < byteCharacters.length; i++) {
|
||||||
|
byteArrays.push(byteCharacters.charCodeAt(i));
|
||||||
|
}
|
||||||
|
return new Blob([new Uint8Array(byteArrays)], { type: contentType });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function arrayBufferToBlob(arrayBuffer, contentType) {
|
||||||
|
return new Blob([new Uint8Array(arrayBuffer)], { type: contentType });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function blobToFile(blob, fileName, contentType) {
|
||||||
|
fileName = fileName || 'file'
|
||||||
|
contentType = contentType || blob.type ||'image/png'
|
||||||
|
return new File([blob], fileName, { type: contentType });
|
||||||
|
}
|
||||||
|
|
||||||
// ============= 数学公式--相关 ===================
|
// ============= 数学公式--相关 ===================
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -59,11 +59,23 @@ import emitter from '@/utils/mitt'
|
||||||
import EditDialog from './edit-dialog.vue'
|
import EditDialog from './edit-dialog.vue'
|
||||||
import AdjustDialog from './adjust-dialog.vue'
|
import AdjustDialog from './adjust-dialog.vue'
|
||||||
import { completion, tempResult } from '@/api/mode/index.js'
|
import { completion, tempResult } from '@/api/mode/index.js'
|
||||||
import { dataSetJson } from '@/utils/comm.js'
|
// import { dataSetJson } from '@/utils/comm.js'
|
||||||
|
import * as commUtils from '@/utils/comm.js'
|
||||||
import PptDialog from '@/views/prepare/container/pptist-dialog.vue'
|
import PptDialog from '@/views/prepare/container/pptist-dialog.vue'
|
||||||
|
|
||||||
|
import useUserStore from '@/store/modules/user'
|
||||||
|
import {PPTXFileToJson} from '@/AixPPTist/src/hooks/useImport' // ppt转json
|
||||||
|
import * as API_entpcourse from '@/api/education/entpcourse' // 相关api
|
||||||
|
import * as API_entpcoursefile from '@/api/education/entpcoursefile' // 相关api
|
||||||
|
import * as Api_server from '@/api/apiService' // 相关api
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
const pptDialog = ref(false)
|
const pptDialog = ref(false)
|
||||||
const resultList = ref([])
|
const resultList = ref([])
|
||||||
|
const courseObj = reactive({
|
||||||
|
node: null, // 选择的课程节点
|
||||||
|
})
|
||||||
|
|
||||||
emitter.on('changeMode', (item) => {
|
emitter.on('changeMode', (item) => {
|
||||||
console.log(item, 'item')
|
console.log(item, 'item')
|
||||||
resultList.value = item.child
|
resultList.value = item.child
|
||||||
|
@ -98,9 +110,39 @@ const params = reactive(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
const addAiPPT = (res) => {
|
const addAiPPT = async(res) => {
|
||||||
|
let node = courseObj.node
|
||||||
|
if (!node) return msgUtils.msgWarning('请选择章节?')
|
||||||
//TODO res中有PPT地址
|
//TODO res中有PPT地址
|
||||||
console.log(res)
|
const params = { evalid: node.id, edituserid: userStore.id, pageSize: 1 }
|
||||||
|
const resEnpt = await HTTP_SERVER_API('getCourseList', params)
|
||||||
|
if (!(resEnpt?.rows?.[0] || null)) { // 创建
|
||||||
|
const resid = await HTTP_SERVER_API('addEntpcourse')
|
||||||
|
courseObj.entp.id = resid
|
||||||
|
} else courseObj.entp = resEnpt?.rows?.[0] || null
|
||||||
|
// 下载PPT 并解析json转换到我们自己数据库
|
||||||
|
fetch(res.url)
|
||||||
|
.then(res => res.arrayBuffer())
|
||||||
|
.then(async buffer => {
|
||||||
|
const resPptJson = await PPTXFileToJson(buffer)
|
||||||
|
const { def, slides, ...content } = resPptJson
|
||||||
|
console.log(slides)
|
||||||
|
for( let o of slides ) {
|
||||||
|
await toRousrceUrl(o)
|
||||||
|
}
|
||||||
|
// return
|
||||||
|
// 生成ppt课件-父级
|
||||||
|
const p_params = {parentContent: JSON.stringify(content)}
|
||||||
|
const parentid = await HTTP_SERVER_API('addEntpcoursefile', p_params)
|
||||||
|
if (!!parentid??null) { // 生成内容幻灯片
|
||||||
|
if (slides.length > 0) {
|
||||||
|
const resSlides = slides.map(({id, ...slide}) => slide)
|
||||||
|
const params = {parentid, filetype: 'slide', title: '', slides: resSlides }
|
||||||
|
const res_3 = await HTTP_SERVER_API('batchAddNew', params)
|
||||||
|
console.log('xxxx', res_3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
const conversation = async () => {
|
const conversation = async () => {
|
||||||
for (let item of resultList.value) {
|
for (let item of resultList.value) {
|
||||||
|
@ -155,15 +197,107 @@ emitter.on('changeResult', (item) => {
|
||||||
resultList.value[curIndex.value].answer = item
|
resultList.value[curIndex.value].answer = item
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// ======== zdg start ============
|
||||||
|
// 统一HTTP处理
|
||||||
|
const HTTP_SERVER_API = (type, params = {}) => {
|
||||||
|
switch (type) {
|
||||||
|
case 'addEntpcourse': { // 添加课程
|
||||||
|
const node = courseObj.node || {}
|
||||||
|
if (!node) return msgUtils.msgWarning('请选择章节?')
|
||||||
|
const def = { // 默认参数
|
||||||
|
entpid: userStore.user.deptId, // 部门id
|
||||||
|
level: 1, // 层级
|
||||||
|
parentid: 0, // 父级id
|
||||||
|
dictid: 0, // 字典id
|
||||||
|
evalid: node.id, // 章节id
|
||||||
|
evalparentid: node.parentid, // 单元id(父级id)
|
||||||
|
edusubject: node.edusubject, // 学科
|
||||||
|
edudegree: node.edudegree, // 年级
|
||||||
|
edustage: node.edustage, // 阶段
|
||||||
|
coursetype: '课标学科', // 课程类型
|
||||||
|
coursetitle: node.itemtitle, // 课程名称
|
||||||
|
coursedesc: '', // 课程描述
|
||||||
|
status: '', // 状态
|
||||||
|
dflag: 0, // 状态
|
||||||
|
edituserid: userStore.id, // 编辑人id
|
||||||
|
createblankfile: 'no', // 创建空白文件
|
||||||
|
}
|
||||||
|
courseObj.entp = def
|
||||||
|
return API_entpcourse.addEntpcourse(def)
|
||||||
|
}
|
||||||
|
case 'addEntpcoursefile': { // 添加课程文件
|
||||||
|
params = getDefParams(params)
|
||||||
|
return API_entpcoursefile.addEntpcoursefileReturnId(params)
|
||||||
|
}
|
||||||
|
case 'batchAddNew': { // 批量添加课程文件
|
||||||
|
params = getDefParams(params)
|
||||||
|
return API_entpcoursefile.batchAddNew(params)
|
||||||
|
}
|
||||||
|
case 'getCourseList': { // 获取课程列表
|
||||||
|
return API_entpcourse.listEntpcourse(params)
|
||||||
|
}
|
||||||
|
case 'getCourseFileList':{ // 获取课程文件列表
|
||||||
|
return API_entpcoursefile.listEntpcoursefileNew(params)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 获取默认参数
|
||||||
|
const getDefParams = (params) => {
|
||||||
|
const enpt = courseObj.entp
|
||||||
|
const def = {
|
||||||
|
parentid: 0,
|
||||||
|
entpid: userStore.user.deptId,
|
||||||
|
entpcourseid: enpt.id,
|
||||||
|
ppttype: 'file',
|
||||||
|
title: enpt.coursetitle,
|
||||||
|
fileurl: '',
|
||||||
|
filetype: 'aptist',
|
||||||
|
datacontent: '',
|
||||||
|
filekey: '',
|
||||||
|
filetag: '',
|
||||||
|
fileidx: 0,
|
||||||
|
dflag: 0,
|
||||||
|
status: '',
|
||||||
|
edituserid: userStore.id
|
||||||
|
}
|
||||||
|
return Object.assign(def, params)
|
||||||
|
}
|
||||||
|
// 图片|音频|视频 转换为在线地址
|
||||||
|
const toRousrceUrl = async(o) => {
|
||||||
|
if (!!o.src) { // 如果有src就转换
|
||||||
|
const isBase64 = /^data:image\/(\w+);base64,/.test(o.src)
|
||||||
|
const isBlobUrl = /^blob:/.test(o.src)
|
||||||
|
console.log('isBase64', o, isBase64)
|
||||||
|
if (isBase64) {
|
||||||
|
const bolb = commUtils.base64ToBlob(o.src)
|
||||||
|
const fileName = Date.now() + '.png'
|
||||||
|
const file = commUtils.blobToFile(bolb, fileName)
|
||||||
|
// o.src = fileName
|
||||||
|
// console.log('file', file)
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', file)
|
||||||
|
const res = await Api_server.Other.uploadFile(formData)
|
||||||
|
if (res && res.code == 200){
|
||||||
|
const url = res?.url
|
||||||
|
url &&(o.src = url)
|
||||||
|
}
|
||||||
|
} else if (isBlobUrl) { // 视频和音频
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (o?.background?.image) await toRousrceUrl(o.background.image)
|
||||||
|
if (o?.elements) o.elements.forEach(async o => {await toRousrceUrl(o)})
|
||||||
|
}
|
||||||
|
// ======== zdg end ============
|
||||||
|
|
||||||
const curNode = reactive({})
|
const curNode = reactive({})
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
let data = sessionStore.get('subject.curNode')
|
let data = sessionStore.get('subject.curNode')
|
||||||
Object.assign(curNode, data);
|
Object.assign(curNode, data);
|
||||||
|
courseObj.node = data
|
||||||
|
|
||||||
let jsonKey = `课标-${data.edustage}-${data.edusubject}`
|
let jsonKey = `课标-${data.edustage}-${data.edusubject}`
|
||||||
params.dataset_id = dataSetJson[jsonKey]
|
params.dataset_id = commUtils.dataSetJson[jsonKey]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue