Commit f8159880 authored by 罗超's avatar 罗超

Merge branch 'master' of http://gitlab.oytour.com/viitto/pptist

# Conflicts:
#	src/App.vue
parents 9bde0bff 1a7dd09f
<template>
<div v-if="isFinish" style="height: 100%;">
<Screen v-if="screening" />
<Market v-else-if="Market"></Market>
<!-- <NewFile v-else-if="market"></NewFile> -->
<Market v-else-if="market"></Market>
<Editor v-else-if="_isPC" />
<Mobile v-else />
</div>
</template>
<script lang="ts" setup>
import { onMounted,ref } from 'vue'
import { onMounted,ref,provide } from 'vue'
import { storeToRefs } from 'pinia'
import { useScreenStore, useMainStore, useSnapshotStore } from '@/store'
import { LOCALSTORAGE_KEY_DISCARDED_DB } from '@/configs/storage'
import { deleteDiscardedDB } from '@/utils/database'
import { isPC, query } from './utils/common'
import { userStore } from './store/user'
import { injectKeyTemplate } from '@/types/injectKey'
import Editor from './views/Editor/index.vue'
import Screen from './views/Screen/index.vue'
import Mobile from './views/Mobile/index.vue'
import Market from './views/Market/Index.vue'
import NewFile from './views/Market/newFile.vue'
const searchData = ref({} as any)
provide(injectKeyTemplate,searchData)
const isFinish = ref(false)
const _isPC = isPC()
const mainStore = useMainStore()
const snapshotStore = useSnapshotStore()
const modelStore = useScreenStore()
const ConfigIdStore = useScreenStore()
const { databaseId } = storeToRefs(mainStore)
const { screening, market, model, ConfigId } = storeToRefs(useScreenStore())
if (process.env.NODE_ENV === 'production') {
window.onbeforeunload = () => false
}
const userLoginHandler = async ()=>{
let param = query()
let userId = 1
let ConfigId = 0
let model = 1
if(param.uid) userId=parseInt(param.uid)
if(ConfigId) ConfigIdStore.setConfigId(ConfigId)
if(model) modelStore.setModel(model)
try {
await userStore().setUserLoginAsync(userId)
} catch (error) {
......@@ -37,17 +59,6 @@ const userLoginHandler = async ()=>{
}
userLoginHandler()
const _isPC = isPC()
const mainStore = useMainStore()
const snapshotStore = useSnapshotStore()
const { databaseId } = storeToRefs(mainStore)
const { screening, market } = storeToRefs(useScreenStore())
if (process.env.NODE_ENV === 'production') {
window.onbeforeunload = () => false
}
onMounted(async () => {
await deleteDiscardedDB()
snapshotStore.initSnapshotDatabase()
......
......@@ -263,6 +263,9 @@ page {
.q-pt-md{
padding-top: 12px;
}
.q-pb-md{
padding-bottom: 10px;
}
.q-ma-lg{
margin:20px
}
......@@ -278,6 +281,9 @@ page {
.q-mt-lg{
margin-top:20px
}
.q-mb-md{
margin-bottom:10px
}
.q-mb-lg{
margin-bottom:20px
}
......@@ -308,4 +314,7 @@ page {
}
.text-light{
font-weight: 300;
}
.text-nowrap{
white-space: nowrap;
}
\ No newline at end of file
......@@ -65,7 +65,7 @@ const getErrorCode2text = (response: AxiosResponse): string => {
* service.get<{data: string; code: number}>('/test').then(({data}) => { console.log(data.code) })
*/
const service = Axios.create({
baseURL: 'http://192.168.10.160/api/common/post',
baseURL: 'http://192.168.10.214/api/common/post',
timeout: 20000,
headers: {
'User-Type': 'bus',
......
......@@ -5,7 +5,7 @@ import { saveAs } from 'file-saver'
import pptxgen from 'pptxgenjs'
import tinycolor from 'tinycolor2'
import { toPng, toJpeg } from 'html-to-image'
import { useSlidesStore } from '@/store'
import { useSlidesStore, useScreenStore } from '@/store'
import type { PPTElementOutline, PPTElementShadow, PPTElementLink, Slide } from '@/types/slides'
import { getElementRange, getLineElementPath, getTableSubThemeColor } from '@/utils/element'
import { type AST, toAST } from '@/utils/htmlParser'
......@@ -25,18 +25,18 @@ interface ExportImageConfig {
export default () => {
const slidesStore = useSlidesStore()
const coverImgStore = useScreenStore()
const isCoverImgStore = useScreenStore()
const { slides, theme, viewportRatio, title } = storeToRefs(slidesStore)
const { isCoverImg } = storeToRefs(useScreenStore())
const exporting = ref(false)
// 导出图片
const exportImage = (domRef: HTMLElement, format: string, quality: number, ignoreWebfont = true) => {
exporting.value = true
const toImage = format === 'png' ? toPng : toJpeg
const foreignObjectSpans = domRef.querySelectorAll('foreignObject [xmlns]')
foreignObjectSpans.forEach(spanRef => spanRef.removeAttribute('xmlns'))
setTimeout(() => {
const config: ExportImageConfig = {
quality,
......@@ -47,7 +47,12 @@ export default () => {
toImage(domRef, config).then(dataUrl => {
exporting.value = false
saveAs(dataUrl, `${title.value}.${format}`)
if (isCoverImg.value) {
coverImgStore.setCoverImg(dataUrl)
isCoverImgStore.setIsCoverImg(false)
} else {
saveAs(dataUrl, `${title.value}.${format}`)
}
}).catch(() => {
exporting.value = false
message.error('导出图片失败')
......
......@@ -120,6 +120,7 @@ export default () => {
id: nanoid(10),
elements: [],
background,
pageType: 1
}
const parseElements = (elements: Element[]) => {
......
......@@ -35,6 +35,7 @@ export default () => {
type: 'solid',
color: theme.value.backgroundColor,
},
pageType: 1
}
slidesStore.updateSlideIndex(0)
mainStore.setActiveElementIdList([])
......@@ -84,6 +85,7 @@ export default () => {
type: 'solid',
color: theme.value.backgroundColor,
},
pageType: 1,
}
mainStore.setActiveElementIdList([])
slidesStore.addSlide(emptySlide)
......
......@@ -3,6 +3,9 @@ import { createPinia } from 'pinia'
import App from './App.vue'
import './registerServiceWorker'
import { ElMessage, ElMessageBox } from 'element-plus'
import 'element-plus/dist/index.css'
import '@icon-park/vue-next/styles/index.css'
import 'prosemirror-view/style/prosemirror.css'
import 'animate.css'
......
......@@ -5,6 +5,7 @@ import type { Slide } from '@/types/slides'
export const layouts: Slide[] = [
{
id: 'template',
pageType: 1,
elements: [
{
type: 'shape',
......@@ -80,6 +81,7 @@ export const layouts: Slide[] = [
},
{
id: 'template',
pageType: 2,
elements: [
{
type: 'text',
......@@ -139,6 +141,7 @@ export const layouts: Slide[] = [
},
{
id: 'template',
pageType: 3,
elements: [
{
type: 'shape',
......@@ -188,6 +191,7 @@ export const layouts: Slide[] = [
},
{
id: 'MZVO1kkj',
pageType: 4,
elements: [
{
type: 'shape',
......@@ -273,6 +277,7 @@ export const layouts: Slide[] = [
},
{
id: 'template',
pageType: 4,
elements: [
{
type: 'shape',
......@@ -457,6 +462,7 @@ export const layouts: Slide[] = [
},
{
id: 'template',
pageType: 4,
elements: [
{
type: 'shape',
......@@ -510,6 +516,7 @@ export const layouts: Slide[] = [
},
{
id: 'template',
pageType: 1,
elements: [
{
type: 'text',
......@@ -573,6 +580,7 @@ export const layouts: Slide[] = [
},
{
id: 'template',
pageType: 1,
elements: [
{
type: 'text',
......@@ -690,6 +698,7 @@ export const layouts: Slide[] = [
},
{
id: 'template',
pageType: 1,
elements: [
{
type: 'text',
......@@ -766,6 +775,7 @@ export const layouts: Slide[] = [
},
{
id: 'template',
pageType: 1,
elements: [
{
type: 'shape',
......
import type { Slide } from '@/types/slides'
// pageType 1基础 2酒店 3景 4餐
export const slides: Slide[] = [
{
id: 'test-slide-1',
pageType: 1,
elements: [
{
type: 'shape',
......@@ -77,6 +79,7 @@ export const slides: Slide[] = [
},
{
id: 'test-slide-2',
pageType: 2,
elements: [
{
type: 'text',
......@@ -136,6 +139,7 @@ export const slides: Slide[] = [
},
{
id: 'test-slide-3',
pageType: 3,
elements: [
{
type: 'shape',
......
......@@ -96,7 +96,9 @@ import {
ListView,
Magic,
HighLight,
Upload,
Download,
Check,
IndentLeft,
IndentRight,
VerticalSpacingBetweenItems,
......@@ -221,7 +223,9 @@ export const icons: Icons = {
IconListView: ListView,
IconMagic: Magic,
IconHighLight: HighLight,
IconUpload: Upload,
IconDownload: Download,
IconCheck: Check,
IconIndentLeft: IndentLeft,
IconIndentRight: IndentRight,
IconVerticalSpacingBetweenItems: VerticalSpacingBetweenItems,
......
import Api,{ HttpResponse, Result } from './../utils/request';
/**
* 配置相关方法
*/
class ConfigService{
/**
* 根据ConfigId获取行程配置相关数据
*/
static async triptemplateGetTripFiledData(params : any):Promise<HttpResponse>{
return Api.Post("triptemplate_GetTripFiledData",params)
}
/**
* 根据团期配置编号获取行程详情
*/
static async triptemplateGetTripConfig(params : any):Promise<HttpResponse>{
return Api.Post("triptemplate_GetTripConfig",params)
}
/**
* 新增修改模版数据
*/
static async SetSetTripConfig(params : any):Promise<HttpResponse>{
return Api.Post("triptemplate_SetTripConfig",params)
}
/**
* 新增修改模版
*/
static async SetTripTemplateSlide(params : any):Promise<HttpResponse>{
return Api.Post("triptemplate_SetTripTemplate",params)
}
/**
* 根据TempId获取模版数据
*/
static async GetTripTemplateSlide(params : any):Promise<HttpResponse>{
return Api.Post("triptemplate_GetTripTemplate",params)
}
/**
* 获取绑定数据源列表
*/
static async TemplateGetTripFiled(params : any):Promise<HttpResponse>{
return Api.Post("triptemplate_GetTripFiled",params)
}
/**
*
* @returns 获取模板查询条件
*/
static async GetTemplateQueryAsync():Promise<HttpResponse>{
return Api.Post("triptemplate_GetTemplateConfigData",{})
}
/**
* 获取模板市场分页列表
*/
static async GetTemplagePageAsync(params : any):Promise<HttpResponse>{
return Api.Post("triptemplate_GetTripTemplatePage",params)
}
}
export default ConfigService;
\ No newline at end of file
......@@ -2,7 +2,17 @@ import Api,{ HttpResponse, Result } from './../utils/request';
class LineService{
// 获取配置项数据(颜色、国家、季节)
static async GetTemplateConfigData(params : any):Promise<HttpResponse>{
return Api.Post("triptemplate_GetTemplateConfigData",params)
}
// 系列
static async GetSeriesListAsync(params : any):Promise<HttpResponse>{
return Api.Post("team_post_GetList",params)
}
// 线路
static async GetLineListAsync():Promise<HttpResponse>{
return Api.Post("line_post_GetAllList",{})
}
......
......@@ -59,7 +59,7 @@ export const useMainStore = defineStore('main', {
creatingElement: null, // 正在插入的元素信息,需要通过绘制插入的元素(文字、形状、线条)
creatingCustomShape: false, // 正在绘制任意多边形
availableFonts: SYS_FONTS, // 当前环境可用字体
toolbarState: ToolbarStates.SLIDE_DESIGN, // 右侧工具栏状态
toolbarState: ToolbarStates.SLIDE_DESIGN, // 右侧工具栏状态 设计 模版数据EL_TEMPLATEDATA
clipingImageElementId: '', // 当前正在裁剪的图片ID
richTextAttrs: defaultRichTextAttrs, // 富文本状态
selectedTableCells: [], // 选中的表格单元格
......
import { fa } from 'element-plus/es/locale'
import { defineStore } from 'pinia'
export interface ScreenState {
screening: boolean,
market:boolean
market:boolean,
model:number,
isModel: boolean,
ConfigId:number,
TemplateType: [],
TemplateDataSource: [],
CoverImg: any,
isCoverImg: boolean,
dataLoading: boolean,
}
export const useScreenStore = defineStore('screen', {
state: (): ScreenState => ({
screening: false, // 是否进入放映状态
market: true
market: true,
model: 0, // 是否有新增修改模版权限
isModel: false, // 该团是否存在模版
ConfigId: 0,
TemplateType: [], // 数据源分类
TemplateDataSource: [], // 所有数据源
CoverImg: null, // 封面图
isCoverImg: false, // 封面
dataLoading: false, // 记录保存是否成功
}),
actions: {
......@@ -18,8 +35,32 @@ export const useScreenStore = defineStore('screen', {
this.market = false
}
},
setMarket(market: boolean){
setMarket(market: boolean) {
this.market = market
},
setModel(model: number) {
this.model = model
},
setIsModel(isModel: boolean) {
this.isModel = isModel
},
setConfigId(ConfigId: number) {
this.ConfigId = ConfigId
},
setTemplateType(TemplateType: []) {
this.TemplateType = TemplateType
},
setCoverImg(CoverImg: any) {
this.CoverImg = CoverImg
},
setIsCoverImg(isCoverImg: boolean) {
this.isCoverImg = isCoverImg
},
setTemplateDataSource(TemplateDataSource: []) {
this.TemplateDataSource = TemplateDataSource
},
setDataLoading(dataLoading: boolean) {
this.dataLoading = dataLoading
}
},
})
\ No newline at end of file
......@@ -28,6 +28,7 @@ export interface SlidesState {
slides: Slide[]
slideIndex: number
viewportRatio: number
layoutSlides: Slide[]
}
export const useSlidesStore = defineStore('slides', {
......@@ -36,7 +37,8 @@ export const useSlidesStore = defineStore('slides', {
theme: theme, // 主题样式
slides: slides, // 幻灯片页面数据
slideIndex: 0, // 当前页面索引
viewportRatio: 0.5625, // 可视区域比例,默认16:9
viewportRatio: 0.75, // 可视区域比例,默认16:9 0.5625
layoutSlides: slides, // 所有模版数据
}),
getters: {
......@@ -92,10 +94,9 @@ export const useSlidesStore = defineStore('slides', {
fontName,
backgroundColor,
} = state.theme
const subColor = tinycolor(fontColor).isDark() ? 'rgba(230, 230, 230, 0.5)' : 'rgba(180, 180, 180, 0.5)'
const layoutsString = JSON.stringify(layouts)
console.log('layouts,--------')
const layoutsString = JSON.stringify(state.layoutSlides)
.replaceAll('{{themeColor}}', themeColor)
.replaceAll('{{fontColor}}', fontColor)
.replaceAll('{{fontName}}', fontName)
......@@ -123,6 +124,10 @@ export const useSlidesStore = defineStore('slides', {
setSlides(slides: Slide[]) {
this.slides = slides
},
setLayouts(layoutSlides: Slide[]) {
this.layoutSlides = layoutSlides
},
addSlide(slide: Slide | Slide[]) {
const slides = Array.isArray(slide) ? slide : [slide]
......
......@@ -6,7 +6,9 @@ export type RadioGroupValue = {
value: Ref<string>
updateValue: (value: string) => void
}
export type SlideDataSource = Ref<object>
export const injectKeySlideScale: InjectionKey<SlideScale> = Symbol()
export const injectKeySlideId: InjectionKey<SlideId> = Symbol()
export const injectKeyRadioGroupValue: InjectionKey<RadioGroupValue> = Symbol()
\ No newline at end of file
export const injectKeyRadioGroupValue: InjectionKey<RadioGroupValue> = Symbol()
export const injectKeyDataSource: InjectionKey<SlideDataSource> = Symbol()
export const injectKeyTemplate: InjectionKey<SlideDataSource> = Symbol()
\ No newline at end of file
......@@ -676,6 +676,7 @@ export interface Slide {
background?: SlideBackground
animations?: PPTAnimation[]
turningMode?: TurningMode
pageType: number
}
/**
......
export const enum ToolbarStates {
SYMBOL = 'symbol',
EL_ANIMATION = 'elAnimation',
EL_TEMPLATEDATA = 'elTemplateData',
EL_STYLE = 'elStyle',
EL_POSITION = 'elPosition',
SLIDE_DESIGN = 'slideDesign',
......
......@@ -26,4 +26,17 @@ export const query = (url?:string)=>{
json[item[0]] = item[1]
}
return json
}
/**
* 提取字符串中的文字
*/
export const getHtmlPlainText = (html_str:string) => {
let re = new RegExp('<[^<>]+>', 'g')
if (html_str) {
let text = html_str.replace(re, '')
return text
} else {
return ''
}
}
\ No newline at end of file
......@@ -22,7 +22,7 @@
width: viewportStyles.width * canvasScale + 'px',
height: viewportStyles.height * canvasScale + 'px',
left: viewportStyles.left + 'px',
top: viewportStyles.top + 'px',
top: viewportStyles.top-20 + 'px',
}"
>
<div class="operates">
......@@ -168,7 +168,7 @@ watch(handleElementId, () => {
const elementList = ref<PPTElement[]>([])
const setLocalElementList = () => {
elementList.value = currentSlide.value ? JSON.parse(JSON.stringify(currentSlide.value.elements)) : []
elementList.value = currentSlide.value&&currentSlide.value.elements ? JSON.parse(JSON.stringify(currentSlide.value.elements)) : []
}
watchEffect(setLocalElementList)
......
......@@ -51,7 +51,7 @@
<IconInsertTable class="handler-item" v-tooltip="'插入表格'" />
</Popover>
<IconFormula class="handler-item" v-tooltip="'插入公式'" @click="latexEditorVisible = true" />
<Popover trigger="click" v-model:value="mediaInputVisible">
<!-- <Popover trigger="click" v-model:value="mediaInputVisible">
<template #content>
<MediaInput
@close="mediaInputVisible = false"
......@@ -60,7 +60,7 @@
/>
</template>
<IconVideoTwo class="handler-item" v-tooltip="'插入音视频'" />
</Popover>
</Popover> -->
</div>
<div class="right-handler">
......
<template>
<div v-if="datas.DataSource.DataSourceOverlay">
<div class="DataaSourceOverlay" @click="OffDataSource"></div>
<div class="DataaSource">
<div class="DataaSourceList">
<el-table
:data="datas.DataSource.DataSourceList"
style="width: 100%"
border
>
<el-table-column
prop=""
label="基础数据">
<template #default="scope">
<div class="DataaSourceL">
<div v-if="scope.row.type=='text'">
{{scope.row.FiledTypeStr}}
</div>
<div v-if="scope.row.type=='image'">
<img style="width: 20px; height: 20px"
:src="scope.row.FiledTypeStr" />
</div>
</div>
</template>
</el-table-column>
<el-table-column
prop=""
label="绑定数据源"
width="170">
<template #default="scope">
<div class="DataaSourceR" v-if="scope.row.TemplateList">
<el-select v-model="scope.row.TemplateDataSource.Id" class="m-2"
placeholder="请绑定数据源"
@change="setTemplateDataSource(scope.row.TemplateDataSource.Id,scope.$index)">
<!-- :disabled="scope.row.type=='image'&&item.Name.indexOf('图')==-1" -->
<el-option
v-for="item in setType(scope.row)"
:key="item.Id"
:label="item.Name"
:value="item.Id"/>
</el-select>
</div>
</template>
</el-table-column>
</el-table>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, nextTick, ref, watch, reactive, inject } from 'vue'
import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store'
import { injectKeyDataSource } from '@/types/injectKey'
import { getHtmlPlainText } from '@/utils/common'
const datas = reactive({
DataSource:{},
})
datas.DataSource = inject(injectKeyDataSource)
const slidesStore = useSlidesStore()
const { slides, slideIndex } = storeToRefs(slidesStore)
const setType = (x) =>{
if(x.type=="image"){
return x.TemplateList.filter(item=>{ return item.Name.indexOf('图')!=-1})
}if(x.type=="text"){
return x.TemplateList.filter(item=>{ return item.Name.indexOf('图')==-1})
}
}
const setNewDatas = () => {
const slidesData = slides.value
// 更新Slides数据
const savelides = []
const newSlides = []
let obj = slidesData.find((x,index)=>{
return slideIndex.value == index
})
if(obj){
obj.elements.forEach(x=>{
let dataObj = datas.DataSource.DataSourceList.find(y=>{
return y.id == x.id
})
if(dataObj){
x = dataObj
}
savelides.push(x)
})
obj.elements = JSON.parse(JSON.stringify(savelides))
slidesData.forEach((x,index)=>{
if(slideIndex.value == index){
x.pgaeType = datas.DataSource.pgaeType
x.elements = obj.elements
}
newSlides.push(x)
})
slidesStore.setSlides(JSON.parse(JSON.stringify(newSlides)))
}
}
// 数据源关键数据赋值
const setTemplateDataSource = (Id,index) => {
datas.DataSource.DataSourceList.forEach((x,indexs)=>{
if(index==indexs){
let obj = x.TemplateList.find(y=>{
return y.Id==x.TemplateDataSource.Id
})
x.TemplateDataSource.Content = obj.Content
x.TemplateDataSource.Name = obj.Name
if(x.type=="text"){
x.FiledTypeStr = obj.Name
x.content = x.content.replace(getHtmlPlainText(x.content),obj.Name)
}
}
})
setNewDatas()
}
const OffDataSource = () =>{
datas.DataSource.DataSourceOverlay = !datas.DataSource.DataSourceOverlay
}
</script>
<style lang="scss" scoped>
.DataaSourceOverlay{
position: fixed;
left: 160px;
top: 80px;
right: 260px;
bottom: 0;
z-index: 1;
background: rgba(23,23,23,0.5);
cursor: pointer;
}
.DataaSource{
position: fixed;
left: 200px;
top: 120px;
right: 300px;
bottom: 30px;
z-index: 2;
padding: 40px;
border-radius: 10px;
background: #fff;
}
.DataaSourceList{
height: 100%;
border: 1px solid #ebeef5;
padding: 20px;
border-radius: 5px;
overflow: auto;
}
.DataaSourceL{
font-weight: bold;
color: black;
font-size: 14px;
}
</style>
\ No newline at end of file
<template>
<div class="editor-header">
<div class="left">
<div class="menu-item" v-tooltip="'去首页'" @click="goBack()">首页</div>
<Popover trigger="click" placement="bottom-start" v-model:value="mainMenuVisible">
<template #content>
<FileInput accept=".pptist" @change="files => {
......@@ -28,21 +29,21 @@
<Input
class="title-input"
ref="titleInputRef"
v-model:value="titleValue"
v-model:value="queryObj.Title"
@blur="handleUpdateTitle()"
v-if="editingTitle"
></Input>
<div
class="title-text"
@click="startEditTitle()"
:title="title"
:title="queryObj.Title"
v-else
>{{ title }}</div>
>{{ queryObj.Title }}</div>
</div>
</div>
<div class="right">
<div class="group-menu-item">
<!-- <div class="group-menu-item">
<div class="menu-item" v-tooltip="'幻灯片放映'" @click="enterScreening()">
<IconPpt class="icon" />
</div>
......@@ -53,13 +54,21 @@
</template>
<div class="arrow-btn"><IconDown class="arrow" /></div>
</Popover>
</div> -->
<div class="group-menu-item" v-if="userInfo.IsEditTripTemplate==1&&model">
<div class="menu-item" v-tooltip="'导入PSD'" @click="UploadPsd()">
<IconUpload class="icon" />
</div>
</div>
<div class="menu-item" v-tooltip="'导出'" @click="setDialogForExport('pptx')">
<IconDownload class="icon" />
</div>
<a class="github-link" href="https://github.com/pipipi-pikachu/PPTist" target="_blank">
<el-button v-tooltip="'保存'" type="danger"
size="small" icon="Check" circle :loading="datas.loading"
@click="setTemplate()" style="color: #ffff;"></el-button>
<!-- <a class="github-link" href="https://github.com/pipipi-pikachu/PPTist" target="_blank">
<div class="menu-item"><IconGithub class="icon" /></div>
</a>
</a> -->
</div>
<Drawer
......@@ -75,13 +84,18 @@
</template>
<script lang="ts" setup>
import { nextTick, ref } from 'vue'
import { nextTick, ref, reactive, inject } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import useScreening from '@/hooks/useScreening'
import useImport from '@/hooks/useImport'
import useSlideHandler from '@/hooks/useSlideHandler'
import type { DialogForExportTypes } from '@/types/export'
import { userStore } from "@/store/user";
import { useScreenStore } from "@/store/screen";
import ConfigService from '@/services/ConfigService'
import { injectKeyDataSource, injectKeyTemplate } from '@/types/injectKey'
import { svg2Base64 } from '@/utils/svg2Base64'
import HotkeyDoc from './HotkeyDoc.vue'
import FileInput from '@/components/FileInput.vue'
......@@ -93,7 +107,8 @@ import PopoverMenuItem from '@/components/PopoverMenuItem.vue'
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const { title } = storeToRefs(slidesStore)
const layoutsStore = useSlidesStore()
const { title, slides } = storeToRefs(slidesStore)
const { enterScreening, enterScreeningFromStart } = useScreening()
const { importSpecificFile, importPPTXFile, exporting } = useImport()
const { resetSlides } = useSlideHandler()
......@@ -104,6 +119,165 @@ const editingTitle = ref(false)
const titleInputRef = ref<InstanceType<typeof Input>>()
const titleValue = ref('')
const { userInfo } = storeToRefs(userStore())
const datas = reactive({
DataSource:{},
loading: false
})
const queryObj = ref({} as any)
const searchData = ref({} as any)
datas.DataSource = inject(injectKeyDataSource)
queryObj.value = inject(injectKeyDataSource).queryObj
searchData.value = inject(injectKeyTemplate)
const marketStore = useScreenStore()
const CoverImgStore = useScreenStore()
const dataLoadingStore = useScreenStore()
const { market, model, ConfigId, CoverImg, dataLoading } = storeToRefs(useScreenStore())
// 返回到首页
const goBack = () =>{
let list = [
{
id: 'test-slide-1',
pageType: 1,
elements: [],
background: {
type: 'solid',
color: '#ffffff',
},
}
]
if(model.value) {
searchData.value.TempId = 0
marketStore.setMarket(true)
slidesStore.setSlides(list)
layoutsStore.setLayouts([])
CoverImgStore.setCoverImg(null)
return
}
ElMessageBox.confirm(
'退出此页面将清空当前数据,请谨慎操作?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
searchData.value.TempId = 0
marketStore.setMarket(true)
slidesStore.setSlides(list)
layoutsStore.setLayouts([])
CoverImgStore.setCoverImg(null)
})
.catch(() => {
})
}
// 导入PSD
const UploadPsd = () => {
}
// 新增修改模版
const SetTripTemplateSlide = async () => {
// console.log(JSON.parse(queryObj.value.TempData),'--------')
try {
console.log(queryObj.value,'新增修改模版---')
let TemplateRes = await ConfigService.SetTripTemplateSlide(queryObj.value);
if (TemplateRes.data.resultCode == 1) {
}
dataLoadingStore.setDataLoading(true)
datas.loading = false
} catch (error) {
datas.loading = false
console.log("TemplateGetTripFiled", error);
}
}
// 用户新增修改数据
const SetTripTemplateConfig = async () => {
try {
let queryMsg = {
ConfigId: ConfigId.value,
TempId: queryObj.value.TempId,
TempData: queryObj.value.TempData
}
console.log(queryMsg,'新增修改团数据---')
let TemplateRes = await ConfigService.SetSetTripConfig(queryMsg);
if (TemplateRes.data.resultCode == 1) {
}
dataLoadingStore.setDataLoading(true)
datas.loading = false
} catch (error) {
datas.loading = false
console.log("TemplateGetTripFiled", error);
}
}
// 保存
const setTemplate = async () =>{
if(dataLoading.value){
dataLoadingStore.setDataLoading(false)
}
// console.log(JSON.stringify(slides.value),'----保存接口',queryObj.value)
if(model.value&&userInfo.value.IsEditTripTemplate==1){
if(CoverImg&&CoverImg.value) queryObj.value.CoverImg = CoverImg.value
else return ElMessage({
showClose: true,
message: '请生成封面图',
type: 'warning',
})
if(queryObj.value.Title==''||!queryObj.value.LineId||!queryObj.value.LtId
||queryObj.value.CoverImg==''
||queryObj.value.CountryName==''||queryObj.value.SeasonName==''
||queryObj.value.ColorName==''||queryObj.value.ColorStr==''||queryObj.value.LineName==''){
return ElMessage({
showClose: true,
message: '请完善右侧模版数据',
type: 'warning',
})
}
}
for(let i=0;i<slides.value.length;i++){
if(slides.value[i].elements.length==0) {
return ElMessage({
showClose: true,
message: `请设计 第 ${i+1} 页 的数据`,
type: 'warning',
})
}
// for(let j=0;j<slides.value[i].elements.length;j++){
// if(model.value&&userInfo.value.IsEditTripTemplate==1){
// if(slides.value[i].elements[j].type=="text"||slides.value[i].elements[j].type=="image"){
// if(!slides.value[i].elements[j].TemplateDataSource
// ||!slides.value[i].elements[j].TemplateDataSource.Id) {
// return ElMessage({
// showClose: true,
// message: `请完善 第 ${i+1} 页 需要绑定的数据源`,
// type: 'warning',
// })
// }
// }
// }
// }
}
queryObj.value.TempData = JSON.stringify(slides.value)
datas.loading = true
if(model.value&&userInfo.value.IsEditTripTemplate==1){
await SetTripTemplateSlide()
}else if(ConfigId.value){
await SetTripTemplateConfig()
}
}
const startEditTitle = () => {
titleValue.value = title.value
editingTitle.value = true
......
......@@ -13,7 +13,7 @@
</div>
<div class="configs">
<div class="row">
<div class="title">导出格式:</div>
<div class="title">{{isCoverImg?'生成格式:':'导出格式:'}}</div>
<RadioGroup
class="config-item"
v-model:value="format"
......@@ -23,7 +23,7 @@
</RadioGroup>
</div>
<div class="row">
<div class="title">导出范围:</div>
<div class="title">{{isCoverImg?'生成范围:':'导出范围:'}}</div>
<RadioGroup
class="config-item"
v-model:value="rangeType"
......@@ -65,18 +65,19 @@
</div>
<div class="btns">
<Button class="btn export" type="primary" @click="expImage()">导出图片</Button>
<Button class="btn export" type="primary" @click="expImage()">
{{isCoverImg?'生成封面':'导出图片'}}</Button>
<Button class="btn close" @click="emit('close')">关闭</Button>
</div>
<FullscreenSpin :loading="exporting" tip="正在导出..." />
<FullscreenSpin :loading="exporting" :tip="isCoverImg?'正在生成...':'正在导出...'" />
</div>
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue'
import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store'
import { useSlidesStore, useScreenStore } from '@/store'
import useExport from '@/hooks/useExport'
import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'
......@@ -92,13 +93,15 @@ const emit = defineEmits<{
}>()
const { slides, currentSlide } = storeToRefs(useSlidesStore())
const { isCoverImg } = storeToRefs(useScreenStore())
const imageThumbnailsRef = ref<HTMLElement>()
const rangeType = ref<'all' | 'current' | 'custom'>('all')
const rangeType = ref<'all' | 'current' | 'custom'>('current')
const range = ref<[number, number]>([1, slides.value.length])
const format = ref<'jpeg' | 'png'>('jpeg')
const quality = ref(1)
const ignoreWebfont = ref(true)
const ignoreWebfont = ref(false) //开启在线字体
const renderSlides = computed(() => {
if (rangeType.value === 'all') return slides.value
......
......@@ -7,7 +7,7 @@
@update:value="key => setDialogForExport(key as DialogForExportTypes)"
/>
<div class="content">
<component :is="currentDialogComponent" @close="setDialogForExport('')"></component>
<component :is="currentDialogComponent" @close="setDialogForExport(''),setDialogIsCoverImg()"></component>
</div>
</div>
</template>
......@@ -15,7 +15,7 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { useMainStore, useScreenStore } from '@/store'
import type { DialogForExportTypes } from '@/types/export'
import ExportImage from './ExportImage.vue'
......@@ -30,11 +30,17 @@ interface TabItem {
label: string
}
const isCoverImgStore = useScreenStore()
const mainStore = useMainStore()
const { dialogForExport } = storeToRefs(mainStore)
const { isCoverImg } = storeToRefs(isCoverImgStore)
const setDialogForExport = mainStore.setDialogForExport
const setDialogIsCoverImg = () => {
isCoverImgStore.setIsCoverImg(false)
}
const tabs: TabItem[] = [
{ key: 'pptist', label: '导出 pptist 文件' },
{ key: 'pptx', label: '导出 PPTX' },
......@@ -51,8 +57,8 @@ const currentDialogComponent = computed<unknown>(() => {
'pptx': ExportPPTX,
'pptist': ExportSpecificFile,
}
if (dialogForExport.value) return dialogMap[dialogForExport.value] || null
return null
if (dialogForExport.value) return dialogMap[dialogForExport.value] || isCoverImgStore.setIsCoverImg(false)
return isCoverImgStore.setIsCoverImg(false)
})
</script>
......
......@@ -23,7 +23,6 @@ const emit = defineEmits<{
}>()
const { layouts } = storeToRefs(useSlidesStore())
const selectSlideTemplate = (slide: Slide) => {
emit('select', slide)
}
......
......@@ -11,7 +11,7 @@
<template #content>
<LayoutPool @select="slide => { createSlideByTemplate(slide); presetLayoutPopoverVisible = false }" />
</template>
<div class="select-btn"><IconDown /></div>
<div class="select-btn" v-if="layoutSlides.length>0"><IconDown /></div>
</Popover>
</div>
......@@ -47,30 +47,36 @@
</template>
<script lang="ts" setup>
import { computed, nextTick, ref, watch } from 'vue'
import { computed, nextTick, ref, reactive, watch, inject } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore, useKeyboardStore } from '@/store'
import { useMainStore, useSlidesStore, useKeyboardStore, useScreenStore } from '@/store'
import { fillDigit } from '@/utils/common'
import { isElementInViewport } from '@/utils/element'
import type { ContextmenuItem } from '@/components/Contextmenu/types'
import useSlideHandler from '@/hooks/useSlideHandler'
import useScreening from '@/hooks/useScreening'
import useLoadSlides from '@/hooks/useLoadSlides'
import { injectKeyDataSource, injectKeyTemplate } from '@/types/injectKey'
import ConfigService from '@/services/ConfigService'
import { getHtmlPlainText } from '@/utils/common'
import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'
import LayoutPool from './LayoutPool.vue'
import Popover from '@/components/Popover.vue'
import Draggable from 'vuedraggable'
const mainStore = useMainStore()
const slidesStore = useSlidesStore()
const layoutsStore = useSlidesStore()
const keyboardStore = useKeyboardStore()
const { selectedSlidesIndex: _selectedSlidesIndex, thumbnailsFocus } = storeToRefs(mainStore)
const { slides, slideIndex } = storeToRefs(slidesStore)
const { slides, slideIndex, layoutSlides } = storeToRefs(slidesStore)
const { ctrlKeyState, shiftKeyState } = storeToRefs(keyboardStore)
const { slidesLoadLimit } = useLoadSlides()
const TemplateTypeStore = useScreenStore()
const CoverImgStore = useScreenStore()
const dataLoadingStore = useScreenStore()
const { ConfigId, TemplateDataSource, TemplateType, dataLoading } = storeToRefs(TemplateTypeStore)
const selectedSlidesIndex = computed(() => [..._selectedSlidesIndex.value, slideIndex.value])
const presetLayoutPopoverVisible = ref(false)
......@@ -87,10 +93,15 @@ const {
sortSlides,
} = useSlideHandler()
// 页面被切换时
const thumbnailsRef = ref<InstanceType<typeof Draggable>>()
watch(() => slideIndex.value, () => {
const datas = reactive({
DataSource:{}
})
const queryObj = ref({} as any)
const searchData = ref({} as any)
datas.DataSource = inject(injectKeyDataSource)
searchData.value = inject(injectKeyTemplate)
watch(() => slideIndex.value, () => {
// 清除多选状态的幻灯片
if (selectedSlidesIndex.value.length) {
mainStore.updateSelectedSlidesIndex([])
......@@ -107,10 +118,169 @@ watch(() => slideIndex.value, () => {
})
})
// 监听请求保存成功 重新请求数据
watch(() => dataLoading.value, (n,o) =>{
if(n!=o&&n){
GetTripTemplate()
}
})
queryObj.value = inject(injectKeyDataSource).queryObj
// 获取行程团数据
const GetTripFiledData = async (status) =>{
if(queryObj.value.TempId&&!status) return
const slidesData = slides.value
try {
let queryMsg = {
ConfigId: ConfigId.value
}
let dataRes = await ConfigService.triptemplateGetTripFiledData(queryMsg);
if (dataRes.data.resultCode == 1) {
if(!dataRes.data.data) return
const travel = dataRes.data.data
const cursors = [] as Array<any>
slidesData.forEach((x,index)=>{
x.elements.forEach(y=>{
if(y.TemplateDataSource && y.TemplateDataSource.Content){
let dataPath = y.TemplateDataSource.Content.split('.')
let value=JSON.parse(JSON.stringify(travel));
dataPath.forEach((oo,i)=>{
if(value && value[oo]){
if(i==0 && Array.isArray(value[oo])){
let temp = cursors.find(item=>item.key==oo)
if(temp){
temp.index++
}else{
temp={key:oo,index:0}
cursors.push(temp)
}
if(value[oo].length>temp.index) value=value[oo][temp.index]
else value=value[oo]
}else{
value=value[oo]
}
}else{
value = null
}
})
if(value && typeof(value) == 'string'){
//替换
y.content= y.content.replace(getHtmlPlainText(y.content),value)
}else if(value && Array.isArray(value)){
//替换
y.content=value[0]
}
}
})
})
slidesStore.setSlides(slidesData)
}
} catch (error) {
console.log("triptemplateGetTripFiledData", error);
}
}
// 获取行程模版数据
const GetTripTemplate = async () =>{
if(!queryObj.value.TempId) {
let list = [
{
id: 'test-slide-1',
pageType: 1,
elements: [],
background: {
type: 'solid',
color: '#ffffff',
},
}
]
return slidesStore.setSlides(list)
}
try {
let queryMsg = {
TempId:queryObj.value.TempId
}
let dataRes = await ConfigService.GetTripTemplateSlide(queryMsg);
if (dataRes.data.resultCode == 1) {
let viewportRatio = 1.414
if(dataRes.data.data.TempType==1) viewportRatio = 0.75
slidesStore.setViewportRatio(viewportRatio)
let SlidesData = JSON.parse(dataRes.data.data.TempData)
let newSlides = []
if(typeof SlidesData=='object'&&!SlidesData.length){
let obj = {
pageType: 1,
...SlidesData
}
newSlides.push(obj)
}else if(SlidesData.length>0){
newSlides = SlidesData
}
slidesStore.setSlides(newSlides)
layoutsStore.setLayouts(JSON.parse(JSON.stringify(newSlides)))
CoverImgStore.setCoverImg(dataRes.data.data.CoverImg)
queryObj.value.TempId = dataRes.data.data.TempId
queryObj.value.LineId = dataRes.data.data.LineId
queryObj.value.LineName = dataRes.data.data.LineName
queryObj.value.LtId = dataRes.data.data.LtId
queryObj.value.Title = dataRes.data.data.Title
queryObj.value.TempData = dataRes.data.data.TempData
queryObj.value.CoverImg = dataRes.data.data.CoverImg
queryObj.value.CountryName = dataRes.data.data.CountryName
queryObj.value.SeasonName = dataRes.data.data.SeasonName
queryObj.value.ColorName = dataRes.data.data.ColorName
queryObj.value.ColorStr = dataRes.data.data.ColorStr
queryObj.value.TempType = dataRes.data.data.TempType
if(ConfigId.value==0) return
await GetTripFiledData(1)
}
} catch (error) {
console.log("GetTripTemplateSlide", error);
}
}
// 页面被切换时
const thumbnailsRef = ref<InstanceType<typeof Draggable>>()
// 切换页面
const changeSlideIndex = (index: number) => {
mainStore.setActiveElementIdList([])
// 绑定数据源
const newElements = slides.value.find((slide,indexs) => {
return index==indexs
})
datas.DataSource.pageType = newElements.pageType
let TemplateList = TemplateDataSource.value.filter(x=>{
return x.FiledType==newElements.pageType
})
datas.DataSource.DataSourceList = []
newElements&&newElements.elements&&newElements.elements.forEach(slide=>{
if(slide.type=="text"||slide.type=="image") {
let FiledTypeStr
if(slide.type=="text") FiledTypeStr = getHtmlPlainText(slide.content)
if(slide.type=="image") FiledTypeStr = slide.src
let Obj = {}
Obj = {
...slide,
FiledTypeStr: FiledTypeStr,
TemplateList: TemplateList,
TemplateDataSource: {
Content: slide.TemplateDataSource&&slide.TemplateDataSource.Content?slide.TemplateDataSource.Content:'',
Name: slide.TemplateDataSource&&slide.TemplateDataSource.Name?slide.TemplateDataSource.Name:'',
Id: slide.TemplateDataSource&&slide.TemplateDataSource.Id?slide.TemplateDataSource.Id:null as Number
}
}
if(Obj){
datas.DataSource.DataSourceList.push(Obj)
}
}
})
if (slideIndex.value === index) return
slidesStore.updateSlideIndex(index)
}
......@@ -125,6 +295,7 @@ const handleClickSlideThumbnail = (e: MouseEvent, index: number) => {
// 如果被取消选中的页面刚好是当前激活页面,则需要从其他被选中的页面中选择第一个作为当前激活页面
if (ctrlKeyState.value) {
if (slideIndex.value === index) {
if (!isMultiSelected) return
const newSelectedSlidesIndex = selectedSlidesIndex.value.filter(item => item !== index)
......@@ -253,6 +424,8 @@ const contextmenusThumbnailItem = (): ContextmenuItem[] => {
},
]
}
GetTripTemplate()
</script>
<style lang="scss" scoped>
......
This diff is collapsed.
......@@ -99,12 +99,12 @@
<div class="row">
<Button style="flex: 1;" @click="applyBackgroundAllSlide()">应用背景到全部</Button>
</div>
<Divider />
<div class="row">
<div style="width: 40%;">画布尺寸:</div>
<Select
<!-- <Select
style="width: 60%;"
:value="viewportRatio"
@update:value="value => updateViewportRatio(value as number)"
......@@ -114,6 +114,15 @@
{ label: '标准 4 : 3', value: 0.75 },
{ label: '纸张 A3 / A4', value: 0.70710678 },
]"
/> -->
<Select
style="width: 60%;"
:value="viewportRatio"
@update:value="value => updateViewportRatio(value as number)"
:options="[
{ label: '横屏', value: 0.75 },
{ label: '竖屏', value: 1.414 },
]"
/>
</div>
......@@ -290,7 +299,7 @@
</template>
<script lang="ts" setup>
import { computed, ref } from 'vue'
import { computed, ref, reactive,inject } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore } from '@/store'
import type { SlideBackground, SlideTheme } from '@/types/slides'
......@@ -299,6 +308,7 @@ import { WEB_FONTS } from '@/configs/font'
import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import useSlideTheme from '@/hooks/useSlideTheme'
import { getImageDataURL } from '@/utils/image'
import { injectKeyDataSource } from '@/types/injectKey'
import ColorButton from './common/ColorButton.vue'
import FileInput from '@/components/FileInput.vue'
......@@ -310,9 +320,17 @@ import Select from '@/components/Select.vue'
import Popover from '@/components/Popover.vue'
import NumberInput from '@/components/NumberInput.vue'
const datas = reactive({
DataSource:{
DataSourceOverlay: false
}
})
const queryObj = ref({} as any)
datas.DataSource = inject(injectKeyDataSource)
queryObj.value = inject(injectKeyDataSource).queryObj
const slidesStore = useSlidesStore()
const { availableFonts } = storeToRefs(useMainStore())
const { slides, currentSlide, viewportRatio, theme } = storeToRefs(slidesStore)
const { slides, currentSlide, viewportRatio, theme, slideIndex } = storeToRefs(slidesStore)
const moreThemeConfigsVisible = ref(false)
......@@ -390,6 +408,7 @@ const applyBackgroundAllSlide = () => {
addHistorySnapshot()
}
// 设置主题
const updateTheme = (themeProps: Partial<SlideTheme>) => {
slidesStore.setTheme(themeProps)
......@@ -397,6 +416,11 @@ const updateTheme = (themeProps: Partial<SlideTheme>) => {
// 设置画布尺寸(宽高比例)
const updateViewportRatio = (value: number) => {
if(value==0.75){
queryObj.value.TempType = 1
}else{
queryObj.value.TempType = 2
}
slidesStore.setViewportRatio(value)
}
</script>
......
......@@ -13,14 +13,16 @@
</template>
<script lang="ts" setup>
import { computed, watch } from 'vue'
import { ref, computed, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { useScreenStore } from '@/store'
import { ToolbarStates } from '@/types/toolbar'
import ElementStylePanel from './ElementStylePanel/index.vue'
import ElementPositionPanel from './ElementPositionPanel.vue'
import ElementAnimationPanel from './ElementAnimationPanel.vue'
import ElementTemplateData from './ElementTemplateData.vue'
import SlideDesignPanel from './SlideDesignPanel.vue'
import SlideAnimationPanel from './SlideAnimationPanel.vue'
import MultiPositionPanel from './MultiPositionPanel.vue'
......@@ -34,6 +36,7 @@ interface ElementTabs {
const mainStore = useMainStore()
const { activeElementIdList, handleElement, toolbarState } = storeToRefs(mainStore)
const { model } = storeToRefs(useScreenStore())
const elementTabs = computed<ElementTabs[]>(() => {
if (handleElement.value?.type === 'text') {
......@@ -50,11 +53,22 @@ const elementTabs = computed<ElementTabs[]>(() => {
{ label: '动画', key: ToolbarStates.EL_ANIMATION },
]
})
const slideTabs = [
{ label: '设计', key: ToolbarStates.SLIDE_DESIGN },
{ label: '切换', key: ToolbarStates.SLIDE_ANIMATION },
{ label: '动画', key: ToolbarStates.EL_ANIMATION },
]
const slideTabs = ref([] as any)
if(model.value){
slideTabs.value = [
{ label: '设计', key: ToolbarStates.SLIDE_DESIGN },
{ label: '切换', key: ToolbarStates.SLIDE_ANIMATION },
{ label: '动画', key: ToolbarStates.EL_ANIMATION },
{ label: '模版数据', key: ToolbarStates.EL_TEMPLATEDATA },
]
}else {
slideTabs.value = [
{ label: '设计', key: ToolbarStates.SLIDE_DESIGN },
{ label: '切换', key: ToolbarStates.SLIDE_ANIMATION },
{ label: '动画', key: ToolbarStates.EL_ANIMATION },
]
}
const multiSelectTabs = [
{ label: '样式', key: ToolbarStates.EL_STYLE },
{ label: '位置', key: ToolbarStates.MULTI_POSITION },
......@@ -65,7 +79,7 @@ const setToolbarState = (value: ToolbarStates) => {
}
const currentTabs = computed(() => {
if (!activeElementIdList.value.length) return slideTabs
if (!activeElementIdList.value.length) return slideTabs.value
else if (activeElementIdList.value.length > 1) return multiSelectTabs
return elementTabs.value
})
......@@ -82,6 +96,7 @@ const currentPanelComponent = computed(() => {
[ToolbarStates.EL_STYLE]: ElementStylePanel,
[ToolbarStates.EL_POSITION]: ElementPositionPanel,
[ToolbarStates.EL_ANIMATION]: ElementAnimationPanel,
[ToolbarStates.EL_TEMPLATEDATA]: ElementTemplateData,
[ToolbarStates.SLIDE_DESIGN]: SlideDesignPanel,
[ToolbarStates.SLIDE_ANIMATION]: SlideAnimationPanel,
[ToolbarStates.MULTI_POSITION]: MultiPositionPanel,
......
......@@ -5,12 +5,14 @@
<Thumbnails class="layout-content-left" />
<div class="layout-content-center">
<CanvasTool class="center-top" />
<Canvas class="center-body" :style="{ height: `calc(100% - ${remarkHeight + 40}px)` }" />
<Remark
<!-- :style="{ height: `calc(100% - ${remarkHeight + 40}px)` }" -->
<Canvas class="center-body" :style="{ height: `100%`}" />
<!-- <Remark
class="center-bottom"
v-model:height="remarkHeight"
:style="{ height: `${remarkHeight}px` }"
/>
/> -->
<DataaSource/>
</div>
<Toolbar class="layout-content-right" />
</div>
......@@ -29,11 +31,12 @@
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { ref, reactive, provide, watch, inject } from 'vue'
import { storeToRefs } from 'pinia'
import { useMainStore } from '@/store'
import { useMainStore, useSlidesStore, useScreenStore } from '@/store'
import useGlobalHotkey from '@/hooks/useGlobalHotkey'
import usePasteEvent from '@/hooks/usePasteEvent'
import { injectKeyDataSource, injectKeyTemplate } from '@/types/injectKey'
import EditorHeader from './EditorHeader/index.vue'
import Canvas from './Canvas/index.vue'
......@@ -45,6 +48,69 @@ import ExportDialog from './ExportDialog/index.vue'
import SelectPanel from './SelectPanel.vue'
import SearchPanel from './SearchPanel.vue'
import Modal from '@/components/Modal.vue'
import DataaSource from './DataaSource/index.vue'
import ConfigService from '@/services/ConfigService'
const datas = reactive({
DataSource:{
ConfigId: inject(injectKeyTemplate).ConfigId?inject(injectKeyTemplate).ConfigId:0,
pageType: 1,//1基础 2酒店 3景 4餐
DataSourceOverlay: false,
DataSourceList:[],
queryObj:{
TempId: inject(injectKeyTemplate).TempId?inject(injectKeyTemplate).TempId:0,//编号(新增传0) 是 [int]
LineId: null,//线路Id 是 [int]
LineName: '',//线路名称 是 [string]
LtId: null,//系列Id 是 [int]
Title: '',//名称 是 [string]
TempData: null,//模板数据 是 [json]
CoverImg: '',//封面图 是 [string]
CountryName: null,//国家 是 [string]
SeasonName: '',//季节 是 [string]
ColorName: '',//颜色名称 是 [string]
ColorStr: null,//颜色值 是 [string]
TempType: 1,// 版面类型(1-横版,2-竖版)
}
},
})
const slidesStore = useSlidesStore()
const TemplateTypeStore = useScreenStore()
const TempDataSourceStore = useScreenStore()
const { slides, slideIndex } = storeToRefs(slidesStore)
const { TemplateType } = storeToRefs(TemplateTypeStore)
const pageTypesList = ref([] as any)
watch(() => datas.DataSource, () => {
provide(injectKeyDataSource,datas.DataSource)
})
// 数据源
const GetTripFiled = async () =>{
try {
let TemplateRes = await ConfigService.TemplateGetTripFiled();
if (TemplateRes.data.resultCode == 1) {
TemplateRes.data.data.forEach(x=>{
let obj = pageTypesList.value.findIndex(z=>{
return z.FiledType==x.FiledType
})
if(obj==-1){
let object = {
FiledType: x.FiledType,
Name: x.FiledTypeStr
}
pageTypesList.value.push(object)
}
})
TemplateTypeStore.setTemplateType(pageTypesList.value)
TempDataSourceStore.setTemplateDataSource(TemplateRes.data.data)
}
} catch (error) {
console.log("TemplateGetTripFiled", error);
}
}
GetTripFiled()
const mainStore = useMainStore()
const { dialogForExport, showSelectPanel, showSearchPanel } = storeToRefs(mainStore)
......@@ -52,8 +118,12 @@ const closeExportDialog = () => mainStore.setDialogForExport('')
const remarkHeight = ref(40)
useGlobalHotkey()
usePasteEvent()
provide(injectKeyDataSource,datas.DataSource)
</script>
<style lang="scss" scoped>
......
This diff is collapsed.
......@@ -29,7 +29,7 @@ import BaseVideoElement from '@/views/components/element/VideoElement/BaseVideoE
import BaseAudioElement from '@/views/components/element/AudioElement/BaseAudioElement.vue'
const props = defineProps<{
elementInfo: PPTElement
elementInfo: PPTElement,
elementIndex: number
}>()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment