PixelAI-mobile/pages/pc_web/home/components/second.vue

545 lines
14 KiB
Vue
Raw Normal View History

2025-01-06 00:54:54 +08:00
<template>
<view class="home-second">
2025-01-22 20:25:38 +08:00
<view class="hs-search-title">
推荐作品
<image :src="fileUrl+blackStar"></image>
</view>
<!-- 筛选项 -->
<scroll-view :scroll-x="true" class="hs-search">
<view class="hs-scroll">
<view v-for="(item,index) in serviceList" :key="index" class="search-tag"
:class="siftIndex===index ? 'search-tag-selected' : ''" @click="sift(item,index)">{{ item.name }}</view>
</view>
</scroll-view>
<!-- 第一栏轮播图+服务 -->
<view class="hs-swiper">
<view class="hs-carousel">
<el-carousel>
<el-carousel-item v-for="(item,index) in swiperList" :key="index">
<image @click="linkTo(item.url)" class="swiper-image" :src="item.path"
:style="{cursor: item.url ? 'pointer' : 'default'}"></image>
</el-carousel-item>
</el-carousel>
</view>
<view class="hs-second">
<u-section class="hss-lam" title="AI工具" sub-title="更多"
font-size="50" @click="$emit('handleChangeService')"/>
2025-01-22 20:25:38 +08:00
<view class="hss-scroll">
<view class="hss-left" @click="scrollTo(0)" v-show="showScroll[0]">
<u-icon name="arrow-left" size="34"></u-icon>
</view>
<scroll-view class="hss-scroll-view" @scroll="scroller" ref="scrollView"
scroll-with-animation :scroll-left="scrollLeft" scroll-x>
<view class="hss-services">
2025-02-06 10:42:27 +08:00
<view class="hss-service" v-for="(item,index) in serviceList.slice(1)" :key="index" @click="$emit('handleChangeService', item.id)">
2025-01-22 20:25:38 +08:00
<image :src="encodeURI(staticIp+item.icon)"></image>
{{ item.name }}
</view>
</view>
</scroll-view>
<view class="hss-right" @click="scrollTo(1)" v-show="showScroll[1]">
<u-icon name="arrow-right" size="34"></u-icon>
</view>
</view>
</view>
</view>
<view class="hs-services">
2025-02-18 11:53:32 +08:00
<!-- 瀑布流布局图片 -->
<masonry :cols="7" gutter="1em">
<view class="hs-service" v-for="(item,index) in workList" :key="item.id">
<u-lazy-load @click="preview(item)" :title="item.serviceName||'暂无'" border-radius="30" class="hss-picture"
:image="getWorkPath(item.path)" v-loading="item.loading"></u-lazy-load>
<view class="sign-text">{{ item.serviceName || '暂无' }}</view>
<image :lazy-load="true" class="sign" :src="fileUrl+sign"></image>
<view class="work-todo">
<view class="wt-same" @click.stop="$emit('handleChangeService', item.serviceId)">
<image :src="fileUrl+magicWand"></image>
<text>做同款</text>
</view>
<view class="wt-same wt-download" @click="download(item)">
<u-icon name="download" size="36" color="#c9fe76" />
<text>下载 </text>
</view>
</view>
</view>
</masonry>
<!-- 下面这里等后端有了之后用isFinish判断 -->
<view class="last-tip" :class="recommendForm.isFinish?'':'clickable'" @click="getMore">
{{ recommendForm.isFinish ? '~~ 已加载全部 ~~' : '~~ 点击加载更多 ~~' }}
2025-01-22 20:25:38 +08:00
</view>
</view>
2025-01-06 00:54:54 +08:00
</view>
</template>
<script>
2025-01-22 20:25:38 +08:00
import configService from '@/common/config.service.js';
import { tools } from '@/utils/utils.js';
export default {
data(){
return{
// 基础地址
staticIp: configService.ip,
aliUrl: configService.aliUrl.split("://")[1],
fileUrl: configService.fileUrl + 'pixel/',
aliIp: configService.aliUrl,
otherAliIp: configService.otherAliUrl,
anotherAliIp: configService.anotherAliUrl,
2025-01-22 20:25:38 +08:00
// 选择黑星图片
blackStar: 'work/black-star.png',
// 魔术棒
magicWand: 'home/magic-wand.png',
// 标签图标
sign: 'home/typelam.png',
// 轮播图列表
swiperList: [],
// 服务列表
serviceList: [],
// 推荐作品列表
workList: [],
// 筛选项
siftIndex: 0,
// 滚动程度
scrollLeft: 0,
// 是否滚动到最左/右边
showScroll: [false,true],
// ai工具栏scroll宽度
scrollViewWidth: 0,
// 推荐作品表单
recommendForm: {
current: 1,
2025-02-18 11:53:32 +08:00
size: 20,
2025-01-22 20:25:38 +08:00
isFinish: true,
serviceName: '',
isBackend: 0
},
// 下载加载
downLoading: false,
}
},
mounted() {
// 获取ai工具栏宽度
this.scrollViewWidth = this.$refs.scrollView.$el.clientWidth;
this.getBanner();
this.getServices();
this.recommendForm = {current: 1,size: 20,isFinish: false,serviceName: '',isBackend: 0};
this.getWorkList();
},
methods:{
// 获取轮播图
async getBanner(){
let res = await this.$api.allBanners();
if(res?.success){
this.swiperList = res.data.map(item=>{
return {...item,path: encodeURI(this.staticIp+item.path)}
});
}else{
this.$emit('showToast',{type:'error',title: "轮播图获取失败!"});
}
},
// 获取服务筛选列表
async getServices(){
let res = await this.$api.allServices();
if(res.success){
const arr = res.data;
this.serviceList = [{id: -1,name:"全部"},...arr];
}else{
this.$emit('showToast',{type:'error',title: "筛选列表获取失败!"});
}
},
// 获取推荐作品列表
async getWorkList(){
if(this.recommendForm.isFinish) return;
let res = await this.$api.getRecommend(this.recommendForm);
if(res?.success){
const { records, total, current, size } = res.data;
const result = records;
if(current === 1){
this.workList = result;
}else{
this.workList.push(...result);
}
this.recommendForm.isFinish = current*size >= total;
this.$forceUpdate();
}else{
this.$emit('showToast',{type:'error',title: "推荐作品获取失败!"});
}
},
// 筛选
sift(item, index){
this.siftIndex = index;
this.recommendForm.serviceName = item.name === '全部' ? '' : item.name;
this.recommendForm.current = 1;
this.recommendForm.isFinish = false;
this.getWorkList();
},
// 图片格式化
getWorkPath(path){
if(!path) return;
let index = path?.indexOf('?');
let judge = path?.includes(configService.anotherAliUrl);
return path?.includes('://') ? path.substring(0,(judge||!index||index===-1) ? path.length : index) : encodeURI(this.staticIp+path);
2025-01-22 20:25:38 +08:00
},
// 轮播图跳转
linkTo(url){
if(url) window.open(encodeURI(url));
},
// 预览图片
preview(item){
const array = [this.getWorkPath(item.path)];
if(item.sourcePath) array.push(this.getWorkPath(item.sourcePath));
tools.methods.lookImage(0,array);
},
// ai工具栏滚动——0左滚、1右滚
scrollTo(type = 0){
let endo = 1000;
type === 0 ? this.scrollLeft -= endo : this.scrollLeft += endo;
},
// ai工具栏滚动监听
scroller({detail}){
const { scrollLeft, scrollWidth, deltaX } = detail;
this.showScroll[0] = scrollLeft !== 0;
this.showScroll[1] = (scrollLeft + this.scrollViewWidth - (deltaX || 0)) < scrollWidth;
this.$forceUpdate();
},
// 图片下载
async download(item){
let that = this;
let path = item.path;
item.loading = true;
if(!path || path==='') {
this.$emit('showToast',{type:'error',title: "该作品暂不可下载!"});
item.loading = false;
return;
}
// 下载地址
// let downloadUrl = await path.replace(that.aliIp, "/ossUpload");
let downloadUrl = path;
if(path.includes(that.aliIp)||path.includes(that.otherAliIp)||path.includes(that.anotherAliIp)){window.open(downloadUrl);item.loading = false;}
2025-01-22 20:25:38 +08:00
else
uni.request({
url: encodeURI(downloadUrl),
method: 'GET',
header: { 'token' : that.$store.state.vuex_token },
responseType: 'arraybuffer',
success(res) {
const arrayBuffer = res.data;
const blob = new Blob([arrayBuffer], {type: 'image/png'}); // 创建 Blob 对象
const imageUrl = URL.createObjectURL(blob); // 通过 Blob 对象创建图片 URL
let a = document.createElement('a'); //创建一个 a 标签
a.href = imageUrl; //把路径赋到a标签的href上
a.download = 'pixel.png';
a.click();
URL.revokeObjectURL(imageUrl);
a = null;
that.$emit('showToast',{type:'success',title: "图片下载成功!"});
},
fail() {
that.$emit('showToast',{type:'error',title: "图片下载失败,请重试!"});
},
complete() {
item.loading = false;
}
});
},
2025-02-18 11:53:32 +08:00
// 查看更多
getMore(){
if(this.recommendForm.isFinish) return;
this.recommendForm.current++;
this.getWorkList();
},
2025-01-22 20:25:38 +08:00
}
}
2025-01-06 00:54:54 +08:00
</script>
<style scoped lang="scss">
.home-second{
width: 100%;
2025-01-22 20:25:38 +08:00
min-height: 73.5em;
background-image: linear-gradient(to left top, #ffffff, #fcfbfc, #f8f8f9, #f5f4f7, #f1f1f4, #eef0f6, #eaeff7, #e5eff8, #ddf3f9, #d9f6f2, #def7e6, #eef6d9);
.hs-search-title{
padding: 100rpx 40rpx 40rpx;
margin-left: 14rpx;
font-size: 40rpx;
font-weight: bold;
position: relative;
color: #222;
image{
position: absolute;
top: 84rpx;
width: 30rpx;
height: 34rpx;
}
}
.hs-search{
padding: 0rpx 40rpx 40rpx;
.hs-scroll{
display: flex;
align-items: center;
.search-tag{
white-space: nowrap;
border: 2rpx solid #ebebec;
color: #909399;
display: flex;
align-items: center;
justify-content: center;
padding: 20rpx 30rpx;
margin: 0 14rpx;
height: 74rpx;
border-radius: 16rpx;
background-color: #f4f4f5;
cursor: pointer;
&:hover{
border-color: #c2e7b0;
color: #49cc90;
background-color: #e8f6f0;
}
}
.search-tag-selected{
border-color: #c2e7b0;
color: #49cc90;
background-color: #e8f6f0;
}
}
}
.hs-swiper{
height: 600rpx;
display: flex;
margin: 40rpx 40rpx 2em;
.hs-carousel{
min-width: 1250rpx;
border-radius: 16rpx;
background-color: #e2fd7d;
.swiper-image{
width: 100%;
height: 100%;
border-radius: 16rpx;
}
}
.hs-second{
display: flex;
flex-direction: column;
width: 2460rpx;
margin: 0 0 0 2em;
background: red;
border-radius: 40rpx;
background-image: linear-gradient(0deg,#e1ecfd,#cee2ff);
padding: 50rpx;
.hss-lam{}
.hss-scroll{
flex: 1;
background-image: linear-gradient(235deg,#e1ecfd 31.76%,#cee2ff 86.2%);
margin-top: 30rpx;
border-radius: 30rpx;
padding: 50rpx;
position: relative;
display: flex;
align-items: center;
.hss-scroll-view{
.hss-services{
height: 100%;
display: flex;
white-space: nowrap;
// overflow-x: scroll;
align-items: center;
.hss-service{
display: flex;
flex-direction: column;
align-items: center;
margin: 0 40rpx 0 0;
cursor: pointer;
font-size: 30rpx;
&:nth-last-child(1){
margin-right: 0;
}
image{
width: 266rpx;
height: 260rpx;
border-radius: 32rpx;
border: 6rpx solid #eee;
margin-bottom: 10rpx;
}
&:hover{
color: #dcffe9;
image{
box-shadow: 0 0 20rpx #eee;
border-color: #daf6f3;
}
}
&:active{
opacity: 0.8;
}
}
}
}
.hss-left,.hss-right{
z-index: 1;
position: absolute;
border-radius: 100%;
display: flex;
align-items: center;
justify-content: center;
width: 100rpx;
height: 100rpx;
background-color: rgba(240,240,240,0.9);
cursor: pointer;
opacity: 0;
transition: 0.5s;
&:hover{
opacity: 0.9 !important;
}
&:active{
opacity: 0.6 !important;
}
}
.hss-left{
left: 30rpx;
}
.hss-right{
right: 30rpx;
}
&:hover{
.hss-left,.hss-right{
opacity: 0.6;
}
}
}
::v-deep .u-section__right-info{
cursor: pointer;
&:hover{
opacity: 0.8;
}
&:active{
opacity: 0.6;
}
}
}
}
.hs-services{
2025-02-18 11:53:32 +08:00
padding: 0rpx 40rpx 40rpx;
// column-count:5;
// -moz-column-count:5; /* Firefox */
// -webkit-column-count:5; /* Safari 和 Chrome */
// column-gap: 2em;
// -moz-column-gap: 2em;
// -webkit-column-gap: 2em;
2025-01-22 20:25:38 +08:00
.hs-service{
-webkit-column-break-inside: avoid;
break-inside: avoid; /*防止断点*/
// width: 400rpx;
2025-02-18 11:53:32 +08:00
margin-bottom: 1em;
2025-01-22 20:25:38 +08:00
position: relative;
overflow: hidden;
border-radius: 30rpx;
.hss-picture{
cursor: pointer;
border: 2rpx solid #d5ff00;
border-radius: 30rpx;
// 骗系统开启硬件加速
transform: transition3d(0, 0, 0);
// 防止图片加载“闪一下”
will-change: transform;
}
.sign{
border: none;
border-radius: 0;
position: absolute;
top: 0.8em;
left: 0.6em;
width: 190rpx;
height: 54rpx;
}
.sign-text{
width: 160rpx;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
color: #ffffff;
font-size: 30rpx;
position: absolute;
top: 0.9em;
left: 0.9em;
z-index: 1;
}
.work-todo{
width: 100%;
height: 100rpx;
position: absolute;
z-index: 1;
border-radius: 8rpx 8rpx 30rpx 30rpx;
bottom: -100rpx;
// bottom: 2rpx;
left: 0;
background-color: rgba(0, 0, 0, 0.3);
display: flex;
align-items: center;
justify-content: space-around;
font-size: 30rpx;
transition: 0.5s;
.wt-same{
width: 200rpx;
height: 70rpx;
border-radius: 56rpx;
border: 2rpx solid #a3d4ff;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(242, 245, 247, 0.2);
text{
font-weight: bold;
background-image: linear-gradient(to right, #cdfbf2 0%, #a3d4ff 100%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
image{
margin-right: 10rpx;
width: 34rpx;
height: 34rpx;
}
&:hover{
opacity: 0.8;
}
&:active{
opacity: 0.6;
}
}
.wt-download{
width: 180rpx;
border-color: #c5fe6e;
text{
background-image: linear-gradient(to right, #c9fe76 0%, #a5fe2f 100%);
}
}
}
&:hover{
.work-todo{
bottom: 2rpx;
}
}
}
2025-02-18 11:53:32 +08:00
.last-tip{
font-size: 36rpx;
text-align: center;
margin-top: 20rpx;
margin-bottom: 20rpx;
background-image: linear-gradient(to right, #a3d4ff 0%, #bee7df 100%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.clickable{
cursor: pointer;
&:hover{
opacity: 0.8;
}
&:active{
opacity: 0.6;
}
}
2025-01-22 20:25:38 +08:00
}
2025-01-06 00:54:54 +08:00
}
</style>