Jelajahi Sumber

Merge branch 'gn3.2'

shanbinzhang 3 hari lalu
induk
melakukan
314817cbd0

+ 38 - 0
src/api/modules/reportV2.js

@@ -165,6 +165,44 @@ export const reportV2Interface = {
 	},
 }
 
+export const reportPushInterface = {
+	/**
+	 * 推送消息
+	 * @param {*} params ReportId   PptId
+	 * @returns 
+	 */
+	pushMsg: params => {
+		return http.post('/report/ice_msg/push',params)
+	},
+
+	/**
+	 * 接收人配置
+	 * @param {*} params ClassifyId   NotifyUsers:[]
+	 * @returns 
+	 */
+	setMsgUsers: params => {
+		return http.post('/report/ice_msg/config',params)
+	},
+
+	/**
+	 * 推送列表
+	 * @param {*} params PageSize CurrentIndex ClassifyId ClassifyType Status SendTime
+	 * @returns 
+	 */
+	getPushList:params => {
+		return http.get('/report/ice_msg/record',params)
+	},
+
+	/**
+	 * 固定某几个分类
+	 * @param {*} params 
+	 * @returns 
+	 */
+	classifyList: params => {
+		return http.get('/report/ice_msg/classify',params)
+	}
+}
+
 
 const reportlist = params => { return http.get('/report/list',params); };  //获取报告列表
 

TEMPAT SAMPAH
src/assets/img/ppt_m/view-icon-push.png


+ 9 - 0
src/routes/modules/oldRoutes.js

@@ -311,6 +311,15 @@ export default [
         meta:{
           name_en:"Report Center"
         }
+      },
+
+      {
+        path: 'reportPushList',
+        name:'推送管理',
+        component: () => import("@/views/report_manage/pushMessageList.vue"),
+        meta:{
+          name_en:"Push Manage"
+        }
       }
     ],
   },

+ 6 - 0
src/utils/buttonConfig.js

@@ -43,6 +43,10 @@ export const reportManageBtn={
     reportMange_chapter_share: 'reportMange:chapter:share',//章节分享
     reportMange_chapter_editTag: 'reportMange:chapter:editTag',//章节添加标签
     reportMange_history: 'reportManage:history',//历史记录
+
+    reportPush_setView: 'reportPush:setView',
+    reportPush_recordView: 'reportPush:recordView',
+    reportPush_setBtn: 'reportPush:setBtn',
 }
 /*
  *--------智能研报列表----------- 
@@ -197,6 +201,8 @@ export const pptPermission ={
     ppt_setShare:'ppt:setShare',//设置共享
     ppt_visible:'ppt:visible',//可见权限
     ppt_history:'ppt:history',//添加我的目录
+
+    ppt_sendMsg:'ppt:sendMsg',//推送消息/已推送消息
 }
 /*
 *--------英文PPT---------- 

+ 26 - 0
src/views/ppt_manage/newVersion/pptCatalog.vue

@@ -143,6 +143,11 @@
               <div style="margin-bottom: 4px;" class="item-title">审批时间</div>
               <div class="item-content">{{$moment(pptItem.ApproveTime).format('YYYY-MM-DD HH:mm:ss')}}</div>
             </div>
+
+            <div style="margin-bottom: 10px;">
+              <div style="margin-bottom: 4px;" class="item-title">最近一次推送时间</div>
+              <div class="item-content" v-if="pptItem.MsgSendTime">{{$moment(pptItem.MsgSendTime).format('YYYY-MM-DD HH:mm:ss')}}</div>
+            </div>
             
             <div style="display: flex;align-items: center;">
               <div class="report-state">报告状态</div>
@@ -204,6 +209,9 @@ import {pptInterface} from '@/api/api.js';
 import MergePptDialog from './components/catalog/mergePPTDialog.vue';
 // import shareUserDialog from './components/catalog/chooseShareUserDia.vue';
 import addPptBaseDia from './components/catalog/addPptBaseDia.vue';
+import {
+  reportPushInterface,
+} from '@/api/modules/reportV2.js';
 //触发window.resize,使Highcharts重绘
 const reloadPPTWid = ()=>{
   const resizeEvent = new Event('resize')
@@ -432,6 +440,7 @@ export default {
           'download':checkPermissionBtn(pptPermission.ppt_download)&&((item.State===6&&item.ReportSource===2) || item.ReportSource===1),
           'edit':checkPermissionBtn(pptPermission.ppt_save)&&item.HasAuth&&(([3,5].includes(item.State)&&item.ReportSource===2) || item.ReportSource===1),
           'delete':checkPermissionBtn(pptPermission.ppt_del)&&item.ReportSource===1&&item.AdminId===this.RoleId,
+          'push': [2,6].includes(item.State)&&checkPermissionBtn(pptPermission.ppt_sendMsg) && item.CanSendMsg
       }
 
       return toolList.filter((i)=>btnAuthMap[i.key]) 
@@ -515,6 +524,7 @@ export default {
       const handleCommand = {
         'download':this.downloadPpt,
         'delete':this.deletePPT,
+        'push':this.pushMessage
       }
       handleCommand[item.key](pptItem)
     },
@@ -571,6 +581,7 @@ export default {
         // 'copy':this.handleCopy,
         'download':this.downloadPpt,
         'delete':this.deletePPT,
+        'push':this.pushMessage
         // 'transform':this.transformPPT,
         // 'transEn':this.handleTransform
       }
@@ -595,6 +606,21 @@ export default {
       }
     },
 
+    async pushMessage(item) {
+      await this.$confirm('报告将被推送到订阅号,无法撤回,确定推送吗?','提示',{
+        type: 'warning'
+      })
+       const res = await reportPushInterface.pushMsg({ 
+        ReportId: 0,
+        PptId: item.PptId
+      })
+
+      if (res.Ret !== 200) return
+      this.$message.success(this.$t('ReportManage.smart_msg.push_success'));
+      item.MsgIsSend = 1;
+      item.MsgSendTime = res.Data.MsgSendTime;
+    },
+
     /* 目录栏收起 展开 */
     slideHandle() {
       this.isSlideLeft = !this.isSlideLeft;

+ 4 - 0
src/views/ppt_manage/newVersion/utils/config.js

@@ -676,6 +676,10 @@ export const toolList = [
         label:'编辑',
         key:'edit'
     },
+    {
+      label:'推送消息',
+      key:'push'
+    },
     // {
     //     label:'复制',
     //     key:'copy'

+ 243 - 0
src/views/report_manage/components/reportReceiveSet.vue

@@ -0,0 +1,243 @@
+<template>
+  <div class="content-box reportPush-userSet">
+    <el-tree
+      :data="list"
+      node-key="Id"
+      :props="{
+          label: 'ClassifyName',
+          children: 'Child'
+      }"
+      check-strictly
+      :empty-text="$t('Common.no_classify_msg')"
+      draggable
+      indent='76'
+      :allow-drop="canDropHandle"
+      @node-drop="dropOverHandle"
+    >
+      <div
+        class="classify-item-wrap"
+        slot-scope="{ data,node }"
+      >
+          <div>
+              <span>{{data.ClassifyName}}</span>
+              <template v-if="!data.Child||(data.Child&&!data.Child.length)">
+                <el-tag 
+                  :type="data.IceMsgUsers?'success':'danger'"
+                  size="small"
+                >{{ data.IceMsgUsers ? '已配置' : '未配置' }}</el-tag>
+              </template>
+          </div>
+
+          <div class="opt-box">
+              <span 
+                  class="editsty" 
+                  v-if="(!data.Child||(data.Child&&!data.Child.length)) && permissionBtn.isShowBtn('reportManageBtn','reportPush_setBtn')" 
+                  @click="handleOpenSetUser(data,node)"
+              >
+                配置人员
+              </span>
+          </div>
+      </div>
+    </el-tree>
+
+
+      <!-- 配置人员弹窗 -->
+    <m-dialog
+      :show.sync="isOpenSetDialog"
+      :title="$t('ReportManage.ReportList.set_tags_title')"
+      width="450px"
+    >
+      <div class="edit-tag-wrap">
+        <el-form 
+          :model="classifyForm" 
+          inline
+        >
+          <el-form-item label="报告分类">
+            <span style="margin-right: 20px">{{classifyForm.classifyName}}</span>
+          </el-form-item>
+          <el-form-item label="接收人员" prop="users">
+            <el-cascader
+              v-model="classifyForm.users"
+              ref="userRef"
+              :options="userOptions"
+              :props="{
+                value: 'NodeIdKey',
+                label: 'NodeName',
+                children: 'Children',
+                emitPath: false,
+                multiple: true,
+              }"
+              collapse-tags
+              :show-all-levels="false"
+              clearable
+              @change="checkUser"
+              filterable
+              :placeholder="this.$t('SystemManage.OperateAuth.ph_see_user')" 
+              style="width:300px"
+            />
+          </el-form-item>
+        </el-form>
+          
+          <div style="margin:30px 0;text-align:center">
+              <el-button type="primary" plain @click="isOpenSetDialog=false">{{$t('Dialog.cancel_btn')}}</el-button>
+              <el-button type="primary" @click="handleSetUser">{{$t('Dialog.confirm_btn')}}</el-button>
+          </div>
+      </div>
+    </m-dialog>
+  </div>
+</template>
+<script>
+import mDialog from '@/components/mDialog.vue';
+import { departInterence } from '@/api/modules/setApi';
+import { traverseTree } from "@/utils/commonOptions"
+import {
+  reportPushInterface
+} from '@/api/modules/reportV2.js';
+export default {
+  components: { mDialog },
+  data() {
+    return {
+      list: [],
+
+      userOptions: [],
+      isOpenSetDialog: false,
+      classifyForm: {
+        users:[],
+        classifyId: 0
+      }
+    }
+  },
+  mounted(){
+    this.getUserList();
+    this.getList()
+  },
+  methods:{
+    async getList(){
+      const res=await reportPushInterface.classifyList()
+
+      if(res.Ret!==200) return
+      this.list=res.Data.List||[]
+    },
+
+    /* 获取用户列表 */
+    async getUserList() {
+      
+      const res = await departInterence.getSystemUser();
+      if (res.Ret !== 200) return
+    
+      this.userOptions = res.Data || []
+      //遍历加上唯一的key
+      traverseTree(
+          {Children:this.userOptions},
+          {
+              childKey:'Children',
+              nodeKey:'NodeIdKey',
+              cb:(node)=>node.NodeType===3,
+              cb2:(node)=>node.NodeId+''
+          }
+      )
+      
+      this.filterTreeEmpty({Children:this.userOptions})
+    },
+
+    // 递归处理数组
+    filterTreeEmpty(arr) {
+      function dfs(node) {
+          if (Array.isArray(node.Children)) {
+              for (let child of node.Children) {
+                  dfs(child);
+              }
+              if(node.Children.length===0) delete node.Children
+          }
+          //若为叶子节点,且不为用户,禁止选中
+          if(!node.Children||!Array.isArray(node.Children)){
+              if(node.NodeType!==3) node.disabled = true
+          }
+      }
+      dfs(arr); 
+    },
+
+    handleOpenSetUser(data,node) {
+      let classifyName = '';
+
+      switch(node.level){
+        case 1:
+          classifyName = data.ClassifyName;
+          break;
+        case 2:
+          classifyName = `${node.parent.data.ClassifyName}/${data.ClassifyName}`;
+          break;
+        case 3:
+          classifyName = `${node.parent.parent.data.ClassifyName}/${node.parent.data.ClassifyName}/${data.ClassifyName}`;
+          break;
+      }
+
+      this.classifyForm = {
+        classifyId: data.Id,
+        classifyName,
+        users: data.IceMsgUsers ? data.IceMsgUsers.map(_ => String(_)) : []
+      }
+      this.isOpenSetDialog = true;
+    },
+
+    async handleSetUser() {
+      const res = await reportPushInterface.setMsgUsers({
+        ClassifyId: this.classifyForm.classifyId,
+        NotifyUsers: this.classifyForm.users.map(_ => Number(_))
+      })
+      if(res.Ret !== 200) return 
+      this.$message.success('配置成功')
+      this.isOpenSetDialog = false;
+      this.getList()
+    }
+  },
+}
+</script>
+<style scoped lang='scss'>
+.content-box{
+    padding: 20px;
+    margin-top: 20px;
+    height: calc(100vh - 260px);
+    overflow-y: auto;
+    background-color: #FFFFFF;
+    .classify-item-wrap{
+        flex: 1;
+        padding-right: 20px;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        .tag{
+            display: inline-block;
+            min-width: 76px;
+            line-height: 30px;
+            text-align: center;
+            &.open{
+                background-color: #ECF2FE;
+                color: #0052D9;
+            }
+            &.close{
+                background-color: #0052D9;
+                color: #fff;
+            }
+        }
+        .opt-box{
+            .icon-drag,.icon-set{
+                width: 16px;
+                height: 16px;
+                margin-left: 10px;
+            }
+        }
+    } 
+}
+</style>
+<style lang="scss">
+.reportPush-userSet {
+    .el-tree-node__content{
+        height: fit-content;
+        padding-top: 10px;
+        padding-bottom: 10px;
+        border-bottom: 1px solid #C8CDD9;
+    }
+
+}
+</style>

+ 200 - 0
src/views/report_manage/components/repotPushRecord.vue

@@ -0,0 +1,200 @@
+<template>
+  <div>
+    <div class="filter-cont">
+      <div>
+
+        <el-cascader
+            @change="initList"
+            :options="classifyOptions"
+            v-model="filterForm.classifyId"
+            :props="{
+              value: 'Id',
+              label: 'ClassifyName',
+              children: 'Child',
+              emitPath: false
+            }"
+            clearable
+            :placeholder="$t('ReportManage.smart_type_filtering')"
+            style="width:240px;"
+        ></el-cascader>
+
+        <el-select
+          v-model="filterForm.classifyType"
+          style="width: 200px"
+          placeholder="报告类型"
+          clearable
+          @change="initList"
+        >
+          <el-option label="研报" :value="1"/>
+          <el-option label="PPT" :value="2"/>
+        </el-select>
+
+        <el-select
+          v-model="filterForm.pushStatus"
+          style="width: 200px"
+          placeholder="推送状态"
+          clearable
+          @change="initList"
+        >
+          <el-option 
+            :label="status.label" 
+            :value="status.value" 
+            v-for="status in pushStatusOptions" 
+            :key="status.key"
+          />
+        </el-select>
+        <el-date-picker 
+            v-model="filterForm.date"
+            @change="initList"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="操作时间">
+        </el-date-picker>
+      </div>
+
+       <el-input 
+        v-model="filterForm.searchTxt" 
+        prefix-icon="el-icon-search" 
+        clearable 
+        @change="initList"
+        placeholder="报告标题" 
+        style="width:260px;margin-left: auto;"
+      />
+    </div>
+
+    <el-table
+      :data="list"
+      ref="tableRef"
+      highlight-current-row
+      border
+    >
+      <el-table-column
+        v-for="item in tableColums"
+        :key="item.label"
+        :label="item.label"
+        :width="item.widthsty"
+        :min-width="item.minwidthsty"
+        align="center"
+      >
+        <template slot-scope="scope">
+          <span 
+            v-if="item.key==='Status'"
+            :class="scope.row[item.key]===1?'successty':'deletesty'"
+          >
+            {{scope.row[item.key]===1?'推送成功':'推送失败'}}
+          </span>
+          <span v-else-if="item.key==='ClassifyType'">
+            {{scope.row[item.key]===1?'研报':'PPT'}}
+          </span>
+          <span v-else>{{ scope.row[item.key] }}</span>
+        </template>
+      </el-table-column>
+      <div slot="empty">
+        <tableNoData text="暂无推送记录" size="mini"/>
+      </div>
+    </el-table>
+
+    <div style="height:35px;margin: 20px 0;">
+      <m-page
+        :page_no="pageNo"
+        :pageSize="pageSize"
+        :total="total"
+        @handleCurrentChange="pageChange"
+      />
+    </div>
+  </div>
+</template>
+<script>
+import {
+  reportPushInterface
+} from '@/api/modules/reportV2.js';
+import mPage from '@/components/mPage.vue'
+export default {
+  components: { mPage },
+  data() {
+    return {
+      filterForm: {
+        classifyId: 0,
+        classifyType:'',
+        pushStatus: '',
+        date:'',
+        searchTxt: ''
+      },
+      classifyOptions: [],
+
+      pushStatusOptions: [
+        { label: '推送成功',value: 1 },
+        { label: '推送失败',value: 2 },
+      ],
+
+      tableColums: [
+        { label:'报告标题',key:'ReportTitle' },
+        { label:'报告分类',key:'ClassifyFullName' },
+        { label:'报告类型',key:'ClassifyType' },
+        { label:'操作人',key:'SendAdminName' },
+        { label:'接收人',key:'ReceiveAdminName' },
+        { label:'推送状态',key:'Status' },
+        { label:'操作时间',key:'CreateTime' },
+      ],
+
+      list: [],
+      total: 0,
+      pageSize: 10,
+      pageNo: 1
+    }
+  },
+  mounted(){
+    this.getclassifylist();
+    this.getList()
+  },
+  methods:{
+    pageChange(page) {
+      this.pageNo = page;
+      this.getList()
+    },
+
+    initList() {
+      this.pageChange(1)
+    },
+
+    async getList() {
+      let params = {
+        PageSize: this.pageSize,
+        CurrentIndex: this.pageNo,
+        ClassifyId: this.filterForm.classifyId,
+        ClassifyType: this.filterForm.classifyType,
+        Status: this.filterForm.pushStatus,
+        SendTime: this.filterForm.date,
+        ReportTitle: this.filterForm.searchTxt
+      }
+
+      const res = await reportPushInterface.getPushList(params)
+      if(res.Ret !== 200) return
+      
+      this.list = res.Data.List || [];
+      this.total = res.Data.Paging.Totals;
+    },
+
+    getclassifylist() {
+      //获取分类列表
+      let params = { CurrentIndex: 0, PageSize: 1000, KeyWord: "" };
+
+      reportPushInterface.classifyList(params).then((res) => {
+        if (res.Ret == 200 && Array.isArray(res.Data.List)) {
+          this.classifyOptions = res.Data.List||[];
+          
+        }
+      });
+    },
+  },
+}
+</script>
+<style scoped lang='scss'>
+.filter-cont {
+  margin-bottom: 10px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  flex-wrap: wrap;
+}
+</style>

+ 76 - 0
src/views/report_manage/pushMessageList.vue

@@ -0,0 +1,76 @@
+<template>
+  <div class="report-push-page">
+    <div class="top">
+      <div 
+        :class="['tab-item',{ 'act': item.key===defaultTab }]" 
+        v-for="item in tabs" 
+        :key="item.key"
+        @click="defaultTab=item.key"
+      >
+        {{item.label}}
+      </div>
+    </div>
+
+    <div class="main">
+      <components
+        :is="defaultTab==='record'?'repotPushRecord':'reportReceiveSet'"
+      />
+    </div>
+  </div>
+</template>
+<script>
+import repotPushRecord from './components/repotPushRecord.vue'
+import reportReceiveSet from './components/reportReceiveSet.vue'
+export default {
+  components: { repotPushRecord,reportReceiveSet },
+  data() {
+    return {
+      defaultTab: '',
+      alltabs: [
+        { label: '推送记录', key:'record',authCode:'reportPush_recordView' },
+        { label: '接收人员配置', key:'set',authCode:'reportPush_setView' },
+      ],
+      tabs: []
+    }
+  },
+  mounted(){
+    this.init()
+  },
+  methods:{
+    init() {
+      const {reportManageBtn,checkPermissionBtn}=this.permissionBtn;
+      this.tabs = this.alltabs.filter( _ => checkPermissionBtn(reportManageBtn[_.authCode]));
+      this.defaultTab = this.tabs[0].key;
+    }
+  },
+}
+</script>
+<style scoped lang='scss'>
+* {
+  box-sizing: border-box;
+}
+.report-push-page {
+  padding: 20px;
+  height: calc(100vh - 120px);
+  overflow-y: auto;
+  background-color: #FFFFFF;
+
+  .top {
+    display: flex;
+    gap: 20px;
+    .tab-item {
+      border-bottom: 2px solid transparent;
+      font-size: 16px;
+      padding-bottom: 5px;
+      &.act {
+        color: #0052D9;
+        border-color: #0052D9;
+      }
+    }
+  }
+
+  .main {
+    margin-top: 20px;
+  }
+}
+</style>

+ 25 - 15
src/views/report_manage/reportV2/list.vue

@@ -195,16 +195,19 @@
             </template>
           </el-table-column>
 
-          <el-table-column v-if="permissionBtn.checkPermissionBtn(permissionBtn.reportManageBtn.reportManage_reportList_sendTime)"
+          <el-table-column
             prop="MsgSendTime"
-            :label="$t('ReportManage.smart_report_push_time_btn')"
+            label="最近一次推送时间"
             min-width="124"
             align="center"
           >
             <template slot-scope="scope">{{
-              scope.row.MsgSendTime | formatTime
+              scope.row.MsgSendTime 
+                ? $moment(scope.row.MsgSendTime).format('YYYY.MM.DD HH:mm:ss') 
+                : ''
             }}</template>
           </el-table-column>
+
           <el-table-column
             prop="ModifyTime"
             :label="$t('ReportManage.smart_update_time')"
@@ -424,7 +427,7 @@ import {
   voiceupload,
   reportdelete,
   markReport,
-  reportMessageSend,
+  reportPushInterface,
   weekReportValidAudio,
 } from '@/api/modules/reportV2.js';
 import { departInterence } from "api/api.js";
@@ -545,7 +548,7 @@ export default {
         {label:"撤销",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_cancelPublish'),States:[4,5,6],text:'ReportManage.smart_btn.withdraw'},
         {label:"下载Pdf",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_exportPdf'),States:[2,6],text:'ReportManage.smart_btn.download_pdf'},
         {label:"下载长图",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_exportImg'),States:[2,6],text:'ReportManage.smart_btn.download_long_image'},
-        // {label:"推送消息",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_sendMsg'),States:[2,6],text:'ReportManage.smart_push_notification_btn'},
+        {label:"推送消息",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_sendMsg'),States:[2,6],text:'ReportManage.smart_push_notification_btn'},
         // {label:"已推送消息",permission:this.permissionBtn.isShowBtn('reportManageBtn','reportManage_sendMsg'),States:[2,6],text:'ReportManage.smart_notification_pushed'},
       ],
 
@@ -942,15 +945,22 @@ export default {
       }
     },
 
-    // 推送消息(同时推送模板消息和客群消息)
-    messageSend(item) {
-      reportMessageSend({ ReportId: item.Id }).then((res) => {
-        if (res.Ret === 200) {
-          this.$message.success(this.$t('ReportManage.smart_msg.push_success'));
-          item.MsgIsSend = 1;
-          item.MsgSendTime = res.Data.MsgSendTime;
-        }
-      });
+    // 推送消息
+    async messageSend(item) {
+      await this.$confirm('报告将被推送到订阅号,无法撤回,确定推送吗?','提示',{
+        type: 'warning'
+      })
+
+      const res = await reportPushInterface.pushMsg({ 
+        ReportId: item.Id,
+        PptId: 0
+      })
+
+      if (res.Ret === 200) {
+        this.$message.success(this.$t('ReportManage.smart_msg.push_success'));
+        item.MsgIsSend = 1;
+        item.MsgSendTime = res.Data.MsgSendTime;
+      }
     },
 
     //操作
@@ -1041,7 +1051,7 @@ export default {
               (typeof(but.States)=='boolean' || but.States.includes(row.State) ) &&
               (!row.CanEdit)
         }else if(but.label==='推送消息'){
-          return commonFilterPass && row.MsgIsSend==0 && row.HasAuth
+          return commonFilterPass && row.MsgIsSend==0 && row.HasAuth && row.CanSendMsg
         }else if(but.label==='已推送消息'){
           return commonFilterPass && row.MsgIsSend!==0
         }else if(['音频上传'].includes(but.label)){