Merge branch 'main' into wyfMain-dev

This commit is contained in:
wangyifeng 2025-05-09 10:58:37 +08:00
commit 903ae24458
12 changed files with 106 additions and 266 deletions

View File

@ -1,6 +0,0 @@
ENV = 'production'
VITE_BASE=./
VITE_ROUTER_MODE=hash
VITE_BASE_API=https://xxx.xxx.com
VITE_SOCKET_API=wss://xxx.xxx.com

View File

@ -1,23 +0,0 @@
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
env: {
node: true // 只需将该项设置为 true 即可
},
root: true,
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier/skip-formatting'
],
parserOptions: {
ecmaVersion: 'latest'
},
rules: {
'vue/multi-word-component-names': 'off',
'@typescript-eslint/no-unused-vars': 'off',
"no-unused-vars":"off"
}
}

143
README.md
View File

@ -1,87 +1,104 @@
# Lumen IM 即时聊天
# LumenIM - 在线即时通讯应用
<img alt="GitHub stars badge" src="https://img.shields.io/github/stars/gzydong/LumenIM"> <img alt="GitHub forks badge" src="https://img.shields.io/github/forks/gzydong/LumenIM"> <img alt="GitHub license badge" src="https://img.shields.io/github/license/gzydong/LumenIM">
LumenIM 是一个基于 Vue 3 开发的现代化在线即时通讯应用,提供实时聊天、消息管理、笔记等功能。
### 项目介绍
## 功能特性
Lumen IM 是一个网页版在线聊天项目,前端使用 Naive UI + Vue3后端采用 GO 开发。
- 📱 实时聊天:支持一对一即时通讯
- 📝 消息管理:高效管理各类消息
- 📓 笔记功能支持Markdown格式的笔记编辑与管理
- 🌓 暗色模式:支持明暗主题切换,呵护您的眼睛
- 🔒 用户认证:完善的登录注册系统
### 功能模块
## 技术栈
- 支持私聊及群聊
- 支持多种聊天消息类型 例如:文本消息、代码块、群投票、图片及其它类型文件,并支持文件下载
- 支持聊天消息撤回、删除(批量删除)、转发消息(逐条转发、合并转发)
- 支持编写笔记
- **前端框架**Vue 3 + TypeScript
- **状态管理**Pinia
- **UI组件库**Naive UI
- **路由管理**Vue Router
- **CSS预处理器**Less
- **构建工具**Vite
- **WebSocket**:用于实时通讯
- **编辑器**
- Markdown编辑器@kangc/v-md-editor
- 富文本编辑器Quill
### 项目预览
## 快速开始
- 地址: [http://im.gzydong.com](http://im.gzydong.com)
### 环境要求
### 项目安装
- Node.js >= 14.0.0
- pnpm >= 6.0.0
###### 下载安装
### 安装依赖
```bash
## 克隆项目源码包
git clone https://gitee.com/gzydong/LumenIM.git
git clone https://github.com/gzydong/LumenIM.git
## 安装项目依赖扩展组件
yarn install
# 启动本地开发环境
yarn dev
# 启动本地开发环境桌面客户端
yarn electron:dev
## 生产环境构建项目
yarn build
## 生产环境桌面客户端打包
yarn electron:build
pnpm install
```
###### 修改 .env 配置信息
### 开发环境运行
```env
VITE_BASE_API=http://127.0.0.1:8503
VITE_SOCKET_API=ws://127.0.0.1:8504
```bash
# 测试环境
pnpm dev:test
# 生产环境
pnpm dev:prod
```
###### 关于 Nginx 的一些配置
### 打包构建
```nginx
server {
listen 80;
server_name www.yourdomain.com;
```bash
# 测试环境构建
pnpm build:test
root /project-path/dist;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|ico)$ {
expires 7d;
}
location ~ .*\.(js|css)?$ {
expires 7d;
}
}
# 生产环境构建
pnpm build:prod
```
### 项目源码
### 预览构建后的项目
| 代码仓库 | 前端源码 | 后端源码 |
| -------- | ---------------------------------- | ---------------------------------- |
| Github | https://github.com/gzydong/LumenIM | https://github.com/gzydong/go-chat |
| 码云 | https://gitee.com/gzydong/LumenIM | https://gitee.com/gzydong/go-chat |
```bash
pnpm preview
```
#### 联系方式
## 项目结构
QQ作者 : 837215079
```
src/
├── api/ # API请求
├── assets/ # 静态资源
├── components/ # 公共组件
├── connect.ts # WebSocket连接管理
├── constant/ # 常量定义
├── directive/ # 自定义指令
├── event/ # 事件管理
├── hooks/ # 自定义钩子
├── layout/ # 布局组件
├── main.ts # 入口文件
├── plugins/ # 插件配置
├── router/ # 路由配置
├── store/ # 状态管理
├── types/ # 类型定义
├── utils/ # 工具函数
└── views/ # 页面视图
```
### 如果你觉得还不错,请 Star , Fork 给作者鼓励一下。
## 环境变量配置
项目支持不同环境配置,环境变量文件位于`env/`目录下。
## 浏览器支持
支持现代浏览器如Chrome、Firefox、Safari、Edge等。
## 相关链接
- [Vue 3](https://v3.vuejs.org/)
- [Vite](https://vitejs.dev/)
- [Naive UI](https://www.naiveui.com/)
- [Pinia](https://pinia.vuejs.org/)
## 许可证
Copyright © 2023 LumenIM

View File

@ -1,92 +0,0 @@
// 控制应用生命周期和创建原生浏览器窗口的模组
const { app, BrowserWindow, ipcMain, Menu, MenuItem } = require('electron')
const path = require('path')
const { shell } = require('electron')
const NODE_ENV = process.env.NODE_ENV
function loadHtmlUrl() {
return NODE_ENV === 'development'
? `http://localhost:${process.env.PROT}`
: `file://${path.join(__dirname, '../dist/index.html')}`
}
function createWindow() {
// 创建浏览器窗口
const win = new BrowserWindow({
width: 1200,
height: 800,
minWidth: 900,
minHeight: 600,
frame: false,
titleBarStyle: 'hidden',
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: true,
},
})
// 加载 index.html
win.loadURL(loadHtmlUrl())
// 打开开发工具
if (NODE_ENV === 'development') {
win.webContents.openDevTools()
}
// 进入全屏模式
win.on('enter-full-screen', function () {
win.webContents.send('full-screen', 'enter')
})
// 退出全屏模式
win.on('leave-full-screen', function () {
win.webContents.send('full-screen', 'leave')
})
ipcMain.on('get-full-screen', (e, data) => {
e.returnValue = win.isFullScreen()
})
ipcMain.on('app-info', (e, data) => {
e.returnValue = {
platform: process.platform,
version: app.getVersion(),
appPath: app.getAppPath(),
}
})
}
// 这段程序将会在 Electron 结束初始化
// 和创建浏览器窗口的时候调用
// 部分 API 在 ready 事件触发后才能使用。
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
// 通常在 macOS 上,当点击 dock 中的应用程序图标时,如果没有其他
// 打开的窗口,那么程序会重新创建一个窗口。
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// 除了 macOS 外,当所有窗口都被关闭的时候退出程序。 因此,通常对程序和它们在
// 任务栏上的图标来说,应当保持活跃状态,直到用户使用 Cmd + Q 退出。
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
// 在这个文件中,你可以包含应用程序剩余的所有部分的代码,
// 也可以拆分成几个文件,然后用 require 导入。
ipcMain.on('ipc:set-badge', async (event, num) => {
if (process.platform === 'darwin') {
app.dock.setBadge(num > 99 ? '99+' : num)
}
})
ipcMain.on('ipc:open-link', async (event, link) => {
// Open a link in the default browser
shell.openExternal(link)
})

View File

@ -1,46 +0,0 @@
const { contextBridge, ipcRenderer } = require('electron')
// 暴露方法给渲染进程调用
contextBridge.exposeInMainWorld('electron', {
// 设置消息未读数
setBadge: num => {
ipcRenderer.send('ipc:set-badge', num == 0 ? '' : `${num}`)
},
// 获取窗口全屏状态
getFullScreenStatus: () => {
return ipcRenderer.sendSync('get-full-screen', '')
},
// 系统信息
getAppPlatform: () => {
return ipcRenderer.sendSync('app-info', '')
},
openLink: link => {
ipcRenderer.send('ipc:open-link', link)
},
})
// 窗口变化事件
ipcRenderer.on('full-screen', function (event, value) {
// isFullScreenStatus = value == 'enter'
document.dispatchEvent(
new CustomEvent('full-screen-event', { detail: value })
)
})
// 触发自定义事件
// document.dispatchEvent(new CustomEvent('myTestEvent', {num: i}))
// document.addEventListener('myTestEvent', e => {console.log(e)})
// 所有Node.js API都可以在预加载过程中使用。
// 它拥有与Chrome扩展一样的沙盒。
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const dependency of ['chrome', 'node', 'electron']) {
replaceText(`${dependency}-version`, process.versions[dependency])
}
})

View File

View File

View File

@ -477,17 +477,12 @@ packages:
resolution: {integrity: sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==}
engines: {node: '>=4'}
'@nodelib/fs.scandir@2.1.5':
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
engines: {node: '>= 8'}
'@nodelib/fs.stat@1.1.3':
resolution: {integrity: sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==}
engines: {node: '>= 6'}
'@nodelib/fs.stat@2.0.5':
resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
engines: {node: '>= 8'}
'@polka/url@1.0.0-next.29':
resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==}
'@nodelib/fs.walk@1.2.8':
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
@ -2112,10 +2107,6 @@ packages:
resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==}
engines: {node: '>=0.10.0'}
micromatch@4.0.8:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
mime-db@1.52.0:
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
engines: {node: '>= 0.6'}
@ -2434,9 +2425,6 @@ packages:
engines: {node: '>=14.18.0', npm: '>=8.0.0'}
hasBin: true
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
rw@1.3.3:
resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==}
@ -3290,16 +3278,11 @@ snapshots:
call-me-maybe: 1.0.2
glob-to-regexp: 0.3.0
'@nodelib/fs.scandir@2.1.5':
dependencies:
'@nodelib/fs.stat': 2.0.5
run-parallel: 1.2.0
'@nodelib/fs.stat@1.1.3': {}
'@nodelib/fs.stat@2.0.5': {}
'@polka/url@1.0.0-next.29': {}
'@nodelib/fs.walk@1.2.8':
'@quansync/fs@0.1.2':
dependencies:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.19.1
@ -5251,11 +5234,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
micromatch@4.0.8:
dependencies:
braces: 3.0.3
picomatch: 2.3.1
mime-db@1.52.0: {}
mime-types@2.1.35:
@ -5567,10 +5545,6 @@ snapshots:
optionalDependencies:
fsevents: 2.3.3
run-parallel@1.2.0:
dependencies:
queue-microtask: 1.2.3
rw@1.3.3: {}
rxjs@7.8.2:

View File

@ -31,8 +31,7 @@ const settingsStore = useSettingsStore()
</template>
<style lang="less" scoped>
.container {
height: 100vh;
width: 100vw;
background: url(@/assets/image/background.jpeg);
background-position: center center;
background-repeat: no-repeat;
@ -40,7 +39,7 @@ const settingsStore = useSettingsStore()
background-size: cover;
.im-container {
height: 100vh;
height: 80vh;
width: 100vw;
overflow: hidden;
background-color: #fff;

View File

@ -18,7 +18,7 @@ export function isLoggedIn() {
*/
export function getAccessToken() {
// return storage.get(AccessToken) || ''
return '79b5c732d96d2b27a48a99dfd4a5566c43aaa5796242e854ebe3ffc198d6876b9628e7b764d9af65ab5dbb2d517ced88170491b74b048c0ba827c0d3741462cb89dc59ed46653a449af837a8262941caaef1334d640773710f8cd96473bacfb190cba595a5d6a9c87d70f0999a3ebb41147213b31b4bdccffca66a56acf3baab5af0154f0dce360079f37709f78e13711036899344bddb0fb4cf0f2890287cb62c3fcbe33368caa5e213624577be8b8420ab75b1f50775ee16142a4321c5d56995f37354a66a969da98d95ba6e65d142ed097e04b411c1ebad2f62866d0ec7e1838420530a9941dbbcd00490199f8b892000b1d18303354ea8a7c57f91ffb617f5d82513d2af46e6ce5848a80c59c75b9ddf4a552092d70ecda72c97d99cb5d0f114a50ddfd9674f22576675e3390d2367951eb502aa1dd94e8823d528a503fb'
return JSON.parse(localStorage.getItem('token'))||'79b5c732d96d2b27a48a99dfd4a5566c43aaa5796242e854ebe3ffc198d6876b9628e7b764d9af65ab5dbb2d517ced88170491b74b048c0ba827c0d3741462cb89dc59ed46653a449af837a8262941caaef1334d640773710f8cd96473bacfb190cba595a5d6a9c87d70f0999a3ebb41147213b31b4bdccffca66a56acf3baab5af0154f0dce360079f37709f78e13711036899344bddb0fb4cf0f2890287cb62c3fcbe33368caa5e213624577be8b8420ab75b1f50775ee16142a4321c5d56995f37354a66a969da98d95ba6e65d142ed097e04b411c1ebad2f62866d0ec7e1838420530a9941dbbcd00490199f8b892000b1d18303354ea8a7c57f91ffb617f5d82513d2af46e6ce5848a80c59c75b9ddf4a552092d70ecda72c97d99cb5d0f114a50ddfd9674f22576675e3390d2367951eb502aa1dd94e8823d528a503fb'
}
/**

16
uno.config.ts Normal file
View File

@ -0,0 +1,16 @@
import { defineConfig } from 'unocss'
import { presetAttributify, presetIcons } from 'unocss'
export default defineConfig({
// 预设
presets: [
presetAttributify(), // 启用属性模式
presetIcons(), // 启用图标
],
// 自定义规则
rules: [
],
// 快捷方式
shortcuts: {
'btn': 'px-4 py-2 rounded-lg bg-blue-500 text-white hover:bg-blue-600',
},
})

View File

@ -3,7 +3,7 @@ import { fileURLToPath, URL } from 'node:url'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import compressPlugin from 'vite-plugin-compression'
import UnoCSS from 'unocss/vite'
// https://vitejs.dev/config/
export default defineConfig(({ mode }) => {
// 根据当前工作目录中的 `mode` 加载 .env 文件
@ -12,6 +12,7 @@ export default defineConfig(({ mode }) => {
return {
base: env.VITE_BASE,
envDir: './env',
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
@ -20,7 +21,7 @@ export default defineConfig(({ mode }) => {
},
root: process.cwd(),
assetsInclude: ['./src/assets'],
plugins: [vue(), vueJsx({}), compressPlugin()],
plugins: [vue(), vueJsx({}), compressPlugin(),UnoCSS()],
define: {
__APP_ENV__: env.APP_ENV
},