2024-01-05 18:34:45 +08:00

628 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>
<scroll-view class="main" scroll-y="true">
<!-- <div style="position: fixed;right: 0;top: 20%;z-index:99999999999">-->
<!-- <commercial-type :have="1"/>-->
<!-- </div>-->
<header-top ref="headerTop" :bgUrl="bgUrl" :menu="menu" :topBg="topBg" :bgColor="bgColor" :title="title" :page="page" :backType="backType" :analyseInfo="analyseInfo"
:serverpartName="serviceInfo.SERVERPART_NAME" :spregionTypeName="serviceInfo.SPREGIONTYPE_NAME" :serviceInfo="serviceInfo"
:topLeftBg="topLeftBg" :topLeftColor="topLeftColor" :iconObj="iconObj" :haveIconObj="haveIconObj" :detailBoxBg="detailBoxBg"
:haveFun="haveFun" :serviceTypeObj="serviceTypeObj" :serviceInfoObj="serviceInfoObj" :pageType="pageType" :pageIndex="2"
:headerBg="'linear-gradient( #3ca284 0%, #ffffff 100%)'"/>
<div class="charts" :style="{paddingTop:serviceInfo.SERVERPART_NAME==='安徽驿达'?menu.bottom + 62 + 14 + 'px':''}">
<div class="chartsItem" style="height: 440px">
<div style="display: flex;align-items: center;justify-content: space-between">
<p class="title">客单分析</p>
<div class="item">
<text class="value">{{time}}</text>
</div>
</div>
<div v-if="customer">
<customer-first :analyseInfo="{analysisins_type: 1202,analysisins_format: 2000}" :data="customer" />
</div>
<no-data v-else />
</div>
<div class="chartsItem" style="margin-top: 32px;height: 330px">
<div class="time">
<div class="select">
<picker mode="date" fields="month" :value="single" :end="endData" @change="bindDateChange" >
<view class="time">
<view class="uni-input" style="background: transparent;padding: 0;height:100%">{{ single }}</view>
<image class="icon" src="https://eshangtech.com/ShopICO/ahyd-BID/index/arrow_bottom.svg"></image>
</view>
</picker>
</div>
</div>
<p class="title">客群特征分析</p>
<div v-if="genderBubbleList.res && genderBubbleList.res.length>0">
<customer-second :data="genderBubbleList" />
<analyse :analyseInfo="{analysisins_type: 1203,analysisins_format: 2000}" />
</div>
<no-data v-else />
</div>
<div class="chartsItem" style="margin-top: 32px;height: 310px">
<p class="title">客群消费偏好</p>
<div v-if="consterPreferList.series && consterPreferList.series.length>0">
<consum-prefer :data="consterPreferList" />
<analyse :analyseInfo="{analysisins_type: 1204,analysisins_format: 2000}" />
</div>
<no-data v-else/>
</div>
<div class="chartsItem" style="margin-top: 32px;height: 210px">
<p class="title">客群消费水平</p>
<div v-if="consumptionLevelList && consumptionLevelList.length>0">
<consumption-level :data="consumptionLevelList"/>
<analyse :analyseInfo="{analysisins_type: 1205,analysisins_format: 2000}" />
</div>
<no-data v-else />
</div>
<div class="chartsItem" style="margin-top: 32px;height: 220px">
<p class="title" style="margin-bottom: 24px">业态客单偏好</p>
<div >
<business-type :data="businessTypeList"></business-type>
<analyse :analyseInfo="{analysisins_type: 1206,analysisins_format: 2000}" />
</div>
<!-- <no-data v-else />-->
</div>
</div>
</scroll-view>
</template>
<script>
import request from '@/util/index.js'
import headerTop from "./components/headerTop.vue";
import customerFirst from "./components/guest/customerFirst.vue";
import customerSecond from "./components/guest/customerSecond.vue";
import analyse from "./components/analyse.vue";
import ConsumPrefer from "./components/guest/consumPrefer.vue";
import ConsumptionLevel from "./components/guest/consumptionLevel.vue";
import BusinessType from "./components/guest/businessType.vue";
import NoData from "./components/noData.vue";
import {getFieldEnum} from "../../../util/dateTime/index";
import SliderPage from "./components/sliderPage.vue";
export default {
name: "guestPortrait",
components:{
SliderPage,
NoData, BusinessType, ConsumptionLevel, ConsumPrefer, analyse, headerTop,customerFirst,customerSecond},
data() {
return {
topBg:'linear-gradient(180deg, #A1D0C1 0%, #B1D9CD 100%);',//顶部组件的悬浮背景色
title:'客群画像',//页面标题
bgColor:'180deg, #30C8ED 0%, #0B9353 100%',//标签背景颜色
bgUrl:'https://eshangtech.com/ShopICO/ahyd-BID/newCommercialBI/guestPortraitBg.svg',//背景图片路径
page:'/pages/commercialBI/guestPortrait',
pageType:1000,
detailBoxBg:'linear-gradient(136deg, #ECF6F6 0%, #FFFFFF 100%);',
topLeftBg:'linear-gradient(180deg, rgba(48, 200, 237, 0.2) 0%, rgba(11, 147, 83, 0.2) 100%)',// 类别背景
topLeftColor:'#0E9760',// 类别文字颜色
iconObj:{
car:'https://eshangtech.com/ShopICO/ahyd-BID/newCommercialBI/carGuest.svg',
charge:'https://eshangtech.com/ShopICO/ahyd-BID/newCommercialBI/chargeGuest.svg',
bady:'https://eshangtech.com/ShopICO/ahyd-BID/newCommercialBI/badyGuest.svg',
guestRoom:'https://eshangtech.com/ShopICO/ahyd-BID/newCommercialBI/guestRoomGuest.svg'
},
haveIconObj:{
have:'https://eshangtech.com/ShopICO/ahyd-BID/newCommercialBI/haveGuest.svg',
noHave:'https://eshangtech.com/ShopICO/ahyd-BID/newCommercialBI/noHaveGuest.svg'
},
time:'',//跳转携带的时间
menu:{},//手机配置信息
customer:{}, // 客群分析第一个
genderBubbleList:[],//男女的气泡图
consterPreferList:{},//客群消费偏好
consumptionLevelList:[],//客群消费水平
businessTypeList:[],//业态偏好
serviceInfo:{}, //当前服务区信息
backType:'',//返回的页面类型
analyseInfo:{
analysisins_type: 1201,
},
single:'',//显示时间
thisMonth:'',//几月
endData:'', // 结束时间
haveFun:{},
serviceTypeObj:{},// 服务区类型对象
serviceInfoObj:{}
}
},
props:{
selectIndex:{
type:Number,
default:0
}
},
watch:{
selectIndex:{
handler(value){
if (value===2){
this.handleGetPageData()
}
},
immediate:true
}
},
onLoad(option){
// if (option.serviceInfo){
// this.serviceInfo = JSON.parse(option.serviceInfo)
// }
// this.backType = option.type
// //跳转的时候带上时间
// this.time = option.time
// this.endData = new Date()
// // 服务区类型枚举
// this.handleServiceType()
},
onShow(){
let storeTime = uni.getStorageSync('lastDay')
if (storeTime){
this.time = storeTime
}
this.single = this.$util.getThisMonthHave(this.time)
console.log('this.single',this.single)
const date = new Date(this.single)
//设置日期选择器的开始时间和结束时间
let m = date.getMonth() + 1
if (m<10){
m = '0' + m
}
this.thisMonth = m
let storeServiceInfo = uni.getStorageSync('currentService')
if (storeServiceInfo){
this.serviceInfo = storeServiceInfo
}
// 获取手机参数对页面进行适配
let systemInfo = uni.getSystemInfoSync()
// 把获取到的手机参数保存
uni.setStorageSync('phoneInfo',systemInfo)
this.statusBarHeight = Number(systemInfo.statusBarHeight)
this.menu = uni.getMenuButtonBoundingClientRect()
// 把获取图表数据的方法统一放在一起 然后去请求接口拿到数据 再分批传到相对应的图标组件
// 每个图表都是用组件的方式引入的 数据是通过prop传入的
// 每个组件需要的数据格式都注释在方法的下面 方便修改接口拿到数据之后 就是对数据进行处理 普通的遍历数组和遍历对象的方法
if (!storeServiceInfo){
this.nearestService()
}
//customer
this.getCustomer()
//客群分析男女的气泡图
this.getGenderBubbleList()
//客群消费偏好
this.getConsterPreferList()
//客群消费水平
this.getConsumptionLevelList()
//业态偏好
this.getBusinessTypeList()
// 服务区基本信息
this.getServiceInfo()
this.handleChangeCurrent()
},
onUnload() {
this.$util.addUserBehavior()
},
methods:{
// 拿到页面数据
handleGetPageData(){
this.endData = new Date()
// 服务区类型枚举
this.handleServiceType()
let storeTime = uni.getStorageSync('lastDay')
if (storeTime){
this.time = storeTime
}
this.single = this.$util.getThisMonthHave(this.time)
console.log('this.single',this.single)
const date = new Date(this.single)
//设置日期选择器的开始时间和结束时间
let m = date.getMonth() + 1
if (m<10){
m = '0' + m
}
this.thisMonth = m
let storeServiceInfo = uni.getStorageSync('currentService')
if (storeServiceInfo){
this.serviceInfo = storeServiceInfo
}
// 获取手机参数对页面进行适配
let systemInfo = uni.getSystemInfoSync()
// 把获取到的手机参数保存
uni.setStorageSync('phoneInfo',systemInfo)
this.statusBarHeight = Number(systemInfo.statusBarHeight)
this.menu = uni.getMenuButtonBoundingClientRect()
// 把获取图表数据的方法统一放在一起 然后去请求接口拿到数据 再分批传到相对应的图标组件
// 每个图表都是用组件的方式引入的 数据是通过prop传入的
// 每个组件需要的数据格式都注释在方法的下面 方便修改接口拿到数据之后 就是对数据进行处理 普通的遍历数组和遍历对象的方法
if (!storeServiceInfo){
this.nearestService()
}
//customer
this.getCustomer()
//客群分析男女的气泡图
this.getGenderBubbleList()
//客群消费偏好
this.getConsterPreferList()
//客群消费水平
this.getConsumptionLevelList()
//业态偏好
this.getBusinessTypeList()
// 服务区基本信息
this.getServiceInfo()
this.handleChangeCurrent()
},
handleChangeCurrent(){
this.$refs.headerTop.handleChangeCurrent()
},
bindDateChange(e){
const date = new Date(e.detail.value)
let m = date.getMonth() + 1
if (m<10){
m = '0' + m
}
this.thisMonth = m
this.single = e.detail.value
let d = this.$util.getThisMonthDay(e.detail.value)
this.endTime = e.detail.value + '-' + d
this.onRefresh()
},
// 枚举服务区类型 SERVERPART_TYPE
async handleServiceType(){
const data = await getFieldEnum({ FieldExplainField: 'SERVERPART_TYPE' });
console.log('data',data)
let obj = {}
data.forEach(item=>{
obj[Number(item.value)] = item.label
})
console.log('obj',obj)
this.serviceTypeObj = obj
},
//重新调一遍页面数据的方法
onRefresh(){
//客群分析男女的气泡图
this.getGenderBubbleList()
//客群消费偏好
this.getConsterPreferList()
//客群消费水平
this.getConsumptionLevelList()
//业态偏好
this.getBusinessTypeList()
// 服务区基本信息
this.getServiceInfo()
},
//获取服务区基本信息
async getServiceInfo(){
let req = {
ServerpartId:this.serviceInfo.Serverpart_ID
}
const total = await request.$webGet('CommercialApi/BaseInfo/GetServerpartInfo',req)
this.serviceInfoObj = total.Result_Data
this.haveFun = {
car:total.Result_Data.HASPILOTLOUNGE,
charge:total.Result_Data.HASCHARGE ,
bady:total.Result_Data.HASMOTHER ,
gusetHome:total.Result_Data.HASGUESTROOM
}
},
//当前最近的服务区数据
async nearestService(){
let seat = uni.getStorageSync('seatInfo');
let req = {
longitude:seat.longitude,
Province_Code:'340000',
latitude:seat.latitude,
}
const data = await request.$webGet('CommercialApi/BaseInfo/GetServerpartList',req)
let res = {
SERVERPART_NAME:data.Result_Data.List[0].SERVERPART_NAME,//服务区
SPREGIONTYPE_NAME:data.Result_Data.List[0].SPREGIONTYPE_NAME,//片区
Serverpart_ID:data.Result_Data.List[0].SERVERPART_ID,
longitude:data.Result_Data.List[0].SERVERPART_X,
latitude:data.Result_Data.List[0].SERVERPART_Y,
}
uni.setStorageSync('currentService',res)
},
//customer
// 用async await直接等待接口数据返回之后再对数据直接进行处理 节约时间
async getCustomer(){
let time = ''
const date = new Date(this.single)
let y = date.getFullYear()
let m = date.getMonth() + 1
const nowDate = new Date(this.time)
let nowYear = nowDate.getFullYear()
let nowMonth = nowDate.getMonth() + 1
if (y===nowYear && m===nowMonth){
time = this.time
}else{
time = this.endTime
}
console.log('time',time)
const req = {
Province_Code:'340000',
Statistics_Date:time,
Serverpart_ID:this.serviceInfo.SERVERPART_NAME==='安徽驿达'?null:this.serviceInfo.Serverpart_ID,
ShowConsumptionLevel:true,
ShowConvertRate:true
}
let totalData = await request.$webGet('CommercialApi/Revenue/GetTransactionAnalysis',req)
console.log('totalData',totalData)
this.customer = totalData.Result_Data?totalData.Result_Data:{}
},
//客群分析男女的气泡图
async getGenderBubbleList(){
let time = ''
const date = new Date(this.single)
let y = date.getFullYear()
let m = date.getMonth() + 1
const nowDate = new Date(this.time)
let nowYear = nowDate.getFullYear()
let nowMonth = nowDate.getMonth() + 1
if (y===nowYear && m===nowMonth){
time = this.time
}else{
time = this.endTime
}
let result = {
man:'',
woman:'',
res:[]
}
const req = {
statisticsType:1,
provinceCode:'340000',
serverpartId:this.serviceInfo.SERVERPART_NAME==='安徽驿达'?null:this.serviceInfo.Serverpart_ID,
statisticsMonth:this.$util.getThisMonth(time)
}
let totalData = await request.$webGet('CommercialApi/Customer/GetCustomerRatio',req)
totalData.Result_Data.List.forEach(item=>{
// 判断男性和女性 然后赋值
if (item.name === '男性'){
result.man = item.data[0]
}else if(item.name === '女性'){
result.woman = item.data[0]
}
})
const bubbleReq = {
provinceCode:'340000',
serverpartId:this.serviceInfo.SERVERPART_NAME==='安徽驿达'?null:this.serviceInfo.Serverpart_ID,
statisticsMonth:this.$util.getThisMonth(time)
}
let bubbleData = await request.$webGet('CommercialApi/Customer/GetCustomerGroupRatio',bubbleReq)
result.res = bubbleData.Result_Data.List
// let res = [
// {
// name: "男",
// data: [[25,60,30],[40,35,17]]
// },
// {
// name: "女",
// data: [[25,35,17],[35,15,15]]
// }
// ]
this.genderBubbleList = result
},
//客群消费偏好
async getConsterPreferList(){
let time = ''
const date = new Date(this.single)
let y = date.getFullYear()
let m = date.getMonth() + 1
const nowDate = new Date(this.time)
let nowYear = nowDate.getFullYear()
let nowMonth = nowDate.getMonth() + 1
if (y===nowYear && m===nowMonth){
time = this.time
}else{
time = this.endTime
}
let req
if (this.serviceInfo.SERVERPART_NAME==='安徽驿达'){
req = {
statisticsType:1,
startMonth:this.$util.getThisMonth(time),
endMonth:this.$util.getThisMonth(time),
provinceCode: '340000',
}
}else{
req = {
statisticsType:1,
startMonth:this.$util.getThisMonth(time),
endMonth:this.$util.getThisMonth(time),
provinceCode: '340000',
serverpartId: this.serviceInfo.Serverpart_ID || ''
}
}
const data = await request.$webGet('CommercialApi/Customer/GetCustomerSaleRatio',req)
let res = {
categories:[],
series:[
{name: "男", data: []},
{name: "女", data: []}
],
max:''
}
if (data.Result_Data){
data.Result_Data.CustomerSaleList.forEach(item=>{
res.categories.push(item.BusinessTradeName)
res.series[0].data.push(item.MaleRatio)
res.series[1].data.push(item.FemaleRatio)
})
res.max = data.Result_Data.MaxSexRatio
// let res = {
// categories: ['餐饮','商超','水果饮品','连锁品牌','粽子','小吃'],
// series: [
// {name: "男", data: [90,110,165,195,187,172]},
// {name: "女", data: [190,210,105,35,27,102]}
// ]
// }
this.consterPreferList = res
}else{
this.consterPreferList = {}
}
},
//客群消费水平
async getConsumptionLevelList(){
let time = ''
const date = new Date(this.single)
let y = date.getFullYear()
let m = date.getMonth() + 1
const nowDate = new Date(this.time)
let nowYear = nowDate.getFullYear()
let nowMonth = nowDate.getMonth() + 1
if (y===nowYear && m===nowMonth){
time = this.time
}else{
time = this.endTime
}
const req = {
provinceCode:'340000',
serverpartId:this.serviceInfo.SERVERPART_NAME==='安徽驿达'?null:this.serviceInfo.Serverpart_ID,
statisticsMonth:this.$util.getThisMonth(time)
}
const data = await request.$webGet('CommercialApi/Customer/GetCustomerConsumeRatio',req)
let res = []
data.Result_Data.List.forEach(item=>{
res.push({name:item.name,big:(item.data[3]+item.data[2]).toFixed(2),normal:(item.data[1]).toFixed(2),small:item.data[0].toFixed(2)})
})
// let res=[{name:'男',big:'14.8',normal:'41.7',small:'43.5'},
// {name:'女',big:'44.1',normal:'31.7',small:'24.2'}]
this.consumptionLevelList = res
},
//业态偏好
async getBusinessTypeList(){
let time = ''
const date = new Date(this.single)
let y = date.getFullYear()
let m = date.getMonth() + 1
const nowDate = new Date(this.time)
let nowYear = nowDate.getFullYear()
let nowMonth = nowDate.getMonth() + 1
if (y===nowYear && m===nowMonth){
time = this.time
}else{
time = this.endTime
}
let req
if (this.serviceInfo.SERVERPART_NAME==='安徽驿达'){
req = {
ProvinceCode:'340000',
StatisticsDate:time,
}
}else{
req = {
ProvinceCode:'340000',
StatisticsDate:time,
serverpartId:this.serviceInfo.Serverpart_ID
}
}
const data = await request.$webGet('CommercialApi/Revenue/GetBusinessTradeRevenue',req)
let res = []
let all = 0
if (data.Result_Data){
data.Result_Data.BusinessTradeRank.forEach((item,index)=>{
if (index<=4){
res.push({name:`${item.name} ${item.value}%`,value:Number(item.value)})
all+=Number(item.value)
}else if(index===5){
if (all<100){
res.push({name:`其他${(100-all).toFixed(2)}%`,value:Number((100 - all).toFixed(2))})
}
}
})
let result = [
{
data:res
}
]
// let res=[
// {
// data: [{name:"餐饮 35.6%",value:35.6},
// {name:"小吃 22.5%",value:22.5},
// {name:"水果饮品 17.3%",value:17.3},
// {name:"粽子 15.2%",value:15.2},
// {name:"商超 5.8%",value:5.8},
// {name:"其他 3.6%",value:3.6}]
// }
// ]
this.businessTypeList = result
}
}
}
}
</script>
<style scoped lang="scss">
.main{
width: 100vw;
height: 100vh;
.charts{
width: 100%;
box-sizing: border-box;
padding: 14px 16px 24px;
background: #fff;
.time{
margin-bottom: 4px;
.thisTime{
font-size: 14px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 500;
color: #160002;
}
.select{
margin-left: 8px;
display: inline-block;
.time {
display: flex;
align-items: center;
margin-right: 4px;
.day {
font-size: 32rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #782717;
line-height: 44rpx;
margin-right: 4px;
}
.uni-input {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ae664e;
line-height: 36rpx;
}
.icon {
width: 24px;
height: 16px;
}
}
}
}
.chartsItem{
.title{
font-size: 17px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #160002;
line-height: 24px;
}
.item{
.value{
font-size: 14px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 400;
color: #160002;
line-height: 20px;
}
}
}
}
}
</style>