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

842 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="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="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" @mousedown.stop="move" @wheel="handleWheel">
<div :style="{ transform: `scale(${scale})` }">
<vue2-org-tree
:data="data"
collapsable
:render-content="renderContent"
@on-expand="onExpand"
@on-node-click="NodeClick"
@on-node-mouseover="onMouseover"
@on-node-mouseout="onMouseout"
/>
</div>
</div>
</div>
</div>
<el-dialog
:visible.sync="ifShow"
:close-on-click-modal="false"
width="516px"
>
<div class="rendercontent">
<div ref="htmlContent">
<div class="toprender">
<div class="leftimg">
<img
class="img1"
:src="'data:image/png;base64,' + treeData.avatarUrlBase64"
>
<img
class="img2"
:src="'data:image/png;base64,' + treeData.countryUrl2Base64"
>
</div>
<div class="centerbox">
<div class="lineboex">
<div class="linetitle">{{ '会员编号' }}</div>
<div class="linecontent">{{ treeData.memberCode }}</div>
</div>
<div class="lineboex">
<div class="linetitle">{{ '会员姓名' }}</div>
<div class="linecontent">{{ treeData.name }}</div>
</div>
<div class="lineboex">
<div class="linetitle">安置部门</div>
<div class="linecontent">{{ `第${treeData.placeDept}部门` }}</div>
</div>
<div class="lineboex">
<div class="linetitle">{{ '支付日期' }}</div>
<div class="linecontent">{{ treeData.payDate }}</div>
</div>
</div>
<div class="rightimg">
<img
:src="
'data:image/png;base64,' + treeData.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">{{ 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 class="linecontent">{{ data.aNewBox || 0 }}</div>
<div class="linecontent">{{ data.aSumBox || 0 }}</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 class="linecontent">{{ data.bNewBox || 0 }}</div>
<div class="linecontent">{{ data.bSumBox || 0 }}</div> -->
</div>
</div>
</div>
<div class="footerbox">
<div class="footerbtn btn1" @click="downloadImage">下载图片</div>
<div class="footerbtn btn2" @click="copyText">复制文字</div>
<!-- <div class="footerbtn btn3" @click="goTop(treeData)">置顶</div> -->
</div>
</div>
</el-dialog>
<div v-show="false" ref="copyContent" class="copyContent">
<div>{{ '会员编号' }}{{ treeData.memberCode }}</div>
<div>{{ '会员姓名' }}{{ treeData.name }}</div>
<div>{{ '支付日期' }}{{ treeData.payDate }}</div>
<div>{{ '业绩' }}({{ isLocals() }})&nbsp;&nbsp;左区&nbsp;&nbsp;右区</div>
<div>
真实新增&nbsp;&nbsp;{{ treeData.leftRealNewPv }}&nbsp;&nbsp;{{
treeData.rightRealNewPv
}}
</div>
<div>
首购新增&nbsp;&nbsp;{{ treeData.leftFirstPurchaseAdd }}&nbsp;&nbsp;{{
treeData.rightFirstPurchaseAdd
}}
</div>
<div>
复购新增{{ treeData.leftRepeatPurchaseAdd }}&nbsp;&nbsp;
{{ treeData.rightRepeatPurchaseAdd }}
</div>
<div>
真实累计{{ treeData.leftRealTotal }}&nbsp;&nbsp;{{
treeData.rightRealTotal
}}
</div>
<div>
首购累计{{ treeData.leftFirstTotal }}&nbsp;&nbsp;{{
treeData.rightFirstTotal
}}
</div>
<div>
复购累计 {{ treeData.leftRepeatPurchaseTotal }}&nbsp;&nbsp;{{
treeData.rightRepeatPurchaseTotal
}}
</div>
<div>
首购结余{{ treeData.leftFirstSurplus }}&nbsp;&nbsp;{{
treeData.rightFirstSurplus
}}
</div>
<div>
复购结余 {{ treeData.leftRepeatPurchaseSurplus }}&nbsp;&nbsp;{{
treeData.rightRepeatPurchaseSurplus
}}
</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: 'Azjg4',
components: {
topBar,
TopMemberSelect
},
data() {
return {
moren: 'azjg4',
topList: [
{
name: '方案一',
path: 'azjg'
},
{
name: '方案二',
path: 'azjg2'
},
{
name: '方案三',
path: 'azjg3'
},
{
name: '方案四',
path: 'azjg4'
},
{
name: '方案五',
path: 'azjg5'
}
],
queryParams: {
memberSettlePeriodId: '', // 期数
memberCode: '', // 会员编号
type: 4
},
basicSwitch: false,
basicInfo: { id: null, label: null },
data: {},
treeData: {},
ifShow: false,
avaerInfoList: [],
memberSettlePeriodList: [], // 期数
tzList: [
{ value: 0, label: '是' },
{ value: 1, label: '否' }
],
cantz: 1, // 0不可拖拽,1可拖拽
scale: 1,
loading: false
}
},
created() {
// this.getSearch()
this.getAvarerInfo()
},
methods: {
TopMemberHandleChange(val) {
if (val) {
this.queryParams.memberCode = val
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
}
},
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() {
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()
},
async downloadImage(data) {
this.popdata = data
const element = this.$refs.htmlContent
// 使用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()
},
// 返回
goback() {
this.queryParams.memberCode = this.data.parentMemberCode
this.getSearch()
},
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) {
if (!data || Object.keys(data).length === 0) {
return
}
return (
<div class='xrBox'>
<div class='neibox' on-click={() => this.showPover(data)}>
<div class='topbox'>
<img src={data.avatarUrl}></img>
</div>
<div class='centerbox'>
<div class='cflexbox'>
<img src={data.countryUrl2}></img>
<div class='matitle'>{data.memberCode}</div>
</div>
<div class='cflexbox'>
<img src={data.settleCountryUrl2}></img>
<div class='matitle'>{data.name}</div>
</div>
</div>
<div class='footerbox'>
{/* 阻止冒泡事件 */}
<div
class='ftopbtn'
on-click={() => {
event.stopPropagation(), this.goTop(data)
}}
>
{'置顶'}
</div>
</div>
</div>
</div>
)
},
// 置顶
goTop(row) {
this.queryParams.memberCode = row.memberCode
this.getSearch()
},
showPover(row) {
if (row.memberCode) {
getUrlBase({
countryUrl2: row.countryUrl2,
settleCountryUrl2: row.settleCountryUrl2,
avatarUrl: row.avatarUrl
}).then((res) => {
this.treeData = row
this.treeData.countryUrl2Base64 = res.countryUrl2Base64
this.treeData.settleCountryUrl2Base64 = res.settleCountryUrl2Base64
this.treeData.avatarUrlBase64 = res.avatarUrlBase64
this.ifShow = true
})
}
},
// 点击节点
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) => {
this.data = res.data[0]
// 默认是否展开
this.toggleExpand(this.data, false)
}).finally(() => {
this.loading = false
})
},
resetHandle() {
this.$refs.topMemberSelect.reset()
this.queryParams = {
memberSettlePeriodId: '', // 期数
memberCode: '', // 会员编号
type: 4
}
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-inner {
box-shadow: 0px 2px 20px 0px rgba(204, 204, 204, 0.5);
border-radius: 38px;
}
::v-deep .xrBox {
.neibox {
padding: 10px 24px;
.topbox {
// width: 68px;
// height: 68px;
margin: 0 auto;
img {
width: 68px;
height: 68px;
border-radius: 50%;
}
}
.centerbox {
display: flex;
align-items: center;
justify-content: space-between;
padding: 10px 5px;
text-align: center;
box-shadow: 0px 2px 20px 0px rgba(204, 204, 204, 0.5);
.cflexbox {
margin: 0 10px;
img {
width: 51px;
height: 34px;
border-radius: 8px;
margin-bottom: 8px;
}
.matitle {
font-size: 10px;
}
}
}
.footerbox {
margin-top: 20px;
.ftopbtn {
margin: 0 auto;
width: 68px;
height: 28px;
background: #21c8f4;
border-radius: 4px;
line-height: 28px;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #ffffff;
cursor: pointer;
}
}
}
}
.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 .org-tree-node-label .org-tree-node-label-inner {
padding: 0;
}
::v-deep .el-dialog__body {
padding: 0;
}
::v-deep .org-tree-container {
display: block;
background: rgba(1, 1, 1, 0) !important;
}
::v-deep .xrBox {
.neibox {
// padding: 20px;
.topbox {
// width: 68px;
// height: 68px;
margin: 0 auto;
img {
width: 68px;
height: 68px;
border-radius: 50%;
}
}
}
}
::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: 10px;
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: 10px 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: 10px;
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;
}
.page {
padding: 10px 20px;
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;
}
</style>