123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424 |
- <template>
- <el-container class="portrait">
- <el-header style="height: auto; padding-top: 1em">
- <el-card>
- <el-form ref="form" size="small" :inline="true" label-width="120px">
- <el-form-item label="选择应用">
- <el-select v-model="appSelect" placeholder="请选择">
- <el-option
- v-for="item in appList"
- :key="item.appid"
- :label="item.name"
- :value="item.appid"
- />
- </el-select>
- </el-form-item>
- <el-form-item style="float: right">
- <el-button type="primary" @click="getData"> 查询 </el-button>
- </el-form-item>
- </el-form>
- </el-card>
- </el-header>
- <el-main>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-card>
- <template #header>
- <span>用户性别分布</span>
- </template>
- <div ref="sex"></div>
- </el-card>
- </el-col>
- <el-col :span="12">
- <el-card>
- <template #header>
- <span>用户年龄分布</span>
- </template>
- <div ref="age"></div>
- </el-card>
- </el-col>
- </el-row>
- <br />
- <el-card>
- <template #header>
- <span>用户标签分布</span>
- </template>
- <div ref="tag"></div>
- </el-card>
- <br />
- <el-card>
- <template #header>
- <span>陕西省内用户分布</span>
- </template>
- <el-row :gutter="20">
- <el-col :span="12">
- <div ref="city"></div>
- </el-col>
- <el-col :span="12">
- <el-table :data="tableProData" style="width: 100%">
- <el-table-column prop="category" label="地名" />
- <el-table-column center prop="ct" label="访问人数" />
- </el-table>
- </el-col>
- </el-row>
- </el-card>
- <br />
- <el-row :gutter="20">
- <el-col :span="12">
- <el-card>
- <template #header>
- <span>用户机型分布</span>
- </template>
- <div ref="phone"></div>
- </el-card>
- </el-col>
- <el-col :span="12">
- <el-card>
- <template #header>
- <span>APP栏目用户分布</span>
- </template>
- <div ref="category"></div>
- </el-card>
- </el-col>
- </el-row>
- <br />
- <el-row :gutter="20">
- <el-col :span="12">
- <el-card>
- <template #header>
- <span>起点号用户访问排行</span>
- </template>
- <div ref="publisher"></div>
- </el-card>
- </el-col>
- <el-col :span="12">
- <el-card>
- <template #header>
- <span>重点节目用户访问排行</span>
- </template>
- <div ref="program"></div>
- </el-card>
- </el-col>
- </el-row>
- </el-main>
- </el-container>
- </template>
- <script setup>
- import {
- getAppList,
- getSexData,
- getAgeData,
- getCityData,
- getTagData,
- getPhoneData,
- getCategoryData,
- getPublisherData,
- getProgramData
- } from '@/api/portrait.js';
- import { ref, onMounted } from 'vue';
- import { createChart, numform, chart } from './tool';
- import config from './config';
- const appList = ref([]);
- const tableProData = ref([]);
- const appSelect = ref('');
- const sex = ref(null);
- const age = ref(null);
- const tag = ref(null);
- const city = ref(null);
- const phone = ref(null);
- const category = ref(null);
- const publisher = ref(null);
- const program = ref(null);
- let sexChart = undefined;
- let ageChart = undefined;
- let tagChart = undefined;
- let cityChart = undefined;
- let phoneChart = undefined;
- let categoryChart = undefined;
- let publisherChart = undefined;
- let programChart = undefined;
- const createSex = (list = []) => {
- if (!sex.value || !list || list.length == 0) return;
- const p = {
- ...config.pieOption
- };
- p.series[0].data = list.map(v => {
- return {
- name: v.category,
- value: v.ct,
- selected: true
- };
- });
- sexChart = createChart(sex.value, sex.value.offsetWidth / 2, p, sexChart);
- };
- const createAge = (list = []) => {
- if (!age.value || !list || list.length == 0) return;
- const p = {
- ...config.pieOption
- };
- p.series[0].radius = ['40%', '70%'];
- p.series[0].itemStyle = {
- borderRadius: 5,
- borderColor: '#fff',
- borderWidth: 1
- };
- p.series[0].data = list.map(v => {
- return {
- name: v.category,
- value: v.ct,
- selected: true
- };
- });
- ageChart = createChart(age.value, age.value.offsetWidth / 2, p, ageChart);
- };
- const createTag = (list = []) => {
- if (!tag.value || !list || list.length == 0) return;
- let category = list.map(v => {
- return {
- name: v.category,
- value: v.ct
- };
- });
- let yName = []; // y轴名称
- let bgData = []; // 最大值用作背景显示的数据
- let maxValue = category[0].value; //最大值
- category = category.reverse();
- category.forEach(element => {
- yName.push(element.name);
- bgData.push({
- name: element.name,
- value: maxValue
- });
- });
- const p = {
- ...config.tagOption
- };
- p.xAxis.max = maxValue;
- p.yAxis[0].data = yName;
- p.yAxis[1].data = Array.from(
- { length: yName.length },
- (_, i) => i + 1
- ).reverse();
- p.yAxis[2].data = category;
- p.series[0].data = bgData;
- p.series[1].data = category;
- p.series[2].data = bgData;
- p.series[2].symbolBoundingData = maxValue;
- tagChart = createChart(tag.value, tag.value.offsetWidth / 2, p, tagChart);
- };
- const createCity = (list = []) => {
- if (!city.value || !list || list.length == 0) return;
- tableProData.value = list;
- let max = -Infinity,
- min = Infinity,
- values = [];
- for (let i = 0; i < list.length; i++) {
- const v = list[i];
- if (v.ct > max) max = v.ct;
- if (v.ct < min) min = v.ct;
- values.push({
- name: v.category,
- value: v.ct
- // distribution: ((v.ct / t) * 100).toFixed(2) - 0 + '%'
- });
- }
- const p = {
- ...config.cityOption
- };
- p.visualMap.min = min;
- p.visualMap.max = max;
- p.tooltip.formatter = data => {
- if (isNaN(data.value)) return '';
- return `${data.name}<br/>${numform(data.value)}`;
- };
- p.visualMap.text = [max, min];
- p.series[0].data = values;
- cityChart = createChart(city.value, city.value.offsetWidth, p, cityChart);
- };
- const createPhone = (list = []) => {
- if (!phone.value || !list || list.length == 0) return;
- list = list.reverse();
- const p = {
- ...config.phoneOption
- };
- p.series[0].data = list.map(v => {
- return {
- value: v.ct,
- name: v.category
- };
- });
- phoneChart = createChart(
- phone.value,
- phone.value.offsetWidth / 2,
- p,
- phoneChart
- );
- };
- const createCategory = (list = []) => {
- if (!category.value || !list || list.length == 0) return;
- list = list.reverse();
- const p = {
- ...config.pieOption
- };
- p.series[0].radius = ['40%', '70%'];
- p.series[0].itemStyle = {
- borderRadius: 5,
- borderColor: '#fff',
- borderWidth: 1
- };
- p.series[0].data = list.map(v => {
- return {
- name: v.category,
- value: v.ct,
- selected: true
- };
- });
- categoryChart = createChart(
- category.value,
- category.value.offsetWidth / 2,
- p,
- categoryChart
- );
- };
- const createPublisher = (list = []) => {
- if (!publisher.value || !list || list.length == 0) return;
- const keys = [],
- values = [];
- let max = -Infinity;
- for (let i = 0; i < list.length; i++) {
- const v = list[i];
- keys.push(v.category);
- values.push(v.ct);
- if (max < v.ct) max = v.ct;
- }
- const p = {
- ...config.publisherOption
- };
- p.xAxis[0].data = keys;
- p.series[0].data = values;
- p.series[0].itemStyle = {
- normal: {
- borderRadius: [5, 5, 0, 0],
- color: new chart.graphic.LinearGradient(0, 0, 1, 0, [
- {
- offset: 0,
- color: '#8ba6d6'
- },
- {
- offset: 1,
- color: '#a085ee'
- }
- ])
- }
- };
- publisherChart = createChart(
- publisher.value,
- publisher.value.offsetWidth,
- p,
- publisherChart
- );
- };
- const createProgram = (list = []) => {
- if (!program.value || !list || list.length == 0) return;
- const keys = [],
- values = [];
- let max = -Infinity;
- list = list.reverse();
- for (let i = 0; i < list.length; i++) {
- const v = list[i];
- keys.push(v.category);
- values.push(v.ct);
- if (max < v.ct) max = v.ct;
- }
- const p = {
- ...JSON.parse(JSON.stringify(config.publisherOption))
- };
- p.xAxis[0].data = keys;
- p.series[0].data = values;
- const xAxis = JSON.parse(JSON.stringify(p.xAxis));
- const yAxis = JSON.parse(JSON.stringify(p.yAxis));
- p.yAxis = xAxis;
- p.xAxis = yAxis;
- p.grid = {
- top: '5%',
- left: 5,
- right: 5,
- bottom: '6%',
- containLabel: true
- };
- p.series[0].label.offset = [50, 0];
- p.series[0].label.position = 'right';
- p.series[0].label.align = 'right';
- p.series[0].itemStyle = {
- normal: {
- borderRadius: [0, 5, 5, 0],
- color: new chart.graphic.LinearGradient(0, 0, 1, 0, [
- {
- offset: 0,
- color: '#8ba6d6'
- },
- {
- offset: 1,
- color: '#a085ee'
- }
- ])
- }
- };
- p.series[0].label.formatter = data => {
- if (isNaN(data.value)) return '';
- return numform(data.value);
- };
- programChart = createChart(
- program.value,
- publisher.value.offsetWidth,
- p,
- programChart
- );
- };
- const getData = () => {
- Promise.all([
- getSexData({ appid: appSelect.value }),
- getAgeData({ appid: appSelect.value }),
- getCityData({ appid: appSelect.value }),
- getTagData({ appid: appSelect.value }),
- getPhoneData({ appid: appSelect.value }),
- getCategoryData({ appid: appSelect.value }),
- getPublisherData({ appid: appSelect.value }),
- getProgramData({ appid: appSelect.value })
- ]).then(list => {
- createSex(list[0]);
- createAge(list[1]);
- createCity(list[2]);
- createTag(list[3]);
- createPhone(list[4]);
- createCategory(list[5]);
- createPublisher(list[6]);
- createProgram(list[7]);
- });
- };
- onMounted(() => {
- getAppList().then(res => {
- appSelect.value = (res || [])[0].appid;
- appList.value = res || [];
- getData();
- });
- });
- </script>
|