فهرست منبع

add:首页日程弹窗提醒

luoaoxuan 1 سال پیش
والد
کامیت
b6e6f4f8b6

+ 100 - 81
package-lock.json

@@ -1331,6 +1331,25 @@
         "tslib": "^2.1.0"
       }
     },
+    "@fullcalendar/interaction": {
+      "version": "5.11.5",
+      "resolved": "https://registry.npmmirror.com/@fullcalendar/interaction/-/interaction-5.11.5.tgz",
+      "integrity": "sha512-Vg9uw8zKXZc2RP7it88U8R/kxJIQsK4pyv+s+RhlvT5NBZ9KLOh5y2xGCS4A4hyY7qLrzugxnKYlu6NwNqJ/RQ==",
+      "requires": {
+        "@fullcalendar/common": "~5.11.5",
+        "tslib": "^2.1.0"
+      },
+      "dependencies": {
+        "@fullcalendar/common": {
+          "version": "5.11.5",
+          "resolved": "https://registry.npmmirror.com/@fullcalendar/common/-/common-5.11.5.tgz",
+          "integrity": "sha512-3iAYiUbHXhjSVXnYWz27Od2cslztUPsOwiwKlfGvQxBixv2Kl6a8IPwaijKFYJHXdwYmfPoEgK7rvqAGVoIYwA==",
+          "requires": {
+            "tslib": "^2.1.0"
+          }
+        }
+      }
+    },
     "@fullcalendar/list": {
       "version": "5.10.1",
       "resolved": "https://registry.npmjs.org/@fullcalendar/list/-/list-5.10.1.tgz",
@@ -2722,6 +2741,87 @@
         "webpack-chain": "^6.4.0",
         "webpack-dev-server": "^3.11.0",
         "webpack-merge": "^4.2.2"
+      },
+      "dependencies": {
+        "ansi-styles": {
+          "version": "4.3.0",
+          "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
+          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "4.1.2",
+          "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
+          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+          "dev": true,
+          "optional": true
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+          "dev": true,
+          "optional": true
+        },
+        "loader-utils": {
+          "version": "2.0.4",
+          "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
+          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^2.1.2"
+          }
+        },
+        "supports-color": {
+          "version": "7.2.0",
+          "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
+          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
+        },
+        "vue-loader-v16": {
+          "version": "npm:vue-loader@16.8.3",
+          "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
+          "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
+          "dev": true,
+          "optional": true,
+          "requires": {
+            "chalk": "^4.1.0",
+            "hash-sum": "^2.0.0",
+            "loader-utils": "^2.0.0"
+          }
+        }
       }
     },
     "@vue/cli-shared-utils": {
@@ -17455,87 +17555,6 @@
         }
       }
     },
-    "vue-loader-v16": {
-      "version": "npm:vue-loader@16.8.3",
-      "resolved": "https://registry.npmmirror.com/vue-loader/-/vue-loader-16.8.3.tgz",
-      "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
-      "dev": true,
-      "optional": true,
-      "requires": {
-        "chalk": "^4.1.0",
-        "hash-sum": "^2.0.0",
-        "loader-utils": "^2.0.0"
-      },
-      "dependencies": {
-        "ansi-styles": {
-          "version": "4.3.0",
-          "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz",
-          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-convert": "^2.0.1"
-          }
-        },
-        "chalk": {
-          "version": "4.1.2",
-          "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz",
-          "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "ansi-styles": "^4.1.0",
-            "supports-color": "^7.1.0"
-          }
-        },
-        "color-convert": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz",
-          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "color-name": "~1.1.4"
-          }
-        },
-        "color-name": {
-          "version": "1.1.4",
-          "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz",
-          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-          "dev": true,
-          "optional": true
-        },
-        "has-flag": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz",
-          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-          "dev": true,
-          "optional": true
-        },
-        "loader-utils": {
-          "version": "2.0.4",
-          "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-2.0.4.tgz",
-          "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "big.js": "^5.2.2",
-            "emojis-list": "^3.0.0",
-            "json5": "^2.1.2"
-          }
-        },
-        "supports-color": {
-          "version": "7.2.0",
-          "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz",
-          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-          "dev": true,
-          "optional": true,
-          "requires": {
-            "has-flag": "^4.0.0"
-          }
-        }
-      }
-    },
     "vue-router": {
       "version": "3.5.3",
       "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.3.tgz",

+ 25 - 12
src/api/detection/newHomeApi.js

@@ -5,7 +5,7 @@ const news_url = 'business/v3'
  * 个人信息
  * @param {*} params
  */
-export function getAccountInfo (params) {
+export function getAccountInfo(params) {
     return request({
         url: NEWHOME_URL + '/desktop/facade/userInfo',
         method: 'get',
@@ -16,7 +16,7 @@ export function getAccountInfo (params) {
  * 新建流程
  * @param {*} params
  */
-export function findBpm (params) {
+export function findBpm(params) {
     return request({
         url: NEWHOME_URL + '/bpm/initiated/find/dashboard/bpmn',
         method: 'get',
@@ -27,7 +27,7 @@ export function findBpm (params) {
  * 公告栏目
  * @param {*} params
  */
-export function getNews (params) {
+export function getNews(params) {
     return request({
         url: NEWHOME_URL + '/desktop/facade/getNews',
         method: 'get',
@@ -38,7 +38,7 @@ export function getNews (params) {
  * 新短信公告
  * @param {*} params
  */
-export function getCmsNews (params) {
+export function getCmsNews(params) {
     return request({
         url: news_url + '/data/template/queryDataTable',
         method: 'post',
@@ -50,7 +50,7 @@ export function getCmsNews (params) {
  * 未读消息
  * @param {*} params
  */
-export function unreadMessage (params) {
+export function unreadMessage(params) {
     return request({
         url: NEWHOME_URL + '/desktop/facade/unreadMessage',
         method: 'get',
@@ -62,7 +62,7 @@ export function unreadMessage (params) {
  * 查询当前用户日历日程信息
  * @param {*} params
  */
-export function findAllByCurrUserId (params) {
+export function findAllByCurrUserId(params) {
     return request({
         url: NEWHOME_URL + '/desktop/facade/calendar/findAllByCurrUserId',
         method: 'get',
@@ -74,7 +74,7 @@ export function findAllByCurrUserId (params) {
  * 编辑保存用户日历日程
  * @param {*} params
  */
-export function saveCalendarInfos (params) {
+export function saveCalendarInfos(params) {
     return request({
         url: NEWHOME_URL + '/desktop/facade/calendar/save',
         method: 'post',
@@ -86,19 +86,32 @@ export function saveCalendarInfos (params) {
  * 删除用户日历日程
  * @param {*} params
  */
-export function removeCalendarInfos (params) {
+export function removeCalendarInfos(params) {
     return request({
         url: NEWHOME_URL + '/desktop/facade/calendar/remove',
         method: 'post',
         params: params
     })
 }
+/**
+ * 标记该日历为已读
+ * @param {*} params 
+ */
+export function markReadCalendar(params) {
+    return request({
+        url: NEWHOME_URL + '/desktop/facade/calendar/markRead',
+        method: 'post',
+        params: params
+    })
+}
+
+
 
 /**
  * 添加快捷导航,带参数
  * @param {*} params
  */
-export function addNavigation (params) {
+export function addNavigation(params) {
     return request({
         url: NEWHOME_URL + '/desktop/facade/navigate/save',
         method: 'post',
@@ -108,7 +121,7 @@ export function addNavigation (params) {
 /**
  * 查找快捷导航
  */
-export function getNavigation () {
+export function getNavigation() {
     return request({
         url: NEWHOME_URL + '/desktop/facade/navigate/findAllByCurrUserId',
         method: 'get'
@@ -118,7 +131,7 @@ export function getNavigation () {
  * 删除快捷导航,带参数
  * @param {*} params
  */
-export function delNavigation (params) {
+export function delNavigation(params) {
     return request({
         url: NEWHOME_URL + '/desktop/facade/navigate/remove',
         method: 'post',
@@ -130,7 +143,7 @@ export function delNavigation (params) {
  * 保存用户导航排序
  * @param {*} params
  */
-export function sortNavigation (params) {
+export function sortNavigation(params) {
     return request({
         url: NEWHOME_URL + '/desktop/facade/navigate/order',
         method: 'post',

+ 92 - 0
src/views/system/dashboard/components/calendar-alert.vue

@@ -0,0 +1,92 @@
+<template>
+  <div class="calendar-alert">
+    <el-dialog
+      title="提醒事项"
+      :visible.sync="dialogFormVisible"
+      width="30%"
+      :close-on-click-modal="false"
+      :close-on-press-escape="false"
+    >
+    <div style="height: 50vh; overflow-y: auto;">
+        <div
+        v-for="(value, key) in calendarAlertData"
+        :key="key"
+        class="item-container"
+      >
+        <div
+          class="start-time"
+          :class="{ alertcolor: new Date() > new Date(key) }"
+        >
+          {{ key }}:
+        </div>
+        <div class="message" v-for="(item, index) in value" :key="item.id">
+          {{ index + 1 }}.{{ item.title }}
+        </div>
+      </div>
+    </div>
+    
+
+      <div slot="footer" class="dialog-footer">
+        <el-checkbox v-model="checked">今日不再提醒</el-checkbox>
+        <el-button type="primary" @click="confirm">确 定</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    calendarAlertData: {
+      default: () => {},
+    },
+  },
+  data() {
+    return {
+      dialogFormVisible: false,
+      checked: false,
+    };
+  },
+  methods: {
+    open() {
+      this.dialogFormVisible = true;
+    },
+    close() {
+      this.dialogFormVisible = false;
+    },
+    confirm() {
+      this.dialogFormVisible = false;
+      this.$emit("onCalendarAlert", this.checked);
+    },
+  },
+};
+</script>
+
+<style>
+.item-container {
+  margin: 6px 6px 12px 6px;
+}
+
+.start-time {
+  font-weight: bold;
+  color: #333;
+  margin-left: 10px;
+  font-size: 18px;
+  margin-bottom: 4px;
+}
+
+.message {
+  color: #666;
+  margin-left: 16px;
+  font-size: 15px;
+  margin-bottom: 4px;
+}
+
+.dialog-footer {
+  display: flex;
+  justify-content: space-between;
+}
+.alertcolor {
+  color: red;
+}
+</style>

+ 86 - 44
src/views/system/dashboard/components/util.js

@@ -9,11 +9,11 @@ import { isEqual } from 'lodash'
 import Bus from '@/utils/EventBus'
 import newPng from '@/assets/images/homepage/new.png'
 import { BASE_URL } from '@/constant'
-
+import dayjs from 'dayjs'
 /**
  * 创建组件
  */
-export function buildComponent (name, column, preview, vm) {
+export function buildComponent(name, column, preview, vm) {
     try {
         return {
             name,
@@ -23,7 +23,7 @@ export function buildComponent (name, column, preview, vm) {
             props: {
                 params: {
                     type: Object,
-                    default: () => {}
+                    default: () => { }
                 },
                 height: {
                     type: Number,
@@ -39,7 +39,7 @@ export function buildComponent (name, column, preview, vm) {
                 }
             },
             filters: {
-                filterStatus (val, type) {
+                filterStatus(val, type) {
                     if (Utils.isEmpty(val)) {
                         return ''
                     }
@@ -58,7 +58,7 @@ export function buildComponent (name, column, preview, vm) {
                     return typeMap[type].find(x => x['value'] === val) ? typeMap[type].find(x => x['value'] === val).label : val
                 }
             },
-            data () {
+            data() {
                 const { first = '', second = '' } = this.$store.getters.level
                 const { userId, userList = [], deptList = [], menus, userInfo } = this.$store.getters
                 const t1 = deptList.find(i => i.positionId === first) || {}
@@ -146,7 +146,8 @@ export function buildComponent (name, column, preview, vm) {
                         animation: 200,
                         axis: 'y'
                     },
-                    calendarToolbar: this.fullScreen ? [{ key: 'refresh' }] : [{ key: 'refresh' }, { key: 'fullscreen' }, { key: 'collapse' }]
+                    calendarToolbar: this.fullScreen ? [{ key: 'refresh' }] : [{ key: 'refresh' }, { key: 'fullscreen' }, { key: 'collapse' }],
+                    isFirstAlert: true // 是否首次日程提醒
                 }
             },
             computed: {
@@ -154,14 +155,14 @@ export function buildComponent (name, column, preview, vm) {
                     userInfo: state => state.ibps.user.info
                 })
             },
-            mounted () {
+            mounted() {
                 this.defaultForm = JSON.parse(JSON.stringify(this.quickNavform))
                 this.$nextTick(() => {
                     this.fetchData()
                 })
             },
             methods: {
-                fetchData (columns, params = {}) {
+                fetchData(columns, params = {}) {
                     this.loading = true
                     this.data = []
                     this.showHeight = this.getHeight()
@@ -172,6 +173,10 @@ export function buildComponent (name, column, preview, vm) {
                         const { getFormatDate, getDate } = this.$common
                         findAllByCurrUserId().then(res => {
                             const { data = [] } = res || {}
+                            if (this.isFirstAlert) {
+                                this.isFirstAlert = false
+                                this.showAlert(data)
+                            }
                             this.data = data.map(i => ({
                                 id: i.id,
                                 title: i.title,
@@ -215,16 +220,49 @@ export function buildComponent (name, column, preview, vm) {
                         })
                     }
                 },
-                getPhoto (photo) {
+                // 过滤日程提醒数据
+                filterAlertData(data, dayNumber = 3) {
+                    if (dayNumber <= 0) return
+                    const today = dayjs()
+                    let tempCalendarAlertData = data.filter(day => {
+                        const startTime = dayjs(day.startTime);
+                        const endTime = dayjs(day.endTime);
+                        if (day.popUp) {
+                            if ((startTime.diff(today, 'day') <= 0 && endTime.diff(today, 'day') >= 0) || (startTime.diff(today, 'day') <= dayNumber - 2 && startTime.diff(today, 'day') >= 0)) {
+                                return true
+                            }
+                        }
+                    })
+                    tempCalendarAlertData.sort((a, b) => new Date(a.startTime) - new Date(b.startTime))
+                    let calendarIds = tempCalendarAlertData.map(item => item.id)
+
+                    let calendarAlertData = {}
+                    tempCalendarAlertData.forEach(item => {
+                        if (calendarAlertData[item.startTime]) {
+                            calendarAlertData[item.startTime].push(item)
+                        }
+                        else {
+                            calendarAlertData[item.startTime] = []
+                            calendarAlertData[item.startTime].push(item)
+                        }
+                    })
+                    return { calendarAlertData, calendarIds }
+                },
+                // 日程提醒
+                showAlert(data) {
+                    let calendarAlertData = this.filterAlertData(data)
+                    this.handleCalendarAlert(calendarAlertData)
+                },
+                getPhoto(photo) {
                     return getFile(photo)
                 },
-                getTaskDesc (v) {
+                getTaskDesc(v) {
                     if (!v.includes('#')) {
                         return ''
                     }
                     return v.split('#')[1] || ''
                 },
-                getTaskInfo (val, arg) {
+                getTaskInfo(val, arg) {
                     const arr = val.split('#')
                     if (!arr[2]) {
                         return ''
@@ -242,14 +280,14 @@ export function buildComponent (name, column, preview, vm) {
                     result.deptName = deptNames.join(',')
                     return result[arg]
                 },
-                transformData (val, dataset, from, to) {
+                transformData(val, dataset, from, to) {
                     if (!val) {
                         return ''
                     }
                     const temp = this[dataset].find(u => u[from] === val)
                     return temp ? temp[to] : ''
                 },
-                getHeightNoUnit () {
+                getHeightNoUnit() {
                     // 高度 - header - 边框
                     if (!this.visible) {
                         return this.height ? (this.height - 60 - 20) : 150
@@ -257,7 +295,7 @@ export function buildComponent (name, column, preview, vm) {
                         return 150
                     }
                 },
-                getHeight (h = 20) {
+                getHeight(h = 20) {
                     // 高度 - header - 边框
                     if (!this.visible) {
                         return this.height ? `${(this.height - 60 - h)}px` : '150px'
@@ -265,10 +303,10 @@ export function buildComponent (name, column, preview, vm) {
                         return '100%'
                     }
                 },
-                getDashboardHeight () {
+                getDashboardHeight() {
                     return this.height ? `${this.height + 20}px` : '150px'
                 },
-                getAttrs () {
+                getAttrs() {
                     const item = JSON.parse(JSON.stringify(column))
                     item.templateHtml = null
                     return item
@@ -278,7 +316,7 @@ export function buildComponent (name, column, preview, vm) {
                  * @param {*} data
                  * @returns
                  */
-                getFullCalendarConfig (data) {
+                getFullCalendarConfig(data) {
                     const events = data === null ? [] : Utils.parseJSON(data)
                     const config = {
                         height: preview ? '100%' : (this.height ? this.height : 180),
@@ -311,7 +349,7 @@ export function buildComponent (name, column, preview, vm) {
                     }
                     return config
                 },
-                handleDateClick (param) {
+                handleDateClick(param) {
                     this.$emit(
                         'open',
                         'calendar',
@@ -319,7 +357,7 @@ export function buildComponent (name, column, preview, vm) {
                         this.data
                     )
                 },
-                handleEventClick (param) {
+                handleEventClick(param) {
                     this.$emit(
                         'open',
                         'calendar',
@@ -328,7 +366,7 @@ export function buildComponent (name, column, preview, vm) {
                         param.event.id
                     )
                 },
-                handleMoreLinkClick (date) {
+                handleMoreLinkClick(date) {
                     this.$emit(
                         'open',
                         'calendar',
@@ -337,7 +375,7 @@ export function buildComponent (name, column, preview, vm) {
                         date.allSegs[0].event.id
                     )
                 },
-                refreshData () {
+                refreshData() {
                     this.fetchData()
                 },
                 /**
@@ -347,7 +385,7 @@ export function buildComponent (name, column, preview, vm) {
                  * @param {*} data
                  * @param {*} actions
                  */
-                handleActionEvent (command, position, data, actions) {
+                handleActionEvent(command, position, data, actions) {
                     switch (command) {
                         case 'refresh': // 刷新
                             this.refreshData()
@@ -369,23 +407,27 @@ export function buildComponent (name, column, preview, vm) {
                             break
                     }
                 },
-                emitActionEventHandler (command) {
+                emitActionEventHandler(command) {
                     this.$emit('action-event', command, ...Array.from(arguments).slice(1))
                 },
                 // 公告栏目点击事件
-                handleApprove (id, title) {
+                handleApprove(id, title) {
                     this.$emit('action-event', 'approve', {
                         id, title
                     })
                 },
-                handleUnreadMessage (id, tableId, tableName) {
+                handleUnreadMessage(id, tableId, tableName) {
                     this.$emit('action-event', 'unRead', { id, tableId, tableName })
                 },
+                // 日程提醒
+                handleCalendarAlert(calendarAlertData) {
+                    this.$emit('action-event', 'calendarAlert', { calendarAlertData })
+                },
                 // 处理全屏
-                handleFullscreen () {
+                handleFullscreen() {
                     this.emitActionEventHandler('fullscreen', { id: this.attrs.id })
                 },
-                openPlate (url) {
+                openPlate(url) {
                     const menuMap = {
                         myTraining: 'rygl/rypx/wdpx',
                         myTesting: 'rygl/kszx/wdks',
@@ -404,7 +446,7 @@ export function buildComponent (name, column, preview, vm) {
                 /**
                  * 处理更多
                  */
-                handleMore () {
+                handleMore() {
                     if (this.attrs.alias === 'quickNavigation') {
                         return this.openPlate('quickNavigation')
                     }
@@ -414,22 +456,22 @@ export function buildComponent (name, column, preview, vm) {
                     this.openPlate(this.attrs.colUrl)
                 },
                 // 未读消息
-                handleClick (option) {
+                handleClick(option) {
                     this.unreadMessageOption = option
                     option[this.activeName].dataMode = column.dataMode
                     this.fetchData(option[this.activeName])
                 },
                 // 待办事务
-                handleTabClick (option) {
+                handleTabClick(option) {
                     this.pendingBusinessOption = option
                     option[this.pendingTabActiveName].dataMode = column.dataMode
                     this.fetchData(option[this.pendingTabActiveName])
                 },
-                handleFlowClick (params) {
+                handleFlowClick(params) {
                     params.$alias = this.alias
                     this.emitActionEventHandler('flow', params)
                 },
-                handleCollapseExpand (command, data, actions) {
+                handleCollapseExpand(command, data, actions) {
                     this.bodyShow = !this.bodyShow
                     const index = actions.findIndex((action) => action.key === data.key)
                     actions[index].key = this.bodyShow ? 'collapse' : 'expansion'
@@ -440,17 +482,17 @@ export function buildComponent (name, column, preview, vm) {
                     this.showHeight = this.bodyShow ? this.getHeight() : 0
                     this.$refs['toolbar'].callback(actions)
                 },
-                formValidate (formName) {
+                formValidate(formName) {
                     this.$nextTick(() => {
-                        this.$refs[formName].validate(() => {})
+                        this.$refs[formName].validate(() => { })
                     })
                 },
-                getFormData () {
+                getFormData() {
                     this.quickNavform = JSON.parse(JSON.stringify(this.defaultForm))
                     this.formValidate('quickNavform')
                     this.dialogFormVisible = true
                 },
-                handleNavRemove (navId, i) {
+                handleNavRemove(navId, i) {
                     this.$confirm('是否确认删除该快捷导航?', '提示', {
                         confirmButtonText: '确认',
                         cancelButtonText: '取消',
@@ -465,15 +507,15 @@ export function buildComponent (name, column, preview, vm) {
                     })
                 },
                 // 错误头像的照片
-                errorAvatarHandler (data) {
+                errorAvatarHandler(data) {
                     // data.photo = require('https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png')
                     return true
                 },
-                close () {
+                close() {
                     this.$refs[this.formName].resetFields()
                     this.dialogFormVisible = false
                 },
-                saveQuickNav () {
+                saveQuickNav() {
                     this.$refs[this.formName].validate(valid => {
                         if (valid) {
                             addNavigation({ id: '', ...this.quickNavform }).then(res => {
@@ -487,7 +529,7 @@ export function buildComponent (name, column, preview, vm) {
                         }
                     })
                 },
-                handleSortChange () {
+                handleSortChange() {
                     this.isDragging = false
                     const newSort = this.quickNavigationData.map(i => i.id)
                     if (isEqual(this.navigationList, newSort)) {
@@ -499,7 +541,7 @@ export function buildComponent (name, column, preview, vm) {
                     })
                 },
                 // 父组件调用该方法给日程添加数据
-                async setCalendarEvents (param) {
+                async setCalendarEvents(param) {
                     const { name = '' } = this.$store.getters
                     const form = param.form
                     const paramObject = {
@@ -516,7 +558,7 @@ export function buildComponent (name, column, preview, vm) {
                     await saveCalendarInfos(paramObject)
                     this.refreshData()
                 },
-                async hanldeCalendardel (param) {
+                async hanldeCalendardel(param) {
                     if (param.form.id) {
                         await removeCalendarInfos({
                             calendarIds: param.form.id
@@ -525,12 +567,12 @@ export function buildComponent (name, column, preview, vm) {
                     this.refreshData()
                 },
                 // 公告栏是否显示new图标
-                showNewIcon (date, days) {
+                showNewIcon(date, days) {
                     const nowDate = new Date().getTime()
                     const targetDate = new Date(date).getTime()
                     return targetDate + days * 24 * 60 * 60 * 1000 > nowDate
                 },
-                handleOverflow (val, length) {
+                handleOverflow(val, length) {
                     if (val.length > length) {
                         return val.slice(0, length - 2) + '...'
                     }

+ 781 - 681
src/views/system/homepage/index.vue

@@ -1,724 +1,824 @@
 <template>
-    <ibps-container
-        ref="dashboardContainer"
-        v-loading="loading"
-        :element-loading-text="$t('common.loading')"
-        :scroll-delay="scrollDelay"
-        type="full"
-        class="ibps-desktop-page"
-        @scroll="({ x, y }) => { scrollTop = y }"
-    >
-        <ibps-back-to-top
-            :visibility-height="150"
-            :scroll-top="scrollTop"
-            transition-name="fade"
-            @scrollToTop="scrollToTop"
-        />
-        <preview
-            :id="id"
-            :visible="dialogPreviewVisible"
-            title="全屏预览"
-            screen
-            @close="visible => (dialogPreviewVisible = visible)"
-        />
-        <bpmn-formrender
-            :visible="bpmnFormrenderDialogVisible"
-            :def-id="defId"
-            :task-id="taskId"
-            :instance-id="instanceId"
-            :title="flowName"
-            @close="visible => (bpmnFormrenderDialogVisible = visible)"
-            @callback="handleFlowCallback"
-        />
+  <ibps-container
+    ref="dashboardContainer"
+    v-loading="loading"
+    :element-loading-text="$t('common.loading')"
+    :scroll-delay="scrollDelay"
+    type="full"
+    class="ibps-desktop-page"
+    @scroll="
+      ({ x, y }) => {
+        scrollTop = y;
+      }
+    "
+  >
+    <ibps-back-to-top
+      :visibility-height="150"
+      :scroll-top="scrollTop"
+      transition-name="fade"
+      @scrollToTop="scrollToTop"
+    />
+    <preview
+      :id="id"
+      :visible="dialogPreviewVisible"
+      title="全屏预览"
+      screen
+      @close="(visible) => (dialogPreviewVisible = visible)"
+    />
+    <bpmn-formrender
+      :visible="bpmnFormrenderDialogVisible"
+      :def-id="defId"
+      :task-id="taskId"
+      :instance-id="instanceId"
+      :title="flowName"
+      @close="(visible) => (bpmnFormrenderDialogVisible = visible)"
+      @callback="handleFlowCallback"
+    />
 
-        <ibps-news-dialog
-            :id="newsEditId"
-            :title="newsTitle"
-            :visible="ibpsNewsDialogVisible"
-            :readonly="true"
-            @close="visible => (ibpsNewsDialogVisible = visible)"
-        />
+    <ibps-news-dialog
+      :id="newsEditId"
+      :title="newsTitle"
+      :visible="ibpsNewsDialogVisible"
+      :readonly="true"
+      @close="(visible) => (ibpsNewsDialogVisible = visible)"
+    />
 
-        <ibps-message-dialog
-            :id="messageEditId"
-            title="消息明细"
-            :table-id="messageTableId"
-            :table-name="messageTableName"
-            :readonly="true"
-            :visible="ibpsMessageDialogVisible"
-            @callback="handleMessageCallback"
-            @close="visible => (ibpsMessageDialogVisible = visible)"
+    <ibps-message-dialog
+      :id="messageEditId"
+      title="消息明细"
+      :table-id="messageTableId"
+      :table-name="messageTableName"
+      :readonly="true"
+      :visible="ibpsMessageDialogVisible"
+      @callback="handleMessageCallback"
+      @close="(visible) => (ibpsMessageDialogVisible = visible)"
+    />
+    <div v-if="initLoading">
+      <template v-if="localSystem">
+        <ibps-grid-layout
+          v-if="layout && layout.length > 0"
+          :layout.sync="layout"
+          :col-num="colNum"
+          :row-height="rowHeight"
+          :is-draggable="isDraggable"
+          :is-resizable="isResizable"
+          :is-mirrored="isMirrored"
+          :vertical-compact="verticalCompact"
+          :margin="margin"
+          :use-css-transforms="useCssTransforms"
+        >
+          <ibps-grid-item
+            v-for="(item, index) in layout"
+            :key="item.i"
+            :x="item.x"
+            :y="item.y"
+            :w="item.w"
+            :h="item.h"
+            :i="item.i"
+          >
+            <component
+              :is="'ibps-desktop-' + item.alias"
+              v-if="hasComponent(item.alias)"
+              :id="item.i"
+              :ref="item.alias"
+              :alias="item.alias"
+              :height="getHeight(item.h)"
+              :add-component-datas="addComponentDatas"
+              @open="handleOpen"
+              @close="handleClose"
+              @action-event="
+                (command, data) => handleActionEvent(command, data, index)
+              "
+            />
+          </ibps-grid-item>
+        </ibps-grid-layout>
+        <el-alert
+          v-else-if="!loading"
+          :closable="false"
+          type="warning"
+          show-icon
+          style="height: 50px"
+        >
+          <span slot="title"
+            >未设置个人桌面布局,可以通过“<a
+              href="javascript:void(0)"
+              @click="goMyLayout"
+              >个人办公-》个人桌面布局</a
+            >”进行设置</span
+          >
+        </el-alert>
+      </template>
+      <!--不是本地系统-->
+      <template v-else>
+        <!--iframe方式-->
+        <iframe
+          v-if="systemUrlType === 'iframe'"
+          ref="systemrender"
+          class="ibps-container-frame"
+          frameborder="0"
         />
-        <div v-if="initLoading">
-            <template v-if="localSystem">
-                <ibps-grid-layout
-                    v-if="layout && layout.length >0"
-                    :layout.sync="layout"
-                    :col-num="colNum"
-                    :row-height="rowHeight"
-                    :is-draggable="isDraggable"
-                    :is-resizable="isResizable"
-                    :is-mirrored="isMirrored"
-                    :vertical-compact="verticalCompact"
-                    :margin="margin"
-                    :use-css-transforms="useCssTransforms"
-                >
-                    <ibps-grid-item
-                        v-for="(item,index) in layout"
-                        :key="item.i"
-                        :x="item.x"
-                        :y="item.y"
-                        :w="item.w"
-                        :h="item.h"
-                        :i="item.i"
-                    >
-                        <component
-                            :is="'ibps-desktop-'+item.alias"
-                            v-if="hasComponent(item.alias)"
-                            :id="item.i"
-                            :ref="item.alias"
-                            :alias="item.alias"
-                            :height="getHeight(item.h)"
-                            :add-component-datas="addComponentDatas"
-                            @open="handleOpen"
-                            @close="handleClose"
-                            @action-event="(command,data)=> handleActionEvent(command,data,index)"
-                        />
-                    </ibps-grid-item>
-                </ibps-grid-layout>
-                <el-alert
-                    v-else-if="!loading"
-                    :closable="false"
-                    type="warning"
-                    show-icon
-                    style="height:50px"
-                >
-                    <span slot="title">未设置个人桌面布局,可以通过“<a href="javascript:void(0)" @click="goMyLayout">个人办公-》个人桌面布局</a>”进行设置</span>
-                </el-alert>
-            </template>
-            <!--不是本地系统-->
-            <template v-else>
-                <!--iframe方式-->
-                <iframe
-                    v-if="systemUrlType === 'iframe'"
-                    ref="systemrender"
-                    class="ibps-container-frame"
-                    frameborder="0"
-                />
-                <!--vue组件方式-->
-                <component
-                    :is="systemUrlName"
-                    v-else
-                    ref="systemrender"
-                    :params="systemUrlParams"
-                />
-            </template>
-        </div>
-        <schedule-add
-            :visible="calendarDialogVisible"
-            :form="calendarDialogForm"
-            @close="handleClose"
-            @saveData="handleSaveData"
-            @delData="handleDelData"
+        <!--vue组件方式-->
+        <component
+          :is="systemUrlName"
+          v-else
+          ref="systemrender"
+          :params="systemUrlParams"
         />
-    </ibps-container>
-
+      </template>
+    </div>
+    <schedule-add
+      :visible="calendarDialogVisible"
+      :form="calendarDialogForm"
+      @close="handleClose"
+      @saveData="handleSaveData"
+      @delData="handleDelData"
+    />
+    <CalendarAlert
+      :calendarAlertData="calendarAlertData"
+      ref="calendarRef"
+      @onCalendarAlert="onCalendarAlert"
+    ></CalendarAlert>
+  </ibps-container>
 </template>
 
 <script>
-import { getMyDesktop } from '@/api/platform/desktop/myLayout'
-import { initColumn, isInit, getComponents } from '@/views/system/dashboard/components'
+import { getMyDesktop } from "@/api/platform/desktop/myLayout";
+import {
+  initColumn,
+  isInit,
+  getComponents,
+} from "@/views/system/dashboard/components";
 // 引用导出地址
-import { BASE_API, BUSINESS_BASE_URL } from '@/api/baseUrl'
+import { BASE_API, BUSINESS_BASE_URL } from "@/api/baseUrl";
 //  网格布局组件
-import { GridLayout, GridItem } from 'vue-grid-layout'
-import IbpsBackToTop from '@/components/ibps-back-to-top'
-import Preview from '@/views/platform/desktop/column/preview'
-import BpmnFormrender from '@/business/platform/bpmn/form/dialog'
+import { GridLayout, GridItem } from "vue-grid-layout";
+import IbpsBackToTop from "@/components/ibps-back-to-top";
+import Preview from "@/views/platform/desktop/column/preview";
+import BpmnFormrender from "@/business/platform/bpmn/form/dialog";
+
+import IbpsNewsDialog from "@/views/platform/system/news/detail";
+import IbpsMessageDialog from "@/views/platform/message/inner/detail/dialog";
+import { getToken } from "@/utils/auth";
+import ScheduleAdd from "@/views/system/dashboard/templates/scheduleAdd";
 
-import IbpsNewsDialog from '@/views/platform/system/news/detail'
-import IbpsMessageDialog from '@/views/platform/message/inner/detail/dialog'
-import { getToken } from '@/utils/auth'
-import ScheduleAdd from '@/views/system/dashboard/templates/scheduleAdd'
+// 标记日历已读
+import { markReadCalendar } from "@/api/detection/newHomeApi";
+// 日程提醒弹窗组件
+import CalendarAlert from "@/views/system/dashboard/components/calendar-alert.vue";
 
-const _import = require('@/utils/util.import.' + process.env.NODE_ENV)
+const _import = require("@/utils/util.import." + process.env.NODE_ENV);
 export default {
-    components: {
-        'ibps-news-dialog': IbpsNewsDialog,
-        'ibps-message-dialog': IbpsMessageDialog,
-        IbpsBackToTop,
-        Preview,
-        BpmnFormrender,
-        'ibps-grid-layout': GridLayout,
-        'ibps-grid-item': GridItem,
-        ScheduleAdd
-    },
-    data () {
-        return {
-            infoMessage: [],
-            uloadPath: BASE_API() + BUSINESS_BASE_URL() + '/ck/task/importExcel',
-            reportPath: BASE_API() + BUSINESS_BASE_URL() + '/sys/SysDataContext/replaceReportFile',
-            layout: null,
-            colNum: 24,
-            rowHeight: 30,
-            isDraggable: false,
-            isResizable: false,
-            isMirrored: false,
-            verticalCompact: true,
-            margin: [15, 15],
-            useCssTransforms: true,
-            taskId: '',
-            flowName: '',
-            ibpsNewsDialogVisible: false,
-            newsEditId: '',
-            newsTitle: '公告明细',
-            showRepost: true,
+  components: {
+    "ibps-news-dialog": IbpsNewsDialog,
+    "ibps-message-dialog": IbpsMessageDialog,
+    IbpsBackToTop,
+    Preview,
+    BpmnFormrender,
+    "ibps-grid-layout": GridLayout,
+    "ibps-grid-item": GridItem,
+    ScheduleAdd,
+    CalendarAlert,
+  },
+  data() {
+    return {
+      infoMessage: [],
+      uloadPath: BASE_API() + BUSINESS_BASE_URL() + "/ck/task/importExcel",
+      reportPath:
+        BASE_API() +
+        BUSINESS_BASE_URL() +
+        "/sys/SysDataContext/replaceReportFile",
+      layout: null,
+      colNum: 24,
+      rowHeight: 30,
+      isDraggable: false,
+      isResizable: false,
+      isMirrored: false,
+      verticalCompact: true,
+      margin: [15, 15],
+      useCssTransforms: true,
+      taskId: "",
+      flowName: "",
+      ibpsNewsDialogVisible: false,
+      newsEditId: "",
+      newsTitle: "公告明细",
+      showRepost: true,
 
-            ibpsMessageDialogVisible: false,
-            messageEditId: '',
-            messageTableId: '',
-            messageTableName: '',
+      ibpsMessageDialogVisible: false,
+      messageEditId: "",
+      messageTableId: "",
+      messageTableName: "",
 
-            scrollDelay: 0,
-            scrollTop: 0,
-            initLoading: false,
-            loading: false,
-            id: '',
-            dialogPreviewVisible: false, // 预览
-            defaultData: [],
+      scrollDelay: 0,
+      scrollTop: 0,
+      initLoading: false,
+      loading: false,
+      id: "",
+      dialogPreviewVisible: false, // 预览
+      defaultData: [],
 
-            bpmnFormrenderDialogVisible: false, // 流程
-            defId: '',
-            instanceId: '',
-            layoutIndex: '',
-            initInterval: null,
+      bpmnFormrenderDialogVisible: false, // 流程
+      defId: "",
+      instanceId: "",
+      layoutIndex: "",
+      initInterval: null,
 
-            systemUrlType: 'iframe',
-            systemUrlName: '',
-            systemUrlParams: {},
-            alias: '',
-            headers: {
-                'X-Authorization-access_token': getToken()
-            },
-            scheduledTask: false,
-            calendarDialogVisible: false,
-            calendarDialogForm: {},
-            addComponentDatas: {}
-        }
+      systemUrlType: "iframe",
+      systemUrlName: "",
+      systemUrlParams: {},
+      alias: "",
+      headers: {
+        "X-Authorization-access_token": getToken(),
+      },
+      scheduledTask: false,
+      calendarDialogVisible: false,
+      calendarDialogForm: {},
+      addComponentDatas: {},
+      calendarAlertData: {}, // 日程
+      calendarIds: [], // 日程 id 数组
+    };
+  },
+  computed: {
+    system() {
+      return this.$store.getters.system ? this.$store.getters.system : null;
     },
-    computed: {
-        system () {
-            return this.$store.getters.system ? this.$store.getters.system : null
-        },
-        systemAlias () {
-            return this.$store.getters.system ? this.$store.getters.system.alias : ''
-        },
-        localSystem () {
-            return this.system.isLocal
-        }
+    systemAlias() {
+      return this.$store.getters.system ? this.$store.getters.system.alias : "";
+    },
+    localSystem() {
+      return this.system.isLocal;
     },
-    mounted () {
-        if (localStorage.getItem('statistic') === 'isNormal') {
-            this.showRepost = false
+  },
+  mounted() {
+    if (localStorage.getItem("statistic") === "isNormal") {
+      this.showRepost = false;
+    }
+    this.initLoading = false;
+    this.initData();
+  },
+  created() {
+    const today = new Date().toLocaleDateString();
+    const savedDate = localStorage.getItem("doNotShowToday");
+    if (savedDate !== today) {
+      // this.getPeriodTask()
+    }
+  },
+  beforeDestroy() {
+    for (let i = 0; i < this.infoMessage.length; i++) {
+      this.infoMessage[i].close();
+    }
+  },
+  methods: {
+    cancelInfo(cronId, title, num, processData, taskId) {
+      /* 调用流程*/
+      if (taskId) {
+        this.$router.push({
+          name: "pendingItems",
+        });
+      } else if (processData) {
+        this.defId = processData;
+        this.bpmnFormrenderDialogVisible = true;
+      }
+      this.infoMessage[num].close();
+    },
+    downloadData() {
+      window.location.href =
+        BASE_API() + BUSINESS_BASE_URL() + "/sys/SysDataContext/downloadData";
+    },
+    scrollToTop() {
+      this.$refs.dashboardContainer.scrollToTop();
+    },
+    initData() {
+      this.initInterval = setInterval(() => {
+        if (this.$utils.isNotEmpty(this.systemAlias)) {
+          this.initLoading = true;
+          if (this.localSystem) {
+            this.fetchData();
+          } else {
+            this.initSystemUrl(this.system.homePage);
+          }
+          clearInterval(this.initInterval);
         }
-        this.initLoading = false
-        this.initData()
-    },
-    created () {
-        const today = new Date().toLocaleDateString()
-        const savedDate = localStorage.getItem('doNotShowToday')
-        if (savedDate !== today) {
-            // this.getPeriodTask()
+      }, 100);
+    },
+    // 抓取数据
+    fetchData() {
+      initColumn(this.systemAlias, this);
+      this.loading = true;
+      const interval = setInterval(() => {
+        if (isInit()) {
+          getMyDesktop({
+            systemAlias: this.systemAlias,
+          })
+            .then((response) => {
+              try {
+                this.layout = this.$utils.parseData(response.data);
+                this.defaultData = this.$utils.parseData(response.data);
+              } catch (error) {
+                this.layout = [];
+                this.defaultData = [];
+              }
+              this.loading = false;
+            })
+            .catch(() => {
+              this.loading = false;
+            });
+          clearInterval(interval);
         }
+      }, 100);
+    },
+    getHeight(h) {
+      // if (document.body.clientWidth > 1366 && document.body.clientWidth < 1920) {
+      //     const mH = (1920 - 1366) / (33 - 23)
+      //     this.rowHeight = ((document.body.clientWidth - 1366) / mH) + 23
+      //     // let mH = (1925-768)/(33-23)
+      //     // this.rowHeight=((document.body.clientWidth-768)/mH)+17
+      //     // console.log(this.rowHeight)
+      // } else if (document.body.clientWidth <= 1366) {
+      //     this.rowHeight = 23
+      // }
+      return (h - 1) * (this.rowHeight + this.margin[1]) + this.margin[1];
+    },
+    hasComponent(alias) {
+      const name = "ibps-desktop-" + alias;
+      const components = getComponents();
+      if (components) {
+        return components.includes(name);
+      } else {
+        return false;
+      }
     },
-    beforeDestroy () {
-        for (let i = 0; i < this.infoMessage.length; i++) {
-            this.infoMessage[i].close()
+    resizedHandler(i, newH, newW, newHPx, newWPx) {
+      if (!this.layout) return;
+      this.layout.layout.find((n) => {
+        if (i === n.i) {
+          n.widthPx = this.getWidth(n.w);
+          n.heightPx = this.getHeight(n.h);
         }
+      });
+    },
+    goMyLayout() {
+      this.$router.push({ path: "/officeDesk/grzlsw/desktopMyLayout" });
+    },
+    handleActionEvent(command, params, index) {
+      this.layoutIndex = index;
+      this.alias = params.$alias;
+      switch (command) {
+        case "fullscreen":
+          this.handleFullscreen(params.id);
+          break;
+        case "collapse":
+        case "expansion":
+          this.handleCollapseExpansion(index, command === "collapse");
+          break;
+        case "flow":
+          this.handleFlow(params);
+          break;
+        case "approve":
+          this.handleApprove(params);
+          break;
+        case "unRead":
+          this.handleUnreadMessage(params);
+          break;
+        case "calendarAlert":
+          this.handleCalendarAlert(params);
+        default:
+          break;
+      }
+    },
+    /**
+     * 日程提醒
+     */
+    handleCalendarAlert(calendarAlertData) {
+      this.calendarAlertData =
+        calendarAlertData.calendarAlertData.calendarAlertData;
+      this.calendarIds = calendarAlertData.calendarAlertData.calendarIds;
+      if (Object.keys(this.calendarAlertData).length > 0) {
+        this.$refs.calendarRef.open();
+      }
+    },
+    /**
+     * 标记日程已读
+     */
+    onCalendarAlert(checked) {
+      if (checked) {
+        markReadCalendar({
+          calendarIds: this.calendarIds + "",
+        })
+          .then((res) => {})
+          .catch((err) => {
+            console.log(err);
+          });
+      }
     },
-    methods: {
-        cancelInfo (cronId, title, num, processData, taskId) {
-            /* 调用流程*/
-            if (taskId) {
-                this.$router.push({
-                    name: 'pendingItems'
-                })
-            } else if (processData) {
-                this.defId = processData
-                this.bpmnFormrenderDialogVisible = true
-            }
-            this.infoMessage[num].close()
-        },
-        downloadData () {
-            window.location.href = BASE_API() + BUSINESS_BASE_URL() + '/sys/SysDataContext/downloadData'
-        },
-        scrollToTop () {
-            this.$refs.dashboardContainer.scrollToTop()
-        },
-        initData () {
-            this.initInterval = setInterval(() => {
-                if (this.$utils.isNotEmpty(this.systemAlias)) {
-                    this.initLoading = true
-                    if (this.localSystem) {
-                        this.fetchData()
-                    } else {
-                        this.initSystemUrl(this.system.homePage)
-                    }
-                    clearInterval(this.initInterval)
-                }
-            }, 100)
-        },
-        // 抓取数据
-        fetchData () {
-            initColumn(this.systemAlias, this)
-            this.loading = true
-            const interval = setInterval(() => {
-                if (isInit()) {
-                    getMyDesktop({
-                        systemAlias: this.systemAlias
-                    }).then(response => {
-                        try {
-                            this.layout = this.$utils.parseData(response.data)
-                            this.defaultData = this.$utils.parseData(response.data)
-                        } catch (error) {
-                            this.layout = []
-                            this.defaultData = []
-                        }
-                        this.loading = false
-                    }).catch(() => {
-                        this.loading = false
-                    })
-                    clearInterval(interval)
-                }
-            }, 100)
-        },
-        getHeight (h) {
-            // if (document.body.clientWidth > 1366 && document.body.clientWidth < 1920) {
-            //     const mH = (1920 - 1366) / (33 - 23)
-            //     this.rowHeight = ((document.body.clientWidth - 1366) / mH) + 23
-            //     // let mH = (1925-768)/(33-23)
-            //     // this.rowHeight=((document.body.clientWidth-768)/mH)+17
-            //     // console.log(this.rowHeight)
-            // } else if (document.body.clientWidth <= 1366) {
-            //     this.rowHeight = 23
-            // }
-            return (h - 1) * (this.rowHeight + this.margin[1]) + this.margin[1]
-        },
-        hasComponent (alias) {
-            const name = 'ibps-desktop-' + alias
-            const components = getComponents()
-            if (components) {
-                return components.includes(name)
-            } else {
-                return false
-            }
-        },
-        resizedHandler (i, newH, newW, newHPx, newWPx) {
-            if (!this.layout) return
-            this.layout.layout.find(n => {
-                if (i === n.i) {
-                    n.widthPx = this.getWidth(n.w)
-                    n.heightPx = this.getHeight(n.h)
-                }
-            })
-        },
-        goMyLayout () {
-            this.$router.push({ path: '/officeDesk/grzlsw/desktopMyLayout' })
-        },
-        handleActionEvent (command, params, index) {
-            this.layoutIndex = index
-            this.alias = params.$alias
-            switch (command) {
-                case 'fullscreen':
-                    this.handleFullscreen(params.id)
-                    break
-                case 'collapse':
-                case 'expansion':
-                    this.handleCollapseExpansion(index, command === 'collapse')
-                    break
-                case 'flow':
-                    this.handleFlow(params)
-                    break
-                case 'approve':
-                    this.handleApprove(params)
-                    break
-                case 'unRead':
-                    this.handleUnreadMessage(params)
-                    break
 
-                default:
-                    break
-            }
-        },
-        /**
-         * 全屏展示切换
-         */
-        handleFullscreen (id) {
-            this.dialogPreviewVisible = true
-            this.id = id
-        },
-        // 处理收缩/展开
-        handleCollapseExpansion (index, isCollapse) {
-            this.layout[index].h = isCollapse ? 1.34 : this.defaultData[index].h
-            this.layout.push({ i: '0' })
-            const deleteIndex = this.layout.findIndex(item => item.i === '0')
-            this.layout.splice(deleteIndex, 1)
-        },
-        handleApprove (params) {
-            this.ibpsNewsDialogVisible = true
-            this.newsEditId = params.id || params
-            this.newsTitle = params.title || this.newsTitle
-        },
-        handleUnreadMessage (params) {
-            this.messageEditId = params.id || params
-            this.messageTableId = params.tableId || ''
-            this.messageTableName = params.tableName || ''
-            this.ibpsMessageDialogVisible = true
-        },
-        handleFlow (params) {
-            this.defId = params.defId || null
-            this.taskId = params.taskId || null
-            this.instanceId = params.instanceId || null
-            this.flowName = params.flowName || null
-            this.bpmnFormrenderDialogVisible = true
-        },
-        handleFlowCallback () {
-            this.$refs[this.alias] ? this.$refs[this.alias][0].refreshData() : null
-        },
-        handleMessageCallback (isRead) {
-            if (isRead && this.$refs.unreadMessage) {
-                this.$refs.unreadMessage[0].refreshData()
-            }
-        },
-        initSystemUrl (url) {
-            if (url.startsWith('http')) {
-                this.systemUrlType = 'iframe'
-                this.$nextTick(() => {
-                    this.$refs.systemrender.src = url
-                    // 传递消息
-                    // this.$refs.systemrender.contentWindow.postMessage({ data: this.attributes }, '*')
-                })
-            } else {
-                const component = url.split('?')[0]
-                this.systemUrlParams.attrs = this.urlParse(url)
-                this.systemUrlType = 'inner'
-                const systemUrlName = 'IbpsBpmnSystemUrl'
-                this.$options.components[systemUrlName] = _import(component)
-                this.systemUrlName = systemUrlName
-            }
-        },
-        urlParse (str) {
-            const obj = {}
-            if (str.indexOf('?') !== -1) {
-                const str1 = str.split('?')[1].split('&')
-                for (let i = 0; i < str1.length; i++) {
-                    const params = str1[i].split('=')
-                    obj[params[0]] = params[1]
-                }
-            }
-            return obj
-        },
-        /* 文件类型*/
-        beforeUpload (file) {
-            var testmsg = file.name.substring(file.name.lastIndexOf('.') + 1)
-            const extension = testmsg === 'xls'
-            const extension2 = testmsg === 'xlsx'
-            if (!extension && !extension2) {
-                this.$message({
-                    message: '上传文件只能是excel格式!',
-                    type: 'warning'
-                })
-                return false
-            }
-            return extension || extension2
-        },
-        /* 文件类型*/
-        ReportBeforeUpload (file) {
-            var testmsg = file.name.substring(file.name.lastIndexOf('.') + 1)
-            const extension = testmsg === 'rpx'
-            if (!extension) {
-                this.$message({
-                    message: '上传文件只能是rpx格式!',
-                    type: 'warning'
-                })
-                return false
-            }
-            return extension
-        },
+    /**
+     * 全屏展示切换
+     */
+    handleFullscreen(id) {
+      this.dialogPreviewVisible = true;
+      this.id = id;
+    },
+    // 处理收缩/展开
+    handleCollapseExpansion(index, isCollapse) {
+      this.layout[index].h = isCollapse ? 1.34 : this.defaultData[index].h;
+      this.layout.push({ i: "0" });
+      const deleteIndex = this.layout.findIndex((item) => item.i === "0");
+      this.layout.splice(deleteIndex, 1);
+    },
+    handleApprove(params) {
+      this.ibpsNewsDialogVisible = true;
+      this.newsEditId = params.id || params;
+      this.newsTitle = params.title || this.newsTitle;
+    },
+    handleUnreadMessage(params) {
+      this.messageEditId = params.id || params;
+      this.messageTableId = params.tableId || "";
+      this.messageTableName = params.tableName || "";
+      this.ibpsMessageDialogVisible = true;
+    },
+    handleFlow(params) {
+      this.defId = params.defId || null;
+      this.taskId = params.taskId || null;
+      this.instanceId = params.instanceId || null;
+      this.flowName = params.flowName || null;
+      this.bpmnFormrenderDialogVisible = true;
+    },
+    handleFlowCallback() {
+      this.$refs[this.alias] ? this.$refs[this.alias][0].refreshData() : null;
+    },
+    handleMessageCallback(isRead) {
+      if (isRead && this.$refs.unreadMessage) {
+        this.$refs.unreadMessage[0].refreshData();
+      }
+    },
+    initSystemUrl(url) {
+      if (url.startsWith("http")) {
+        this.systemUrlType = "iframe";
+        this.$nextTick(() => {
+          this.$refs.systemrender.src = url;
+          // 传递消息
+          // this.$refs.systemrender.contentWindow.postMessage({ data: this.attributes }, '*')
+        });
+      } else {
+        const component = url.split("?")[0];
+        this.systemUrlParams.attrs = this.urlParse(url);
+        this.systemUrlType = "inner";
+        const systemUrlName = "IbpsBpmnSystemUrl";
+        this.$options.components[systemUrlName] = _import(component);
+        this.systemUrlName = systemUrlName;
+      }
+    },
+    urlParse(str) {
+      const obj = {};
+      if (str.indexOf("?") !== -1) {
+        const str1 = str.split("?")[1].split("&");
+        for (let i = 0; i < str1.length; i++) {
+          const params = str1[i].split("=");
+          obj[params[0]] = params[1];
+        }
+      }
+      return obj;
+    },
+    /* 文件类型*/
+    beforeUpload(file) {
+      var testmsg = file.name.substring(file.name.lastIndexOf(".") + 1);
+      const extension = testmsg === "xls";
+      const extension2 = testmsg === "xlsx";
+      if (!extension && !extension2) {
+        this.$message({
+          message: "上传文件只能是excel格式!",
+          type: "warning",
+        });
+        return false;
+      }
+      return extension || extension2;
+    },
+    /* 文件类型*/
+    ReportBeforeUpload(file) {
+      var testmsg = file.name.substring(file.name.lastIndexOf(".") + 1);
+      const extension = testmsg === "rpx";
+      if (!extension) {
+        this.$message({
+          message: "上传文件只能是rpx格式!",
+          type: "warning",
+        });
+        return false;
+      }
+      return extension;
+    },
 
-        handleSuccess (res, file, fileList) {
-            if (res.state === 200) {
-                this.$message({
-                    message: '上传数据成功!',
-                    type: 'success'
-                })
-            } else {
-                this.$message({
-                    message: res.message,
-                    type: 'error'
-                })
-            }
+    handleSuccess(res, file, fileList) {
+      if (res.state === 200) {
+        this.$message({
+          message: "上传数据成功!",
+          type: "success",
+        });
+      } else {
+        this.$message({
+          message: res.message,
+          type: "error",
+        });
+      }
+    },
+    getPeriodTask() {
+      const { userId, role = [] } = this.$store.getters;
+      const roles = role.map((i) => i.id);
+      const sql = `select * from t_zqswtxb where shi_fou_ti_xing_ = '是' and (zhi_xing_ren_yuan like '%${userId}%' or find_in_set(zhi_xing_jiao_se_, '${roles.join(
+        ","
+      )}')) order by field(zhi_xing_zhou_qi_, '1次/天', '1次/周', '1次/月', '1次/季度', '1次/半年', '1次/年')`;
+      this.$common
+        .request("sql", sql)
+        .then((res) => {
+          const { data = [] } = res.variables || {};
+          if (data.length) {
+            this.showMsg(data);
+          }
+        })
+        .catch((error) => {
+          this.$message.error("获取周期事务信息失败!");
+          console.log(error);
+        });
+    },
+    showMsg(data) {
+      const h = this.$createElement;
+      const text = {
+        "1次/天": "本日",
+        "1次/周": "本周",
+        "1次/月": "本月",
+        "1次/季度": "本季度",
+        "1次/半年": "近半年",
+        "1次/年": "本年度",
+      };
+      const result = data.reduce((acc, item) => {
+        const key = item.zhi_xing_zhou_qi_;
+        if (!acc[key]) {
+          acc[key] = [];
+        }
+        acc[key].push({
+          name: item.shi_wu_ming_cheng,
+          path: item.ye_mian_lu_jing_,
+        });
+        return acc;
+      }, {});
+      const msg = [];
+      const doNotShowBtn = h(
+        "el-button",
+        {
+          attrs: {
+            size: "mini",
+            type: "primary",
+            plain: true,
+          },
+          on: {
+            click: () => {
+              this.doNotShowToday();
+            },
+          },
         },
-        getPeriodTask () {
-            const { userId, role = [] } = this.$store.getters
-            const roles = role.map(i => i.id)
-            const sql = `select * from t_zqswtxb where shi_fou_ti_xing_ = '是' and (zhi_xing_ren_yuan like '%${userId}%' or find_in_set(zhi_xing_jiao_se_, '${roles.join(',')}')) order by field(zhi_xing_zhou_qi_, '1次/天', '1次/周', '1次/月', '1次/季度', '1次/半年', '1次/年')`
-            this.$common.request('sql', sql).then(res => {
-                const { data = [] } = res.variables || {}
-                if (data.length) {
-                    this.showMsg(data)
-                }
-            }).catch(error => {
-                this.$message.error('获取周期事务信息失败!')
-                console.log(error)
-            })
+        "今日不再提示"
+      );
+      const confirmBtn = h(
+        "el-button",
+        {
+          attrs: {
+            size: "mini",
+            type: "success",
+            plain: true,
+          },
+          on: {
+            click: () => {
+              this.infoMessage.close();
+            },
+          },
         },
-        showMsg (data) {
-            const h = this.$createElement
-            const text = {
-                '1次/天': '本日',
-                '1次/周': '本周',
-                '1次/月': '本月',
-                '1次/季度': '本季度',
-                '1次/半年': '近半年',
-                '1次/年': '本年度'
-            }
-            const result = data.reduce((acc, item) => {
-                const key = item.zhi_xing_zhou_qi_
-                if (!acc[key]) {
-                    acc[key] = []
-                }
-                acc[key].push({
-                    name: item.shi_wu_ming_cheng,
-                    path: item.ye_mian_lu_jing_
-                })
-                return acc
-            }, {})
-            const msg = []
-            const doNotShowBtn = h('el-button', {
-                attrs: {
-                    size: 'mini',
-                    type: 'primary',
-                    plain: true
+        "确认"
+      );
+      Object.keys(result).forEach((key) => {
+        // msg.push(h('p', {style: {
+        //     'font-weight': 'bold',
+        //     'color': '#666',
+        //     'font-size': '16px'
+        // }}, key))
+        // result[key].forEach(i => {
+        //     msg.push(h('span', null, i))
+        //     msg.push(h('br'))
+        // })
+        const ul = [text[key]];
+        result[key].forEach((i) => {
+          ul.push(
+            h(
+              "li",
+              {
+                style: {
+                  "font-weight": "normal",
+                  color: "#666",
+                  "font-size": "14px",
+                  cursor: "pointer",
                 },
                 on: {
-                    click: () => {
-                        this.doNotShowToday()
-                    }
-                }
-            }, '今日不再提示')
-            const confirmBtn = h('el-button', {
-                attrs: {
-                    size: 'mini',
-                    type: 'success',
-                    plain: true
+                  click: () => {
+                    this.infoMessage.close();
+                    this.$router.push(i.path);
+                  },
                 },
-                on: {
-                    click: () => {
-                        this.infoMessage.close()
-                    }
-                }
-            }, '确认')
-            Object.keys(result).forEach(key => {
-                // msg.push(h('p', {style: {
-                //     'font-weight': 'bold',
-                //     'color': '#666',
-                //     'font-size': '16px'
-                // }}, key))
-                // result[key].forEach(i => {
-                //     msg.push(h('span', null, i))
-                //     msg.push(h('br'))
-                // })
-                const ul = [text[key]]
-                result[key].forEach(i => {
-                    ul.push(h('li', {
-                        style: {
-                            'font-weight': 'normal',
-                            'color': '#666',
-                            'font-size': '14px',
-                            'cursor': 'pointer'
-                        },
-                        on: {
-                            click: () => {
-                                this.infoMessage.close()
-                                this.$router.push(i.path)
-                            }
-                        }
-                    }, i.name))
-                })
-                msg.push(h('ul', { style: {
-                    'font-weight': 'bold',
-                    'color': '#000',
-                    'font-size': '16px',
-                    'margin': '0',
-                    'padding': '0',
-                    'margin-bottom': '5px'
-                }}, ul))
-            })
-            msg.push(doNotShowBtn, confirmBtn)
-            window.setTimeout(() => {
-                this.infoMessage = this.$notify({
-                    title: '以下是您的周期性事务提示',
-                    message: h('div', null, msg),
-                    duration: 0,
-                    iconClass: 'el-icon-bell',
-                    showClose: false
-                })
-            }, 0)
-        },
-        doNotShowToday () {
-            const today = new Date().toLocaleDateString()
-            localStorage.setItem('doNotShowToday', today)
-            this.infoMessage.close()
-        },
-        /**
-         * 关于预览日历日程组件的方法及属性,在预览处也有相同的逻辑
-         */
-        // 关闭指定弹框
-        handleClose (state) {
-            switch (state) {
-                case 'calendar':
-                    this.calendarDialogVisible = false
-                    break
-                default:
-                    break
-            }
-        },
-        // 打开指定弹框
-        handleOpen (state, dateArr, events, clickId) {
-            const status = ['急', '重', '轻', '缓']
-            const eventTrees = []
-            switch (state) {
-                case 'calendar':
-                    this.calendarDialogVisible = true
-                    for (const i of events) {
-                        // 根据指定日期A获取A在时间区间内的数据
-                        if (!((this.compareDates(i.start, dateArr[1]) > 0) || (this.compareDates(i.jieShuShiJian, dateArr[0]) < 0))) {
-                            i.label = i.zhuangTai ? `【${status[Number(i.zhuangTai) - 1] ? status[Number(i.zhuangTai) - 1] : ''}】` + i.title : i.title
-                            eventTrees.push(i)
-                        }
-                    }
-                    this.calendarDialogForm = {
-                        eventTrees: eventTrees.length ? eventTrees : []
-                    }
-                    this.calendarDialogForm.clickedDate = dateArr[0]
-                    this.calendarDialogForm.clickId = clickId
-                    break
-                default:
-                    break
-            }
-        },
-        /**
-         * date1(2024-01-01) 大于 date2(2023-01-01) 返回 1
-         * date1 小于 date2 返回 -1
-         * date1 等于 date2 返回 0
-         */
-        compareDates (date1, date2) {
-            var time1 = new Date(date1).getTime()
-            var time2 = new Date(date2).getTime()
-            return Math.sign(time1 - time2) // 使用Math.sign()函数返回值为 -1, 0, 1
-        },
-        // 日历弹框组件保存时候的回调
-        handleSaveData (param) {
-            if (param.state === 'calendar') {
-                this.$refs.myCalendar[0].setCalendarEvents(param)
-            }
-        },
-        // 日历弹框组件删除日程时候的回调
-        handleDelData (param) {
-            if (param.state === 'calendar') {
-                this.$refs.myCalendar[0].hanldeCalendardel(param)
+              },
+              i.name
+            )
+          );
+        });
+        msg.push(
+          h(
+            "ul",
+            {
+              style: {
+                "font-weight": "bold",
+                color: "#000",
+                "font-size": "16px",
+                margin: "0",
+                padding: "0",
+                "margin-bottom": "5px",
+              },
+            },
+            ul
+          )
+        );
+      });
+      msg.push(doNotShowBtn, confirmBtn);
+      window.setTimeout(() => {
+        this.infoMessage = this.$notify({
+          title: "以下是您的周期性事务提示",
+          message: h("div", null, msg),
+          duration: 0,
+          iconClass: "el-icon-bell",
+          showClose: false,
+        });
+      }, 0);
+    },
+    doNotShowToday() {
+      const today = new Date().toLocaleDateString();
+      localStorage.setItem("doNotShowToday", today);
+      this.infoMessage.close();
+    },
+    /**
+     * 关于预览日历日程组件的方法及属性,在预览处也有相同的逻辑
+     */
+    // 关闭指定弹框
+    handleClose(state) {
+      switch (state) {
+        case "calendar":
+          this.calendarDialogVisible = false;
+          break;
+        default:
+          break;
+      }
+    },
+    // 打开指定弹框
+    handleOpen(state, dateArr, events, clickId) {
+      const status = ["急", "重", "轻", "缓"];
+      const eventTrees = [];
+      switch (state) {
+        case "calendar":
+          this.calendarDialogVisible = true;
+          for (const i of events) {
+            // 根据指定日期A获取A在时间区间内的数据
+            if (
+              !(
+                this.compareDates(i.start, dateArr[1]) > 0 ||
+                this.compareDates(i.jieShuShiJian, dateArr[0]) < 0
+              )
+            ) {
+              i.label = i.zhuangTai
+                ? `【${
+                    status[Number(i.zhuangTai) - 1]
+                      ? status[Number(i.zhuangTai) - 1]
+                      : ""
+                  }】` + i.title
+                : i.title;
+              eventTrees.push(i);
             }
-        }
-    }
-}
+          }
+          this.calendarDialogForm = {
+            eventTrees: eventTrees.length ? eventTrees : [],
+          };
+          this.calendarDialogForm.clickedDate = dateArr[0];
+          this.calendarDialogForm.clickId = clickId;
+          break;
+        default:
+          break;
+      }
+    },
+    /**
+     * date1(2024-01-01) 大于 date2(2023-01-01) 返回 1
+     * date1 小于 date2 返回 -1
+     * date1 等于 date2 返回 0
+     */
+    compareDates(date1, date2) {
+      var time1 = new Date(date1).getTime();
+      var time2 = new Date(date2).getTime();
+      return Math.sign(time1 - time2); // 使用Math.sign()函数返回值为 -1, 0, 1
+    },
+    // 日历弹框组件保存时候的回调
+    handleSaveData(param) {
+      if (param.state === "calendar") {
+        this.$refs.myCalendar[0].setCalendarEvents(param);
+      }
+    },
+    // 日历弹框组件删除日程时候的回调
+    handleDelData(param) {
+      if (param.state === "calendar") {
+        this.$refs.myCalendar[0].hanldeCalendardel(param);
+      }
+    },
+  },
+};
 </script>
 
 <style lang="scss" scoped>
-    @import '~@/assets/styles/public.scss';
-    .ibps-desktop-page {
-        .ibps-container-frame {
-            position: absolute;
-            top: 0px;
-            left: 0px;
-            height: 100%;
-            width: 100%;
-        }
+@import "~@/assets/styles/public.scss";
+.ibps-desktop-page {
+  .ibps-container-frame {
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    height: 100%;
+    width: 100%;
+  }
 
-        .ibps-grid-item, .el-card {
-            height: 100%;
-        }
-        .vue-grid-layout {
-            border-radius: 4px;
-            // margin: -10px;
-            .page_card {
-                height: 100%;
-                @extend %unable-select;
-            }
-            .vue-resizable-handle {
-                opacity: 0.3;
-                &:hover {
-                    opacity: 1;
-                }
-            }
-        }
+  .ibps-grid-item,
+  .el-card {
+    height: 100%;
+  }
+  .vue-grid-layout {
+    border-radius: 4px;
+    // margin: -10px;
+    .page_card {
+      height: 100%;
+      @extend %unable-select;
     }
+    .vue-resizable-handle {
+      opacity: 0.3;
+      &:hover {
+        opacity: 1;
+      }
+    }
+  }
+}
 </style>
 
 <style lang="scss">
-    .ibps-desktop-dashboard {
-        .item {
-            position: relative;
-            margin: 12px;
-            padding: 12px;
-            height: 90px;
-            border-radius: 4px;
-            box-sizing: border-box;
-            overflow: hidden;
-            color: #fff;
-        }
-        .item-header {
-            position: relative;
-            & > p {
-                margin: 0px;
-                font-size: 14px;
-            }
-            & > span {
-                position: absolute;
-                right: 0px;
-                top: 0px;
-                padding: 2px 8px;
-                border-radius: 4px;
-                font-size: 12px;
-                background: rgba(255, 255, 255, 0.3);
-            }
-        }
-        .item-body {
-            & > h2 {
-                margin: 0;
-                font-size: 32px;
-                line-height: 60px;
-            }
-        }
-        .item-tip {
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            position: absolute;
-            width: 80px;
-            height: 80px;
-            bottom: -35px;
-            right: 50px;
-            border: 2px solid #fff;
-            border-radius: 100%;
-            font-size: 48px;
-            transform: rotate(-40deg);
-            opacity: 0.1;
-        }
+.ibps-desktop-dashboard {
+  .item {
+    position: relative;
+    margin: 12px;
+    padding: 12px;
+    height: 90px;
+    border-radius: 4px;
+    box-sizing: border-box;
+    overflow: hidden;
+    color: #fff;
+  }
+  .item-header {
+    position: relative;
+    & > p {
+      margin: 0px;
+      font-size: 14px;
     }
-    .fc .fc-toolbar.fc-header-toolbar{
-        margin-top: -1em;
-        margin-bottom: 0em;
-        font-size: 10px;
+    & > span {
+      position: absolute;
+      right: 0px;
+      top: 0px;
+      padding: 2px 8px;
+      border-radius: 4px;
+      font-size: 12px;
+      background: rgba(255, 255, 255, 0.3);
     }
+  }
+  .item-body {
+    & > h2 {
+      margin: 0;
+      font-size: 32px;
+      line-height: 60px;
+    }
+  }
+  .item-tip {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    position: absolute;
+    width: 80px;
+    height: 80px;
+    bottom: -35px;
+    right: 50px;
+    border: 2px solid #fff;
+    border-radius: 100%;
+    font-size: 48px;
+    transform: rotate(-40deg);
+    opacity: 0.1;
+  }
+}
+.fc .fc-toolbar.fc-header-toolbar {
+  margin-top: -1em;
+  margin-bottom: 0em;
+  font-size: 10px;
+}
 </style>