123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- <!-- 微信私域运营数据看板页面 -->
- <template>
- <PageWrapper class="page-wrapper">
- <!-- 页面头部内容 -->
- <template #headerContent>
- <Flex justify="space-between" align="center">
- <h1 class="title">微信私域用户运营数据看板</h1>
- <Space>
- <!-- 快捷日期选择按钮组 -->
- <div>
- <a-button type="link" size="small" @click="toDate(7)">近7天</a-button>
- <a-button type="link" size="small" @click="toDate(1)">昨天</a-button>
- <a-button type="link" size="small" @click="toDate(0)">今天</a-button>
- </div>
- <!-- 日期范围选择器 -->
- <RangePicker
- v-model:value="date"
- size="small"
- :allowClear="false"
- inputReadOnly
- @change="fetchData"
- />
- <!-- 超级管理员可见的组织选择器 -->
- <template v-if="isSuper">
- <UserOutlined />
- <Select
- size="small"
- style="width: 100px"
- v-model:value="organizationId"
- @change="fetchData"
- >
- <SelectOption :value="0">所有账号</SelectOption>
- <SelectOption v-for="item in departmentList" :key="item.id" :value="item.id">
- {{ item.name }}
- </SelectOption>
- </Select>
- </template>
- </Space>
- </Flex>
- </template>
- <!-- 数据加载状态 -->
- <Spin :spinning="loading" size="large">
- <!-- 图表展示区域 -->
- <Space v-if="charts" direction="vertical" :size="32">
- <!-- 第一行:数据概览卡片 -->
- <Row :gutter="[32, 32]">
- <Col :span="6" v-for="item in chartsAreaLineMap" :key="item.key">
- <ChartsAreaLine
- :label="item.label"
- :rate="charts[item.key].rate"
- :title="charts[item.key].count"
- :labels="charts[item.key].label"
- :data="charts[item.key].val"
- />
- </Col>
- </Row>
- <!-- 第二行:趋势图表 -->
- <Row :gutter="32">
- <Col :span="12">
- <ChartsLine
- title="Token 消耗趋势"
- :labels="charts.consume_token.label"
- :data="charts.consume_token.val"
- />
- </Col>
- <Col :span="12">
- <ChartsLine
- title="用户增长趋势"
- :labels="charts.new_user.label"
- :data="charts.new_user.val"
- />
- </Col>
- </Row>
- <!-- 第三行:标签分布和账号分析 -->
- <Row :gutter="32">
- <Col :span="12">
- <ChartsPie title="标签分布" :data="charts.label_dist" />
- </Col>
- <Col :span="12">
- <TableList title="账号分析" :columns="columns" :data="tableData" />
- </Col>
- </Row>
- </Space>
- </Spin>
- </PageWrapper>
- </template>
- <script lang="ts" setup>
- // 导入所需的组件和工具
- import { onMounted, ref } from 'vue';
- import { PageWrapper } from '@/components/Page';
- import { Flex, Row, Col, Space, Select, SelectOption, RangePicker, Spin } from 'ant-design-vue';
- import { UserOutlined } from '@ant-design/icons-vue';
- import ChartsAreaLine from './components/ChartsAreaLine.vue';
- import ChartsLine from './components/ChartsLine.vue';
- import ChartsPie from './components/ChartsPie.vue';
- import TableList from './components/TableList.vue';
- import dayjs from 'dayjs';
- import { getDashboardCharts, getDashboardWxList } from '/@/api/dashboard/dashboard';
- import { getDepartmentList } from '@/api/sys/department';
- import { useUserStore } from '/@/store/modules/user';
- import { DepartmentInfo } from '/@/api/sys/model/departmentModel';
- // 用户信息和权限判断
- const userStore = useUserStore();
- const userInfo = userStore.getUserInfo;
- const isSuper = userInfo.roleName.some((str) => str == '超级管理员');
- // 页面状态管理
- const loading = ref(false);
- const organizationId = ref(0);
- const departmentList = ref<DepartmentInfo[]>([]);
- const charts = ref();
- const date = ref<[dayjs.Dayjs, dayjs.Dayjs]>();
- const tableData = ref<object[]>([]);
- // 图表配置数据
- const chartsAreaLineMap = [
- { label: 'AI 回复次数', key: 'ai_response' },
- { label: 'SOP执行次数', key: 'sop_run' },
- { label: '总好友数', key: 'total_friend' },
- { label: '总群数', key: 'total_group' },
- { label: '账户余额', key: 'account_balance' },
- { label: 'Token消耗', key: 'consume_token' },
- { label: '活跃用户', key: 'active_user' },
- { label: '新增好友', key: 'new_user' },
- ];
- // 表格列配置
- const columns = [
- { title: '账号', dataIndex: 'nickname' },
- { title: '好友数', dataIndex: 'total_friend' },
- { title: '群数量', dataIndex: 'total_group' },
- { title: '互动率', dataIndex: 'interaction_rate' },
- ];
- // 页面初始化
- onMounted(async () => {
- toDate(0); // 默认显示今天的数据
- if (isSuper) {
- // 如果是超级管理员,加载部门列表
- const res = await getDepartmentList({ page: 1, pageSize: 100 });
- departmentList.value = res.data.data;
- }
- });
- // 获取图表数据
- async function fetchCharts() {
- try {
- loading.value = true;
- let start_date = '';
- let end_date = '';
- if (date.value && date.value.length) {
- [start_date, end_date] = date.value.map((o) => o.format('YYYY-MM-DD'));
- }
- const res = await getDashboardCharts({
- start_date,
- end_date,
- organizationId: organizationId.value,
- });
- charts.value = res.data;
- } finally {
- loading.value = false;
- }
- }
- // 获取账号列表数据
- async function fetchList() {
- try {
- let end_date = dayjs().format('YYYY-MM-DD');
- if (date.value && date.value.length) {
- end_date = date.value[1].format('YYYY-MM-DD');
- }
- const res = await getDashboardWxList({
- page: 1,
- pageSize: 1000,
- end_date,
- organizationId: organizationId.value,
- });
- tableData.value = res.data.data;
- } catch (error) {
- console.error(error);
- }
- }
- // 刷新所有数据
- function fetchData() {
- fetchCharts();
- fetchList();
- }
- // 快捷设置日期范围
- function toDate(day) {
- date.value = [dayjs().subtract(day, 'day'), dayjs()];
- fetchData();
- }
- </script>
- <style lang="scss" scoped>
- // 页面样式
- .page-wrapper {
- background: #fff;
- }
- .title {
- font-size: 1.5em;
- }
- </style>
|