|
@@ -0,0 +1,305 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="msg">
|
|
|
|
|
+ <div class="msg-title">
|
|
|
|
|
+ 通知消息
|
|
|
|
|
+ <el-button round size="small" @click="setAllRead()">全部已读</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="msg-type">
|
|
|
|
|
+ <div class="msg-type-item" v-for="(item, index) in msgType" :key="index" @click="getMsgList(item.msgType)">
|
|
|
|
|
+ <el-badge :value="item.total" :max="99" :hidden="item.total==0" class="item">
|
|
|
|
|
+ <el-button round size="small">{{item.msgTypeName}}</el-button>
|
|
|
|
|
+ </el-badge>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="mst-list">
|
|
|
|
|
+ <el-timeline>
|
|
|
|
|
+ <el-timeline-item :timestamp="item.createTime" placement="top" v-for="(item, index) in list" :key="index">
|
|
|
|
|
+ <el-card>
|
|
|
|
|
+ <h4>{{item.title}}</h4>
|
|
|
|
|
+ <p>{{item.content}}</p>
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <el-button type="text" v-if="item.isRead==0" @click="setRead(item)">标记为已读</el-button>
|
|
|
|
|
+ <el-button type="text" @click="showDetail(item)">查看详情</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </el-card>
|
|
|
|
|
+ </el-timeline-item>
|
|
|
|
|
+ </el-timeline>
|
|
|
|
|
+ <div v-if="isMore" class="more" @click="loadMore()">
|
|
|
|
|
+ <el-button type="text">加载更多</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <el-dialog
|
|
|
|
|
+ title="消息详情"
|
|
|
|
|
+ :visible.sync="detailVisible"
|
|
|
|
|
+ width="480px"
|
|
|
|
|
+ :close-on-click-modal="false"
|
|
|
|
|
+ :append-to-body="true"
|
|
|
|
|
+ :modal-append-to-body="true"
|
|
|
|
|
+ custom-class="msg-detail-dialog"
|
|
|
|
|
+ center
|
|
|
|
|
+ >
|
|
|
|
|
+ <div class="msg-content">
|
|
|
|
|
+ <div class="msg-icon">
|
|
|
|
|
+ <i class="el-icon-bell"></i>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="msg-text">
|
|
|
|
|
+ <h3>{{ detailData.title }}</h3>
|
|
|
|
|
+ <p>{{ detailData.content }}</p>
|
|
|
|
|
+ <div class="msg-time" v-if="detailData.createTime">
|
|
|
|
|
+ <i class="el-icon-time"></i>
|
|
|
|
|
+ {{ detailData.createTime }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <span slot="footer" class="dialog-footer">
|
|
|
|
|
+ <el-button @click="closeDetail" size="medium">关闭</el-button>
|
|
|
|
|
+ <el-button type="primary" @click="goToProcess" size="medium" v-if="detailData.actionUrl">
|
|
|
|
|
+ <i class="el-icon-right"></i> 去处理
|
|
|
|
|
+ </el-button>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </el-dialog>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script>
|
|
|
|
|
+import { setAllRead, getMsg, getMsgList, getMsgCount, setRead } from "@/api/crm/msg";
|
|
|
|
|
+
|
|
|
|
|
+export default {
|
|
|
|
|
+ name: "msg",
|
|
|
|
|
+ data() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ isMore: false,
|
|
|
|
|
+ currentTypeId: undefined,
|
|
|
|
|
+ msgType: [],
|
|
|
|
|
+ loading: true,
|
|
|
|
|
+ ids: [],
|
|
|
|
|
+ single: true,
|
|
|
|
|
+ multiple: true,
|
|
|
|
|
+ showSearch: true,
|
|
|
|
|
+ total: 0,
|
|
|
|
|
+ list: [],
|
|
|
|
|
+ queryParams: {
|
|
|
|
|
+ pageNum: 1,
|
|
|
|
|
+ pageSize: 10,
|
|
|
|
|
+ },
|
|
|
|
|
+ detailVisible: false,
|
|
|
|
|
+ detailData: {
|
|
|
|
|
+ msgId: null,
|
|
|
|
|
+ title: '',
|
|
|
|
|
+ content: '',
|
|
|
|
|
+ actionUrl: '',
|
|
|
|
|
+ createTime: ''
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ },
|
|
|
|
|
+ created() {
|
|
|
|
|
+ this.getMsg();
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ loadMore() {
|
|
|
|
|
+ this.queryParams.pageNum += 1;
|
|
|
|
|
+ this.getList();
|
|
|
|
|
+ },
|
|
|
|
|
+ getMsg() {
|
|
|
|
|
+ getMsg().then(response => {
|
|
|
|
|
+ this.msgType = response.counts;
|
|
|
|
|
+ if (this.currentTypeId == undefined) {
|
|
|
|
|
+ this.currentTypeId = this.msgType[0].msgType;
|
|
|
|
|
+ }
|
|
|
|
|
+ this.list = [];
|
|
|
|
|
+ this.getList();
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ setAllRead() {
|
|
|
|
|
+ setAllRead().then(response => {
|
|
|
|
|
+ this.getMsg();
|
|
|
|
|
+ this.$emit('update-count');
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ setRead(row) {
|
|
|
|
|
+ row.isRead = 1;
|
|
|
|
|
+ setRead(row).then(response => {
|
|
|
|
|
+ this.getMsg();
|
|
|
|
|
+ this.$emit('update-count');
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ getMsgList(typeId) {
|
|
|
|
|
+ this.currentTypeId = typeId;
|
|
|
|
|
+ this.queryParams.pageNum = 1;
|
|
|
|
|
+ this.list = [];
|
|
|
|
|
+ this.getList();
|
|
|
|
|
+ },
|
|
|
|
|
+ getList() {
|
|
|
|
|
+ this.loading = true;
|
|
|
|
|
+ this.queryParams.type = this.currentTypeId;
|
|
|
|
|
+ getMsgList(this.queryParams).then(response => {
|
|
|
|
|
+ this.list = this.list.concat(response.data.list);
|
|
|
|
|
+ this.total = response.data.total;
|
|
|
|
|
+ this.loading = false;
|
|
|
|
|
+ this.isMore = response.data.hasNextPage;
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
|
|
+ showDetail(item) {
|
|
|
|
|
+ this.detailData = item;
|
|
|
|
|
+ this.detailVisible = true;
|
|
|
|
|
+ },
|
|
|
|
|
+ closeDetail() {
|
|
|
|
|
+ this.detailVisible = false;
|
|
|
|
|
+ },
|
|
|
|
|
+ goToProcess() {
|
|
|
|
|
+ if (this.detailData.msgId && this.detailData.isRead == 0) {
|
|
|
|
|
+ this.detailData.isRead = 1;
|
|
|
|
|
+ setRead(this.detailData).then(() => {
|
|
|
|
|
+ this.getMsg();
|
|
|
|
|
+ this.$emit('update-count');
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ this.detailVisible = false;
|
|
|
|
|
+ if (this.detailData.actionUrl) {
|
|
|
|
|
+ let url = this.detailData.actionUrl;
|
|
|
|
|
+ if (url.endsWith('/index')) {
|
|
|
|
|
+ url = url.slice(0, -6)
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!url.startsWith('/')) {
|
|
|
|
|
+ url = '/' + url
|
|
|
|
|
+ }
|
|
|
|
|
+ this.$router.push({ path: url }).catch(err => {
|
|
|
|
|
+ console.error('路由跳转失败:', err)
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style scoped>
|
|
|
|
|
+.msg {
|
|
|
|
|
+ padding: 15px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.dialog-footer {
|
|
|
|
|
+ margin-top: 30px;
|
|
|
|
|
+ float: right;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-type {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: row;
|
|
|
|
|
+ flex-wrap: wrap;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-type-item {
|
|
|
|
|
+ margin: 10px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.mst-list {
|
|
|
|
|
+ margin: 10px 0px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-detail-dialog {
|
|
|
|
|
+ border-radius: 12px;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-content {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: flex-start;
|
|
|
|
|
+ padding: 24px 16px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-icon {
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+ width: 56px;
|
|
|
|
|
+ height: 56px;
|
|
|
|
|
+ border-radius: 50%;
|
|
|
|
|
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ margin-right: 20px;
|
|
|
|
|
+ box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-icon i {
|
|
|
|
|
+ font-size: 28px;
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-text {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-text h3 {
|
|
|
|
|
+ margin: 0 0 12px 0;
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ color: #303133;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-text p {
|
|
|
|
|
+ margin: 0 0 12px 0;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ color: #606266;
|
|
|
|
|
+ line-height: 1.6;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-time {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ color: #909399;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-time i {
|
|
|
|
|
+ margin-right: 4px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.dialog-footer {
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ padding: 10px 20px 20px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.dialog-footer .el-button {
|
|
|
|
|
+ min-width: 100px;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|
|
|
|
|
+
|
|
|
|
|
+<style>
|
|
|
|
|
+.el-drawer__header {
|
|
|
|
|
+ margin-bottom: 10px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.more {
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ font-size: 14px;
|
|
|
|
|
+ color: #909399;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-title {
|
|
|
|
|
+ margin: 10px 10px 20px 10px;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-detail-dialog .el-dialog__header {
|
|
|
|
|
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
|
|
+ padding: 16px 20px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-detail-dialog .el-dialog__title {
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ font-size: 16px;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-detail-dialog .el-dialog__headerbtn .el-dialog__close {
|
|
|
|
|
+ color: #fff;
|
|
|
|
|
+ font-size: 18px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.msg-detail-dialog .el-dialog__body {
|
|
|
|
|
+ padding: 0;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|