Files
dvcp_v2_wxcp_app/src/project/caw/AppCountryAlbum/Watermark.vue
2022-08-08 15:06:42 +08:00

904 lines
23 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>
<div class="photo" :class="[isHide ? 'home-active' : '']" @click="isHide = true" :style="{height: height + 'px'}">
<div class="photo-top" data-html2canvas-ignore>
<div class="photo-top__middle" @click="isShowAlbum = true">
<span>保存至{{ albumName || '系统相册' }}</span>
<image src="./images/to-right.png" />
</div>
</div>
<div class="photo-wrapper">
<div ref="waterMarker" class="waterMarker-wrapper" :style="{height: canvasHeight + 'px'}">
<img class="waterMarker-img" :src="img" mode="widthFix" @load="onImgLoad" />
<div
class="watermark"
v-if="currIndex > -1 && currWatermarkConfig.length"
:style="{left: x + 'px', top: y + 'px', transform: 'scale(' + watermarkScale + ')', transformOrigin: 'left' }"
@touchstart="onTouchstart"
@touchmove="onTouchmove">
<component ref="WatermarkItem" :addressInfo="address" :is="'Watermark' + (currIndex + 1)" :config="currWatermarkConfig"></component>
<div v-if="!isHide" @click.stop="currIndex = -1" class="watermark-close" data-html2canvas-ignore>
<image src="./images/close-b.png" />
</div>
<span v-if="!isHide" class="watermark-edit" @click.stop="toEdit" data-html2canvas-ignore>编辑</span>
</div>
</div>
</div>
<div class="photo-bottom" data-html2canvas-ignore>
<div class="photo-bottom__top">
<span @click.stop="isHide = true">取消</span>
<h2>水印</h2>
<span @click.stop="isHide = true">确定</span>
</div>
<div class="waterlist">
<div
class="water-item"
:class="[currIndex === -1 ? 'active' : '']"
key="-1"
@click.stop="currIndex = -1">
<image src="./images/clear.png" />
<image class="checked" v-if="currIndex === -1" src="./images/xuanzhong.png" />
<div class="water-item__bottom">不使用水印</div>
</div>
<div
class="water-item"
:class="[currIndex === index ? 'active' : '']"
v-for="(item, index) in watermarkList"
:key="item.id"
@click.stop="currIndex = index">
<image :src="item.thum" />
<span v-show="currIndex === index" @click.stop="toEdit">编辑</span>
<image class="checked" v-if="currIndex === index" src="./images/xuanzhong.png" />
<div class="water-item__bottom">{{ item.name }}</div>
</div>
</div>
</div>
<div class="photo-tabbar" data-html2canvas-ignore>
<h2>编辑图片</h2>
<div class="tabbar-wrapper">
<div class="item" @click.stop="back">
<image src="./images/fanhui-black.png" />
<div>返回</div>
</div>
<div class="item" @click.stop="isHide = false">
<image src="./images/shuiyin-white.png" />
<div>水印</div>
</div>
<div class="item" @click.stop="toClipping">
<image src="./images/jiancai.png" />
<div>剪裁</div>
</div>
<div class="item" @click.stop="save">
<image src="./images/shangchuan-black.png" />
<div>上传</div>
</div>
</div>
</div>
<u-popup v-model="isShowAlbum" :closeable="false" border-radius="32" height="70%" mode="bottom">
<div class="album">
<div class="top">
<span @click="isShowAlbum = false">取消</span>
<span @click="onConfirm">确定</span>
</div>
<scroll-view scroll-y class="album-list__wrapper">
<div
class="item"
@click="albumIndex = index"
v-for="(item, index) in albumList"
:key="index"
:class="[albumIndex === index ? 'active' : '']">
<image class="checked" v-if="albumIndex === index" src="./images/xuanzhong.png" />
<image class="icon" v-if="!item.lastPhotoUrl" src="./images/icon.png" />
<image class="img" v-if="item.lastPhotoUrl" :src="item.lastPhotoUrl" mode="aspectFill" />
<div class="item-bottom">
<h2>{{ item.albumName }}</h2>
<div class="item-bottom__info">
<div class="left">
<span>今日新增</span>
<i>{{ item.dayPhtoto }}</i>
<span></span>
</div>
<div class="right">
<image src="./images/zhaopianshuliang.png" />
<span>{{ item.photoTotal || 0 }}</span>
</div>
</div>
</div>
</div>
</scroll-view>
</div>
</u-popup>
</div>
</template>
<script>
import Watermark1 from './components/watermark/Watermark1'
import Watermark2 from './components/watermark/Watermark2'
import Watermark3 from './components/watermark/Watermark3'
import Watermark4 from './components/watermark/Watermark4'
import Watermark5 from './components/watermark/Watermark5'
import Watermark6 from './components/watermark/Watermark6'
import Watermark7 from './components/watermark/Watermark7'
import Watermark8 from './components/watermark/Watermark8'
import { mapActions, mapState } from 'vuex'
export default {
name: 'Watermark',
appName: '水印相机',
components: {
Watermark1,
Watermark2,
Watermark3,
Watermark4,
Watermark5,
Watermark6,
Watermark7,
Watermark8
},
data () {
return {
img: '',
currIndex: 0,
isHide: true,
height: '100%',
waterSrc: '',
albumId: '',
albumName: '',
albumIndex: 0,
watermarkList: [],
isShowAlbum: false,
albumList: [],
address: {},
x: 32,
y: 24,
startX: 0,
watermarkScale: 1,
startY: 0,
canvasHeight: 0
}
},
computed: {
defaultValue () {
if (!this.albumList.length) {
return [0]
}
return [this.albumList.map(v => v.value).indexOf(this.albumId)]
},
currWatermarkConfig () {
if (this.currIndex < 0 || !this.watermarkList.length) return []
return this.watermarkList[this.currIndex].itemList
},
...mapState(['wxwork'])
},
onLoad (query) {
if (query.albumId) {
this.albumId = query.albumId
}
this.img = decodeURIComponent(query.url)
this.height = uni.getSystemInfoSync().windowHeight
this.getLocation()
this.$nextTick(() => {
this.getWatermarkList()
})
uni.$on('cropper', e => {
this.img = e
this.x = 32
this.y = 200
})
},
mounted () {
// this.$nextTick(() => {
// document.body.addEventListener('touchmove', this.bindEvent, { passive: false })
// })
},
onUnload () {
uni.$off('cropper')
},
methods: {
...mapActions(['injectJWeixin', 'agentSign']),
toClipping () {
uni.navigateTo({
url: `./Clipping?url=${encodeURIComponent(this.img)}`
})
},
bindEvent (e) {
e.preventDefault()
},
onImgLoad () {
const img = document.querySelector('.waterMarker-img')
this.canvasHeight = img.clientHeight
this.watermarkScale = img.clientWidth / uni.getSystemInfoSync().windowWidth
},
onTouchstart (e) {
const isMobile = e.type !== 'mousemove'
const watermark = document.querySelector('.watermark')
if (isMobile) {
this.startX = e.touches[0].clientX - Number((watermark.style.left).replace('px', ''))
this.startY = e.touches[0].clientY - Number((watermark.style.top).replace('px', ''))
} else {
this.startX = e.clientX - Number((watermark.style.left).replace('px', ''))
this.startY = e.clientY -Number((watermark.style.top).replace('px', ''))
}
},
onTouchmove (e) {
const isMobile = e.type !== 'mousemove'
if (isMobile) {
this.x = e.touches[0].clientX - this.startX
this.y = e.touches[0].clientY - this.startY
} else {
this.x = e.clientX - this.startX
this.y = e.clientY - this.startY
}
},
toEdit () {
this.$refs.WatermarkItem.linkTo('./WatermarkConfig')
},
save () {
this.$loading()
this.isHide = true
this.$nextTick(() => {
html2canvas(this.$refs.waterMarker, {
allowTaint: true,
useCORS: true
}).then((canvas) => {
let dataURL = canvas.toDataURL('image/png')
const file = this.dataURLtoFile(dataURL, 'photo.png')
let formData = new FormData()
formData.append('file', file)
this.$http.post('/admin/file/add2?type=image', formData).then(res => {
if (res.code === 0) {
let info = {}
if (this.currIndex > -1) {
info = this.watermarkList[this.currIndex]
}
this.$http.post('/api/appalbumphoto/addOrUpdate', {
albumId: this.albumId,
photoUrl: res.data.url,
fileId: res.data.id,
watermarkType: this.currIndex > -1 ? info.watermarkType : '',
templateId: this.currIndex > -1 ? info.id : ''
}).then(res => {
if (res.code === 0) {
uni.$emit('update')
this.$u.toast('新增成功')
setTimeout(() => {
this.back()
}, 500)
} else {
this.$u.toast(res.msg)
}
})
}
})
}).catch(e => {
console.log(e)
})
})
},
getWeather (code) {
this.$http.post(`/api/bdweather/wdata?districtId=${code}`).then(res => {
if (res.code === 0) {
const data = res.data.result.now
uni.setStorageSync('address', {
...uni.getStorageSync('address'),
weather: `${data.text} ${data.temp}°` || ''
})
this.address = {
...uni.getStorageSync('address'),
weather: `${data.text} ${data.temp}°` || ''
}
}
})
},
getLocation () {
this.agentSign({
corpId: this.wxwork.config.corpId,
suiteId: this.wxwork.config.suiteId
}).then(() => {
this.injectJWeixin(['getLocation']).then(() => {
wx.getLocation({
type: 'wgs84',
success: res => {
var lat = res.latitude
var lng = res.longitude
this.$http.post('/api/appdvcpconfig/apiForward', `https://apis.map.qq.com/ws/geocoder/v1/?location=${lat},${lng}&key=3RZBZ-LZUCF-CT6J5-NWKZH-FCWOQ-UUFKY&get_poi=1`).then(res => {
if (res.code === 0) {
const data = res.data.result
uni.setStorageSync('address', {
lat,
lng,
address: data.address,
cityCode: `${data.ad_info.adcode}`
})
this.address = {
...uni.getStorageSync('address')
}
this.getWeather(`${data.ad_info.adcode}`)
}
})
},
error: res => {
console.log(res)
}
})
}).catch(e => {
})
})
},
dataURLtoFile (dataurl, filename) {
let arr = dataurl.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], filename, { type: mime })
},
onConfirm () {
this.albumId = this.albumList[this.albumIndex].value
this.albumName = this.albumList[this.albumIndex].label
this.isShowAlbum = false
},
getWatermarkList () {
this.$http.post(`/api/appalbumtemplate/list?size=100&templateType=0`).then(res => {
if (res.code === 0) {
this.watermarkList = res.data.records
}
})
this.$http.post('/api/appalbum/list', null, {
params: {
size: 1000
}
}).then(res => {
if (res.code === 0) {
this.albumList = res.data.records.map(v => {
return {
...v,
label: v.albumName,
value: v.id
}
})
this.albumList.some((v, index) => {
if (this.albumId) {
if (v.value === this.albumId) {
this.albumIndex = index
this.albumName = v.label
return true
}
} else {
if (v.label === '系统相册') {
this.albumIndex = index
this.albumId = v.value
this.albumName = '系统相册'
return true
}
}
})
}
})
},
back () {
uni.navigateBack({
delta: 1
})
}
}
}
</script>
<style lang="scss" scoped>
.photo {
width: 100%;
background: #333;
overflow: hidden;
.photo-wrapper {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 128px;
left: 0;
width: 100%;
height: calc(100vh - 321px - 128px);
}
.newImg {
position: fixed;
left: 0;
top: 0;
z-index: 11111;
width: 100%;
height: 100%;
}
.album {
height: 100%;
overflow: hidden;
.album-list__wrapper {
display: flex;
align-items: center;
flex-wrap: wrap;
justify-content: space-between;
.item {
display: inline-block;
position: relative;
width: 328px;
height: 328px;
margin-bottom: 32px;
box-shadow: 0px 4px 8px 0px rgba(17, 67, 110, 0.1);
border-radius: 16px;
overflow: hidden;
background: #EFF5FA;
&:nth-of-type(2n) {
margin-left: 30px;
}
&.active {
border: 4px solid #2477F1;
}
.img {
width: 100%;
height: 100%;
}
.item-bottom {
position: absolute;
left: 0;
bottom: 0;
z-index: 1;
width: 100%;
padding: 20px 16px 16px;
background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.6) 100%);
box-shadow: 0px 4px 8px 0px rgba(17, 67, 110, 0.1);
& > h2 {
margin-bottom: 14px;
font-size: 32px;
color: #fff;
}
.item-bottom__info {
display: flex;
align-items: center;
justify-content: space-between;
.right {
display: flex;
align-items: center;
justify-content: space-between;
width: 86px;
height: 48px;
padding: 0 8px;
color: #fff;
background: rgba(0, 0, 0, 0.5);
box-shadow: 0px 4px 8px 0px rgba(17, 67, 110, 0.1);
border-radius: 8px;
image {
width: 28px;
height: 28px;
}
span {
font-size: 28px;
}
}
.left {
span {
color: #c6c5c4;
font-size: 28px;
}
i {
padding: 0 3px;
color: #fff;
font-size: 28px;
font-style: normal;
}
}
}
}
& > span {
position: absolute;
left: 16px;
top: 16px;
z-index: 1;
width: 94px;
height: 40px;
line-height: 40px;
text-align: center;
color: #fff;
font-size: 28px;
background: #FF524F;
box-shadow: 0px 4px 8px 0px rgba(17, 67, 110, 0.1);
border-radius: 8px;
}
.checked {
position: absolute;
top: 0;
right: 0;
z-index: 1;
width: 64px;
height: 64px;
}
.icon {
position: absolute;
top: 50%;
left: 50%;
z-index: 1;
width: 80px;
height: 80px;
transform: translate(-50%, -50%);
}
}
}
scroll-view {
height: calc(100% - 96px);
padding: 0 32px;
font-size: 0;
}
.top {
display: flex;
align-items: center;
justify-content: space-between;
height: 96px;
padding: 0 32px;
font-size: 32px;
color: #999;
font-weight: 600;
span:last-child {
color: #222;
}
}
}
.waterMarker-wrapper {
position: relative;
max-height: calc(100vh - 321px - 128px);
overflow: hidden;
.waterMarker-img {
max-width: 100%;
object-fit: cover;
max-height: calc(100vh - 321px - 128px);
}
.watermark {
position: absolute;
left: 32px;
z-index: 11;
padding: 8px;
color: #FFFFFF;
font-size: 28px;
border: 2px solid #FFFFFF;
.watermark-edit {
position: absolute;
right: 0;
top: 0;
z-index: 1;
width: 80px;
height: 48px;
line-height: 48px;
text-align: center;
background: #FFFFFF;
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5);
border-radius: 24px;
color: #222222;
font-size: 24px;
transform: translate(50%, -50%);
image {
width: 32px;
height: 32px;
}
}
.watermark-close {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
left: 0;
top: 0;
z-index: 1;
width: 48px;
height: 48px;
background: #FFFFFF;
border-radius: 50%;
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.5);
transform: translate(-50%, -50%);
image {
width: 32px;
height: 32px;
}
}
}
}
* {
box-sizing: border-box;
}
.photo-tabbar {
position: fixed;
bottom: 0;
left: 0;
z-index: 10;
width: 100%;
height: 321px;
background: #FFFFFF;
border-radius: 32px 32px 0px 0px;
border: 1px solid #DDDDDD;
overflow: hidden;
h2 {
width: 750px;
height: 96px;
line-height: 96px;
margin-bottom: 20px;
text-align: center;
color: #333333;
font-size: 28px;
}
& > div {
align-items: center;
display: flex;
}
.item {
flex: 1;
text-align: center;
image {
width: 56px;
height: 56px;
margin-bottom: 6px;
}
div {
font-size: 28px;
color: #333;
}
}
}
.photo-bottom {
position: fixed;
bottom: 0;
left: 0;
z-index: 111;
width: 100%;
height: 474px;
background: #FFFFFF;
border-radius: 32px 32px 0px 0px;
transition: all ease 0.3s;
.waterlist {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
height: calc(100% - 96px);
padding: 18px 16px;
overflow-y: auto;
.water-item {
display: flex;
position: relative;
align-items: center;
justify-content: center;
width: 352px;
height: 240px;
margin-bottom: 16px;
background: #2A3540;
border-radius: 8px;
overflow: hidden;
&.active {
border: 6px solid #408EF6;
}
image {
width: 236px;
height: 200px;
}
span {
position: absolute;
left: 50%;
top: 50%;
z-index: 1;
width: 128px;
height: 56px;
line-height: 56px;
text-align: center;
background: rgba(0, 0, 0, 0.8);
border-radius: 8px;
color: #fff;
font-size: 32px;
transform: translate(-50%, -50%);
}
&:first-child {
flex-direction: column;
background: #E4E7EB;
& > image {
width: 64px;
height: 64px;
}
.water-item__bottom {
position: relative;
color: #8A93A4;
font-size: 28px;
background: transparent;
}
}
.checked {
position: absolute;
top: 0;
right: 0;
z-index: 1;
width: 64px;
height: 64px;
}
.water-item__bottom {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 56px;
line-height: 56px;
color: #fff;
text-align: center;
font-size: 28px;
background: rgba(0, 0, 0, 0.7);
}
}
}
.photo-bottom__top {
display: flex;
align-items: center;
justify-content: space-between;
height: 96px;
padding: 0 32px;
image {
width: 40px;
height: 40px;
}
h2 {
font-size: 28px;
color: #333;
}
span {
font-size: 32px;
color: #222;
font-weight: 600;
}
}
}
.photo-top {
display: flex;
position: fixed;
align-items: center;
justify-content: center;
top: 0;
left: 0;
z-index: 11;
width: 100%;
height: 128px;
padding: 0 32px;
background: rgba(0, 0, 0, 0.5);
& > image {
width: 28px;
height: 28px;
}
& > span {
color: #cbcbcb;
font-size: 32px;
}
.photo-top__middle {
display: flex;
align-items: center;
justify-content: center;
width: 400px;
height: 72px;
line-height: 1;
background: #0B111F;
border-radius: 40px;
font-size: 28px;
color: #cbcbcb;
span {
max-width: 70%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
image {
width: 32px;
height: 32px;
margin-left: 16px;
}
}
}
&.home-active {
.photo-bottom {
transform: translateY(100%);
}
.watermark {
border-color: transparent;
// bottom: 38px;
}
}
}
</style>