514 lines
14 KiB
Vue
514 lines
14 KiB
Vue
<template>
|
||
<!-- #ifdef APP -->
|
||
<view class="mobile-workshops" :style="{ backgroundImage: `url(${myFileUrl+background})`,paddingTop: CustomBar+'rpx' }">
|
||
<view class="app-top" :style="{ height: CustomBar+'rpx',
|
||
background: topLevel===0? '#ffffff00' : `rgba(255, 255, 255,${topLevel})` }"></view>
|
||
<!-- #endif -->
|
||
<!-- #ifndef APP -->
|
||
<view class="mobile-workshops" :style="{ backgroundImage: `url(${myFileUrl+background})` }">
|
||
<!-- #endif -->
|
||
<view class="mwt-top">
|
||
<view class="mobile-logo" :style="{backgroundColor: `rgba(255, 255, 255,${topLevel})`}">
|
||
<!-- #ifdef H5 -->
|
||
<!-- <u-icon name="arrow-left" size="40" color="#c2ea04" class="back" @click="back"></u-icon> -->
|
||
<!-- #endif -->
|
||
<image :src="myFileUrl+logo"></image>
|
||
</view>
|
||
<view class="mw-title">
|
||
<u-icon name="arrow-left" size="40" color="#fff" class="back" @click="back"></u-icon>
|
||
{{ form.title }}
|
||
</view>
|
||
<view class="mw-upload">
|
||
<view class="mwu-cover" v-if="uploadFile==''" @click="selectImage">
|
||
<u-icon name="plus-circle" size="100" color="#fff" label="上传图片" labelSize="40"
|
||
labelColor="#fff" labelPos="bottom" marginTop="25"></u-icon>
|
||
</view>
|
||
<view class="center-image" v-else-if="resultFile===''">
|
||
<image mode="widthFix" :src="uploadFile" @click="selectImage"></image>
|
||
</view>
|
||
<view class="center-image" v-else>
|
||
<image mode="widthFix" :src="ip+resultFile" @click="previewImage"></image>
|
||
</view>
|
||
<view class="selections" v-if="form.model=='repaint'">
|
||
<view class="selections-item" :style="currentSelect===index?{ backgroundImage: `url(${fileUrl+selectBackground})` }:
|
||
{ color: '#000', backgroundImage: `url(${fileUrl+noSelectBackground})` }"
|
||
v-for="(item,index) in selections" :key="index" @click="currentSelect=index">
|
||
{{ item }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="mw-editor" v-if="form.model=='repaint'">
|
||
<EditorBox :icon="fileUrl+editorIcon"
|
||
placeholder="如: 衣服/鞋子/头发或者英文:clothes and shose">
|
||
<template #title>
|
||
<text class="slot">需<text style="color: #d8fa35;">替换</text>的元素</text>
|
||
</template>
|
||
</EditorBox>
|
||
<EditorBox :icon="fileUrl+editorIcon"
|
||
placeholder="如: 衣服/鞋子/头发或者英文:clothes and shose">
|
||
<template #title>
|
||
<text class="slot"><text style="color: #d8fa35;">替换后</text>的图像</text>
|
||
</template>
|
||
</EditorBox>
|
||
</view>
|
||
<view class="workshops-tip" v-else>
|
||
Tips:{{ resultFile ? '点击预览图片效果~' : placeholderList[form.model] }}
|
||
</view>
|
||
</view>
|
||
<view class="workshops-btn">
|
||
<u-button class="wbu-btn" @click="startDeal" v-if="resultFile===''"
|
||
ripple :hairLine="false" shape="circle" rippleBgColor="#f0fdbf" :loading='dotLoading'>
|
||
<u-icon name="edit-pen" size="42"></u-icon>开启魔法
|
||
</u-button>
|
||
<u-button :loading="functionLoading" class="wbu-btn" v-else ripple :hairLine="false"
|
||
shape="circle" rippleBgColor="#f0fdbf" @click="resultFunction[currentType].fun"
|
||
:style="{backgroundImage: resultFunction[currentType].background}" :class="transition?'transition':''">
|
||
<u-icon :name="resultFunction[currentType].icon" size="42"></u-icon>
|
||
{{ resultFunction[currentType].name }}
|
||
</u-button>
|
||
<view class="wb-change" v-if="resultFile!==''">
|
||
<u-icon :name="fileUrl+'change.png'" size="50" @click="changeFunction"></u-icon>
|
||
</view>
|
||
</view>
|
||
<u-toast ref="uToast"></u-toast>
|
||
<DotLoading :show="dotLoading" />
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import configService from '@/common/config.service.js';
|
||
import { tools } from '@/utils/utils.js';
|
||
import EditorBox from './components/editor.vue';
|
||
import { selectDealFunction } from './common/imgDeal'
|
||
export default {
|
||
components: {
|
||
EditorBox
|
||
},
|
||
data(){
|
||
return{
|
||
// 顶部距离等级
|
||
topLevel: 0,
|
||
// 基础路径
|
||
ip: configService.ip,
|
||
myFileUrl: configService.fileUrl + 'pixel/my/',
|
||
fileUrl: configService.fileUrl + 'pixel/workshops/',
|
||
// 上传图片
|
||
// http://8.138.171.103/upload%5CAttachment%5C20241127%5Caa73abfb8b3a433292c94de57aef0a35.png
|
||
uploadFile: '',
|
||
// 结果图
|
||
// upload%5CAttachment%5C20241127%5Caa73abfb8b3a433292c94de57aef0a35.png
|
||
resultFile: '',
|
||
// logo图标
|
||
logo: 'logo.png',
|
||
// 我的页面背景
|
||
background: 'background.png',
|
||
// 数据
|
||
form: {
|
||
title: '',// 标题
|
||
model: ''// 模式
|
||
},
|
||
// 模式选择
|
||
selections:["保留模式","替换模式"],
|
||
// 模式选择下标
|
||
currentSelect: 0,
|
||
// 模式选择背景
|
||
selectBackground: 'selectedBd.png',
|
||
// 未选择背景
|
||
noSelectBackground: 'noSelectedBd.png',
|
||
// 编辑图标
|
||
editorIcon: 'editor.png',
|
||
// 提示语列表
|
||
placeholderList: {
|
||
stylereplace: '上传图片后,选择更换不同风格~',
|
||
animeization: '上传人像图,快进入anime的世界吧~',
|
||
oldrepair: '上传黑白旧照片,焕发色彩~'
|
||
},
|
||
// 创作之后的操作按钮
|
||
resultFunction: {
|
||
download: {
|
||
name: '下载',
|
||
icon: 'download',
|
||
background: 'linear-gradient(to right, #56ab2f 0%, #96fe11 51%, #56ab2f 100%)',
|
||
fun: ()=>{this.download()}
|
||
},
|
||
reUpload: {
|
||
name: '重新上传',
|
||
icon: 'camera',
|
||
background: 'linear-gradient(to right, #c2fc3b 0%, #c2ffd8 51%, #c2fc3b 100%)',
|
||
fun: ()=>{this.selectImage()}
|
||
},
|
||
saveWork: {
|
||
name: '保存作品',
|
||
icon: 'bookmark',
|
||
background: 'linear-gradient(to right, #4AC29A 0%, #BDFFF3 51%, #4AC29A 100%)',
|
||
fun: ()=>{}
|
||
}
|
||
},
|
||
// 当前功能按钮
|
||
currentType: 'download',
|
||
// 当前功能下标
|
||
index: 0,
|
||
// 下载加载
|
||
functionLoading: false,
|
||
// 过渡动画
|
||
transition: false,
|
||
// 图片处理加载动画
|
||
dotLoading: false
|
||
}
|
||
},
|
||
// #ifndef H5
|
||
onPageScroll(e) {
|
||
const level = e.scrollTop/60;
|
||
if(level<=1) this.topLevel = level;
|
||
else this.topLevel = 1;
|
||
},
|
||
// #endif
|
||
|
||
// #ifdef H5
|
||
mounted(){
|
||
let that = this;
|
||
window.onscroll = function () {
|
||
//为了保证兼容性,这里取三个值,哪个有值取哪一个
|
||
//scrollTop就是触发滚轮事件时滚轮的高度
|
||
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
|
||
const level = scrollTop/60;
|
||
if(level<=1) that.topLevel = level;
|
||
else that.topLevel = 1;
|
||
}
|
||
},
|
||
|
||
onHide() {
|
||
window.onscroll = null;
|
||
},
|
||
// #endif
|
||
onLoad(options) {
|
||
this.form.title = options.name;
|
||
this.form.model = options.model;
|
||
},
|
||
methods:{
|
||
// 返回
|
||
back(){
|
||
uni.navigateBack();
|
||
},
|
||
// 上传图片
|
||
selectImage(){
|
||
let that = this;
|
||
uni.chooseImage({
|
||
count: 1, // 默认9
|
||
sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
|
||
sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
|
||
success: (res) => {
|
||
// #ifdef H5
|
||
if (res.tempFiles[0].type.indexOf('image') === -1) {
|
||
that.$refs.uToast.show({
|
||
type: 'warning',
|
||
title: "图片上传格式错误!"
|
||
});
|
||
return;
|
||
}
|
||
// #endif
|
||
if(this.resultFile!=='') this.resultFile = '';
|
||
that.uploadFile = res.tempFilePaths[0];
|
||
}
|
||
});
|
||
},
|
||
// 预览图片
|
||
previewImage(){
|
||
tools.methods.lookImage(0,[this.ip+this.resultFile,this.uploadFile]);
|
||
},
|
||
// 开始处理图片
|
||
async startDeal(){
|
||
try{
|
||
this.dotLoading = true;
|
||
let that = this;
|
||
if(this.uploadFile===''){
|
||
this.$refs.uToast.show({type:'error',title: "请上传图片!"});
|
||
this.dotLoading = false;
|
||
return;
|
||
}
|
||
// 再实际处理
|
||
selectDealFunction(that,that.form.model,that.getParams(that.form.model),
|
||
(path)=>{
|
||
that.resultFile = path;
|
||
that.$refs.uToast.show({type:'success',title: `${that.form.title}成功!`});
|
||
this.dotLoading = false;
|
||
});
|
||
}catch(e){
|
||
this.dotLoading = false;
|
||
}finally{
|
||
}
|
||
},
|
||
// 获取参数值
|
||
getParams(model){
|
||
let result,that = this;
|
||
switch(model){
|
||
case 'oldrepair' :
|
||
result = {
|
||
filePath: this.uploadFile,
|
||
}
|
||
break;
|
||
case 'animeization' :
|
||
result = {
|
||
filePath: this.uploadFile,
|
||
}
|
||
break;
|
||
}
|
||
return result;
|
||
},
|
||
// 判断是否在微信内置浏览器打开
|
||
// #ifndef APP
|
||
isMpWeb(){
|
||
if(navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger'){
|
||
this.$refs.uToast.show({type:'warning',title: "请在浏览器打开进行下载,或长按图片保存到相册!"});
|
||
return true;
|
||
}else{
|
||
return false;
|
||
}
|
||
},
|
||
// #endif
|
||
// 图片下载
|
||
async download(){
|
||
let that = this;
|
||
|
||
// #ifndef APP
|
||
if(this.isMpWeb()) return;
|
||
// #endif
|
||
|
||
this.functionLoading = true;
|
||
if(this.resultFile==='') {
|
||
this.$refs.uToast.show({type:'error',title: "暂无结果图片可下载!"});
|
||
this.functionLoading = false;
|
||
return;
|
||
}
|
||
|
||
// #ifdef H5
|
||
uni.request({
|
||
url: '/'+that.resultFile,
|
||
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.$refs.uToast.show({type:'success',title: "图片下载成功!"});
|
||
},
|
||
fail() {
|
||
that.$refs.uToast.show({type:'error',title: "图片下载失败,请重试!"});
|
||
},
|
||
complete() {
|
||
that.functionLoading = false;
|
||
}
|
||
});
|
||
// #endif
|
||
|
||
// #ifndef H5
|
||
uni.downloadFile({
|
||
url: that.ip+that.resultFile,
|
||
header: { 'token': that.$store.state.vuex_token },
|
||
success: (res) => {
|
||
if (res.statusCode === 200) {
|
||
//文件保存到本地
|
||
uni.saveImageToPhotosAlbum({
|
||
filePath: res.tempFilePath, //临时路径
|
||
success: function(resp) {
|
||
that.$refs.uToast.show({type:'success',title: "下载成功,请前往手机相册查看!"});
|
||
}
|
||
});
|
||
}else{
|
||
that.$refs.uToast.show({type:'error',title: "下载失败,请重试!"});
|
||
}
|
||
},
|
||
fail() {
|
||
that.$refs.uToast.show({type:'error',title: "暂不支持下载,请长按保存!"});
|
||
},
|
||
complete() {
|
||
that.functionLoading = false;
|
||
}
|
||
});
|
||
// #endif
|
||
},
|
||
// 切换操作按钮
|
||
changeFunction(){
|
||
this.transition = true;
|
||
const keys = Object.keys(this.resultFunction);
|
||
this.index = (this.index+1) % keys.length;
|
||
this.currentType = keys[this.index];
|
||
setTimeout(()=>{
|
||
this.transition = false;
|
||
},500)
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.mobile-workshops{
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
min-height: 100vh;
|
||
background-size: cover;
|
||
.mwt-top{
|
||
// #ifdef APP
|
||
.app-top{
|
||
width: 100%;
|
||
position: fixed;
|
||
z-index: 81;
|
||
top: 0;
|
||
}
|
||
// #endif
|
||
.mobile-logo{
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: center;
|
||
position: fixed;
|
||
z-index: 81;
|
||
padding: 15rpx 0;
|
||
image{
|
||
width: 200rpx;
|
||
height: 45rpx;
|
||
}
|
||
}
|
||
.mw-title{
|
||
color: #fff;
|
||
font-size: 35rpx;
|
||
line-height: 35rpx;
|
||
font-weight: bold;
|
||
position: relative;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin: 80rpx 40rpx 32rpx;
|
||
height: 40rpx;
|
||
.back{
|
||
position: absolute;
|
||
left: 0;
|
||
&:active{
|
||
filter: opacity(0.8);
|
||
}
|
||
}
|
||
}
|
||
.mw-upload{
|
||
display: flex;
|
||
flex-direction: column;
|
||
margin: 15rpx 100rpx;
|
||
.mwu-cover{
|
||
width: 100%;
|
||
height: 550rpx;
|
||
background-color: #626262;
|
||
border-radius: 35rpx;
|
||
border: 2rpx solid #858585;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
&:active{
|
||
filter: opacity(0.8);
|
||
}
|
||
}
|
||
.center-image{
|
||
border-radius: 35rpx;
|
||
width: 100%;
|
||
min-height: 650rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
image{
|
||
width: 100%;
|
||
border-radius: 35rpx;
|
||
}
|
||
}
|
||
.selections{
|
||
margin-top: 20rpx;
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
.selections-item{
|
||
margin-left: 20rpx;
|
||
width: 150rpx;
|
||
height: 48rpx;
|
||
line-height: 50rpx;
|
||
border: 56rpx;
|
||
color: #fff;
|
||
font-weight: bold;
|
||
font-size: 20rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background-size: cover;
|
||
}
|
||
}
|
||
}
|
||
.mw-editor{
|
||
margin: 12rpx 46rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
.slot{
|
||
color: #fff;
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
}
|
||
}
|
||
.workshops-tip{
|
||
margin-top: 70rpx;
|
||
color: #d5ff00;
|
||
font-size: 28rpx;
|
||
text-align: center;
|
||
}
|
||
}
|
||
.workshops-btn{
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin: 80rpx 0 40rpx;
|
||
.wbu-btn{
|
||
margin: 0;
|
||
border: none;
|
||
width: 70%;
|
||
height: 100rpx;
|
||
color: rgba(42, 35, 61, 0.9);
|
||
font-size: 35rpx;
|
||
font-weight: bold;
|
||
background-size: 200% auto;
|
||
transition: 0.5s;
|
||
animation-duration: 1s;
|
||
animation-fill-mode: both;
|
||
background-image: linear-gradient(to right, #c2fc3b 0%, #c2ffd8 51%, #c2fc3b 100%);
|
||
&:active {
|
||
background-position: right center;
|
||
color: #fff;
|
||
text-decoration: none;
|
||
}
|
||
.u-icon{
|
||
margin-right: 10rpx;
|
||
}
|
||
}
|
||
.transition{
|
||
animation-name: fadeIn;
|
||
}
|
||
.wb-change{
|
||
color: #fff;
|
||
margin-left: 20rpx;
|
||
margin-right: -70rpx;
|
||
&:active{
|
||
filter: opacity(0.6);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
@keyframes fadeIn {
|
||
from {
|
||
opacity: 0;
|
||
}
|
||
|
||
to {
|
||
opacity: 1;
|
||
}
|
||
}
|
||
</style> |