mirror of
https://github.com/thousmile/molly-multi-tenant.git
synced 2025-12-30 04:32:26 +00:00
1.修改 推送数据内容
2.修改 web-ui 推送组件
This commit is contained in:
@@ -21,6 +21,8 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.xaaef.molly.system.cron.TestCronAsync.randomChinese;
|
||||
|
||||
|
||||
@SpringBootTest
|
||||
public class MollyApplicationTests {
|
||||
@@ -75,13 +77,4 @@ public class MollyApplicationTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String randomChinese(int len) {
|
||||
var chars = new char[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
chars[i] = RandomUtil.randomChinese();
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.xaaef.molly.system.cron;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.xaaef.molly.auth.service.JwtTokenService;
|
||||
import com.xaaef.molly.common.util.IdUtils;
|
||||
import com.xaaef.molly.common.util.JsonUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -10,8 +11,10 @@ import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -40,35 +43,58 @@ public class TestCronAsync {
|
||||
"I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
|
||||
"S", "T", "U", "V", "W", "X", "Y", "Z");
|
||||
|
||||
private final static AtomicInteger count1 = new AtomicInteger(8760);
|
||||
|
||||
@Scheduled(fixedRate = 5000)
|
||||
@Scheduled(fixedRate = 30000)
|
||||
public void cron1() {
|
||||
if (!tokenService.listLoginIds().isEmpty()) {
|
||||
var ind = count1.decrementAndGet();
|
||||
var map = Map.of(
|
||||
"id", RandomUtil.randomInt(10000, 99999),
|
||||
"msg", RandomUtil.randomString(12),
|
||||
"dataArr", RandomUtil.randomEleSet(arrs, 3)
|
||||
"id", IdUtils.getStandaloneId(),
|
||||
"title", String.format("广播消息=>%d", RandomUtil.randomInt(10000, 99999)),
|
||||
"message", randomChinese(20),
|
||||
"createTime", LocalDateTime.now().minusHours(ind)
|
||||
);
|
||||
var json = JsonUtils.toJson(map);
|
||||
// 广播通知 给所有用户
|
||||
messagingTemplate.convertAndSend("/topic/broadcast/notice", json);
|
||||
if (ind == 1) {
|
||||
count2.set(8760);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Scheduled(fixedRate = 8000)
|
||||
private final static AtomicInteger count2 = new AtomicInteger(8760);
|
||||
|
||||
|
||||
@Scheduled(fixedRate = 60000)
|
||||
public void cron2() {
|
||||
var ind = count2.decrementAndGet();
|
||||
tokenService.listLoginUsers().forEach(user -> {
|
||||
var map = Map.of(
|
||||
"id", RandomUtil.randomInt(10000, 99999),
|
||||
"msg", StrUtil.format("hello : {} => {}", user.getUsername(), RandomUtil.randomString(15)),
|
||||
"dataArr", RandomUtil.randomEleSet(arrs, 3)
|
||||
"id", IdUtils.getStandaloneId(),
|
||||
"title", String.format("推送消息=>%d", RandomUtil.randomInt(10000, 99999)),
|
||||
"message", randomChinese(20),
|
||||
"createTime", LocalDateTime.now().minusHours(ind)
|
||||
);
|
||||
var json = JsonUtils.toJson(map);
|
||||
// 推送给指定用户 , /user/queue/single/push
|
||||
messagingTemplate.convertAndSendToUser(user.getLoginId(), "/queue/single/push", json);
|
||||
if (ind == 1) {
|
||||
count2.set(8760);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public static String randomChinese(int len) {
|
||||
var chars = new char[len];
|
||||
for (int i = 0; i < len; i++) {
|
||||
chars[i] = RandomUtil.randomChinese();
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts" setup>
|
||||
import { type ListItem } from "./data"
|
||||
import { IPushMessage } from "@/types/base"
|
||||
|
||||
interface Props {
|
||||
list: ListItem[]
|
||||
list: IPushMessage[]
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
@@ -14,19 +14,13 @@ const props = defineProps<Props>()
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<div>
|
||||
<span>
|
||||
<span class="card-title">{{ item.title }}</span>
|
||||
<el-tag v-if="item.extra" :type="item.status" effect="plain" size="small">{{ item.extra }}</el-tag>
|
||||
</span>
|
||||
<div class="card-time">{{ item.datetime }}</div>
|
||||
</div>
|
||||
<div v-if="item.avatar" class="card-avatar">
|
||||
<img :src="item.avatar" width="34" />
|
||||
<span class="card-title">{{ item.title }}</span>
|
||||
<div class="card-time">{{ item.createTime }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="card-body">
|
||||
{{ item.description ?? "No Data" }}
|
||||
{{ item.message ?? "No Data" }}
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
@@ -34,25 +28,29 @@ const props = defineProps<Props>()
|
||||
<style lang="scss" scoped>
|
||||
.card-container {
|
||||
margin-bottom: 10px;
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.card-title {
|
||||
font-weight: bold;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.card-time {
|
||||
font-size: 12px;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.card-avatar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.card-body {
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
}</style>
|
||||
|
||||
@@ -3,14 +3,17 @@ import { ref, computed } from "vue"
|
||||
import { ElMessage } from "element-plus"
|
||||
import { Bell } from "@element-plus/icons-vue"
|
||||
import NotifyList from "./NotifyList.vue"
|
||||
import { type ListItem, notifyData, messageData, todoData } from "./data"
|
||||
import { useNoticeStoreHook } from "@/store/modules/notice"
|
||||
import { IPushMessage } from "@/types/base"
|
||||
|
||||
const { broadcast, pushNotices } = useNoticeStoreHook()
|
||||
|
||||
type TabName = "通知" | "消息" | "待办"
|
||||
|
||||
interface DataItem {
|
||||
name: TabName
|
||||
type: "primary" | "success" | "warning" | "danger" | "info"
|
||||
list: ListItem[]
|
||||
list: IPushMessage[]
|
||||
}
|
||||
|
||||
/** 角标当前值 */
|
||||
@@ -29,19 +32,19 @@ const data = ref<DataItem[]>([
|
||||
{
|
||||
name: "通知",
|
||||
type: "primary",
|
||||
list: notifyData
|
||||
list: broadcast
|
||||
},
|
||||
// 消息数据
|
||||
{
|
||||
name: "消息",
|
||||
type: "danger",
|
||||
list: messageData
|
||||
list: pushNotices
|
||||
},
|
||||
// 待办数据
|
||||
{
|
||||
name: "待办",
|
||||
type: "warning",
|
||||
list: todoData
|
||||
list: []
|
||||
}
|
||||
])
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
<el-pagination
|
||||
v-model:current-page="params.pageIndex"
|
||||
:page-size="params.pageSize"
|
||||
:page-sizes="[5, 10, 20, 50]"
|
||||
:background="true"
|
||||
layout="sizes, total, prev, pager, next, jumper"
|
||||
:total="params.pageTotal"
|
||||
@@ -73,7 +74,7 @@ const loading = ref(false)
|
||||
const params = reactive({
|
||||
pageTotal: 0,
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 5,
|
||||
keywords: ""
|
||||
})
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
<el-pagination
|
||||
v-model:current-page="params.pageIndex"
|
||||
:page-size="params.pageSize"
|
||||
:page-sizes="[5, 10, 20, 50]"
|
||||
:background="true"
|
||||
layout="sizes, total, prev, pager, next, jumper"
|
||||
:total="params.pageTotal"
|
||||
@@ -73,7 +74,7 @@ const loading = ref(false)
|
||||
const params = reactive({
|
||||
pageTotal: 0,
|
||||
pageIndex: 1,
|
||||
pageSize: 10,
|
||||
pageSize: 5,
|
||||
keywords: ""
|
||||
})
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { type RouteLocationNormalized } from "vue-router"
|
||||
const loginUrl = "/login"
|
||||
|
||||
/** 免登录白名单(匹配路由 path) */
|
||||
const whiteListByPath: string[] = ["/login"]
|
||||
const whiteListByPath: string[] = [loginUrl]
|
||||
|
||||
/** 免登录白名单(匹配路由 name) */
|
||||
const whiteListByName: string[] = []
|
||||
|
||||
@@ -14,6 +14,7 @@ interface PaginationData {
|
||||
pageSizes?: number[]
|
||||
pageSize?: number
|
||||
layout?: string
|
||||
keywords?: string
|
||||
}
|
||||
|
||||
/** 默认的分页参数 */
|
||||
@@ -25,16 +26,20 @@ const defaultPaginationData: DefaultPaginationData = {
|
||||
layout: "total, sizes, prev, pager, next, jumper"
|
||||
}
|
||||
|
||||
export function usePagination(initialPaginationData: PaginationData = {}) {
|
||||
export function usePagination(fn: Function, initialPaginationData: PaginationData = {}) {
|
||||
/** 合并分页参数 */
|
||||
const paginationData = reactive({ ...defaultPaginationData, ...initialPaginationData })
|
||||
|
||||
/** 改变当前页码 */
|
||||
const handleCurrentChange = (value: number) => {
|
||||
paginationData.currentPage = value
|
||||
fn()
|
||||
}
|
||||
|
||||
/** 改变页面大小 */
|
||||
const handleSizeChange = (value: number) => {
|
||||
paginationData.pageSize = value
|
||||
fn()
|
||||
}
|
||||
|
||||
return { paginationData, handleCurrentChange, handleSizeChange }
|
||||
|
||||
@@ -5,12 +5,12 @@ import { useTenantStoreHook } from "@/store/modules/tenant"
|
||||
const projectStore = useProjectStoreHook()
|
||||
const tenantStore = useTenantStoreHook()
|
||||
|
||||
// 租户ID 和 项目 组成的 唯一ID
|
||||
const currentOnlyId = computed(() => {
|
||||
return tenantStore.getCurrentTenantId() + projectStore.getCurrentProjectId()
|
||||
})
|
||||
|
||||
export function useTenantAndProject() {
|
||||
// 租户ID 和 项目 组成的 唯一ID
|
||||
const currentOnlyId = computed(() => {
|
||||
return tenantStore.getCurrentTenantId() + projectStore.getCurrentProjectId()
|
||||
})
|
||||
|
||||
return {
|
||||
currentOnlyId
|
||||
}
|
||||
|
||||
@@ -7,13 +7,14 @@ import SockJS from "sockjs-client/dist/sockjs.min.js"
|
||||
import { getToken } from "@/utils/cache/cookies"
|
||||
import { useTenantStoreHook } from "./tenant"
|
||||
import { getEnvBaseURL } from "@/utils"
|
||||
import { IPushMessage } from "@/types/base"
|
||||
|
||||
export const useNoticeStore = defineStore("notice", () => {
|
||||
// 广播消息
|
||||
const broadcast = ref<any[]>([])
|
||||
const broadcast = ref<IPushMessage[]>([])
|
||||
|
||||
// 推送消息
|
||||
const pushNotices = ref<any[]>([])
|
||||
const pushNotices = ref<IPushMessage[]>([])
|
||||
|
||||
const stompClientActive = ref<boolean>(false)
|
||||
|
||||
@@ -51,15 +52,13 @@ export const useNoticeStore = defineStore("notice", () => {
|
||||
|
||||
// 订阅广播主题
|
||||
stompClientAgent.subscribe("/topic/broadcast/notice", (resp) => {
|
||||
const result = JSON.parse(resp.body)
|
||||
console.log("广播 :>> ", result)
|
||||
const result = JSON.parse(resp.body) as IPushMessage
|
||||
broadcast.value?.push(result)
|
||||
})
|
||||
|
||||
// 订阅推送主题
|
||||
stompClientAgent.subscribe("/user/queue/single/push", (resp) => {
|
||||
const result = JSON.parse(resp.body)
|
||||
console.log("推送 :>> ", result)
|
||||
const result = JSON.parse(resp.body) as IPushMessage
|
||||
pushNotices.value?.push(result)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -99,3 +99,15 @@ export interface IUpdateMenus {
|
||||
/** 全部的菜单 */
|
||||
all: ISimpleMenu[]
|
||||
}
|
||||
|
||||
// 推送消息
|
||||
export interface IPushMessage {
|
||||
/** ID */
|
||||
id: number
|
||||
/** 标题 */
|
||||
title: string
|
||||
/** 消息 */
|
||||
message: string
|
||||
/** 创建时间 */
|
||||
createTime: string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user