luzhenxing 2 місяців тому
батько
коміт
2150b2d935
2 змінених файлів з 170 додано та 208 видалено
  1. 7 7
      src/locales/lang/zh-CN/wechat.ts
  2. 163 201
      src/views/dashboard/workbench/index.vue

+ 7 - 7
src/locales/lang/zh-CN/wechat.ts

@@ -85,13 +85,13 @@ export default {
   },
   sop_task_type: ['好友', '群组', '公众号', '企业微信联系人'],
   chatroomMember: {
-    wxid: 'Wxid',
-    chatRoom: 'ChatRoom',
-    ownerWxid: 'OwnerWxid',
-    account: 'Account',
-    addChatroomMember: '添加 ChatroomMember',
-    editChatroomMember: '编辑 ChatroomMember',
-    chatroomMemberList: 'ChatroomMember 列表',
+    wxid: '微信号',
+    chatRoom: '群聊',
+    ownerWxid: '所属账号',
+    account: '账号',
+    addChatroomMember: '添加群成员',
+    editChatroomMember: '编辑群成员',
+    chatroomMemberList: '群成员列表',
   },
   batchMsg: {
     status: '状态',

+ 163 - 201
src/views/dashboard/workbench/index.vue

@@ -1,258 +1,220 @@
+<!-- 微信私域运营数据看板页面 -->
 <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" />
+          <!-- 日期范围选择器 -->
+          <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">
+            <Select
+              size="small"
+              style="width: 100px"
+              v-model:value="organizationId"
+              @change="fetchData"
+            >
               <SelectOption :value="0">所有账号</SelectOption>
-              <SelectOption v-for="item in departmentList" :value="item.id">{{ item.name }}</SelectOption>
+              <SelectOption v-for="item in departmentList" :key="item.id" :value="item.id">
+                {{ item.name }}
+              </SelectOption>
+            </Select>
+            <!-- 新增的 select -->
+            <Select
+              size="small"
+              style="width: 100px"
+              v-model:value="filterType"
+              @change="fetchData"
+            >
+              <SelectOption :value="0">全部类型</SelectOption>
+              <SelectOption :value="1">个人号</SelectOption>
+              <SelectOption :value="2">企业号</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">
-            <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 :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" />
+            <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" />
+            <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" />
+            <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';
+  // 导入所需的组件和工具
+  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 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 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 filterType = ref(0);
 
-const charts = ref()
-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 date = ref<[dayjs.Dayjs, dayjs.Dayjs]>()
+  // 图表配置数据
+  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'
-}]
+  // 表格列配置
+  const columns = [
+    { title: '账号', dataIndex: 'nickname' },
+    { title: '好友数', dataIndex: 'total_friend' },
+    { title: '群数量', dataIndex: 'total_group' },
+    { title: '互动率', dataIndex: 'interaction_rate' },
+  ];
 
-const tableData = ref<object[]>([])
+  // 页面初始化
+  onMounted(async () => {
+    toDate(0); // 默认显示今天的数据
+    if (isSuper) {
+      // 如果是超级管理员,加载部门列表
+      const res = await getDepartmentList({ page: 1, pageSize: 100 });
+      departmentList.value = res.data.data;
+    }
+  });
 
-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 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'))
+  // 获取账号列表数据
+  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);
     }
-    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
-  } finally {
-    // tableData.value = [{
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }, {
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }, {
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }, {
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }, {
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }, {
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }, {
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }, {
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }, {
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }, {
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }, {
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }, {
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }, {
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }, {
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }, {
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }, {
-    //   wechat: '微信账号1',
-    //   friend: 856,
-    //   group: 45,
-    //   interaction: '78.5%'
-    // }]
+
+  // 刷新所有数据
+  function fetchData() {
+    fetchCharts();
+    fetchList();
+  }
+
+  // 快捷设置日期范围
+  function toDate(day) {
+    date.value = [dayjs().subtract(day, 'day'), dayjs()];
+    fetchData();
   }
-}
-function fetchData() {
-  fetchCharts()
-  fetchList()
-}
-function toDate(day) {
-  date.value = [dayjs().subtract(day, 'day'), dayjs()]
-  fetchData()
-}
 </script>
+
 <style lang="scss" scoped>
-.page-wrapper {
-  background: #fff;
-}
+  // 面样式
+  .page-wrapper {
+    background: #fff;
+  }
 
-.title {
-  font-size: 1.5em;
-}
+  .title {
+    font-size: 1.5em;
+  }
 </style>