Commit e83e74eb authored by 罗超's avatar 罗超

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

# Conflicts:
#	src/App.vue
parents 2f4e69e0 f23b1243
<template> <template>
<div v-if="isFinish" style="height: 100vh;overflow: auto;background: rgb(243, 246, 251);"> <div v-if="isFinish" style="height: 100vh;background: rgb(243, 246, 251);">
<Screen v-if="screening" /> <Screen v-if="screening" />
<Market v-else-if="market"></Market> <Market v-else-if="market"></Market>
<Editor v-else-if="_isPC" /> <Editor v-else-if="_isPC" />
...@@ -10,20 +10,20 @@ ...@@ -10,20 +10,20 @@
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted,ref,provide } from 'vue' import { onMounted,ref,provide } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useScreenStore, useMainStore, useSnapshotStore } from '@/store' import { useScreenStore, useMainStore, useSnapshotStore, useFontStore } from '@/store'
import { LOCALSTORAGE_KEY_DISCARDED_DB } from '@/configs/storage' import { LOCALSTORAGE_KEY_DISCARDED_DB } from '@/configs/storage'
import { deleteDiscardedDB } from '@/utils/database' import { deleteDiscardedDB } from '@/utils/database'
import { isPC, query } from './utils/common' import { isPC, query } from './utils/common'
import { userStore } from './store/user' import { userStore } from './store/user'
import { injectKeyTemplate } from '@/types/injectKey' import { injectKeyTemplate } from '@/types/injectKey'
import ConfigService from '@/services/ConfigService'
import Editor from './views/Editor/index.vue' import Editor from './views/Editor/index.vue'
import Screen from './views/Screen/index.vue' import Screen from './views/Screen/index.vue'
import Mobile from './views/Mobile/index.vue' import Mobile from './views/Mobile/index.vue'
import Market from './views/Market/Index.vue' import Market from './views/Market/Index.vue'
import { useFontStore } from './store/font' import NewFile from './views/Market/newFile.vue'
import { ElMessageBox } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus'
const searchData = ref({} as any) const searchData = ref({} as any)
provide(injectKeyTemplate,searchData) provide(injectKeyTemplate,searchData)
...@@ -32,32 +32,39 @@ const isFinish = ref(false) ...@@ -32,32 +32,39 @@ const isFinish = ref(false)
const _isPC = isPC() const _isPC = isPC()
const mainStore = useMainStore() const mainStore = useMainStore()
const snapshotStore = useSnapshotStore() const snapshotStore = useSnapshotStore()
const modelStore = useScreenStore() const modelStore = useScreenStore()
const ConfigIdStore = useScreenStore() const ConfigIdStore = useScreenStore()
const marketStore = useScreenStore()
const isModelStore = useScreenStore()
const TempIdStore = useScreenStore()
const { databaseId } = storeToRefs(mainStore) const { databaseId } = storeToRefs(mainStore)
const { screening, market, model, ConfigId } = storeToRefs(useScreenStore()) const { screening, market, model, ConfigId } = storeToRefs(useScreenStore())
const { userInfo } = storeToRefs(userStore())
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
window.onbeforeunload = () => false window.onbeforeunload = () => false
} }
const userLoginHandler = async ()=>{ const userLoginHandler = async ()=>{
let param = query() let param = query()
let userId = 1 let userId = 1
let ConfigId = 0 let ConfigId = 0 // 9117
let model = 1 let model = 0
if(param.uid) userId=parseInt(param.uid) if(param.uid) userId=parseInt(param.uid)
if(param.ConfigId) ConfigId=parseInt(param.ConfigId) if(param.ConfigId) ConfigId=parseInt(param.ConfigId)
if(param.model) model=parseInt(param.model) if(param.model) model=parseInt(param.model)
ConfigIdStore.setConfigId(ConfigId) ConfigIdStore.setConfigId(ConfigId)
modelStore.setModel(model) modelStore.setModel(model)
try { if(!userInfo.value.EmployeeId){
await userStore().setUserLoginAsync(userId) try {
await useFontStore().loadAllFonts() await userStore().setUserLoginAsync(userId,ConfigId)
} catch (error) { await useFontStore().loadAllFonts()
if(ConfigId) await GetTripConfig(ConfigId)
} catch (error) {}
}else{
if(ConfigId) await GetTripConfig(ConfigId)
} }
isFinish.value=true isFinish.value=true
if(!ConfigId&&!model) ElMessageBox.confirm( if(!ConfigId&&!model) ElMessageBox.confirm(
...@@ -72,7 +79,6 @@ const userLoginHandler = async ()=>{ ...@@ -72,7 +79,6 @@ const userLoginHandler = async ()=>{
.catch(() => {}) .catch(() => {})
} }
userLoginHandler()
onMounted(async () => { onMounted(async () => {
await deleteDiscardedDB() await deleteDiscardedDB()
...@@ -80,6 +86,33 @@ onMounted(async () => { ...@@ -80,6 +86,33 @@ onMounted(async () => {
mainStore.setAvailableFonts() mainStore.setAvailableFonts()
}) })
/**
* 根据团期配置编号获取行程详情
*/
const GetTripConfig = async (ConfigId) =>{
try {
let queryMsg = {
ConfigId: ConfigId
}
let datasRes = await ConfigService.triptemplateGetTripConfig(queryMsg);
if (datasRes.data.resultCode == 1) {
if(datasRes.data.data&&datasRes.data.data.length>0&&datasRes.data.data[0].TempId){
isModelStore.setIsModel(true)
marketStore.setMarket(!market)
TempIdStore.setTempId(datasRes.data.data[0].TempId)
}
}else{
return ElMessage({
showClose: true,
message: datasRes.data.message,
type: 'warning',
})
}
} catch (error) {
console.log("triptemplate_GetTripConfig", error);
}
}
userLoginHandler()
// 应用注销时向 localStorage 中记录下本次 indexedDB 的数据库ID,用于之后清除数据库 // 应用注销时向 localStorage 中记录下本次 indexedDB 的数据库ID,用于之后清除数据库
window.addEventListener('unload', () => { window.addEventListener('unload', () => {
const discardedDB = localStorage.getItem(LOCALSTORAGE_KEY_DISCARDED_DB) const discardedDB = localStorage.getItem(LOCALSTORAGE_KEY_DISCARDED_DB)
......
import Axios, {
AxiosResponse,
InternalAxiosRequestConfig,
AxiosError,
} from 'axios';
import { domainManager } from '../utils/domainManager'
let datas: AxiosResponse
export enum ApiResult{
'SUCCESS' = 1,
'FAILED' = 0,
'TOKEN_INVALID' = 10000,
'TOKEN_ILLEGAL' = 10001,
}
/**
* get status code
* @param {AxiosResponse} response Axios response object
*/
const getErrorCode2text = (response: AxiosResponse): string => {
const code = response.status
let message = 'Request Error'
switch (code) {
case 400:
message = 'Request Error'
break
case 401:
message = 'Unauthorized, please login'
break
case 403:
message = '拒绝访问'
break
case 404:
message = '访问资源不存在'
break
case 408:
message = '请求超时'
break
case 500:
message = '位置错误'
break
case 501:
message = '承载服务未实现'
break
case 502:
message = '网关错误'
break
case 503:
message = '服务暂不可用'
break
case 504:
message = '网关超时'
break
case 505:
message = '暂不支持的 HTTP 版本'
break
default:
message = '位置错误'
}
return message
}
/**
* @returns {AxiosResponse} result
* @tutorial see more:https://github.com/onlyling/some-demo/tree/master/typescript-width-axios
* @example
* service.get<{data: string; code: number}>('/test').then(({data}) => { console.log(data.code) })
*/
const service = Axios.create({
baseURL: domainManager().UploadUrl,
timeout: 20000,
headers: {
"Content-Type": "application/x-www-form-urlencoded;"
}
})
/**
* @description 请求发起前的拦截器
* @returns {AxiosRequestConfig} config
*/
service.interceptors.request.use(
async (config: InternalAxiosRequestConfig) => {
return config;
},
error => {
//TODO: 新增网络请求异常处理业务
return Promise.reject(error)
}
)
/**
* @description 响应收到后的拦截器
* @returns {}
*/
service.interceptors.response.use(
/** 请求有响应 */
async (response: AxiosResponse) => {
if (response.status === 200) {
if(response.data.resultCode == ApiResult.TOKEN_ILLEGAL || response.data.resultCode == ApiResult.TOKEN_INVALID){
}
datas = response
return Promise.resolve(datas)
} else {
const __text = getErrorCode2text(response)
return Promise.reject(new Error(__text))
}
},
/** 请求无响应 */
(error: AxiosError) => {
if (error && error.response) {
const __text = getErrorCode2text(error.response);
return Promise.reject(new Error(__text));
} else {
return Promise.reject(new Error('unknow error'));
}
}
)
export default service
...@@ -27,10 +27,40 @@ export default () => { ...@@ -27,10 +27,40 @@ export default () => {
const slidesStore = useSlidesStore() const slidesStore = useSlidesStore()
const coverImgStore = useScreenStore() const coverImgStore = useScreenStore()
const isCoverImgStore = useScreenStore() const isCoverImgStore = useScreenStore()
const FeatureImgStore = useScreenStore()
const { slides, theme, viewportRatio, title } = storeToRefs(slidesStore) const { slides, theme, viewportRatio, title } = storeToRefs(slidesStore)
const { isCoverImg } = storeToRefs(useScreenStore()) const { isCoverImg, FeatureImg } = storeToRefs(useScreenStore())
const exporting = ref(false) const exporting = ref(false)
// 生成行程图片
const exportFeatureImg = (domRef: HTMLElement, format: string, quality: number, ignoreWebfont = true, i: number) => {
const toImage = format === 'png' ? toPng : toJpeg
const foreignObjectSpans = domRef.querySelectorAll('foreignObject [xmlns]')
foreignObjectSpans.forEach(spanRef => spanRef.removeAttribute('xmlns'))
setTimeout(() => {
const config: ExportImageConfig = {
quality,
width: 1600,
}
if (ignoreWebfont) config.fontEmbedCSS = ''
toImage(domRef, config).then(dataUrl => {
const obj = {
index: i,
url: dataUrl
}
FeatureImg.value.push(obj)
FeatureImgStore.setFeatureImg(JSON.parse(JSON.stringify(FeatureImg.value)))
}).catch(() => {
message.error('导出图片失败')
})
}, 200)
}
// 导出图片 // 导出图片
const exportImage = (domRef: HTMLElement, format: string, quality: number, ignoreWebfont = true) => { const exportImage = (domRef: HTMLElement, format: string, quality: number, ignoreWebfont = true) => {
exporting.value = true exporting.value = true
...@@ -49,7 +79,7 @@ export default () => { ...@@ -49,7 +79,7 @@ export default () => {
exporting.value = false exporting.value = false
if (isCoverImg.value) { if (isCoverImg.value) {
coverImgStore.setCoverImg(dataUrl) coverImgStore.setCoverImg(dataUrl)
isCoverImgStore.setIsCoverImg(false) isCoverImgStore.setIsCoverImg(false)
} else { } else {
saveAs(dataUrl, `${title.value}.${format}`) saveAs(dataUrl, `${title.value}.${format}`)
} }
...@@ -783,6 +813,7 @@ export default () => { ...@@ -783,6 +813,7 @@ export default () => {
return { return {
exporting, exporting,
exportFeatureImg,
exportImage, exportImage,
exportJSON, exportJSON,
exportSpecificFile, exportSpecificFile,
......
import Api,{ HttpResponse, Result } from './../utils/requestUpload';
import { domainManager } from './../utils/domainManager'
/**
* 配置相关方法
*/
class UploadService{
/**
* base64Str上传
*/
static async UploadBase64Two(path:any, params: any):Promise<HttpResponse>{
let apiurl = `${domainManager().UploadUrl}/Upload/UploadBase64${path}`
return Api.Post(apiurl,params)
}
}
export default UploadService;
\ No newline at end of file
...@@ -9,9 +9,12 @@ export interface ScreenState { ...@@ -9,9 +9,12 @@ export interface ScreenState {
ConfigId:number, ConfigId:number,
TemplateType: [], TemplateType: [],
TemplateDataSource: [], TemplateDataSource: [],
TempId: number,
CoverImg: any, CoverImg: any,
isCoverImg: boolean, isCoverImg: boolean,
dataLoading: boolean, dataLoading: boolean,
FeatureImg: any
} }
export const useScreenStore = defineStore('screen', { export const useScreenStore = defineStore('screen', {
...@@ -23,9 +26,11 @@ export const useScreenStore = defineStore('screen', { ...@@ -23,9 +26,11 @@ export const useScreenStore = defineStore('screen', {
ConfigId: 0, ConfigId: 0,
TemplateType: [], // 数据源分类 TemplateType: [], // 数据源分类
TemplateDataSource: [], // 所有数据源 TemplateDataSource: [], // 所有数据源
TempId: 0, // 模版Id
CoverImg: null, // 封面图 CoverImg: null, // 封面图
isCoverImg: false, // 封面 isCoverImg: false, // 封面
dataLoading: false, // 记录保存是否成功 dataLoading: false, // 记录保存是否成功
FeatureImg: [], // 行程特色图
}), }),
actions: { actions: {
...@@ -59,8 +64,14 @@ export const useScreenStore = defineStore('screen', { ...@@ -59,8 +64,14 @@ export const useScreenStore = defineStore('screen', {
setTemplateDataSource(TemplateDataSource: []) { setTemplateDataSource(TemplateDataSource: []) {
this.TemplateDataSource = TemplateDataSource this.TemplateDataSource = TemplateDataSource
}, },
setTempId(TempId: number) {
this.TempId = TempId
},
setDataLoading(dataLoading: boolean) { setDataLoading(dataLoading: boolean) {
this.dataLoading = dataLoading this.dataLoading = dataLoading
},
setFeatureImg(FeatureImg: any) {
this.FeatureImg = FeatureImg
} }
}, },
}) })
\ No newline at end of file
...@@ -36,7 +36,15 @@ export const useSlidesStore = defineStore('slides', { ...@@ -36,7 +36,15 @@ export const useSlidesStore = defineStore('slides', {
state: (): SlidesState => ({ state: (): SlidesState => ({
title: '未命名演示文稿', // 幻灯片标题 title: '未命名演示文稿', // 幻灯片标题
theme: theme, // 主题样式 theme: theme, // 主题样式
slides: slides, // 幻灯片页面数据 slides: [{
id: 'test-slide-1',
pageType: 1,
elements: [],
background: {
type: 'solid',
color: '#ffffff',
},
}], // 幻灯片页面数据 slides
slideIndex: 0, // 当前页面索引 slideIndex: 0, // 当前页面索引
viewportRatio: 0.7069, // 可视区域比例,默认16:9 0.5625 viewportRatio: 0.7069, // 可视区域比例,默认16:9 0.5625
layoutSlides: slides, // 所有模版数据 layoutSlides: slides, // 所有模版数据
......
export const domainManager = () => {
const locationName = window.location.hostname
console.log(window.location.hostname, '=====hostname')
const obj = {
domainUrl: locationName.indexOf('oytour') !== -1 ? "http://reborn.oytour.com" : "http://192.168.10.214/api/common/post",
//上传站点
UploadUrl: locationName.indexOf('oytour') !== -1 ? "http://upload.oytour.com" : "http://192.168.10.214:8120",
//文件站点
ViittoFileUrl: locationName.indexOf('oytour') !== -1 ? "http://imgfile.oytour.com" : 'http://192.168.10.214:8130',
}
return obj
}
\ No newline at end of file
import service, { ApiResult } from "../configs/axiosUpload";
export interface HttpResponse {
status: number
statusText: string
data: Result
}
export interface Result {
resultCode: ApiResult
message: string
data: any
[key: string]: any
}
class Api{
constructor(){ }
static Post = (path:string,base64Str:any): Promise<HttpResponse>=>{
return service.post(path,base64Str)
}
}
export default Api;
...@@ -94,19 +94,35 @@ ...@@ -94,19 +94,35 @@
<LinkDialog @close="linkDialogVisible = false" /> <LinkDialog @close="linkDialogVisible = false" />
</Modal> </Modal>
</div> </div>
<div style="position: relative;z-index: -1;">
<div class="export-img-dialog">
<div class="thumbnails-view">
<div class="thumbnails" v-for="slide in slides" ref="FeatureImgRef">
<ThumbnailSlide
class="thumbnail"
:key="slide.id"
:slide="slide"
:size="1600"
/>
</div>
</div>
</div>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { nextTick, onMounted, onUnmounted, provide, ref, watch, watchEffect } from 'vue' import { nextTick, onMounted, onUnmounted, provide, ref, reactive, watch, watchEffect, computed, inject } from 'vue'
import { throttle } from 'lodash' import { throttle } from 'lodash'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { useMainStore, useSlidesStore, useKeyboardStore } from '@/store' import { useMainStore, useSlidesStore, useKeyboardStore, useScreenStore } from '@/store'
import type { ContextmenuItem } from '@/components/Contextmenu/types' import type { ContextmenuItem } from '@/components/Contextmenu/types'
import type { PPTElement } from '@/types/slides' import type { PPTElement } from '@/types/slides'
import type { AlignmentLineProps, CreateCustomShapeData } from '@/types/edit' import type { AlignmentLineProps, CreateCustomShapeData } from '@/types/edit'
import { injectKeySlideScale } from '@/types/injectKey' import { injectKeySlideScale } from '@/types/injectKey'
import { removeAllRanges } from '@/utils/selection' import { removeAllRanges } from '@/utils/selection'
import { KEYS } from '@/configs/hotkey' import { KEYS } from '@/configs/hotkey'
import useExport from '@/hooks/useExport'
import { injectKeyDataSource } from '@/types/injectKey'
import useViewportSize from './hooks/useViewportSize' import useViewportSize from './hooks/useViewportSize'
import useMouseSelection from './hooks/useMouseSelection' import useMouseSelection from './hooks/useMouseSelection'
...@@ -138,6 +154,7 @@ import MultiSelectOperate from './Operate/MultiSelectOperate.vue' ...@@ -138,6 +154,7 @@ import MultiSelectOperate from './Operate/MultiSelectOperate.vue'
import Operate from './Operate/index.vue' import Operate from './Operate/index.vue'
import LinkDialog from './LinkDialog.vue' import LinkDialog from './LinkDialog.vue'
import Modal from '@/components/Modal.vue' import Modal from '@/components/Modal.vue'
import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'
const mainStore = useMainStore() const mainStore = useMainStore()
const { const {
...@@ -153,12 +170,45 @@ const { ...@@ -153,12 +170,45 @@ const {
canvasScale, canvasScale,
textFormatPainter, textFormatPainter,
} = storeToRefs(mainStore) } = storeToRefs(mainStore)
const { currentSlide } = storeToRefs(useSlidesStore()) const { currentSlide, slides } = storeToRefs(useSlidesStore())
const { ctrlKeyState, spaceKeyState } = storeToRefs(useKeyboardStore()) const { ctrlKeyState, spaceKeyState } = storeToRefs(useKeyboardStore())
const viewportRef = ref<HTMLElement>() const viewportRef = ref<HTMLElement>()
const alignmentLines = ref<AlignmentLineProps[]>([]) const alignmentLines = ref<AlignmentLineProps[]>([])
const { exportFeatureImg } = useExport()
const datas = reactive({
FeatureImgList: [],
loading: false
})
datas.FeatureImgList = inject(injectKeyDataSource).FeatureImgList
const FeatureImgStore = useScreenStore()
const { market, model, ConfigId, CoverImg, dataLoading, FeatureImg } = storeToRefs(useScreenStore())
const renderSlides = computed(() => {
return slides.value
})
const FeatureImgRef = ref(null)
// 将界面生成形成图
watch(() => slides.value, (n,o) =>{
FeatureImgStore.setFeatureImg([])
setTimeout(()=>{
for(let i=0;i<FeatureImgRef.value.length;i++){
exportFeatureImg(FeatureImgRef.value[i], 'jpeg', 1, true,i+1)
}
},500)
})
// 监听请求保存成功 重新请求数据
watch(() => FeatureImgRef.value, (n,o) =>{
})
watch(() => FeatureImg.value, (n,o) =>{
FeatureImg.value.sort((a,b)=>{
return a.index-b.index
})
})
const linkDialogVisible = ref(false) const linkDialogVisible = ref(false)
const openLinkDialog = () => linkDialogVisible.value = true const openLinkDialog = () => linkDialogVisible.value = true
......
...@@ -109,10 +109,10 @@ ...@@ -109,10 +109,10 @@
x.TemplateDataSource.Content = obj.Content x.TemplateDataSource.Content = obj.Content
x.TemplateDataSource.Name = obj.Name x.TemplateDataSource.Name = obj.Name
if(x.type=="text"){ // if(x.type=="text"){
x.FiledTypeStr = obj.Name // x.FiledTypeStr = obj.Name
x.content = x.content.replace(getHtmlPlainText(x.content),obj.Name) // x.content = x.content.replace(getHtmlPlainText(x.content),obj.Name)
} // }
} }
}) })
setNewDatas() setNewDatas()
......
...@@ -18,8 +18,8 @@ ...@@ -18,8 +18,8 @@
</FileInput> </FileInput>
<PopoverMenuItem @click="setDialogForExport('pptx')">导出文件</PopoverMenuItem> <PopoverMenuItem @click="setDialogForExport('pptx')">导出文件</PopoverMenuItem>
<PopoverMenuItem @click="resetSlides(); mainMenuVisible = false">重置幻灯片</PopoverMenuItem> <PopoverMenuItem @click="resetSlides(); mainMenuVisible = false">重置幻灯片</PopoverMenuItem>
<PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/issues')">意见反馈</PopoverMenuItem> <!-- <PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/issues')">意见反馈</PopoverMenuItem>
<PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/blob/master/doc/Q&A.md')">常见问题</PopoverMenuItem> <PopoverMenuItem @click="goLink('https://github.com/pipipi-pikachu/PPTist/blob/master/doc/Q&A.md')">常见问题</PopoverMenuItem> -->
<PopoverMenuItem @click="mainMenuVisible = false; hotkeyDrawerVisible = true">快捷键</PopoverMenuItem> <PopoverMenuItem @click="mainMenuVisible = false; hotkeyDrawerVisible = true">快捷键</PopoverMenuItem>
</template> </template>
<div class="menu-item"><IconHamburgerButton class="icon" /></div> <div class="menu-item"><IconHamburgerButton class="icon" /></div>
...@@ -77,6 +77,8 @@ ...@@ -77,6 +77,8 @@
保存行程 保存行程
</template> </template>
</el-button> </el-button>
<div>
</div>
<!-- <a class="github-link" href="https://github.com/pipipi-pikachu/PPTist" target="_blank"> <!-- <a class="github-link" href="https://github.com/pipipi-pikachu/PPTist" target="_blank">
<div class="menu-item"><IconGithub class="icon" /></div> <div class="menu-item"><IconGithub class="icon" /></div>
</a> --> </a> -->
...@@ -93,11 +95,15 @@ ...@@ -93,11 +95,15 @@
<FullscreenSpin :loading="exporting" tip="正在导入..." /> <FullscreenSpin :loading="exporting" tip="正在导入..." />
<Psd-Upload :visible="psdVisibleStatus" @closed="psdVisibleStatus=false"></Psd-Upload> <Psd-Upload :visible="psdVisibleStatus" @closed="psdVisibleStatus=false"></Psd-Upload>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { nextTick, ref, reactive, inject } from 'vue' import { nextTick, ref, reactive, inject, computed, watch } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import { toPng, toJpeg } from 'html-to-image'
import message from '@/utils/message'
import { useMainStore, useSlidesStore } from '@/store' import { useMainStore, useSlidesStore } from '@/store'
import useScreening from '@/hooks/useScreening' import useScreening from '@/hooks/useScreening'
import useImport from '@/hooks/useImport' import useImport from '@/hooks/useImport'
...@@ -109,6 +115,11 @@ import ConfigService from '@/services/ConfigService' ...@@ -109,6 +115,11 @@ import ConfigService from '@/services/ConfigService'
import { injectKeyDataSource, injectKeyTemplate } from '@/types/injectKey' import { injectKeyDataSource, injectKeyTemplate } from '@/types/injectKey'
import PsdUpload from '@/components/PSD/Index.vue' import PsdUpload from '@/components/PSD/Index.vue'
import { svg2Base64 } from '@/utils/svg2Base64' import { svg2Base64 } from '@/utils/svg2Base64'
import UploadService from '@/services/UploadService'
import { domainManager } from '@/utils/domainManager'
import { ToolbarStates } from '@/types/toolbar'
import HotkeyDoc from './HotkeyDoc.vue' import HotkeyDoc from './HotkeyDoc.vue'
import FileInput from '@/components/FileInput.vue' import FileInput from '@/components/FileInput.vue'
...@@ -118,6 +129,7 @@ import Input from '@/components/Input.vue' ...@@ -118,6 +129,7 @@ import Input from '@/components/Input.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'
const mainStore = useMainStore() const mainStore = useMainStore()
const slidesStore = useSlidesStore() const slidesStore = useSlidesStore()
const layoutsStore = useSlidesStore() const layoutsStore = useSlidesStore()
...@@ -126,18 +138,22 @@ const { enterScreening, enterScreeningFromStart } = useScreening() ...@@ -126,18 +138,22 @@ const { enterScreening, enterScreeningFromStart } = useScreening()
const { importSpecificFile, importPPTXFile, exporting } = useImport() const { importSpecificFile, importPPTXFile, exporting } = useImport()
const { resetSlides } = useSlideHandler() const { resetSlides } = useSlideHandler()
const imageThumbnailsRef = ref<HTMLElement>()
const mainMenuVisible = ref(false) const mainMenuVisible = ref(false)
const hotkeyDrawerVisible = ref(false) const hotkeyDrawerVisible = ref(false)
const editingTitle = ref(false) const editingTitle = ref(false)
const titleInputRef = ref<InstanceType<typeof Input>>() const titleInputRef = ref<InstanceType<typeof Input>>()
const titleValue = ref('') const titleValue = ref('')
const { userInfo } = storeToRefs(userStore()) const { userInfo } = storeToRefs(userStore())
const datas = reactive({ const datas = reactive({
FeatureImgList:[],
DataSource:{}, DataSource:{},
loading: false loading: false
}) })
datas.FeatureImgList = inject(injectKeyDataSource).FeatureImgList
const queryObj = ref({} as any) const queryObj = ref({} as any)
const searchData = ref({} as any) const searchData = ref({} as any)
datas.DataSource = inject(injectKeyDataSource) datas.DataSource = inject(injectKeyDataSource)
...@@ -146,8 +162,12 @@ searchData.value = inject(injectKeyTemplate) ...@@ -146,8 +162,12 @@ searchData.value = inject(injectKeyTemplate)
const marketStore = useScreenStore() const marketStore = useScreenStore()
const CoverImgStore = useScreenStore() const CoverImgStore = useScreenStore()
const dataLoadingStore = useScreenStore() const dataLoadingStore = useScreenStore()
const TempIdStore = useScreenStore()
const FeatureImgStore = useScreenStore()
const ConfigIdStore = useScreenStore()
const psdVisibleStatus = ref(false) const psdVisibleStatus = ref(false)
const { market, model, ConfigId, CoverImg, dataLoading } = storeToRefs(useScreenStore()) const { market, model, ConfigId, CoverImg, dataLoading, TempId, FeatureImg } = storeToRefs(useScreenStore())
// 返回到首页 // 返回到首页
const goBack = () =>{ const goBack = () =>{
...@@ -163,7 +183,8 @@ const goBack = () =>{ ...@@ -163,7 +183,8 @@ const goBack = () =>{
} }
] ]
if(model.value) { if(model.value) {
searchData.value.TempId = 0 // searchData.value.TempId = 0
TempIdStore.setTempId(0)
marketStore.setMarket(true) marketStore.setMarket(true)
slidesStore.setSlides(list) slidesStore.setSlides(list)
layoutsStore.setLayouts([]) layoutsStore.setLayouts([])
...@@ -180,7 +201,8 @@ const goBack = () =>{ ...@@ -180,7 +201,8 @@ const goBack = () =>{
} }
) )
.then(() => { .then(() => {
searchData.value.TempId = 0 // searchData.value.TempId = 0
TempIdStore.setTempId(0)
marketStore.setMarket(true) marketStore.setMarket(true)
slidesStore.setSlides(list) slidesStore.setSlides(list)
layoutsStore.setLayouts([]) layoutsStore.setLayouts([])
...@@ -196,7 +218,6 @@ const UploadPsdHandler = () => { ...@@ -196,7 +218,6 @@ const UploadPsdHandler = () => {
psdVisibleStatus.value = true psdVisibleStatus.value = true
} }
// 新增修改模版 // 新增修改模版
const SetTripTemplateSlide = async () => { const SetTripTemplateSlide = async () => {
// console.log(JSON.parse(queryObj.value.TempData),'--------') // console.log(JSON.parse(queryObj.value.TempData),'--------')
...@@ -204,93 +225,160 @@ const SetTripTemplateSlide = async () => { ...@@ -204,93 +225,160 @@ const SetTripTemplateSlide = async () => {
console.log(queryObj.value,'新增修改模版---') console.log(queryObj.value,'新增修改模版---')
let TemplateRes = await ConfigService.SetTripTemplateSlide(queryObj.value); let TemplateRes = await ConfigService.SetTripTemplateSlide(queryObj.value);
if (TemplateRes.data.resultCode == 1) { if (TemplateRes.data.resultCode == 1) {
if(!queryObj.value.TempId){
queryObj.value.TempId = TemplateRes.data.data.TempId
searchData.value.TempId = TemplateRes.data.data.TempId
}
ElMessage({
showClose: true,
message: '操作成功',
type: 'success',
})
dataLoadingStore.setDataLoading(true)
}else{
ElMessage({
showClose: true,
message: '操作失败',
type: 'warning',
})
} }
dataLoadingStore.setDataLoading(true)
datas.loading = false datas.loading = false
} catch (error) { } catch (error) {
datas.loading = false datas.loading = false
console.log("TemplateGetTripFiled", error); ElMessage({
showClose: true,
message: '操作失败',
type: 'warning',
})
} }
} }
// 用户新增修改数据 // 用户新增修改数据
const SetTripTemplateConfig = async () => { const SetTripTemplateConfig = async () => {
try { try {
let queryMsg = { let queryMsg = {
ConfigId: ConfigId.value, ConfigId: ConfigId.value,
TempId: queryObj.value.TempId, TempId: queryObj.value.TempId,
TempData: queryObj.value.TempData TempData: queryObj.value.TempData,
FeatureImg: datas.FeatureImgList
} }
console.log(queryMsg,'新增修改团数据---') let TemplateRes = await ConfigService.SetSetTripConfig(queryMsg);
let TemplateRes = await ConfigService.SetSetTripConfig(queryMsg); if (TemplateRes.data.resultCode == 1) {
if (TemplateRes.data.resultCode == 1) { if(!ConfigId.value){
ConfigIdStore.value = TemplateRes.data.data.ConfigId
} }
dataLoadingStore.setDataLoading(true) ElMessage({
datas.loading = false showClose: true,
} catch (error) { message: '操作成功',
datas.loading = false type: 'success',
console.log("TemplateGetTripFiled", error); })
}
dataLoadingStore.setDataLoading(true)
}else{
ElMessage({
showClose: true,
message: '操作失败',
type: 'warning',
})
}
FeatureImgStore.setFeatureImg([])
datas.loading = false
} catch (error) {
FeatureImgStore.setFeatureImg([])
datas.loading = false
ElMessage({
showClose: true,
message: '操作失败',
type: 'warning',
})
}
} }
// 保存 // 保存
const setTemplate = async () =>{ const setTemplate = async () =>{
let arr = JSON.parse(JSON.stringify(slides.value))
if(dataLoading.value){ if(dataLoading.value){
dataLoadingStore.setDataLoading(false) dataLoadingStore.setDataLoading(false)
} }
// console.log(JSON.stringify(slides.value),'----保存接口',queryObj.value) // console.log(JSON.stringify(slides.value),'----保存接口',queryObj.value)
if(model.value&&userInfo.value.IsEditTripTemplate==1){ if(model.value&&userInfo.value.IsEditTripTemplate==1){
arr.forEach(x=>{
x.elements.forEach(y=>{
delete y.TemplateList
})
})
if(CoverImg&&CoverImg.value) queryObj.value.CoverImg = CoverImg.value if(CoverImg&&CoverImg.value) queryObj.value.CoverImg = CoverImg.value
else return ElMessage({ else {
showClose: true, mainStore.setToolbarState(ToolbarStates.EL_TEMPLATEDATA)
message: '请生成封面图', return ElMessage({
type: 'warning', showClose: true,
message: '请生成封面图',
type: 'warning',
}) })
}
if(queryObj.value.Title==''||!queryObj.value.LineId||!queryObj.value.LtId if(queryObj.value.Title==''||!queryObj.value.LineId||!queryObj.value.LtId
||queryObj.value.CoverImg=='' ||queryObj.value.CoverImg==''
||queryObj.value.CountryName==''||queryObj.value.SeasonName=='' ||queryObj.value.CountryName==''||queryObj.value.SeasonName==''
||queryObj.value.ColorName==''||queryObj.value.ColorStr==''||queryObj.value.LineName==''){ ||queryObj.value.ColorName==''||queryObj.value.ColorStr==''||queryObj.value.LineName==''){
mainStore.setToolbarState(ToolbarStates.EL_TEMPLATEDATA)
return ElMessage({ return ElMessage({
showClose: true, showClose: true,
message: '请完善右侧模版数据', message: '请完善右侧模版数据',
type: 'warning', type: 'warning',
}) })
} }
} else {
arr.forEach(x=>{
x.elements.forEach(y=>{
delete y.TemplateList
delete y.TemplateDataSource
})
})
} }
for(let i=0;i<slides.value.length;i++){ for(let i=0;i<slides.value.length;i++){
if(slides.value[i].elements.length==0) { if(slides.value[i].elements.length==0) {
mainStore.setToolbarState(ToolbarStates.EL_TEMPLATEDATA)
return ElMessage({ return ElMessage({
showClose: true, showClose: true,
message: `请设计 第 ${i+1} 页 的数据`, message: `请设计 第 ${i+1} 页 的数据`,
type: 'warning', 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) // console.log(arr,'-------tttt')
queryObj.value.TempData = JSON.stringify(arr)
datas.loading = true datas.loading = true
if(model.value&&userInfo.value.IsEditTripTemplate==1){ if(model.value&&userInfo.value.IsEditTripTemplate==1){
await SetTripTemplateSlide() await SetTripTemplateSlide()
}else if(ConfigId.value){ }
await SetTripTemplateConfig() if(ConfigId.value){
datas.FeatureImgList = []
FeatureImg.value.forEach(item=>{
setTimeout(()=>{
setFeatureImgList(item.url)
},300)
})
} }
} }
// 上传文件
const setFeatureImgList = async (url) => {
try {
let queryObj = {
MyFile: url
}
let path = `?fileType=1&fileLimit=5&&filePath=Feature/${ConfigId.value}_`
let Res = await UploadService.UploadBase64Two(path,queryObj);
if (Res.data&&Res.data.FilePath) {
datas.FeatureImgList.push(`${domainManager().ViittoFileUrl}/${Res.data.FilePath}`)
if(datas.FeatureImgList.length==slides.value.length){
await SetTripTemplateConfig()
}
}
} catch (error) {
}
}
const startEditTitle = () => { const startEditTitle = () => {
titleValue.value = title.value titleValue.value = title.value
...@@ -315,6 +403,70 @@ const setDialogForExport = (type: DialogForExportTypes) => { ...@@ -315,6 +403,70 @@ const setDialogForExport = (type: DialogForExportTypes) => {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.export-img-dialog {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
position: relative;
overflow: hidden;
}
.thumbnails-view {
@include absolute-0();
&::after {
content: '';
background-color: #fff;
@include absolute-0();
}
}
.configs {
width: 350px;
height: calc(100% - 100px);
display: flex;
flex-direction: column;
justify-content: center;
z-index: 1;
.row {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 25px;
}
.title {
width: 100px;
position: relative;
&::after {
content: attr(data-range);
position: absolute;
top: 20px;
left: 0;
}
}
.config-item {
flex: 1;
}
}
.btns {
width: 300px;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
z-index: 1;
.export {
flex: 1;
}
.close {
width: 100px;
margin-left: 10px;
}
}
.editor-header { .editor-header {
background-color: #fff; background-color: #fff;
user-select: none; user-select: none;
......
...@@ -64,19 +64,20 @@ import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue' ...@@ -64,19 +64,20 @@ import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'
import LayoutPool from './LayoutPool.vue' import LayoutPool from './LayoutPool.vue'
import Popover from '@/components/Popover.vue' import Popover from '@/components/Popover.vue'
import Draggable from 'vuedraggable' import Draggable from 'vuedraggable'
const mainStore = useMainStore() const mainStore = useMainStore()
const slidesStore = useSlidesStore() const slidesStore = useSlidesStore()
const layoutsStore = useSlidesStore() const layoutsStore = useSlidesStore()
const keyboardStore = useKeyboardStore() const keyboardStore = useKeyboardStore()
const { selectedSlidesIndex: _selectedSlidesIndex, thumbnailsFocus } = storeToRefs(mainStore) const { selectedSlidesIndex: _selectedSlidesIndex, thumbnailsFocus } = storeToRefs(mainStore)
const { slides, slideIndex, layoutSlides } = storeToRefs(slidesStore) const { slides, currentSlide, slideIndex, layoutSlides } = storeToRefs(slidesStore)
const { ctrlKeyState, shiftKeyState } = storeToRefs(keyboardStore) const { ctrlKeyState, shiftKeyState } = storeToRefs(keyboardStore)
const { slidesLoadLimit } = useLoadSlides() const { slidesLoadLimit } = useLoadSlides()
const TemplateTypeStore = useScreenStore() const TemplateTypeStore = useScreenStore()
const CoverImgStore = useScreenStore() const CoverImgStore = useScreenStore()
const dataLoadingStore = useScreenStore() const dataLoadingStore = useScreenStore()
const { ConfigId, TemplateDataSource, TemplateType, dataLoading } = storeToRefs(TemplateTypeStore) const { ConfigId, TemplateDataSource, TemplateType, dataLoading, TempId } = storeToRefs(TemplateTypeStore)
const selectedSlidesIndex = computed(() => [..._selectedSlidesIndex.value, slideIndex.value]) const selectedSlidesIndex = computed(() => [..._selectedSlidesIndex.value, slideIndex.value])
const presetLayoutPopoverVisible = ref(false) const presetLayoutPopoverVisible = ref(false)
...@@ -235,6 +236,7 @@ const GetTripTemplate = async () =>{ ...@@ -235,6 +236,7 @@ const GetTripTemplate = async () =>{
queryObj.value.ColorName = dataRes.data.data.ColorName queryObj.value.ColorName = dataRes.data.data.ColorName
queryObj.value.ColorStr = dataRes.data.data.ColorStr queryObj.value.ColorStr = dataRes.data.data.ColorStr
queryObj.value.TempType = dataRes.data.data.TempType queryObj.value.TempType = dataRes.data.data.TempType
slidesStore.updateSlideIndex(0)
if(ConfigId.value==0) return if(ConfigId.value==0) return
await GetTripFiledData(1) await GetTripFiledData(1)
} }
......
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
<div class="row wrap q-mt-md"> <div class="row wrap q-mt-md">
<el-select v-model="queryObj.LineId" class="m-2" <el-select v-model="queryObj.LineId" class="m-2"
filterable placeholder="请选择线路" filterable placeholder="请选择线路"
@change="onLineChangeHandler"> @change="onLineChangeHandler(1)">
<el-option <el-option
v-for="item in lines" v-for="item in lines"
:key="item.LineID" :key="item.LineID"
...@@ -267,6 +267,7 @@ ...@@ -267,6 +267,7 @@
let response = await LineService.GetLineListAsync() let response = await LineService.GetLineListAsync()
if (response.data.resultCode == 1) { if (response.data.resultCode == 1) {
lines.value = response.data.data; lines.value = response.data.data;
onLineChangeHandler()
} }
} catch (error) { } catch (error) {
console.log("getLinesHandler", error); console.log("getLinesHandler", error);
...@@ -276,12 +277,14 @@ ...@@ -276,12 +277,14 @@
/** /**
* 获取系列列表 * 获取系列列表
*/ */
const onLineChangeHandler = async () =>{ const onLineChangeHandler = async (type) =>{
let obj = lines.value.find(x=>{ let obj = lines.value.find(x=>{
return x.LineID == queryObj.value.LineId return x.LineID == queryObj.value.LineId
}) })
queryObj.value.LtId = null if(type){
queryObj.value.LineName = obj.LineName queryObj.value.LtId = null
}
if(obj&&obj.LineName) queryObj.value.LineName = obj.LineName
try { try {
let queryMsg = { let queryMsg = {
lineID: queryObj.value.LineId, lineID: queryObj.value.LineId,
......
...@@ -120,7 +120,7 @@ ...@@ -120,7 +120,7 @@
:value="viewportRatio" :value="viewportRatio"
@update:value="value => updateViewportRatio(value as number)" @update:value="value => updateViewportRatio(value as number)"
:options="[ :options="[
{ label: '横屏', value: 0.7069 }, { label: '横屏', value: 0.7723 },
{ label: '竖屏', value: 1.414 }, { label: '竖屏', value: 1.414 },
]" ]"
/> />
...@@ -337,7 +337,7 @@ const { formatFonts } = storeToRefs(useFontStore()) ...@@ -337,7 +337,7 @@ const { formatFonts } = storeToRefs(useFontStore())
const moreThemeConfigsVisible = ref(false) const moreThemeConfigsVisible = ref(false)
const background = computed(() => { const background = computed(() => {
if (!currentSlide.value.background) { if (!currentSlide.value||!currentSlide.value.background) {
return { return {
type: 'solid', type: 'solid',
value: '#fff', value: '#fff',
......
...@@ -51,14 +51,27 @@ import Modal from '@/components/Modal.vue' ...@@ -51,14 +51,27 @@ import Modal from '@/components/Modal.vue'
import DataaSource from './DataaSource/index.vue' import DataaSource from './DataaSource/index.vue'
import ConfigService from '@/services/ConfigService' import ConfigService from '@/services/ConfigService'
const slidesStore = useSlidesStore()
const TemplateTypeStore = useScreenStore()
const TempDataSourceStore = useScreenStore()
const { slides, slideIndex } = storeToRefs(slidesStore)
const { TemplateType, ConfigId, TempId} = storeToRefs(TemplateTypeStore)
const pageTypesList = ref([] as any)
const searchData = ref({} as any)
searchData.value = inject(injectKeyTemplate)
let TempIds = 0
if(TempId.value&&!searchData.value.TempId) TempIds = TempId.value
if(searchData.value.TempId) TempIds = searchData.value.TempId
const datas = reactive({ const datas = reactive({
DataSource:{ DataSource:{
ConfigId: inject(injectKeyTemplate).ConfigId?inject(injectKeyTemplate).ConfigId:0, FeatureImgList: [],
ConfigId: ConfigId.value?ConfigId.value:0,
pageType: 1,//1基础 2酒店 3景 4餐 pageType: 1,//1基础 2酒店 3景 4餐
DataSourceOverlay: false, DataSourceOverlay: false,
DataSourceList:[], DataSourceList:[],
queryObj:{ queryObj:{
TempId: inject(injectKeyTemplate).TempId?inject(injectKeyTemplate).TempId:0,//编号(新增传0) 是 [int] TempId: TempIds,//编号(新增传0) 是 [int]
LineId: null,//线路Id 是 [int] LineId: null,//线路Id 是 [int]
LineName: '',//线路名称 是 [string] LineName: '',//线路名称 是 [string]
LtId: null,//系列Id 是 [int] LtId: null,//系列Id 是 [int]
...@@ -76,14 +89,6 @@ const datas = reactive({ ...@@ -76,14 +89,6 @@ const datas = reactive({
}) })
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, () => { watch(() => datas.DataSource, () => {
provide(injectKeyDataSource,datas.DataSource) provide(injectKeyDataSource,datas.DataSource)
}) })
......
<template> <template>
<div style="background: #f3f6fb;height:100vh;"> <div style="background: #f3f6fb;height:100vh;overflow: auto;">
<div style="padding: 30px; max-width:1440px; margin:0 auto;"> <div style="padding: 30px; max-width:1440px; margin:0 auto;">
<el-row justify="space-between"> <el-row justify="space-between">
<el-col :span="6"> <el-col :span="6">
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
</el-col> </el-col>
</el-row> </el-row>
<div class="q-mt-lg bg-white rounded text-nowrap" style="padding: 20px 20px 0 20px;"> <div class="q-mt-lg bg-white rounded text-nowrap" style="padding: 20px 20px 0 20px;">
<div class="row text-small items-center" style="flex-wrap: wrap;"> <div class="row text-small items-center wrap">
<span style="margin-right: 50px;">适用线路:</span> <span style="margin-right: 50px;">适用线路:</span>
<el-check-tag :checked="queryObj.LineId == 0" @change="onLineChangeHandler(0)" <el-check-tag :checked="queryObj.LineId == 0" @change="onLineChangeHandler(0)"
class="text-small q-mr-md">全部</el-check-tag> class="text-small q-mr-md">全部</el-check-tag>
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
<el-divider style="margin:12px 0;border-top-color:#f3f6fb;"></el-divider> <el-divider style="margin:12px 0;border-top-color:#f3f6fb;"></el-divider>
<div class="row wrap q-pb-md"> <div class="row wrap q-pb-md">
<div class="q-pb-md"> <div class="q-pb-md">
<div class="row text-small items-center"> <div class="row text-small items-center wrap">
<span style="margin-right: 50px;">适用国家:</span> <span style="margin-right: 50px;">适用国家:</span>
<el-check-tag :checked="queryObj.CountryName == ''" @change="onCountryNameChangeHandler('')" <el-check-tag :checked="queryObj.CountryName == ''" @change="onCountryNameChangeHandler('')"
class="text-small q-mr-md">通用</el-check-tag> class="text-small q-mr-md">通用</el-check-tag>
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
<div class="MarketVerticalLine">&nbsp;</div> <div class="MarketVerticalLine">&nbsp;</div>
</div> </div>
<div class="q-pb-md"> <div class="q-pb-md">
<div class="row text-small items-center"> <div class="row text-small items-center wrap">
<span style="margin-right: 50px;">季节:</span> <span style="margin-right: 50px;">季节:</span>
<el-check-tag :checked="queryObj.SeasonName == ''" @change="onSeasonNameChangeHandler('')" <el-check-tag :checked="queryObj.SeasonName == ''" @change="onSeasonNameChangeHandler('')"
class="text-small q-mr-md">通用</el-check-tag> class="text-small q-mr-md">通用</el-check-tag>
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
<div class="MarketVerticalLine">&nbsp;</div> <div class="MarketVerticalLine">&nbsp;</div>
</div> </div>
<div class="q-pb-md"> <div class="q-pb-md">
<div class="row text-small items-center"> <div class="row text-small items-center wrap">
<span style="margin-right: 50px;">颜色:</span> <span style="margin-right: 50px;">颜色:</span>
<el-check-tag :checked="queryObj.ColorName == ''" @change="onColorNameChangeHandler('')" <el-check-tag :checked="queryObj.ColorName == ''" @change="onColorNameChangeHandler('')"
class="text-small q-mr-md">通用</el-check-tag> class="text-small q-mr-md">通用</el-check-tag>
...@@ -68,6 +68,27 @@ ...@@ -68,6 +68,27 @@
<div style="margin-top: 20px;" v-loading="loading"> <div style="margin-top: 20px;" v-loading="loading">
<div v-if="dataList.length>0" class="q-mt-lg row wrap bg-white rounded" style="padding: 30px 10px 0 10px;"> <div v-if="dataList.length>0" class="q-mt-lg row wrap bg-white rounded" style="padding: 30px 10px 0 10px;">
<template v-for="(item,index) in dataList"> <template v-for="(item,index) in dataList">
<div class="MarketIndexListBox">
<div class="MarketIndexList bg-white rounded">
<div class="MarketIndexList-Hover">
<div class="q-mr-lg">
<el-button type="primary" v-tooltip="'详情'"
icon="Tickets" circle style="color: #ffff;"
@click="getTemplate(item)"></el-button>
</div>
<div class="q-ml-lg">
<el-button type="primary" v-tooltip="'选择该模版'"
icon="Pointer" circle style="color: #ffff;"
@click="goToTemplate(item)"></el-button>
</div>
</div>
<div class="MarketIndexList-img">
<el-image style="width: 100%;height: 100%" :src="item.CoverImg" fit="cover" />
</div>
<div class="MarketIndexList-text">{{item.Title}}</div>
</div>
</div>
<!--
<el-popover effect="light" trigger="hover" placement="bottom-start" width="auto" height="auto"> <el-popover effect="light" trigger="hover" placement="bottom-start" width="auto" height="auto">
<template #default> <template #default>
<LayoutPool v-loading="queryObj.loading" /> <LayoutPool v-loading="queryObj.loading" />
...@@ -78,13 +99,12 @@ ...@@ -78,13 +99,12 @@
@mouseover="getTemplate(item)"> @mouseover="getTemplate(item)">
<div class="MarketIndexList-img"> <div class="MarketIndexList-img">
<el-image style="width: 100%;height: 100%" :src="item.CoverImg" fit="cover" /> <el-image style="width: 100%;height: 100%" :src="item.CoverImg" fit="cover" />
<!-- <img :src="item.CoverImg" style="height:100%"/> -->
</div> </div>
<div class="MarketIndexList-text">{{item.Title}}</div> <div class="MarketIndexList-text">{{item.Title}}</div>
</div> </div>
</div> </div>
</template> </template>
</el-popover> </el-popover> -->
</template> </template>
</div> </div>
<div v-else class="q-mt-lg bg-white rounded" style="padding: 30px 10px 30px 10px;text-align: center;color: #909399;">暂无数据</div> <div v-else class="q-mt-lg bg-white rounded" style="padding: 30px 10px 30px 10px;text-align: center;color: #909399;">暂无数据</div>
...@@ -104,11 +124,31 @@ ...@@ -104,11 +124,31 @@
</div> </div>
</div> </div>
</div> </div>
<el-dialog v-model="datas.DetailsVisible" :show-close="true" :close-on-press-escape="false"
:close-on-click-modal="true" style="width: 650px;">
<template #header>
<div class="text-title">{{datas.TemplateRow.Title}} 模版详情</div>
</template>
<div class="MarketDetails-LayoutPool" v-loading="datas.loading">
<LayoutPool style="width: 100%;"/>
</div>
<div class="q-mt-lg row items-center">
<div class="col">
</div>
<div>
<el-button v-if="ConfigId||model" class="q-ml-lg"
@click="datas.DetailsVisible=false,datas.TemplateRow={}">关闭</el-button>
<el-button v-if="ConfigId||model" type="primary" class="q-ml-lg"
@click="goToTemplate(datas.TemplateRow)">选择该模版</el-button>
</div>
</div>
</el-dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { reactive, ref, inject} from "vue"; import { reactive, ref, inject, watch} from "vue";
import LineService from '@/services/LineService' import LineService from '@/services/LineService'
import ConfigService from '@/services/ConfigService' import ConfigService from '@/services/ConfigService'
import { userStore } from "@/store/user"; import { userStore } from "@/store/user";
...@@ -117,7 +157,7 @@ ...@@ -117,7 +157,7 @@
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
import { injectKeyTemplate } from '@/types/injectKey' import { injectKeyTemplate } from '@/types/injectKey'
import LayoutPool from '../Editor/Thumbnails/LayoutPool.vue' import LayoutPool from './LayoutPool.vue'
const { const {
userInfo userInfo
...@@ -129,6 +169,11 @@ ...@@ -129,6 +169,11 @@
const dataList = ref([] as Array < any > ); //模板数据列表 const dataList = ref([] as Array < any > ); //模板数据列表
const currentPage = ref(1 as Number); const currentPage = ref(1 as Number);
const datas = reactive({
TemplateRow: {},
DetailsVisible: false,
loading: false,
})
const queryObj = reactive({ const queryObj = reactive({
pageIndex: 1, pageIndex: 1,
pageSize: 20, pageSize: 20,
...@@ -139,7 +184,6 @@ ...@@ -139,7 +184,6 @@
ColorName: '', //颜色名称 ColorName: '', //颜色名称
totalCount: 0, //总调试 totalCount: 0, //总调试
pageCount: 0, //总页数 pageCount: 0, //总页数
loading: false,
}) })
const loading = ref(false as any) const loading = ref(false as any)
...@@ -148,15 +192,20 @@ ...@@ -148,15 +192,20 @@
const marketStore = useScreenStore() const marketStore = useScreenStore()
const isModelStore = useScreenStore() const isModelStore = useScreenStore()
const layoutsStore = useSlidesStore() const layoutsStore = useSlidesStore()
const { screening, market, model, isModel, ConfigId} = storeToRefs(useScreenStore()) const TempIdStore = useScreenStore()
const { screening, market, model, isModel, ConfigId, TempId} = storeToRefs(useScreenStore())
const addTemplate = () =>{ const addTemplate = () =>{
marketStore.setMarket(!market) marketStore.setMarket(!market)
// TempIdStore.setTempId(0)
searchData.value.TempId = 0
} }
// 查看所有子模版 // 查看所有子模版
const getTemplate = async (item) => { const getTemplate = async (item) => {
queryObj.loading = true datas.DetailsVisible = true
datas.TemplateRow = JSON.parse(JSON.stringify(item))
datas.loading = true
layoutsStore.setLayouts([]) layoutsStore.setLayouts([])
try { try {
let queryMsg = { let queryMsg = {
...@@ -176,44 +225,23 @@ ...@@ -176,44 +225,23 @@
newSlides = SlidesData newSlides = SlidesData
} }
layoutsStore.setLayouts(JSON.parse(JSON.stringify(newSlides))) layoutsStore.setLayouts(JSON.parse(JSON.stringify(newSlides)))
queryObj.loading = false
} }
} catch (error) { datas.loading = false
console.log("GetTripTemplateSlide", error);
queryObj.loading = false
}
}
/**
* 根据团期配置编号获取行程详情
*/
const GetTripConfig = async () =>{
try {
if(!ConfigId||isModel) return
let queryMsg = {
ConfigId: ConfigId
}
let datasRes = await ConfigService.triptemplateGetTripConfig(queryMsg);
if (datasRes.data.resultCode == 1) {
if(datasRes.data.data&&datasRes.data.data.length>0&&datasRes.data.data[0].TempId){
searchData.value.TempId = datasRes.data.data[0].TempId
isModelStore.setIsModel(true)
marketStore.setMarket(!market)
}
}
} catch (error) { } catch (error) {
console.log("triptemplate_GetTripConfig", error); console.log("GetTripTemplateSlide", error);
datas.loading = false
} }
} }
GetTripConfig()
/** /**
* 页面跳转 * 页面跳转
*/ */
const goToTemplate = (item: any) => { const goToTemplate = (item: any) => {
if(!ConfigId.value&&!model.value) return if(!ConfigId.value&&!model.value) return
datas.DetailsVisible = false
searchData.value.TempId = item.TempId searchData.value.TempId = item.TempId
marketStore.setMarket(!market) marketStore.setMarket(!market)
datas.TemplateRow = {}
// console.log("item", item.TempId); // console.log("item", item.TempId);
} }
...@@ -310,7 +338,7 @@ ...@@ -310,7 +338,7 @@
queryTemplateBySearchHandler(); queryTemplateBySearchHandler();
</script> </script>
<style scoped> <style lang="scss" scoped>
@import url('../../assets/styles/common.css'); @import url('../../assets/styles/common.css');
@font-face { @font-face {
...@@ -338,6 +366,36 @@ ...@@ -338,6 +366,36 @@
} }
.MarketIndexList{ .MarketIndexList{
width: 100%; width: 100%;
position: relative;
overflow: hidden;
}
.MarketIndexList-Hover{
z-index: 1;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(23,23,23,0.7);
opacity: 0;
transition: opacity 2s ease;
-webkit-transition: opacity 2s ease;
-moz-transition: opacity 2s ease;
-ms-transition: opacity 2s ease;
-o-transition: opacity 2s ease;
display: flex;
justify-content: center;
align-items: center;
color: $themeHoverColor;
}
.MarketIndexList:hover .MarketIndexList-Hover{
opacity: 1;
}
.MarketIndexList-Hover div span{
display: inline-block;
background: #fff;
border-radius: 4px;
padding: 0 10px 3px 10px;
} }
.MarketIndexListBox:hover{ .MarketIndexListBox:hover{
position: relative; position: relative;
...@@ -378,4 +436,7 @@ ...@@ -378,4 +436,7 @@
margin-right: 30px; margin-right: 30px;
margin-top: 5px; margin-top: 5px;
} }
.layout-item{
width: 180px;
}
</style> </style>
\ No newline at end of file
<template>
<div class="layout-pool">
<div
class="layout-item q-ma-md"
v-for="slide in layouts"
:key="slide.id"
@click="selectSlideTemplate(slide)"
>
<ThumbnailSlide class="thumbnail" :slide="slide" :size="180" />
</div>
</div>
</template>
<script lang="ts" setup>
import { storeToRefs } from 'pinia'
import { useSlidesStore } from '@/store'
import type { Slide } from '@/types/slides'
import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'
const emit = defineEmits<{
(event: 'select', payload: Slide): void
}>()
const { layouts } = storeToRefs(useSlidesStore())
const selectSlideTemplate = (slide: Slide) => {
emit('select', slide)
}
</script>
<style lang="scss" scoped>
.layout-pool {
width: 394px;
height: 500px;
padding: 2px;
/* margin-right: -12px;
padding-right: 12px; */
overflow: auto;
@include flex-grid-layout();
}
.layout-item {
/* @include flex-grid-layout-children(2, 48%); */
width: 180px;
&:nth-last-child(2), &:last-child {
margin-bottom: 0;
}
.thumbnail {
outline: 1px solid $borderColor;
cursor: pointer;
&:hover {
outline-color: $themeColor;
}
}
}
</style>
\ No newline at end of file
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