Commit 7ada23e0 7ada23e0294418296c99ec343894b113ef7c5fdb by 官美宏

爱奇艺小卡销售

1 parent 2e9681bc
......@@ -3,7 +3,7 @@ ENV = 'development'
# 接口地址
# VUE_APP_BASE_API = 'http://10.100.6.140:18006'
# VUE_APP_BASE_API = 'http://139.196.4.234:18006'
VUE_APP_BASE_API = 'http://139.196.192.242:18000'
VUE_APP_BASE_API = 'http://139.196.4.234:8011/'
# VUE_APP_BASE_API = 'http://10.100.6.90:8000'
# VUE_APP_WS_API = 'ws://localhost:8000'
......
import request from '@/utils/request'
function getSmallSellList(params) {
return request({
url: 'api/vipCard',
method: 'get',
params
})
}
export default {
getSmallSellList
}
import request from '@/utils/request'
// 获取开卡数,激活数接口
function getNumInfo(params) {
return request({
url: 'api/statistics/getNumInfo',
method: 'get',
params
})
}
// 查询地区分布
function getRegionStatistics(params) {
return request({
url: 'api/statistics/getRegionStatistics',
method: 'get',
params
})
}
// 查询批次分布
function getBatchStatistics(params) {
return request({
url: 'api/statistics/getBatchStatistics',
method: 'get',
params
})
}
// 查询渠道分布
function getChannelStatistics(params) {
return request({
url: 'api/statistics/getChannelStatistics',
method: 'get',
params
})
}
function getSexStatistics() {
return request({
url: 'api/statistics/sexStatistics',
......@@ -44,6 +76,10 @@ function getActivityStatistics() {
}
export default {
getNumInfo,
getRegionStatistics,
getBatchStatistics,
getChannelStatistics,
getSexStatistics,
getAgeStatistics,
getVodStatistics,
......
<template>
<div class="app-container">
<!--工具栏-->
<div class="head-container">
<div>
<!-- 搜索 -->
<el-select v-model="searchObj.vipType" filterable class="filter-item" clearable size="mini" placeholder="请选择VIP类型">
<el-option
v-for="item in vipTypeList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-select v-model="searchObj.status" filterable class="filter-item" clearable size="mini" placeholder="请选择状态">
<el-option
v-for="item in statusList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-select v-model="searchObj.channel" filterable class="filter-item" clearable size="mini" placeholder="请选择渠道">
<el-option
v-for="item in dictMap.channel"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-select v-model="searchObj.region" filterable class="filter-item" clearable size="mini" placeholder="请选择地区">
<el-option
v-for="item in dictMap.origin"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-input v-model="searchObj.cardNum" clearable size="small" placeholder="请输入卡号" style="width: 200px;" class="filter-item" />
<el-input v-model="searchObj.batch" clearable size="small" placeholder="请输入批次(数字)" style="width: 200px;" class="filter-item" />
<el-input v-model="searchObj.rcvMobile" clearable size="small" placeholder="请输入手机号" style="width: 200px;" class="filter-item" />
<poly-search :query-type-options="queryTypeOptions" @toQuery="searchQuery" />
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="getSmallSellList('reset')">搜索</el-button>
</div>
</div>
<!--表格渲染-->
<el-table
v-loading="loading"
:max-height="tableHeight"
:data="smallSellList"
>
<el-table-column label="ID" width="125px" prop="id" />
<el-table-column label="vip类型" width="125px" prop="vipType">
<template slot-scope="scope">
<span v-if="Number(scope.row.vipType) === 1">爱奇艺包月</span>
<span v-if="Number(scope.row.vipType) === 4">爱奇艺包年</span>
</template>
</el-table-column>
<el-table-column label="卡号" width="125px" prop="cardNum" />
<el-table-column label="卡密" width="125px" prop="cardKey" />
<el-table-column label="vip类型" width="125px" prop="status">
<template slot-scope="scope">
<span v-if="Number(scope.row.status) === 0">未兑换</span>
<span v-if="Number(scope.row.status) === 1">已兑换</span>
<span v-if="Number(scope.row.status) === 2">兑换失败</span>
<span v-if="Number(scope.row.status) === 3">已失效</span>
</template>
</el-table-column>
<el-table-column label="地区" width="125px" prop="region" />
<el-table-column label="渠道" width="125px" prop="channel" />
<el-table-column label="批次" width="125px" prop="batch" />
<el-table-column label="产品id" width="125px" prop="productId" />
<el-table-column label="产品" width="125px" prop="productName" />
<el-table-column label="大屏账号" width="125px" prop="account" />
<el-table-column label="订单号" width="125px" prop="bossOrderNo" />
<el-table-column label="备注" width="125px" prop="remark" />
<el-table-column label="领取手机号" width="125px" prop="rcvMobile" />
</el-table>
<el-pagination
:page-size.sync="searchObj.size"
:total="total"
:current-page.sync="searchObj.page"
style="margin-top: 8px;"
layout="total, prev, pager, next, sizes"
@size-change="changeSize"
@current-change="changePage"
/>
</div>
</template>
<script>
import aiqiyi from '@/api/aiqiyi/aiqiyi'
import polySearch from '@/components/polySearch/index'
import initDict from '@/mixins/initDict'
export default {
name: 'AiqiyiVipCard',
components: { polySearch },
mixins: [initDict],
data() {
return {
loading: false,
smallSellList: [],
queryTypeOptions: [
{ key: 'account', display_name: '大屏账号' },
{ key: 'bossOrderNo', display_name: '订单号' }
],
vipTypeList: [{ label: '爱奇艺包月', value: '1' }, { label: '爱奇艺包年', value: '4' }],
statusList: [{ label: '未兑换', value: '0' }, { label: '已兑换', value: '1' }, { label: '兑换失败', value: '2' }, { label: '已失效', value: '3' }],
total: 0,
tableHeight: '',
searchObj: {
page: 0,
size: 20,
vipType: '',
cardNum: '',
status: '',
region: '',
channel: '',
batch: '',
account: '',
bossOrderNo: '',
rcvMobile: '',
userId: this.$store.state.user.user.id
}
}
},
created() {
this.$nextTick(() => {
this.getDictMap('channel,origin')
this.getSmallSellList()
})
},
mounted() {
this.$nextTick(() => {
this.tableHeight = window.innerHeight - (window.innerWidth < 1530 ? 300 : 280)
})
},
methods: {
searchQuery(e) {
console.log(e)
this.queryTypeOptions.forEach(item => {
this.searchObj[item.key] = ''
})
this.searchObj[e.type] = e.value
},
getSmallSellList(type) {
if (type === 'reset') {
this.searchObj.page = 0
}
this.loading = true
aiqiyi.getSmallSellList(this.searchObj).then(res => {
this.loading = false
this.smallSellList = res.content
this.total = res.totalElements
}).catch(() => {
this.smallSellList = []
this.total = 0
this.loading = false
})
},
changePage(e) {
console.log(e)
this.searchObj.page = e
this.getSmallSellList()
},
changeSize(e) {
console.log(e)
this.searchObj.page = 0
this.searchObj.size = e
this.getSmallSellList()
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
</style>
<template>
<div :class="className" :style="{height:height,width:width}" />
</template>
<script>
import echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import { debounce } from '@/utils'
export default {
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '300px'
},
option: {
type: Object,
default: () => {}
},
optionData: {
type: Object,
default: () => {}
}
},
data() {
return {
chart: null,
colorList: [
'#ff7e50', '#97d3f9', '#dd70d9', '#34cf34',
'#6497ef', '#85802b', '#D7504B', '#C6E579',
'#F4E001', '#F0805A', '#26C0C0'
]
}
},
watch: {
option: {
handler(newVal) {
// console.log('获取配置', newVal)
if (this.chart) {
this.setOption()
}
},
immediate: true,
deep: true
},
optionData: {
handler(newVal) {
console.log('获取柱状数据', newVal, this.chart)
if (this.chart) {
this.initData()
}
},
immediate: true,
deep: true
}
},
mounted() {
this.initChart()
this.__resizeHandler = debounce(() => {
if (this.chart) {
this.chart.resize()
}
}, 100)
window.addEventListener('resize', this.__resizeHandler)
},
beforeDestroy() {
if (!this.chart) {
return
}
window.removeEventListener('resize', this.__resizeHandler)
this.chart.dispose()
this.chart = null
},
methods: {
initChart() {
this.chart = echarts.init(this.$el, 'macarons')
const option = {
title: {
show: false,
right: 'center',
textStyle: {
fontSize: 14
}
},
tooltip: {
trigger: 'axis'
// formatter: function(a, b, c, d) {
// console.log(a, b, c, d)
// }
},
grid: {
top: '10%',
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'value',
// axisLabel: {
// formatter: function(index, value) {
// console.log(index, value)
// }
// },
boundaryGap: [0, 0.01],
splitNumber: 5,
max: 'auto',
data: [],
axisLine: {
show: false
},
axisTick: {
show: false
}
},
yAxis: {
type: 'category',
axisLine: {
show: false
},
axisTick: {
show: false,
alignWithLabel: true
},
splitLine: {
show: false
},
axisPointer: {
type: 'shadow'
}
},
series: [
{
name: '标签人数分布',
type: 'bar',
data: [],
itemStyle: {
color: (params) => {
return this.colorList[params.dataIndex]
}
}
}
]
}
this.chart.setOption(option)
if (Object.keys(this.option).length > 0) {
this.setOption()
}
console.log(this.optionData)
if (Object.keys(this.optionData).length > 0) {
this.initData()
}
},
initData() {
console.log(123)
console.log(this.optionData)
const keyArray = Object.keys(this.optionData)
let yAxis = []
const xAxis = []
if (typeof this.optionData[keyArray[0]] !== 'object') {
keyArray.forEach(item => {
yAxis.push(item)
xAxis.push(this.optionData[item])
})
console.log(yAxis, xAxis)
} else {
if (keyArray.length > 1) {
keyArray.forEach(item => {
const array = Object.keys(this.optionData[item])
array.forEach(itemArray => {
yAxis.push(item + ':' + itemArray)
xAxis.push(this.optionData[item][itemArray])
})
})
} else {
yAxis = Object.keys(this.optionData[keyArray[0]])
yAxis.forEach(item => {
xAxis.push(this.optionData[keyArray[0]][item])
})
}
}
const option = {
yAxis: {
data: yAxis
},
series: [
{
data: xAxis
}
]
}
console.log(option)
this.chart.setOption(option)
},
setOption() {
this.chart.setOption(this.option)
}
}
}
</script>
<template>
<el-row :gutter="40" class="panel-group">
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
<div class="card-panel" @click="handleSetLineChartData('newVisitis')">
<div class="card-panel" @click="handleSetLineChartData('all')">
<div class="card-panel-icon-wrapper icon-people">
<svg-icon icon-class="peoples" class-name="card-panel-icon" />
</div>
<div class="card-panel-description">
<div class="card-panel-text">
New Visits
开卡数
</div>
<count-to :start-val="0" :end-val="102400" :duration="2600" class="card-panel-num" />
<count-to :start-val="0" :end-val="countData.all" :duration="2600" class="card-panel-num" />
</div>
</div>
</el-col>
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
<div class="card-panel" @click="handleSetLineChartData('messages')">
<div class="card-panel" @click="handleSetLineChartData('already')">
<div class="card-panel-icon-wrapper icon-message">
<svg-icon icon-class="message" class-name="card-panel-icon" />
</div>
<div class="card-panel-description">
<div class="card-panel-text">
Messages
激活数
</div>
<count-to :start-val="0" :end-val="81212" :duration="3000" class="card-panel-num" />
<count-to :start-val="0" :end-val="countData.already" :duration="3000" class="card-panel-num" />
</div>
</div>
</el-col>
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
<!-- <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
<div class="card-panel" @click="handleSetLineChartData('purchases')">
<div class="card-panel-icon-wrapper icon-money">
<svg-icon icon-class="money" class-name="card-panel-icon" />
......@@ -51,20 +51,56 @@
<count-to :start-val="0" :end-val="13600" :duration="3600" class="card-panel-num" />
</div>
</div>
</el-col>
</el-col> -->
</el-row>
</template>
<script>
import CountTo from 'vue-count-to'
import homeData from '../../api/home/homeData'
export default {
components: {
CountTo
},
data() {
return {
countData: {
'all': 174,
'already': 37
}
}
},
watch: {
'$store.state.user': {
handler(newVal) {
console.log('用户信息', newVal, newVal.id)
if (newVal.user.id) {
this.getNumInfoData()
}
},
deep: true
}
},
created() {
console.log(homeData.getNumInfo)
if (this.$store.state.user.user && this.$store.state.user.user.id) {
this.getNumInfoData()
}
},
methods: {
getNumInfoData() {
homeData.getNumInfo({
userId: this.$store.state.user.user.id
}).then(res => {
this.countData = res
console.log(res)
}).catch(err => {
console.log(err)
})
},
handleSetLineChartData(type) {
this.$emit('handleSetLineChartData', type)
// this.$emit('handleSetLineChartData', type)
}
}
}
......
......@@ -2,73 +2,123 @@
<div class="dashboard-container">
<div class="dashboard-editor-container">
<github-corner class="github-corner" />
<panel-group @handleSetLineChartData="handleSetLineChartData" />
<el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
<line-chart :chart-data="lineChartData" />
</el-row>
<el-row :gutter="32">
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<radar-chart />
<panel-group />
<div class="active-open-card">
<el-card>
<div slot="header" class="clearfix">
<span>开卡地区</span>
</div>
</el-col>
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<pie-chart />
<el-row>
<el-col :xs="24" :sm="24" :lg="24">
<div class="chart-wrapper">
<bar-chart :option-data="regionStatistics[0]" :option="{title: { show: true, text: '开卡地区:地区分布' }}" />
</div>
</el-col>
<el-col :xs="24" :sm="24" :lg="24">
<div class="chart-wrapper">
<bar-chart :option-data="batchStatistics[0]" :option="{title: { show: true, text: '开卡地区:批次分布' }}" />
</div>
</el-col>
<el-col :xs="24" :sm="24" :lg="24">
<div class="chart-wrapper">
<bar-chart :option-data="channelStatistics[0]" :option="{title: { show: true, text: '开卡地区:渠道分布' }}" />
</div>
</el-col>
</el-row>
</el-card>
<el-card>
<div slot="header" class="clearfix">
<span>激活地区</span>
</div>
</el-col>
<el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper">
<bar-chart />
</div>
</el-col>
</el-row>
<el-row>
<el-col :xs="24" :sm="24" :lg="24">
<div class="chart-wrapper">
<bar-chart :option-data="regionStatistics[1]" :option="{title: { show: true, text: '激活地区:地区分布' }}" />
</div>
</el-col>
<el-col :xs="24" :sm="24" :lg="24">
<div class="chart-wrapper">
<bar-chart :option-data="batchStatistics[1]" :option="{title: { show: true, text: '激活地区:批次分布' }}" />
</div>
</el-col>
<el-col :xs="24" :sm="24" :lg="24">
<div class="chart-wrapper">
<bar-chart :option-data="channelStatistics[1]" :option="{title: { show: true, text: '激活地区:渠道分布' }}" />
</div>
</el-col>
</el-row>
</el-card>
</div>
</div>
</div>
</template>
<script>
import GithubCorner from '@/components/GithubCorner'
import PanelGroup from './dashboard/PanelGroup'
import LineChart from './dashboard/LineChart'
import RadarChart from '@/components/Echarts/RadarChart'
import PieChart from '@/components/Echarts/PieChart'
import BarChart from '@/components/Echarts/BarChart'
const lineChartData = {
newVisitis: {
expectedData: [100, 120, 161, 134, 105, 160, 165],
actualData: [120, 82, 91, 154, 162, 140, 145]
},
messages: {
expectedData: [200, 192, 120, 144, 160, 130, 140],
actualData: [180, 160, 151, 106, 145, 150, 130]
},
purchases: {
expectedData: [80, 100, 121, 104, 105, 90, 100],
actualData: [120, 90, 100, 138, 142, 130, 130]
},
shoppings: {
expectedData: [130, 140, 141, 142, 145, 150, 160],
actualData: [120, 82, 91, 154, 162, 140, 130]
}
}
import BarChart from './dashboard/BarChart'
import homeData from '@/api/home/homeData'
export default {
name: 'Dashboard',
components: {
GithubCorner,
PanelGroup,
LineChart,
RadarChart,
PieChart,
BarChart
},
data() {
return {
lineChartData: lineChartData.newVisitis
regionStatistics: [{}, {}],
batchStatistics: [{}, {}],
channelStatistics: [{}, {}]
}
},
mounted() {
this.getRegionStatistics(0)
this.getBatchStatistics(0)
this.getChannelStatistics(0)
this.getRegionStatistics(1)
this.getBatchStatistics(1)
this.getChannelStatistics(1)
},
methods: {
handleSetLineChartData(type) {
this.lineChartData = lineChartData[type]
getRegionStatistics(status) {
homeData.getRegionStatistics({
userId: this.$store.state.user.user.id,
status: status
}).then(res => {
console.log(res)
this.$set(this.regionStatistics, status, res)
}).catch(err => {
this.$message.error(err.message)
this.$set(this.regionStatistics, status, [])
console.log(err)
})
},
getBatchStatistics(status) {
homeData.getBatchStatistics({
userId: this.$store.state.user.user.id,
status: status
}).then(res => {
console.log(res)
this.$set(this.batchStatistics, status, res)
}).catch(err => {
this.$message.error(err.message)
this.$set(this.batchStatistics, status, [])
console.log(err)
})
},
getChannelStatistics(status) {
homeData.getChannelStatistics({
userId: this.$store.state.user.user.id,
status: status
}).then(res => {
console.log(res)
this.$set(this.channelStatistics, status, res)
}).catch(err => {
this.$message.error(err.message)
this.$set(this.channelStatistics, status, [])
console.log(err)
})
}
}
}
......@@ -86,8 +136,13 @@ export default {
}
.chart-wrapper {
background: #fff;
padding: 16px 16px 0;
margin-bottom: 32px;
padding: 16px;
border-top: 1px solid #ccc;
}
.el-col:nth-of-type(1) {
.chart-wrapper {
border-top: 0;
}
}
}
@media (max-width:1024px) {
......@@ -95,4 +150,13 @@ export default {
padding: 8px;
}
}
.active-open-card {
display: flex;
justify-content: space-between;
}
.el-card {
width: 48%;
flex-shrink: 0;
flex-grow: 0;
}
</style>
......