├── .gitignore
├── LICENSE
├── README.md
├── babel.config.js
├── jsconfig.json
├── package-lock.json
├── package.json
├── public
├── audio
│ ├── chat.wav
│ └── friend.wav
├── images
│ ├── empty.svg
│ ├── favicon.png
│ ├── logo.svg
│ ├── verify
│ │ ├── image1.jpeg
│ │ ├── image2.jpeg
│ │ ├── image3.jpeg
│ │ ├── image4.jpeg
│ │ ├── image5.jpeg
│ │ ├── image6.jpeg
│ │ ├── image7.jpeg
│ │ └── image8.jpeg
│ └── wechat
│ │ ├── wechat1.png
│ │ ├── wechat2.png
│ │ ├── wechat3.png
│ │ ├── wechat4.png
│ │ ├── wechat5.png
│ │ └── wechat6.png
└── index.html
├── src
├── App.vue
├── api
│ ├── index.js
│ ├── mockAxios.js
│ └── request.js
├── assets
│ ├── css
│ │ └── index.css
│ └── images
│ │ └── background
│ │ ├── background-1.jpeg
│ │ ├── background-2.jpeg
│ │ ├── background-3.jpeg
│ │ ├── background-4.jpeg
│ │ ├── background-5.jpeg
│ │ ├── background-6.jpeg
│ │ └── background-7.jpeg
├── main.js
├── mock
│ ├── chatHistoryList.json
│ ├── chatList.json
│ ├── friendList.json
│ ├── friendVerifyList.json
│ └── mockServer.js
├── moment
│ └── moment.js
├── pages
│ ├── about
│ │ └── index.vue
│ ├── home
│ │ ├── chat
│ │ │ ├── emoticons.json
│ │ │ ├── file-upload
│ │ │ │ └── index.vue
│ │ │ ├── img-upload
│ │ │ │ └── index.vue
│ │ │ └── index.vue
│ │ ├── empty
│ │ │ └── index.vue
│ │ ├── index.vue
│ │ ├── menu
│ │ │ ├── calendar
│ │ │ │ └── index.vue
│ │ │ ├── index.vue
│ │ │ ├── profile-edit
│ │ │ │ ├── index.vue
│ │ │ │ └── regions.json
│ │ │ ├── search
│ │ │ │ └── index.vue
│ │ │ └── settings
│ │ │ │ ├── index.vue
│ │ │ │ └── password-reset
│ │ │ │ └── index.vue
│ │ ├── profile
│ │ │ └── index.vue
│ │ ├── sidebar-archived
│ │ │ └── index.vue
│ │ ├── sidebar-chats
│ │ │ ├── chat-add
│ │ │ │ └── index.vue
│ │ │ └── index.vue
│ │ ├── sidebar-favorites
│ │ │ └── index.vue
│ │ ├── sidebar-friends
│ │ │ ├── friend-add
│ │ │ │ └── index.vue
│ │ │ ├── friend-verify
│ │ │ │ └── index.vue
│ │ │ ├── index.vue
│ │ │ └── remark-reset
│ │ │ │ └── index.vue
│ │ └── sidebar-groups
│ │ │ └── index.vue
│ ├── login
│ │ └── index.vue
│ ├── password
│ │ └── index.vue
│ └── register
│ │ └── index.vue
├── router
│ └── index.js
├── store
│ ├── home
│ │ └── index.js
│ └── index.js
└── utils
│ ├── cookie.js
│ ├── date.js
│ └── encrypt.js
└── vue.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 toollong
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # easychat-client
2 |
3 | ## 介绍
4 |
5 | easychat-client 是 EasyChat 项目的前端部分,基于 Vue CLI 开发。
6 |
7 | EasyChat 是一个可以在线聊天的即时通讯平台,完全由个人设计和开发,初衷主要是觉得好玩儿,顺便学习一些新东西,所以网站有些简陋,属实是本人的能力和财力有限。网站没有任何付费内容,所有内容完全免费,欢迎大家使用体验,也期待大佬们的交流与反馈。
8 |
9 | 体验地址:[https://toollong.icu](https://toollong.icu)(网站已于 2023.08.18 下线,运行时长 382 天)
10 |
11 | > ### 功能介绍
12 |
13 | - 注册
14 | - 登录
15 | - 找回密码
16 | - 添加聊天
17 | - 删除聊天
18 | - 发送文本消息
19 | - 发送 Emoji 表情(Windows 7 可能无法正常显示)
20 | - 发送图片(批量发送)
21 | - 发送文件(同步发送,有点慢)
22 | - 新消息通知(有提示音)
23 | - 搜索用户
24 | - 修改好友备注
25 | - 好友申请
26 | - 好友验证
27 | - 好友删除(单向删除)
28 | - 验证消息通知(有提示音)
29 | - 查看资料
30 | - 编辑资料
31 | - 设置(头像、隐身、标签、修改密码)
32 | - 夜间模式
33 | - 小抽屉(搜一搜、日历)
34 |
35 |
36 | > ### 技术栈
37 |
38 | - 前端:Vue 3,Vue Router,Vuex,Element Plus,Socket.IO,Axios,VueUse...
39 |
40 | - 后端:Spring Cloud,Nacos,MyBatis-Plus,Netty-socketio,MinIO,Gson,MySQL,Redis,Docker...
41 |
42 | > ### 注意
43 |
44 | - 本网站仅供学习交流使用,由于网站的安全保障和加密措施并不完善,**请勿在网站中输入敏感信息**,避免信息泄露的风险。
45 |
46 | - 我的邮箱:toollong@163.com
47 |
48 | - 我的博客:[https://blog.csdn.net/weixin_49523761](https://blog.csdn.net/weixin_49523761)
49 |
50 |
51 | ## 安装
52 |
53 | ```
54 | npm install
55 | ```
56 |
57 | ## 启动
58 |
59 | 需要修改的地方:
60 |
61 | - 入口文件 main.js 中 socket.io 的 url
62 | - vue.config.js 中 devServer 的 url
63 |
64 | ```
65 | npm run serve
66 | ```
67 |
68 | ## 构建
69 |
70 | ```
71 | npm run build
72 | ```
73 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/jsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es5",
4 | "module": "esnext",
5 | "baseUrl": "./",
6 | "moduleResolution": "node",
7 | "paths": {
8 | "@/*": [
9 | "src/*"
10 | ]
11 | },
12 | "lib": [
13 | "esnext",
14 | "dom",
15 | "dom.iterable",
16 | "scripthost"
17 | ]
18 | }
19 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "easychat-web",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "@formkit/auto-animate": "^1.0.0-beta.1",
12 | "@vueuse/core": "^8.6.0",
13 | "@wcjiang/notify": "^2.1.0",
14 | "axios": "^0.26.1",
15 | "core-js": "^3.8.3",
16 | "element-plus": "^2.2.2",
17 | "mockjs": "^1.1.0",
18 | "moment": "^2.29.3",
19 | "nprogress": "^0.2.0",
20 | "socket.io-client": "^2.4.0",
21 | "vue": "^3.2.13",
22 | "vue-particles": "^1.0.9",
23 | "vue-router": "^4.0.14",
24 | "vue3-slide-verify": "^1.1.1",
25 | "vuex": "^4.0.2"
26 | },
27 | "devDependencies": {
28 | "@babel/core": "^7.12.16",
29 | "@babel/eslint-parser": "^7.12.16",
30 | "@iconify-json/ep": "^1.1.5",
31 | "@iconify-json/mdi": "^1.1.19",
32 | "@vue/cli-plugin-babel": "~5.0.0",
33 | "@vue/cli-plugin-eslint": "~5.0.0",
34 | "@vue/cli-service": "~5.0.0",
35 | "eslint": "^7.32.0",
36 | "eslint-plugin-vue": "^8.0.3",
37 | "unplugin-auto-import": "^0.8.5",
38 | "unplugin-icons": "^0.14.3",
39 | "unplugin-vue-components": "^0.19.6"
40 | },
41 | "eslintConfig": {
42 | "root": true,
43 | "env": {
44 | "node": true
45 | },
46 | "extends": [
47 | "plugin:vue/vue3-essential",
48 | "eslint:recommended"
49 | ],
50 | "parserOptions": {
51 | "parser": "@babel/eslint-parser"
52 | },
53 | "rules": {}
54 | },
55 | "browserslist": [
56 | "> 1%",
57 | "last 2 versions",
58 | "not dead",
59 | "not ie 11"
60 | ]
61 | }
62 |
--------------------------------------------------------------------------------
/public/audio/chat.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/audio/chat.wav
--------------------------------------------------------------------------------
/public/audio/friend.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/audio/friend.wav
--------------------------------------------------------------------------------
/public/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/images/favicon.png
--------------------------------------------------------------------------------
/public/images/logo.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/verify/image1.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/images/verify/image1.jpeg
--------------------------------------------------------------------------------
/public/images/verify/image2.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/images/verify/image2.jpeg
--------------------------------------------------------------------------------
/public/images/verify/image3.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/images/verify/image3.jpeg
--------------------------------------------------------------------------------
/public/images/verify/image4.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/images/verify/image4.jpeg
--------------------------------------------------------------------------------
/public/images/verify/image5.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/images/verify/image5.jpeg
--------------------------------------------------------------------------------
/public/images/verify/image6.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/images/verify/image6.jpeg
--------------------------------------------------------------------------------
/public/images/verify/image7.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/images/verify/image7.jpeg
--------------------------------------------------------------------------------
/public/images/verify/image8.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/images/verify/image8.jpeg
--------------------------------------------------------------------------------
/public/images/wechat/wechat1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/images/wechat/wechat1.png
--------------------------------------------------------------------------------
/public/images/wechat/wechat2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/images/wechat/wechat2.png
--------------------------------------------------------------------------------
/public/images/wechat/wechat3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/images/wechat/wechat3.png
--------------------------------------------------------------------------------
/public/images/wechat/wechat4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/images/wechat/wechat4.png
--------------------------------------------------------------------------------
/public/images/wechat/wechat5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/images/wechat/wechat5.png
--------------------------------------------------------------------------------
/public/images/wechat/wechat6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/public/images/wechat/wechat6.png
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | EasyChat - 快乐星球
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
28 |
29 |
31 |
--------------------------------------------------------------------------------
/src/api/index.js:
--------------------------------------------------------------------------------
1 | import axios from "./request";
2 | import mockAxios from "./mockAxios";
3 |
4 | export const mockGetUserInfo = () => mockAxios.get('/user');
5 | export const mockGetChatList = () => mockAxios.get('/chats');
6 | export const mockGetFriendList = () => mockAxios.get('/friends');
7 | export const mockGetFriendVerify = () => mockAxios.get('/friends/verify');
8 | export const mockGetHistory = () => mockAxios.get('/chats/chat/history');
9 |
10 |
11 | export const reqLogin = (data) => axios.post('/auth/login', data);
12 |
13 | export const reqLogout = () => axios.post('/auth/logout');
14 |
15 | export const reqRegister = (data) => axios.post('/user/register', data);
16 |
17 | export const reqSendCode = (data) => axios.post('/user/verifyCode/send', data);
18 |
19 | export const reqValidateCode = (data) => axios.post('/user/verifyCode/validate', data);
20 |
21 | export const reqValidateUsername = (data) => axios.post('/user/username/validate', data);
22 |
23 | export const reqValidatePassword = (data) => axios.post('/user/password/validate', data);
24 |
25 | export const reqSearchUsers = (params) => axios.get('/user/search', { params: params });
26 |
27 | export const reqGetUserInfo = (params) => axios.get('/user/user', { params: params });
28 |
29 | export const reqEditUserInfo = (data) => axios.post('/user/user/edit', data);
30 |
31 | export const reqChangeAvatar = (data) => axios.post('/user/user/changeAvatar', data, { headers: { 'Content-Type': 'multipart/form-data' } });
32 |
33 | export const reqChangePassword = (data) => axios.post('/user/user/changePassword', data);
34 |
35 | export const reqAddTag = (data) => axios.post('/user/user/addTag', data);
36 |
37 | export const reqRemoveTag = (data) => axios.post('/user/user/removeTag', data);
38 |
39 | export const reqGetChatList = (params) => axios.get('/chat/chats', { params: params });
40 |
41 | export const reqGetFriendList = (params) => axios.get('/user/friends', { params: params });
42 |
43 | export const reqGetFriendVerify = (params) => axios.get('/user/friendVerify', { params: params });
44 |
45 | export const reqGetHistory = (params) => axios.get('/chat/chats/chatHistory', { params: params });
46 |
47 | export const reqSavePictureMsg = (data) => axios.post('/chat/chats/savePictureMsg', data, { headers: { 'Content-Type': 'multipart/form-data' } });
48 |
49 | export const reqSaveFileMsg = (data) => axios.post('/chat/chats/saveFileMsg', data, { headers: { 'Content-Type': 'multipart/form-data' } });
50 |
--------------------------------------------------------------------------------
/src/api/mockAxios.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import nprogress from "nprogress";
3 |
4 | import "nprogress/nprogress.css";
5 |
6 | const requests = axios.create({
7 | baseURL: '/mock',
8 | timeout: 5000
9 | })
10 |
11 | requests.interceptors.request.use((config) => {
12 | nprogress.start();
13 | return config;
14 | })
15 |
16 | requests.interceptors.response.use((res) => {
17 | nprogress.done();
18 | return res.data;
19 | }, (error) => {
20 | return Promise.reject(new Error("response failed..."));
21 | })
22 |
23 | export default requests;
--------------------------------------------------------------------------------
/src/api/request.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import nprogress from "nprogress";
3 |
4 | import "nprogress/nprogress.css";
5 |
6 | const requests = axios.create({
7 | baseURL: '/api',
8 | timeout: 60000
9 | })
10 |
11 | requests.interceptors.request.use((config) => {
12 | if (config.url.includes("/auth/")
13 | || config.url.includes("/register")
14 | || config.url.includes("/verifyCode/")
15 | || config.url.includes("/validate")
16 | || config.url.includes("/changePassword")) {
17 | return config;
18 | }
19 | nprogress.start();
20 | return config;
21 | }, (error) => {
22 | return Promise.reject(error);
23 | })
24 |
25 | requests.interceptors.response.use((response) => {
26 | if (response.status === 200) {
27 | nprogress.done();
28 | return response.data;
29 | }
30 | nprogress.done();
31 | }, (error) => {
32 | return Promise.reject(error);
33 | })
34 |
35 | export default requests;
--------------------------------------------------------------------------------
/src/assets/css/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | width: 100%;
4 | min-width: 320px;
5 | min-height: 100vh;
6 | font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, 微软雅黑, Arial, sans-serif;
7 | font-size: 14px;
8 | font-weight: 400;
9 | line-height: 1.5;
10 | color: var(--text-color-primary);
11 | background-color: var(--bg-color);
12 | text-align: left;
13 | direction: ltr;
14 | }
15 |
16 | *,
17 | ::before,
18 | ::after {
19 | box-sizing: border-box;
20 | }
21 |
22 | :root {
23 | color-scheme: light;
24 | --color-white: #ffffff;
25 | --color-black: #000000;
26 | --color-primary: #0a80ff;
27 | --color-primary-light: #409eff;
28 | --color-primary-light-3: #79bbff;
29 | --color-primary-light-5: #a0cfff;
30 | --color-primary-light-7: #c6e2ff;
31 | --color-primary-light-8: #d9ecff;
32 | --color-primary-light-9: #ecf5ff;
33 | --color-primary-dark-2: #337ecc;
34 | --color-success: #0abb87;
35 | --color-success-light: #67c23a;
36 | --color-success-light-3: #95d475;
37 | --color-success-light-5: #b3e19d;
38 | --color-success-light-7: #d1edc4;
39 | --color-success-light-8: #e1f3d8;
40 | --color-success-light-9: #f0f9eb;
41 | --color-success-dark-2: #529b2e;
42 | --color-warning: #e6a23c;
43 | --color-warning-light-3: #eebe77;
44 | --color-warning-light-5: #f3d19e;
45 | --color-warning-light-7: #f8e3c5;
46 | --color-warning-light-8: #faecd8;
47 | --color-warning-light-9: #fdf6ec;
48 | --color-warning-dark-2: #b88230;
49 | --color-danger: #fd397a;
50 | --color-danger-light: #f56c6c;
51 | --color-danger-light-3: #f89898;
52 | --color-danger-light-5: #fab6b6;
53 | --color-danger-light-7: #fcd3d3;
54 | --color-danger-light-8: #fde2e2;
55 | --color-danger-light-9: #fef0f0;
56 | --color-danger-dark-2: #c45656;
57 | --color-error: #f56c6c;
58 | --color-error-light-3: #f89898;
59 | --color-error-light-5: #fab6b6;
60 | --color-error-light-7: #fcd3d3;
61 | --color-error-light-8: #fde2e2;
62 | --color-error-light-9: #fef0f0;
63 | --color-error-dark-2: #c45656;
64 | --color-info: #909399;
65 | --color-info-light-3: #b1b3b8;
66 | --color-info-light-5: #c8c9cc;
67 | --color-info-light-7: #dedfe0;
68 | --color-info-light-8: #e9e9eb;
69 | --color-info-light-9: #f4f4f5;
70 | --color-info-dark-2: #73767a;
71 | --bg-color: #ffffff;
72 | --bg-color-page: #f2f3f5;
73 | --bg-color-overlay: #ffffff;
74 | --text-color-primary: #303133;
75 | --text-color-regular: #606266;
76 | --text-color-secondary: #969696;
77 | --text-color-placeholder: #a8abb2;
78 | --text-color-disabled: #c0c4cc;
79 | --border-color: #dcdfe6;
80 | --border-color-light: #e4e7ed;
81 | --border-color-lighter: #ebeef5;
82 | --border-color-extra-light: #f2f6fc;
83 | --border-color-dark: #d4d7de;
84 | --border-color-darker: #cdd0d6;
85 | --fill-color: #f0f2f5;
86 | --fill-color-light: #f5f7fa;
87 | --fill-color-lighter: #fafafa;
88 | --fill-color-extra-light: #fafcff;
89 | --fill-color-dark: #ebedf0;
90 | --fill-color-darker: #e6e8eb;
91 | --fill-color-blank: #ffffff;
92 | --box-shadow: 0px 12px 32px 4px rgba(0, 0, 0, .04), 0px 8px 20px rgba(0, 0, 0, .08);
93 | --box-shadow-light: 0px 0px 12px rgba(0, 0, 0, .12);
94 | --box-shadow-lighter: 0px 0px 6px rgba(0, 0, 0, .12);
95 | --box-shadow-dark: 0px 16px 48px 16px rgba(0, 0, 0, .08), 0px 12px 32px rgba(0, 0, 0, .12), 0px 8px 16px -8px rgba(0, 0, 0, .16);
96 | --theme-color-light-1: #0a80ff;
97 | --theme-color-light-2: #409eff;
98 | --theme-color-light-3: #79bbff;
99 | --theme-color-light-8: #d9ecff;
100 | --theme-color-light-4: #ecf5ff;
101 | --theme-color-light-11: #7269ef;
102 | --theme-color-light-12: #626aef;
103 | --theme-box-shadow-1: 0px 0px 12px rgba(0, 47, 255, .12);
104 | --background-image-1: url(../images/background/background-1.jpeg);
105 | --background-image-2: url(../images/background/background-2.jpeg);
106 | --background-image-3: url(../images/background/background-3.jpeg);
107 | --background-image-4: url(../images/background/background-4.jpeg);
108 | --background-image-5: url(../images/background/background-5.jpeg);
109 | --background-image-6: url(../images/background/background-6.jpeg);
110 | --background-image-7: url(../images/background/background-7.jpeg);
111 | }
112 |
113 | html.dark {
114 | color-scheme: dark;
115 | --color-primary: #0a80ff;
116 | --color-primary-light: #409eff;
117 | --color-primary-light-3: #3375b9;
118 | --color-primary-light-5: #2a598a;
119 | --color-primary-light-7: #213d5b;
120 | --color-primary-light-8: #1d3043;
121 | --color-primary-light-9: #18222c;
122 | --color-primary-dark-2: #66b1ff;
123 | --color-success: #0abb87;
124 | --color-success-light: #67c23a;
125 | --color-success-light-3: #4e8e2f;
126 | --color-success-light-5: #3e6b27;
127 | --color-success-light-7: #2d481f;
128 | --color-success-light-8: #25371c;
129 | --color-success-light-9: #1c2518;
130 | --color-success-dark-2: #85ce61;
131 | --color-warning: #e6a23c;
132 | --color-warning-light-3: #a77730;
133 | --color-warning-light-5: #7d5b28;
134 | --color-warning-light-7: #533f20;
135 | --color-warning-light-8: #3e301c;
136 | --color-warning-light-9: #292218;
137 | --color-warning-dark-2: #ebb563;
138 | --color-danger: #fd397a;
139 | --color-danger-light: #f56c6c;
140 | --color-danger-light-3: #b25252;
141 | --color-danger-light-5: #854040;
142 | --color-danger-light-7: #582e2e;
143 | --color-danger-light-8: #412626;
144 | --color-danger-light-9: #2b1d1d;
145 | --color-danger-dark-2: #f78989;
146 | --color-error: #f56c6c;
147 | --color-error-light-3: #b25252;
148 | --color-error-light-5: #854040;
149 | --color-error-light-7: #582e2e;
150 | --color-error-light-8: #412626;
151 | --color-error-light-9: #2b1d1d;
152 | --color-error-dark-2: #f78989;
153 | --color-info: #909399;
154 | --color-info-light-3: #6b6d71;
155 | --color-info-light-5: #525457;
156 | --color-info-light-7: #393a3c;
157 | --color-info-light-8: #2d2d2f;
158 | --color-info-light-9: #202121;
159 | --color-info-dark-2: #a6a9ad;
160 | --bg-color-page: #0a0a0a;
161 | --bg-color: #16161a;
162 | --bg-color-overlay: #1d1e1f;
163 | --text-color-primary: #E5EAF3;
164 | --text-color-regular: #CFD3DC;
165 | --text-color-secondary: #A3A6AD;
166 | --text-color-placeholder: #8D9095;
167 | --text-color-disabled: #6C6E72;
168 | --border-color-darker: #636466;
169 | --border-color-dark: #58585B;
170 | --border-color: #4C4D4F;
171 | --border-color-light: #414243;
172 | --border-color-lighter: #363637;
173 | --border-color-extra-light: #2B2B2C;
174 | --fill-color-darker: #424243;
175 | --fill-color-dark: #39393A;
176 | --fill-color: #303030;
177 | --fill-color-light: #262727;
178 | --fill-color-lighter: #1D1D1D;
179 | --fill-color-extra-light: #191919;
180 | --fill-color-blank: transparent;
181 | --box-shadow: 0px 12px 32px 4px rgba(0, 0, 0, .36), 0px 8px 20px rgba(0, 0, 0, .72);
182 | --box-shadow-light: 0px 0px 12px rgba(0, 0, 0, .72);
183 | --box-shadow-lighter: 0px 0px 6px rgba(0, 0, 0, .72);
184 | --box-shadow-dark: 0px 16px 48px 16px rgba(0, 0, 0, .72), 0px 12px 32px #000000, 0px 8px 16px -8px #000000;
185 | --theme-color-light-1: #0a80ff;
186 | --theme-color-light-2: #409eff;
187 | --theme-color-light-3: #3375b9;
188 | --theme-color-light-8: #1d3043;
189 | --theme-color-light-4: #1f2b38;
190 | --theme-color-light-11: #7269ef;
191 | --theme-color-light-12: #626aef;
192 | --theme-box-shadow-1: 0px 0px 12px rgba(255, 255, 255, 0.158);
193 | }
194 |
195 | /* element plus */
196 |
197 | html.dark {
198 | color-scheme: dark;
199 | --el-color-primary: #409eff;
200 | --el-color-primary-light-3: #3375b9;
201 | --el-color-primary-light-5: #2a598a;
202 | --el-color-primary-light-7: #213d5b;
203 | --el-color-primary-light-8: #1d3043;
204 | --el-color-primary-light-9: #18222c;
205 | --el-color-primary-dark-2: #66b1ff;
206 | --el-color-success: #67c23a;
207 | --el-color-success-light-3: #4e8e2f;
208 | --el-color-success-light-5: #3e6b27;
209 | --el-color-success-light-7: #2d481f;
210 | --el-color-success-light-8: #25371c;
211 | --el-color-success-light-9: #1c2518;
212 | --el-color-success-dark-2: #85ce61;
213 | --el-color-warning: #e6a23c;
214 | --el-color-warning-light-3: #a77730;
215 | --el-color-warning-light-5: #7d5b28;
216 | --el-color-warning-light-7: #533f20;
217 | --el-color-warning-light-8: #3e301c;
218 | --el-color-warning-light-9: #292218;
219 | --el-color-warning-dark-2: #ebb563;
220 | --el-color-danger: #f56c6c;
221 | --el-color-danger-light-3: #b25252;
222 | --el-color-danger-light-5: #854040;
223 | --el-color-danger-light-7: #582e2e;
224 | --el-color-danger-light-8: #412626;
225 | --el-color-danger-light-9: #2b1d1d;
226 | --el-color-danger-dark-2: #f78989;
227 | --el-color-error: #f56c6c;
228 | --el-color-error-light-3: #b25252;
229 | --el-color-error-light-5: #854040;
230 | --el-color-error-light-7: #582e2e;
231 | --el-color-error-light-8: #412626;
232 | --el-color-error-light-9: #2b1d1d;
233 | --el-color-error-dark-2: #f78989;
234 | --el-color-info: #909399;
235 | --el-color-info-light-3: #6b6d71;
236 | --el-color-info-light-5: #525457;
237 | --el-color-info-light-7: #393a3c;
238 | --el-color-info-light-8: #2d2d2f;
239 | --el-color-info-light-9: #202121;
240 | --el-color-info-dark-2: #a6a9ad;
241 | --el-box-shadow: 0px 12px 32px 4px rgba(0, 0, 0, 0.36), 0px 8px 20px rgba(0, 0, 0, 0.72);
242 | --el-box-shadow-light: 0px 0px 12px rgba(0, 0, 0, 0.72);
243 | --el-box-shadow-lighter: 0px 0px 6px rgba(0, 0, 0, 0.72);
244 | --el-box-shadow-dark: 0px 16px 48px 16px rgba(0, 0, 0, 0.72), 0px 12px 32px #000000, 0px 8px 16px -8px #000000;
245 | --el-bg-color-page: #0a0a0a;
246 | --el-bg-color: #141414;
247 | --el-bg-color-overlay: #1d1e1f;
248 | --el-text-color-primary: #E5EAF3;
249 | --el-text-color-regular: #CFD3DC;
250 | --el-text-color-secondary: #A3A6AD;
251 | --el-text-color-placeholder: #8D9095;
252 | --el-text-color-disabled: #6C6E72;
253 | --el-border-color-darker: #636466;
254 | --el-border-color-dark: #58585B;
255 | --el-border-color: #4C4D4F;
256 | --el-border-color-light: #414243;
257 | --el-border-color-lighter: #363637;
258 | --el-border-color-extra-light: #2B2B2C;
259 | --el-fill-color-darker: #424243;
260 | --el-fill-color-dark: #39393A;
261 | --el-fill-color: #303030;
262 | --el-fill-color-light: #262727;
263 | --el-fill-color-lighter: #1D1D1D;
264 | --el-fill-color-extra-light: #191919;
265 | --el-fill-color-blank: transparent;
266 | --el-mask-color: rgba(0, 0, 0, 0.8);
267 | --el-mask-color-extra-light: rgba(0, 0, 0, 0.3)
268 | }
269 |
270 | html.dark .el-button {
271 | --el-button-disabled-text-color: rgba(255, 255, 255, 0.5)
272 | }
273 |
274 | html.dark .el-popover {
275 | --el-popover-bg-color: var(--el-bg-color-overlay)
276 | }
277 |
278 | html.dark .el-card {
279 | --el-card-bg-color: var(--el-bg-color-overlay)
280 | }
281 |
282 | html.dark .el-empty {
283 | --el-empty-fill-color-0: var(--el-color-black);
284 | --el-empty-fill-color-1: #4b4b52;
285 | --el-empty-fill-color-2: #36383d;
286 | --el-empty-fill-color-3: #1e1e20;
287 | --el-empty-fill-color-4: #262629;
288 | --el-empty-fill-color-5: #202124;
289 | --el-empty-fill-color-6: #212224;
290 | --el-empty-fill-color-7: #1b1c1f;
291 | --el-empty-fill-color-8: #1c1d1f;
292 | --el-empty-fill-color-9: #18181a
293 | }
294 |
295 | .el-drawer {
296 | height: calc(100vh - 40px) !important;
297 | border-radius: 10px;
298 | margin: 20px;
299 | }
300 |
301 | .el-drawer .el-drawer__header {
302 | margin-bottom: 10px;
303 | }
304 |
305 | .el-dialog {
306 | border-radius: 10px !important;
307 | }
308 |
309 | .el-dialog .el-dialog__body {
310 | padding: 10px 20px;
311 | }
312 |
313 | .el-popover.el-popper {
314 | border-radius: 8px !important;
315 | }
316 |
317 | .el-calendar .el-calendar__header {
318 | align-items: center;
319 | }
--------------------------------------------------------------------------------
/src/assets/images/background/background-1.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/src/assets/images/background/background-1.jpeg
--------------------------------------------------------------------------------
/src/assets/images/background/background-2.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/src/assets/images/background/background-2.jpeg
--------------------------------------------------------------------------------
/src/assets/images/background/background-3.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/src/assets/images/background/background-3.jpeg
--------------------------------------------------------------------------------
/src/assets/images/background/background-4.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/src/assets/images/background/background-4.jpeg
--------------------------------------------------------------------------------
/src/assets/images/background/background-5.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/src/assets/images/background/background-5.jpeg
--------------------------------------------------------------------------------
/src/assets/images/background/background-6.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/src/assets/images/background/background-6.jpeg
--------------------------------------------------------------------------------
/src/assets/images/background/background-7.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/toollong/easychat-client/8f6ff3d996f36dac2986917fcc26fe58487bd103/src/assets/images/background/background-7.jpeg
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import { ElCollapseTransition } from 'element-plus'
3 | import { autoAnimatePlugin } from '@formkit/auto-animate/vue'
4 | import io from 'socket.io-client'
5 | import VueParticles from 'vue-particles'
6 | import router from '@/router'
7 | import store from '@/store'
8 | import App from '@/App.vue'
9 |
10 | // import "@/mock/mockServer"
11 | import "@/moment/moment"
12 |
13 | import "@/assets/css/index.css"
14 | import "element-plus/theme-chalk/base.css"
15 | import "element-plus/theme-chalk/el-loading.css"
16 | import "element-plus/theme-chalk/el-message.css"
17 | import "element-plus/theme-chalk/el-message-box.css"
18 | import "element-plus/theme-chalk/el-notification.css"
19 | import "vue3-slide-verify/dist/style.css"
20 |
21 | const app = createApp(App)
22 |
23 | app.config.globalProperties.socket = io('https://toollong.icu', { transports: ['websocket'] })
24 | app.component(ElCollapseTransition.name, ElCollapseTransition)
25 | app.use(router)
26 | app.use(store)
27 | app.use(autoAnimatePlugin)
28 | app.use(VueParticles)
29 | app.mount('#app')
30 |
--------------------------------------------------------------------------------
/src/mock/chatHistoryList.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "id": "70000000001",
4 | "senderId": "20000000001",
5 | "receiverId": "20000000002",
6 | "sessionId": "10000000001",
7 | "type": 0,
8 | "content": "听我说谢谢你,因为有你,温暖了四季...",
9 | "hasRead": 1,
10 | "showTime": 1,
11 | "createTime": "2022-05-26 09:40:25"
12 | },
13 | {
14 | "id": "70000000002",
15 | "senderId": "20000000002",
16 | "receiverId": "20000000001",
17 | "sessionId": "10000000001",
18 | "type": 0,
19 | "content": "不用谢,沙雕...",
20 | "hasRead": 1,
21 | "showTime": 0,
22 | "createTime": "2022-05-26 09:41:25"
23 | },
24 | {
25 | "id": "70000000003",
26 | "senderId": "20000000001",
27 | "receiverId": "20000000002",
28 | "sessionId": "10000000001",
29 | "type": 1,
30 | "content": "/images/image1.jpg",
31 | "hasRead": 1,
32 | "showTime": 1,
33 | "createTime": "2022-05-27 10:22:25"
34 | },
35 | {
36 | "id": "70000000004",
37 | "senderId": "20000000002",
38 | "receiverId": "20000000001",
39 | "sessionId": "10000000001",
40 | "type": 0,
41 | "content": "这鞋是真的丑,兄弟...",
42 | "hasRead": 1,
43 | "showTime": 0,
44 | "createTime": "2022-05-27 10:30:25"
45 | },
46 | {
47 | "id": "70000000005",
48 | "senderId": "20000000001",
49 | "receiverId": "20000000002",
50 | "sessionId": "10000000001",
51 | "type": 0,
52 | "content": "听我说谢谢你,因为有你,温暖了四季...",
53 | "hasRead": 1,
54 | "showTime": 1,
55 | "createTime": "2022-05-27 12:40:25"
56 | },
57 | {
58 | "id": "70000000006",
59 | "senderId": "20000000001",
60 | "receiverId": "20000000002",
61 | "sessionId": "10000000001",
62 | "type": 0,
63 | "content": "听我说谢谢你,因为有你,温暖了四季...",
64 | "hasRead": 1,
65 | "showTime": 1,
66 | "createTime": "2022-05-27 13:40:25"
67 | },
68 | {
69 | "id": "70000000006",
70 | "senderId": "20000000001",
71 | "receiverId": "20000000002",
72 | "sessionId": "10000000001",
73 | "type": 0,
74 | "content": "听我说谢谢你,因为有你,温暖了四季...",
75 | "hasRead": 1,
76 | "showTime": 1,
77 | "createTime": "2022-05-27 13:40:25"
78 | },
79 | {
80 | "id": "70000000006",
81 | "senderId": "20000000001",
82 | "receiverId": "20000000002",
83 | "sessionId": "10000000001",
84 | "type": 0,
85 | "content": "听我说谢谢你,因为有你,温暖了四季...",
86 | "hasRead": 1,
87 | "showTime": 1,
88 | "createTime": "2022-05-27 13:40:25"
89 | },
90 | {
91 | "id": "70000000006",
92 | "senderId": "20000000001",
93 | "receiverId": "20000000002",
94 | "sessionId": "10000000001",
95 | "type": 0,
96 | "content": "听我说谢谢你,因为有你,温暖了四季...",
97 | "hasRead": 1,
98 | "showTime": 1,
99 | "createTime": "2022-05-27 13:40:25"
100 | },
101 | {
102 | "id": "70000000006",
103 | "senderId": "20000000001",
104 | "receiverId": "20000000002",
105 | "sessionId": "10000000001",
106 | "type": 0,
107 | "content": "听我说谢谢你,因为有你,温暖了四季...",
108 | "hasRead": 1,
109 | "showTime": 1,
110 | "createTime": "2022-05-27 13:40:25"
111 | }
112 | ]
--------------------------------------------------------------------------------
/src/mock/chatList.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "sessionId": "10000000001",
4 | "userId": "20000000001",
5 | "friendUserId": "20000000005",
6 | "friendRemark": "老王",
7 | "friendNickName": "王五",
8 | "friendAvatar": "/images/avatar1.jpeg",
9 | "createTime": "2022-06-07 13:17:56",
10 | "latestChatHistory": {
11 | "senderId": "20000000001",
12 | "receiverId": "20000000002",
13 | "sessionId": "10000000001",
14 | "type": 0,
15 | "content": "hello world!",
16 | "hasRead": 1,
17 | "showTime": 0,
18 | "createTime": "2022-06-07 13:17:56"
19 | }
20 | },
21 | {
22 | "sessionId": "10000000002",
23 | "userId": "20000000001",
24 | "friendUserId": "20000000003",
25 | "friendRemark": "单身狗",
26 | "friendNickName": "张三",
27 | "friendAvatar": "/images/avatar2.jpg",
28 | "createTime": "2022-05-26 13:17:56",
29 | "latestChatHistory": {
30 | "senderId": "20000000003",
31 | "receiverId": "20000000001",
32 | "sessionId": "10000000002",
33 | "type": 0,
34 | "content": "你好,世界!",
35 | "hasRead": 0,
36 | "showTime": 0,
37 | "createTime": "2022-05-26 13:17:56"
38 | }
39 | },
40 | {
41 | "sessionId": "10000000003",
42 | "userId": "20000000001",
43 | "friendUserId": "20000000004",
44 | "friendRemark": "laoli",
45 | "friendNickName": "李四",
46 | "friendAvatar": "/images/avatar3.jpg",
47 | "createTime": "2022-06-06 13:17:56",
48 | "latestChatHistory": {
49 | "senderId": "20000000004",
50 | "receiverId": "20000000001",
51 | "sessionId": "10000000003",
52 | "type": 1,
53 | "content": "/images/image1.jpg",
54 | "hasRead": 1,
55 | "showTime": 0,
56 | "createTime": "2022-06-06 13:17:56"
57 | }
58 | },
59 | {
60 | "sessionId": "10000000004",
61 | "userId": "20000000001",
62 | "friendUserId": "20000000002",
63 | "friendRemark": "",
64 | "friendNickName": "老六",
65 | "friendAvatar": "/images/avatar4.jpg",
66 | "createTime": "2022-06-07 13:18:56",
67 | "latestChatHistory": {}
68 | }
69 | ]
--------------------------------------------------------------------------------
/src/mock/friendList.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "userId": "20000000001",
4 | "friendUserId": "20000000005",
5 | "friendRemark": "老王",
6 | "friendNickName": "王五",
7 | "friendAvatar": "/images/avatar1.jpeg",
8 | "introduction": "",
9 | "friendTags": [
10 | "时间管理大师",
11 | "程序员",
12 | "打工仔"
13 | ],
14 | "sessionId": "10000000001",
15 | "sessionTime": "2022-06-06 13:17:56"
16 | },
17 | {
18 | "userId": "20000000001",
19 | "friendUserId": "20000000003",
20 | "friendRemark": "单身狗",
21 | "friendNickName": "张三",
22 | "friendAvatar": "/images/avatar2.jpg",
23 | "introduction": "",
24 | "friendTags": [
25 | "时间管理大师",
26 | "程序员",
27 | "打工仔"
28 | ],
29 | "sessionId": "10000000002",
30 | "sessionTime": "2022-06-06 13:17:56"
31 | },
32 | {
33 | "userId": "20000000001",
34 | "friendUserId": "20000000004",
35 | "friendRemark": "laoli",
36 | "friendNickName": "李四",
37 | "friendAvatar": "/images/avatar3.jpg",
38 | "introduction": "",
39 | "friendTags": [
40 | "时间管理大师",
41 | "程序员",
42 | "打工仔"
43 | ],
44 | "sessionId": "10000000003",
45 | "sessionTime": "2022-06-06 13:17:56"
46 | },
47 | {
48 | "userId": "20000000001",
49 | "friendUserId": "20000000002",
50 | "friendRemark": "",
51 | "friendNickName": "老六",
52 | "friendAvatar": "/images/avatar4.jpg",
53 | "introduction": "",
54 | "friendTags": [],
55 | "sessionId": "10000000004",
56 | "sessionTime": "2022-06-06 13:17:56"
57 | },
58 | {
59 | "userId": "20000000001",
60 | "friendUserId": "20000000006",
61 | "friendRemark": "",
62 | "friendNickName": "老八",
63 | "friendAvatar": "/images/avatar5.jpg",
64 | "introduction": "",
65 | "friendTags": [],
66 | "sessionId": "-1",
67 | "sessionTime": "2022-06-06 13:17:56"
68 | },
69 | {
70 | "userId": "20000000001",
71 | "friendUserId": "20000000007",
72 | "friendRemark": "大佬",
73 | "friendNickName": "ohMyGod",
74 | "friendAvatar": "/images/avatar5.jpg",
75 | "introduction": "",
76 | "friendTags": [],
77 | "sessionId": "-1",
78 | "sessionTime": "2022-06-06 13:17:56"
79 | }
80 | ]
--------------------------------------------------------------------------------
/src/mock/friendVerifyList.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "senderId": "20000000002",
4 | "senderNickName": "张三",
5 | "senderAvatar": "/images/avatar1.jpeg",
6 | "receiverId": "20000000001",
7 | "receiverNickName": "无敌",
8 | "receiverAvatar": "/images/avatar2.jpg",
9 | "applyReason": "加我加我加我",
10 | "remark": "老张",
11 | "status": 0,
12 | "hasRead": 0,
13 | "createTime": "2022-06-21 10:43:26"
14 | },
15 | {
16 | "senderId": "20000000003",
17 | "senderNickName": "李四",
18 | "senderAvatar": "/images/avatar3.jpg",
19 | "receiverId": "20000000001",
20 | "receiverNickName": "无敌",
21 | "receiverAvatar": "/images/avatar2.jpg",
22 | "applyReason": "加我",
23 | "remark": "",
24 | "status": 1,
25 | "hasRead": 1,
26 | "createTime": "2022-06-15 10:43:26"
27 | },
28 | {
29 | "senderId": "20000000001",
30 | "senderNickName": "无敌",
31 | "senderAvatar": "/images/avatar2.jpg",
32 | "receiverId": "20000000004",
33 | "receiverNickName": "王五",
34 | "receiverAvatar": "/images/avatar4.jpg",
35 | "applyReason": "加我加我",
36 | "remark": "王哥",
37 | "status": 1,
38 | "hasRead": 1,
39 | "createTime": "2022-06-02 10:43:26"
40 | },
41 | {
42 | "senderId": "20000000001",
43 | "senderNickName": "无敌",
44 | "senderAvatar": "/images/avatar2.jpg",
45 | "receiverId": "20000000005",
46 | "receiverNickName": "大佬",
47 | "receiverAvatar": "/images/avatar5.jpg",
48 | "applyReason": "加我加我加我",
49 | "remark": "",
50 | "status": 2,
51 | "hasRead": 1,
52 | "createTime": "2022-06-20 08:43:26"
53 | },
54 | {
55 | "senderId": "20000000006",
56 | "senderNickName": "123456",
57 | "senderAvatar": "/images/avatar1.jpeg",
58 | "receiverId": "20000000001",
59 | "receiverNickName": "无敌",
60 | "receiverAvatar": "/images/avatar2.jpg",
61 | "applyReason": "加我",
62 | "remark": "",
63 | "status": 3,
64 | "hasRead": 1,
65 | "createTime": "2022-06-11 10:43:26"
66 | }
67 | ]
--------------------------------------------------------------------------------
/src/mock/mockServer.js:
--------------------------------------------------------------------------------
1 | import Mock from "mockjs"
2 | import chatList from "./chatList.json"
3 | import friendList from "./friendList.json"
4 | import friendVerifyList from "./friendVerifyList.json"
5 | import chatHistoryList from "./chatHistoryList.json"
6 |
7 | const userInfo = {
8 | code: 200, data: {
9 | id: "20000000001",
10 | username: "1234567890",
11 | avatar: "/images/avatar1.jpeg",
12 | nickName: "无敌",
13 | gender: "1",
14 | age: 20,
15 | birthday: "2000-01-01",
16 | email: "123456789@qq.com",
17 | phone: "1234567890",
18 | region: "山东省 烟台市",
19 | tags: [
20 | "时间管理大师",
21 | "程序员",
22 | "打工仔"
23 | ],
24 | introduction: ""
25 | }
26 | }
27 |
28 | Mock.mock("/mock/user", "get", userInfo)
29 | Mock.mock("/mock/chats", "get", { code: 200, data: chatList })
30 | Mock.mock("/mock/friends", "get", { code: 200, data: friendList })
31 | Mock.mock("/mock/friends/verify", "get", { code: 200, data: friendVerifyList })
32 | Mock.mock("/mock/chats/chat/history", "get", { code: 200, data: chatHistoryList })
--------------------------------------------------------------------------------
/src/moment/moment.js:
--------------------------------------------------------------------------------
1 | import moment from 'moment'
2 |
3 | moment.locale('zh-cn', {
4 | months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
5 | monthsShort: '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
6 | weekdays: '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
7 | weekdaysShort: '周日_周一_周二_周三_周四_周五_周六'.split('_'),
8 | weekdaysMin: '日_一_二_三_四_五_六'.split('_'),
9 | longDateFormat: {
10 | LT: 'HH:mm',
11 | LTS: 'HH:mm:ss',
12 | L: 'YYYY-MM-DD',
13 | LL: 'YYYY年MM月DD日',
14 | LLL: 'YYYY年MM月DD日Ah点mm分',
15 | LLLL: 'YYYY年MM月DD日ddddAh点mm分',
16 | l: 'YYYY-M-D',
17 | ll: 'YYYY年M月D日',
18 | lll: 'YYYY年M月D日 HH:mm',
19 | llll: 'YYYY年M月D日dddd HH:mm'
20 | },
21 | meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
22 | meridiemHour: function (hour, meridiem) {
23 | if (hour === 12) {
24 | hour = 0;
25 | }
26 | if (meridiem === '凌晨' || meridiem === '早上' ||
27 | meridiem === '上午') {
28 | return hour;
29 | } else if (meridiem === '下午' || meridiem === '晚上') {
30 | return hour + 12;
31 | } else {
32 | // '中午'
33 | return hour >= 11 ? hour : hour + 12;
34 | }
35 | },
36 | meridiem: function (hour, minute, isLower) {
37 | const hm = hour * 100 + minute;
38 | if (hm < 600) {
39 | return '凌晨';
40 | } else if (hm < 900) {
41 | return '早上';
42 | } else if (hm < 1130) {
43 | return '上午';
44 | } else if (hm < 1230) {
45 | return '中午';
46 | } else if (hm < 1800) {
47 | return '下午';
48 | } else {
49 | return '晚上';
50 | }
51 | },
52 | calendar: {
53 | sameDay: '[今天]LT',
54 | nextDay: '[明天]LT',
55 | nextWeek: '[下]ddddLT',
56 | lastDay: '[昨天]LT',
57 | lastWeek: '[上]ddddLT',
58 | sameElse: 'L'
59 | },
60 | dayOfMonthOrdinalParse: /\d{1,2}(日|月|周)/,
61 | ordinal: function (number, period) {
62 | switch (period) {
63 | case 'd':
64 | case 'D':
65 | case 'DDD':
66 | return number + '日';
67 | case 'M':
68 | return number + '月';
69 | case 'w':
70 | case 'W':
71 | return number + '周';
72 | default:
73 | return number;
74 | }
75 | },
76 | relativeTime: {
77 | future: '%s内',
78 | past: '%s前',
79 | s: '几秒',
80 | ss: '%d秒',
81 | m: '1分钟',
82 | mm: '%d分钟',
83 | h: '1小时',
84 | hh: '%d小时',
85 | d: '1天',
86 | dd: '%d天',
87 | M: '1个月',
88 | MM: '%d个月',
89 | y: '1年',
90 | yy: '%d年'
91 | },
92 | week: {
93 | // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
94 | dow: 1, // Monday is the first day of the week.
95 | doy: 4 // The week that contains Jan 4th is the first week of the year.
96 | }
97 | })
--------------------------------------------------------------------------------
/src/pages/about/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | EasyChat
8 | 是一个可以在线聊天的即时通讯平台,完全由个人设计和开发,初衷主要是觉得好玩儿,顺便学习一些新东西,所以网站有些简陋,属实是本人的能力和财力有限。
9 | 网站没有任何付费内容,所有内容完全免费,欢迎大家使用体验,也期待大佬们的交流与反馈。
10 |
11 |
12 |
13 |
14 |
已实现的功能:
15 |
注册
16 |
登录
17 |
找回密码
18 |
19 |
添加聊天
20 |
删除聊天
21 |
发送文本消息
22 |
发送 Emoji 表情(Windows 7 可能无法正常显示)
23 |
发送图片(批量发送)
24 |
发送文件(同步发送,有点慢)
25 |
新消息通知(有提示音)
26 |
27 |
搜索用户
28 |
修改好友备注
29 |
好友申请
30 |
好友验证
31 |
好友删除(单向删除)
32 |
验证消息通知(有提示音)
33 |
34 |
查看资料
35 |
编辑资料
36 |
设置(头像、隐身、标签、修改密码)
37 |
夜间模式
38 |
小抽屉(搜一搜、日历)
39 |
40 |
暂未实现的功能:
41 |
语音通话、视频通话、聊天组、特别关心、收藏、听音乐、看电影
42 |
43 |
44 |
45 |
46 |
网站正在持续建设中,更多的功能敬请期待...
47 |
48 |
53 |
54 | v1.1.0
55 |
56 | - 新增反馈社区,在这里可以写文章、交朋友、提建议、找BUG...
57 |
58 |
59 |
60 |
65 |
66 | v1.0.1
67 | - 新增聊天消息提示音和好友验证提示音
68 | - 修复了部分已知 BUG
69 |
70 |
71 |
77 |
78 | v1.0.0
79 | - 发布上线
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
目前已知的 BUG :
88 |
89 | - 聊天表情显示问题(Win7系统 Emoji 表情可能无法正常显示)
90 | -
91 | 单次发送多张图片,图片在消息列表中的显示问题(刷新页面后可正确显示)
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | 本网站前端使用 Vue CLI ,部署在 Nginx ;后端使用 Java ,部署在
100 | Tomcat 。
101 |
102 |
前端:
103 |
104 | Vue 3、Vue Router、Vuex、Element
105 | Plus、Socket.IO、Axios、VueUse...
106 |
107 |
后端:
108 |
109 | Spring
110 | Cloud、Nacos、MyBatis-Plus、Netty-socketio、MinIO、Gson、MySQL、Redis、Docker...
111 |
112 |
113 |
114 |
115 |
116 |
136 |
137 |
143 |
144 |
150 |
154 |
155 |
156 |
157 |
158 |
174 |
175 |
--------------------------------------------------------------------------------
/src/pages/home/chat/emoticons.json:
--------------------------------------------------------------------------------
1 | [
2 | "😀",
3 | "😄",
4 | "😁",
5 | "😆",
6 | "😅",
7 | "🤣",
8 | "😂",
9 | "🙂",
10 | "🙃",
11 | "😉",
12 | "😊",
13 | "😇",
14 | "🥰",
15 | "😍",
16 | "🤩",
17 | "😘",
18 | "😗",
19 | "😚",
20 | "😙",
21 | "🥲",
22 | "😋",
23 | "😛",
24 | "😜",
25 | "🤪",
26 | "😝",
27 | "🤑",
28 | "🤗",
29 | "🤭",
30 | "🤫",
31 | "🤔",
32 | "🤐",
33 | "🤨",
34 | "😐",
35 | "😑",
36 | "😶",
37 | "😶🌫️",
38 | "😏",
39 | "😒",
40 | "🙄",
41 | "😬",
42 | "😮💨",
43 | "🤥",
44 | "😌",
45 | "😔",
46 | "😪",
47 | "🤤",
48 | "😴",
49 | "😷",
50 | "🤒",
51 | "🤕",
52 | "🤢",
53 | "🤮",
54 | "🤧",
55 | "🥵",
56 | "🥶",
57 | "🥴",
58 | "😵",
59 | "😵💫",
60 | "🤯",
61 | "🤠",
62 | "🥳",
63 | "🥸",
64 | "😎",
65 | "🤓",
66 | "🧐",
67 | "😕",
68 | "😟",
69 | "🙁",
70 | "☹️",
71 | "😮",
72 | "😯",
73 | "😲",
74 | "😳",
75 | "🥺",
76 | "😦",
77 | "😧",
78 | "😨",
79 | "😰",
80 | "😥",
81 | "😢",
82 | "😭",
83 | "😱",
84 | "😖",
85 | "😣",
86 | "😞",
87 | "😓",
88 | "😩",
89 | "😫",
90 | "🥱",
91 | "😤",
92 | "😡",
93 | "😠",
94 | "🤬",
95 | "😈",
96 | "👿",
97 | "💀",
98 | "☠️",
99 | "💩",
100 | "🤡",
101 | "👹",
102 | "👺",
103 | "👻",
104 | "👽",
105 | "👾",
106 | "🤖",
107 | "😺",
108 | "😸",
109 | "😹",
110 | "😻",
111 | "😼",
112 | "😽",
113 | "🙀",
114 | "😿",
115 | "😾",
116 | "🙈",
117 | "🙉",
118 | "🙊",
119 | "💋",
120 | "💌",
121 | "💘",
122 | "💝",
123 | "💖",
124 | "💗",
125 | "💓",
126 | "💞",
127 | "💕",
128 | "💟",
129 | "❣️",
130 | "💔",
131 | "❤️🔥",
132 | "❤️🩹",
133 | "❤️",
134 | "🧡",
135 | "💛",
136 | "💚",
137 | "💙",
138 | "💜",
139 | "🤎",
140 | "🖤",
141 | "🤍",
142 | "💯",
143 | "💢",
144 | "💥",
145 | "💫",
146 | "💦",
147 | "💨",
148 | "🕳️",
149 | "💣",
150 | "💬",
151 | "👁️🗨️",
152 | "🗨️",
153 | "🗯️",
154 | "💭",
155 | "💤",
156 | "👋",
157 | "🤚",
158 | "🖐️",
159 | "✋",
160 | "🖖",
161 | "👌",
162 | "🤌",
163 | "🤏",
164 | "✌️",
165 | "🤞",
166 | "🤟",
167 | "🤘",
168 | "🤙",
169 | "👈",
170 | "👉",
171 | "👆",
172 | "🖕",
173 | "👇",
174 | "☝️",
175 | "👍",
176 | "👎",
177 | "✊",
178 | "👊",
179 | "🤛",
180 | "🤜",
181 | "👏",
182 | "🙌",
183 | "👐",
184 | "🤲",
185 | "🤝",
186 | "🙏",
187 | "✍️",
188 | "💅",
189 | "🤳",
190 | "💪",
191 | "🦾",
192 | "🦿",
193 | "🦵",
194 | "🦶",
195 | "👂",
196 | "🦻",
197 | "👃",
198 | "🧠",
199 | "🫀",
200 | "🫁",
201 | "🦷",
202 | "🦴",
203 | "👀",
204 | "👁️",
205 | "👅",
206 | "👄"
207 | ]
--------------------------------------------------------------------------------
/src/pages/home/chat/file-upload/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
14 | 选择文件
15 |
16 |
17 |
18 |
19 | 注意:只支持单个文件上传,文件大小不能超过 30MB
20 | ,新文件将会覆盖旧文件。
21 |
22 |
23 |
24 |
33 | 发送
34 |
35 |
36 |
37 |
38 |
164 |
165 |
--------------------------------------------------------------------------------
/src/pages/home/chat/img-upload/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
17 | 注意:只支持 JPG 或 PNG 格式的图片,每张图片大小不能超过 2MB
18 | ,一次最多可发送五张图片。
19 |
20 |
21 |
22 |
31 | 发送
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
179 |
180 |
--------------------------------------------------------------------------------
/src/pages/home/empty/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 所 有 的 相 遇 都 是 久 别 重 逢,该 遇 见 的 人 总 归 不 晚
9 |
10 |
16 |
17 |
18 |
19 |
20 |
25 |
26 |
--------------------------------------------------------------------------------
/src/pages/home/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
126 |
127 |
--------------------------------------------------------------------------------
/src/pages/home/menu/calendar/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
21 |
22 |
23 |
24 |
25 | ⭐ 要天天开心哦 ! ⭐
26 |
27 | {{ date }}
28 |
29 |
30 |
36 | 上一年
37 |
38 |
44 | 上个月
45 |
46 | 今天
53 |
59 | 下个月
60 |
61 |
67 | 下一年
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
114 |
115 |
--------------------------------------------------------------------------------
/src/pages/home/menu/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
192 |
193 |
194 |
283 |
284 |
--------------------------------------------------------------------------------
/src/pages/home/menu/profile-edit/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
23 |
24 |
32 |
33 | 昵称
34 |
41 |
42 |
43 |
44 |
45 | 性别
46 |
47 | 男
48 | 女
49 | 保密
50 |
51 |
52 |
53 | 生日
54 |
61 |
62 |
63 | 邮箱
64 |
72 |
73 |
74 |
75 |
76 | 手机号
77 |
84 |
85 |
86 |
87 |
88 | 地区
89 |
98 |
99 |
100 | 个人介绍
101 |
111 |
112 |
120 | {{ loading ? "保存中..." : "保 存" }}
121 |
122 |
123 |
124 |
125 |
126 |
127 |
261 |
262 |
--------------------------------------------------------------------------------
/src/pages/home/menu/search/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
21 |
22 |
23 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | 搜索
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
104 |
105 |
--------------------------------------------------------------------------------
/src/pages/home/menu/settings/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
21 |
22 |
23 |
24 |
头像
25 |
33 | true"
38 | >
39 |
40 |
44 |
45 |
46 |
47 |
48 | 预览
49 |
50 |
58 | 保存
59 |
60 |
61 |
62 | 状态
63 |
73 |
74 |
75 | 标签
76 |
77 |
86 | {{ tag }}
87 |
88 |
98 |
99 | + 添加标签
100 |
101 |
102 |
103 |
104 |
105 | 修改密码
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
121 |
125 |
126 |
127 |
138 |
139 |
140 |
141 |
142 |
334 |
335 |
--------------------------------------------------------------------------------
/src/pages/home/menu/settings/password-reset/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
20 |
21 |
22 | 原密码
23 |
24 |
31 |
32 |
33 |
34 | 新密码
35 |
36 |
43 |
44 |
45 |
46 | 确认密码
47 |
48 |
55 |
56 |
57 |
64 | {{ loading ? "修改中..." : "修改" }}
65 |
66 | 重置
67 |
68 |
69 |
70 |
71 |
72 |
215 |
216 |
--------------------------------------------------------------------------------
/src/pages/home/profile/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
20 |
21 |
22 |
23 | true"
31 | >
32 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | {{ tag }}
42 |
43 |
44 |
45 |
46 | {{
47 | userInfo.introduction
48 | ? userInfo.introduction
49 | : "这个人很神秘,什么都没有写..."
50 | }}
51 |
52 |
53 |
54 |
用户名
55 |
{{ userInfo.username }}
56 |
57 |
58 |
59 |
昵称
60 |
{{ userInfo.nickName }}
61 |
62 |
63 |
64 |
性别
65 |
66 | {{
67 | userInfo.gender === 0
68 | ? "女"
69 | : userInfo.gender === 1
70 | ? "男"
71 | : "保密"
72 | }}
73 |
74 |
75 |
76 |
77 |
年龄
78 |
{{ userInfo.age > 0 ? userInfo.age : "保密" }}
79 |
80 |
81 |
82 |
生日
83 |
84 | {{
85 | userInfo.birthday
86 | ? formatDate(userInfo.birthday, "M 月 D 日")
87 | : "保密"
88 | }}
89 |
90 |
91 |
92 |
93 |
邮箱
94 |
{{ userInfo.email }}
95 |
96 |
97 |
98 |
手机号
99 |
{{ userInfo.phone ? userInfo.phone : "保密" }}
100 |
101 |
102 |
103 |
地区
104 |
{{ userInfo.region ? userInfo.region : "银河 地球" }}
105 |
106 |
107 |
108 |
109 |
110 |
111 |
176 |
177 |
--------------------------------------------------------------------------------
/src/pages/home/sidebar-archived/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/src/pages/home/sidebar-chats/chat-add/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 | 好友
14 |
23 |
34 |
35 |
36 |
37 |
38 |
39 | 返回
40 |
41 | 确定
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
99 |
100 |
--------------------------------------------------------------------------------
/src/pages/home/sidebar-favorites/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/src/pages/home/sidebar-friends/friend-add/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
16 |
26 |
27 |
28 |
29 | 搜索
30 |
31 |
32 |
33 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
85 |
86 | {{
87 | user.introduction
88 | ? user.introduction
89 | : "这个人很神秘,什么都没有写..."
90 | }}
91 |
92 |
101 |
102 |
103 |
104 |
105 |
106 |
184 |
185 |
186 |
187 | 返回
188 |
195 | {{ loading ? "发送中..." : "发送" }}
196 |
197 |
198 |
199 |
200 |
201 |
202 |
355 |
356 |
--------------------------------------------------------------------------------
/src/pages/home/sidebar-friends/friend-verify/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | 申请理由:{{ row.applyReason ? row.applyReason : "无" }}
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | true"
47 | >
48 |
51 |
52 |
53 |
54 |
55 | {{
56 | row.senderId === user.userId
57 | ? row.receiverNickName
58 | : row.senderNickName
59 | }}
60 |
61 |
62 | {{
63 | row.senderId === user.userId
64 | ? "请求添加对方为好友"
65 | : "请求添加你为好友"
66 | }}
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | {{
76 | row.status === 0
77 | ? "等待验证"
78 | : row.status === 1
79 | ? "对方已同意"
80 | : row.status === 2
81 | ? "对方已拒绝"
82 | : "已过期"
83 | }}
84 |
85 |
86 |
87 | 同意
90 | 拒绝
93 |
94 |
95 | {{
96 | row.status === 1
97 | ? "已同意"
98 | : row.status === 2
99 | ? "已拒绝"
100 | : "已过期"
101 | }}
102 |
103 |
104 |
105 |
106 |
107 |
108 |
155 |
156 |
157 |
158 | 取消
159 |
160 | 完成
161 |
162 |
163 |
164 |
165 |
166 |
167 |
290 |
291 |
--------------------------------------------------------------------------------
/src/pages/home/sidebar-friends/remark-reset/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
10 |
60 |
61 |
62 |
63 |
176 |
177 |
--------------------------------------------------------------------------------
/src/pages/home/sidebar-groups/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/src/pages/login/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
密码登录
6 |
14 |
15 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | 7天内免登录
49 |
50 | 忘记密码?
51 |
52 |
58 | {{ loading ? "登录中..." : "登 录" }}
59 |
60 |
61 |
62 | 没有账号?
63 | 立即注册
64 |
65 |
66 | 登录即表示同意《用户协议》《隐私政策》
69 |
70 |
71 |
82 |
99 |
105 |
109 |
110 |
117 |
129 | {{ successMsg }}
130 |
131 |
132 |
133 |
134 |
239 |
240 |
--------------------------------------------------------------------------------
/src/pages/register/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
14 | 欢迎注册EasyChat
15 |
16 |
23 |
24 | 6~11个字符,可使用字母、数字、下划线,需以字母开头
25 |
26 |
27 |
28 |
35 | 1~11个字符,可自由输入您的昵称
36 |
37 |
38 |
47 |
48 | 8~16个字符,可使用字母、数字、特殊符号 (~!@#$%^&*?_.)
49 | ,需包含其中至少两种
50 |
51 |
52 |
53 |
61 | 可通过该邮箱找回密码
62 |
63 |
64 |
71 |
72 |
79 | 获取验证码
80 | 重新获取({{ count }}s)
81 |
82 |
83 |
84 |
85 |
86 |
91 |
94 |
95 |
96 |
102 | {{ loading ? "注册中..." : "立即注册" }}
103 |
104 |
105 | 已有账号? 直接登录
106 |
107 |
108 |
109 |
110 |
121 |
127 |
131 |
132 |
133 |
134 |
135 |
338 |
339 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import { createRouter, createWebHashHistory } from 'vue-router'
2 | import { getCookie } from '@/utils/cookie';
3 |
4 | const routes = [
5 | {
6 | path: '/login',
7 | component: () => import('@/pages/login'),
8 | name: 'login'
9 | },
10 | {
11 | path: '/register',
12 | component: () => import('@/pages/register'),
13 | name: 'register'
14 | },
15 | {
16 | path: '/home',
17 | component: () => import('@/pages/home'),
18 | name: 'home'
19 | },
20 | {
21 | path: '/findPassword',
22 | component: () => import('@/pages/password'),
23 | name: 'findPassword'
24 | },
25 | {
26 | path: '/about',
27 | component: () => import('@/pages/about'),
28 | name: 'about'
29 | },
30 | {
31 | path: '/',
32 | redirect: "/home"
33 | }
34 | ]
35 |
36 | const router = createRouter({
37 | history: createWebHashHistory(),
38 | routes
39 | })
40 |
41 | router.beforeEach((to, from, next) => {
42 | if (to.path === "/login" || to.path === "/register" || to.path === "/findPassword" || to.path === "/about") {
43 | return next();
44 | }
45 | const uid = getCookie("uid");
46 | if (uid !== null && new RegExp(/\d{19}/).test(uid)) {
47 | return next();
48 | }
49 | return next("/login");
50 | })
51 |
52 | export default router
--------------------------------------------------------------------------------
/src/store/home/index.js:
--------------------------------------------------------------------------------
1 | import { mockGetChatList, mockGetFriendList, mockGetFriendVerify, mockGetHistory, reqGetChatList, reqGetFriendList, reqGetFriendVerify, reqGetHistory } from "@/api";
2 |
3 | const state = {
4 | onlineUsers: [],
5 | chatList: [],
6 | friendList: [],
7 | friendVerifyList: [],
8 | chatHistories: []
9 | };
10 | const mutations = {
11 | ONLINEUSERS(state, onlineUsers) {
12 | state.onlineUsers = onlineUsers;
13 | },
14 | CHATLIST(state, chatList) {
15 | state.chatList = chatList;
16 | },
17 | FRIENDLIST(state, friendList) {
18 | state.friendList = friendList;
19 | },
20 | FRIENDVERIFY(state, friendVerifyList) {
21 | state.friendVerifyList = friendVerifyList
22 | },
23 | HISTORY(state, chatHistories) {
24 | state.chatHistories = chatHistories;
25 | }
26 | };
27 | const actions = {
28 | // async getChatList({ commit }) {
29 | // let result = await mockGetChatList();
30 | // if (result.code === 200) {
31 | // commit("CHATLIST", result.data.sort((obj1, obj2) => {
32 | // if (obj1.createTime > obj2.createTime) {
33 | // return -1;
34 | // } else if (obj1.createTime < obj2.createTime) {
35 | // return 1;
36 | // } else {
37 | // return 0;
38 | // }
39 | // }));
40 | // }
41 | // },
42 | // async getFriendList({ commit }) {
43 | // let result = await mockGetFriendList();
44 | // if (result.code === 200) {
45 | // commit("FRIENDLIST", result.data.sort());
46 | // }
47 | // },
48 | // async getFriendVerify({ commit }) {
49 | // let result = await mockGetFriendVerify();
50 | // if (result.code === 200) {
51 | // commit("FRIENDVERIFY", result.data.sort((obj1, obj2) => {
52 | // if (obj1.createTime > obj2.createTime) {
53 | // return -1;
54 | // } else if (obj1.createTime < obj2.createTime) {
55 | // return 1;
56 | // } else {
57 | // return 0;
58 | // }
59 | // }));
60 | // }
61 | // },
62 | // async getHistory({ commit }) {
63 | // let result = await mockGetHistory();
64 | // if (result.code === 200) {
65 | // commit("HISTORY", result.data);
66 | // }
67 | // },
68 |
69 | async getChatList({ commit }, userId) {
70 | let result = await reqGetChatList({ id: userId });
71 | if (result.success) {
72 | commit("CHATLIST", result.data.sort((obj1, obj2) => {
73 | let time1 = obj1.latestChatHistory ? obj1.latestChatHistory.createTime : obj1.sessionTime;
74 | let time2 = obj2.latestChatHistory ? obj2.latestChatHistory.createTime : obj2.sessionTime;
75 | if (time1 > time2) {
76 | return -1;
77 | } else if (time1 < time2) {
78 | return 1;
79 | } else {
80 | return 0;
81 | }
82 | }));
83 | }
84 | },
85 | async getFriendList({ commit }, userId) {
86 | let result = await reqGetFriendList({ id: userId });
87 | if (result.success) {
88 | commit("FRIENDLIST", result.data.sort());
89 | }
90 | },
91 | async getFriendVerify({ commit }, userId) {
92 | let result = await reqGetFriendVerify({ id: userId });
93 | if (result.success) {
94 | commit("FRIENDVERIFY", result.data.sort((obj1, obj2) => {
95 | if (obj1.createTime > obj2.createTime) {
96 | return -1;
97 | } else if (obj1.createTime < obj2.createTime) {
98 | return 1;
99 | } else {
100 | return 0;
101 | }
102 | }));
103 | }
104 | },
105 | async getHistory({ commit }, params) {
106 | let result = await reqGetHistory(params);
107 | if (result.success) {
108 | if (result.data.records) {
109 | commit("HISTORY", result.data.records.sort((obj1, obj2) => {
110 | if (obj1.createTime < obj2.createTime) {
111 | return -1;
112 | } else if (obj1.createTime > obj2.createTime) {
113 | return 1;
114 | } else {
115 | return 0;
116 | }
117 | }));
118 | } else {
119 | commit("HISTORY", []);
120 | }
121 | }
122 | }
123 | };
124 | const getters = {};
125 |
126 | export default {
127 | namespaced: true,
128 |
129 | state,
130 | mutations,
131 | actions,
132 | getters
133 | }
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import { createStore } from "vuex";
2 |
3 | import home from './home';
4 |
5 | export default createStore({
6 | modules: {
7 | home
8 | }
9 | })
--------------------------------------------------------------------------------
/src/utils/cookie.js:
--------------------------------------------------------------------------------
1 | export function getCookie(name) {
2 | if (typeof name === 'string' && name !== '') {
3 | var arr = document.cookie.match(new RegExp("(^| )" + name + "=([^;]*)(;|$)"));
4 | if (arr != null) {
5 | return arr[2] ? decodeURIComponent(arr[2]) : null;
6 | }
7 | }
8 | return null;
9 | }
10 |
11 | export function setCookie(name, value, seconds) {
12 | var date = new Date();
13 | date.setTime(date.getTime + seconds * 1000);
14 | var expires = "expires=" + date.toGMTString();
15 | document.cookie = name + "=" + value + "; " + expires;
16 | }
--------------------------------------------------------------------------------
/src/utils/date.js:
--------------------------------------------------------------------------------
1 | import moment from "moment";
2 |
3 | export function compareDate(date, day = 0) {
4 | return moment(date).format("YYYY-MM-DD") ===
5 | moment().subtract(day, "days").format("YYYY-MM-DD");
6 | }
7 |
8 | export function compareYear(date) {
9 | return moment(date).format("YYYY") === moment().format("YYYY");
10 | }
11 |
12 | export function formatDate(date, formatStr) {
13 | return moment(date).format(formatStr);
14 | }
15 |
16 | export function computeMinuteDiff(startTime, endTime) {
17 | return moment(endTime).diff(startTime) / (1000 * 60);
18 | }
--------------------------------------------------------------------------------
/src/utils/encrypt.js:
--------------------------------------------------------------------------------
1 | export function encryptPhone(str) {
2 | if (null !== str && str !== undefined) {
3 | var pat = /(\d{3})\d*(\d{2})/;
4 | return str.replace(pat, '$1****$2');
5 | } else {
6 | return "";
7 | }
8 | }
9 |
10 | export function encryptIdNo(str) {
11 | if (null !== str && str !== undefined) {
12 | var pat = /(\d{4})\d*(\d{4})/;
13 | return str.replace(pat, '$1***********$2');
14 | } else {
15 | return "";
16 | }
17 | }
18 |
19 | export function encryptName(str) {
20 | if (null !== str && str !== undefined) {
21 | if (str.length <= 3) {
22 | return "*" + str.substring(1, str.length);
23 | } else if (str.length > 3 && str.length <= 6) {
24 | return "**" + str.substring(2, str.length);
25 | } else if (str.length > 6) {
26 | return str.substring(0, 2) + "****" + str.substring(6, str.length)
27 | }
28 | } else {
29 | return "";
30 | }
31 | }
32 |
33 | export function encryptEmail(email) {
34 | let new_email = email;
35 | if (String(email).indexOf('@') > 0) {
36 | let str = email.split('@');
37 | let _s = '';
38 | if (str[0].length > 3) { //@前面多于3位
39 | for (let i = 3; i < str[0].length; i++) {
40 | _s += '*';
41 | }
42 | new_email = str[0].substr(0, 3) + _s + '@' + str[1];
43 | } else { //@前面小于等于于3位
44 | for (let i = 1; i < str[0].length; i++) {
45 | _s += '*'
46 | }
47 | new_email = str[0].substr(0, 1) + _s + '@' + str[1]
48 | }
49 | }
50 | return new_email;
51 | }
--------------------------------------------------------------------------------
/vue.config.js:
--------------------------------------------------------------------------------
1 | const { defineConfig } = require('@vue/cli-service')
2 | const AutoImport = require('unplugin-auto-import/webpack')
3 | const Components = require('unplugin-vue-components/webpack')
4 | const Icons = require('unplugin-icons/webpack')
5 | const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
6 | const IconsResolver = require('unplugin-icons/resolver')
7 |
8 | module.exports = defineConfig({
9 | transpileDependencies: true,
10 | lintOnSave: false,
11 | configureWebpack: {
12 | plugins: [
13 | AutoImport({
14 | resolvers: [
15 | ElementPlusResolver(),
16 | ],
17 | }),
18 | Components({
19 | resolvers: [
20 | ElementPlusResolver(),
21 | IconsResolver({
22 | prefix: 'icon',
23 | enabledCollections: ['ep', 'mdi'],
24 | }),
25 | ],
26 | }),
27 | Icons(),
28 | ],
29 | },
30 | devServer: {
31 | port: 8080,
32 | allowedHosts: "all",
33 | proxy: {
34 | '/api': {
35 | target: 'https://toollong.icu'
36 | }
37 | }
38 | }
39 | })
--------------------------------------------------------------------------------