Merge branch 'master' of https://github.com/youlaitech/vue3-element-admin
Former-commit-id: ecbba4384964ab453d345736cd790ddd7e9e84b1
This commit is contained in:
33
README.md
33
README.md
@@ -1,7 +1,7 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://img.shields.io/badge/Vue-3.3.1-brightgreen.svg"/>
|
<img src="https://img.shields.io/badge/Vue-3.3.1-brightgreen.svg"/>
|
||||||
<img src="https://img.shields.io/badge/Vite-4.3.5-green.svg"/>
|
<img src="https://img.shields.io/badge/Vite-4.3.5-green.svg"/>
|
||||||
<img src="https://img.shields.io/badge/Element Plus-2.3.4-blue.svg"/>
|
<img src="https://img.shields.io/badge/Element Plus-2.3.6-blue.svg"/>
|
||||||
<img src="https://img.shields.io/badge/license-MIT-green.svg"/>
|
<img src="https://img.shields.io/badge/license-MIT-green.svg"/>
|
||||||
<a href="https://gitee.com/youlaiorg" target="_blank">
|
<a href="https://gitee.com/youlaiorg" target="_blank">
|
||||||
<img src="https://img.shields.io/badge/Author-有来开源组织-orange.svg"/>
|
<img src="https://img.shields.io/badge/Author-有来开源组织-orange.svg"/>
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
<a target="_blank" href="https://juejin.cn/post/7228990409909108793">vue3-element-admin官方文档</a> | <a target="_blank" href="http://vue3.youlai.tech">在线预览</a>
|
<a target="_blank" href="https://juejin.cn/post/7228990409909108793">vue3-element-admin官方文档</a> | <a target="_blank" href="http://vue3.youlai.tech">在线预览</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
## 项目介绍
|
## 项目介绍
|
||||||
|
|
||||||
[vue3-element-admin](https://gitee.com/youlaiorg/vue3-element-admin) 是基于 Vue3 + Vite4+ TypeScript5 + Element-Plus + Pinia 等最新主流技术栈构建的后台管理前端模板(配套后端源码)。
|
[vue3-element-admin](https://gitee.com/youlaiorg/vue3-element-admin) 是基于 Vue3 + Vite4+ TypeScript5 + Element-Plus + Pinia 等最新主流技术栈构建的后台管理前端模板(配套后端源码)。
|
||||||
@@ -45,7 +46,7 @@
|
|||||||
| 项目 | Gitee | Github |GitCode |
|
| 项目 | Gitee | Github |GitCode |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| 前端 | [vue3-element-admin](https://gitee.com/youlaiorg/vue3-element-admin) | [vue3-element-admin](https://github.com/youlaitech/vue3-element-admin) |[vue3-element-admin](https://gitcode.net/youlai/vue3-element-admin)|
|
| 前端 | [vue3-element-admin](https://gitee.com/youlaiorg/vue3-element-admin) | [vue3-element-admin](https://github.com/youlaitech/vue3-element-admin) |[vue3-element-admin](https://gitcode.net/youlai/vue3-element-admin)|
|
||||||
| 后端 | [youlai-boot](https://gitee.com/youlaiorg/youlai-boot) | [youlai-boot](https://github.com/hxrui/youlai-boot.git) |[youlai-boot](https://gitcode.net/youlai/youlai-boot)|
|
| 后端 | [youlai-boot](https://gitee.com/youlaiorg/youlai-boot) | [youlai-boot](https://github.com/haoxianrui/youlai-boot.git) |[youlai-boot](https://gitcode.net/youlai/youlai-boot)|
|
||||||
|
|
||||||
## 环境准备
|
## 环境准备
|
||||||
|
|
||||||
@@ -97,6 +98,27 @@ server {
|
|||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
- **自动导入插件自动生成默认关闭**
|
||||||
|
|
||||||
|
模板项目的组件类型声明已自动生成。如果添加和使用新的组件,请按照图示方法开启自动生成。在自动生成完成后,记得将其设置为 `false`,避免重复执行引发冲突。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- **项目启动浏览器访问空白**
|
||||||
|
|
||||||
|
请升级浏览器尝试,低版本浏览器内核可能不支持某些新的 JavaScript 语法,比如可选链操作符 `?.`。
|
||||||
|
|
||||||
|
- **项目同步仓库更新升级**
|
||||||
|
|
||||||
|
项目同步仓库更新升级之后,建议 `pnpm install` 安装更新依赖之后启动 。
|
||||||
|
|
||||||
|
- **其他问题**
|
||||||
|
|
||||||
|
如果有其他问题或者建议,建议 [ISSUE](https://gitee.com/youlaiorg/vue3-element-admin/issues/new)
|
||||||
|
|
||||||
## 接口支持
|
## 接口支持
|
||||||
|
|
||||||
- **接口调用地址**:[https://vapi.youlai.tech](https://vapi.youlai.tech)
|
- **接口调用地址**:[https://vapi.youlai.tech](https://vapi.youlai.tech)
|
||||||
@@ -105,8 +127,8 @@ server {
|
|||||||
- **本地接口**:默认使用线上接口,你可以通过以下步骤完成本地接口环境搭建:
|
- **本地接口**:默认使用线上接口,你可以通过以下步骤完成本地接口环境搭建:
|
||||||
|
|
||||||
> 1. 获取基于 `Java 、SpringBoot` 开发的后端 [youlai-boot](https://gitee.com/youlaiorg/youlai-boot.git) 源码 ;
|
> 1. 获取基于 `Java 、SpringBoot` 开发的后端 [youlai-boot](https://gitee.com/youlaiorg/youlai-boot.git) 源码 ;
|
||||||
> 2. 根据后端工程说明文档 [README.md](https://gitee.com/youlaiorg/youlai-boot#%E9%A1%B9%E7%9B%AE%E8%BF%90%E8%A1%8C) 完成本地启动;
|
>2. 根据后端工程说明文档 [README.md](https://gitee.com/youlaiorg/youlai-boot#%E9%A1%B9%E7%9B%AE%E8%BF%90%E8%A1%8C) 完成本地启动;
|
||||||
> 3. 替换 [vite.config.ts](vite.config.ts) 的代理目标地址 [vapi.youlai.tech](vapi.youlai.tech) 为本地的 [localhost:8989](localhost:8989).
|
> 3. 替换 [vite.config.ts](vite.config.ts) 的代理目标地址 `vapi.youlai.tech` 为本地的 `localhost:8989`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -118,6 +140,8 @@ server {
|
|||||||
- [Husky + Lint-staged + Commitlint + Commitizen + cz-git 配置 Git 提交规范](https://blog.csdn.net/u013737132/article/details/130191363)
|
- [Husky + Lint-staged + Commitlint + Commitizen + cz-git 配置 Git 提交规范](https://blog.csdn.net/u013737132/article/details/130191363)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 提交规范
|
## 提交规范
|
||||||
|
|
||||||
执行 `pnpm run commit` 唤起 git commit 交互,根据提示完成信息的输入和选择。
|
执行 `pnpm run commit` 唤起 git commit 交互,根据提示完成信息的输入和选择。
|
||||||
@@ -136,4 +160,3 @@ server {
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"codemirror": "^5.65.13",
|
"codemirror": "^5.65.13",
|
||||||
"echarts": "^5.2.2",
|
"echarts": "^5.2.2",
|
||||||
"element-plus": "^2.3.4",
|
"element-plus": "^2.3.6",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* 登录用户信息
|
* 登录用户信息
|
||||||
*/
|
*/
|
||||||
export interface UserInfo {
|
export interface UserInfo {
|
||||||
|
userId: number;
|
||||||
nickname: string;
|
nickname: string;
|
||||||
avatar: string;
|
avatar: string;
|
||||||
roles: string[];
|
roles: string[];
|
||||||
|
|||||||
27
src/api/websocket/index.ts
Normal file
27
src/api/websocket/index.ts
Normal 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 },
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<a
|
<a
|
||||||
href="https://github.com/hxrui"
|
href="https://github.com/haoxianrui"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="github-corner"
|
class="github-corner"
|
||||||
aria-label="View source on Github"
|
aria-label="View source on Github"
|
||||||
|
|||||||
@@ -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);
|
const currentPage = useVModel(props, "page", emit);
|
||||||
|
|
||||||
|
|||||||
@@ -88,13 +88,19 @@ function logout() {
|
|||||||
<router-link to="/">
|
<router-link to="/">
|
||||||
<el-dropdown-item>{{ $t("navbar.dashboard") }}</el-dropdown-item>
|
<el-dropdown-item>{{ $t("navbar.dashboard") }}</el-dropdown-item>
|
||||||
</router-link>
|
</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>
|
<el-dropdown-item>Github</el-dropdown-item>
|
||||||
</a>
|
</a>
|
||||||
<a target="_blank" href="https://gitee.com/haoxr">
|
<a target="_blank" href="https://gitee.com/haoxr">
|
||||||
<el-dropdown-item>{{ $t("navbar.gitee") }}</el-dropdown-item>
|
<el-dropdown-item>{{ $t("navbar.gitee") }}</el-dropdown-item>
|
||||||
</a>
|
</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>
|
<el-dropdown-item>{{ $t("navbar.document") }}</el-dropdown-item>
|
||||||
</a>
|
</a>
|
||||||
<el-dropdown-item divided @click="logout">
|
<el-dropdown-item divided @click="logout">
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { useStorage } from "@vueuse/core";
|
|||||||
|
|
||||||
export const useUserStore = defineStore("user", () => {
|
export const useUserStore = defineStore("user", () => {
|
||||||
// state
|
// state
|
||||||
|
const userId = ref();
|
||||||
const token = useStorage("accessToken", "");
|
const token = useStorage("accessToken", "");
|
||||||
const nickname = ref("");
|
const nickname = ref("");
|
||||||
const avatar = ref("");
|
const avatar = ref("");
|
||||||
@@ -49,6 +50,7 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
if (!data.roles || data.roles.length <= 0) {
|
if (!data.roles || data.roles.length <= 0) {
|
||||||
reject("getUserInfo: roles must be a non-null array!");
|
reject("getUserInfo: roles must be a non-null array!");
|
||||||
}
|
}
|
||||||
|
userId.value = data.userId;
|
||||||
nickname.value = data.nickname;
|
nickname.value = data.nickname;
|
||||||
avatar.value = data.avatar;
|
avatar.value = data.avatar;
|
||||||
roles.value = data.roles;
|
roles.value = data.roles;
|
||||||
@@ -95,6 +97,10 @@ export const useUserStore = defineStore("user", () => {
|
|||||||
getInfo,
|
getInfo,
|
||||||
logout,
|
logout,
|
||||||
resetToken,
|
resetToken,
|
||||||
|
/**
|
||||||
|
* 当前登录用户ID
|
||||||
|
*/
|
||||||
|
userId,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
2363
src/types/auto-imports.d.ts
vendored
2363
src/types/auto-imports.d.ts
vendored
File diff suppressed because it is too large
Load Diff
139
src/types/components.d.ts
vendored
139
src/types/components.d.ts
vendored
@@ -5,79 +5,78 @@
|
|||||||
// Read more: https://github.com/vuejs/core/pull/3399
|
// Read more: https://github.com/vuejs/core/pull/3399
|
||||||
import '@vue/runtime-core'
|
import '@vue/runtime-core'
|
||||||
|
|
||||||
export {}
|
export {};
|
||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
declare module "@vue/runtime-core" {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
Breadcrumb: typeof import('./../components/Breadcrumb/index.vue')['default']
|
Breadcrumb: typeof import("./../components/Breadcrumb/index.vue")["default"];
|
||||||
ElAlert: typeof import('element-plus/es')['ElAlert']
|
ElAlert: typeof import("element-plus/es")["ElAlert"];
|
||||||
ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb']
|
ElBreadcrumb: typeof import("element-plus/es")["ElBreadcrumb"];
|
||||||
ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
|
ElBreadcrumbItem: typeof import("element-plus/es")["ElBreadcrumbItem"];
|
||||||
ElButton: typeof import('element-plus/es')['ElButton']
|
ElButton: typeof import("element-plus/es")["ElButton"];
|
||||||
ElCard: typeof import('element-plus/es')['ElCard']
|
ElCard: typeof import("element-plus/es")["ElCard"];
|
||||||
ElCol: typeof import('element-plus/es')['ElCol']
|
ElCol: typeof import("element-plus/es")["ElCol"];
|
||||||
ElDialog: typeof import('element-plus/es')['ElDialog']
|
ElDialog: typeof import("element-plus/es")["ElDialog"];
|
||||||
ElDivider: typeof import('element-plus/es')['ElDivider']
|
ElDivider: typeof import("element-plus/es")["ElDivider"];
|
||||||
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
ElDropdown: typeof import("element-plus/es")["ElDropdown"];
|
||||||
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
ElDropdownItem: typeof import("element-plus/es")["ElDropdownItem"];
|
||||||
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
|
ElDropdownMenu: typeof import("element-plus/es")["ElDropdownMenu"];
|
||||||
ElForm: typeof import('element-plus/es')['ElForm']
|
ElForm: typeof import("element-plus/es")["ElForm"];
|
||||||
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
ElFormItem: typeof import("element-plus/es")["ElFormItem"];
|
||||||
ElIcon: typeof import('element-plus/es')['ElIcon']
|
ElIcon: typeof import("element-plus/es")["ElIcon"];
|
||||||
ElInput: typeof import('element-plus/es')['ElInput']
|
ElInput: typeof import("element-plus/es")["ElInput"];
|
||||||
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
|
ElInputNumber: typeof import("element-plus/es")["ElInputNumber"];
|
||||||
ElLink: typeof import('element-plus/es')['ElLink']
|
ElLink: typeof import("element-plus/es")["ElLink"];
|
||||||
ElMenu: typeof import('element-plus/es')['ElMenu']
|
ElMenu: typeof import("element-plus/es")["ElMenu"];
|
||||||
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
ElMenuItem: typeof import("element-plus/es")["ElMenuItem"];
|
||||||
ElOption: typeof import('element-plus/es')['ElOption']
|
ElOption: typeof import("element-plus/es")["ElOption"];
|
||||||
ElPagination: typeof import('element-plus/es')['ElPagination']
|
ElPagination: typeof import("element-plus/es")["ElPagination"];
|
||||||
ElPopover: typeof import('element-plus/es')['ElPopover']
|
ElPopover: typeof import("element-plus/es")["ElPopover"];
|
||||||
ElRadio: typeof import('element-plus/es')['ElRadio']
|
ElRadio: typeof import("element-plus/es")["ElRadio"];
|
||||||
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
ElRadioGroup: typeof import("element-plus/es")["ElRadioGroup"];
|
||||||
ElRow: typeof import('element-plus/es')['ElRow']
|
ElRow: typeof import("element-plus/es")["ElRow"];
|
||||||
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
ElScrollbar: typeof import("element-plus/es")["ElScrollbar"];
|
||||||
ElSelect: typeof import('element-plus/es')['ElSelect']
|
ElSelect: typeof import("element-plus/es")["ElSelect"];
|
||||||
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
|
ElSubMenu: typeof import("element-plus/es")["ElSubMenu"];
|
||||||
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
ElSwitch: typeof import("element-plus/es")["ElSwitch"];
|
||||||
ElTable: typeof import('element-plus/es')['ElTable']
|
ElTable: typeof import("element-plus/es")["ElTable"];
|
||||||
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
ElTableColumn: typeof import("element-plus/es")["ElTableColumn"];
|
||||||
ElTag: typeof import('element-plus/es')['ElTag']
|
ElTag: typeof import("element-plus/es")["ElTag"];
|
||||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
ElTooltip: typeof import("element-plus/es")["ElTooltip"];
|
||||||
ElTree: typeof import('element-plus/es')['ElTree']
|
ElTree: typeof import("element-plus/es")["ElTree"];
|
||||||
ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
|
ElTreeSelect: typeof import("element-plus/es")["ElTreeSelect"];
|
||||||
ElUpload: typeof import('element-plus/es')['ElUpload']
|
ElUpload: typeof import("element-plus/es")["ElUpload"];
|
||||||
GithubCorner: typeof import('./../components/GithubCorner/index.vue')['default']
|
GithubCorner: typeof import("./../components/GithubCorner/index.vue")["default"];
|
||||||
Hamburger: typeof import('./../components/Hamburger/index.vue')['default']
|
Hamburger: typeof import("./../components/Hamburger/index.vue")["default"];
|
||||||
IconSelect: typeof import('./../components/IconSelect/index.vue')['default']
|
IconSelect: typeof import("./../components/IconSelect/index.vue")["default"];
|
||||||
IEpCaretBottom: typeof import('~icons/ep/caret-bottom')['default']
|
IEpCaretBottom: typeof import("~icons/ep/caret-bottom")["default"];
|
||||||
IEpCaretTop: typeof import('~icons/ep/caret-top')['default']
|
IEpCaretTop: typeof import("~icons/ep/caret-top")["default"];
|
||||||
IEpClose: typeof import('~icons/ep/close')['default']
|
IEpClose: typeof import("~icons/ep/close")["default"];
|
||||||
IEpCollection: typeof import('~icons/ep/collection')['default']
|
IEpCollection: typeof import("~icons/ep/collection")["default"];
|
||||||
IEpDelete: typeof import('~icons/ep/delete')['default']
|
IEpDelete: typeof import("~icons/ep/delete")["default"];
|
||||||
IEpDownload: typeof import('~icons/ep/download')['default']
|
IEpDownload: typeof import("~icons/ep/download")["default"];
|
||||||
IEpEdit: typeof import('~icons/ep/edit')['default']
|
IEpEdit: typeof import("~icons/ep/edit")["default"];
|
||||||
IEpPlus: typeof import('~icons/ep/plus')['default']
|
IEpPlus: typeof import("~icons/ep/plus")["default"];
|
||||||
IEpPosition: typeof import('~icons/ep/position')['default']
|
IEpPosition: typeof import("~icons/ep/position")["default"];
|
||||||
IEpRefresh: typeof import('~icons/ep/refresh')['default']
|
IEpRefresh: typeof import("~icons/ep/refresh")["default"];
|
||||||
IEpRefreshLeft: typeof import('~icons/ep/refresh-left')['default']
|
IEpRefreshLeft: typeof import("~icons/ep/refresh-left")["default"];
|
||||||
IEpSearch: typeof import('~icons/ep/search')['default']
|
IEpSearch: typeof import("~icons/ep/search")["default"];
|
||||||
IEpSetting: typeof import('~icons/ep/setting')['default']
|
IEpSetting: typeof import("~icons/ep/setting")["default"];
|
||||||
IEpTop: typeof import('~icons/ep/top')['default']
|
IEpTop: typeof import("~icons/ep/top")["default"];
|
||||||
IEpUploadFilled: typeof import('~icons/ep/upload-filled')['default']
|
IEpUploadFilled: typeof import("~icons/ep/upload-filled")["default"];
|
||||||
LangSelect: typeof import('./../components/LangSelect/index.vue')['default']
|
LangSelect: typeof import("./../components/LangSelect/index.vue")["default"];
|
||||||
MultiUpload: typeof import('./../components/Upload/MultiUpload.vue')['default']
|
MultiUpload: typeof import("./../components/Upload/MultiUpload.vue")["default"];
|
||||||
Pagination: typeof import('./../components/Pagination/index.vue')['default']
|
Pagination: typeof import("./../components/Pagination/index.vue")["default"];
|
||||||
RightPanel: typeof import('./../components/RightPanel/index.vue')['default']
|
RightPanel: typeof import("./../components/RightPanel/index.vue")["default"];
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import("vue-router")["RouterLink"];
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import("vue-router")["RouterView"];
|
||||||
Screenfull: typeof import('./../components/Screenfull/index.vue')['default']
|
SingleUpload: typeof import("./../components/Upload/SingleUpload.vue")["default"];
|
||||||
SingleUpload: typeof import('./../components/Upload/SingleUpload.vue')['default']
|
SizeSelect: typeof import("./../components/SizeSelect/index.vue")["default"];
|
||||||
SizeSelect: typeof import('./../components/SizeSelect/index.vue')['default']
|
SvgIcon: typeof import("./../components/SvgIcon/index.vue")["default"];
|
||||||
SvgIcon: typeof import('./../components/SvgIcon/index.vue')['default']
|
TagInput: typeof import("./../components/TagInput/index.vue")["default"];
|
||||||
TagInput: typeof import('./../components/TagInput/index.vue')['default']
|
WangEditor: typeof import("./../components/WangEditor/index.vue")["default"];
|
||||||
WangEditor: typeof import('./../components/WangEditor/index.vue')['default']
|
|
||||||
}
|
}
|
||||||
export interface ComponentCustomProperties {
|
export interface ComponentCustomProperties {
|
||||||
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
|
vLoading: typeof import("element-plus/es")["ElLoadingDirective"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
<script lang="ts">
|
|
||||||
export default { name: "Dashboard" };
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
<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 { useUserStore } from "@/store/modules/user";
|
||||||
import { useTransition, TransitionPresets } from "@vueuse/core";
|
import { useTransition, TransitionPresets } from "@vueuse/core";
|
||||||
|
|
||||||
|
|||||||
119
src/views/demo/websocket.vue
Normal file
119
src/views/demo/websocket.vue
Normal 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>
|
||||||
@@ -196,6 +196,8 @@ function resetForm() {
|
|||||||
formData.visible = 1;
|
formData.visible = 1;
|
||||||
formData.sort = 1;
|
formData.sort = 1;
|
||||||
formData.perm = undefined;
|
formData.perm = undefined;
|
||||||
|
formData.component = undefined;
|
||||||
|
formData.path = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["src/*"]
|
"@/*": ["src/*"]
|
||||||
},
|
},
|
||||||
"types": ["vite/client", "element-plus/global", "unplugin-icons/types/vue"],
|
"types": ["vite/client", "unplugin-icons/types/vue"],
|
||||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */,
|
"skipLibCheck": true /* Skip type checking all .d.ts files. */,
|
||||||
"allowSyntheticDefaultImports": true /* 允许默认导入 */,
|
"allowSyntheticDefaultImports": true /* 允许默认导入 */,
|
||||||
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */
|
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */
|
||||||
|
|||||||
@@ -71,7 +71,8 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
|||||||
IconsResolver({}),
|
IconsResolver({}),
|
||||||
],
|
],
|
||||||
vueTemplate: true, // 是否在 vue 模板中自动导入
|
vueTemplate: true, // 是否在 vue 模板中自动导入
|
||||||
dts: path.resolve(pathSrc, "types", "auto-imports.d.ts"), // 自动导入组件类型声明文件位置,默认根目录; false 关闭自动生成
|
dts: false, // 关闭自动生成
|
||||||
|
//dts: path.resolve(pathSrc, "types", "auto-imports.d.ts"), // 自动导入组件类型声明文件位置,默认根目录
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Components({
|
Components({
|
||||||
@@ -83,7 +84,8 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
|||||||
// 自动导入 Element Plus 组件
|
// 自动导入 Element Plus 组件
|
||||||
ElementPlusResolver(),
|
ElementPlusResolver(),
|
||||||
],
|
],
|
||||||
dts: path.resolve(pathSrc, "types", "components.d.ts"), // 自动导入组件类型声明文件位置,默认根目录; false 关闭自动生成
|
dts: false, // 关闭自动生成
|
||||||
|
// dts: path.resolve(pathSrc, "types", "components.d.ts"), // 自动导入组件类型声明文件位置,默认根目录
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Icons({
|
Icons({
|
||||||
@@ -149,7 +151,7 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
|
|||||||
"@wangeditor/editor",
|
"@wangeditor/editor",
|
||||||
"@wangeditor/editor-for-vue",
|
"@wangeditor/editor-for-vue",
|
||||||
"vue-i18n",
|
"vue-i18n",
|
||||||
'codemirror'
|
"codemirror",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user