123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536 |
- <style lang="less">
- page {
- background-color: #eceff4;
- }
- .page-container {
- width: 100%;
- height: 100%;
- box-sizing: border-box;
- box-sizing: border-box;
- padding: 30rpx 44rpx;
- font-family: PingFang SC;
- }
- .visitor-title {
- display: flex;
- justify-content: space-between;
- align-items: flex-end;
- .visitor-title-left {
- font-size: 48rpx;
- font-weight: 400;
- line-height: 68rpx;
- color: rgba(0, 0, 0, 1);
- }
- .visitor-title-right {
- font-family: Montserrat;
- display: flex;
- font-size: 26rpx;
- font-weight: 400;
- line-height: 36rpx;
- color: rgba(77, 82, 98, 1);
- }
- }
- .visitor-info {
- margin-top: 60rpx;
- display: flex;
- justify-content: space-between;
- height: 212rpx;
- width: 662rpx;
- border-radius: 16rpx;
- background: rgba(255, 255, 255, 1);
- padding: 60rpx 40rpx;
- box-sizing: border-box;
- .visitor-info-item {
- .info-title {
- font-size: 26rpx;
- font-weight: 400;
- line-height: 36rpx;
- color: rgba(196, 196, 196, 1);
- }
- .info-num {
- display: flex;
- padding-top: 14rpx;
- .info-num-value {
- font-family: Montserrat;
- font-size: 46rpx;
- font-weight: 400;
- line-height: 42rpx;
- color: rgba(0, 0, 0, 1);
- margin-right: 6rpx;
- }
- .info-num-unit {
- font-size: 18rpx;
- font-weight: 400;
- line-height: 26rpx;
- color: rgba(196, 196, 196, 1);
- }
- }
- }
- }
- .visitor-num {
- margin-top: 26rpx;
- height: 350rpx;
- width: 100%;
- .meeting-time-legend {
- display: flex;
- .legend-item {
- display: flex;
- align-items: center;
- margin-right: 40rpx;
- .legend-item-shape {
- height: 12rpx;
- width: 30rpx;
- border-radius: 6rpx;
- background: #5e8bcf;
- margin-right: 12rpx;
- &.grey {
- background: #9fb7cd;
- }
- }
- .legend-item-text {
- font-size: 20rpx;
- font-weight: 400;
- line-height: 28rpx;
- color: #4d5262;
- }
- }
- }
- }
- .visitor-function {
- padding: 36rpx 40rpx;
- margin-top: 30rpx;
- // height: 276px;
- border-radius: 16rpx;
- background: rgba(255, 255, 255, 1);
- .visitor-card-item {
- display: flex;
- align-items: center;
- .visitor-card-item-pic {
- width: 32rpx;
- height: 32rpx;
- .img {
- width: 100%;
- height: 100%;
- }
- }
- .visitor-card-item-pic:nth-child(1) {
- padding-bottom: 4rpx;
- }
- .visitor-card-item-name {
- margin-left: 24rpx;
- margin-right: 38rpx;
- font-size: 24rpx;
- font-weight: 400;
- line-height: 34rpx;
- width: 104rpx;
- }
- .visitor-card-item-line {
- height: 10rpx;
- width: 220rpx;
- background: rgba(166, 206, 227, 1);
- border-radius: 0px 6rpx 6rpx 0px;
- &.nav {
- background: #1f78b4;
- }
- }
- }
- .visitor-card-item:first-child {
- margin-top: 66rpx;
- }
- .visitor-card-item:last-child {
- margin-top: 22rpx;
- margin-bottom: 30rpx;
- }
- }
- .visitor-card-ttile {
- margin-bottom: 34rpx;
- font-size: 34rpx;
- font-weight: 600;
- line-height: 48rpx;
- color: rgba(0, 0, 0, 1);
- }
- .notNum {
- height: 800rpx;
- display: flex;
- justify-content: center;
- align-items: center;
- .notNum-text {
- margin-top: 20rpx;
- font-family: PingFang SC;
- font-size: 34rpx;
- font-weight: 400;
- line-height: 48rpx;
- color: #c4c4c4;
- }
- }
- .logo-text {
- margin-top:260rpx;
- display: flex;
- justify-content: center;
- width: 100%;
- height: 24rpx;
- padding: 98rpx 0 80rpx;
- }
- </style>
- <template>
- <div class="page-container">
- <div class="visitor-title">
- <div class="visitor-title-left">
- 访客统计
- </div>
- <div
- class="visitor-title-right"
- @click="changeMonth"
- >
- <span>{{yearMonthText}}</span>
- <div>
- <image
- style="height:36rpx;width:36rpx"
- src="{{h5StaticPath}}/page-portrait/statistics-icon-down.svg"
- >
- </image>
- </div>
- </div>
- </div>
- <div v-if="isPageShow">
- <div class="visitor-info">
- <div
- class="visitor-info-item"
- v-for="(item,idx) in infoArr"
- :key="idx"
- >
- <div class="info-title">{{item.title}}</div>
- <div class="info-num">
- <div class="info-num-value">{{item.value}}</div>
- <div class="info-num-unit">{{item.unit}}</div>
- </div>
- </div>
- </div>
- <div class="visitor-num">
- <div class="meeting-time-legend">
- <div class="legend-item">
- <div class="legend-item-shape"></div>
- <div class="legend-item-text">访问人数</div>
- </div>
- <div class="legend-item">
- <div class="legend-item-shape grey"></div>
- <div class="legend-item-text">接待时长</div>
- </div>
- </div>
- <image
- v-if="!imgSrc==''"
- src="{{imgSrc}}"
- ></image>
- <ff-canvas
- v-if="imgSrc==''"
- canvas-id="visitor-num-chart"
- :onInit="numChartData"
- ></ff-canvas>
- </div>
- <div class="visitor-function">
- <div class="visitor-card-ttile">访客使用的功能</div>
- <div
- class="visitor-card-item"
- v-for="(item,idx) in functionArr"
- :key="idx"
- >
- <div class="visitor-card-item-pic">
- <image
- class="img"
- src="{{h5StaticPath +'/page-portrait/' + item.img}}"
- />
- </div>
- <div class="visitor-card-item-name">{{item.title}}</div>
- <div
- class="visitor-card-item-line {{item.actClass}}"
- style="width:{{item.wth}}rpx"
- ></div>
- </div>
- </div>
- <image
- class="logo-text"
- src="{{h5StaticPath}}/page-home/tenatslink.svg"
- ></image>
- </div>
- <div
- class="notNum"
- v-if="!isPageShow"
- >
- <div style="text-align: center;">
- <image
- style="height:200rpx;width:200rpx"
- src="{{h5StaticPath}}/page-portrait/nodata.png"
- />
- <div class="notNum-text">
- 暂无数据
- </div>
- </div>
- </div>
- <van-popup
- custom-style="height: 50%"
- overlay-style="background: rgba(0, 0, 0, 0.4)"
- position="bottom"
- round
- @close="visible = false"
- :show="visible"
- >
- <div>
- <monthcom
- @checkTime="checkTime"
- :yearMonthText="yearMonthText"
- ></monthcom>
- </div>
- </van-popup>
- </div>
- </template>
- <script>
- import wepy from '@wepy/core'
- import store from '@/store'
- import config from '@/config'
- import moment from 'moment'
- import { mapState } from '@wepy/x'
- import { checkLogin, checkHasUserInfo } from '@/service/user'
- import { queryInvitationStatisticsHttp, queeyBuriedEventLogHttp } from '@/packagesEnv/api/portrait'
- let numChart = null
- let resultData = {
- data: [
- ]
- }
- function numChartData(F2, config) {
- let data = resultData.data
- numChart = new F2.Chart({ ...config, appendPadding: [30, 30, 15, 5] })
- numChart.clear()
- numChart.source(data, {
- 'x': {
- type: 'linear',
- tickInterval: 2,
- min: 1,
- max: 31
- }
- })
- numChart.guide().text({
- top: false,
- limitInPlot: true,
- position: ['max', 'min'], // 文本的起始位置,值为原始数据值,支持 callback
- content: '日期', // 显示的文本内容
- style: {
- fill: '#C4C4C4', // 文本颜色
- fontSize: '10' // 文本大小
- }, // 文本的图形样式属性
- offsetX: 20, // x 方向的偏移量
- offsetY: 12 // y 方向偏移量
- })
- numChart.guide().text({
- position: ['min', 'max'], // 文本的起始位置,值为原始数据值,支持 callback
- content: '时长', // 显示的文本内容
- style: {
- fill: '#C4C4C4', // 文本颜色
- fontSize: '10' // 文本大小
- }, // 文本的图形样式属性
- offsetX: -4, // x 方向的偏移量
- offsetY: -20 // y 方向偏移量
- })
- numChart.tooltip(false)
- numChart.point().position('x*y')
- .size('r', [0, 30])
- .shape('circle')
- .style({
- opacity: 0.6
- })
- numChart.render()
- return numChart
- }
- wepy.page({
- store,
- data: {
- h5StaticPath: config.h5StaticPath,
- yearMonth: moment().add(-1, 'months').format('YYYYMM'),
- yearMonthText: moment().add(-1, 'months').format('YYYY.MM'),
- infoArr: [
- { id: '111', title: '累计邀约', value: '--', unit: '人' },
- { id: '222', title: '接待时长', value: '--', unit: '小时' },
- { id: '333', title: '平均', value: '--', unit: '小时/天' }
- ],
- functionArr: [
- { id: 'wifi', title: '连接WiFi', img: 'icon-wifi.svg', value: '--', wth: 0, actClass: '' },
- { id: 'nav', title: '导航', img: 'icon-nav.svg', value: '--', wth: 0, actClass: 'nav' }
- ],
- numChartData,
- visible: false, // 弹窗
- isPageShow: false,
- imgSrc: '' // canvas 图片
- },
- computed: {
- ...mapState({ userInfo: state => state.user.userInfo, token: state => state.user.token })
- },
- onLoad() {
- checkHasUserInfo()
- this.getData()
- },
- onReady() { },
- methods: {
- canvasToImg() { // 将canvas转为图片
- wx.canvasToTempFilePath({
- width: 331,
- height: 140,
- destWidth: 100,
- destHeight: 100,
- canvas: numChartData,
- canvasId: 'visitor-num-chart',
- fileType: 'png',
- success: (res) => {
- this.imgSrc = res.tempFilePath
- },
- fail: res => {
- console.log('转图片失败', res)
- }
- }, this)
- },
- async getData() {
- let res = await this.getInvitationStatistics()
- if (res && res.visitorTotal) { // 有访客,显示界面,再请求
- await this.getBuriedEventLog()
- this.isPageShow = true
- }
- },
- getInvitationStatistics() {
- let endDate = ''
- if (moment().format('YYYYMM') === this.yearMonth) {
- endDate = moment().add(1, 'days').format('YYYYMMDD')
- } else {
- endDate = moment(this.yearMonth).add(1, 'months').startOf('month').format('YYYYMMDD')
- }
- let paramObj = {
- startDate: this.yearMonth + '01',
- endDate: endDate
- }
- return queryInvitationStatisticsHttp(paramObj).then(res => {
- this.isPageShow = false
- if (JSON.stringify(res.data) === '{}') { return };
- let resData = JSON.parse(JSON.stringify(res.data))
- this.infoArr[0].value = resData.visitorTotal
- this.infoArr[1].value = resData.invitationTimeTotal
- this.infoArr[2].value = Number.isInteger(resData.avgTimePerDay) ? resData.avgTimePerDay : resData.avgTimePerDay.toFixed(2)
- let charArr = []
- let resCharArr = resData.detailList
- let startMonthday = this.yearMonth + '01'
- let endMonthday = moment(this.yearMonth).endOf('month').format('YYYYMMDD')
- // 补齐坐标轴
- for (let i = Number(startMonthday); i <= Number(endMonthday); i++) {
- let flag = true
- let jItem = {}
- resCharArr.forEach(j => {
- let JMs = j.date // 时间戳
- if (i == JMs) {
- flag = false
- jItem = j
- }
- })
- if (flag) {
- charArr.push({
- date: i,
- invitationTime: 0,
- visitorNum: 0
- })
- } else {
- charArr.push(jItem)
- }
- }
- let visitorNumArr = [] // 人数
- let invitationTimeArr = [] // 时长
- charArr.forEach(item => {
- let dateItem = String(item.date)
- item.date = moment(dateItem).format('DD')
- visitorNumArr.push({ x: item.date, y: item.invitationTime, r: item.visitorNum, color: '#5E8BCF' })
- invitationTimeArr.push({ x: item.date, y: item.invitationTime, r: item.invitationTime, color: '#D0DBED' })
- })
- resultData.data = invitationTimeArr.concat(visitorNumArr)
- // return new Promise((res, reject) => {
- // this.canvasToImg();
- // })
- return res.data
- })
- },
- getBuriedEventLog() { // 访客使用的功能
- let funArr = ['connect_wifi', 'navigation']
- let $lt = ''
- if (moment().format('YYYYMM') === this.yearMonth) {
- $lt = moment().add(1, 'days').format('YYYYMMDD')
- } else {
- $lt = moment(this.yearMonth).add(1, 'months').startOf('month').format('YYYYMMDD')
- }
- funArr.forEach((item, idx) => {
- let paramObj = {
- status: true,
- name: funArr[idx], // connect_wifi navigation 导航
- createTime: {
- $gte: this.yearMonth + '0100000', // 开始
- $lt: $lt + '00000' // 结束
- }
- }
- return queeyBuriedEventLogHttp(paramObj).then(res => {
- if (res.count) {
- if (res.content[0].name === 'connect_wifi') {
- this.functionArr[0].value = res.count
- } else {
- this.functionArr[1].value = res.count
- }
- let maxValue = Math.max.apply(Math, this.functionArr.map(item => { return item.value }))
- this.functionArr.forEach(item => {
- item.wth = item.value / maxValue * 220 // 220 为最大宽度
- })
- } else {
- this.functionArr.forEach(item => {
- item.value = 0
- item.wth = 0
- })
- }
- })
- })
- },
- checkTime(val) {
- wx.uma.trackEvent('portrait_visitor_card', { key: '访客-月份切换' })
- this.visible = !this.visible
- this.chartFlag = false
- this.yearMonth = val
- this.yearMonthText = moment(this.yearMonth).format('YYYY.MM')
- this.getData()
- },
- changeMonth() {
- this.visible = !this.visible
- }
- }
- })
- </script>
- <config>
- {
- 'navigationBarBackgroundColor': '#eceff4',
- 'navigationBarTextStyle':'black',
- 'navigationBarTitleText': '',
- 'backgroundColor': '#eceff4',
- "usingComponents": {
- "ff-canvas": "../../vendor/antv/wx-f2",
- "van-popup": "module:@vant/weapp/dist/popup",
- "monthcom": "./components/monthcom"
- }
- }
- </config>
|