web-retail-h5/components/architectures/resettleSO3.vue

730 lines
18 KiB
Vue
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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="table pr" :style="'zoom:' + size + ';'">
<view class="v-tr" style="display: flex">
<view
class="v-td"
:class="{
colspan: Array.isArray(treeData.children)
? treeData.children.length * 2
: 1,
parentLevel:
Array.isArray(treeData.children) && treeData.children.length,
extend:
Array.isArray(treeData.children) &&
treeData.children.length &&
treeData.extend,
}"
>
<view :class="{ node: true }">
<view
class="person"
:class="Array.isArray(treeData.class) ? treeData.class : []"
>
<view class="Poster1">
<view class="pop_top">
<view class="pop_top">
<view>
<image
crossorigin="anonymous"
data-etype="image"
:data-enode="treeData.avatarUrl"
:src="'data:image/png;base64,' + treeData.avatarUrlBase64"
mode="aspectFit"
class="poster1"
></image>
</view>
<view>
<image
crossorigin="anonymous"
data-etype="image"
:data-enode="treeData.countryUrl2"
:src="
'data:image/png;base64,' + treeData.countryUrl2Base64
"
mode="aspectFit"
class="poster2"
></image>
</view>
</view>
<view class="top_right">
<image
crossorigin="anonymous"
data-etype="image"
:data-enode="treeData.settleCountryUrl2"
:src="
'data:image/png;base64,' +
treeData.settleCountryUrl2Base64
"
mode="aspectFit"
class="poster2"
></image>
<view style="margin-top: 18rpx"> 结算国家 </view>
</view>
</view>
<view class="pop_center">
<view class="center_flex">
<view class="c1">会员编号</view>
<view class="c2">{{ treeData.memberCode }}</view>
</view>
<view class="center_flex">
<view class="c1">会员姓名</view>
<view class="c2">{{ treeData.name }}</view>
</view>
<view class="center_flex">
<view class="c1">支付时间</view>
<view class="c2">{{ treeData.payDate }}</view>
</view>
</view>
<view class="pop_bottom">
<view class="b_flex">
<view class="bt1">业绩</view>
<view class="bt1">左区</view>
<view class="bt1">右区</view>
</view>
<view class="b_flex">
<view class="bt2">真实新增</view>
<view class="bt2">{{ treeData.leftRealNewPv }}</view>
<view class="bt2">{{ treeData.rightRealNewPv }}</view>
</view>
<view class="b_flex">
<view class="bt2">首购新增</view>
<view class="bt2">{{ treeData.leftFirstPurchaseAdd }}</view>
<view class="bt2">{{ treeData.rightFirstPurchaseAdd }}</view>
</view>
<view class="b_flex">
<view class="bt2">复购新增</view>
<view class="bt2">{{
treeData.leftRepeatPurchaseSurplus
}}</view>
<view class="bt2">{{
treeData.rightRepeatPurchaseSurplus
}}</view>
</view>
<view class="b_flex">
<view class="bt2">真实累计</view>
<view class="bt2">{{ treeData.leftRealTotal }}</view>
<view class="bt2">{{ treeData.rightRealTotal }}</view>
</view>
<view class="b_flex">
<view class="bt2">首购累计</view>
<view class="bt2">{{ treeData.leftFirstTotal }}</view>
<view class="bt2">{{ treeData.rightFirstTotal }}</view>
</view>
<view class="b_flex">
<view class="bt2">复购累计</view>
<view class="bt2">{{
treeData.leftRepeatPurchaseTotal
}}</view>
<view class="bt2">{{
treeData.rightRepeatPurchaseTotal
}}</view>
</view>
<view class="b_flex">
<view class="bt2">首购结余</view>
<view class="bt2">{{ treeData.leftFirstSurplus }}</view>
<view class="bt2">{{ treeData.rightFirstSurplus }}</view>
</view>
<view class="b_flex">
<view class="bt2">复购结余</view>
<view class="bt2">{{
treeData.leftRepeatPurchaseSurplus
}}</view>
<view class="bt2">{{
treeData.rightRepeatPurchaseSurplus
}}</view>
</view>
</view>
</view>
<view class="flex_btn">
<view
@click.stop="downImage('Poster1')"
class="goTop_btn"
style="backgroundcolor: #ee1e26"
>
下载图片
</view>
<view
@click.stop="copyText(treeData)"
class="goTop_btn"
style="backgroundcolor: #f37825"
>
复制文字
</view>
<view
@click.stop="clickTop(treeData)"
class="goTop_btn"
style="backgroundcolor: #21c8f4"
>
置顶
</view>
</view>
</view>
</view>
</view>
</view>
<view
class="v-tr"
v-if="
Array.isArray(treeData.children) &&
treeData.children.length &&
treeData.extend
"
>
<view
v-for="(children, index) in treeData.children"
:key="index"
colspan="2"
class="childLevel v-td"
>
<TreeChart
:json="children"
:left="0"
:top="0"
@click-node="clickNode"
@click-top="clickTop"
/>
</view>
</view>
<Eposter
width="750"
height="1334"
:list="list"
backgroundColor="rgb(255, 255, 255)"
@on-success="onSuccess"
ref="Eposter"
>
</Eposter>
</view>
</template>
<script>
import html2canvas from 'html2canvas'
import Eposter from '@/components/architectures/Poster.vue'
import * as arc from '@/config/architecture.js'
export default {
components: {
Eposter,
},
name: 'TreeChart',
props: ['json', 'size'],
data() {
return {
treeData: {},
list: [],
}
},
watch: {
json: {
handler: function (Props) {
let extendKey = function (jsonData) {
jsonData.extend =
jsonData.extend === void 0 ? true : !!jsonData.extend
if (Array.isArray(jsonData.children)) {
jsonData.children.forEach(c => {
extendKey(c)
})
}
return jsonData
}
if (Props) {
arc
.getUrlBase({
countryUrl2: extendKey(Props).countryUrl2,
settleCountryUrl2: extendKey(Props).settleCountryUrl2,
avatarUrl: extendKey(Props).avatarUrl,
})
.then(res => {
extendKey(Props).countryUrl2Base64 = res.countryUrl2Base64
extendKey(Props).settleCountryUrl2Base64 =
res.settleCountryUrl2Base64
extendKey(Props).avatarUrlBase64 = res.avatarUrlBase64
this.treeData = extendKey(Props)
})
}
},
immediate: true,
},
},
methods: {
//复制文字
copyText() {
let self = this
let md = self.treeData
let text = `会员编号:${md.memberCode} \n会员姓名${md.name}支付时间:${md.payDate} \n业绩  左区  右区 \n真实新增  ${md.leftRealNewPv}  ${md.rightRealNewPv} \n首购新增  ${md.leftFirstPurchaseAdd}  ${md.rightFirstPurchaseAdd} \n复购新增 ${md.leftRepeatPurchaseSurplus}  ${md.rightRepeatPurchaseSurplus} \n真实累计 ${md.leftRealTotal}  ${md.rightRealTotal} \n首购累计 ${md.leftFirstTotal}  ${md.rightFirstTotal} \n复购累计 ${md.leftRepeatPurchaseTotal}  ${md.rightRepeatPurchaseTotal} \n首购结余 ${md.leftFirstSurplus}  ${md.rightFirstSurplus} \n复购结余 ${md.leftRepeatPurchaseSurplus}  ${md.rightRepeatPurchaseSurplus} \n`
uni.setClipboardData({
data: text,
success: function (res) {
uni.getClipboardData({
success: function (res) {
uni.showToast({
title: '复制成功',
})
},
})
},
})
},
//下载图片
downImage(elClass) {
this.$refs.Eposter.createForElRect(elClass, false)
},
downloadImg() {
let self = this
let element = document.querySelector('.Poster1')
uni.showLoading({
title: '图片保存中',
})
html2canvas(element)
.then(function (canvas) {
let dataURL = canvas.toDataURL('image/jpeg')
let link = document.createElement('a')
link.style.display = 'none'
link.href = dataURL
link.download = 'image.jpg'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
uni.showToast({
icon: 'none',
title: '保存成功',
duration: 2000,
})
uni.hideLoading()
})
.catch(function (error) {
uni.hideLoading()
uni.showModal({
title: '保存失败',
})
})
},
onSuccess(val) {
this.posterImg = val
this.downloadImg(this.posterImg)
},
toggleExtend: function (treeData) {
treeData.extend = !treeData.extend
this.$forceUpdate()
},
clickTop(e) {
this.$emit('click-top', e)
},
},
}
</script>
<style scoped lang="scss">
.flex_btn {
display: flex;
justify-content: space-between;
align-items: center;
color: #ffffff;
.goTop_btn {
padding: 10rpx 10rpx;
border-radius: 8rpx;
font-size: 22rpx;
margin: 0 auto;
width: 100rpx;
}
}
.Poster1 {
width: 670rpx;
font-size: 24rpx;
color: #333333;
// background-color: pink;
.pop_top {
display: flex;
justify-content: space-between;
align-items: center;
.poster1 {
height: 88rpx;
width: 88rpx;
}
.poster2 {
width: 88rpx;
height: 54rpx;
border-radius: 10rpx;
margin-left: 20rpx;
}
.top_right {
display: flex;
flex-direction: column;
align-items: center;
}
}
.pop_center {
.center_flex {
display: flex;
align-items: center;
margin-top: 20rpx;
.c1 {
width: 20%;
}
.c2 {
width: 80%;
display: flex;
justify-content: center;
align-items: center;
background: #f3f3f3;
border: 2rpx solid #eeeeee;
border-radius: 8rpx;
padding: 10rpx 0;
}
}
}
.pop_bottom {
margin: 20rpx 0;
border-top: 2rpx solid #eeeeee;
border-top: 2rpx solid #eeeeee;
.b_flex {
display: flex;
.bt1 {
display: flex;
justify-content: center;
align-items: center;
margin-top: 22rpx;
flex: 1;
}
.bt2 {
display: flex;
justify-content: center;
align-items: center;
margin-top: 22rpx;
flex: 1;
background: #f3f3f3;
border: 2rpx solid #eeeeee;
border-radius: 8rpx;
padding: 12rpx 0;
margin: 11rpx 18rpx;
}
}
}
.btn_box {
display: flex;
align-items: center;
justify-content: space-between;
.small-btn {
width: 312rpx;
height: 72rpx;
background: #005bac;
border-radius: 34rpx;
font-size: 28rpx;
font-weight: 400;
color: #ffffff;
display: flex;
justify-content: center;
align-items: center;
}
.small-text-btn {
width: 312rpx;
height: 72rpx;
border: 1px solid #005bac;
border-radius: 34rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 28rpx;
color: #005bac;
}
}
}
.f18 {
font-size: 18rpx;
}
.pv-btn {
width: 200rpx;
height: 50rpx;
background-color: #b2821e;
color: #fff;
font-size: 20rpx;
line-height: 50rpx;
display: flex;
align-items: center;
margin: auto;
margin-top: 12rpx;
margin-bottom: 12rpx;
}
.next-btn {
border-radius: 50%;
background: none;
width: 40rpx;
height: 40rpx;
margin: auto;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
}
.table {
border-collapse: separate !important;
border-spacing: 0 !important;
width: 100%;
}
.v-tr {
display: inline-flex;
justify-content: center;
align-items: flex-start;
/* width: 100%; */
}
.v-td {
position: relative;
vertical-align: top;
padding: 0 0 130rpx 0;
text-align: center;
}
.extend_handle {
position: absolute;
left: 50%;
bottom: 30rpx;
width: 10rpx;
height: 10rpx;
padding: 10rpx;
transform: translate3d(-30rpx, 0, 0);
cursor: pointer;
}
.extend_handle:before {
content: '';
display: block;
width: 100%;
height: 100%;
box-sizing: border-box;
border: 4rpx solid;
border-color: #f2f2f2 #f2f2f2 transparent transparent;
transform: rotateZ(135deg);
transform-origin: 50% 50% 0;
transition: transform ease 300ms;
}
.extend_handle:hover:before {
border-color: #f2f2f2 #f2f2f2 transparent transparent;
}
.extend .extend_handle:before {
transform: rotateZ(-45deg);
}
.extend::after {
content: '';
position: absolute;
left: 50%;
bottom: 84rpx;
height: 84rpx;
border-left: 4rpx solid #f2f2f2;
transform: translate3d(-2rpx, 0, 0);
}
.childLevel::before {
content: '';
position: absolute;
left: 50%;
bottom: 100%;
height: 84rpx;
border-left: 4rpx solid #f2f2f2;
transform: translate3d(-2rpx, 0, 0);
}
.childLevel::after {
content: '';
position: absolute;
left: 0;
right: 0;
top: -88rpx;
border-top: 4rpx solid #f2f2f2;
}
.childLevel:first-child:before,
.childLevel:last-child:before {
display: none;
}
.childLevel:first-child:after {
left: 50%;
height: 84rpx;
border: 4rpx solid;
border-color: #f2f2f2 transparent transparent #f2f2f2;
border-radius: 6rpx 0 0 0;
transform: translate3d(2rpx, 0, 0);
}
.childLevel:last-child:after {
right: 50%;
height: 84rpx;
border: 4rpx solid;
border-color: #f2f2f2 #f2f2f2 transparent transparent;
border-radius: 0 6rpx 0 0;
transform: translate3d(-2rpx, 0, 0);
}
.childLevel:first-child.childLevel:last-child::after {
left: auto;
border-radius: 0;
border-color: transparent #f2f2f2 transparent transparent;
transform: translate3d(2rpx, 0, 0);
}
.node {
position: relative;
display: inline-block;
margin: 0 10rpx;
box-sizing: border-box;
text-align: center;
}
.node .person {
position: relative;
display: inline-block;
z-index: 2;
padding: 23rpx 50rpx;
background-color: #ffffff;
box-shadow: 0rpx 3rpx 7rpx 0rpx rgba(0, 0, 0, 0.15);
border-radius: 15rpx;
font-size: 22rpx;
}
.person_flex {
display: flex;
padding: 10rpx 20rpx;
box-shadow: 0rpx 3rpx 7rpx 0rpx rgba(0, 0, 0, 0.15);
margin: 0rpx 0 20rpx 0;
}
.flex-p1 {
margin: 0 5rpx;
}
.node .person .person-ava {
width: 88rpx;
height: 53rpx;
border-radius: 10rpx;
}
.node .person .person-ava1 {
width: 104rpx;
height: 104rpx;
border-radius: 50%;
}
.node .person .avat {
display: block;
width: 4em;
height: 4em;
margin: auto;
overflow: hidden;
background: #fff;
border: 4px solid #f2f2f2;
box-sizing: border-box;
border-radius: 0.5em;
}
.node .person .avat img {
width: 100%;
height: 100%;
}
.node .person .name {
display: block;
margin: auto;
overflow: hidden;
box-sizing: border-box;
overflow: hidden;
font-size: 20rpx;
line-height: 1.5;
padding-top: 24rpx;
}
.node .person .name-bottom {
display: block;
margin: auto;
overflow: hidden;
border-top: none;
box-sizing: border-box;
overflow: hidden;
}
.node .person .operation {
}
.node.hasMate::after {
content: '';
position: absolute;
left: 2em;
right: 2em;
top: 2em;
border-top: 4px solid #f2f2f2;
z-index: 1;
}
/* 横板 */
.landscape {
transform: translate(-100%, 0) rotate(-90deg);
transform-origin: 100% 0;
}
.landscape .node {
text-align: left;
height: 8em;
width: 8em;
}
.landscape .person {
position: relative;
transform: rotate(90deg);
padding-left: 4.5em;
height: 4em;
top: 4em;
left: -1em;
}
.landscape .person .avat {
position: absolute;
left: 0;
}
.landscape .person .name {
height: 4em;
line-height: 4em;
}
.landscape .hasMate {
position: relative;
}
.landscape .hasMate .person {
position: absolute;
}
.landscape .hasMate .person:first-child {
left: auto;
right: -4em;
}
.landscape .hasMate .person:last-child {
left: -4em;
margin-left: 0;
}
</style>