Commit ccce2e20 authored by 罗超's avatar 罗超

新增第三方资源导入功能

parent ef28abb0
...@@ -26,6 +26,7 @@ declare module 'vue' { ...@@ -26,6 +26,7 @@ declare module 'vue' {
ElDivider: typeof import('element-plus/es')['ElDivider'] ElDivider: typeof import('element-plus/es')['ElDivider']
ElEmpty: typeof import('element-plus/es')['ElEmpty'] ElEmpty: typeof import('element-plus/es')['ElEmpty']
ElIcon: typeof import('element-plus/es')['ElIcon'] ElIcon: typeof import('element-plus/es')['ElIcon']
ElImage: typeof import('element-plus/es')['ElImage']
ElInput: typeof import('element-plus/es')['ElInput'] ElInput: typeof import('element-plus/es')['ElInput']
ElOption: typeof import('element-plus/es')['ElOption'] ElOption: typeof import('element-plus/es')['ElOption']
ElPagination: typeof import('element-plus/es')['ElPagination'] ElPagination: typeof import('element-plus/es')['ElPagination']
......
import {compressionThumbnail} from '@/utils/psdParser/compressor'
class FileService{ class FileService{
static getImageSizeWithoutDownloading = async (url: string): Promise<{ width: number; height: number }> => { static getImageSizeWithoutDownloading = async (url: string): Promise<{ width: number; height: number }> => {
const response = await fetch(url, { method: 'HEAD' }); // Use HEAD request to get metadata const response = await fetch(url, { method: 'HEAD' }); // Use HEAD request to get metadata
...@@ -30,6 +32,35 @@ class FileService{ ...@@ -30,6 +32,35 @@ class FileService{
image.src = objectURL; image.src = objectURL;
}); });
} }
static convertNetworkToBase64Async = async (url:string): Promise<{ width: number; height: number,url:string }> =>{
let result:{ width: number; height: number,url:string }={
width:0,
height:0,
url:''
}
const response = await fetch(url)
const blob = await response.blob()
const objectURL = URL.createObjectURL(blob);
const image = new Image();
return new Promise(async (resolve, reject) => {
image.onload = () => {
result.width=image.width
result.height=image.height
const reader = new FileReader();
reader.onload = async (e) => {
result.url = reader.result as string
result.url = await compressionThumbnail(result.url,"image/jpeg", 0, 0.9)
resolve(result)
}
reader.readAsDataURL(blob);
};
image.onerror = reject;
image.src = objectURL;
})
}
} }
export default FileService export default FileService
\ No newline at end of file
import Api,{ HttpResponse, Result } from './../utils/request';
class SpiderService{
static async GetThirdPartyResourceAsync(params : any):Promise<HttpResponse>{
return Api.Post("mongoscenic_GetMongoScenicPage",params)
}
}
export default SpiderService
\ No newline at end of file
<template>
<div v-if="!currentPoi">
<div class="row items-center">
<div class="text-small" style="color:#BABABA;">已接入:路书云,马蜂窝</div>
<div class="col q-ml-lg">
<el-input v-model="keyValue" placeholder="输入国家/城市/名称快速查找" clearable @keyup.enter="changeKeyValueHandler">
<template #append>
<el-button type="primary" @click="changeKeyValueHandler">搜索</el-button>
</template>
</el-input>
</div>
</div>
<div class="q-mt-lg row wrap" style="margin-left: -10px;" v-if="loading || (data && data.length>0)" v-loading="loading">
<div class="spider-item" v-for="x in data" @click="currentPoi=x">
<img :src="x.PicPath" v-if="x.PicPath"/>
<div class="subtitle" :title="x.Name">{{ x.Name }}</div>
<div class="imgcount row items-center">
<el-icon class="q-mr-md"><Picture /></el-icon>
<span class="alifont">{{ x.ImgArray?x.ImgArray.length:0 }}</span>
</div>
</div>
</div>
<el-empty class="q-ma-lg" description="暂无数据" v-if="!loading&& (!data || data.length==0)" />
<div class="q-mt-md" style="display: flex;justify-content: center;" v-if="data && data.length>0">
<el-pagination
v-model:current-page="queryParameters.pageIndex"
:page-size="queryParameters.pageSize"
small-padding
layout="prev, pager, next"
:total="total"
@size-change="SearchHandler"
@current-change="SearchHandler"
/>
</div>
</div>
<div v-else>
<div class="row item-center">
<el-button type="primary" @click="currentPoi=null" link><el-icon><ArrowLeft /></el-icon> 返回</el-button>
<div class="q-ml-lg text-small">【{{ currentPoi.Name }}】相关图片</div>
</div>
<div class="q-mt-lg row wrap" style="margin-left: -10px;height: 440px;overflow-y: auto;">
<div class="spider-item" v-for="x in currentPoi.ImgArray">
<img :src="x" />
<div class="img-box">
<el-image
style="width: 100%; height: 100%"
:src="x"
:zoom-rate="1.2"
:max-scale="7"
:min-scale="0.2"
:preview-src-list="[x]"
fit="cover"
/>
</div>
<div class="imgcount" style="padding:0px;">
<el-checkbox label="" :checked="chooseUrl==x" @click.stop="changeChooseUrlHandler(x)"></el-checkbox>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ApiResult } from '@/configs/axios';
import SpiderService from '@/services/SpiderService';
import { ElLoading } from 'element-plus';
import { ref,defineEmits } from 'vue';
import { Picture,ArrowLeft } from '@element-plus/icons-vue';
const emit = defineEmits<{
(event: 'change',payload:string): void
}>()
const keyValue = ref('')
const loading = ref(false)
const data = ref<any[]>()
const currentPoi = ref<any>()
const chooseUrl = ref('')
const queryParameters = ref<{
pageIndex:number,
pageSize:number,
Name?:string
}>({
pageIndex:1,
pageSize:16,
Name:''
})
const total = ref(0)
const SearchHandler = async ()=>{
loading.value=true
queryParameters.value.Name=keyValue.value
data.value=[]
let response = await SpiderService.GetThirdPartyResourceAsync(queryParameters.value)
if(response.data.resultCode == ApiResult.SUCCESS){
data.value = checkPoiCoverImg(response.data.data.pageData)
total.value = response.data.data.count
}
loading.value=false
}
const checkPoiCoverImg = (array:any[])=>{
array.forEach(x=>{
if((!x.PicPath||x.PicPath=='') && x.ImgArray && x.ImgArray.length>0){
x.PicPath=x.ImgArray[0]
}else if(x.PicPath && x.PicPath!=''){
if(x.PicPath.indexOf('?')!=-1) x.PicPath=x.PicPath.split('?')[0]
x.ImgArray = x.ImgArray ?? []
x.ImgArray.splice(0,0,x.PicPath)
}
})
return array
}
const changeKeyValueHandler = ()=>{
if(queryParameters.value.Name!=keyValue.value){
queryParameters.value.pageIndex=1
total.value=0
SearchHandler()
}
}
const changeChooseUrlHandler = (url:string)=>{
chooseUrl.value = chooseUrl.value==url?'':url
emit('change',chooseUrl.value)
}
SearchHandler()
</script>
<style scoped>
.spider-item{
width:calc(25% - 10px) !important;
height: 0;
overflow: hidden;
border-radius: 5px;
position: relative;
padding-bottom: 15.25%;
margin-left: 10px;
margin-bottom: 10px;
cursor: pointer;
}
.spider-item img{
width: 100%;
height: 100%;
position: absolute;
object-fit: cover;
}
.spider-item .img-box{
width: 100%;
height: 100%;
position: absolute;
}
.spider-item .subtitle {
font-size: 13px;
color: #fff;
text-shadow: 2px 2px 5px rgba(0,0,0,0.5);
word-break: break-all;
z-index: 2;
background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.5));
padding: 10px;
position: absolute;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.spider-item .imgcount {
font-size: 12px;
color: #fff;
text-shadow: 2px 2px 5px rgba(0,0,0,0.5);
word-break: break-all;
z-index: 2;
background: linear-gradient(rgba(0, 0, 0, 0.5),rgba(0, 0, 0, 0));
padding: 10px;
position: absolute;
left: 0;
right: 0;
top: 0;
text-align: right;
}
</style>
\ No newline at end of file
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<div class="text-title">选择、上传图片</div> <div class="text-title">选择、上传图片</div>
</template> </template>
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick"> <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
<el-tab-pane label="erp资料库" name="1"> <el-tab-pane label="ERP资料库" name="1">
<el-row class="q-mb-md"> <el-row class="q-mb-md">
<el-col :span="6"> <el-col :span="6">
<el-select v-model="datas.queryMsg.Type" class="m-2" <el-select v-model="datas.queryMsg.Type" class="m-2"
...@@ -55,6 +55,9 @@ ...@@ -55,6 +55,9 @@
</div> </div>
</el-tab-pane> </el-tab-pane>
<el-tab-pane label="第三方资源" name="4">
<SpiderResource @change="(payload:string)=> spiderImgUrl=payload"></SpiderResource>
</el-tab-pane>
<el-tab-pane label="本地图" name="2"> <el-tab-pane label="本地图" name="2">
<FileInput @change="files => insertImageElement(files)"> <FileInput @change="files => insertImageElement(files)">
<div class="upload-box"> <div class="upload-box">
...@@ -88,7 +91,7 @@ ...@@ -88,7 +91,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive, inject } from 'vue' import { ref, reactive, inject } from 'vue'
import { storeToRefs } from 'pinia' import { storeToRefs } from 'pinia'
import type { UploadProps, UploadUserFile,UploadInstance } from 'element-plus' import { type UploadProps, type UploadUserFile,type UploadInstance, ElMessage, ElLoading } from 'element-plus'
import useCreateElement from '@/hooks/useCreateElement' import useCreateElement from '@/hooks/useCreateElement'
import useHistorySnapshot from '@/hooks/useHistorySnapshot' import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import { getImageDataURL } from '@/utils/image' import { getImageDataURL } from '@/utils/image'
...@@ -97,6 +100,7 @@ import { injectKeyDataSource } from '@/types/injectKey' ...@@ -97,6 +100,7 @@ import { injectKeyDataSource } from '@/types/injectKey'
import ConfigService from '@/services/ConfigService' import ConfigService from '@/services/ConfigService'
import { VIEWPORT_SIZE, VIEWPORT_VER_SIZE } from '@/configs/canvas' import { VIEWPORT_SIZE, VIEWPORT_VER_SIZE } from '@/configs/canvas'
import FileService from '@/services/FileService' import FileService from '@/services/FileService'
import SpiderResource from '@/views/Editor/CanvasTool/SpiderResource.vue'
import FileInput from '@/components/FileInput.vue' import FileInput from '@/components/FileInput.vue'
const showVisible = ref(true) const showVisible = ref(true)
...@@ -108,12 +112,13 @@ const imageFile = ref({}) ...@@ -108,12 +112,13 @@ const imageFile = ref({})
const imgOnline = ref('') const imgOnline = ref('')
const imgPath = ref('') const imgPath = ref('')
const imgUrl = ref('') const imgUrl = ref('')
const spiderImgUrl = ref('')
const currentPage = ref(1) const currentPage = ref(1)
const upload = ref<UploadInstance>() const upload = ref<UploadInstance>()
const imgType = ref(0) // 1 插入图片 2替换图片 const imgType = ref(0) // 1 插入图片 2替换图片
imgType.value = inject('imgType') imgType.value = inject('imgType')
const propsDatas = ref({src: ''}) const propsDatas = ref<any>({})
const typeLists = ref([ const typeLists = ref([
{label: '不限',value:0}, {label: '不限',value:0},
{label: '酒店',value:1}, {label: '酒店',value:1},
...@@ -166,15 +171,19 @@ const insertImageElement = (files: FileList) => { ...@@ -166,15 +171,19 @@ const insertImageElement = (files: FileList) => {
const setImgs = async () => { const setImgs = async () => {
let text = '请选择图片' let text = '请选择图片'
let url = imgOnline.value let url = imgOnline.value
let downloadInfo:any = {}
if(activeName.value=='1') propsDatas.value = { src: imgOnline.value } if(activeName.value=='1') propsDatas.value = { src: imgOnline.value }
else if(activeName.value=='2') { else if(activeName.value=='2') {
text = '请上传图片' text = '请上传图片'
url = imgPath.value url = imgPath.value
} } else if(activeName.value=='3') {
else if(activeName.value=='3') {
text = '请输入图片url地址' text = '请输入图片url地址'
url = imgUrl.value url = imgUrl.value
propsDatas.value = { src: imgUrl.value } propsDatas.value = { src: imgUrl.value }
} else if(activeName.value=='4') {
text = '请选择你需要的图片'
url = spiderImgUrl.value
propsDatas.value = { src: spiderImgUrl.value }
} }
if(!url){ if(!url){
return ElMessage({ return ElMessage({
...@@ -183,65 +192,77 @@ const setImgs = async () => { ...@@ -183,65 +192,77 @@ const setImgs = async () => {
type: 'warning', type: 'warning',
}) })
} }
if(activeName.value=='4'){
const downLoading = ElLoading.service({
lock:true,
text:'正在导入图片'
})
try {
downloadInfo = await FileService.convertNetworkToBase64Async(url)
url = downloadInfo.url
propsDatas.value.src = url
} catch (error) {}
if(downloadInfo.url == ''){
ElMessage({
showClose: true,
message: '图片导入失败,请重试',
type: 'error',
})
return
}
downLoading.close()
}
if(imgType.value==1){ if(imgType.value==1){
createImageElement(url) createImageElement(url)
close() close()
} }
if(imgType.value==2){ if(imgType.value==2){
const slidesData = slides.value let maxWidth = VIEWPORT_SIZE,maxHeight = VIEWPORT_VER_SIZE, viewportRatio = slidesStore.viewportRatio
for (let index = 0; index < slidesData.length; index++) { if(viewportRatio<1){
const x = slidesData[index] as any; maxWidth = VIEWPORT_VER_SIZE
for (let j = 0; j < x.elements.length; j++) { maxHeight = VIEWPORT_SIZE
const y = x.elements[j]; }
if(slideIndex.value==index&&y.id==handleElementId.value){
let maxWidth = VIEWPORT_SIZE,maxHeight = VIEWPORT_VER_SIZE, viewportRatio = slidesStore.viewportRatio if(activeName.value=='1'||activeName.value=='3' || activeName.value == '4'){
if(viewportRatio<1){ let tempSize = downloadInfo
maxWidth = VIEWPORT_VER_SIZE if(activeName.value != '4') tempSize = await FileService.getImageSizeWithoutDownloading(propsDatas.value.src)
maxHeight = VIEWPORT_SIZE if(tempSize.width>maxWidth){
let ratio = maxWidth/tempSize.width
tempSize.width = maxWidth
tempSize.height = tempSize.height*ratio
}
if(tempSize.height>maxHeight){
let ratio = maxHeight/tempSize.height
tempSize.height = maxHeight
tempSize.width = tempSize.width*ratio
}
if(handleElement.left<0) propsDatas.value.left=0
if(handleElement.top<0) propsDatas.value.top=0
propsDatas.value.width = tempSize.width
propsDatas.value.height = tempSize.height
} else{
var img = new Image()
img.src = propsDatas.value.src
img.onload = () => {
if(img.width>maxWidth){
let ratio = maxWidth/img.width
img.width = maxWidth
img.height = img.height*ratio
} }
let tempSize = null if(img.height>maxHeight){
if(activeName.value==1||activeName.value==3){ let ratio = maxHeight/img.height
tempSize = await FileService.getImageSizeWithoutDownloading(propsDatas.value.src) img.height = maxHeight
if(tempSize.width>maxWidth){ img.width = img.width*ratio
let ratio = maxWidth/tempSize.width
tempSize.width = maxWidth
tempSize.height = tempSize.height*ratio
}
if(tempSize.height>maxHeight){
let ratio = maxHeight/tempSize.height
tempSize.height = maxHeight
tempSize.width = tempSize.width*ratio
}
if(y.left<0)y.left=0
if(y.top<0)y.top=0
y.width = tempSize.width
y.height = tempSize.height
}else{
var img = new Image()
img.src = propsDatas.value.src
img.onload = () => {
if(img.width>maxWidth){
let ratio = maxWidth/img.width
img.width = maxWidth
img.height = img.height*ratio
}
if(img.height>maxHeight){
let ratio = maxHeight/img.height
img.height = maxHeight
img.width = img.width*ratio
}
if(y.left<0)y.left=0
if(y.top<0)y.top=0
y.width = img.width
y.height = img.height
}
y.src = propsDatas.value.src
y.fixedRatio = true
} }
if(handleElement.left<0)propsDatas.value.left=0
if(handleElement.top<0)propsDatas.value.top=0
propsDatas.value.width = img.width
propsDatas.value.height = img.height
} }
}
} }
propsDatas.value.fixedRatio = true
slidesStore.updateElement({ id: handleElementId.value, props:propsDatas.value }) slidesStore.updateElement({ id: handleElementId.value, props:propsDatas.value })
addHistorySnapshot() addHistorySnapshot()
close() close()
......
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