Former-commit-id: ecbba4384964ab453d345736cd790ddd7e9e84b1
This commit is contained in:
april
2023-06-05 19:29:15 +08:00
15 changed files with 1847 additions and 883 deletions

View File

@@ -2,6 +2,7 @@
* 登录用户信息
*/
export interface UserInfo {
userId: number;
nickname: string;
avatar: string;
roles: string[];

View File

@@ -0,0 +1,27 @@
import request from "@/utils/request";
/**
* 发送消息给所有人
*
* @param file
*/
export function sendToAll(message: string) {
return request({
url: "/websocket/sendToAll",
method: "post",
params: { message: message },
});
}
/**
* 发送消息给指定用户
*
* @param
*/
export function sendToUser(userId: number, message: string) {
return request({
url: "/websocket/sendToUser/" + userId,
method: "post",
params: { message: message },
});
}

View File

@@ -1,6 +1,6 @@
<template>
<a
href="https://github.com/hxrui"
href="https://github.com/haoxianrui"
target="_blank"
class="github-corner"
aria-label="View source on Github"

View File

@@ -55,7 +55,7 @@ const props = defineProps({
},
});
const emit = defineEmits(["pagination"]);
const emit = defineEmits(["pagination", "update:page", "update:limit"]);
const currentPage = useVModel(props, "page", emit);

View File

@@ -88,13 +88,19 @@ function logout() {
<router-link to="/">
<el-dropdown-item>{{ $t("navbar.dashboard") }}</el-dropdown-item>
</router-link>
<a target="_blank" href="https://github.com/hxrui">
<a
target="_blank"
href="https://github.com/youlaitech/vue3-element-admin"
>
<el-dropdown-item>Github</el-dropdown-item>
</a>
<a target="_blank" href="https://gitee.com/haoxr">
<el-dropdown-item>{{ $t("navbar.gitee") }}</el-dropdown-item>
</a>
<a target="_blank" href="https://www.cnblogs.com/haoxianrui/">
<a
target="_blank"
href="https://juejin.cn/post/7228990409909108793"
>
<el-dropdown-item>{{ $t("navbar.document") }}</el-dropdown-item>
</a>
<el-dropdown-item divided @click="logout">

View File

@@ -12,6 +12,7 @@ import { useStorage } from "@vueuse/core";
export const useUserStore = defineStore("user", () => {
// state
const userId = ref();
const token = useStorage("accessToken", "");
const nickname = ref("");
const avatar = ref("");
@@ -49,6 +50,7 @@ export const useUserStore = defineStore("user", () => {
if (!data.roles || data.roles.length <= 0) {
reject("getUserInfo: roles must be a non-null array!");
}
userId.value = data.userId;
nickname.value = data.nickname;
avatar.value = data.avatar;
roles.value = data.roles;
@@ -95,6 +97,10 @@ export const useUserStore = defineStore("user", () => {
getInfo,
logout,
resetToken,
/**
* 当前登录用户ID
*/
userId,
};
});

File diff suppressed because it is too large Load Diff

View File

@@ -5,79 +5,78 @@
// Read more: https://github.com/vuejs/core/pull/3399
import '@vue/runtime-core'
export {}
export {};
declare module '@vue/runtime-core' {
declare module "@vue/runtime-core" {
export interface GlobalComponents {
Breadcrumb: typeof import('./../components/Breadcrumb/index.vue')['default']
ElAlert: typeof import('element-plus/es')['ElAlert']
ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
ElButton: typeof import('element-plus/es')['ElButton']
ElCard: typeof import('element-plus/es')['ElCard']
ElCol: typeof import('element-plus/es')['ElCol']
ElDialog: typeof import('element-plus/es')['ElDialog']
ElDivider: typeof import('element-plus/es')['ElDivider']
ElDropdown: typeof import('element-plus/es')['ElDropdown']
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
ElForm: typeof import('element-plus/es')['ElForm']
ElFormItem: typeof import('element-plus/es')['ElFormItem']
ElIcon: typeof import('element-plus/es')['ElIcon']
ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElLink: typeof import('element-plus/es')['ElLink']
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption']
ElPagination: typeof import('element-plus/es')['ElPagination']
ElPopover: typeof import('element-plus/es')['ElPopover']
ElRadio: typeof import('element-plus/es')['ElRadio']
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
ElRow: typeof import('element-plus/es')['ElRow']
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
ElSelect: typeof import('element-plus/es')['ElSelect']
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
ElSwitch: typeof import('element-plus/es')['ElSwitch']
ElTable: typeof import('element-plus/es')['ElTable']
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
ElTag: typeof import('element-plus/es')['ElTag']
ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElTree: typeof import('element-plus/es')['ElTree']
ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
ElUpload: typeof import('element-plus/es')['ElUpload']
GithubCorner: typeof import('./../components/GithubCorner/index.vue')['default']
Hamburger: typeof import('./../components/Hamburger/index.vue')['default']
IconSelect: typeof import('./../components/IconSelect/index.vue')['default']
IEpCaretBottom: typeof import('~icons/ep/caret-bottom')['default']
IEpCaretTop: typeof import('~icons/ep/caret-top')['default']
IEpClose: typeof import('~icons/ep/close')['default']
IEpCollection: typeof import('~icons/ep/collection')['default']
IEpDelete: typeof import('~icons/ep/delete')['default']
IEpDownload: typeof import('~icons/ep/download')['default']
IEpEdit: typeof import('~icons/ep/edit')['default']
IEpPlus: typeof import('~icons/ep/plus')['default']
IEpPosition: typeof import('~icons/ep/position')['default']
IEpRefresh: typeof import('~icons/ep/refresh')['default']
IEpRefreshLeft: typeof import('~icons/ep/refresh-left')['default']
IEpSearch: typeof import('~icons/ep/search')['default']
IEpSetting: typeof import('~icons/ep/setting')['default']
IEpTop: typeof import('~icons/ep/top')['default']
IEpUploadFilled: typeof import('~icons/ep/upload-filled')['default']
LangSelect: typeof import('./../components/LangSelect/index.vue')['default']
MultiUpload: typeof import('./../components/Upload/MultiUpload.vue')['default']
Pagination: typeof import('./../components/Pagination/index.vue')['default']
RightPanel: typeof import('./../components/RightPanel/index.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
Screenfull: typeof import('./../components/Screenfull/index.vue')['default']
SingleUpload: typeof import('./../components/Upload/SingleUpload.vue')['default']
SizeSelect: typeof import('./../components/SizeSelect/index.vue')['default']
SvgIcon: typeof import('./../components/SvgIcon/index.vue')['default']
TagInput: typeof import('./../components/TagInput/index.vue')['default']
WangEditor: typeof import('./../components/WangEditor/index.vue')['default']
Breadcrumb: typeof import("./../components/Breadcrumb/index.vue")["default"];
ElAlert: typeof import("element-plus/es")["ElAlert"];
ElBreadcrumb: typeof import("element-plus/es")["ElBreadcrumb"];
ElBreadcrumbItem: typeof import("element-plus/es")["ElBreadcrumbItem"];
ElButton: typeof import("element-plus/es")["ElButton"];
ElCard: typeof import("element-plus/es")["ElCard"];
ElCol: typeof import("element-plus/es")["ElCol"];
ElDialog: typeof import("element-plus/es")["ElDialog"];
ElDivider: typeof import("element-plus/es")["ElDivider"];
ElDropdown: typeof import("element-plus/es")["ElDropdown"];
ElDropdownItem: typeof import("element-plus/es")["ElDropdownItem"];
ElDropdownMenu: typeof import("element-plus/es")["ElDropdownMenu"];
ElForm: typeof import("element-plus/es")["ElForm"];
ElFormItem: typeof import("element-plus/es")["ElFormItem"];
ElIcon: typeof import("element-plus/es")["ElIcon"];
ElInput: typeof import("element-plus/es")["ElInput"];
ElInputNumber: typeof import("element-plus/es")["ElInputNumber"];
ElLink: typeof import("element-plus/es")["ElLink"];
ElMenu: typeof import("element-plus/es")["ElMenu"];
ElMenuItem: typeof import("element-plus/es")["ElMenuItem"];
ElOption: typeof import("element-plus/es")["ElOption"];
ElPagination: typeof import("element-plus/es")["ElPagination"];
ElPopover: typeof import("element-plus/es")["ElPopover"];
ElRadio: typeof import("element-plus/es")["ElRadio"];
ElRadioGroup: typeof import("element-plus/es")["ElRadioGroup"];
ElRow: typeof import("element-plus/es")["ElRow"];
ElScrollbar: typeof import("element-plus/es")["ElScrollbar"];
ElSelect: typeof import("element-plus/es")["ElSelect"];
ElSubMenu: typeof import("element-plus/es")["ElSubMenu"];
ElSwitch: typeof import("element-plus/es")["ElSwitch"];
ElTable: typeof import("element-plus/es")["ElTable"];
ElTableColumn: typeof import("element-plus/es")["ElTableColumn"];
ElTag: typeof import("element-plus/es")["ElTag"];
ElTooltip: typeof import("element-plus/es")["ElTooltip"];
ElTree: typeof import("element-plus/es")["ElTree"];
ElTreeSelect: typeof import("element-plus/es")["ElTreeSelect"];
ElUpload: typeof import("element-plus/es")["ElUpload"];
GithubCorner: typeof import("./../components/GithubCorner/index.vue")["default"];
Hamburger: typeof import("./../components/Hamburger/index.vue")["default"];
IconSelect: typeof import("./../components/IconSelect/index.vue")["default"];
IEpCaretBottom: typeof import("~icons/ep/caret-bottom")["default"];
IEpCaretTop: typeof import("~icons/ep/caret-top")["default"];
IEpClose: typeof import("~icons/ep/close")["default"];
IEpCollection: typeof import("~icons/ep/collection")["default"];
IEpDelete: typeof import("~icons/ep/delete")["default"];
IEpDownload: typeof import("~icons/ep/download")["default"];
IEpEdit: typeof import("~icons/ep/edit")["default"];
IEpPlus: typeof import("~icons/ep/plus")["default"];
IEpPosition: typeof import("~icons/ep/position")["default"];
IEpRefresh: typeof import("~icons/ep/refresh")["default"];
IEpRefreshLeft: typeof import("~icons/ep/refresh-left")["default"];
IEpSearch: typeof import("~icons/ep/search")["default"];
IEpSetting: typeof import("~icons/ep/setting")["default"];
IEpTop: typeof import("~icons/ep/top")["default"];
IEpUploadFilled: typeof import("~icons/ep/upload-filled")["default"];
LangSelect: typeof import("./../components/LangSelect/index.vue")["default"];
MultiUpload: typeof import("./../components/Upload/MultiUpload.vue")["default"];
Pagination: typeof import("./../components/Pagination/index.vue")["default"];
RightPanel: typeof import("./../components/RightPanel/index.vue")["default"];
RouterLink: typeof import("vue-router")["RouterLink"];
RouterView: typeof import("vue-router")["RouterView"];
SingleUpload: typeof import("./../components/Upload/SingleUpload.vue")["default"];
SizeSelect: typeof import("./../components/SizeSelect/index.vue")["default"];
SvgIcon: typeof import("./../components/SvgIcon/index.vue")["default"];
TagInput: typeof import("./../components/TagInput/index.vue")["default"];
WangEditor: typeof import("./../components/WangEditor/index.vue")["default"];
}
export interface ComponentCustomProperties {
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
vLoading: typeof import("element-plus/es")["ElLoadingDirective"];
}
}

View File

@@ -1,8 +1,10 @@
<script lang="ts">
export default { name: "Dashboard" };
</script>
<script setup lang="ts">
defineOptions({
// eslint-disable-next-line vue/no-reserved-component-names
name: "Dashboard",
inheritAttrs: false,
});
import { useUserStore } from "@/store/modules/user";
import { useTransition, TransitionPresets } from "@vueuse/core";

View File

@@ -0,0 +1,119 @@
<!-- websocket 示例 -->
<script setup lang="ts">
import { sendToAll, sendToUser } from "@/api/websocket";
const inputVal = ref("初始内容");
const topicMsgs = ref<string[]>(["接收到一条主题消息"]); // 主题消息列表
const p2pMsgs = ref<string[]>(["接收到一条点对线消息"]); // 点对点消息列表
import { useUserStore } from "@/store/modules/user";
const userId = useUserStore().userId;
import { useWebSocket } from "@vueuse/core";
const { data, status, close, send, open } = useWebSocket(
"ws://localhost:8989/ws",
{
onConnected(ws) {
console.log("订阅主题");
// 连接建立后发送订阅消息
ws.send(JSON.stringify({ type: "subscribe", topic: "/topic/all" }));
},
onMessage(ws, event) {
// 获取接收到的消息内容
const message = event.data;
// 处理消息内容
console.log("Received message:", message);
},
}
);
// 监听 WebSocket 连接状态变化
watch(status, (newStatus) => {
if (newStatus === "OPEN") {
// 连接已打开,订阅主题
console.log(" 连接已打开,订阅主题");
const subscribeMessage = {
type: "subscribe",
channel: "/topic/all",
};
send(JSON.stringify(subscribeMessage));
} else if (newStatus === "CLOSED") {
// 连接已关闭,执行相应的清理操作
// ...
}
});
// 监听 WebSocket 接收到的消息
watch(data, (newData) => {
console.log("Received data:", newData);
// 解析消息体
const message = JSON.parse(newData);
// 判断消息主题并处理
if (message.topic === "topic1") {
// 处理来自 topic1 的消息
console.log("Received message from topic1:", message);
} else if (message.topic === "topic2") {
// 处理来自 topic2 的消息
console.log("Received message from topic2:", message);
}
// 可以根据需要添加更多的判断逻辑来处理其他主题的消息
});
function handleSendToAll() {
sendToAll(inputVal.value);
}
function handleSendToUser() {
sendToUser(userId, inputVal.value);
}
onMounted(() => {});
</script>
<template>
<div class="app-container">
<el-link
href="https://gitee.com/youlaiorg/vue3-element-admin/blob/master/src/views/demo/websocket.vue"
type="primary"
target="_blank"
class="mb-[20px]"
>示例源码 请点击>>>></el-link
>
<div>
<div class="search">
<el-form :inline="true">
<el-form-item> <el-input v-model="inputVal" /></el-form-item>
<el-form-item
><el-button @click="handleSendToUser">发送点对点消息</el-button>
<el-button @click="handleSendToAll">发送广播消息</el-button>
</el-form-item>
</el-form>
</div>
<el-row :gutter="20">
<el-col :span="12">
<el-card>
<template #header>点对点消息接收 </template>
<div v-for="(msg, index) in p2pMsgs" :key="index">
{{ msg }}
</div>
</el-card>
</el-col>
<el-col :span="12">
<el-card>
<template #header> 广播消息接收 </template>
<div v-for="(msg, index) in topicMsgs" :key="index">
{{ msg }}
</div>
</el-card>
</el-col>
</el-row>
</div>
</div>
</template>

View File

@@ -196,6 +196,8 @@ function resetForm() {
formData.visible = 1;
formData.sort = 1;
formData.perm = undefined;
formData.component = undefined;
formData.path = undefined;
}
onMounted(() => {