|
|
@@ -5,71 +5,71 @@
|
|
|
<div class="top-pre-num adfacjb">
|
|
|
<div class="top-pre-num-l">
|
|
|
<p>累计注册用户总数</p>
|
|
|
- <p class="n">{{ 24589 }}</p>
|
|
|
+ <p class="n">{{ headData?.totalRegister||0 }}</p>
|
|
|
</div>
|
|
|
<div class="top-pre-num-r">
|
|
|
<img src="@/assets/images/agent/user_img1.png">
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="top-pre-text adfac">
|
|
|
+ <!-- <div class="top-pre-text adfac">
|
|
|
<div class="tn">较昨日 {{ 23345 }}% <i class="el-icon-caret-bottom" style="color: #FD4F66;"></i></div>
|
|
|
- </div>
|
|
|
+ </div> -->
|
|
|
</div>
|
|
|
<div class="top-pre">
|
|
|
<div class="top-pre-num adfacjb">
|
|
|
<div class="top-pre-num-l">
|
|
|
<p>今日新增用户总数</p>
|
|
|
- <p class="n">{{ 679 }}</p>
|
|
|
+ <p class="n">{{ headData?.todayRegister||0 }}</p>
|
|
|
</div>
|
|
|
<div class="top-pre-num-r">
|
|
|
<img src="@/assets/images/agent/user_img2.png">
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="top-pre-text adfac">
|
|
|
+ <!-- <div class="top-pre-text adfac">
|
|
|
<div class="tn">较昨日 {{ 345 }}% <i class="el-icon-caret-top" style="color: #33A7A7;"></i></div>
|
|
|
- </div>
|
|
|
+ </div> -->
|
|
|
</div>
|
|
|
<div class="top-pre">
|
|
|
<div class="top-pre-num adfacjb">
|
|
|
<div class="top-pre-num-l">
|
|
|
<p>创衡运营邀请渠道</p>
|
|
|
- <p class="n">{{ 2458 }}</p>
|
|
|
+ <p class="n">{{ headData?.scanTotal||0 }}</p>
|
|
|
</div>
|
|
|
<div class="top-pre-num-r">
|
|
|
<img src="@/assets/images/agent/user_img3.png">
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="top-pre-text adfac">
|
|
|
+ <!-- <div class="top-pre-text adfac">
|
|
|
<div class="tn">较昨日 {{ 345 }}% <i class="el-icon-caret-top" style="color: #33A7A7;"></i></div>
|
|
|
- </div>
|
|
|
+ </div> -->
|
|
|
</div>
|
|
|
<div class="top-pre">
|
|
|
<div class="top-pre-num adfacjb">
|
|
|
<div class="top-pre-num-l">
|
|
|
<p>用户推荐转发</p>
|
|
|
- <p class="n">{{ 7289 }}</p>
|
|
|
+ <p class="n">{{ headData?.shareTotal||0 }}</p>
|
|
|
</div>
|
|
|
<div class="top-pre-num-r">
|
|
|
<img src="@/assets/images/agent/user_img4.png">
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="top-pre-text adfac">
|
|
|
+ <!-- <div class="top-pre-text adfac">
|
|
|
<div class="tn">较昨日 {{ 345 }}% <i class="el-icon-caret-top" style="color: #33A7A7;"></i></div>
|
|
|
- </div>
|
|
|
+ </div> -->
|
|
|
</div>
|
|
|
<div class="top-pre">
|
|
|
<div class="top-pre-num adfacjb">
|
|
|
<div class="top-pre-num-l">
|
|
|
<p>团队教练转发问卷任务</p>
|
|
|
- <p class="n">{{ 4589 }}</p>
|
|
|
+ <p class="n">{{ headData?.todayShare||0 }}</p>
|
|
|
</div>
|
|
|
<div class="top-pre-num-r">
|
|
|
<img src="@/assets/images/agent/user_img5.png">
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="top-pre-text adfac">
|
|
|
+ <!-- <div class="top-pre-text adfac">
|
|
|
<div class="tn">较昨日 {{ 345 }}% <i class="el-icon-caret-bottom" style="color: #FD4F66;"></i></div>
|
|
|
- </div>
|
|
|
+ </div> -->
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="middle adfacjb">
|
|
|
@@ -108,11 +108,15 @@
|
|
|
<div class="middle adfacjb">
|
|
|
<div class="box box2 adffc">
|
|
|
<div class="date adfac">
|
|
|
- <div class="date-pre" :class="{'active':didx==1}" @click="changeDate(1)">本周</div>
|
|
|
+ <div class="date-pre" :class="{'active':didx==1}" @click="changeDate(1)">近7天</div>
|
|
|
<div class="date-pre" :class="{'active':didx==2}" @click="changeDate(2)">本月</div>
|
|
|
- <el-select v-model="queryDate" placeholder="自定义时间" @change="changeCusDate" style="width: 167px;">
|
|
|
- <el-option label="近10天" value="10"></el-option>
|
|
|
- </el-select>
|
|
|
+ <el-date-picker @change="changeCusDate"
|
|
|
+ v-model="queryParams.startEndTime"
|
|
|
+ type="daterange"
|
|
|
+ range-separator="至"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期">
|
|
|
+ </el-date-picker>
|
|
|
</div>
|
|
|
<div class="box-title">用户概览</div>
|
|
|
<div class="box-echart">
|
|
|
@@ -126,14 +130,22 @@
|
|
|
<script setup name="">
|
|
|
import * as echarts from "echarts";
|
|
|
import {
|
|
|
+ getUserRegisterSummary,
|
|
|
getRegisterChannelStats,
|
|
|
- getIndustryScattergram
|
|
|
+ getIndustryScattergram,
|
|
|
+ getUserRegisterGraph
|
|
|
} from '@/api/agent/indexTwo.js'
|
|
|
import { ref, getCurrentInstance, onMounted } from 'vue'
|
|
|
const { proxy } = getCurrentInstance();
|
|
|
|
|
|
const didx = ref(1)
|
|
|
- const queryDate = ref('')
|
|
|
+ const headData = ref(null)
|
|
|
+ const queryParams = ref({
|
|
|
+ beginTime:'',
|
|
|
+ endTime:'',
|
|
|
+ startEndTime:'',
|
|
|
+ type:1
|
|
|
+ })
|
|
|
const yhglRef = ref(null)
|
|
|
const yhzcqdRef = ref(null)
|
|
|
const yhhxRef = ref(null)
|
|
|
@@ -145,11 +157,154 @@
|
|
|
const yhzcqdTypeList = ref([])
|
|
|
|
|
|
const changeDate = (idx) => {
|
|
|
- didx.value = idx
|
|
|
+ if(idx===didx.value) return
|
|
|
+ didx.value = idx;
|
|
|
+ queryParams.value.type = idx;
|
|
|
+ queryParams.value.beginTime = '';
|
|
|
+ queryParams.value.endTime = '';
|
|
|
+ queryParams.value.startEndTime = '';
|
|
|
+ getUserRegisterGraphFn()
|
|
|
+ }
|
|
|
+
|
|
|
+ const changeCusDate = (e) => {
|
|
|
+ didx.value = '';
|
|
|
+ queryParams.value.type = 3;
|
|
|
+ queryParams.value.beginTime = proxy.parseTime(new Date(e[0]), '{yy}-{mm}-{dd}');
|
|
|
+ queryParams.value.endTime = proxy.parseTime(new Date(e[1]), '{yy}-{mm}-{dd}');
|
|
|
+ getUserRegisterGraphFn()
|
|
|
+ }
|
|
|
+
|
|
|
+ const getUserRegisterGraphFn = () => {
|
|
|
+ let params = JSON.parse(JSON.stringify(queryParams.value))
|
|
|
+ delete params.startEndTime;
|
|
|
+ getUserRegisterGraph(params).then(res => {
|
|
|
+ let startDate = '', endDate = '';
|
|
|
+ if(queryParams.value.type<3){
|
|
|
+ startDate = getDateRange(queryParams.value.type).startDate;
|
|
|
+ endDate = getDateRange(queryParams.value.type).endDate;
|
|
|
+ }else{
|
|
|
+ startDate = queryParams.value.beginTime;
|
|
|
+ endDate = queryParams.value.endTime;
|
|
|
+ }
|
|
|
+ let data = fillMissingDates(res.data,startDate,endDate)
|
|
|
+ console.log(data)
|
|
|
+
|
|
|
+ let xdata = data.map(item => item.dateDay)
|
|
|
+ let ydata = data.map(item => item.registerNum)
|
|
|
+ initYhglEchart(xdata,ydata)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 填充指定日期范围内缺失的数据。
|
|
|
+ * 该函数会确保从开始日期到结束日期的每一天都有一条数据记录。
|
|
|
+ * 如果某天的数据不存在,则会使用指定的默认值进行填充。
|
|
|
+ *
|
|
|
+ * @param {Array<Object>} dataList - 原始数据数组,例如 [{stats: 2, dateDay: "2025-11-06"}]
|
|
|
+ * @param {string} startDateStr - 开始日期字符串, 格式为 "YYYY-MM-DD"
|
|
|
+ * @param {string} endDateStr - 结束日期字符串, 格式为 "YYYY-MM-DD"
|
|
|
+ * @param {Object} options - (可选) 配置项
|
|
|
+ * @param {string} options.dateKey - (可选) 数据对象中表示日期的属性名,默认为 'dateDay'
|
|
|
+ * @param {Object} options.defaultValue - (可选) 缺失日期的默认数据对象,默认为 { stats: 0 }
|
|
|
+ * @returns {Array<Object>} 填充完毕的完整数据数组
|
|
|
+ */
|
|
|
+ function fillMissingDates(dataList, startDateStr, endDateStr, options = {}) {
|
|
|
+ const {
|
|
|
+ dateKey = 'dateDay',
|
|
|
+ defaultValue = { registerNum: 0 }
|
|
|
+ } = options;
|
|
|
+
|
|
|
+ const dataMap = new Map(dataList.map(item => [item[dateKey], item]));
|
|
|
+ const result = [];
|
|
|
+
|
|
|
+ // 注意:这里的 new Date() 也会受时区影响,但配合下面的循环和 formatLocalDate 可以正确工作
|
|
|
+ const currentDate = new Date(startDateStr);
|
|
|
+ const endDate = new Date(endDateStr);
|
|
|
+
|
|
|
+ // 将 currentDate 的时间部分设置为中午12点,可以更稳妥地避免夏令时等边界问题
|
|
|
+ currentDate.setHours(12, 0, 0, 0);
|
|
|
+ endDate.setHours(12, 0, 0, 0);
|
|
|
+
|
|
|
+ while (currentDate <= endDate) {
|
|
|
+ const dateString = formatDate(currentDate);
|
|
|
+
|
|
|
+ if (dataMap.has(dateString)) {
|
|
|
+ result.push(dataMap.get(dateString));
|
|
|
+ } else {
|
|
|
+ result.push({
|
|
|
+ ...defaultValue,
|
|
|
+ [dateKey]: dateString,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将日期增加一天
|
|
|
+ currentDate.setDate(currentDate.getDate() + 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 格式化日期对象为 'YYYY.MM.DD' 格式的字符串
|
|
|
+ * @param {Date} date - 需要格式化的日期对象
|
|
|
+ * @returns {string} - 格式化后的日期字符串
|
|
|
+ */
|
|
|
+ function formatDate(date) {
|
|
|
+ const year = date.getFullYear();
|
|
|
+ const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
|
+ const day = String(date.getDate()).padStart(2, '0');
|
|
|
+ return `${year}-${month}-${day}`;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据类型获取指定的日期范围
|
|
|
+ * @param {number} type - 类型 (1: 近7天, 2: 本月, 3: 本周)
|
|
|
+ * @returns {{startDate: string, endDate: string} | {startDate: null, endDate: null}}
|
|
|
+ */
|
|
|
+ function getDateRange(type=1) {
|
|
|
+ const today = new Date();
|
|
|
+ // 为了避免跨天等时区问题,将时间统一设置为当天的零点
|
|
|
+ today.setHours(0, 0, 0, 0);
|
|
|
+
|
|
|
+ let startDate = new Date(today);
|
|
|
+ const endDate = new Date(today); // 结束日期在所有情况下都是今天
|
|
|
+
|
|
|
+ switch (type) {
|
|
|
+ case 1:
|
|
|
+ // --- 近7天 ---
|
|
|
+ // 开始日期 = 今天 - 6天 (总共7天)
|
|
|
+ startDate.setDate(today.getDate() - 6);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 2:
|
|
|
+ // --- 本月 (从1号到今天) ---
|
|
|
+ // 直接将开始日期的日设置为1号
|
|
|
+ startDate.setDate(1);
|
|
|
+ break;
|
|
|
+
|
|
|
+ case 3:
|
|
|
+ // --- 本周 (从周一到今天) ---
|
|
|
+ // getDay() 返回 0(周日)-6(周六)。我们希望周一是1,周日是7
|
|
|
+ const dayOfWeek = today.getDay() === 0 ? 7 : today.getDay();
|
|
|
+ // 开始日期 = 今天 - (今天是本周第几天 - 1)
|
|
|
+ startDate.setDate(today.getDate() - (dayOfWeek - 1));
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ console.error("无效的类型参数,请输入 1, 2, 或 3。");
|
|
|
+ return { startDate: null, endDate: null };
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ startDate: formatDate(startDate),
|
|
|
+ endDate: formatDate(endDate),
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
- const changeCusDate = () => {
|
|
|
- didx.value = ''
|
|
|
+ const getUserRegisterSummaryFn = () => {
|
|
|
+ getUserRegisterSummary().then(res => {
|
|
|
+ headData.value = res.data
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
const getRegisterChannelStatsFn = () => {
|
|
|
@@ -164,14 +319,14 @@
|
|
|
})
|
|
|
}
|
|
|
|
|
|
- const initYhglEchart = () => {
|
|
|
+ const initYhglEchart = (xdata,ydata) => {
|
|
|
const chart = echarts.init(yhglRef.value)
|
|
|
let option = {
|
|
|
color: ['#01A79C','#0177B3'],
|
|
|
xAxis: {
|
|
|
type: 'category',
|
|
|
boundaryGap: false,
|
|
|
- data: ['11-01', '11-02', '11-03', '11-04', '11-05', '11-06', '11-07']
|
|
|
+ data: xdata
|
|
|
},
|
|
|
yAxis: {
|
|
|
type: 'value'
|
|
|
@@ -184,7 +339,8 @@
|
|
|
containLabel: true
|
|
|
},
|
|
|
legend: {
|
|
|
- data: ['新增用户', '累计用户'],
|
|
|
+ // data: ['新增用户', '累计用户'],
|
|
|
+ data: ['新增用户'],
|
|
|
top:'3%',
|
|
|
left:'1%'
|
|
|
},
|
|
|
@@ -200,7 +356,7 @@
|
|
|
series: [
|
|
|
{
|
|
|
name:'新增用户',
|
|
|
- data: [30,170,30,80,50,160,20],
|
|
|
+ data: ydata,
|
|
|
type: 'line',
|
|
|
smooth: true,
|
|
|
lineStyle: {
|
|
|
@@ -208,16 +364,16 @@
|
|
|
},
|
|
|
showSymbol: false,
|
|
|
},
|
|
|
- {
|
|
|
- name:'累计用户',
|
|
|
- data: [200,90,130,90,220,60,80],
|
|
|
- type: 'line',
|
|
|
- smooth: true,
|
|
|
- lineStyle: {
|
|
|
- width: 4,
|
|
|
- },
|
|
|
- showSymbol: false,
|
|
|
- }
|
|
|
+ // {
|
|
|
+ // name:'累计用户',
|
|
|
+ // data: [200,90,130,90,220,60,80],
|
|
|
+ // type: 'line',
|
|
|
+ // smooth: true,
|
|
|
+ // lineStyle: {
|
|
|
+ // width: 4,
|
|
|
+ // },
|
|
|
+ // showSymbol: false,
|
|
|
+ // }
|
|
|
]
|
|
|
}
|
|
|
chart.setOption(option)
|
|
|
@@ -386,13 +542,13 @@
|
|
|
}
|
|
|
|
|
|
onMounted(()=>{
|
|
|
+ getUserRegisterSummaryFn()
|
|
|
getRegisterChannelStatsFn()
|
|
|
- initYhglEchart()
|
|
|
initHyfbData()
|
|
|
- initYhhxEchart()
|
|
|
- initNlfbEcharts()
|
|
|
+ // initYhhxEchart()
|
|
|
+ // initNlfbEcharts()
|
|
|
proxy.$nextTick(()=>{
|
|
|
-
|
|
|
+ getUserRegisterGraphFn()
|
|
|
})
|
|
|
})
|
|
|
</script>
|
|
|
@@ -619,6 +775,7 @@
|
|
|
position: absolute;
|
|
|
top: 42px;
|
|
|
right: 20px;
|
|
|
+ z-index: 1001;
|
|
|
&-pre{
|
|
|
width: 54px;
|
|
|
height: 40px;
|