提交 6c241513 authored 作者: 龙菲's avatar 龙菲

暂时修改以图搜图页面UI

上级 96e9c6bc
<template>
<div class="content">
<div class="bg">
<div class="main">
<img src="@/assets/imgs/show/bg.png" alt="" class="main" />
</div>
</div>
<div class="wrapper wow animate__animated animate__fadeInUpBig">
<div class="breadcrumb">
<Breadcrumb :list="guideList" />
</div>
<!-- tabs -->
<div class="inner">
<div class="inner-left">
<!-- 基本信息 -->
<div class="info-container-right" v-if="nodeActive === 'intro'">
<div class="wow animate__animated animate__fadeInRight">
<div class="info-title">
<span>{{ CRDetail.name }} </span>
</div>
<div class="basic-info">
<div class="body-item" v-if="CRDetail.yearsLabel">
<span class="value">{{ CRDetail.yearsLabel || "暂无" }}</span>
</div>
<div class="body-item" v-if="CRDetail.sourceWay">
<span class="value">{{ CRDetail.sourceWay || "暂无" }}</span>
</div>
<div class="body-item" v-if="CRDetail.typeLabel">
<span class="value">{{ CRDetail.typeLabel || "暂无" }}</span>
</div>
<div class="body-item" v-if="CRDetail.levelLabel">
<span class="value">{{ CRDetail.levelLabel || "暂无" }}</span>
</div>
<div class="body-item" v-if="CRDetail.textureTypeLabel">
<span class="value">{{
CRDetail.textureTypeLabel || "暂无"
}}</span>
</div>
<div class="body-item" v-if="CRDetail.detailSize">
<span class="value">{{ CRDetail.detailSize || "暂无" }}</span>
</div>
<div class="body-item" v-if="CRDetail.deptName">
<span class="value">{{ CRDetail.deptName || "暂无" }}</span>
</div>
</div>
<!-- 文物简介 -->
<div
class="content-item display-detail_intro"
v-if="CRDetail.intro"
id="intro"
>
<div class="intro-content">
<div
class="intro-content-container"
v-html="CRDetail.intro"
></div>
</div>
</div>
<div class="bottom">
<div class="tools">
<ReaderOperations
:info="CRDetail"
:sourceType="'biz_cultural_relic'"
color="#333"
selectColor="#333"
@reload="loadDetail"
/>
</div>
<div class="showIcon" v-if="CRDetail.url3d" @click="handleTo3D">
<svg-icon icon-class="3d" class="icon"></svg-icon
>查看文物3D模型
</div>
</div>
</div>
</div>
<!-- 音频 -->
<!-- <div
class="audio wow animate__animated animate__fadeInRight"
:style="{
animationPlayState: audioPlaying ? 'running' : 'paused',
}"
@click="handleClickAudio"
v-if="CRDetail.audiosVo && CRDetail.audiosVo.length > 0"
>
<svg-icon icon-class="music"></svg-icon>
<AudioPlayer
style="display: none"
:url="$getFullUrl(CRDetail.audiosVo[0].url)"
ref="AudioPlayer"
/>
</div> -->
<!-- 文物视频 -->
<div
class="content-item display-detail_videos"
v-if="
CRDetail.videosVo &&
CRDetail.videosVo.length > 0 &&
nodeActive === 'videosVo'
"
id="videosVo"
>
<div class="video-title">
<!-- <i class="el-icon-video-camera"></i> -->
相关视频
</div>
<div class="video-names">
<div
class="video-item"
v-for="(item, index) in CRDetail.videosVo"
:key="index"
@click="handleChangeCurrentVideo(item)"
>
<div
:class="[
'name',
currentVideo && item.fileId == currentVideo.fileId
? 'active'
: '',
]"
>
{{ item.name.split(".")[0] }}
</div>
</div>
</div>
<video-player
v-if="currentVideo"
:src="$getFullUrl(currentVideo.url)"
class="video-box"
></video-player>
</div>
<!--相关文物 -->
<div
class="content-item display-detail_relate_rc"
ref="units"
id="relateRelics"
v-if="nodeActive === 'relateRelics'"
>
<div class="recommend-type">
<el-radio-group v-model="currentRcKey" size="small">
<el-radio :label="'type'" v-if="CRDetail.type">同类别</el-radio>
<el-radio :label="'years'" v-if="CRDetail.years"
>同年代</el-radio
>
<el-radio :label="'deptId'" v-if="CRDetail.deptId"
>同馆藏</el-radio
>
</el-radio-group>
</div>
<div class="recommend-obj">
<div class="recommend-obj-node" v-if="relateRelics.length > 0">
<div v-for="(item, index) in relateRelics" :key="index">
<div class="img-container" @click="handleToCr(item)">
<img
:src="
$getFullUrl(
item.faceImageMiddleUrl || item.faceImagePressUrl
)
"
alt=""
/>
</div>
<div class="cr-name">{{ item.name }}</div>
</div>
</div>
<el-empty
v-else
description="暂无相关推荐,去看看其他的吧~"
></el-empty>
</div>
</div>
<!-- 相关文献 -->
<div
class="content-item display-detail_lts"
id="literatureVo"
v-if="
CRDetail.literatureVo &&
CRDetail.literatureVo.length > 0 &&
nodeActive === 'literatureVo'
"
>
<div class="title">相关文献</div>
<div class="lts-content">
<el-scrollbar style="height: 100%">
<div
class="lt-item"
v-for="(item, index) in CRDetail.literatureVo"
:key="index"
@click="handleViewLt(item)"
>
<span class="lt-order">[{{ index + 1 }}]</span>
<span class="lt-authors" v-if="item.authors"
>{{ item.authors }}.</span
>
<span class="lt-name" v-if="item.name">{{ item.name }}.</span>
<span class="lt-source" v-if="item.source"
>{{ item.source }}.</span
>
<span class="lt-date" v-if="item.date">{{ item.date }}</span>
</div>
</el-scrollbar>
</div>
</div>
</div>
<!-- 展览基本信息 -->
<div class="inner-right wow animate__animated animate__fadeInLeft">
<swiper :options="swiperOption2" ref="crSwiper">
<swiper-slide v-for="(item, i) in imagesVo" :key="i">
<div
class="img-container"
@click.stop="handelPreviewImages(imagesVo, i)"
>
<img
:src="$getFullUrl(item.middleUrl || item.pressUrl)"
alt=""
/>
</div>
</swiper-slide>
<div class="swiper-pagination" slot="pagination"></div>
</swiper>
<div class="swiper-button-prev" slot="button-prev">
<i class="el-icon-arrow-left"></i>
</div>
<div class="swiper-button-next" slot="button-next">
<i class="el-icon-arrow-right"></i>
</div>
</div>
<ul class="menu-tabs">
<li
:class="{ active: nodeActive === 'intro' }"
@click="handleTabClick('intro')"
>
<span>文物简介</span>
</li>
<template v-for="node in tabbarData">
<li
:key="node.domId"
:class="{ active: nodeActive === node.domId }"
@click="handleTabClick(node.domId)"
v-if="
node.domId !== 'intro' &&
CRDetail[`${node.domId}`] &&
CRDetail[`${node.domId}`].length > 0
"
>
<span>{{ node.name }}</span>
</li>
</template>
<li
:class="{ active: nodeActive === 'relateRelics' }"
@click="handleTabClick('relateRelics')"
>
<span>相关文物</span>
</li>
</ul>
</div>
</div>
</div>
</template>
<script>
import AudioPlayer from "@/components/AudioPlayer";
import Video from "@/components/Video";
import ReaderOperations from "@/components/ReaderOperations";
import { getRCDetailByIdV2, crRecommendByPage } from "@/api/culturalRelic";
import { previewFile } from "@/utils/index";
import videoPlayer from "@/components/VideoPlayer";
import SlideImage from "@/components/SlideImage/slider.vue";
import { isElementInViewport2 } from "@/utils/index";
import { swiper, swiperSlide } from "vue-awesome-swiper";
import Breadcrumb from "@/components/Breadcrumb/index";
export default {
components: {
AudioPlayer,
ReaderOperations,
Video,
videoPlayer,
SlideImage,
swiper,
swiperSlide,
Breadcrumb,
"el-image-viewer": () =>
import("element-ui/packages/image/src/image-viewer"),
},
data() {
let vm = this;
return {
CRDetail: {},
relateRelics: [],
audioPlaying: true,
page: null,
currentRcKey: "type",
currentVideo: null,
currentTab: null,
isFixed: false,
tabbarData: [
{
name: "文物简介",
domId: "intro",
},
{
name: "相关视频",
domId: "videosVo",
},
{
name: "相关文物",
domId: "relateRelics",
},
{
name: "相关文献",
domId: "literatureVo",
},
],
// tabbarItems: ["文物简介", "相关视频", "相关文物", "相关文献"],
nodeActive: "intro",
swiperOption2: {
// effect: "coverflow",
fadeEffect: {
crossFade: true,
},
// grabCursor: true,
// 显示分页
pagination: {
el: ".swiper-pagination",
clickable: true, //允许分页点击跳转
},
// 设置点击箭头
navigation: {
nextEl: ".swiper-button-next",
prevEl: ".swiper-button-prev",
},
},
guideList: [
{
name: "首页",
path: "/",
},
{
name: "文物展示",
path: "/culturalRelic",
},
],
};
},
watch: {
"$route.params.crId"(value) {
this.loadDetail(value);
},
currentRcKey(key) {
this.loadCrRecommend();
},
},
computed: {
imagesVo() {
if (Object.keys(this.CRDetail).length == 0) {
return;
}
if (this.CRDetail.imagesVo.length > 0) {
return this.CRDetail.imagesVo;
} else {
return [
{
pressUrl: this.CRDetail.faceImagePressUrl,
url: this.CRDetail.faceImageUrl,
middleUrl: this.CRDetail.faceImageMiddleUrl,
},
];
}
},
},
async mounted() {
let crId = this.$route.params.crId;
this.loadDetail(crId);
/* setTimeout(() => {
window.addEventListener("scroll", this.initHeight);
this.offsetTop = document.querySelector("#tabbar").offsetTop; //距离offsetParent的高度
this.tabbarData.map((item) => {
let dom = document.getElementById(item.domId);
if (dom) {
item.position = dom.offsetTop - 320; //100navbar 55tabbar
}
});
}, 500); */
},
beforeRouteLeave(to, form, next) {
// 离开路由移除滚动事件
window.removeEventListener("scroll", this.initHeight);
next();
},
methods: {
async loadDetail(crId) {
if (crId) {
let res = await getRCDetailByIdV2({ crId });
if (res.code == 0) {
this.CRDetail = res.data.culturalRelicVo;
this.guideList.push({
name: this.CRDetail.name,
path: `/culturalRelic/${this.CRDetail.crId}`,
});
if (this.CRDetail.videosVo && this.CRDetail.videosVo.length > 0) {
this.currentVideo = this.CRDetail.videosVo[0];
}
// 获取关联文物
this.loadCrRecommend();
this.$nextTick(() => {
if (this.CRDetail.audiosVo && this.CRDetail.audiosVo.length > 0) {
this.$message.info("正在播放当前文物讲解音频,点击按钮可关闭");
this.$refs.AudioPlayer.play();
}
});
}
}
},
async loadCrRecommend() {
const { crId } = this.CRDetail;
const params = {
crId,
page: 1,
limit: 4,
};
if (this.currentRcKey == "type") {
params.type = this.CRDetail.type;
}
if (this.currentRcKey == "years") {
params.years = this.CRDetail.years;
}
if (this.currentRcKey == "deptId") {
params.deptId = this.CRDetail.deptId;
}
let res = await crRecommendByPage(params);
this.relateRelics = res.data.records;
// console.log("res", res);
},
replaceFaceImage() {
var img = new Image(); //新建一个图片对象
let url; //最终显示的大图
// debugger
if (this.CRDetail.faceImagePressUrl) {
url = this.$getFullUrl(this.CRDetail.faceImageUrl);
} else if (this.CRDetail.imagesVo.length > 0) {
url = this.$getFullUrl(this.CRDetail.imagesVo[0].url);
}
let faceImage = document.getElementById("faceImage");
img.src = url;
img.onload = function () {
faceImage.src = url;
};
},
handleBack() {
this.$router.go(-1);
},
handleTo3D() {
this.$message.info("即将打开3D模型...");
setTimeout(() => {
window.open(this.CRDetail.url3d, "_blank");
}, 1000);
},
handelPreviewImages(items, index) {
this.imgList = items.map((item) => this.$getFullUrl(item.url));
const $viewer = this.$viewerApi({
images: this.imgList,
options: {
initialViewIndex: index,
zoomRatio: 1.4,
},
});
},
//禁止页面滚动
handleOverflowHidden() {
document.documentElement.style.overflowY = "hidden";
},
//恢复页面滚动
handleOverflowAuto() {
document.documentElement.style.overflowY = "auto";
},
handleToDetail(crId) {
const newPage = this.$router.resolve({
path: `culturalReli/${crId}`,
});
window.open(newPage.href, "_blank");
},
// 点击音频
handleClickAudio() {
this.audioPlaying = !this.audioPlaying;
if (this.audioPlaying) {
this.$refs["AudioPlayer"].play();
} else {
this.$refs["AudioPlayer"].pause();
}
},
handleToCr(item) {
const { crId } = item;
const newPage = this.$router.resolve({
path: "/culturalRelic/" + crId,
});
window.open(newPage.href, "_blank");
},
handleChangeCurrentVideo(video) {
this.currentVideo = video;
},
handleClickTabItem(item) {
this.currentTab = item;
if (item.position) {
document.documentElement.scrollTop = item.position;
}
},
initHeight() {
let scrollTop =
window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop;
this.isFixed = scrollTop > this.offsetTop - 155 ? true : false; //100为navbar的高度,55为tabbar的高度
this.tabbarData.map((item) => {
let content = document.getElementById(item.domId);
if (content && isElementInViewport2(content)) {
this.currentTab = item;
}
});
},
handleTabClick(type) {
this.nodeActive = type;
},
// 预览关联文献
handleViewLt(item) {
if (item.files[0].url) {
previewFile(item.files[0].url, item.files[0].name);
// window.open(item.files[0].url, '_blank')
} else {
this.$message.info("当前文献暂不支持在线浏览");
}
},
},
};
</script>
<style lang="scss">
// 自定义分页器样式
#page {
height: 30px;
display: flex;
justify-content: center;
}
.page-item {
cursor: pointer;
}
</style>
<style lang="scss" scoped>
$node-w: 700px;
.content {
position: relative;
.bg {
position: absolute;
top: 0;
left: 0;
z-index: 0;
width: 100%;
height: 100%;
> img {
width: 100%;
}
> .main {
width: 100%;
min-height: 100vh;
height: calc(100% + $nav-height);
position: absolute;
top: -$nav-height;
left: 0;
overflow: hidden;
> img {
width: 100%;
height: 100%;
}
}
> .color {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
> img {
position: absolute;
&.river {
width: 100%;
height: 727px;
bottom: -275px;
left: 0;
}
&.cb {
width: 830px;
height: 830px;
right: 100px;
top: 100px;
}
&.circle {
width: 454px;
height: 454px;
right: 283px;
top: 287px;
}
}
}
.mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgb(32 44 48 / 80%);
}
}
.breadcrumb {
padding: 60px;
position: relative;
z-index: 999;
}
.inner {
width: 100%;
display: flex;
position: relative;
padding: 0 120px 0 100px;
.inner-left {
// padding-left: 120px;
width: 50%;
min-height: calc(100vh - $nav-height - 100px);
position: relative;
.info-container-right {
color: #333;
width: $node-w;
padding-bottom: 80px;
.info-title {
display: flex;
justify-content: space-between;
// padding-top: 90px;
padding-bottom: 10px;
align-items: center;
> span {
font-size: 50px;
font-family: "华文行楷";
font-weight: 600;
}
.view-count {
> span {
margin-left: 10px;
color: #ddd;
}
> svg {
color: #ddd;
}
}
}
.basic-info {
margin-top: 30px;
// display: flex;
// flex-wrap: wrap;
color: #333;
position: relative;
font-weight: bold;
&::before {
content: "";
display: block;
height: calc(100% - 42px);
border-left: 1px dashed #333;
position: absolute;
top: 21px;
left: 0;
}
> div {
// line-height: 24px;
padding: 10px 0;
padding-left: 50px;
font-size: 18px;
position: relative;
&::before {
content: "";
display: block;
width: 40px;
border-top: 1px dashed #333;
position: absolute;
top: 50%;
left: 0;
}
}
}
}
#intro {
padding-top: 50px;
min-height: 350px;
.intro-content {
color: #333;
}
.intro-content-container {
width: $node-w;
font-size: 18px;
line-height: 2.5;
// font-weight: 600;
// text-indent: 32px;
}
}
.bottom {
padding-top: 20px;
display: flex;
font-size: 16px;
> .view-count {
width: 100px;
display: flex;
align-items: center;
> svg {
margin-right: 10px;
font-size: 28px;
}
}
> .tools {
width: 400px;
}
}
#relateRelics {
padding-top: 40px;
width: 800px;
.recommend-type {
display: flex;
justify-content: center;
}
.recommend-obj {
width: 100%;
overflow: hidden;
.recommend-obj-node {
display: flex;
flex-wrap: wrap;
justify-content: center;
> div {
width: 40%;
padding: 20px;
}
}
.img-container {
width: 100%;
height: 220px;
display: flex;
justify-content: center;
&:hover {
cursor: pointer;
> img {
transform: scale(1.2);
}
}
> img {
max-width: 100%;
max-height: 100%;
object-fit: contain;
transition: all 0.3s ease;
transform: scale(1);
}
}
.cr-name {
line-height: 32px;
text-align: center;
font-weight: 600;
font-family: "楷体";
color: #333;
font-size: 24px;
}
}
}
#literatureVo {
padding-top: 90px;
width: 800px;
color: #333;
.title {
font-size: 18px;
font-family: SourceHanSerifCN-Bold;
margin-bottom: 30px;
display: flex;
justify-content: center;
}
.lts-content {
height: 64vh;
overflow-y: auto;
overflow-x: hidden;
}
.lt-item {
border-bottom: 1px dashed #333;
padding: 10px 0;
cursor: pointer;
& > span {
padding: 0 4px;
}
}
}
}
.inner-right {
width: 50%;
height: calc(100vh - $nav-height - 100px);
display: flex;
align-items: center;
flex-direction: column;
padding: 0 0 80px 20px;
margin-right: 160px;
position: relative;
::v-deep .firstDiv {
position: unset;
transform: none;
}
.swiper-container {
width: 100%;
.swiper-slide {
display: flex;
justify-content: center;
height: 100%;
}
.img-container {
height: 100%;
width: 80%;
img {
height: 100%;
width: 100%;
object-fit: contain;
}
}
}
.swiper-button-next,
.swiper-button-prev {
background-image: none;
border: 2px solid #666;
background-color: rgba($deep-blue, 0.5);
width: 60px;
height: 60px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
font-weight: bolder;
font-size: 28px !important;
}
.swiper-button-next {
transform: translate(10px, -200px);
}
.swiper-button-prev {
transform: translate(-10px, -200px);
}
}
.menu-tabs {
line-height: 50px;
position: absolute;
right: 120px;
top: 0;
// width: 30px;
z-index: 10;
> li {
// border: 1px solid #333;
writing-mode: vertical-lr;
width: 45px;
height: 157px;
background-image: url(@/assets/imgs/show/outer.png);
background-size: cover;
position: relative;
+ li {
margin-top: 20px;
}
> span {
color: #fff;
width: 40px;
height: 138px;
background-image: url(@/assets/imgs/show/inner.png);
background-size: cover;
position: absolute;
left: 10px;
top: 10px;
display: flex;
align-items: center;
justify-content: center;
font-size: 18px;
letter-spacing: 5px;
}
&:hover,
&.active {
cursor: pointer;
// background-color: $deep-blue;
background-image: url(@/assets/imgs/show/outer-active.png);
> span {
// background: #b5800a;
background-image: url(@/assets/imgs/show/inner-active.png);
}
}
}
}
}
::v-deep .el-scrollbar__wrap {
overflow-x: hidden;
}
::v-deep .reader-operations {
color: #b2b2b2;
font-weight: 600;
font-family: "幼圆";
svg {
color: #b2b2b2;
}
}
}
::v-deep .el-carousel__item--card {
width: 100%;
height: 100%;
transform: translateX(0) scale(1) !important;
}
::v-deep .el-carousel {
height: 100%;
}
::v-deep .el-carousel__container {
height: 100%;
}
::v-deep .el-tree {
background: transparent;
.el-tree-node__content {
height: 50px;
:hover {
background: #fff;
color: $deep-blue;
}
}
}
::v-deep .el-radio__input {
display: none;
}
::v-deep .el-radio__label {
font-size: 24px;
padding-left: 0;
font-weight: bold;
}
/* ::v-deep .el-radio__input.is-checked + .el-radio__label {
color: #ffb836;
}
::v-deep .el-radio__input + .el-radio__label {
color: #fff;
} */
//左侧图片轮播
:v-deep .swiper {
height: 66vh;
}
:v-deep .swiper-container {
height: 100%;
width: 100%;
.swiper-wrapper {
height: 100%;
}
}
// ::v-deep .el-radio-button:first-child .el-radio-button__inner{
// border-radius: 0;
// }
// ::v-deep .el-radio-button:last-child .el-radio-button__inner{
// border-radius: 0;
// }
@keyframes filmMoveLeft {
0% {
transform: translateX(0);
}
100% {
transform: translateX(-1200px);
}
}
@keyframes filmMoveRight {
0% {
transform: translateX(0);
}
100% {
transform: translateX(1200px);
}
}
@keyframes audioRotate {
0% {
transform: rotateZ(0deg);
}
100% {
transform: rotateZ(360deg);
}
}
@-webkit-keyframes audioRotate {
0% {
transform: rotateZ(0deg);
}
100% {
transform: rotateZ(360deg);
}
}
.animation-play-paused {
animation-play-state: paused;
-webkit-animation-play-state: paused;
/* Safari 和 Chrome */
}
</style>
......@@ -275,22 +275,6 @@ export default {
defImg(e) {
e.target.src = require("@/assets/404_images/no-pic.png");
},
// handleTypeChange(value) {
// this.type = value;
// this.list.current = 1;
// this.loadData();
// },
// handleYearsChange(value) {
// if (value && value instanceof Array) {
// this.years = value[value.length - 1];
// } else {
// this.years = value;
// }
// this.list.current = 1;
// this.loadData();
// this.$refs.years.dropDownVisible = false;
// },
handleKeyWordChange(value) {
this.keyword = value;
this.loadData();
......
......@@ -10,11 +10,11 @@
:gap="30"
@click="handleClickImg"
>
<div class="img-info" slot-scope="props">
<!-- <div class="img-info" slot-scope="props">
<div class="name">{{ props.value.sourceName }}</div>
<div class="year">{{ props.value.yearsLabel }}</div>
<div class="deptName">{{ props.value.deptName }}</div>
</div>
</div> -->
<div slot="waterfall-over" class="load-over">已加载完全部</div>
</vue-waterfall-easy>
<el-empty v-else></el-empty>
......@@ -68,10 +68,10 @@ export default {
},
// 给父组件调用的
getWaterfallHeight() {
const emptySpace = 300;
this.waterfallHeight = "100vh";
this.waterfallHeight =
this.$refs.ImgList.offsetHeight + emptySpace + "px";
const emptySpace = 340;
this.waterfallHeight = "120vh";
const { offsetHeight } = this.$refs.ImgList;
this.waterfallHeight = offsetHeight + emptySpace + "px";
},
handleClickImg(event, { index, value }) {
// 阻止a标签跳转
......@@ -98,6 +98,11 @@ $box-shadow: 0 2px 8px rgba(28, 31, 35, 0.03),
box-shadow: none;
transition: all ease 0.3s;
cursor: pointer;
img {
border-radius: 8px;
box-shadow: rgba(0, 0, 0, 0.1) 0px 1px 3px 0px,
rgba(0, 0, 0, 0.06) 0px 1px 2px 0px;
}
&:hover {
transform: translateY(-10px);
......@@ -105,7 +110,7 @@ $box-shadow: 0 2px 8px rgba(28, 31, 35, 0.03),
}
::v-deep .vue-waterfall-easy-scroll {
overflow: auto !important;
overflow: hidden !important;
}
.load-over {
......
<template>
<div
:class="['app-container', 'search-pic', showResult ? 'show-result' : '']"
>
<div class="banner">
<div class="text" v-if="!showResult">
<div class="title">以图搜图</div>
<div class="subtitle">
以图搜图是一种方便快捷的搜索方式,它可以帮助您在海量的图片信息中快速找到您需要的图片。
<br />
通过上传或直接输入图片,以图搜图可以为您匹配相似的图片,或者根据图片内容找到相关的图片,让您可以更轻松地获取所需图片。
</div>
</div>
<div class="left-pic"></div>
<div class="right-pic"></div>
</div>
<div class="upload-wrapper">
<div class="upload-bar" @click="handleClickUpload">
<div class="left-area" title="点击此处上传图片">
<div class="text">点击此处上传图片</div>
<div class="camera">
<i class="el-icon-picture-outline" title="点击此处上传图片"></i>
</div>
</div>
<div class="right-button">以图搜图</div>
</div>
<el-upload
v-show="false"
ref="uploader"
class="upload-area"
accept=".jpg,.png"
action
:before-upload="handleBeforeUpload"
:show-file-list="false"
:on-success="handleSuccess"
:disabled="loading"
>
<el-button ref="uploadButton" class="upload-button">上传</el-button>
</el-upload>
</div>
<div class="current-pic" v-if="currentImg && showResult">
<div class="img-container">
<img :src="currentImg" alt="" />
</div>
根据您上传的图片,为您推荐相似图片{{ imgList.length }}
</div>
<ImgList v-if="showResult" :imgList="imgList" ref="List" />
</div>
</template>
<script>
import ImgList from "./components/imgList";
import { searchImageByUpload, searchImageByImg } from "@/api/culturalRelic";
export default {
components: {
ImgList,
},
data() {
return {
showResult: false, //是否展示图片结果
currentImg: "", //当前搜索的图片
loading: false, //是否正在上传
imgList: [],
size: 20,
};
},
mounted() {
const { fileId, fileUrl } = this.$route.query;
this.search(fileId, fileUrl);
},
methods: {
async search(fileId, fileUrl) {
if (!fileId || !fileUrl) {
return;
}
const formData = new FormData();
formData.append("size", this.size);
formData.append("fileId", fileId);
this.showResult = false; //先清空之前imgList已有的高度
const res = await searchImageByImg(formData);
if (res.code == 0) {
this.currentImg = fileUrl;
this.imgList = res.data;
this.showResult = true;
this.$nextTick(() => {
this.$refs["List"].getWaterfallHeight();
});
}
},
// 上传前钩子,处理文件类型
async handleBeforeUpload(file) {
let reg = /(?<=\.)[a-z]+$/g;
let fileType = file.name.match(reg) + "";
let typeArr = ["png", "jpg", "jpeg"];
if (!typeArr.includes(fileType)) {
this.$message.warning("上传文件格式错误!");
return;
}
let formData = new FormData();
formData.append("file", file);
formData.append("size", this.size);
const loading = this.$loading({
lock: true,
text: "正在海量的图库中搜索...",
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)",
});
this.showResult = false; //先清空之前imgList已有的高度
const res = await searchImageByUpload(formData);
if (res.code == 0) {
const length = res.data.length;
this.$message.success(`上传成功并获得${length}张相似图片`);
this.imgList = res.data;
this.showResult = true;
loading.close();
this.showCurrentImg(file);
this.clearRouterQuery();
this.$nextTick(() => {
this.$refs["List"].getWaterfallHeight();
});
}
},
clearRouterQuery() {
if (this.$route.query.fileId) {
const query = {};
this.$router.replace({ query });
}
},
showCurrentImg(file) {
const that = this;
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function (e) {
that.currentImg = this.result; //显示缩略图
};
},
// 上传成功之后的钩子
handleSuccess(res) {
this.loading = false;
},
// 关闭已上传的图片
handleCloseImg() {
this.currentImg = "";
},
// 点击上传
handleClickUpload() {
if (this.loading) {
this.$message.warning("当前有图片正在上传,请稍等~");
return;
}
this.$refs.uploader.$el.querySelector(".upload-button").click();
},
},
};
</script>
<style scoped lang="scss">
$box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;
$box-shadow-hover: rgba(0, 0, 0, 0.16) 0px 3px 6px,
rgba(0, 0, 0, 0.23) 0px 3px 6px;
$transition-ease-03s: all ease 0.3s;
.app-container {
width: 100%;
background-image: url("@/assets/imgs/home-new/all-bg.png");
}
.search-pic {
min-height: 70vh !important;
}
.show-result {
.banner {
height: 40px;
.text {
padding: 80px 12%;
}
}
}
.banner {
height: 400px;
width: 100%;
position: relative;
.left-pic {
transition: all ease 0.5s;
position: absolute;
left: -300px;
top: 100px;
height: 400px;
width: 700px;
background-size: contain;
background-image: url("@/assets/imgs/line-draft/6.png");
background-repeat: no-repeat;
z-index: 0;
}
.right-pic {
position: absolute;
right: 0;
bottom: 0;
height: 200px;
width: 300px;
background-size: contain;
background-image: url("@/assets/imgs/line-draft/3.png");
background-repeat: no-repeat;
z-index: 0;
}
.text {
width: 100%;
height: 100%;
z-index: 4;
color: #fff;
padding: 200px 12%;
opacity: 1;
transition: $transition-ease-03s;
color: $deep-blue;
.title {
font-size: 48px;
font-family: "SourceHanSerifCN-Bold";
text-align: center;
margin-bottom: 8px;
}
.subtitle {
text-align: center;
text-indent: 28px;
letter-spacing: 2px;
}
}
}
.upload-wrapper {
display: flex;
justify-content: center;
padding: 0 16%;
position: relative;
margin-bottom: 16px;
font-size: 18px;
.upload-bar {
box-shadow: $box-shadow;
background: #fff;
border-radius: 12px;
width: 100%;
display: flex;
justify-content: space-between;
padding: 10px 20px;
border: 1px solid $deep-blue;
position: relative;
cursor: pointer;
transition: $transition-ease-03s;
&:hover {
box-shadow: $box-shadow-hover;
}
.left-area {
display: flex;
justify-content: space-between;
padding-right: 16px;
width: 80%;
color: #999;
.text {
display: flex;
align-items: center;
}
i {
font-size: 30px;
color: $deep-blue;
}
}
.right-button {
width: 20%;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
background: $deep-blue;
height: 100%;
position: absolute;
right: 0;
top: 0;
border-radius: 0 12px 12px 0;
}
}
}
.current-pic {
display: flex;
justify-content: flex-start;
align-items: center;
padding: 20px 16%;
position: relative;
z-index: 2;
.img-container {
display: flex;
position: relative;
transition: all ease 0.3s;
margin-right: 16px;
width: 130px;
height: 130px;
background-color: #fff;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
}
.img-wrapper {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
::v-deep .el-loading-mask {
border-radius: 12px;
}
</style>
......@@ -38,7 +38,7 @@
<el-button ref="uploadButton" class="upload-button">上传</el-button>
</el-upload>
</div>
<div class="current-pic" v-if="currentImg">
<div class="current-pic" v-if="currentImg && showResult">
<div class="img-container">
<img :src="currentImg" alt="" />
</div>
......@@ -73,14 +73,18 @@ export default {
if (!fileId || !fileUrl) {
return;
}
const params = {
size: this.size,
fileId,
};
const res = await searchImageByImg(params);
const formData = new FormData();
formData.append("size", this.size);
formData.append("fileId", fileId);
this.showResult = false; //先清空之前imgList已有的高度
const res = await searchImageByImg(formData);
if (res.code == 0) {
this.currentImg = fileUrl;
this.imgList = res.data;
this.showResult = true;
this.$nextTick(() => {
this.$refs["List"].getWaterfallHeight();
});
}
},
// 上传前钩子,处理文件类型
......@@ -101,6 +105,7 @@ export default {
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)",
});
this.showResult = false; //先清空之前imgList已有的高度
const res = await searchImageByUpload(formData);
if (res.code == 0) {
const length = res.data.length;
......@@ -109,11 +114,20 @@ export default {
this.showResult = true;
loading.close();
this.showCurrentImg(file);
this.clearRouterQuery();
this.$nextTick(() => {
this.$refs["List"].getWaterfallHeight();
});
}
},
clearRouterQuery() {
if (this.$route.query.fileId) {
const query = {};
this.$router.replace({ query });
}
},
showCurrentImg(file) {
const that = this;
var reader = new FileReader();
......@@ -155,16 +169,29 @@ $transition-ease-03s: all ease 0.3s;
}
.show-result {
.banner {
height: 40px;
height: 200px;
.text {
padding: 80px 12%;
}
}
.upload-bar {
transform: translateY(-141px) !important;
.right-button {
border: 1px solid #fff;
}
}
.current-pic,
.img-list {
transform: translateY(-136px);
}
}
.banner {
height: 400px;
height: 300px;
width: 100%;
position: relative;
overflow: hidden;
background-color: $deep-blue;
color: #fff;
.left-pic {
transition: all ease 0.5s;
position: absolute;
......@@ -192,11 +219,10 @@ $transition-ease-03s: all ease 0.3s;
width: 100%;
height: 100%;
z-index: 4;
color: #fff;
padding: 200px 12%;
padding: 80px 12% 120px;
opacity: 1;
transition: $transition-ease-03s;
color: $deep-blue;
color: #fff;
.title {
font-size: 48px;
font-family: "SourceHanSerifCN-Bold";
......@@ -217,6 +243,7 @@ $transition-ease-03s: all ease 0.3s;
position: relative;
margin-bottom: 16px;
font-size: 18px;
.upload-bar {
box-shadow: $box-shadow;
background: #fff;
......@@ -229,6 +256,7 @@ $transition-ease-03s: all ease 0.3s;
position: relative;
cursor: pointer;
transition: $transition-ease-03s;
transform: translateY(-34px);
&:hover {
box-shadow: $box-shadow-hover;
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论