|
@@ -0,0 +1,575 @@
|
|
|
+<template>
|
|
|
+ <div class="layout-padding">
|
|
|
+ <div class="!overflow-auto px-1">
|
|
|
+ <Lcard>
|
|
|
+ <div class="flex justify-start items-center">
|
|
|
+ <el-icon class="ml-1" style="color: #333333; margin-right: 25px">
|
|
|
+ <ArrowLeftBold />
|
|
|
+ </el-icon>
|
|
|
+ <el-select v-model="selectChannel" style="width: 100px;">
|
|
|
+ <el-option label="全部渠道" value="1"></el-option>
|
|
|
+ <el-option label="安卓" value="2"></el-option>
|
|
|
+ <el-option label="苹果" value="3"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ </Lcard>
|
|
|
+ <Lcard>
|
|
|
+ <div class="flex justify-between items-center">
|
|
|
+ <Title left-line title="渠道趋势">
|
|
|
+ </Title>
|
|
|
+ <div class="box1">
|
|
|
+ <el-select v-model="selectVersion" style="width: 140px; margin-right: 30px;">
|
|
|
+ <el-option label="全部版本" value="1"></el-option>
|
|
|
+ <el-option label="1.0.1" value="2"></el-option>
|
|
|
+ <el-option label="1.02" value="3"></el-option>
|
|
|
+ </el-select>
|
|
|
+ <div class="box1-time">
|
|
|
+ <el-date-picker style="float: left; width: 240px; margin-right: 30px;" v-model="timeRange"
|
|
|
+ type="datetimerange" range-separator="To" start-placeholder="Start date" end-placeholder="End date" />
|
|
|
+ <el-radio-group v-model="timeGroup" style="width: 240px; margin-right: 30px;">
|
|
|
+ <el-radio-button label="week">过去七天</el-radio-button>
|
|
|
+ <el-radio-button label="month">过去三十天</el-radio-button>
|
|
|
+ </el-radio-group>
|
|
|
+ </div>
|
|
|
+ <div class="link">导出数据
|
|
|
+ <span style="display: inline-block; transform:translateY(3px);">
|
|
|
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
|
+ <g clip-path="url(#clip0_713_1665)">
|
|
|
+ <path
|
|
|
+ d="M14 1.33301H1.99992C1.63172 1.33301 1.33324 1.63149 1.33325 1.99969L1.33358 13.9997C1.33359 14.3679 1.63207 14.6663 2.00025 14.6663H14C14.3682 14.6663 14.6667 14.3679 14.6667 13.9997V1.99967C14.6667 1.63148 14.3682 1.33301 14 1.33301Z"
|
|
|
+ stroke="#167AF0" />
|
|
|
+ <path d="M6.66968 11.3366H11.1669V6.66992" stroke="#167AF0" stroke-linecap="round"
|
|
|
+ stroke-linejoin="round" />
|
|
|
+ <path d="M9.66675 8.16699L10.1667 7.66699L11.1667 6.66699L12.1667 7.66699L12.6667 8.16699"
|
|
|
+ stroke="#167AF0" stroke-linecap="round" stroke-linejoin="round" />
|
|
|
+ <path d="M4.66675 1.33301V14.6663" stroke="#167AF0" stroke-linecap="round" />
|
|
|
+ <path d="M1.33325 4.67959L14.6666 4.66699" stroke="#167AF0" stroke-linecap="round" />
|
|
|
+ <path d="M2.66675 1.33301H9.33341" stroke="#167AF0" stroke-linecap="round"
|
|
|
+ stroke-linejoin="round" />
|
|
|
+ <path d="M2.66675 14.667H9.33341" stroke="#167AF0" stroke-linecap="round" stroke-linejoin="round" />
|
|
|
+ <path d="M14.6667 2.66699V6.00033" stroke="#167AF0" stroke-linecap="round" />
|
|
|
+ <path d="M1.33325 2.66699V6.00033" stroke="#167AF0" stroke-linecap="round" />
|
|
|
+ </g>
|
|
|
+ <defs>
|
|
|
+ <clipPath id="clip0_713_1665">
|
|
|
+ <rect width="16" height="16" fill="white" />
|
|
|
+ </clipPath>
|
|
|
+ </defs>
|
|
|
+ </svg>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="line" style="margin: 35px -30px 40px;"></div>
|
|
|
+ <div class="flex items-center justify-between mb-2 mt-3" style="margin-top: 20px;margin-left: 60px;">
|
|
|
+ <div class="flex items-center">
|
|
|
+ <el-radio-group v-model="lineChartUser">
|
|
|
+ <el-radio-button label="1">新增用户</el-radio-button>
|
|
|
+ <el-radio-button label="2">活跃用户</el-radio-button>
|
|
|
+ <el-radio-button label="3">启动次数</el-radio-button>
|
|
|
+ <el-radio-button label="4">平均单次使用时长</el-radio-button>
|
|
|
+ <el-radio-button label="5">新增次日留存率</el-radio-button>
|
|
|
+ </el-radio-group>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-select placeholder="对比分析" v-model="selectLineChannel" multiple clearable
|
|
|
+ style="width: 140px;margin: 20px 60px;">
|
|
|
+ <el-option label="时段对比" value="1"></el-option>
|
|
|
+ <el-option label="渠道对比" value="2"></el-option>
|
|
|
+ <el-option label="版本对比" value="3"></el-option>
|
|
|
+ </el-select>
|
|
|
+ <div class="relative">
|
|
|
+ <div ref="qChartRef" style="margin-left: 60px; width: calc(100% - 80px); height: 320px"></div>
|
|
|
+ </div>
|
|
|
+ <div class="mt-3" style="margin-top: 20px;margin-left: 60px;">
|
|
|
+ <div class="flex items-center justify-between mb-2">
|
|
|
+ <div class="text-base font-medium cursor-pointer select-none" @click="showDetail1 = !showDetail1">
|
|
|
+ {{ showDetail1 ? '收起明细数据' : '展开明细数据' }}
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <el-button>导出</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-table v-if="showDetail1" :data="pagedTableRows" border>
|
|
|
+ <el-table-column prop="date" label="日期" min-width="140" />
|
|
|
+ <el-table-column label="新增用户(占比)" min-width="220">
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="flex items-center justify-between w-full">
|
|
|
+ <span>{{ scope.row.newUsers }}</span>
|
|
|
+ <span class="text-gray-500 text-xs">{{ scope.row.ratio }}</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <div v-if="showDetail1" class="flex justify-end mt-3">
|
|
|
+ <el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" background
|
|
|
+ layout="total, prev, pager, next, sizes" :total="tableRows.length" :page-sizes="[5, 10, 20]" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </Lcard>
|
|
|
+ <div class="flex justify-between">
|
|
|
+ <Lcard style="width: calc(50% - 5px);">
|
|
|
+ <div class="flex justify-between items-center">
|
|
|
+ <Title left-line title="渠道趋势">
|
|
|
+ <el-popover class="box-item" placement="right" trigger="hover" width="250">
|
|
|
+ <template #reference>
|
|
|
+ <el-icon class="ml-1" style="color: #a4b8cf">
|
|
|
+ <InfoFilled />
|
|
|
+ </el-icon>
|
|
|
+ </template>
|
|
|
+ <template #default>
|
|
|
+ <div class="ant-popover-inner-content">
|
|
|
+ 渠道活跃度,展示指定渠道用户的昨日活跃/过去7天活跃、昨日活跃/过去30天活跃的信息。<br>
|
|
|
+ 通过这两个指标,您可以了解到该渠道用户的粘着度。昨日活跃/过去30天活跃越接入100%,<br>
|
|
|
+ 用户越活跃,流失率越低,粘性越强这里的活跃用户是去重后的活跃用户
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-popover>
|
|
|
+ </Title>
|
|
|
+ <div style="font-size: 15px; color: #646464;">
|
|
|
+ 2025/08/19
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="flex justify-between items-center">
|
|
|
+ <div ref="qdqsRef1" style="width: 48%; height: 220px;"></div>
|
|
|
+ <div ref="qdqsRef2" style="width: 48%; height: 220px;"></div>
|
|
|
+ </div>
|
|
|
+ </Lcard>
|
|
|
+ <Lcard style="width: calc(50% - 5px);">
|
|
|
+ <div class="flex justify-between items-center">
|
|
|
+ <Title left-line title="新增用户留存率">
|
|
|
+ <el-popover class="box-item" placement="right" trigger="hover" width="250">
|
|
|
+ <template #reference>
|
|
|
+ <el-icon class="ml-1" style="color: #a4b8cf">
|
|
|
+ <InfoFilled />
|
|
|
+ </el-icon>
|
|
|
+ </template>
|
|
|
+ <template #default>
|
|
|
+ <div class="ant-popover-inner-content">
|
|
|
+ 展示了渠道近期的留存率情况,可以帮助您了解该渠道用户的忠诚度<br>
|
|
|
+ 次日留存率: 某日的新增用户在次日启动过应用的比例<br>
|
|
|
+ 7日留存率: 某日的新增用户在7天后启动过应用的比例<br>
|
|
|
+ 14日留存率: 某日的新增用户在14天后启动过应用的比例<br>
|
|
|
+ 这里展示的是渠道前天在昨天的次日留存率、8天前在昨天的7日留存率和15天前在昨天的14日留存率
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-popover>
|
|
|
+ </Title>
|
|
|
+ <div style="font-size: 15px; color: #646464;">
|
|
|
+ 2025/08/19
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <Lprogress style="margin-top: 45px;" v-for="i in progressArray" :key="i.label" :label="i.label" :num="i.num" :count="i.count"></Lprogress>
|
|
|
+ </Lcard>
|
|
|
+ </div>
|
|
|
+ <Lcard :height="650">
|
|
|
+ <Title left-line title="渠道矩阵分析">
|
|
|
+ <el-popover class="box-item" placement="right" trigger="hover" width="250">
|
|
|
+ <template #reference>
|
|
|
+ <el-icon class="ml-1" style="color: #a4b8cf">
|
|
|
+ <InfoFilled />
|
|
|
+ </el-icon>
|
|
|
+ </template>
|
|
|
+ <template #default>
|
|
|
+ <div class="ant-popover-inner-content">
|
|
|
+ <div class="um-page-tips-content" style="line-height: 24px">
|
|
|
+ 可通过矩阵分析了解各个渠道的价值,在您推广平台选择时也可选择高转化高偏好的渠道作为重点渠道
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-popover>
|
|
|
+ </Title>
|
|
|
+ <div style="margin: 30px 60px">
|
|
|
+ <span>横轴:新增用户(日均)</span>
|
|
|
+ 纵轴:<el-select v-model="selectSanDian" style="width: 200px;display: inline-block;">
|
|
|
+ <el-option label="次日留存率(日均)" value="1"></el-option>
|
|
|
+ <el-option label="后日留存率(日均)" value="2"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div ref="SDChartRef" style="width: 100%; height: 480px"></div>
|
|
|
+ </Lcard>
|
|
|
+ <Lcard>
|
|
|
+ <Title left-line title="渠道明细数据">
|
|
|
+ </Title>
|
|
|
+ <div class="box1" style="margin: 30px 60px">
|
|
|
+ <div class="flex items-center justify-between">
|
|
|
+ <el-radio-group v-model="radioTableDay">
|
|
|
+ <el-radio-button label="today">今日</el-radio-button>
|
|
|
+ <el-radio-button label="yesterday">昨日</el-radio-button>
|
|
|
+ </el-radio-group>
|
|
|
+ <el-select class="ml-2" v-model="tableChannel" style="width: 140px" placeholder="渠道选择">
|
|
|
+ <el-option label="全部" value="1"></el-option>
|
|
|
+ <el-option label="未分组" value="2"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="link">导出</div>
|
|
|
+ </div>
|
|
|
+ <el-table :data="pagedTableRows" border>
|
|
|
+ <el-table-column prop="date" label="日期" min-width="140" />
|
|
|
+ <el-table-column label="新增用户(占比)" min-width="220">
|
|
|
+ <template #default="scope">
|
|
|
+ <div class="flex items-center justify-between w-full">
|
|
|
+ <span>{{ scope.row.newUsers }}</span>
|
|
|
+ <span class="text-gray-500 text-xs">{{ scope.row.ratio }}</span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <div v-if="showDetail1" class="flex justify-end mt-3">
|
|
|
+ <el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" background
|
|
|
+ layout="total, prev, pager, next, sizes" :total="tableRows.length" :page-sizes="[5, 10, 20]" />
|
|
|
+ </div>
|
|
|
+ </Lcard>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts" setup>
|
|
|
+// import { ref, onMounted, watch, computed, defineAsyncComponent } from 'vue';
|
|
|
+import { useI18n } from 'vue-i18n';
|
|
|
+import * as echarts from 'echarts';
|
|
|
+// 引入组件
|
|
|
+const Lcard = defineAsyncComponent(() => import('/@/components/LYcom/Lcard/index.vue'));
|
|
|
+const Title = defineAsyncComponent(() => import('/@/components/Title/index.vue'));
|
|
|
+const Lprogress = defineAsyncComponent(() => import('/@/components/LYcom/Lprogress/index.vue'));
|
|
|
+const { t } = useI18n();
|
|
|
+
|
|
|
+const selectChannel = ref('1') // 渠道选择
|
|
|
+const timeGroup = ref('1')
|
|
|
+const timeRange: any = ref(null);
|
|
|
+watch(timeGroup, (newVal) => {
|
|
|
+ const now = new Date();
|
|
|
+ let start: Date;
|
|
|
+ let end: Date = new Date(now);
|
|
|
+
|
|
|
+ switch (newVal) {
|
|
|
+ case 'day':
|
|
|
+ // 设置为今天 00:00:00 到 23:59:59
|
|
|
+ start = new Date(now);
|
|
|
+ start.setHours(0, 0, 0, 0);
|
|
|
+ end.setHours(23, 59, 59, 999);
|
|
|
+ break;
|
|
|
+ case 'week':
|
|
|
+ // 设置为本周第一天(周日)到本周最后一天(周六)
|
|
|
+ start = new Date(now);
|
|
|
+ const day = start.getDay();
|
|
|
+ const diff = start.getDate() - day;
|
|
|
+ start.setDate(diff);
|
|
|
+ start.setHours(0, 0, 0, 0);
|
|
|
+ end = new Date(start);
|
|
|
+ end.setDate(start.getDate() + 6);
|
|
|
+ end.setHours(23, 59, 59, 999);
|
|
|
+ break;
|
|
|
+ case 'month':
|
|
|
+ // 设置为本月第一天到本月最后一天
|
|
|
+ start = new Date(now.getFullYear(), now.getMonth(), 1);
|
|
|
+ start.setHours(0, 0, 0, 0);
|
|
|
+ end = new Date(now.getFullYear(), now.getMonth() + 1, 0);
|
|
|
+ end.setHours(23, 59, 59, 999);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ // 其他情况清空时间范围
|
|
|
+ timeRange.value = null;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ timeRange.value = [start, end];
|
|
|
+}, { immediate: true });
|
|
|
+
|
|
|
+const selectVersion = ref('1') // 选择版本
|
|
|
+
|
|
|
+const selectLineChannel = ref([]) // 选择线形图渠道
|
|
|
+
|
|
|
+const selectSanDian = ref('1') // 选择散点图纵坐标
|
|
|
+
|
|
|
+const radioTableDay = ref('1') // 选择表格时间
|
|
|
+const tableChannel = ref('1') // 选择表格渠道
|
|
|
+
|
|
|
+let qualityChart: echarts.ECharts | null = null;
|
|
|
+const qChartRef = ref(null);
|
|
|
+const lineChartUser = ref(null);
|
|
|
+onMounted(() => {
|
|
|
+ setTimeout(() => {
|
|
|
+ initQualityChart();
|
|
|
+ initChart1();
|
|
|
+ initChart2();
|
|
|
+ }, 500)
|
|
|
+});
|
|
|
+const qualityXAxis = ref<string[]>([
|
|
|
+ '2025-07-01',
|
|
|
+ '2025-07-08',
|
|
|
+ '2025-07-15',
|
|
|
+ '2025-07-22',
|
|
|
+ '2025-07-29',
|
|
|
+ '2025-08-05',
|
|
|
+ '2025-08-12',
|
|
|
+ '2025-08-19',
|
|
|
+ '2025-08-26',
|
|
|
+ '2025-09-02',
|
|
|
+ '2025-09-09',
|
|
|
+ '2025-09-16',
|
|
|
+]);
|
|
|
+const retentionSeries = ref<number[]>([20, 23, 27, 24, 22, 15, 5, 4, 16, 26, 25, 2]);
|
|
|
+const industryAvgSeries = ref<number[]>([16, 18, 20, 24, 25, 24, 16, 10, 15, 22, 21, 12]);
|
|
|
+const peerSameScaleSeries = ref<number[]>([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
|
|
|
+function initQualityChart(): void {
|
|
|
+ console.log(qChartRef.value, qChartRef);
|
|
|
+ if (!qChartRef.value) return;
|
|
|
+ if (qualityChart) qualityChart.dispose();
|
|
|
+ qualityChart = echarts.init(qChartRef.value);
|
|
|
+ const option: echarts.EChartsOption = {
|
|
|
+ tooltip: { trigger: 'axis', valueFormatter: (v) => `${v}%` },
|
|
|
+ legend: { data: ['留存率', '同行业App', '同行业同规模App'] },
|
|
|
+ grid: { left: 40, right: 20, top: 30, bottom: 30 },
|
|
|
+ xAxis: { type: 'category', data: qualityXAxis.value },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ min: 0,
|
|
|
+ max: 30,
|
|
|
+ axisLabel: { formatter: '{value}%' },
|
|
|
+ splitLine: { lineStyle: { color: '#f3f4f6' } },
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ { name: '留存率', type: 'line', smooth: true, data: retentionSeries.value },
|
|
|
+ { name: '同行业App', type: 'line', smooth: true, data: industryAvgSeries.value, color: '#f59e0b' },
|
|
|
+ { name: '同行业同规模App', type: 'line', smooth: true, data: peerSameScaleSeries.value, color: '#60a5fa' },
|
|
|
+ ],
|
|
|
+ };
|
|
|
+ qualityChart.setOption(option);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+interface TableRow {
|
|
|
+ date: string;
|
|
|
+ newUsers: number;
|
|
|
+ ratio: string;
|
|
|
+}
|
|
|
+// 展开/收起明细
|
|
|
+const showDetail1 = ref(true);
|
|
|
+const pagedTableRows = computed(() => {
|
|
|
+ const startIndex = (currentPage.value - 1) * pageSize.value;
|
|
|
+ return tableRows.value.slice(startIndex, startIndex + pageSize.value);
|
|
|
+});
|
|
|
+// 表格相关(静态数据)
|
|
|
+const currentPage = ref(1);
|
|
|
+const pageSize = ref(5);
|
|
|
+const tableRows = ref<TableRow[]>(
|
|
|
+ Array.from({ length: 42 }).map((_, idx) => ({
|
|
|
+ date: `2025-08-${String(11).padStart(2, '0')}`,
|
|
|
+ newUsers: 727,
|
|
|
+ ratio: '97.45%',
|
|
|
+ }))
|
|
|
+);
|
|
|
+
|
|
|
+
|
|
|
+// 饼图进度条相关代码
|
|
|
+const qdqsRef1 = ref(null);
|
|
|
+const qdqsCount1 = ref(85);
|
|
|
+const qdqsRef2 = ref(null);
|
|
|
+const qdqsCount2 = ref(65);
|
|
|
+let chart1: echarts.ECharts | null = null;
|
|
|
+let chart2: echarts.ECharts | null = null;
|
|
|
+
|
|
|
+// 初始化第一个饼图进度条
|
|
|
+function initChart1(): void {
|
|
|
+ if (!qdqsRef1.value) return;
|
|
|
+ if (chart1) chart1.dispose();
|
|
|
+
|
|
|
+ chart1 = echarts.init(qdqsRef1.value);
|
|
|
+
|
|
|
+ const option: echarts.EChartsOption = {
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ type: 'pie',
|
|
|
+ radius: ['60%', '70%'],
|
|
|
+ center: ['50%', '50%'],
|
|
|
+ avoidLabelOverlap: false,
|
|
|
+ startAngle: 270,
|
|
|
+ endAngle: 270 - (qdqsCount1.value / 100 * 360),
|
|
|
+ silent: true,
|
|
|
+ itemStyle: {
|
|
|
+ color: '#167AF0',
|
|
|
+ borderRadius: 10
|
|
|
+ },
|
|
|
+ data: [100],
|
|
|
+ label: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
+ disabled: true
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'pie',
|
|
|
+ radius: ['60%', '70%'],
|
|
|
+ center: ['50%', '50%'],
|
|
|
+ avoidLabelOverlap: false,
|
|
|
+ startAngle: 360,
|
|
|
+ endAngle: 360,
|
|
|
+ itemStyle: {
|
|
|
+ color: '#409eff'
|
|
|
+ },
|
|
|
+ data: [65, 35],
|
|
|
+ label: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
+ disabled: true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ graphic: {
|
|
|
+ elements: [
|
|
|
+ {
|
|
|
+ type: 'text',
|
|
|
+ key: 'percent-text',
|
|
|
+ z: 100,
|
|
|
+ left: 'center',
|
|
|
+ top: 'center',
|
|
|
+ style: {
|
|
|
+ text: qdqsCount1.value + '%',
|
|
|
+ fontSize: 24,
|
|
|
+ fontWeight: 'bold',
|
|
|
+ fill: '#121212'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'text',
|
|
|
+ key: 'label-text',
|
|
|
+ z: 100,
|
|
|
+ left: 'center',
|
|
|
+ bottom: '3%',
|
|
|
+ style: {
|
|
|
+ text: '昨日活跃/过去7天活跃',
|
|
|
+ fontSize: 14,
|
|
|
+ fill: '#121212'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ chart1.setOption(option);
|
|
|
+}
|
|
|
+
|
|
|
+// 初始化第二个饼图进度条
|
|
|
+function initChart2(): void {
|
|
|
+ if (!qdqsRef2.value) return;
|
|
|
+ if (chart2) chart2.dispose();
|
|
|
+
|
|
|
+ chart2 = echarts.init(qdqsRef2.value);
|
|
|
+
|
|
|
+ const option: echarts.EChartsOption = {
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ type: 'pie',
|
|
|
+ radius: ['60%', '70%'],
|
|
|
+ center: ['50%', '50%'],
|
|
|
+ avoidLabelOverlap: false,
|
|
|
+ startAngle: 270,
|
|
|
+ endAngle: 270 - (qdqsCount2.value / 100 * 360),
|
|
|
+ silent: true,
|
|
|
+ itemStyle: {
|
|
|
+ color: '#00BC71',
|
|
|
+ borderRadius: 10
|
|
|
+ },
|
|
|
+ data: [100],
|
|
|
+ label: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
+ disabled: true
|
|
|
+ },
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'pie',
|
|
|
+ radius: ['60%', '70%'],
|
|
|
+ center: ['50%', '50%'],
|
|
|
+ avoidLabelOverlap: false,
|
|
|
+ startAngle: 360,
|
|
|
+ endAngle: 360,
|
|
|
+ itemStyle: {
|
|
|
+ color: '#409eff'
|
|
|
+ },
|
|
|
+ data: [65, 35],
|
|
|
+ label: {
|
|
|
+ show: false
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
+ disabled: true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ graphic: {
|
|
|
+ elements: [
|
|
|
+ {
|
|
|
+ type: 'text',
|
|
|
+ key: 'percent-text',
|
|
|
+ z: 100,
|
|
|
+ left: 'center',
|
|
|
+ top: 'center',
|
|
|
+ style: {
|
|
|
+ text: qdqsCount2.value + '%',
|
|
|
+ fontSize: 24,
|
|
|
+ fontWeight: 'bold',
|
|
|
+ fill: '#121212'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: 'text',
|
|
|
+ key: 'label-text',
|
|
|
+ z: 100,
|
|
|
+ left: 'center',
|
|
|
+ bottom: '3%',
|
|
|
+ style: {
|
|
|
+ text: '昨日活跃/过去30天活跃',
|
|
|
+ fontSize: 14,
|
|
|
+ fill: '#121212'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ chart2.setOption(option);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// 横向进度条相关
|
|
|
+const progressArray = ref([
|
|
|
+ {
|
|
|
+ label: '次日留存率',
|
|
|
+ num: 80,
|
|
|
+ count: 200
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '7日留存率',
|
|
|
+ num: 80,
|
|
|
+ count: 200
|
|
|
+ },
|
|
|
+ {
|
|
|
+ label: '14日留存率',
|
|
|
+ num: 40,
|
|
|
+ count: 200
|
|
|
+ },
|
|
|
+])
|
|
|
+
|
|
|
+</script>
|
|
|
+<style lang="scss" scoped>
|
|
|
+.link {
|
|
|
+ color: #167af0;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+.box1 {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+
|
|
|
+.line {
|
|
|
+ margin: 60px -30px 30px;
|
|
|
+ height: 1px;
|
|
|
+ background-color: #E6E6E6;
|
|
|
+}
|
|
|
+</style>
|