web-base-pc/src/views/frame/azjg3.vue

838 lines
24 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">
<div>
<!-- 左侧侧边栏 -->
<sidebarUserInfo></sidebarUserInfo>
</div>
<div>
<btnTopBar
:topList="topList"
:moren="moren"
v-if="topList.length > 0"
></btnTopBar>
<div class="thetopbox">
<el-form ref="form" :model="queryParams" label-width="100px">
<el-row>
<el-col :span="4">
<el-form-item :label="'会员编号'" prop="memberCode">
<el-input
clearable
v-model="queryParams.memberCode"
></el-input></el-form-item
></el-col>
<el-col :span="4">
<el-form-item :label="'结算期数'" prop="memberSettlePeriodId">
<el-select
clearable
:placeholder="'请选择'"
v-model="queryParams.memberSettlePeriodId"
>
<el-option
v-for="item in memberSettlePeriodList"
:key="item.pkId"
:label="item.settleDate"
:value="item.pkId"
></el-option> </el-select></el-form-item
></el-col>
<el-col :span="4">
<el-form-item :label="'展示层数'" prop="level">
<el-input
clearable
v-model="queryParams.level"
></el-input></el-form-item
></el-col>
<el-col :span="4">
<el-form-item :label="'是否固定'"prop="cantz">
<el-select clearable :placeholder="'请选择'" v-model="cantz">
<el-option
v-for="(item, index) in tzList"
:key="index"
:label="item.label"
:value="item.value"
></el-option>
</el-select> </el-form-item
></el-col>
<el-col :span="4" style="margin-left: 30px">
<div class="searchbox">
<el-button class="searchbtn" @click="getSearch">{{ '搜索' }}</el-button>
<el-button @click="reChongzhi">{{ '重置' }}</el-button>
<el-button @click="goback">{{'返回'}}</el-button>
</div>
</el-col>
</el-row></el-form
>
</div>
<div class="theorgtree">
<div class="lefttop">
<div
class="single"
v-for="(item, index) in avaerInfoList"
:key="index"
>
<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
:data="data"
collapsable
ref="orgTree"
@on-expand="onExpand"
@on-node-click="NodeClick"
@on-node-mouseover="onMouseover"
@on-node-mouseout="onMouseout"
:renderContent="renderContent"
v-bind="$listeners"
/>
</div>
</div>
</div>
</div>
</div>
<div
ref="htmlContent"
class="rendercontent"
style="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">{{'业绩'}}(PV)</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>
<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>
</div>
</div>
<div
class="copyContent"
ref="copyContent"
v-show="false"
style="white-space: pre-wrap"
>
<div>{{'会员编号'}}{{ popdata.memberCode }}</div>
<br />
<div>{{'会员姓名'}}{{ popdata.name }}</div>
<div>{{'支付时间'}}{{ popdata.payDate }}</div>
<div>{{'业绩'}}(PV)&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>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import btnTopBar from "@/components/btnTopBar.vue";
import sidebarUserInfo from "@/views/index/components/sidebarUserInfo.vue";
import html2canvas from "html2canvas";
import {
getAzFramework,
getAvarerInfo,
getMemberSettlePeriod,
getUrlBase,
} from "@/api/archityecture";
export default {
components: {
btnTopBar,
sidebarUserInfo,
},
computed: {
...mapGetters(["userInfo"]),
},
data() {
return {
moren: "azjg3",
topList: [
{
name: '方案一',
path: "architecture",
},
{
name: '方案二',
path: "azjg2",
},
{
name: '方案三',
path: "azjg3",
},
{
name: '方案四',
path: "azjg4",
},
],
queryParams: {
memberSettlePeriodId: "", //期数
memberCode: "", //会员编号
level: 2,
type: 3,
},
basicSwitch: false,
basicInfo: { id: null, label: null },
data: {},
treeData: {},
ifShow: false,
avaerInfoList: [],
memberSettlePeriodList: [], //期数
tzList: [
{ value: 0, label: '是' },
{ value: 1, label: '否' },
],
cantz: 1, //0不可拖拽,1可拖拽
popdata: {},
scale: 1,
};
},
created() {
this.queryParams.memberCode = this.userInfo.memberCode;
this.getSearch();
this.getAvarerInfo();
},
methods: {
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));
}
},
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;
};
},
async downloadImage(data) {
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;
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";
},
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">{'业绩'}(PV)</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>
);
},
//置顶
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() {
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);
});
},
reChongzhi() {
this.queryParams = {
memberSettlePeriodId: "", //期数
memberCode: "", //会员编号
level: 2,
type: 3,
};
this.getSearch();
},
},
};
</script>
<style lang="scss" scoped>
::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 {
padding: 0;
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: 5px 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: 5px 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: 5px;
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 0px !important;
background: #f9f9f9;
font-size: 14px;
display: flex;
.thetopbox {
padding: 20px;
background: #ffffff;
border-radius: 8px;
.searchbox {
display: flex;
align-items: center;
.searchtitle {
margin-right: 10px;
}
.searchbtn {
background: #005BAC;
color: #ffffff;
}
}
}
.theorgtree {
width: 100%;
height: 100%;
// margin: 0 auto;
// overflow-y: auto;
// margin-top: 20px;
}
}
::v-deep .org-tree {
margin: 0 auto;
}
::v-deep .org-tree-node-btn {
display: none;
}
</style>