web-base-admin/src/views/framework/architecture/azjg3.vue

864 lines
25 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="page">
<topBar
v-if="topList.length > 0"
:top-list="topList"
:moren="moren"
/>
<div class="thetopbox">
<el-form ref="form" :model="queryParams" label-width="100px">
<el-row>
<el-col :span="4">
<TopMemberSelect ref="topMemberSelect" @change="TopMemberHandleChange" />
</el-col>
<el-col :span="4">
<el-form-item :label="'会员编号'" prop="memberCode">
<el-input
v-model="queryParams.memberCode"
clearable
/></el-form-item></el-col>
<el-col :span="4">
<el-form-item :label="'结算期数'" prop="memberSettlePeriodId">
<el-select
v-model="queryParams.memberSettlePeriodId"
clearable
:placeholder="'请选择'"
>
<el-option
v-for="item in memberSettlePeriodList"
:key="item.pkId"
:label="item.settleDate"
:value="item.pkId"
/> </el-select></el-form-item></el-col>
<el-col :span="4">
<el-form-item :label="'展示层数'" prop="level">
<el-input
v-model="queryParams.level"
clearable
/></el-form-item></el-col>
<el-col :span="4">
<el-form-item :label="'是否固定'" prop="cantz">
<el-select v-model="cantz" clearable :placeholder="'请选择'">
<el-option
v-for="(item, index) in tzList"
:key="index"
:label="item.label"
:value="item.value"
/>
</el-select> </el-form-item></el-col>
<el-col :span="4" style="margin-left: 30px">
<div class="searchbox">
<el-button
:loading="loading"
class="searchbtn"
@click="getSearch"
> {{ '搜索' }}</el-button>
<el-button @click="resetHandle"> {{ '重置' }}</el-button>
<el-button @click="goback"> {{ '返回' }}</el-button>
</div>
</el-col>
</el-row></el-form>
</div>
<div class="theorgtree">
<div class="lefttop">
<div v-for="(item, index) in avaerInfoList" :key="index" class="single">
<img :src="item.value" alt="">
<div class="singletitle">{{ item.name }}</div>
</div>
</div>
<div class="tree">
<div class="tree-content" @wheel="handleWheel" @mousedown.stop="move">
<div :style="{ transform: `scale(${scale})` }">
<vue2-org-tree
ref="orgTree"
:data="data"
collapsable
:render-content="renderContent"
v-bind="$listeners"
@on-expand="onExpand"
@on-node-click="NodeClick"
@on-node-mouseover="onMouseover"
@on-node-mouseout="onMouseout"
/>
</div>
</div>
</div>
</div>
<div
ref="htmlContent"
class="rendercontent"
style="
width: 516px;
background-color: #ffffff;
display: none;
height: 470px;
"
>
<div class="toprender">
<div class="leftimg">
<img
class="img1"
:src="'data:image/png;base64,' + popdata.avatarUrlBase64"
>
<img
class="img2"
:src="'data:image/png;base64,' + popdata.countryUrl2Base64"
>
</div>
<div class="centerbox">
<div class="lineboex">
<div class="linetitle">{{ '会员编号' }}</div>
<div class="linecontent">{{ popdata.memberCode }}</div>
</div>
<div class="lineboex">
<div class="linetitle">{{ '会员姓名' }}</div>
<div class="linecontent">{{ popdata.name }}</div>
</div>
<div class="lineboex">
<div class="linetitle">{{ '支付日期' }}</div>
<div class="linecontent">{{ popdata.payDate }}</div>
</div>
</div>
<div class="rightimg">
<img
:src="'data:image/png;base64,' + popdata.settleCountryUrl2Base64"
>
<div>{{ '结算国家' }}</div>
</div>
</div>
<div class="bottomrender">
<div class="flexbox">
<div class="thetitle">{{ '业绩' }}({{ isLocals() }})</div>
<div class="linecontent">{{ '真实新增' }}</div>
<div class="linecontent">首购新增</div>
<div class="linecontent">复购新增</div>
<div class="linecontent">真实累计</div>
<div class="linecontent">首购累计</div>
<div class="linecontent">复购累计</div>
<div class="linecontent">首购结余</div>
<div class="linecontent">复购结余</div>
<!-- <div class="linecontent">新増套数</div>
<div class="linecontent">累计套数</div> -->
</div>
<div class="flexbox">
<div class="thetitle">左区</div>
<div class="linecontent">{{ popdata.leftRealNewPv }}</div>
<div class="linecontent">{{ popdata.leftFirstPurchaseAdd }}</div>
<div class="linecontent">{{ popdata.leftRepeatPurchaseAdd }}</div>
<div class="linecontent">{{ popdata.leftRealTotal }}</div>
<div class="linecontent">{{ popdata.leftFirstTotal }}</div>
<div class="linecontent">{{ popdata.leftRepeatPurchaseTotal }}</div>
<div class="linecontent">{{ popdata.leftFirstSurplus }}</div>
<div class="linecontent">{{ popdata.leftRepeatPurchaseSurplus }}</div>
<!-- <div class="linecontent">{{ popdata.aNewBox || 0 }}</div>
<div class="linecontent">{{ popdata.aSumBox || 0 }}</div> -->
</div>
<div class="flexbox">
<div class="thetitle">右区</div>
<div class="linecontent">{{ popdata.rightRealNewPv }}</div>
<div class="linecontent">{{ popdata.rightFirstPurchaseAdd }}</div>
<div class="linecontent">{{ popdata.rightRepeatPurchaseAdd }}</div>
<div class="linecontent">{{ popdata.rightRealTotal }}</div>
<div class="linecontent">{{ popdata.rightFirstTotal }}</div>
<div class="linecontent">{{ popdata.rightRepeatPurchaseTotal }}</div>
<div class="linecontent">{{ popdata.rightFirstSurplus }}</div>
<div class="linecontent">
{{ popdata.rightRepeatPurchaseSurplus }}
</div>
<!-- <div class="linecontent">{{ popdata.bNewBox || 0 }}</div>
<div class="linecontent">{{ popdata.bSumBox || 0 }}</div> -->
</div>
</div>
</div>
<div v-show="false" ref="copyContent" class="copyContent">
<div>{{ '会员编号' }}{{ popdata.memberCode }}</div>
<div>{{ '会员姓名' }}{{ popdata.name }}</div>
<div>{{ '支付日期' }}{{ popdata.payDate }}</div>
<div>{{ '业绩' }}({{ isLocals() }})&nbsp;&nbsp;左区&nbsp;&nbsp;右区</div>
<div>
真实新增&nbsp;&nbsp;{{ popdata.leftRealNewPv }}&nbsp;&nbsp;{{
popdata.rightRealNewPv
}}
</div>
<div>
首购新增&nbsp;&nbsp;{{ popdata.leftFirstPurchaseAdd }}&nbsp;&nbsp;{{
popdata.rightFirstPurchaseAdd
}}
</div>
<div>
复购新增{{ popdata.leftRepeatPurchaseAdd }}&nbsp;&nbsp;
{{ popdata.rightRepeatPurchaseAdd }}
</div>
<div>
真实累计{{ popdata.leftRealTotal }}&nbsp;&nbsp;{{
popdata.rightRealTotal
}}
</div>
<div>
首购累计{{ popdata.leftFirstTotal }}&nbsp;&nbsp;{{
popdata.rightFirstTotal
}}
</div>
<div>
复购累计 {{ popdata.leftRepeatPurchaseTotal }}&nbsp;&nbsp;{{
popdata.rightRepeatPurchaseTotal
}}
</div>
<div>
首购结余{{ popdata.leftFirstSurplus }}&nbsp;&nbsp;{{
popdata.rightFirstSurplus
}}
</div>
<div>
复购结余 {{ popdata.leftRepeatPurchaseSurplus }}&nbsp;&nbsp;{{
popdata.rightRepeatPurchaseSurplus
}}
</div>
<div>
新増套数 {{ popdata.aNewBox }}&nbsp;&nbsp;{{
popdata.aSumBox
}}
</div>
<div>
累计套数 {{ popdata.bNewBox }}&nbsp;&nbsp;{{
popdata.bSumBox
}}
</div>
</div>
</div>
</template>
<script>
import topBar from '@/components/topBar'
import html2canvas from 'html2canvas'
import {
getAzFramework,
getAvarerInfo,
getMemberSettlePeriod,
getUrlBase
} from '@/api/archityecture'
import { isLocals } from '../../../utils/numberToCurrency'
import TopMemberSelect from './components/top-member-select.vue'
export default {
name: 'Azjg3',
components: {
topBar,
TopMemberSelect
},
data() {
return {
moren: 'azjg3',
topList: [
{
name: '方案一',
path: 'azjg'
},
{
name: '方案二',
path: 'azjg2'
},
{
name: '方案三',
path: 'azjg3'
},
{
name: '方案四',
path: 'azjg4'
},
{
name: '方案五',
path: 'azjg5'
}
],
queryParams: {
memberSettlePeriodId: '', // 期数
memberCode: '', // 会员编号
level: 3,
type: 3
},
basicSwitch: false,
basicInfo: { id: null, label: null },
data: {},
avaerInfoList: [],
memberSettlePeriodList: [], // 期数
tzList: [
{ value: 0, label: '是' },
{ value: 1, label: '否' }
],
cantz: 1, // 0不可拖拽,1可拖拽
popdata: {},
scale: 1,
loading: false
}
},
created() {
this.getSearch()
this.getAvarerInfo()
},
methods: {
TopMemberHandleChange(val) {
if (val) {
this.queryParams.memberCode = val
this.getSearch()
}
},
handleWheel(event) {
if (this.cantz == 1) {
event.preventDefault()
const delta = Math.sign(event.deltaY)
const newScale = this.scale - delta * 0.1
this.scale = Math.max(0.01, Math.min(newScale, 10))
}
},
isLocals,
copyText(data) {
this.popdata = data
setTimeout(() => {
const copyContent = this.$refs.copyContent
const textLines = Array.from(copyContent.querySelectorAll('div')).map(
(div) => div.textContent.trim()
)
const text = textLines.join('\n')
const tempInput = document.createElement('textarea')
tempInput.value = text
document.body.appendChild(tempInput)
tempInput.select()
try {
document.execCommand('copy')
this.$message({
message: '复制成功',
type: 'success'
})
} catch (error) {
this.$message({
message: '复制失败',
type: 'warning'
})
}
tempInput.remove()
window.getSelection().removeAllRanges()
}, 50)
},
// 返回
goback() {
this.queryParams.memberCode = this.data.parentMemberCode
this.getSearch()
},
// 拖拽移动
move(e) {
if (this.cantz == 0) {
return
}
const odiv = e.currentTarget // 获取元素
// 算出鼠标相对元素的位置
const disX = e.clientX - odiv.offsetLeft
const disY = e.clientY - odiv.offsetTop
document.onmousemove = (e) => {
// 鼠标按下并移动的事件
// 用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
const left = e.clientX - disX
const top = e.clientY - disY
// 绑定元素位置到positionX和positionY上面
this.positionX = top
this.positionY = left
// 移动当前元素
odiv.style.left = left + 'px'
odiv.style.top = top + 'px'
}
document.onmouseup = () => {
document.onmousemove = null
document.onmouseup = null
}
},
getAvarerInfo() {
getAvarerInfo().then((res) => {
this.avaerInfoList = res.data
})
getMemberSettlePeriod().then((res) => {
this.memberSettlePeriodList = res.data
this.memberSettlePeriodList.forEach((ele) => {
if (ele.isThisDay == 0) {
this.queryParams.memberSettlePeriodId = ele.pkId
}
})
})
},
// 鼠标移入
onMouseover(e, data) {
this.basicInfo = data
this.basicSwitch = true
},
// 鼠标移出
onMouseout(e, data) {
this.basicSwitch = false
},
// 渲染节点
renderContent(h, data) {
return (
<div class='rendercontent'>
<div class='toprender'>
<div class='leftimg'>
<img class='img1' src={data.avatarUrl} />
<img class='img2' src={data.countryUrl2} />
</div>
<div class='centerbox'>
<div class='lineboex'>
<div class='linetitle'>{ '会员编号' }</div>
<div class='linecontent'>{data.memberCode}</div>
</div>
<div class='lineboex'>
<div class='linetitle'>{ '会员姓名' }</div>
<div class='linecontent'>{data.name}</div>
</div>
<div class='lineboex'>
<div class='linetitle'>{ '支付日期' }</div>
<div class='linecontent'>{data.payDate}</div>
</div>
</div>
<div class='rightimg'>
<img src={data.settleCountryUrl2} />
<div>{'结算国家'}</div>
</div>
</div>
<div class='bottomrender'>
<div class='flexbox'>
<div class='thetitle'>{ '业绩' }({isLocals()})</div>
<div class='linecontent'>{'真实新增'}</div>
<div class='linecontent'>首购新增</div>
<div class='linecontent'>复购新增</div>
<div class='linecontent'>真实累计</div>
<div class='linecontent'>首购累计</div>
<div class='linecontent'>复购累计</div>
<div class='linecontent'>首购结余</div>
<div class='linecontent'>复购结余</div>
</div>
<div class='flexbox'>
<div class='thetitle'>左区</div>
<div class='linecontent'>{data.leftRealNewPv}</div>
<div class='linecontent'>{data.leftFirstPurchaseAdd}</div>
<div class='linecontent'>{data.leftRepeatPurchaseAdd}</div>
<div class='linecontent'>{data.leftRealTotal}</div>
<div class='linecontent'>{data.leftFirstTotal}</div>
<div class='linecontent'>{data.leftRepeatPurchaseTotal}</div>
<div class='linecontent'>{data.leftFirstSurplus}</div>
<div class='linecontent'>{data.leftRepeatPurchaseSurplus}</div>
</div>
<div class='flexbox'>
<div class='thetitle'>右区</div>
<div class='linecontent'>{data.rightRealNewPv}</div>
<div class='linecontent'>{data.rightFirstPurchaseAdd}</div>
<div class='linecontent'>{data.rightRepeatPurchaseAdd}</div>
<div class='linecontent'>{data.rightRealTotal}</div>
<div class='linecontent'>{data.rightFirstTotal}</div>
<div class='linecontent'>{data.rightRepeatPurchaseTotal}</div>
<div class='linecontent'>{data.rightFirstSurplus}</div>
<div class='linecontent'>{data.rightRepeatPurchaseSurplus}</div>
</div>
</div>
<div class='footerbox'>
<div
class='footerbtn btn1'
on-click={() => {
this.downloadImage(data)
}}
>
下载图片
</div>
<div
class='footerbtn btn2'
on-click={() => {
this.copyText(data)
}}
>
复制文字
</div>
<div
class='footerbtn btn3'
on-click={() => {
event.stopPropagation(), this.goTop(data)
}}
>
{'置顶'}
</div>
</div>
</div>
)
},
// 下载图片
async downloadImage(data) {
// 转换为base64格式
await getUrlBase({
countryUrl2: data.countryUrl2,
settleCountryUrl2: data.settleCountryUrl2,
avatarUrl: data.avatarUrl
}).then((res) => {
this.popdata = data
this.popdata.countryUrl2Base64 = res.countryUrl2Base64
this.popdata.settleCountryUrl2Base64 = res.settleCountryUrl2Base64
this.popdata.avatarUrlBase64 = res.avatarUrlBase64
})
const element = this.$refs.htmlContent
// 使用html2canvas将节点生成为图片添加延迟等待
await new Promise((resolve) => setTimeout(resolve, 50)) // 根据实际情况调整延迟时间
element.style.display = 'block'
// 使用html2canvas将节点生成为图片
const canvas = await html2canvas(element)
const image = canvas.toDataURL('image/png')
// 复制图片到剪贴板
try {
await navigator.clipboard.write([
new ClipboardItem({
'image/png': await new Promise((resolve) =>
canvas.toBlob(resolve, 'image/png')
)
})
])
this.$message({
message: '复制成功',
type: 'success'
})
} catch (error) {
// this.$message({
// message: "复制失败",
// type: "warning",
// });
}
// 下载图片到本地
const link = document.createElement('a')
link.href = image
link.download = 'image.png'
link.click()
// 隐藏图片
element.style.display = 'none'
},
// 置顶
goTop(row) {
this.queryParams.memberCode = row.memberCode
this.getSearch()
},
// 点击节点
NodeClick(e, data) {},
// 默认展开
toggleExpand(data, val) {
if (Array.isArray(data)) {
data.forEach((item) => {
this.$set(item, 'expand', val)
if (item.children) {
this.toggleExpand(item.children, val)
}
})
} else {
this.$set(data, 'expand', val)
if (data.children) {
this.toggleExpand(data.children, val)
}
}
},
collapse(list) {
list.forEach((child) => {
if (child.expand) {
child.expand = false
}
child.children && this.collapse(child.children)
})
},
// 展开
onExpand(e, data) {
if ('expand' in data) {
data.expand = !data.expand
if (!data.expand && data.children) {
this.collapse(data.children)
}
} else {
this.$set(data, 'expand', true)
}
},
getSearch() {
this.loading = true
getAzFramework(this.queryParams).then((res) => {
res.data.forEach((ele) => {
ele.countryUrl2Base64 = ''
ele.settleCountryUrl2Base64 = ''
ele.avatarUrlBase64 = ''
})
this.data = res.data[0]
this.toggleExpand(this.data, true)
}).finally(() => {
this.loading = false
})
},
resetHandle() {
this.$refs.topMemberSelect.reset()
this.queryParams = {
memberSettlePeriodId: '', // 期数
memberCode: '', // 会员编号
level: 3,
type: 3
}
this.getSearch()
}
}
}
</script>
<style lang="scss" scoped>
::v-deep .el-dialog__headerbtn {
top: 5px;
right: 10px;
border: 1px solid #c8c3c3;
padding: 2px 3px;
border-radius: 50%;
}
::v-deep .tree-content {
background: rgba(0, 0, 0, 0) !important;
}
.tree {
background: #fff;
// min-height: 100vh;
min-height: calc(100vh - 110px);
position: relative;
text-align: center;
// overflow-x: scroll;
width: 100%;
height: 100%;
margin: auto;
// overflow-y: hidden;
// margin-left: -60px;
// margin-top: 20px;
// background: red;
&-content {
text-align: center;
width: 100%;
height: 100%;
background: #fff;
position: absolute;
top: 0;
left: 0;
// overflow: auto;
}
}
::v-deep .org-tree-node-label .org-tree-node-label-inner {
margin: auto;
background: rgba(0, 0, 0, 0);
padding: 0 !important;
}
::v-deep .el-dialog__body {
padding: 0;
}
::v-deep .org-tree-container {
display: block;
}
::v-deep .xrBox {
.neibox {
// padding: 20px;
.topbox {
// width: 68px;
// height: 68px;
margin: 0 auto;
img {
width: 68px;
height: 68px;
border-radius: 50%;
}
}
}
}
.lefttop {
display: flex;
justify-items: center;
align-items: center;
padding-left: 20px;
background: #ffffff;
.single {
margin: 0 5px;
img {
width: 40px;
height: 40px;
border-radius: 50%;
// box-shadow: 0px 2px 20px 0px rgba(204, 204, 204, 0.5);
}
.singletitle {
text-align: center;
font-size: 10px;
font-family: PingFang SC-Regular, PingFang SC;
}
}
}
::v-deep .rendercontent {
.toprender {
display: flex;
border-bottom: 1px solid #cccccc;
.leftimg {
border-right: 1px solid #cccccc;
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
padding: 10px;
.img1 {
width: 75px;
height: 75px;
border-radius: 50%;
}
.img2 {
margin-top: 5px;
width: 50px;
height: 30px;
border-radius: 8px;
}
}
.centerbox {
padding: 10px;
.lineboex {
display: flex;
align-items: center;
margin: 10px 0;
.linetitle {
margin-right: 5px;
font-size: 10px;
font-family: MicrosoftYaHei-Bold, MicrosoftYaHei;
font-weight: bold;
color: #333333;
}
.linecontent {
font-size: 10px;
font-family: MicrosoftYaHei;
color: #333333;
display: flex;
justify-content: center;
align-items: center;
padding: 12px 0;
width: 166px;
height: 20px;
background: rgba(216, 216, 216, 0.3);
border-radius: 4px;
border: 1px solid #cccccc;
}
}
}
.rightimg {
flex: 1;
padding: 10px;
font-size: 10px;
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
font-family: MicrosoftYaHei-Bold, MicrosoftYaHei;
font-weight: bold;
color: #333333;
text-align: center;
img {
width: 75px;
height: 50px;
border-radius: 8px;
margin-bottom: 10px;
}
}
}
.bottomrender {
padding: 10px;
display: flex;
.flexbox {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
.thetitle {
font-size: 10px;
font-family: MicrosoftYaHei-Bold, MicrosoftYaHei;
font-weight: bold;
color: #333333;
}
.linecontent {
margin-top: 5px;
padding: 10px 0;
font-size: 10px;
font-family: MicrosoftYaHei;
color: #333333;
display: flex;
justify-content: center;
align-items: center;
width: 110px;
height: 20px;
background: rgba(216, 216, 216, 0.3);
border-radius: 4px;
border: 1px solid #cccccc;
}
}
}
.footerbox {
display: flex;
padding: 10px;
justify-content: space-around;
.footerbtn {
width: 78px;
height: 28px;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #ffffff;
padding: 10px;
cursor: pointer;
}
.btn1 {
background: #ee1e26;
}
.btn2 {
background: #f37825;
}
.btn3 {
background: #21c8f4;
}
}
}
::v-deep .org-tree-container {
display: block;
background: rgba(1, 1, 1, 0) !important;
}
.page {
padding: 10px 20px !important;
background: #f9f9f9;
font-size: 14px;
.thetopbox {
padding: 20px;
background: #ffffff;
border-radius: 8px;
.searchbox {
display: flex;
align-items: center;
.searchtitle {
margin-right: 10px;
}
.searchbtn {
background: #c8161d;
color: #ffffff;
}
}
}
.theorgtree {
overflow: auto;
margin-top: 20px;
}
}
::v-deep .org-tree {
margin: 0 auto;
}
::v-deep .org-tree-node-btn {
display: none;
}
</style>