1
0

7 کامیت‌ها 17b3108238 ... 7c7002fe31

نویسنده SHA1 پیام تاریخ
  yejian 7c7002fe31 router index.js冲突 2 سال پیش
  yejian f247c00388 已发稿件数量排行榜,稿件传播量排行榜 2 سال پیش
  liyongli d636741a2e 提交 2 سال پیش
  liyongli 92dbc89b5a 提交 2 سال پیش
  liyongli 885ffe149e 提交 2 سال پیش
  liyongli 35b870fbcb 提交 2 سال پیش
  liyongli 288e93c0ef 提交 2 سال پیش

+ 26 - 0
a.http

@@ -0,0 +1,26 @@
+### 栏目分析
+POST http://172.16.101.20:8762/cxzx-program/new-media/category 
+Content-Type: application/json;charset=UTF-8
+
+{
+  "start": "2023-01-11",
+  "end": "2023-01-31",
+  "app": "闪视频",
+  "version": [],
+  "lib": ""
+}
+
+### 内容日数据分析
+POST http://172.16.101.20:8762/cxzx-program/new-media/content/daily 
+Content-Type: application/json;charset=UTF-8
+
+{
+  "start": "2023-01-11",
+  "end": "2023-01-31",
+  "app": "西部网",
+  "version": [],
+  "lib": ""
+}
+
+### 内容日数据分析导出
+GET http://172.16.101.20:8762/cxzx-program/new-media/content/daily-export?start=2023-01-21&end=2023-01-31&app=西部网&version=

+ 41 - 1
src/api/index.js

@@ -899,7 +899,7 @@ export function getSearchData(data) {
   });
 }
 /**
- * 获取大数据平台内容分析 top10;
+ * 获取大数据平台内容分析 Top10;
  * @return {AxjxPromise}
  */
 export function getContentTop10(data) {
@@ -910,6 +910,18 @@ export function getContentTop10(data) {
     data,
   });
 }
+/**
+ * 获取大数据平台内容分析 检索内容汇总new-media;
+ * @return {AxjxPromise}
+ */
+export function getContentTotle(data) {
+  return ajax({
+    urlType: "leverAudience",
+    url: "/cxzx-program/new-media/content/total",
+    method: "POST",
+    data,
+  });
+}
 /**
  * 获取大数据平台内容分析 图形;
  * @return {AxjxPromise}
@@ -1107,3 +1119,31 @@ export function getUserActivity(data) {
     data,
   });
 }
+
+
+/**
+ * 已发稿件数量排行榜
+ * @return {AxjxPromise}
+ */
+export function getArticleCnt(data) {
+  return ajax({
+    urlType: "rankApi",
+    url: "/article/articleCnt",
+    method: "GET",
+    data,
+  });
+}
+
+
+/**
+ * 稿件传播量排行榜
+ * @return {AxjxPromise}
+ */
+export function getArticlePv(data) {
+  return ajax({
+    urlType: "rankApi",
+    url: "/article/articlePv",
+    method: "GET",
+    data,
+  });
+}

+ 26 - 0
src/api/newMdeiaApi.js

@@ -0,0 +1,26 @@
+import ajax from '@/utils/request.js';
+/**
+ * 获取大数据平台新媒体 栏目分析;
+ * @return {AxjxPromise}
+ */
+export function getColunmList(data) {
+  return ajax({
+    urlType: 'url2',
+    url: '/new-media/category',
+    method: 'POST',
+    data,
+  });
+}
+
+/**
+ * 获取大数据平台新媒体 内容日传播分析;
+ * @return {AxjxPromise}
+ */
+export function getContentDayList(data) {
+  return ajax({
+    urlType: 'url2',
+    url: '/new-media/content/daily',
+    method: 'POST',
+    data,
+  });
+}

+ 4 - 1
src/config/index.js

@@ -3,7 +3,8 @@ let url = "http://172.16.101.20:8762/cxzx-kuyun",
   url2 = "http://172.16.101.20:8762/cxzx-program",
   kuyunApi = "http://172.16.101.20:8762/cxzx-fm",
   guijiApi = "http://topic.smcic.net",
-  leverAudience = "http://172.16.101.20:8762";
+  leverAudience = "http://172.16.101.20:8762",
+  rankApi = "http://10.30.162.15:8082";
 let base = "";
 // let isRelease = false; //是否是线上发布版本
 if (process.env.NODE_ENV !== "development") {
@@ -12,6 +13,7 @@ if (process.env.NODE_ENV !== "development") {
   url2 = base + "/cxzx-program";
   kuyunApi = base + "/cxzx-fm";
   leverAudience = base;
+  rankApi = base;
   //   isRelease = true;
 }
 
@@ -23,6 +25,7 @@ export default {
     leverAudience,
     kuyunApi,
     guijiApi,
+    rankApi,
     adAPI: "http://topic.smcic.net",
     timeout: 60000,
     // isRelease,

+ 16 - 0
src/router/index.js

@@ -1,5 +1,6 @@
 import { createRouter, createWebHashHistory } from "vue-router";
 import countryRouter from "./country";
+import rankRouter from "./rank";
 const routes = [
   {
     path: "/",
@@ -199,6 +200,21 @@ const routes = [
     component: () =>
       import(/* webpackChunkName: "newMediaOverview" */ "../views/NMedia/ActivityUser.vue"),
   },
+  ...rankRouter,
+  //  新媒体-应用分析-内容分析
+  {
+    path: "/NMedia/column",
+    name: "column",
+    component: () =>
+      import(/* webpackChunkName: "column" */ "../views/NMedia/column/index.vue"),
+  },
+  //  新媒体-应用分析-新媒体内容日传播分析
+  {
+    path: "/NMedia/contentDay",
+    name: "contentDay",
+    component: () =>
+      import(/* webpackChunkName: "contentDay" */ "../views/NMedia/contentDay/index.vue"),
+  },
 
   countryRouter, // 全国数据
 ];

+ 18 - 0
src/router/rank.js

@@ -0,0 +1,18 @@
+const rankRouter = [
+    //   已发稿件排行
+    {
+        path: "/manuscriptIssued",
+        name: "manuscriptIssued",
+        component: () =>
+            import("../views/Ranking/ManuscriptIssued.vue"),
+    },
+    //   稿件传播量排行榜
+    {
+        path: "/ManuscriptDissemination",
+        name: "ManuscriptDissemination",
+        component: () =>
+            import("../views/Ranking/ManuscriptDissemination.vue"),
+    },
+];
+
+export default rankRouter;

+ 154 - 111
src/views/Content/index.vue

@@ -98,12 +98,31 @@
         </el-form-item>
         <el-form-item style="float: right">
           <el-button type="primary" @click="onSubmit">查询</el-button>
+          <el-button size="small" type="primary" @click="onExport">
+            导出
+          </el-button>
         </el-form-item>
       </el-form>
     </el-card>
     <br />
     <el-card class="box-card">
-      <el-row :gutter="20">
+      <div class="head" v-if="total">
+        <div v-for="(item, i) in total" :key="i + item.name" class="head-item">
+          <div>{{ item.name }}</div>
+          <div class="value">
+            <!-- oriData.total.activeUser -->
+            <countTo
+              v-if="!isNaN(item.value)"
+              :startVal="0"
+              :endVal="item.value - 0"
+              :duration="1500"
+            ></countTo>
+            <span v-else v-text="item.value"></span>
+          </div>
+        </div>
+      </div>
+      <!-- 2023年2月1号 因为下边表格同样具备top性质,所以隐藏顶部top -->
+      <el-row :gutter="20" v-if="false">
         <el-col :span="6" v-for="(v, i) in top" :key="i + v.name">
           <div class="libTitle" v-text="v.name"></div>
           <el-table
@@ -136,34 +155,20 @@
       <br />
       <div ref="regionChart"></div>
       <br />
-      <el-row>
-        <el-col :span="8">
-          <el-input
-            size="small"
-            v-model="match"
-            clearable
-            style="width: 300px"
-            placeholder="请输入内容ID或内容标题"
-            class="input-with-select"
-          >
-            <template #append>
-              <el-button @click="onSubmit">
-                <el-icon><Search /></el-icon>
-              </el-button>
-            </template>
-          </el-input>
-        </el-col>
-        <el-col :span="16">
-          <el-button
-            size="small"
-            style="float: right"
-            type="primary"
-            @click="onExport"
-          >
-            导出
+      <el-input
+        size="small"
+        v-model="match"
+        clearable
+        style="width: 300px"
+        placeholder="请输入内容ID或内容标题"
+        class="input-with-select"
+      >
+        <template #append>
+          <el-button @click="onSubmit">
+            <el-icon><Search /></el-icon>
           </el-button>
-        </el-col>
-      </el-row>
+        </template>
+      </el-input>
       <br />
       <br />
       <el-table
@@ -205,7 +210,7 @@
           align="center"
         >
           <template #default>
-            <span>{{ lastParams.app || "-" }}</span>
+            <span>{{ lastParams.app || '-' }}</span>
           </template>
         </el-table-column>
         <el-table-column
@@ -224,7 +229,7 @@
           header-align="center"
           align="center"
           sortable
-          :sort-orders="['descending', null]"
+          :sort-orders="['ascending', 'descending', null]"
           prop="cduration"
         >
           <template #default="scope">
@@ -236,7 +241,7 @@
           header-align="center"
           align="center"
           sortable
-          :sort-orders="['descending', null]"
+          :sort-orders="['ascending', 'descending', null]"
           prop="cpv"
         >
           <template #default="scope">
@@ -252,7 +257,7 @@
           header-align="center"
           align="center"
           sortable
-          :sort-orders="['descending', null]"
+          :sort-orders="['ascending', 'descending', null]"
           prop="csupport"
         >
           <template #default="scope">
@@ -268,7 +273,7 @@
           header-align="center"
           align="center"
           sortable
-          :sort-orders="['descending', null]"
+          :sort-orders="['ascending', 'descending', null]"
           prop="ccollect"
         >
           <template #default="scope">
@@ -284,7 +289,7 @@
           header-align="center"
           align="center"
           sortable
-          :sort-orders="['descending', null]"
+          :sort-orders="['ascending', 'descending', null]"
           prop="cshare"
         >
           <template #default="scope">
@@ -300,7 +305,7 @@
           header-align="center"
           align="center"
           sortable
-          :sort-orders="['descending', null]"
+          :sort-orders="['ascending', 'descending', null]"
           prop="ccomments"
         >
           <template #default="scope">
@@ -316,7 +321,7 @@
           header-align="center"
           align="center"
           sortable
-          :sort-orders="['descending', null]"
+          :sort-orders="['ascending', 'descending', null]"
           prop="cuser"
         >
           <template #default="scope">
@@ -342,7 +347,7 @@
 </template>
 <script>
 // @ is an alias to /src
-import { Search } from "@element-plus/icons-vue";
+import { Search } from '@element-plus/icons-vue';
 import {
   getRule,
   getAppList,
@@ -350,19 +355,20 @@ import {
   getContentTop10,
   getContentChart,
   getContentPage,
-} from "@/api/index";
+  getContentTotle,
+} from '@/api/index';
 
-import countTo from "@/components/counto/vue-countTo.vue";
-import * as echarts from "echarts/core";
-import { LineChart } from "echarts/charts";
+import countTo from '@/components/counto/vue-countTo.vue';
+import * as echarts from 'echarts/core';
+import { LineChart } from 'echarts/charts';
 import {
   TitleComponent,
   TooltipComponent,
   GridComponent,
   ToolboxComponent,
   LegendComponent,
-} from "echarts/components";
-import { CanvasRenderer } from "echarts/renderers";
+} from 'echarts/components';
+import { CanvasRenderer } from 'echarts/renderers';
 echarts.use([
   TitleComponent,
   TooltipComponent,
@@ -373,27 +379,28 @@ echarts.use([
   LegendComponent,
 ]);
 
-import config from "@/config/index";
+import config from '@/config/index';
 let chart = undefined;
 export default {
-  name: "Content",
+  name: 'Content',
   data() {
     return {
       lastParams: {},
       table: {},
       form: {
-        app: "",
+        app: '',
         version: [],
         date: [],
-        content: "",
-        client: "",
+        content: '',
+        client: '',
       },
-      match: "",
+      match: '',
       cycle: [],
       showList: [],
       version: [],
       content: [],
       top: [],
+      total: [],
       client: [],
     };
   },
@@ -410,8 +417,8 @@ export default {
       clentli,
     } = await this.getAppListFunc();
     const keys = {
-      value: "mname",
-      label: "mname",
+      value: 'mname',
+      label: 'mname',
     };
     const clentliList = clentli.find(r => r.mdefault) || false;
     let client = clentliList ? clentliList.mcode.toString() : -1;
@@ -422,21 +429,21 @@ export default {
       clentli,
       clentV,
       {
-        value: "mcode",
-        label: "mname",
+        value: 'mcode',
+        label: 'mname',
       },
       true
     );
     this.form = {
       //   app: (this.cycle[0] || { value: "" }).value,
-      app: "起点新闻",
-      version: [(this.version[0] || { value: "" }).value],
+      app: '起点新闻',
+      version: [(this.version[0] || { value: '' }).value],
       content: -1,
       date: [new Date(Date.now() - 604800000), new Date(Date.now() - 86400000)],
       client,
       page: 1,
       size: 20,
-      sortBy: "",
+      sortBy: '',
     };
     this.onSubmit();
   },
@@ -444,16 +451,26 @@ export default {
   methods: {
     tableChange(e) {
       this.form.page = 1;
-      this.form.sortBy = e.column ? e.column.property : "";
-      this.lastParams.sortBy = e.column ? e.column.property : "";
-      this.lastParams.page = 1;
+      this.form.sortBy = e.column ? e.column.property : '';
+      this.lastParams.sortBy = this.form.sortBy;
+      this.lastParams.page = this.form.page;
+      const sortLibType = {
+        descending: 1,
+        ascending: 0,
+      };
+      if (e.order) {
+        this.form.order = sortLibType[e.order];
+      } else {
+        this.form.order = '';
+      }
+      this.lastParams.order = this.form.order;
       getContentPage(this.lastParams).then(r => (this.table = r || {}));
     },
     verifyList(list, verify, obj, more) {
       if (!obj) return;
       let li = list || [];
       const out = [];
-      more && out.push({ value: -1, label: "不限" });
+      more && out.push({ value: -1, label: '不限' });
       for (let i = 0; i < li.length; i++) {
         const v = li[i];
         if (verify.length !== 0 && !verify[v.mcode]) continue;
@@ -480,8 +497,18 @@ export default {
         match: this.match,
         sortBy: this.form.sortBy,
         lib: this.form.client == -1 ? undefined : this.form.client,
+        order: this.form.order
       };
       getContentPage(this.lastParams).then(r => (this.table = r || {}));
+      getContentTotle({
+        start: this.FormData(this.form.date[0]),
+        end: this.FormData(this.form.date[1]),
+        app: this.form.app,
+        version: this.form.version == -1 ? undefined : this.form.version,
+        lib: this.form.client == -1 ? undefined : this.form.client,
+      }).then(r => {
+        this.total = r || [];
+      });
       getContentTop10({
         app: this.form.app,
         start: this.FormData(this.form.date[0]),
@@ -512,7 +539,7 @@ export default {
                 const v = this.top[i];
                 if (!valueList[i]) valueList[i] = [];
                 if (titles.length < this.top.length)
-                  titles.push(v.name.split("T")[0]);
+                  titles.push(v.name.split('T')[0]);
                 valueList[i].push(item[v.target] || 0);
               }
             }
@@ -534,14 +561,14 @@ export default {
       });
       chart.setOption({
         tooltip: {
-          trigger: "axis",
+          trigger: 'axis',
           confine: true,
         },
         toolbox: {
           feature: {
             saveAsImage: {
-              type: "jpg",
-              name: "内容分析-" + this.form.app,
+              type: 'jpg',
+              name: '内容分析-' + this.form.app,
             },
           },
         },
@@ -549,27 +576,27 @@ export default {
           data: title,
         },
         grid: {
-          left: "3%",
-          right: "4%",
-          bottom: "3%",
+          left: '3%',
+          right: '4%',
+          bottom: '3%',
           containLabel: true,
         },
         xAxis: {
-          type: "category",
+          type: 'category',
           boundaryGap: true,
           data: keyList,
         },
         yAxis: {
-          type: "value",
+          type: 'value',
           scale: true,
           minInterval: 1,
           axisLabel: {
             formatter(v) {
               let val = v;
               if (val >= 100000000) {
-                val = (val / 100000000).toFixed(2) + "亿";
+                val = (val / 100000000).toFixed(2) + '亿';
               } else if (val >= 10000) {
-                val = (val / 10000).toFixed(2) + "万";
+                val = (val / 10000).toFixed(2) + '万';
               }
               return val;
             },
@@ -583,7 +610,7 @@ export default {
             lineStyle: {
               width: 1,
             },
-            type: "line",
+            type: 'line',
             smooth: true,
           };
         }),
@@ -600,17 +627,18 @@ export default {
         contentli = [];
       let clentV = { length: 0 },
         clentli = [];
-      let prvList = r.output.data.prvRolectrl || [];
+      let prvList =
+        (r.output && r.output.data && r.output.data.prvRolectrl) || [];
       for (let i = 0; i < prvList.length; i++) {
         const v = prvList[i];
-        if (v.controlid == "RMT_SOURCE")
+        if (v.controlid == 'RMT_SOURCE')
           (source[v.detid] = true), (source.length = source.length + 1);
-        if (v.controlid == "APP_VERSION")
+        if (v.controlid == 'APP_VERSION')
           (appV[v.detid] = true), (appV.length = appV.length + 1);
-        if (v.controlid == "content_TYPE")
+        if (v.controlid == 'content_TYPE')
           (contentV[v.detid] = true), (contentV.length = contentV.length + 1);
       }
-      if (li.status === "0") appli = li.output.data || [];
+      if (li.status === '0') appli = li.output.data || [];
       if (appVersion.length) appVLi = appVersion || [];
       if (contentList.length) contentli = contentList || [];
       if (clientList.length) clentli = clientList || [];
@@ -627,46 +655,46 @@ export default {
     },
     async getAppListOri() {
       const roleid = JSON.parse(
-        window.parent.localStorage.userinfo || "{}"
+        window.parent.localStorage.userinfo || '{}'
       ).roleid;
       const r = await getRule({
-        db: "authplat",
-        exportMark: "0",
+        db: 'authplat',
+        exportMark: '0',
         menuid: 399,
         roleid,
       });
-      const defaultAppName = "起点新闻";
+      const defaultAppName = '起点新闻';
       // 端列表
       const clientList = await getSearchData({
-        gcode: "CLIENT_TYPE",
+        gcode: 'CLIENT_TYPE',
         source: defaultAppName,
       });
       //   应用列表
 
       const li = await getAppList({
-        exportMark: "0",
-        gcode: "SOURCE",
+        exportMark: '0',
+        gcode: 'SOURCE',
         pageid: 1,
         pagesize: 1000,
       });
       //   应用版本列表
       const appVersion = await getSearchData({
-        gcode: "APP_VERSION",
+        gcode: 'APP_VERSION',
         source: defaultAppName,
       });
       // 端列表
       let contentList = await getAppList({
-        exportMark: "0",
-        gcode: "CONTENT_TYPE",
+        exportMark: '0',
+        gcode: 'CONTENT_TYPE',
         pageid: 1,
         pagesize: 1000,
       });
       contentList =
-        contentList.status == "0" ? contentList.output.data || [] : [];
+        contentList.status == '0' ? contentList.output.data || [] : [];
       return { r, li, appVersion, contentList, clientList };
     },
     disabledDate(time) {
-      const first = new Date("2021-06-21 00:00:00");
+      const first = new Date('2021-06-21 00:00:00');
       return (
         time.getTime() > Date.now() - 86400000 ||
         time.getTime() < first.getTime()
@@ -676,9 +704,9 @@ export default {
       const d = new Date(date || Date.now() - 86400000);
       const year = d.getFullYear();
       const month =
-        d.getMonth() <= 8 ? "0" + (d.getMonth() + 1) : d.getMonth() + 1;
-      const day = d.getDate() <= 9 ? "0" + d.getDate() : d.getDate();
-      return [year, month, day].join("-");
+        d.getMonth() <= 8 ? '0' + (d.getMonth() + 1) : d.getMonth() + 1;
+      const day = d.getDate() <= 9 ? '0' + d.getDate() : d.getDate();
+      return [year, month, day].join('-');
     },
     timeFormat(t) {
       const Time = t || 0;
@@ -686,40 +714,42 @@ export default {
       let hour = (Time - mH) / 3600;
       let min = (mH - (mH % 60)) / 60;
       let son = Number(mH % 60).toFixed(0);
-      hour = hour <= 9 ? "0" + hour : hour;
-      min = min <= 9 ? "0" + min : min;
-      son = son <= 9 ? "0" + son : son;
+      hour = hour <= 9 ? '0' + hour : hour;
+      min = min <= 9 ? '0' + min : min;
+      son = son <= 9 ? '0' + son : son;
       let out = [];
       if (hour * 1 > 0) out.push(hour);
       out.push(...[min, son]);
-      return out.join(":");
+      return out.join(':');
     },
     change() {
       const roleid = JSON.parse(
-        window.parent.localStorage.userinfo || "{}"
+        window.parent.localStorage.userinfo || '{}'
       ).roleid;
       const appV = {
         length: 0,
       };
       getRule({
-        db: "authplat",
-        exportMark: "0",
+        db: 'authplat',
+        exportMark: '0',
         menuid: 399,
         roleid,
       }).then(rule => {
-        let prvList = rule.output.data.prvRolectrl || [];
+        let prvList =
+          (rule.output && rule.output.data && rule.output.data.prvRolectrl) ||
+          [];
         for (let i = 0; i < prvList.length; i++) {
           const v = prvList[i];
-          if (v.controlid == "APP_VERSION")
+          if (v.controlid == 'APP_VERSION')
             (appV[v.detid] = true), (appV.length = appV.length + 1);
         }
         getSearchData({
-          gcode: "APP_VERSION",
+          gcode: 'APP_VERSION',
           source: this.form.app,
         }).then(r => {
           let version = [
             {
-              label: "不限",
+              label: '不限',
               value: -1,
             },
           ];
@@ -759,18 +789,18 @@ export default {
         : undefined;
       const app = this.lastParams.app || this.form.app;
       const version =
-        this.form.version == -1 ? undefined : this.form.version.join(",");
+        this.form.version == -1 ? undefined : this.form.version.join(',');
       const contentType = this.lastParams.contentType || this.form.contentType;
       let url =
         config.base.leverAudience +
-        "/cxzx-program/new-media/content/export?start=" +
+        '/cxzx-program/new-media/content/export?start=' +
         S +
-        "&end=" +
+        '&end=' +
         E +
-        "&app=" +
+        '&app=' +
         app;
-      version && (url += "&version=" + version);
-      contentType && (url += "&contentType=" + contentType);
+      version && (url += '&version=' + version);
+      contentType && (url += '&contentType=' + contentType);
       window.open(url);
     },
   },
@@ -794,7 +824,20 @@ export default {
 .btn-prev i {
   margin: 0 auto;
 }
-.caret-wrapper .ascending {
-  display: none;
+.head {
+  display: flex;
+  font-weight: 500;
+}
+.head .head-item {
+  flex: 1;
+  text-align: center;
+  font-size: 0.8em;
+  border-top: 3px solid #fff;
+  padding-top: 10px;
+}
+.head .value {
+  margin: 15px 0;
+  color: #396fff;
+  font-size: 25px;
 }
 </style>

+ 15 - 10
src/views/Department/index.vue

@@ -90,7 +90,9 @@
                 :prop="item.key"
                 :label="item.label"
                 :sortable="item.sortable"
-                :sort-orders="item.sortable ? ['descending', null] : []"
+                :sort-orders="
+                  item.sortable ? ['ascending', 'descending', null] : []
+                "
               >
                 <template #default="scope">
                   {{
@@ -124,7 +126,9 @@
                 :prop="item.key"
                 :label="item.label"
                 :sortable="item.sortable"
-                :sort-orders="item.sortable ? ['descending', null] : []"
+                :sort-orders="
+                  item.sortable ? ['ascending', 'descending', null] : []
+                "
               >
                 <template #default="scope">
                   {{
@@ -163,6 +167,7 @@ import { formatter } from '@/utils/tool';
 import config from '@/config/index';
 let tableDataListOri = [];
 let sort = null;
+let sortLib = null;
 export default {
   name: 'RealData',
   data() {
@@ -257,6 +262,7 @@ export default {
       this.form = p;
       this.$refs.table1.clearSort();
       this.$refs.table2.clearSort();
+      sortLib = null;
       sort = null;
       this.onSubmit();
     },
@@ -273,7 +279,7 @@ export default {
         [startd.year, startd.month, startd.day].join('-') +
         '&end=' +
         [starte.year, starte.month, starte.day].join('-');
-      if (this.formRael.sort) url += "&sort=" + this.formRael.sort;
+      if (this.formRael.sort) url += '&sort=' + this.formRael.sort;
       window.open(url);
     },
     disabledDate(time) {
@@ -281,6 +287,7 @@ export default {
     },
     sort_change(type) {
       sort = type.prop;
+      sortLib = type.order;
       this.onSubmit();
     },
     onSubmit() {
@@ -351,6 +358,11 @@ export default {
         userId: loginname,
       };
       sort && (p.sort = sort);
+      const sortLibType = {
+        descending: 1,
+        ascending: 0,
+      };
+      sortLib && (p.order = sortLibType[sortLib]);
       return p;
     },
   },
@@ -441,11 +453,4 @@ export default {
   border-color: #fb7299;
   color: #fff;
 }
-
-.program .ascending {
-  opacity: 0;
-}
-.program .caret-wrapper {
-  top: -3px;
-}
 </style>

+ 2 - 2
src/views/LiveRoom/index.vue

@@ -382,7 +382,7 @@ export default {
         appVLi = [];
       let appC = { length: 0 },
         appCLi = [];
-      let prvList = r.output.data.prvRolectrl || [];
+      let prvList = r.output && r.output.data && r.output.data.prvRolectrl || [];
       for (let i = 0; i < prvList.length; i++) {
         const v = prvList[i];
         if (v.controlid == "RMT_SOURCE")
@@ -477,7 +477,7 @@ export default {
         menuid: 399,
         roleid,
       }).then(rule => {
-        let prvList = rule.output.data.prvRolectrl || [];
+        let prvList = rule.output && rule.output.data && rule.output.data.prvRolectrl || [];
         for (let i = 0; i < prvList.length; i++) {
           const v = prvList[i];
           if (v.controlid == "APP_VERSION")

+ 408 - 0
src/views/NMedia/column/index.vue

@@ -0,0 +1,408 @@
+<template>
+  <div class="Content">
+    <el-breadcrumb separator-class="el-icon-arrow-right">
+      <el-breadcrumb-item>新媒体</el-breadcrumb-item>
+      <el-breadcrumb-item>应用分析</el-breadcrumb-item>
+      <el-breadcrumb-item>栏目分析</el-breadcrumb-item>
+    </el-breadcrumb>
+    <el-card class="box-card">
+      <el-form
+        ref="form"
+        :model="form"
+        size="small"
+        :inline="true"
+        label-width="120px"
+        class="demo-form-inline"
+      >
+        <el-form-item label="日期">
+          <el-date-picker
+            v-if="form.date.length"
+            v-model="form.date"
+            type="daterange"
+            :disabled-date="time => disabledDate(time)"
+            range-separator="-"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            :clearable="false"
+          >
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="应用">
+          <el-select
+            v-model="form.app"
+            placeholder="请选择时段"
+            @change="change"
+          >
+            <el-option
+              v-for="item in cycle"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+              :disabled="item.disabled"
+            >
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="版本">
+          <el-select
+            filterable
+            multiple
+            collapse-tags
+            clearable
+            v-model="form.version"
+            placeholder="请选择版本"
+            @change="changeversion"
+          >
+            <el-option
+              v-for="item in version"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+              :disabled="item.disabled"
+            >
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item style="float: right">
+          <el-button type="primary" @click="onSubmit">查询</el-button>
+          <el-button
+            size="small"
+            style="margin-left: 0.5em"
+            type="primary"
+            @click="onExport"
+          >
+            导出
+          </el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+    <br />
+    <el-card class="box-card">
+      <div class="head" v-if="table.total">
+        <div
+          v-for="(item, i) in table.total"
+          :key="i + item.name"
+          class="head-item"
+        >
+          <div>{{ item.name }}</div>
+          <div class="value">
+            <!-- oriData.total.activeUser -->
+            <countTo
+              v-if="!isNaN(item.value)"
+              :startVal="0"
+              :endVal="item.value - 0"
+              :duration="1500"
+            ></countTo>
+            <span v-else v-text="item.value"></span>
+          </div>
+        </div>
+      </div>
+      <el-table
+        :data="table.list || []"
+        style="width: 100%"
+        :header-cell-style="{
+          backgroundColor: '#f4f5f7',
+          color: '#606266',
+        }"
+      >
+        <el-table-column
+          show-overflow-tooltip
+          label="应用名称"
+          header-align="center"
+          align="center"
+        >
+          <template #default>
+            <span>{{ lastParams.app || '-' }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column
+          label="栏目名称"
+          header-align="center"
+          align="center"
+          prop="channelName"
+        >
+        </el-table-column>
+        <el-table-column
+          label="累计访问次数"
+          header-align="center"
+          align="center"
+          prop="pv"
+        >
+          <template #default="scope">
+            <countTo
+              :startVal="scope.row.pv || 0"
+              :endVal="scope.row.pv || 0"
+              :duration="100"
+            ></countTo>
+          </template>
+        </el-table-column>
+        <el-table-column
+          label="累计访问用户数"
+          header-align="center"
+          align="center"
+          prop="uv"
+        >
+          <template #default="scope">
+            <countTo
+              :startVal="scope.row.uv || 0"
+              :endVal="scope.row.uv || 0"
+              :duration="100"
+            ></countTo>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-card>
+  </div>
+</template>
+<script>
+// @ is an alias to /src
+import { getRule, getAppList, getSearchData } from '@/api/index';
+import { getColunmList } from '@/api/newMdeiaApi';
+
+import countTo from '@/components/counto/vue-countTo.vue';
+
+import config from "@/config/index";
+export default {
+  name: 'Version',
+  data() {
+    return {
+      lastParams: {},
+      table: {},
+      numType: 'newUser',
+      form: {
+        app: '',
+        version: [],
+        date: [],
+      },
+      cycle: [],
+      showList: [],
+      version: [],
+    };
+  },
+  async mounted() {
+    const { source, appV, appli, appVLi } = await this.getAppListFunc();
+    const keys = {
+      value: 'mname',
+      label: 'mname',
+    };
+    this.cycle = this.verifyList(appli, source, keys, false);
+    this.version = this.verifyList(appVLi, appV, keys, true);
+    this.form = {
+      //   app: (this.cycle[0] || { value: "" }).value,
+      app: '起点新闻',
+      version: [(this.version[0] || { value: '' }).value],
+      date: [new Date(Date.now() - 604800000), new Date(Date.now() - 86400000)],
+    };
+
+    this.onSubmit();
+  },
+  computed: {},
+  methods: {
+    verifyList(list, verify, obj, more) {
+      if (!obj) return;
+      let li = list || [];
+      const out = [];
+      more && out.push({ value: -1, label: '不限' });
+      for (let i = 0; i < li.length; i++) {
+        const v = li[i];
+        if (verify.length !== 0 && !verify[v.mcode]) continue;
+        out.push({
+          value: v[obj.value],
+          label: v[obj.label],
+        });
+      }
+      return out;
+    },
+    selectNumType(type) {
+      this.numType = type;
+    },
+    onSubmit() {
+      this.lastParams = {
+        app: this.form.app,
+        start: this.FormData(this.form.date[0]),
+        end: this.FormData(this.form.date[1]),
+        version: this.form.version == -1 ? undefined : this.form.version,
+      };
+      getColunmList(this.lastParams).then(r => {
+        this.table = r || { list: [], total: [] };
+      });
+    },
+    async getAppListFunc() {
+      const { r, li, appVersion } = await this.getAppListOri();
+      let source = { length: 0 },
+        appli = [];
+      let appV = { length: 0 },
+        appVLi = [];
+      let prvList =
+        (r.output && r.output.data && r.output.data.prvRolectrl) || [];
+      for (let i = 0; i < prvList.length; i++) {
+        const v = prvList[i];
+        if (v.controlid == 'RMT_SOURCE')
+          (source[v.detid] = true), (source.length = source.length + 1);
+        if (v.controlid == 'APP_VERSION')
+          (appV[v.detid] = true), (appV.length = appV.length + 1);
+      }
+      if (li.status === '0') appli = li.output.data || [];
+      if (appVersion.length) appVLi = appVersion || [];
+      return {
+        source,
+        appV,
+        appli,
+        appVLi,
+      };
+    },
+    async getAppListOri() {
+      const roleid = JSON.parse(
+        window.parent.localStorage.userinfo || '{}'
+      ).roleid;
+      const r = await getRule({
+        db: 'authplat',
+        exportMark: '0',
+        menuid: 399,
+        roleid,
+      });
+      //   应用列表
+
+      const li = await getAppList({
+        exportMark: '0',
+        gcode: 'SOURCE',
+        pageid: 1,
+        pagesize: 1000,
+      });
+      const defaultAppName = '起点新闻';
+      //   应用版本列表
+      const appVersion = await getSearchData({
+        gcode: 'APP_VERSION',
+        source: defaultAppName,
+      });
+      return { r, li, appVersion };
+    },
+    disabledDate(time) {
+      const first = new Date('2021-06-21 00:00:00');
+      return (
+        time.getTime() > Date.now() - 86400000 ||
+        time.getTime() < first.getTime()
+      );
+    },
+    FormData(date) {
+      const d = new Date(date || Date.now() - 86400000);
+      const year = d.getFullYear();
+      const month =
+        d.getMonth() <= 8 ? '0' + (d.getMonth() + 1) : d.getMonth() + 1;
+      const day = d.getDate() <= 9 ? '0' + d.getDate() : d.getDate();
+      return [year, month, day].join('-');
+    },
+    change() {
+      const roleid = JSON.parse(
+        window.parent.localStorage.userinfo || '{}'
+      ).roleid;
+      const appV = {
+        length: 0,
+      };
+      getRule({
+        db: 'authplat',
+        exportMark: '0',
+        menuid: 399,
+        roleid,
+      }).then(rule => {
+        let prvList =
+          (rule.output && rule.output.data && rule.output.data.prvRolectrl) ||
+          [];
+        for (let i = 0; i < prvList.length; i++) {
+          const v = prvList[i];
+          if (v.controlid == 'APP_VERSION')
+            (appV[v.detid] = true), (appV.length = appV.length + 1);
+        }
+        getSearchData({
+          gcode: 'APP_VERSION',
+          source: this.form.app,
+        }).then(r => {
+          let version = [
+            {
+              label: '不限',
+              value: -1,
+            },
+          ];
+          r.map(v => {
+            if ((appV.length && appV[v.mcode]) || appV.length === 0)
+              version.push({
+                value: v.mname,
+                label: v.mname,
+              });
+          });
+          this.version = version;
+          this.form = {
+            ...this.form,
+            version: [-1],
+          };
+        });
+      });
+    },
+    changeversion(v) {
+      if (!v.length) return (this.form.version = [-1]);
+      const last = v[v.length - 1];
+      if (last == -1) return (this.form.version = [-1]);
+      let ver = [];
+      for (let i = 0; i < v.length; i++) {
+        const element = v[i];
+        if (element == -1) continue;
+        ver.push(element);
+      }
+      this.form.version = ver;
+    },
+    onExport(){
+      const S = this.form.date[0]
+        ? this.FormData(this.form.date[0])
+        : undefined;
+      const E = this.form.date[1]
+        ? this.FormData(this.form.date[1])
+        : undefined;
+      const app = this.lastParams.app || this.form.app;
+      const version =
+        this.form.version == -1 ? undefined : this.form.version.join(',');
+      let url =
+        config.base.url2 +
+        '/new-media/category/export?start=' +
+        S +
+        '&end=' +
+        E +
+        '&app=' +
+        app;
+      version && (url += '&version=' + version);
+      window.open(url);
+    }
+  },
+  components: {
+    countTo,
+  },
+};
+</script>
+
+<style>
+.Content {
+  margin: 10px 15px;
+}
+.btn-next i,
+.btn-prev i {
+  margin: 0 auto;
+}
+.caret-wrapper .ascending {
+  display: none;
+}
+.head {
+  display: flex;
+  font-weight: 500;
+}
+.head .head-item {
+  flex: 1;
+  text-align: center;
+  font-size: 0.8em;
+  border-top: 3px solid #fff;
+  padding-top: 10px;
+}
+.head .value {
+  margin: 15px 0;
+  color: #396fff;
+  font-size: 25px;
+}
+</style>

+ 416 - 0
src/views/NMedia/contentDay/index.vue

@@ -0,0 +1,416 @@
+<template>
+  <div class="Content">
+    <el-breadcrumb separator-class="el-icon-arrow-right">
+      <el-breadcrumb-item>新媒体</el-breadcrumb-item>
+      <el-breadcrumb-item>应用分析</el-breadcrumb-item>
+      <el-breadcrumb-item>内容日传播分析</el-breadcrumb-item>
+    </el-breadcrumb>
+    <el-card class="box-card">
+      <el-form
+        ref="form"
+        :model="form"
+        size="small"
+        :inline="true"
+        label-width="120px"
+        class="demo-form-inline"
+      >
+        <el-form-item label="日期">
+          <el-date-picker
+            v-if="form.date.length"
+            v-model="form.date"
+            type="daterange"
+            :disabled-date="time => disabledDate(time)"
+            range-separator="-"
+            start-placeholder="开始日期"
+            end-placeholder="结束日期"
+            :clearable="false"
+          >
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="应用">
+          <el-select
+            v-model="form.app"
+            placeholder="请选择时段"
+            @change="change"
+          >
+            <el-option
+              v-for="item in cycle"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+              :disabled="item.disabled"
+            >
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="版本">
+          <el-select
+            filterable
+            multiple
+            collapse-tags
+            clearable
+            v-model="form.version"
+            placeholder="请选择版本"
+            @change="changeversion"
+          >
+            <el-option
+              v-for="item in version"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+              :disabled="item.disabled"
+            >
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item style="float: right">
+          <el-button type="primary" @click="onSubmit">查询</el-button>
+          <el-button
+            size="small"
+            style="margin-left: 0.5em"
+            type="primary"
+            @click="onExport"
+          >
+            导出
+          </el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+    <br />
+    <el-card class="box-card">
+      <el-table
+        :data="table || []"
+        style="width: 100%"
+        :header-cell-style="{
+          backgroundColor: '#f4f5f7',
+          color: '#606266',
+        }"
+      >
+        <el-table-column
+          show-overflow-tooltip
+          label="应用名称"
+          header-align="center"
+          align="center"
+        >
+          <template #default>
+            <span>{{ lastParams.app || '-' }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column
+          show-overflow-tooltip
+          label="日期"
+          header-align="center"
+          align="center"
+          prop="dtf"
+        >
+        </el-table-column>
+        <el-table-column
+          label="累计访问次数"
+          header-align="center"
+          align="center"
+          prop="pv"
+        >
+          <template #default="scope">
+            <countTo
+              :startVal="scope.row.pv || 0"
+              :endVal="scope.row.pv || 0"
+              :duration="100"
+            ></countTo>
+          </template>
+        </el-table-column>
+        <el-table-column
+          label="累计访问用户数"
+          header-align="center"
+          align="center"
+          prop="uv"
+        >
+          <template #default="scope">
+            <countTo
+              :startVal="scope.row.uv || 0"
+              :endVal="scope.row.uv || 0"
+              :duration="100"
+            ></countTo>
+          </template>
+        </el-table-column>
+        <el-table-column
+          label="日访问最高稿件"
+          header-align="center"
+          align="center"
+        >
+          <el-table-column
+            prop="title"
+            header-align="center"
+            align="center"
+            show-overflow-tooltip
+            label="标题"
+          />
+          <el-table-column
+            label="浏览量"
+            header-align="center"
+            align="center"
+            prop="cpv"
+          >
+            <template #default="scope">
+              <countTo
+                :startVal="scope.row.cpv || 0"
+                :endVal="scope.row.cpv || 0"
+                :duration="100"
+              ></countTo>
+            </template>
+          </el-table-column>
+          <el-table-column
+            label="阅读量"
+            header-align="center"
+            align="center"
+            prop="cuser"
+          >
+            <template #default="scope">
+              <countTo
+                :startVal="scope.row.cuser || 0"
+                :endVal="scope.row.cuser || 0"
+                :duration="100"
+              ></countTo>
+            </template>
+          </el-table-column>
+        </el-table-column>
+      </el-table>
+    </el-card>
+  </div>
+</template>
+<script>
+// @ is an alias to /src
+import { getRule, getAppList, getSearchData } from '@/api/index';
+import { getContentDayList } from '@/api/newMdeiaApi';
+
+import countTo from '@/components/counto/vue-countTo.vue';
+
+import config from '@/config/index';
+export default {
+  name: 'Version',
+  data() {
+    return {
+      lastParams: {},
+      table: [],
+      numType: 'newUser',
+      form: {
+        app: '',
+        version: [],
+        date: [],
+      },
+      cycle: [],
+      showList: [],
+      version: [],
+    };
+  },
+  async mounted() {
+    const { source, appV, appli, appVLi } = await this.getAppListFunc();
+    const keys = {
+      value: 'mname',
+      label: 'mname',
+    };
+    this.cycle = this.verifyList(appli, source, keys, false);
+    this.version = this.verifyList(appVLi, appV, keys, true);
+    this.form = {
+      //   app: (this.cycle[0] || { value: "" }).value,
+      app: '起点新闻',
+      version: [(this.version[0] || { value: '' }).value],
+      date: [new Date(Date.now() - 604800000), new Date(Date.now() - 86400000)],
+    };
+    this.onSubmit();
+  },
+  computed: {},
+  methods: {
+    verifyList(list, verify, obj, more) {
+      if (!obj) return;
+      let li = list || [];
+      const out = [];
+      more && out.push({ value: -1, label: '不限' });
+      for (let i = 0; i < li.length; i++) {
+        const v = li[i];
+        if (verify.length !== 0 && !verify[v.mcode]) continue;
+        out.push({
+          value: v[obj.value],
+          label: v[obj.label],
+        });
+      }
+      return out;
+    },
+    onSubmit() {
+      this.lastParams = {
+        app: this.form.app,
+        start: this.FormData(this.form.date[0]),
+        end: this.FormData(this.form.date[1]),
+        version: this.form.version == -1 ? undefined : this.form.version,
+      };
+      getContentDayList(this.lastParams).then(r => {
+        this.table = r || {};
+      });
+    },
+    async getAppListFunc() {
+      const { r, li, appVersion } = await this.getAppListOri();
+      let source = { length: 0 },
+        appli = [];
+      let appV = { length: 0 },
+        appVLi = [];
+      let prvList =
+        (r.output && r.output.data && r.output.data.prvRolectrl) || [];
+      for (let i = 0; i < prvList.length; i++) {
+        const v = prvList[i];
+        if (v.controlid == 'RMT_SOURCE')
+          (source[v.detid] = true), (source.length = source.length + 1);
+        if (v.controlid == 'APP_VERSION')
+          (appV[v.detid] = true), (appV.length = appV.length + 1);
+      }
+      if (li.status === '0') appli = li.output.data || [];
+      if (appVersion.length) appVLi = appVersion || [];
+      return {
+        source,
+        appV,
+        appli,
+        appVLi,
+      };
+    },
+    async getAppListOri() {
+      const roleid = JSON.parse(
+        window.parent.localStorage.userinfo || '{}'
+      ).roleid;
+      const r = await getRule({
+        db: 'authplat',
+        exportMark: '0',
+        menuid: 399,
+        roleid,
+      });
+      //   应用列表
+
+      const li = await getAppList({
+        exportMark: '0',
+        gcode: 'SOURCE',
+        pageid: 1,
+        pagesize: 1000,
+      });
+      const defaultAppName = '起点新闻';
+      //   应用版本列表
+      const appVersion = await getSearchData({
+        gcode: 'APP_VERSION',
+        source: defaultAppName,
+      });
+      return { r, li, appVersion };
+    },
+    disabledDate(time) {
+      const first = new Date('2021-06-21 00:00:00');
+      return (
+        time.getTime() > Date.now() - 86400000 ||
+        time.getTime() < first.getTime()
+      );
+    },
+    FormData(date) {
+      const d = new Date(date || Date.now() - 86400000);
+      const year = d.getFullYear();
+      const month =
+        d.getMonth() <= 8 ? '0' + (d.getMonth() + 1) : d.getMonth() + 1;
+      const day = d.getDate() <= 9 ? '0' + d.getDate() : d.getDate();
+      return [year, month, day].join('-');
+    },
+    change() {
+      const roleid = JSON.parse(
+        window.parent.localStorage.userinfo || '{}'
+      ).roleid;
+      const appV = {
+        length: 0,
+      };
+      getRule({
+        db: 'authplat',
+        exportMark: '0',
+        menuid: 399,
+        roleid,
+      }).then(rule => {
+        let prvList =
+          (rule.output && rule.output.data && rule.output.data.prvRolectrl) ||
+          [];
+        for (let i = 0; i < prvList.length; i++) {
+          const v = prvList[i];
+          if (v.controlid == 'APP_VERSION')
+            (appV[v.detid] = true), (appV.length = appV.length + 1);
+        }
+        getSearchData({
+          gcode: 'APP_VERSION',
+          source: this.form.app,
+        }).then(r => {
+          let version = [
+            {
+              label: '不限',
+              value: -1,
+            },
+          ];
+          r.map(v => {
+            if ((appV.length && appV[v.mcode]) || appV.length === 0)
+              version.push({
+                value: v.mname,
+                label: v.mname,
+              });
+          });
+          this.version = version;
+          this.form = {
+            ...this.form,
+            version: [-1],
+          };
+        });
+      });
+    },
+    changeversion(v) {
+      if (!v.length) return (this.form.version = [-1]);
+      const last = v[v.length - 1];
+      if (last == -1) return (this.form.version = [-1]);
+      let ver = [];
+      for (let i = 0; i < v.length; i++) {
+        const element = v[i];
+        if (element == -1) continue;
+        ver.push(element);
+      }
+      this.form.version = ver;
+    },
+    onExport() {
+      const S = this.form.date[0]
+        ? this.FormData(this.form.date[0])
+        : undefined;
+      const E = this.form.date[1]
+        ? this.FormData(this.form.date[1])
+        : undefined;
+      const app = this.lastParams.app || this.form.app;
+      const version =
+        this.form.version == -1 ? undefined : this.form.version.join(',');
+      let url =
+        config.base.url2 +
+        '/new-media/content/daily-export?start=' +
+        S +
+        '&end=' +
+        E +
+        '&app=' +
+        app;
+      version && (url += '&version=' + version);
+      window.open(url);
+    },
+  },
+  components: {
+    countTo,
+  },
+};
+</script>
+
+<style>
+.Content {
+  margin: 10px 15px;
+}
+.libTitle {
+  color: tomato;
+  font-weight: 700;
+  font-size: 14px;
+}
+.btn-next i,
+.btn-prev i {
+  margin: 0 auto;
+}
+.caret-wrapper .ascending {
+  display: none;
+}
+</style>

+ 169 - 0
src/views/Ranking/ManuscriptDissemination.vue

@@ -0,0 +1,169 @@
+<template>
+  <div class="manuscriptIssued">
+    <el-loading></el-loading>
+    <el-breadcrumb separator-class="el-icon-arrow-right">
+      <el-breadcrumb-item>新媒体</el-breadcrumb-item>
+      <el-breadcrumb-item>用户分析</el-breadcrumb-item>
+      <el-breadcrumb-item>稿件传播量排行榜</el-breadcrumb-item>
+    </el-breadcrumb>
+    <div class="groupType">
+      <el-row class="mb-4">
+        <el-button
+          v-for="cur in tabs.btns"
+          :key="cur.value"
+          :type="cur.value == btnFocus ? 'primary' : ''"
+          @click="handleClick(cur)"
+          >{{ cur.label }}</el-button
+        >
+      </el-row>
+    </div>
+    <div class="card-rank">
+      <div>
+        <h4>分中心日榜</h4>
+        <el-table
+          :data="dayData"
+          header-row-class-name="card-tabs-header"
+          :height="tabHigh"
+        >
+          <el-table-column align="center" prop="name" label="关键词" />
+          <el-table-column align="center" prop="cnt" label="次数" />
+        </el-table>
+      </div>
+      <div>
+        <h4>分中心周榜</h4>
+        <el-table
+          :data="weekData"
+          header-row-class-name="card-tabs-header"
+          :height="tabHigh"
+        >
+          <el-table-column align="center" prop="name" label="关键词" />
+          <el-table-column align="center" prop="cnt" label="次数" />
+        </el-table>
+      </div>
+      <div>
+        <h4>分中心月榜</h4>
+        <el-table
+          :data="monthData"
+          header-row-class-name="card-tabs-header"
+          :height="tabHigh"
+        >
+          <el-table-column align="center" prop="name" label="关键词" />
+          <el-table-column align="center" prop="cnt" label="次数" />
+        </el-table>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import { getArticlePv } from "@/api/index";
+
+const ElLoading = require("element-plus/lib/el-loading/index");
+import "element-plus/lib/theme-chalk/el-loading.css";
+
+export default {
+  name: "ManuscriptDissemination",
+  data() {
+    return {
+      activeName: 1,
+      btnFocus: "center",
+      tabs: {
+        name: "稿件传播量排行榜",
+        code: 1,
+        btns: [
+          {
+            label: "分中心榜",
+            value: "center",
+          },
+          {
+            label: "人员榜",
+            value: "user",
+          },
+          {
+            label: "中心内部榜",
+            value: 2,
+          },
+          {
+            label: "部门内部人员榜",
+            value: 3,
+          },
+        ],
+      },
+      dayData: [],
+      weekData: [],
+      monthData: [],
+      tabHigh: 600,
+    };
+  },
+  mounted() {
+    this.setTableData();
+  },
+  methods: {
+    handleClick(e) {
+      this.btnFocus = e.value;
+      this.setTableData();
+    },
+    setTableData() {
+      const that = this;
+      if (!this.load) this.load = ElLoading.default.service();
+      getArticlePv({ type: this.btnFocus })
+        .then((res) => {
+          const { day, week, month } = res;
+          const len = month.length + 1;
+          that.dayData = day;
+          that.weekData = week;
+          that.monthData = month;
+          that.tabHigh = len > 15 ? 48 * len : 600;
+          that.load.close();
+        })
+        .catch((err) => {
+          that.dayData = [];
+          that.weekData = [];
+          that.monthData = [];
+          console.log("catch", err);
+        });
+    },
+  },
+};
+/*
+
+融合号粉丝量排行榜
+融合号稿件数量排行榜
+融合号稿件传播量排行榜
+素材贡献量排行榜
+直播热度排行榜
+用户停留排行榜
+*/
+</script>
+<style>
+.manuscriptIssued {
+  margin: 10px;
+}
+.card-tabs,
+.el-tabs__header {
+  padding: 0 100px;
+}
+.groupType{
+  padding: 15px 0;
+  box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.12);
+}
+.card-rank {
+  padding: 10px 15px;
+  border: 1px solid #dcdfe6;
+  box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+.card-rank > div {
+  width: 32%;
+}
+h4 {
+  text-align: left;
+  color: #e18116;
+  margin-bottom: 50px;
+  font-weight: bold;
+}
+.card-tabs-header th {
+  background: #f5f7fa !important;
+}
+</style>

+ 169 - 0
src/views/Ranking/ManuscriptIssued.vue

@@ -0,0 +1,169 @@
+<template>
+  <div class="manuscriptIssued">
+    <el-loading></el-loading>
+    <el-breadcrumb separator-class="el-icon-arrow-right">
+      <el-breadcrumb-item>新媒体</el-breadcrumb-item>
+      <el-breadcrumb-item>用户分析</el-breadcrumb-item>
+      <el-breadcrumb-item>已发稿件数量排行榜</el-breadcrumb-item>
+    </el-breadcrumb>
+    <div class="groupType">
+      <el-row class="mb-4">
+        <el-button
+          v-for="cur in tabs.btns"
+          :key="cur.value"
+          :type="cur.value == btnFocus ? 'primary' : ''"
+          @click="handleClick(cur)"
+          >{{ cur.label }}</el-button
+        >
+      </el-row>
+    </div>
+    <div class="card-rank">
+      <div>
+        <h4>分中心日榜</h4>
+        <el-table
+          :data="dayData"
+          header-row-class-name="card-tabs-header"
+          :height="tabHigh"
+        >
+          <el-table-column align="center" prop="name" label="关键词" />
+          <el-table-column align="center" prop="cnt" label="次数" />
+        </el-table>
+      </div>
+      <div>
+        <h4>分中心周榜</h4>
+        <el-table
+          :data="weekData"
+          header-row-class-name="card-tabs-header"
+          :height="tabHigh"
+        >
+          <el-table-column align="center" prop="name" label="关键词" />
+          <el-table-column align="center" prop="cnt" label="次数" />
+        </el-table>
+      </div>
+      <div>
+        <h4>分中心月榜</h4>
+        <el-table
+          :data="monthData"
+          header-row-class-name="card-tabs-header"
+          :height="tabHigh"
+        >
+          <el-table-column align="center" prop="name" label="关键词" />
+          <el-table-column align="center" prop="cnt" label="次数" />
+        </el-table>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+import { getArticleCnt } from "@/api/index";
+
+const ElLoading = require("element-plus/lib/el-loading/index");
+import "element-plus/lib/theme-chalk/el-loading.css";
+
+export default {
+  name: "ManuscriptIssued",
+  data() {
+    return {
+      activeName: 1,
+      btnFocus: "center",
+      tabs: {
+        name: "已发稿件数量排行榜",
+        code: 1,
+        btns: [
+          {
+            label: "分中心榜",
+            value: "center",
+          },
+          {
+            label: "人员榜",
+            value: "user",
+          },
+          {
+            label: "中心内部榜",
+            value: 2,
+          },
+          {
+            label: "部门内部人员榜",
+            value: 3,
+          },
+        ],
+      },
+      dayData: [],
+      weekData: [],
+      monthData: [],
+      tabHigh: 600,
+    };
+  },
+  mounted() {
+    this.setTableData();
+  },
+  methods: {
+    handleClick(e) {
+      this.btnFocus = e.value;
+      this.setTableData();
+    },
+    setTableData() {
+      const that = this;
+      if (!this.load) this.load = ElLoading.default.service();
+      getArticleCnt({ type: this.btnFocus })
+        .then((res) => {
+          const { day, week, month } = res;
+          const len = month.length + 1;
+          that.dayData = day;
+          that.weekData = week;
+          that.monthData = month;
+          that.tabHigh = len > 15 ? 48 * len : 600;
+          that.load.close();
+        })
+        .catch((err) => {
+          that.dayData = [];
+          that.weekData = [];
+          that.monthData = [];
+          console.log("catch", err);
+        });
+    },
+  },
+};
+/*
+稿件传播量排行榜
+融合号粉丝量排行榜
+融合号稿件数量排行榜
+融合号稿件传播量排行榜
+素材贡献量排行榜
+直播热度排行榜
+用户停留排行榜
+*/
+</script>
+<style>
+.manuscriptIssued {
+  margin: 10px;
+}
+.card-tabs,
+.el-tabs__header {
+  padding: 0 100px;
+}
+.groupType{
+  padding: 15px 0;
+  box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.12);
+}
+.card-rank {
+  padding: 10px 15px;
+  border: 1px solid #dcdfe6;
+  box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.12);
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+}
+.card-rank > div {
+  width: 32%;
+}
+h4 {
+  text-align: left;
+  color: #e18116;
+  margin-bottom: 50px;
+  font-weight: bold;
+}
+.card-tabs-header th {
+  background: #f5f7fa !important;
+}
+</style>

+ 10 - 8
src/views/ReportForm/ReportForm.vue

@@ -90,7 +90,7 @@
                 :prop="item.key"
                 :label="item.label"
                 :sortable="item.sortable"
-                :sort-orders="item.sortable ? ['descending', null] : []"
+                :sort-orders="item.sortable ? ['ascending','descending', null] : []"
               >
                 <template #default="scope">
                   {{
@@ -124,7 +124,7 @@
                 :prop="item.key"
                 :label="item.label"
                 :sortable="item.sortable"
-                :sort-orders="item.sortable ? ['descending', null] : []"
+                :sort-orders="item.sortable ? ['ascending','descending', null] : []"
               >
                 <template #default="scope">
                   {{
@@ -161,6 +161,7 @@ import { platformList, platformlistData, platform } from "@/api/index";
 import { formatter } from "@/utils/tool";
 import config from "@/config/index";
 let tableDataListOri = [];
+let sortLib = null;
 let sort = null;
 export default {
   name: "RealData",
@@ -256,6 +257,7 @@ export default {
       this.form = p;
       this.$refs.table1.clearSort();
       this.$refs.table2.clearSort();
+      sortLib = null;
       sort = null;
       this.onSubmit();
     },
@@ -280,6 +282,7 @@ export default {
     },
     sort_change(type) {
       sort = type.prop;
+      sortLib = type.order;
       this.onSubmit();
     },
     onSubmit() {
@@ -346,6 +349,11 @@ export default {
         match: this.form.match,
       };
       sort && (p.sort = sort);
+      const sortLibType = {
+        descending: 1,
+        ascending: 0,
+      };
+      sortLib && (p.order = sortLibType[sortLib]);
       return p;
     },
   },
@@ -439,10 +447,4 @@ export default {
 .el-table th > .cell {
   white-space: nowrap;
 }
-.program .ascending{
-    opacity: 0;
-}
-.program .caret-wrapper{
-    top: -3px;
-}
 </style>