PixelAI-mobile/pages/mobile_web/home/home.vue

696 lines
19 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="mobile-home">
<!-- #ifdef APP -->
<view class="app-top" :style="{ height: CustomBar+2+'rpx',
background: topLevel===0? 'linear-gradient(180deg, #d8fa35 0%, #f0fdbf 100%)' : `rgba(255, 255, 255,${topLevel})` }"></view>
<view :style="{ height: CustomBar+'rpx',background: 'linear-gradient(180deg, #d8fa35 0%, #f0fdbf 100%)'}"></view>
<view class="mobile-logo" :style="{backgroundColor: `rgba(255, 255, 255,${topLevel})`,marginTop: CustomBar+2+'rpx'}">
<!-- #endif -->
<!-- #ifdef MP -->
<view class="app-top" :style="{height: `${StatusBar}px`,background: topLevel===0? 'linear-gradient(180deg, #d8fa35 0%, #f0fdbf 100%)' : `rgba(255, 255, 255,${topLevel})`}"></view>
<view :style="{height: `${StatusBar}px`}"></view>
<view class="mobile-logo" :style="{marginTop: `${StatusBar}px`,height: `${CustomBarHeight}px`,backgroundColor: `rgba(255, 255, 255,${topLevel})`}">
<!-- #endif -->
<!-- #ifdef H5 -->
<view class="mobile-logo" :style="{backgroundColor: `rgba(255, 255, 255,${topLevel})`}">
<!-- #endif -->
<image :src="fileUrl+logo"></image>
</view>
<u-swiper @click="linkTo" height="420" :list="swiperList" name="path" circular
bgColor="#e2fd7d"></u-swiper>
<view class="mobile-content">
<view class="content-inner">
<!-- 功能栏 -->
<view class="first-functions">
<!-- ai换衣 -->
<view class="ff-left">
<image :src="fileUrl+functionImg[0].picture" @click="toDeal(5)"></image>
<image :src="fileUrl+functionImg[1].picture" class="go" @click="toDeal(5)"></image>
</view>
<!-- 文生图 -->
<view class="ff-right">
<image @click="toDeal(8)" class="redraw" :src="fileUrl+functionImg[2].picture"></image>
<image class="tip" :src="fileUrl+functionImg[3].picture"></image>
</view>
</view>
<!-- 轮播功能栏 -->
<view class="second-functions">
<swiper class="swiper" :style="{height: swiperFunctionList[currentPageindex-1]&&
swiperFunctionList[currentPageindex-1].length>5?'270rpx':'125rpx'}" duration="300" @change="categoryChange">
<swiper-item v-for="(item, index) in swiperFunctionList" :key="index">
<view class="category">
<template v-for="(category, itemIndex) in item">
<view class="category-item" @click="toDeal(category.id)">
<image :class="category.icon?'':'other-set'"
:src="encodeURI(staticIp+(category.icon||'static/pixel/home/default-work.png'))"></image>
<view>{{ category.name }}</view>
</view>
</template>
</view>
</swiper-item>
</swiper>
<view class="dots">
<view v-for="item in swiperFunctionList.length" :key="item"
:class="{ active: item === currentPageindex }"></view>
</view>
</view>
<!-- 推荐作品 -->
<view class="third-functions">
<view class="tf-control">
<image @click="toWall" :src="fileUrl+recommendImg"></image>
<view class="tfc-right">
筛选
<view class="tfcr-btn" @click="showSift = true">
<u-icon :label="siftLabel||'暂无'" :name="fileUrl+select" color="#d4ff00"
size="17" label-pos="left" label-color="#d4ff00"></u-icon>
</view>
</view>
</view>
<u-waterfall class="show-work" v-model="workList" ref="uWaterfall">
<template v-slot:left="{leftList}">
<view @click="maskTouchend(item)" class="work-item" v-for="(item,index) in leftList" :key="item.id">
<view :class="item.display?'ribbon-fadeOutUp':''" class="collect-ribbon" v-show="item.collect">收藏</view>
<u-lazy-load border-radius="30" class="work-picture"
:image="getWorkPath(item.path)"></u-lazy-load>
<!-- <image class="work-picture" :src="item.picture" mode="widthFix"></image> -->
<view class="sign-text">{{ item.serviceName || '暂无' }}</view>
<image :lazy-load="true" class="sign" :src="fileUrl+sign"></image>
<view class="work-todo" @click.stop="toDeal(item.serviceId)">
<image :src="fileUrl+magicWand"></image>
<text>做同款</text>
</view>
<image v-if="item.sourcePath" class="compare-sign" mode="widthFix" :src="getWorkPath(item.sourcePath)"></image>
</view>
</template>
<template v-slot:right="{rightList}">
<view @click="maskTouchend(item)" class="work-item" v-for="(item,index) in rightList" :key="item.id">
<view :class="item.display?'ribbon-fadeOutUp':''" class="collect-ribbon" v-show="item.collect">收藏</view>
<u-lazy-load border-radius="30" class="work-picture"
:image="getWorkPath(item.path)"></u-lazy-load>
<!-- <image class="work-picture" :src="item.picture" mode="widthFix"></image> -->
<view class="sign-text">{{ item.serviceName || '暂无' }}</view>
<image :lazy-load="true" class="sign" :src="fileUrl+sign"></image>
<view class="work-todo" @click.stop="toDeal(item.serviceId)">
<image :src="fileUrl+magicWand"></image>
<text>做同款</text>
</view>
<image v-if="item.sourcePath" class="compare-sign" mode="widthFix" :src="getWorkPath(item.sourcePath)"></image>
</view>
</template>
</u-waterfall>
<!-- 下面这里等后端有了之后用isFinish判断 -->
<view class="last-tip" @click="getMore">
{{ recommendForm.isFinish ? '~~ 已加载全部 ~~' : '~~ 点击加载更多 ~~' }}
</view>
</view>
</view>
</view>
<u-toast ref="uToast"></u-toast>
<!-- 筛选项下拉栏 -->
<u-select v-model="showSift" :list="siftList" @confirm="selectSift" :defaultValue="[siftIndex]"
confirm-color="#94d500" labelName="name" valueName="id"></u-select>
</view>
</template>
<script>
import configService from '@/common/config.service.js';
import { tools } from '@/utils/utils.js';
export default {
props: {
topLevel:{
type: Number,
default: 0
},
},
data(){
return{
// #ifdef MP
// 微信小程序自定义导航栏参数
StatusBar: this.StatusBar || 0,
CustomBarHeight: this.Custom.height+(this.Custom.top-this.StatusBar)*2 || 0,
// #endif
// 基础地址
staticIp: configService.ip,
fileUrl: configService.fileUrl + 'pixel/home/',
// logo图标
logo: 'logo-new.png',
// 第一层功能图片
functionImg:[
{
// ai换装
picture: 'n-dressup.png'
},
{
// ai换装-go
picture: 'dressupgo.png'
},
{
// 涂抹重绘
picture: 'n-redraw.png'
},
{
// 涂抹重绘提示词
picture: 'redrawtip.png'
}
],
// 横向工具栏
swiperFunctionList:[],
// 当前横向工具栏页码
currentPageindex: 1,
// 轮播图
swiperList:[],
// 推荐作品图标
recommendImg: 'recommend.png',
// 筛选下拉栏三角形
select: 'select.png',
// 展示筛选项
showSift: false,
// 筛选项
siftList: [],
// 筛选项label
siftLabel: '全部',
// 筛选项下标
siftIndex: 0,
// 推荐作品列表
workList:[],
// 标签图标
sign: 'typelam.png',
// 点击次数
touchNum : 0,
// 轮播功能列表单组功能数
group: 8,
// 魔术棒
magicWand: 'magic-wand.png',
// 推荐作品表单
recommendForm: {
current: 1,
size: 10,
isFinish: true,
total: 0,
serviceName: '',
isBackend: 0
}
}
},
methods:{
// 初始化
async init(){
this.getBanner();
this.getServices();
this.workList = [];
this.$refs.uWaterfall.clear();
this.recommendForm = {current: 1,size: 10,isFinish: false,total: 0,isBackend: 0};
this.getWorkList();
},
// 获取轮播图
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.$refs.uToast.show({type:'error',title: "轮播图获取失败!"});
}
},
// 图片格式化
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);
},
// 获取应用服务列表
async getServices(){
let res = await this.$api.allServices();
if(res.success){
// 这里按一页10个分组
this.swiperFunctionList = [];
const arr = res.data;
this.siftList = [{id: -1,name:"全部"},...arr];
for (let i = 0; i < arr.length; i += this.group) {
this.swiperFunctionList.push(arr.slice(i, i + this.group));
}
}else{
this.$refs.uToast.show({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.total = total;
this.recommendForm.isFinish = current*size >= total;
this.$forceUpdate();
}else{
this.$refs.uToast.show({type:'error',title: "推荐作品获取失败!"});
}
},
// 查看更多
getMore(){
if(this.recommendForm.isFinish) return;
this.recommendForm.current++;
this.getWorkList();
},
// 横向功能列表切换页
categoryChange(event){
this.currentPageindex = event.detail.current+1;
},
// 推荐作品筛选
selectSift(e){
this.siftLabel = e[0].label;
this.siftIndex = this.siftList.findIndex(item=>item.id === e[0].value) || 0;
this.recommendForm.current = 1;
this.recommendForm.isFinish = false;
this.recommendForm.serviceName = this.siftLabel==='全部'?'':this.siftLabel;
this.$refs.uWaterfall.clear();
this.getWorkList();
},
// 监听单双击,单击-预览图片、双击-收藏
maskTouchend(item){
// 暂时只能预览,不收藏
const array = [this.getWorkPath(item.path)];
if(item.sourcePath) array.push(this.getWorkPath(item.sourcePath));
tools.methods.lookImage(0,array);
// this.touchNum ++;
// setTimeout(()=>{
// if(this.touchNum == 1){
// const array = [this.getWorkPath(item.path)];
// if(item.sourcePath) array.push(this.getWorkPath(item.sourcePath));
// tools.methods.lookImage(0,array);
// }
// if(this.touchNum >= 2){
// // 若collect为null默认没收藏那接下来就是收藏操作
// const result = item.collect ? (item.collect+1)%2 : 1;
// if(result === 0){
// // 添加淡出的class样式
// item.display = 1;
// this.$refs.uWaterfall.$forceUpdate();
// // 下面的操作应该替换为请求后端数据后,再停止动画
// // 模拟操作这里用setTimeout模拟
// setTimeout(() => {
// // 移除淡出类
// item.display = 0;
// item.collect = result;
// }, 1000); // 假设操作需要1秒
// }else{
// item.collect = result;
// this.$refs.uWaterfall.$forceUpdate();
// }
// }
// this.touchNum = 0;
// },250)
},
// 前往作品墙
toWall(){
// uni.navigateTo({url: `/pages/mobile_web/wall/wall`});
uni.navigateTo({url: `/pages/mobile_web/wall/detail`});
},
// 前往工作室
toDeal(id = null){
if(id!==null&&id!=='')
uni.navigateTo({url: `/pages/mobile_web/workshops/index?id=${id}`});
else this.$refs.uToast.show({type:'error',title: "暂未开放对应功能!"});
},
// 轮播图跳转
linkTo(e){
if(this.swiperList[e].url){
if(this.UniPlatform === 'web'){
window.open(encodeURI(this.swiperList[e].url));
}else{
uni.navigateTo({
url: `/pages/index/webview?src=${encodeURI(this.swiperList[e].url)}`
})
}
}
}
}
}
</script>
<style scoped lang="scss">
.mobile-home{
display: flex;
flex-direction: column;
min-height: 100vh;
// #ifdef APP || MP
.app-top{
width: 100%;
position: fixed;
z-index: 81;
}
// #endif
.mobile-logo{
width: 100%;
display: flex;
align-items: center;
justify-content: center;
position: fixed;
z-index: 81;
padding: 15rpx 0;
image{
width: 200rpx;
height: 45rpx;
}
}
.mobile-content{
box-shadow: rgba(0, 0, 0, 0.1) 0px 4px 12px;
z-index: 80;
width: 100%;
flex: 1;
margin-top: -50rpx;
border-top-right-radius: 36rpx;
border-top-left-radius: 36rpx;
background-color: #1a1929;
.content-inner{
margin: 60rpx 45rpx 150rpx;
.first-functions{
display: flex;
height: 270rpx;
.ff-left{
width: 250rpx;
height: 100%;
margin-right: 20rpx;
position: relative;
image{
width: 100%;
height: 105%;
&:active{
filter: opacity(0.8);
}
}
.go{
width: 90rpx;
height: 80rpx;
position: absolute;
bottom: 24rpx;
right: 0;
}
}
.ff-right{
flex: 1;
height: 100%;
width: 250rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
image{
width: 100%;
height: 70%;
}
.redraw{
margin-top: -1%;
&:active{
filter: opacity(0.8);
}
}
.tip{
height: 24%;
margin-bottom: 1%;
}
}
}
.second-functions{
position: relative;
// height: 125rpx;
width: 100%;
margin-top: 50rpx;
.swiper{
width: 100%;
height: 125rpx;
.category{
width: 100%;
height: auto;
display: grid;
row-gap: 20rpx;
grid-template-columns: repeat(4,25%);
.category-item{
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
// border: 2rpx solid #a3d4ff;
padding: 0 12rpx;
&:active{
filter: opacity(0.8);
}
view{
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
color: #fff;
text-align: center;
font-size: 24rpx;
}
image{
// width: 110rpx;
// height: 60rpx;
width: 66rpx;
height:60rpx;
margin-bottom: 14rpx;
}
}
}
}
.dots{
display: flex;
justify-content: center;
height: 14rpx;
width: 100%;
view{
background-color: #818e4f;
width: 20rpx;
height: 10rpx;
margin: 0 6rpx;
border-radius: 20rpx;
transition: all 0.5s;
}
.active{
background-color: #d5ff00 !important;
width: 45rpx !important;
height: 10rpx;
}
}
}
.third-functions{
width: 100%;
margin-top: 35rpx;
.tf-control{
display: flex;
justify-content: space-between;
height: 80rpx;
width: 100%;
image{
margin-left: 15rpx;
width: 160rpx;
height: 52rpx;
filter: drop-shadow(0 0 6rpx rgba(236, 250, 197, 1));
}
.tfc-right{
height: 70rpx;
display: flex;
align-items: center;
margin-right: 5rpx;
color: #ffffff;
font-size: 30rpx;
.tfcr-btn{
margin-left: 25rpx;
border: 2rpx solid #d5ff00;
border-radius: 25rpx;
background-color: #1a1929;
.u-icon{
margin: 16rpx 15rpx;
}
}
}
}
.show-work{
margin-top: 13rpx;
width: 100%;
// column-count:2;
// -moz-column-count:2; /* Firefox */
// -webkit-column-count:2; /* Safari Chrome */
column-gap: 1em;
-moz-column-gap: 1em;
-webkit-column-gap: 1em;
.work-item{
-webkit-column-break-inside: avoid;
break-inside: avoid; /*防止断点*/
margin-bottom: 1em;
position: relative;
padding-top: 13rpx;
.work-picture{
border: 0.1em 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: 170rpx;
height: 47rpx;
}
.sign-text{
width: 140rpx;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
color: #ffffff;
font-size: 28rpx;
position: absolute;
top: 0.85em;
left: 0.9em;
z-index: 1;
}
.work-todo{
position: absolute;
bottom: 0.85em;
right: 0.7em;
z-index: 1;
border-radius: 12rpx;
padding: 14rpx 30rpx;
background-color: rgba(0, 0, 0, 0.3);
display: flex;
align-items: center;
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;
}
&:active{
opacity: 0.8;
}
}
.compare-sign{
position: absolute;
left: 0;
bottom: 0.2em;
width: 120rpx;
height: 50%;
border: 0.1em solid #d5ff00;
border-radius: 20rpx;
box-shadow: 0 0 20rpx #eee;
// box-shadow: rgba(213, 255, 0, 0.3) 0px 4px 12px;
}
.ribbon-fadeOutUp{
animation-name: fadeOutUp !important;
}
.collect-ribbon {
position: absolute;
z-index: 2;
margin-top: -13rpx;
right: 30rpx;
width: 62rpx;
padding: 20rpx 14rpx 0;
box-sizing: border-box;
text-align: center;
background: #ff9900;
font-size: 25rpx;
color: #fff;
animation-name: bounceInDown;
animation-duration: 0.5s;
animation-fill-mode: both;
&::before,
&::after {
content: '';
position: absolute;
}
&::before {
top: 0;
left: -10rpx;
height: 0;
width: 0;
border-bottom: 14rpx solid #ff9900;
border-left: 12rpx solid transparent;
opacity: .8;
}
&::after {
height: 0;
width: 0;
left: 0;
bottom: -39rpx;
border-left: 31rpx solid #ff9900;
border-right: 32rpx solid #ff9900;
border-bottom: 43rpx solid transparent;
}
}
}
}
.last-tip{
color: #d5ff00;
font-size: 28rpx;
text-align: center;
margin-top: 20rpx;
margin-bottom: 160rpx;
}
}
}
}
}
::v-deep .u-swiper-indicator {
margin-bottom: 50rpx;
.u-indicator-item-round-active{
background-color: #1d1d1d !important;
width: 45rpx !important;
height: 10rpx;
}
.u-indicator-item-round{
background-color: #818e4f;
width: 20rpx;
height: 10rpx;
}
}
// 淡入
@keyframes bounceInDown {
from {
opacity: 0;
transform: translate3d(0, -5%, 0);
}
to {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
// 淡出
@keyframes fadeOutUp {
from {
opacity: 1;
}
to {
opacity: 0;
transform: translate3d(0, -5%, 0);
}
}
.other-set{
width: 80rpx !important;
height: 74rpx !important;
}
</style>