mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
feat: 更新导入功能(pptxtojson v0.1.2)
This commit is contained in:
parent
effd46e05e
commit
d03f3a9414
14
package-lock.json
generated
14
package-lock.json
generated
@ -24,7 +24,7 @@
|
|||||||
"number-precision": "^1.6.0",
|
"number-precision": "^1.6.0",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"pptxgenjs": "^3.12.0",
|
"pptxgenjs": "^3.12.0",
|
||||||
"pptxtojson": "^0.0.13",
|
"pptxtojson": "^0.1.2",
|
||||||
"prosemirror-commands": "^1.3.0",
|
"prosemirror-commands": "^1.3.0",
|
||||||
"prosemirror-dropcursor": "^1.6.0",
|
"prosemirror-dropcursor": "^1.6.0",
|
||||||
"prosemirror-gapcursor": "^1.3.1",
|
"prosemirror-gapcursor": "^1.3.1",
|
||||||
@ -10868,9 +10868,9 @@
|
|||||||
"integrity": "sha512-t3rNFBgJRugIhackit2mVcLfF6IRc0JE4oeizPQL8Zrm8n2WY/0wOdpOPhdtG0V9Q2TlW/axbF1MJ6z+Yj/kKQ=="
|
"integrity": "sha512-t3rNFBgJRugIhackit2mVcLfF6IRc0JE4oeizPQL8Zrm8n2WY/0wOdpOPhdtG0V9Q2TlW/axbF1MJ6z+Yj/kKQ=="
|
||||||
},
|
},
|
||||||
"node_modules/pptxtojson": {
|
"node_modules/pptxtojson": {
|
||||||
"version": "0.0.13",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmmirror.com/pptxtojson/-/pptxtojson-0.0.13.tgz",
|
"resolved": "https://registry.npmmirror.com/pptxtojson/-/pptxtojson-0.1.2.tgz",
|
||||||
"integrity": "sha512-ltwUe4U6UVvZ2/+4qhzz8LlH7VBox/Y454ppRPlQeMY/yqszpBdD2/Qj+WEslhrciVY+lup8K+7e7pbL9ZTJuQ==",
|
"integrity": "sha512-UvzEuCnspfZqc1Tf7TU6tSyXV+4OngkTfoAEZdPVW2i6wedU16wr8hkNzwQ77ePyfoyaODAFwS9cfJnnEhwfKQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"tinycolor2": "1.6.0",
|
"tinycolor2": "1.6.0",
|
||||||
@ -23339,9 +23339,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pptxtojson": {
|
"pptxtojson": {
|
||||||
"version": "0.0.13",
|
"version": "0.1.2",
|
||||||
"resolved": "https://registry.npmmirror.com/pptxtojson/-/pptxtojson-0.0.13.tgz",
|
"resolved": "https://registry.npmmirror.com/pptxtojson/-/pptxtojson-0.1.2.tgz",
|
||||||
"integrity": "sha512-ltwUe4U6UVvZ2/+4qhzz8LlH7VBox/Y454ppRPlQeMY/yqszpBdD2/Qj+WEslhrciVY+lup8K+7e7pbL9ZTJuQ==",
|
"integrity": "sha512-UvzEuCnspfZqc1Tf7TU6tSyXV+4OngkTfoAEZdPVW2i6wedU16wr8hkNzwQ77ePyfoyaODAFwS9cfJnnEhwfKQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"tinycolor2": "1.6.0",
|
"tinycolor2": "1.6.0",
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
"number-precision": "^1.6.0",
|
"number-precision": "^1.6.0",
|
||||||
"pinia": "^2.1.7",
|
"pinia": "^2.1.7",
|
||||||
"pptxgenjs": "^3.12.0",
|
"pptxgenjs": "^3.12.0",
|
||||||
"pptxtojson": "^0.0.13",
|
"pptxtojson": "^0.1.2",
|
||||||
"prosemirror-commands": "^1.3.0",
|
"prosemirror-commands": "^1.3.0",
|
||||||
"prosemirror-dropcursor": "^1.6.0",
|
"prosemirror-dropcursor": "^1.6.0",
|
||||||
"prosemirror-gapcursor": "^1.3.1",
|
"prosemirror-gapcursor": "^1.3.1",
|
||||||
|
@ -1,14 +1,25 @@
|
|||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { parse, type Shape, type Element } from 'pptxtojson'
|
import { parse, type Shape, type Element, type ChartItem } from 'pptxtojson'
|
||||||
import { nanoid } from 'nanoid'
|
import { nanoid } from 'nanoid'
|
||||||
import type { Slide, TableCellStyle, TableCell, ChartType, ChartOptions, SlideBackground, PPTShapeElement, PPTLineElement } from '@/types/slides'
|
|
||||||
import { useSlidesStore } from '@/store'
|
import { useSlidesStore } from '@/store'
|
||||||
import { decrypt } from '@/utils/crypto'
|
import { decrypt } from '@/utils/crypto'
|
||||||
import { type ShapePoolItem, SHAPE_LIST, SHAPE_PATH_FORMULAS } from '@/configs/shapes'
|
import { type ShapePoolItem, SHAPE_LIST, SHAPE_PATH_FORMULAS } from '@/configs/shapes'
|
||||||
import { VIEWPORT_SIZE } from '@/configs/canvas'
|
import { VIEWPORT_SIZE } from '@/configs/canvas'
|
||||||
import useAddSlidesOrElements from '@/hooks/useAddSlidesOrElements'
|
import useAddSlidesOrElements from '@/hooks/useAddSlidesOrElements'
|
||||||
import message from '@/utils/message'
|
import message from '@/utils/message'
|
||||||
|
import type {
|
||||||
|
Slide,
|
||||||
|
TableCellStyle,
|
||||||
|
TableCell,
|
||||||
|
ChartType,
|
||||||
|
ChartOptions,
|
||||||
|
SlideBackground,
|
||||||
|
PPTShapeElement,
|
||||||
|
PPTLineElement,
|
||||||
|
ShapeTextAlign,
|
||||||
|
PPTTextElement,
|
||||||
|
} from '@/types/slides'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const slidesStore = useSlidesStore()
|
const slidesStore = useSlidesStore()
|
||||||
@ -65,7 +76,7 @@ export default () => {
|
|||||||
top: el.top,
|
top: el.top,
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
style: el.borderType,
|
style: el.borderType === 'solid' ? 'solid' : 'dashed',
|
||||||
color: el.borderColor,
|
color: el.borderColor,
|
||||||
points: ['', el.shapType === 'straightConnector1' ? 'arrow' : '']
|
points: ['', el.shapType === 'straightConnector1' ? 'arrow' : '']
|
||||||
}
|
}
|
||||||
@ -85,7 +96,10 @@ export default () => {
|
|||||||
|
|
||||||
const reader = new FileReader()
|
const reader = new FileReader()
|
||||||
reader.onload = async e => {
|
reader.onload = async e => {
|
||||||
const json = await parse(e.target!.result as ArrayBuffer)
|
const json = await parse(e.target!.result as ArrayBuffer, {
|
||||||
|
slideFactor: 75 / 914400,
|
||||||
|
fontsizeFactor: 100 / 98,
|
||||||
|
})
|
||||||
|
|
||||||
const width = json.size.width
|
const width = json.size.width
|
||||||
const scale = VIEWPORT_SIZE / width
|
const scale = VIEWPORT_SIZE / width
|
||||||
@ -105,7 +119,7 @@ export default () => {
|
|||||||
background = {
|
background = {
|
||||||
type: 'gradient',
|
type: 'gradient',
|
||||||
gradientType: 'linear',
|
gradientType: 'linear',
|
||||||
gradientColor: [value.colors[0], value.colors[1]],
|
gradientColor: [value.colors[0].color, value.colors[value.colors.length - 1].color],
|
||||||
gradientRotate: value.rot,
|
gradientRotate: value.rot,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -130,7 +144,7 @@ export default () => {
|
|||||||
el.top = el.top * scale
|
el.top = el.top * scale
|
||||||
|
|
||||||
if (el.type === 'text') {
|
if (el.type === 'text') {
|
||||||
slide.elements.push({
|
const textEl: PPTTextElement = {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
id: nanoid(10),
|
id: nanoid(10),
|
||||||
width: el.width,
|
width: el.width,
|
||||||
@ -145,10 +159,13 @@ export default () => {
|
|||||||
outline: {
|
outline: {
|
||||||
color: el.borderColor,
|
color: el.borderColor,
|
||||||
width: el.borderWidth,
|
width: el.borderWidth,
|
||||||
style: el.borderType,
|
style: el.borderType === 'solid' ? 'solid' : 'dashed',
|
||||||
},
|
},
|
||||||
fill: el.fillColor,
|
fill: el.fillColor,
|
||||||
})
|
vertical: el.isVertical,
|
||||||
|
}
|
||||||
|
if (el.shadow) textEl.shadow = el.shadow
|
||||||
|
slide.elements.push(textEl)
|
||||||
}
|
}
|
||||||
else if (el.type === 'image') {
|
else if (el.type === 'image') {
|
||||||
slide.elements.push({
|
slide.elements.push({
|
||||||
@ -163,14 +180,49 @@ export default () => {
|
|||||||
rotate: el.rotate,
|
rotate: el.rotate,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
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') {
|
else if (el.type === 'shape') {
|
||||||
if (el.shapType === 'line' || el.shapType === 'straightConnector1') {
|
if (el.shapType === 'line' || /Connector/.test(el.shapType)) {
|
||||||
const lineElement = parseLineElement(el)
|
const lineElement = parseLineElement(el)
|
||||||
slide.elements.push(lineElement)
|
slide.elements.push(lineElement)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const shape = shapeList.find(item => item.pptxShapeType === el.shapType)
|
const shape = shapeList.find(item => item.pptxShapeType === el.shapType)
|
||||||
|
|
||||||
|
const vAlignMap: { [key: string]: ShapeTextAlign } = {
|
||||||
|
'mid': 'middle',
|
||||||
|
'down': 'bottom',
|
||||||
|
'up': 'top',
|
||||||
|
}
|
||||||
|
|
||||||
const element: PPTShapeElement = {
|
const element: PPTShapeElement = {
|
||||||
type: 'shape',
|
type: 'shape',
|
||||||
id: nanoid(10),
|
id: nanoid(10),
|
||||||
@ -186,15 +238,18 @@ export default () => {
|
|||||||
outline: {
|
outline: {
|
||||||
color: el.borderColor,
|
color: el.borderColor,
|
||||||
width: el.borderWidth,
|
width: el.borderWidth,
|
||||||
style: el.borderType,
|
style: el.borderType === 'solid' ? 'solid' : 'dashed',
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
content: el.content,
|
content: el.content,
|
||||||
defaultFontName: theme.value.fontName,
|
defaultFontName: theme.value.fontName,
|
||||||
defaultColor: theme.value.fontColor,
|
defaultColor: theme.value.fontColor,
|
||||||
align: 'middle',
|
align: vAlignMap[el.vAlign] || 'middle',
|
||||||
}
|
},
|
||||||
|
flipH: el.isFlipH,
|
||||||
|
flipV: el.isFlipV,
|
||||||
}
|
}
|
||||||
|
if (el.shadow) element.shadow = el.shadow
|
||||||
|
|
||||||
if (shape) {
|
if (shape) {
|
||||||
element.path = shape.path
|
element.path = shape.path
|
||||||
@ -212,6 +267,11 @@ export default () => {
|
|||||||
else element.path = pathFormula.formula(el.width, el.height)
|
else element.path = pathFormula.formula(el.width, el.height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (el.shapType === 'custom') {
|
||||||
|
element.special = true
|
||||||
|
element.path = el.path!
|
||||||
|
element.viewBox = [el.width, el.height]
|
||||||
|
}
|
||||||
|
|
||||||
slide.elements.push(element)
|
slide.elements.push(element)
|
||||||
}
|
}
|
||||||
@ -231,7 +291,7 @@ export default () => {
|
|||||||
const cellData = el.data[i][j]
|
const cellData = el.data[i][j]
|
||||||
rowCells.push({
|
rowCells.push({
|
||||||
id: nanoid(10),
|
id: nanoid(10),
|
||||||
colspan: 1,
|
colspan: cellData.colSpan || 1,
|
||||||
rowspan: cellData.rowSpan || 1,
|
rowspan: cellData.rowSpan || 1,
|
||||||
text: cellData.text,
|
text: cellData.text,
|
||||||
style,
|
style,
|
||||||
@ -258,7 +318,7 @@ export default () => {
|
|||||||
color: '#eeece1',
|
color: '#eeece1',
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
color: theme.value.themeColor,
|
color: el.themeColor,
|
||||||
rowHeader: true,
|
rowHeader: true,
|
||||||
rowFooter: false,
|
rowFooter: false,
|
||||||
colHeader: false,
|
colHeader: false,
|
||||||
@ -272,40 +332,47 @@ export default () => {
|
|||||||
let legends: string[]
|
let legends: string[]
|
||||||
let series: number[][]
|
let series: number[][]
|
||||||
|
|
||||||
if (el.chartType === 'scatterChart') {
|
if (el.chartType === 'scatterChart' || el.chartType === 'bubbleChart') {
|
||||||
labels = el.data[0].map(item => item + '')
|
const data = el.data
|
||||||
|
labels = data[0].map(item => item + '')
|
||||||
legends = ['系列1']
|
legends = ['系列1']
|
||||||
series = [el.data[1]]
|
series = [data[1]]
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
labels = Object.values(el.data[0].xlabels)
|
const data = el.data as ChartItem[]
|
||||||
legends = el.data.map(item => item.key)
|
labels = Object.values(data[0].xlabels)
|
||||||
series = el.data.map(item => item.values.map(v => v.y))
|
legends = data.map(item => item.key)
|
||||||
|
series = data.map(item => item.values.map(v => v.y))
|
||||||
}
|
}
|
||||||
|
|
||||||
let options: ChartOptions = {}
|
const options: ChartOptions = {}
|
||||||
|
|
||||||
let chartType: ChartType = 'bar'
|
let chartType: ChartType = 'bar'
|
||||||
if (el.chartType === 'barChart') {
|
|
||||||
|
switch (el.chartType) {
|
||||||
|
case 'barChart':
|
||||||
|
case 'bar3DChart':
|
||||||
chartType = 'bar'
|
chartType = 'bar'
|
||||||
}
|
if (el.barDir === 'bar') options.horizontalBars = true
|
||||||
if (el.chartType === 'stackedBarChart') {
|
if (el.grouping === 'stacked' || el.grouping === 'percentStacked') options.stackBars = true
|
||||||
chartType = 'bar'
|
break
|
||||||
options = { stackBars: true }
|
case 'lineChart':
|
||||||
}
|
case 'line3DChart':
|
||||||
else if (el.chartType === 'lineChart') {
|
case 'areaChart':
|
||||||
|
case 'area3DChart':
|
||||||
|
case 'scatterChart':
|
||||||
|
case 'bubbleChart':
|
||||||
chartType = 'line'
|
chartType = 'line'
|
||||||
}
|
if (el.chartType === 'areaChart' || el.chartType === 'area3DChart') options.showArea = true
|
||||||
else if (el.chartType === 'areaChart') {
|
if (el.chartType === 'scatterChart' || el.chartType === 'bubbleChart') options.showLine = false
|
||||||
chartType = 'line'
|
break
|
||||||
options = { showArea: true }
|
case 'pieChart':
|
||||||
}
|
case 'pie3DChart':
|
||||||
else if (el.chartType === 'scatterChart') {
|
case 'doughnutChart':
|
||||||
chartType = 'line'
|
|
||||||
options = { showLine: false }
|
|
||||||
}
|
|
||||||
else if (el.chartType === 'pieChart' || el.chartType === 'pie3DChart') {
|
|
||||||
chartType = 'pie'
|
chartType = 'pie'
|
||||||
|
if (el.chartType === 'doughnutChart') options.donut = true
|
||||||
|
break
|
||||||
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
slide.elements.push({
|
slide.elements.push({
|
||||||
@ -327,7 +394,7 @@ export default () => {
|
|||||||
options,
|
options,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else if (el.type === 'group') {
|
else if (el.type === 'group' || el.type === 'diagram') {
|
||||||
const elements = el.elements.map(_el => ({
|
const elements = el.elements.map(_el => ({
|
||||||
..._el,
|
..._el,
|
||||||
left: _el.left + el.left,
|
left: _el.left + el.left,
|
||||||
|
@ -266,6 +266,8 @@ export interface ShapeGradient {
|
|||||||
rotate: number
|
rotate: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ShapeTextAlign = 'top' | 'middle' | 'bottom'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 形状内文本
|
* 形状内文本
|
||||||
*
|
*
|
||||||
@ -281,7 +283,7 @@ export interface ShapeText {
|
|||||||
content: string
|
content: string
|
||||||
defaultFontName: string
|
defaultFontName: string
|
||||||
defaultColor: string
|
defaultColor: string
|
||||||
align: 'top' | 'middle' | 'bottom'
|
align: ShapeTextAlign
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user