xiaohaizhao 3 ay önce
ebeveyn
işleme
cdd4f4589d

+ 91 - 89
src/MAR/noticeManage/index.vue

@@ -1,105 +1,107 @@
 <template>
-    <listTemp @handleData="handleData" ref="list" keyRouteName="title" :param="param" tableName="noticeTable" :searchType="searchType" :detailPage="{name:'noticeDetail',idname:'sat_noticeid'}">
-      <template #operation>
-        <addNotive v-if="utils.hasPermission('insert')" @back="delRow"></addNotive>
-        <setClass @back="getClassList" v-if="utils.hasPermission('setClass')"></setClass>
+  <listTemp @handleData="handleData" ref="list" keyRouteName="title" :param="param" tableName="noticeTable"
+    :searchType="searchType" :detailPage="{ name: 'noticeDetail', idname: 'sat_noticeid' }">
+    <template #operation>
+      <addNotive v-if="utils.hasPermission('insert')" @back="delRow"></addNotive>
+      <setClass @back="getClassList" v-if="utils.hasPermission('setClass')"></setClass>
+    </template>
+    <template #tb_cell="{ data }">
+      <template v-if="data.column.dataIndex === 'operation'">
+        <dataAnalysis :id="data.record.sat_noticeid" />
       </template>
-      <template #tb_cell="{data}">
-        <template v-if="data.column.dataIndex === 'operation'">
-        </template>
-      </template>
-    </listTemp>
+    </template>
+  </listTemp>
+
 
-    
 </template>
 <script setup>
-  import listTemp from '@/components/listTemplate/index.vue';
-  import { ref,onMounted, nextTick, provide } from 'vue'
-  import { useRouter } from "vue-router";
-  import Api from '@/api/api'
-  import utils from '@/utils/utils'
-  import setClass from './modules/setClass/index.vue'
-  import addNotive from './modules/addNotice.vue'
-  import customBtn from '@/components/customHandleBtn/index.vue'
+import listTemp from '@/components/listTemplate/index.vue';
+import { ref, onMounted, nextTick, provide } from 'vue'
+import { useRouter } from "vue-router";
+import Api from '@/api/api'
+import utils from '@/utils/utils'
+import setClass from './modules/setClass/index.vue'
+import addNotive from './modules/addNotice.vue'
+import customBtn from '@/components/customHandleBtn/index.vue'
+import dataAnalysis from './modules/dataAnalysis.vue'
 
-  import { useAuthStore } from '@/stores/modules/auth'
-  const router = useRouter()
-  const list = ref()
-  let classList = ref([])
-  let classList2 = ref([])
-  provide('classList',() => classList2.value)
-  let searchType = ref([
-    {label:'版块',key:'sat_notice_classid',type:'select',dataSource:[]},
-    {label:'状态',key:'status',type:'select',dataSource:[{remarks:'全部',value:''},{remarks:'新建',value:'新建'},{remarks:'发布',value:'发布'}]},
-    {label:'发布时间',key:'dateRange',type:'datepickerRange',objKeys:['begindate','enddate']},
-    {label:'搜索',key:'condition',type:'input'},
-  ])
-  let param = ref({
-    "id": "20221101094903",
-    "content": {
-      "pageNumber": 1,
-      "pageSize": 25,
-      "where": {
-          "condition": "",
-          "sat_notice_classid": "",
-          "status": "",
-          "begindate": "",
-          "enddate": ""
+import { useAuthStore } from '@/stores/modules/auth'
+const router = useRouter()
+
+const list = ref()
+let classList = ref([])
+let classList2 = ref([])
+provide('classList', () => classList2.value)
+let searchType = ref([
+  { label: '版块', key: 'sat_notice_classid', type: 'select', dataSource: [] },
+  { label: '状态', key: 'status', type: 'select', dataSource: [{ remarks: '全部', value: '' }, { remarks: '新建', value: '新建' }, { remarks: '发布', value: '发布' }] },
+  { label: '发布时间', key: 'dateRange', type: 'datepickerRange', objKeys: ['begindate', 'enddate'] },
+  { label: '搜索', key: 'condition', type: 'input' },
+])
+let param = ref({
+  "id": "20221101094903",
+  "content": {
+    "pageNumber": 1,
+    "pageSize": 25,
+    "where": {
+      "condition": "",
+      "sat_notice_classid": "",
+      "status": "",
+      "begindate": "",
+      "enddate": ""
+    }
+  }
+})
+const getClassList = async () => {
+  let res = await Api.requested({
+    'id': 20221101094603,
+    'content': {
+      'where': {
+        isenable: 1
       }
     }
   })
-  const getClassList = async () => {
-    let res = await Api.requested({
-      'id':20221101094603,
-      'content': {
-        'where': {
-          isenable:1
-        }
-      }
-    })
-    classList2.value = JSON.parse(JSON.stringify(res.data))
-    console.log(res);
-    classList.value = res.data.map(item => {
-      return {remarks:item.classname,value:item.sat_notice_classid}
-    })
-    classList.value.unshift({'remarks':'全部','value':''})
-    searchType.value[0].dataSource = classList.value
-    console.log(classList.value);
-  }
-  const onSuccess = ()=>{
-    list.value.tableData()
-  }
-  const delRow = (id,init) => {
-    if (init) return list.value.tableData()
+  classList2.value = JSON.parse(JSON.stringify(res.data))
+  console.log(res);
+  classList.value = res.data.map(item => {
+    return { remarks: item.classname, value: item.sat_notice_classid }
+  })
+  classList.value.unshift({ 'remarks': '全部', 'value': '' })
+  searchType.value[0].dataSource = classList.value
+  console.log(classList.value);
+}
+const onSuccess = () => {
+  list.value.tableData()
+}
+const delRow = (id, init) => {
+  if (init) return list.value.tableData()
+  Api.requested({
+    "id": 20221101095103,
+    "content": {
+      "sat_noticeids": [id]
+    }
+  })
+}
+//是否需要删除空数据
+const handleData = (data) => {
+  let initID = '9999' + useAuthStore().nowAccount.userid;
+  let deleteList = [];
+  data.data.forEach(v => (initID == v.sat_notice_classid && v.title == '') ? deleteList.push(v.sat_noticeid) : '')
+  if (deleteList.length != 0) {
     Api.requested({
-      "id":20221101095103,
+      "id": 20221101095103,
       "content": {
-        "sat_noticeids": [id]
+        "sat_noticeids": deleteList
       }
+    }).then(res => {
+      if (res.msg == '成功') list.value.tableData()
     })
   }
-  //是否需要删除空数据
-  const handleData = (data) => {
-    let initID = '9999' + useAuthStore().nowAccount.userid;
-    let deleteList = [];
-    data.data.forEach(v => (initID == v.sat_notice_classid && v.title == '') ? deleteList.push(v.sat_noticeid) : '')
-    if (deleteList.length != 0) {
-      Api.requested({
-        "id":20221101095103,
-        "content": {
-          "sat_noticeids": deleteList
-        }
-      }).then(res => {
-        if (res.msg == '成功') list.value.tableData()
-      })
-    }
-    console.log(data,'数据');
-  }
+  console.log(data, '数据');
+}
 
-  onMounted(() => {
-    getClassList()
-  })
+onMounted(() => {
+  getClassList()
+})
 </script>
-<style scoped>
-
-</style>
+<style scoped></style>

+ 168 - 0
src/MAR/noticeManage/modules/dataAnalysis.vue

@@ -0,0 +1,168 @@
+<template>
+    <a-button type="link" @click="openView">数据分析</a-button>
+    <a-drawer ref="drawer" v-model:open="modeVisible" placement="right" :width="'90%'" :closable="false">
+        <a-tabs v-model:activeKey="activeKey" type="card" size="large" @change="init">
+            <a-tab-pane key="1" tab="经销商分析"></a-tab-pane>
+            <a-tab-pane key="2" tab="团队内部分析"></a-tab-pane>
+        </a-tabs>
+
+        <view class="row-box">
+            <view class="chart" :id="`LearningCondition_${props.id}`" />
+            <view class="right"></view>
+        </view>
+        <view class="row-box">
+            <view class="chart" :id="`DownloadStatus_${props.id}`" />
+            <view class="right"></view>
+        </view>
+    </a-drawer>
+</template>
+
+<script setup>
+import { ref, defineProps } from 'vue'
+import Api from '@/api/api'
+import { Pie } from '@antv/g2plot'
+
+let props = defineProps({
+    id: { type: [String, Number], required: true },
+})
+
+let activeKey = ref('1')
+let modeVisible = ref(false)
+
+// 存储图表实例
+const studyPieInstance = ref(null)
+const downloadPieInstance = ref(null)
+
+const openView = () => {
+    init()
+    modeVisible.value = true
+}
+
+const init = () => {
+    getDealerAnalysis()
+}
+
+const getDealerAnalysis = async () => {
+    let res = await Api.requested(activeKey.value == 1 ? {
+        "classname": "webmanage.saletool.notice.statistics.agent",
+        "method": "getAgentStudyData",
+        "content": { "sat_noticeid": props.id }
+    } : {
+        "classname": "webmanage.saletool.notice.statistics.team",
+        "method": "getTeamStudyData",
+        "content": { "sat_noticeid": props.id }
+    })
+    console.log("经销商浏览分析", res);
+    // 假设接口返回实际数据,这里用模拟数据
+    renderPie(res.data);
+}
+
+const renderPie = (data) => {
+    // 根据 props.id 获取唯一的容器
+    const studyContainerId = `LearningCondition_${props.id}`
+    const downloadContainerId = `DownloadStatus_${props.id}`
+
+    // 销毁旧图表实例
+    if (studyPieInstance.value) {
+        studyPieInstance.value.destroy()
+        studyPieInstance.value = null
+    }
+    if (downloadPieInstance.value) {
+        downloadPieInstance.value.destroy()
+        downloadPieInstance.value = null
+    }
+
+    // 计算总数
+    const studyTotal = data.studyNum + data.unStudyNum
+    const downloadTotal = data.downloadNum + data.unDownloadNum
+
+    // 学习情况数据
+    const studyData = [
+        { type: '已学习', value: data.studyNum },
+        { type: '未学习', value: data.unStudyNum },
+    ]
+
+    // 下载情况数据
+    const downloadData = [
+        { type: '已下载', value: data.downloadNum },
+        { type: '未下载', value: data.unDownloadNum },
+    ]
+
+    // 学习情况饼图
+    studyPieInstance.value = new Pie(studyContainerId, {
+        data: studyData,
+        angleField: 'value',
+        colorField: 'type',
+        color: ['#FBB745', '#F87D5E'],
+        radius: 0.8,
+        label: {
+            type: 'outer',
+            content: (item) => {
+                const percent = ((item.value / studyTotal) * 100).toFixed(1)
+                return `${item.type}\n${percent}%`
+            },
+            style: { fill: '#333', fontSize: 12 },
+            labelLine: { style: { stroke: '#aaa', lineWidth: 1 } },
+            offset: 20,
+        },
+        legend: { position: 'bottom' },
+        tooltip: {
+            showTitle: false,
+            formatter: (item) => ({ name: item.type, value: item.value }),
+        },
+    })
+
+    // 下载情况饼图
+    downloadPieInstance.value = new Pie(downloadContainerId, {
+        data: downloadData,
+        angleField: 'value',
+        colorField: 'type',
+        color: ['#38C2F6', '#657DE6'],
+        radius: 0.8,
+        label: {
+            type: 'outer',
+            content: (item) => {
+                const percent = ((item.value / downloadTotal) * 100).toFixed(1)
+                return `${item.type}\n${percent}%`
+            },
+            style: { fill: '#333', fontSize: 12 },
+            labelLine: { style: { stroke: '#aaa', lineWidth: 1 } },
+            offset: 20,
+        },
+        legend: { position: 'bottom' },
+        tooltip: {
+            showTitle: false,
+            formatter: (item) => ({ name: item.type, value: item.value }),
+        },
+    })
+
+    studyPieInstance.value.render()
+    downloadPieInstance.value.render()
+}
+</script>
+
+<style scoped>
+.row-box {
+    display: flex;
+    align-items: center;
+    width: 100%;
+    height: 700px;
+}
+
+.row-box .chart {
+    box-sizing: border-box;
+    padding: 10px;
+    flex: 0 0 30%;
+    height: 100%;
+    min-width: 0;
+}
+
+.row-box .right {
+    flex: 1;
+    height: 100%;
+    min-width: 0;
+}
+
+/* 由于 id 是动态的,样式选择器无法直接使用 id,所以改用 class 选择器或使用属性选择器 */
+/* 这里我们已经在 .chart 上设置了样式,内部容器会继承宽高 */
+</style>