mirror of
https://github.com/cool-team-official/cool-admin-vue.git
synced 2024-11-01 06:02:38 +08:00
Merge branch 'cool-team-official:5.x' into 5.x
This commit is contained in:
commit
77c53c78fb
File diff suppressed because one or more lines are too long
2252
build/cool/temp/service.d.ts
vendored
2252
build/cool/temp/service.d.ts
vendored
File diff suppressed because it is too large
Load Diff
@ -9,14 +9,14 @@
|
||||
"lint:eslint": "eslint \"{src,mock}/**/*.{vue,ts,tsx}\" --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cool-vue/crud": "^5.0.10",
|
||||
"@cool-vue/crud": "^5.0.13",
|
||||
"@element-plus/icons-vue": "^1.1.3",
|
||||
"@vueuse/core": "^8.2.5",
|
||||
"axios": "^0.27.2",
|
||||
"codemirror": "^5.62.0",
|
||||
"core-js": "^3.6.5",
|
||||
"echarts": "^5.0.2",
|
||||
"element-plus": "^2.2.0",
|
||||
"element-plus": "^2.2.5",
|
||||
"file-saver": "^2.0.5",
|
||||
"js-beautify": "^1.13.5",
|
||||
"lodash": "^4.17.21",
|
||||
@ -25,6 +25,7 @@
|
||||
"nprogress": "^0.2.0",
|
||||
"pinia": "^2.0.12",
|
||||
"quill": "^1.3.7",
|
||||
"socket.io-client": "^4.5.1",
|
||||
"store": "^2.0.12",
|
||||
"unocss": "^0.31.0",
|
||||
"vue": "^3.2.32",
|
||||
|
@ -3,4 +3,4 @@ export * from "./bootstrap";
|
||||
export * from "./hook";
|
||||
export * from "./router";
|
||||
export * from "./config";
|
||||
export { storage } from "./utils";
|
||||
export { storage, module } from "./utils";
|
||||
|
@ -86,6 +86,7 @@ export function useEps(service: Service) {
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("[Eps] 获取失败!", err.message);
|
||||
createDts([]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,10 @@
|
||||
|
||||
<!-- 工具栏 -->
|
||||
<ul class="app-topbar__tools">
|
||||
<li>
|
||||
<cl-chat />
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<cl-theme />
|
||||
</li>
|
||||
@ -115,6 +119,7 @@ function onCommand(name: string) {
|
||||
width: 45px;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
|
265
src/modules/chat/components/index.vue
Normal file
265
src/modules/chat/components/index.vue
Normal file
@ -0,0 +1,265 @@
|
||||
<template>
|
||||
<div class="cl-chat__wrap">
|
||||
<div class="cl-chat__icon" @click="open">
|
||||
<el-badge :value="unCount">
|
||||
<el-icon><BellFilled /></el-icon>
|
||||
</el-badge>
|
||||
</div>
|
||||
|
||||
<!-- 弹框 -->
|
||||
<cl-dialog
|
||||
v-model="visible"
|
||||
title="聊天窗口"
|
||||
height="630px"
|
||||
width="1200px"
|
||||
keep-alive
|
||||
custom-class="cl-chat__dialog"
|
||||
:close-on-click-modal="false"
|
||||
:close-on-press-escape="false"
|
||||
append-to-body
|
||||
:controls="['slot-expand', 'cl-flex1', 'fullscreen', 'close']"
|
||||
>
|
||||
<div
|
||||
class="cl-chat"
|
||||
:class="{
|
||||
'is-mini': app.browser.isMini,
|
||||
'is-expand': isExpand
|
||||
}"
|
||||
>
|
||||
<div class="cl-chat__session">
|
||||
<chat-session />
|
||||
</div>
|
||||
|
||||
<div class="cl-chat__right">
|
||||
<chat-message />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 展开按钮 -->
|
||||
<template #slot-expand>
|
||||
<button class="cl-dialog__controls-icon">
|
||||
<el-icon @click="isExpand = true" v-if="!isExpand">
|
||||
<notebook />
|
||||
</el-icon>
|
||||
<el-icon @click="isExpand = false" v-else>
|
||||
<arrow-left />
|
||||
</el-icon>
|
||||
</button>
|
||||
</template>
|
||||
</cl-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: "cl-chat"
|
||||
};
|
||||
</script>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { nextTick, provide, ref, watch } from "vue";
|
||||
import { module } from "/@/cool/utils";
|
||||
import { useCool, config } from "/@/cool";
|
||||
import { useBase } from "/$/base";
|
||||
import { Notebook, ArrowLeft, BellFilled } from "@element-plus/icons-vue";
|
||||
import { debounce } from "lodash";
|
||||
import io from "socket.io-client";
|
||||
import { Socket } from "socket.io-client";
|
||||
import ChatMessage from "./message.vue";
|
||||
import ChatSession from "./session.vue";
|
||||
import { Chat } from "../types";
|
||||
import { useStore } from "../store";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
const { mitt } = useCool();
|
||||
|
||||
// 缓存
|
||||
const { session, message } = useStore();
|
||||
|
||||
// 缓存
|
||||
const { app, user } = useBase();
|
||||
|
||||
// 模块配置
|
||||
const { options } = module.get("chat");
|
||||
|
||||
// 是否可见
|
||||
const visible = ref(false);
|
||||
|
||||
// 是否展开
|
||||
const isExpand = ref(true);
|
||||
|
||||
// 未读消息
|
||||
const unCount = ref(parseInt(Math.random() * 100));
|
||||
|
||||
// Socket
|
||||
let socket: Socket;
|
||||
|
||||
// 连接
|
||||
function connect() {
|
||||
return refresh();
|
||||
|
||||
if (!socket) {
|
||||
socket = io(config.host + options.path, {
|
||||
auth: {
|
||||
token: user.token
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("connect", () => {
|
||||
console.log(`connect ${user.info?.nickName}`);
|
||||
|
||||
// 监听消息
|
||||
socket.on("message", (msg) => {
|
||||
console.log(msg);
|
||||
mitt("chat-message", msg);
|
||||
});
|
||||
|
||||
refresh();
|
||||
});
|
||||
|
||||
socket.on("disconnect", (err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 打开
|
||||
function open() {
|
||||
visible.value = true;
|
||||
connect();
|
||||
}
|
||||
|
||||
// 关闭
|
||||
function close() {
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
// 发送消息
|
||||
function send(data: Chat.Message, isAppend?: boolean) {
|
||||
// socket.emit("message", {});
|
||||
|
||||
if (isAppend) {
|
||||
append(data);
|
||||
}
|
||||
}
|
||||
|
||||
// 追加消息
|
||||
function append(data: Chat.Message) {
|
||||
message.list.push({
|
||||
fromId: user.info?.id,
|
||||
toId: session.value?.userId,
|
||||
avatar: user.info?.headImg,
|
||||
nickName: user.info?.nickName,
|
||||
createTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
|
||||
...data
|
||||
});
|
||||
|
||||
scrollToBottom();
|
||||
}
|
||||
|
||||
// 滚动到底部
|
||||
const scrollToBottom = debounce(() => {
|
||||
nextTick(() => {
|
||||
const box = document.querySelector(".cl-chat .chat-message .list");
|
||||
box?.scroll({
|
||||
top: 100000 + Math.random(),
|
||||
behavior: "smooth"
|
||||
});
|
||||
});
|
||||
}, 300);
|
||||
|
||||
// 刷新
|
||||
async function refresh() {
|
||||
await session.get();
|
||||
await message.get();
|
||||
scrollToBottom();
|
||||
}
|
||||
|
||||
provide("chat", {
|
||||
socket,
|
||||
send,
|
||||
scrollToBottom
|
||||
});
|
||||
|
||||
// 监听屏幕大小变化
|
||||
watch(
|
||||
() => app.browser.isMini,
|
||||
(val) => {
|
||||
isExpand.value = val ? false : true;
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
open,
|
||||
close
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.cl-chat {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
background-color: #eee;
|
||||
height: 100%;
|
||||
padding: 5px;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
|
||||
&__icon {
|
||||
padding: 5px;
|
||||
.el-badge__content {
|
||||
transform: translateY(-50%) translateX(100%) scale(0.8) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&__dialog {
|
||||
.el-dialog__body {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__footer {
|
||||
padding: 9px 0;
|
||||
}
|
||||
|
||||
&__session {
|
||||
height: calc(100% - 10px);
|
||||
width: 345px;
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
&__right {
|
||||
position: relative;
|
||||
z-index: 99;
|
||||
transition: width 0.3s;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.is-mini {
|
||||
&.is-expand {
|
||||
.cl-chat__session {
|
||||
z-index: 100;
|
||||
}
|
||||
}
|
||||
|
||||
.cl-chat__session {
|
||||
width: calc(100% - 10px);
|
||||
}
|
||||
|
||||
.cl-chat__right {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-expand {
|
||||
.cl-chat__right {
|
||||
width: calc(100% - 350px);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
342
src/modules/chat/components/message.vue
Normal file
342
src/modules/chat/components/message.vue
Normal file
@ -0,0 +1,342 @@
|
||||
<template>
|
||||
<div class="chat-message" v-loading="message?.loading" element-loading-text="消息列表加载中">
|
||||
<!-- 头部 -->
|
||||
<div class="head">
|
||||
<template v-if="session?.value">
|
||||
<div class="avatar">
|
||||
<el-avatar :size="30" shape="square" :src="session?.value.avatar"></el-avatar>
|
||||
</div>
|
||||
<span class="name">与“{{ session?.value.nickName }}”聊天中</span>
|
||||
|
||||
<ul class="tools">
|
||||
<li></li>
|
||||
</ul>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<!-- 消息列表 -->
|
||||
<div class="list scroller1">
|
||||
<ul>
|
||||
<li v-for="(item, index) in list" :key="index">
|
||||
<div
|
||||
class="item"
|
||||
:class="{
|
||||
'is-right': item.isMy
|
||||
}"
|
||||
>
|
||||
<div class="avatar">
|
||||
<el-avatar :size="36" shape="square" :src="item.avatar"></el-avatar>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="det"
|
||||
@contextmenu="
|
||||
(e) => {
|
||||
onContextMenu(e, item);
|
||||
}
|
||||
"
|
||||
>
|
||||
<div class="h">
|
||||
<span class="name">{{ item.nickName }}</span>
|
||||
</div>
|
||||
<div class="content">
|
||||
<!-- 文本 -->
|
||||
<div class="is-text" v-if="item.contentType == 0">
|
||||
<span>{{ item.content.text }}</span>
|
||||
</div>
|
||||
|
||||
<!-- 图片 -->
|
||||
<div class="is-image" v-else-if="item.contentType == 1">
|
||||
<el-image
|
||||
:src="item.content.imageUrl"
|
||||
:preview-src-list="previewUrls"
|
||||
:initial-index="item._index"
|
||||
scroll-container=".chat-message .list"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- 底部 -->
|
||||
<div class="footer">
|
||||
<div class="tools">
|
||||
<ul>
|
||||
<li>
|
||||
<cl-upload @success="onImageSend" :show-file-list="false">
|
||||
<el-icon><Picture /></el-icon>
|
||||
</cl-upload>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="input">
|
||||
<el-input
|
||||
v-model="value"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
resize="none"
|
||||
:autosize="{
|
||||
minRows: 4,
|
||||
maxRows: 10
|
||||
}"
|
||||
placeholder="输入内容"
|
||||
></el-input>
|
||||
<el-button size="small" type="success" @click="onTextSend" :disabled="!value"
|
||||
>发送</el-button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from "vue";
|
||||
import { useChat } from "../hooks";
|
||||
import { useStore } from "../store";
|
||||
import { Picture } from "@element-plus/icons-vue";
|
||||
import { useBase } from "/$/base";
|
||||
import { ContextMenu } from "@cool-vue/crud";
|
||||
import { useClipboard } from "@vueuse/core";
|
||||
import { Chat } from "../types";
|
||||
|
||||
const { user } = useBase();
|
||||
const { chat } = useChat();
|
||||
const { message, session } = useStore();
|
||||
const { copy } = useClipboard();
|
||||
|
||||
const value = ref("");
|
||||
|
||||
// 过滤列表
|
||||
const list = computed(() => {
|
||||
let n = 0;
|
||||
|
||||
return message.list.map((e) => {
|
||||
if (e.contentType == 1) {
|
||||
e._index = n++;
|
||||
}
|
||||
|
||||
// 是否自己发的消息
|
||||
e.isMy = e.fromId == user.info?.id;
|
||||
|
||||
return e;
|
||||
});
|
||||
});
|
||||
|
||||
// 预览图片地址
|
||||
const previewUrls = computed(() =>
|
||||
message.list
|
||||
.filter((e) => e.contentType == 1)
|
||||
.map((e) => e.content?.imageUrl)
|
||||
.filter(Boolean)
|
||||
);
|
||||
|
||||
// 文本消息
|
||||
function onTextSend() {
|
||||
chat?.send(
|
||||
{
|
||||
contentType: 0,
|
||||
content: {
|
||||
text: value.value
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
value.value = "";
|
||||
}
|
||||
|
||||
// 图片消息
|
||||
function onImageSend(res: any) {
|
||||
chat?.send(
|
||||
{
|
||||
contentType: 1,
|
||||
content: {
|
||||
imageUrl: res.url
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
value.value = "";
|
||||
}
|
||||
|
||||
// 右键菜单
|
||||
function onContextMenu(e: Event, item: Chat.Message) {
|
||||
ContextMenu.open(e, {
|
||||
hover: {
|
||||
target: "content"
|
||||
},
|
||||
list: [
|
||||
{
|
||||
label: "复制",
|
||||
callback(done) {
|
||||
copy(item.content.text || "");
|
||||
done();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "转发"
|
||||
},
|
||||
{
|
||||
label: "删除"
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.chat-message {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 50px;
|
||||
padding: 0 10px;
|
||||
|
||||
.name {
|
||||
margin-left: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
ul {
|
||||
li {
|
||||
list-style: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
flex: 1;
|
||||
background-color: #f7f7f7;
|
||||
|
||||
ul {
|
||||
& > li {
|
||||
list-style: none;
|
||||
|
||||
.date {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 40px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
padding: 10px;
|
||||
|
||||
.avatar {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.det {
|
||||
.h {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.name {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 5px;
|
||||
|
||||
.is-text {
|
||||
background-color: #fff;
|
||||
padding: 8px;
|
||||
border-radius: 0 5px 5px 5px;
|
||||
max-width: 400px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.is-image {
|
||||
background-color: #fff;
|
||||
|
||||
.el-image {
|
||||
display: block;
|
||||
min-height: 100px;
|
||||
max-width: 200px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-right {
|
||||
flex-direction: row-reverse;
|
||||
|
||||
.avatar {
|
||||
margin-left: 10px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.det {
|
||||
.h {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.content {
|
||||
.is-text {
|
||||
border-radius: 5px 0 5px 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
padding: 10px;
|
||||
|
||||
.tools {
|
||||
display: flex;
|
||||
margin-bottom: 10px;
|
||||
|
||||
ul {
|
||||
li {
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
border-radius: 3px;
|
||||
margin-right: 10px;
|
||||
list-style: none;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
|
||||
&:hover {
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
.el-button {
|
||||
margin-left: 10px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
bottom: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
176
src/modules/chat/components/session.vue
Normal file
176
src/modules/chat/components/session.vue
Normal file
@ -0,0 +1,176 @@
|
||||
<template>
|
||||
<div class="chat-session">
|
||||
<div class="head">
|
||||
<el-input v-model="keyWord" placeholder="关键字搜索" clearable></el-input>
|
||||
|
||||
<ul class="tools">
|
||||
<li @click="session.get()">
|
||||
<el-icon :size="16"><Refresh /></el-icon>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="list" v-loading="session?.loading">
|
||||
<div class="scroller1">
|
||||
<div
|
||||
class="item"
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
:class="{
|
||||
'is-active': item.id == session?.value?.id
|
||||
}"
|
||||
@click="toDetail(item)"
|
||||
>
|
||||
<div class="avatar">
|
||||
<el-badge :value="item.num" :hidden="item.num == 0">
|
||||
<el-avatar shape="square" :src="item.avatar"></el-avatar>
|
||||
</el-badge>
|
||||
</div>
|
||||
|
||||
<div class="det">
|
||||
<p class="name">{{ item.nickName }}</p>
|
||||
<p class="message">
|
||||
{{ item.text }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="status">
|
||||
<p class="date">{{ item.createTime }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-empty v-if="list.length == 0" image-size="100" description="暂无会话"></el-empty>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from "vue";
|
||||
import { useChat } from "../hooks";
|
||||
import { useStore } from "../store";
|
||||
import { Refresh } from "@element-plus/icons-vue";
|
||||
import { Chat } from "../types";
|
||||
|
||||
const { chat } = useChat();
|
||||
const { session, message } = useStore();
|
||||
|
||||
// 关键字
|
||||
const keyWord = ref("");
|
||||
|
||||
// 过滤列表
|
||||
const list = computed(() => session?.list.filter((e) => e.nickName?.includes(keyWord.value)) || []);
|
||||
|
||||
// 会话详情
|
||||
async function toDetail(item: Chat.Session) {
|
||||
session.set(item);
|
||||
await message.get({ page: 1 });
|
||||
chat?.scrollToBottom();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.chat-session {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
|
||||
.head {
|
||||
display: flex;
|
||||
border-bottom: 1px solid #f7f7f7;
|
||||
padding: 10px;
|
||||
|
||||
.el-input {
|
||||
height: 30px;
|
||||
background-color: #eee !important;
|
||||
}
|
||||
|
||||
.tools {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
li {
|
||||
height: 30px;
|
||||
width: 30px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
border-radius: 3px;
|
||||
|
||||
&:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list {
|
||||
height: calc(100% - 51px);
|
||||
overflow: hidden;
|
||||
|
||||
.scroller1 {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
padding: 15px 10px;
|
||||
cursor: pointer;
|
||||
|
||||
.avatar {
|
||||
margin-right: 15px;
|
||||
|
||||
:deep(.el-badge__content) {
|
||||
transform: translateY(-50%) translateX(100%) scale(0.8) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.det {
|
||||
flex: 1;
|
||||
|
||||
.name,
|
||||
.message {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 1;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 14px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.message {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
.status {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
font-size: 12px;
|
||||
|
||||
.date {
|
||||
margin-bottom: 5px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
&:not(.is-active):hover {
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
4
src/modules/chat/config.ts
Normal file
4
src/modules/chat/config.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export default {
|
||||
// socket.io 连接地址
|
||||
path: "/chat"
|
||||
};
|
10
src/modules/chat/hooks/index.ts
Normal file
10
src/modules/chat/hooks/index.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { inject } from "vue";
|
||||
import { Chat } from "../types";
|
||||
|
||||
export function useChat() {
|
||||
const chat = inject<Chat.Provide>("chat");
|
||||
|
||||
return {
|
||||
chat
|
||||
};
|
||||
}
|
56
src/modules/chat/service/message.ts
Normal file
56
src/modules/chat/service/message.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import { BaseService, Service } from "/@/cool";
|
||||
import Mock from "mockjs";
|
||||
|
||||
@Service("chat/message")
|
||||
class ChatMessage extends BaseService {
|
||||
page() {
|
||||
return new Promise((resolve) => {
|
||||
const data = Mock.mock({
|
||||
"list|20": [
|
||||
{
|
||||
id: "@id",
|
||||
nickName: "@name",
|
||||
createTime: "@datetime(HH:mm:ss)",
|
||||
text: "@cparagraph(5)",
|
||||
"contentType|0-1": 0,
|
||||
"userId|1-2": 1,
|
||||
avatar() {
|
||||
return Mock.Random.image(
|
||||
"40x40",
|
||||
Mock.Random.color(),
|
||||
"#FFF",
|
||||
"png",
|
||||
this.nickName[0]
|
||||
);
|
||||
},
|
||||
content() {
|
||||
return JSON.stringify({
|
||||
text: this.text,
|
||||
imageUrl: Mock.Random.image(
|
||||
"100x100",
|
||||
Mock.Random.color(),
|
||||
"#FFF",
|
||||
"png",
|
||||
this.nickName
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
list: data.list,
|
||||
pagination: {
|
||||
total: 20,
|
||||
page: 1,
|
||||
size: 20
|
||||
}
|
||||
});
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default ChatMessage;
|
43
src/modules/chat/service/session.ts
Normal file
43
src/modules/chat/service/session.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { BaseService, Service } from "/@/cool";
|
||||
import Mock from "mockjs";
|
||||
|
||||
@Service("chat/session")
|
||||
class ChatSession extends BaseService {
|
||||
page() {
|
||||
return new Promise((resolve) => {
|
||||
const data = Mock.mock({
|
||||
"list|20": [
|
||||
{
|
||||
id: "@id",
|
||||
nickName: "@name",
|
||||
createTime: "@datetime(HH:mm:ss)",
|
||||
text: "@cparagraph(5)",
|
||||
"num|0-99": 0,
|
||||
avatar() {
|
||||
return Mock.Random.image(
|
||||
"40x40",
|
||||
Mock.Random.color(),
|
||||
"#FFF",
|
||||
"png",
|
||||
this.nickName[0]
|
||||
);
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
list: data.list,
|
||||
pagination: {
|
||||
total: 20,
|
||||
page: 1,
|
||||
size: 20
|
||||
}
|
||||
});
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default ChatSession;
|
12
src/modules/chat/store/index.ts
Normal file
12
src/modules/chat/store/index.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { useMessageStore } from "./message";
|
||||
import { useSessionStore } from "./session";
|
||||
|
||||
export function useStore() {
|
||||
const session = useSessionStore();
|
||||
const message = useMessageStore();
|
||||
|
||||
return {
|
||||
session,
|
||||
message
|
||||
};
|
||||
}
|
48
src/modules/chat/store/message.ts
Normal file
48
src/modules/chat/store/message.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import { useCool } from "/@/cool";
|
||||
|
||||
export const useMessageStore = defineStore("chat-message", () => {
|
||||
const { service } = useCool();
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(false);
|
||||
|
||||
// 列表
|
||||
const list = ref<any[]>([]);
|
||||
|
||||
// 分页
|
||||
const pagination = ref({
|
||||
page: 1,
|
||||
total: 0,
|
||||
size: 20
|
||||
});
|
||||
|
||||
// 获取列表
|
||||
async function get(params?: any) {
|
||||
loading.value = true;
|
||||
|
||||
// 清空
|
||||
if (params?.page == 1) {
|
||||
list.value = [];
|
||||
}
|
||||
|
||||
// 发送请求
|
||||
await service.chat.message.page(params).then((res) => {
|
||||
list.value = res.list.map((e) => {
|
||||
e.content = JSON.parse(e.content);
|
||||
return e;
|
||||
});
|
||||
pagination.value = res.pagination;
|
||||
});
|
||||
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
return {
|
||||
loading,
|
||||
list,
|
||||
pagination,
|
||||
get
|
||||
};
|
||||
});
|
48
src/modules/chat/store/session.ts
Normal file
48
src/modules/chat/store/session.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import { useCool } from "/@/cool";
|
||||
|
||||
export const useSessionStore = defineStore("chat-session", () => {
|
||||
const { service } = useCool();
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(false);
|
||||
|
||||
// 列表
|
||||
const list = ref<any[]>([]);
|
||||
|
||||
// 选中
|
||||
const value = ref<any>();
|
||||
|
||||
// 获取列表
|
||||
async function get(params?: any) {
|
||||
loading.value = true;
|
||||
|
||||
// 发送请求
|
||||
await service.chat.session.page(params).then((res) => {
|
||||
// 默认加载第一个会话的消息
|
||||
if (!value.value) {
|
||||
set(res.list[0]);
|
||||
}
|
||||
|
||||
// 设置列表
|
||||
list.value = res.list;
|
||||
});
|
||||
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
// 设置值
|
||||
function set(data: any) {
|
||||
// 设置值
|
||||
value.value = data;
|
||||
}
|
||||
|
||||
return {
|
||||
loading,
|
||||
list,
|
||||
value,
|
||||
get,
|
||||
set
|
||||
};
|
||||
});
|
35
src/modules/chat/types/index.d.ts
vendored
Normal file
35
src/modules/chat/types/index.d.ts
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
import { Socket } from "socket.io-client";
|
||||
|
||||
export namespace Chat {
|
||||
enum ContentType {
|
||||
"text" = 0,
|
||||
"image" = 1,
|
||||
"video" = 2
|
||||
}
|
||||
|
||||
interface Message {
|
||||
fromId?: string;
|
||||
toId?: string;
|
||||
content: {
|
||||
text?: string;
|
||||
imageUrl?: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
contentType: ContentType;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
interface Session {
|
||||
id: string;
|
||||
avatar: string;
|
||||
nickName: string;
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
interface Provide {
|
||||
socket?: Socket;
|
||||
send(data: Message, isAppend?: boolean): void;
|
||||
append(data: Message): void;
|
||||
scrollToBottom(): void;
|
||||
}
|
||||
}
|
@ -1,6 +1,14 @@
|
||||
<template>
|
||||
<div class="cl-upload__wrap">
|
||||
<div class="cl-upload" :class="[`cl-upload--${type}`]">
|
||||
<div
|
||||
class="cl-upload"
|
||||
:class="[
|
||||
`cl-upload--${type}`,
|
||||
{
|
||||
'is-slot': $slots.default
|
||||
}
|
||||
]"
|
||||
>
|
||||
<!-- 列表 -->
|
||||
<draggable
|
||||
v-model="list"
|
||||
@ -610,5 +618,15 @@ defineExpose({
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
&.is-slot {
|
||||
.cl-upload__list {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.un-drag {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -26,7 +26,7 @@
|
||||
<div class="cl-upload-space__header scroller1">
|
||||
<el-button @click="refresh({ page: 1 })">刷新</el-button>
|
||||
|
||||
<div :style="{ marginLeft: '10px' }">
|
||||
<div :style="{ margin: '0px 10px' }">
|
||||
<cl-upload
|
||||
ref="Upload"
|
||||
type="file"
|
||||
|
@ -17,6 +17,7 @@
|
||||
<li
|
||||
v-for="(item, index) in flist"
|
||||
:key="index"
|
||||
class="item"
|
||||
:class="{
|
||||
'is-active': item.id == space.category.id
|
||||
}"
|
||||
@ -141,6 +142,9 @@ function onContextMenu(e: any, { id, name }: any) {
|
||||
}
|
||||
|
||||
ContextMenu.open(e, {
|
||||
hover: {
|
||||
target: "item"
|
||||
},
|
||||
list: [
|
||||
{
|
||||
label: "刷新",
|
||||
@ -238,7 +242,7 @@ onMounted(() => {
|
||||
ul {
|
||||
height: 100%;
|
||||
|
||||
li {
|
||||
.item {
|
||||
list-style: none;
|
||||
font-size: 14px;
|
||||
height: 40px;
|
||||
@ -251,7 +255,7 @@ onMounted(() => {
|
||||
color: var(--color-primary);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:not(.cl-context-menu__target):hover {
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
}
|
||||
|
130
yarn.lock
130
yarn.lock
@ -984,10 +984,10 @@
|
||||
"@babel/helper-validator-identifier" "^7.16.7"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@cool-vue/crud@^5.0.10":
|
||||
version "5.0.10"
|
||||
resolved "https://registry.npmjs.org/@cool-vue/crud/-/crud-5.0.10.tgz#c2d70504fccdf89c907e1d32e62a93dd777fba9c"
|
||||
integrity sha512-a3jZPS+Y/+7IJTA3iYjD7PK83rwtIDrnE0tcf5LfenZ7JnnlXs+QFMRybGypJfoeswsG97JmWFeSY6o/JyALDw==
|
||||
"@cool-vue/crud@^5.0.13":
|
||||
version "5.0.13"
|
||||
resolved "https://registry.npmjs.org/@cool-vue/crud/-/crud-5.0.13.tgz#6fe3dc2b0660ea5ccfa8a7420af97972de3887ec"
|
||||
integrity sha512-yzzYWAlUKnOiJKX7+OQZgD39xXCyQCcuOWdp8foMWIWdUaWyHTxK3aFDd+V4EuK+T8lWbG+HggE784fKTxZJRQ==
|
||||
dependencies:
|
||||
array.prototype.flat "^1.2.4"
|
||||
core-js "^3.21.1"
|
||||
@ -1006,6 +1006,11 @@
|
||||
resolved "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-1.1.4.tgz#5d2788ea356f1458068e6d400e724ca5f3d29aca"
|
||||
integrity sha512-Iz/nHqdp1sFPmdzRwHkEQQA3lKvoObk8azgABZ81QUOpW9s/lUyQVUSh0tNtEPZXQlKwlSh7SPgoVxzrE0uuVQ==
|
||||
|
||||
"@element-plus/icons-vue@^2.0.5":
|
||||
version "2.0.5"
|
||||
resolved "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.0.5.tgz#8eb4143a7b5e4d8468d2e72af99eefee446f5ea0"
|
||||
integrity sha512-jvNWyKcdvPvMDLTWjghrPY+bYHKqh7hbAFIPe+HWR073zilzt33csREzmKx3VwhdlJUW5u0nCqN+0rwI8jlH+w==
|
||||
|
||||
"@eslint/eslintrc@^0.4.3":
|
||||
version "0.4.3"
|
||||
resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
|
||||
@ -1026,6 +1031,11 @@
|
||||
resolved "https://registry.npmjs.org/@floating-ui/core/-/core-0.6.2.tgz#f2813f0e5f3d5ed7af5029e1a082203dadf02b7d"
|
||||
integrity sha512-jktYRmZwmau63adUG3GKOAVCofBXkk55S/zQ94XOorAHhwqFIOFAy1rSp2N0Wp6/tGbe9V3u/ExlGZypyY17rg==
|
||||
|
||||
"@floating-ui/core@^0.7.3":
|
||||
version "0.7.3"
|
||||
resolved "https://registry.npmjs.org/@floating-ui/core/-/core-0.7.3.tgz#d274116678ffae87f6b60e90f88cc4083eefab86"
|
||||
integrity sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg==
|
||||
|
||||
"@floating-ui/dom@^0.4.5":
|
||||
version "0.4.5"
|
||||
resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-0.4.5.tgz#2e88d16646119cc67d44683f75ee99840475bbfa"
|
||||
@ -1033,6 +1043,13 @@
|
||||
dependencies:
|
||||
"@floating-ui/core" "^0.6.2"
|
||||
|
||||
"@floating-ui/dom@^0.5.2":
|
||||
version "0.5.3"
|
||||
resolved "https://registry.npmjs.org/@floating-ui/dom/-/dom-0.5.3.tgz#ade192cf9a911fc3e95fb614fe281658b654043c"
|
||||
integrity sha512-vpjWB1uC7rajvgA58uzlJZgtWqrdDQLw+XVA3w63ZTmsWwRmVd0Gl5Dy9VMAViI9cP7hBWaJt23Jy3AVgVYnoQ==
|
||||
dependencies:
|
||||
"@floating-ui/core" "^0.7.3"
|
||||
|
||||
"@hapi/hoek@^9.0.0":
|
||||
version "9.2.1"
|
||||
resolved "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.1.tgz#9551142a1980503752536b5050fd99f4a7f13b17"
|
||||
@ -1127,7 +1144,7 @@
|
||||
resolved "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1"
|
||||
integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==
|
||||
|
||||
"@popperjs/core@npm:@sxzz/popperjs-es@^2.11.6":
|
||||
"@popperjs/core@npm:@sxzz/popperjs-es@^2.11.6", "@popperjs/core@npm:@sxzz/popperjs-es@^2.11.7":
|
||||
version "2.11.7"
|
||||
resolved "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz#a7f69e3665d3da9b115f9e71671dae1b97e13671"
|
||||
integrity sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==
|
||||
@ -1178,6 +1195,11 @@
|
||||
resolved "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
|
||||
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
|
||||
|
||||
"@socket.io/component-emitter@~3.1.0":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553"
|
||||
integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==
|
||||
|
||||
"@trysound/sax@0.2.0":
|
||||
version "0.2.0"
|
||||
resolved "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad"
|
||||
@ -1807,6 +1829,15 @@
|
||||
"@vueuse/shared" "8.4.2"
|
||||
vue-demi "*"
|
||||
|
||||
"@vueuse/core@^8.6.0":
|
||||
version "8.6.0"
|
||||
resolved "https://registry.npmjs.org/@vueuse/core/-/core-8.6.0.tgz#a8f80363cc63d17382423f16beae57696f376e67"
|
||||
integrity sha512-VirzExCm/N+QdrEWT7J4uSrvJ5hquKIAU9alQ37kUvIJk9XxCLxmfRnmekYc1kz2+6BnoyuKYXVmrMV351CB4w==
|
||||
dependencies:
|
||||
"@vueuse/metadata" "8.6.0"
|
||||
"@vueuse/shared" "8.6.0"
|
||||
vue-demi "*"
|
||||
|
||||
"@vueuse/metadata@8.2.5":
|
||||
version "8.2.5"
|
||||
resolved "https://registry.npmjs.org/@vueuse/metadata/-/metadata-8.2.5.tgz#51c7d95e04284ea378a5242a2e88b77494e2c117"
|
||||
@ -1817,6 +1848,11 @@
|
||||
resolved "https://registry.npmjs.org/@vueuse/metadata/-/metadata-8.4.2.tgz#b33e6b7bd5ca69e3f24ea41b149267118bcd566f"
|
||||
integrity sha512-2BIj++7P0/I5dfMsEe8q7Kw0HqVAjVcyNOd9+G22/ILUC9TVLTeYOuJ1kwa1Gpr+0LWKHc6GqHiLWNL33+exoQ==
|
||||
|
||||
"@vueuse/metadata@8.6.0":
|
||||
version "8.6.0"
|
||||
resolved "https://registry.npmjs.org/@vueuse/metadata/-/metadata-8.6.0.tgz#34771443a72ee891ae001a70aa05dd9a1d799372"
|
||||
integrity sha512-F+CKPvaExsm7QgRr8y+ZNJFwXasn89rs5wth/HeX9lJ1q8XEt+HJ16Q5Sxh4rfG5YSKXrStveVge8TKvPjMjFA==
|
||||
|
||||
"@vueuse/shared@8.2.5":
|
||||
version "8.2.5"
|
||||
resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-8.2.5.tgz#1ae200a240c4b8d42d41723b64d8f917aa57ff16"
|
||||
@ -1831,6 +1867,13 @@
|
||||
dependencies:
|
||||
vue-demi "*"
|
||||
|
||||
"@vueuse/shared@8.6.0":
|
||||
version "8.6.0"
|
||||
resolved "https://registry.npmjs.org/@vueuse/shared/-/shared-8.6.0.tgz#63dad9fc4b73a7fccbe5d6b97adeacf73d4fec41"
|
||||
integrity sha512-Y/IVywZo7IfEoSSEtCYpkVEmPV7pU35mEIxV7PbD/D3ly18B3mEsBaPbtDkNM/QP3zAZ5mn4nEkOfddX4uwuIA==
|
||||
dependencies:
|
||||
vue-demi "*"
|
||||
|
||||
"@webassemblyjs/ast@1.11.1":
|
||||
version "1.11.1"
|
||||
resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7"
|
||||
@ -2124,6 +2167,11 @@ async-validator@^4.0.7:
|
||||
resolved "https://registry.npmjs.org/async-validator/-/async-validator-4.0.7.tgz#034a0fd2103a6b2ebf010da75183bec299247afe"
|
||||
integrity sha512-Pj2IR7u8hmUEDOwB++su6baaRi+QvsgajuFB9j95foM1N2gy5HM4z60hfusIO0fBPG5uLAEl6yCJr1jNSVugEQ==
|
||||
|
||||
async-validator@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.npmjs.org/async-validator/-/async-validator-4.1.1.tgz#3cd1437faa2de64743f7d56649dd904c946a18fe"
|
||||
integrity sha512-p4DO/JXwjs8klJyJL8Q2oM4ks5fUTze/h5k10oPPKMiLe1fj3G1QMzPHNmN1Py4ycOk7WlO2DcGXv1qiESJCZA==
|
||||
|
||||
asynckit@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
@ -2743,6 +2791,11 @@ dayjs@^1.11.1:
|
||||
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.2.tgz#fa0f5223ef0d6724b3d8327134890cfe3d72fbe5"
|
||||
integrity sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==
|
||||
|
||||
dayjs@^1.11.3:
|
||||
version "1.11.3"
|
||||
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.3.tgz#4754eb694a624057b9ad2224b67b15d552589258"
|
||||
integrity sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==
|
||||
|
||||
debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
@ -2750,7 +2803,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4:
|
||||
debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||
@ -2984,6 +3037,27 @@ element-plus@^2.2.0:
|
||||
memoize-one "^6.0.0"
|
||||
normalize-wheel-es "^1.1.2"
|
||||
|
||||
element-plus@^2.2.5:
|
||||
version "2.2.5"
|
||||
resolved "https://registry.npmjs.org/element-plus/-/element-plus-2.2.5.tgz#2bb889660c9bcb9bb71e18619915b35e0f48d569"
|
||||
integrity sha512-Kl0yn/PQca5YQo3M3NPBP4Xl71NQuMtDx5zNXZGVyl5FjdMujXiFB9SXKYGDUCgFU3d/Rl14vB4Fpmcl2Iz+Hw==
|
||||
dependencies:
|
||||
"@ctrl/tinycolor" "^3.4.1"
|
||||
"@element-plus/icons-vue" "^2.0.5"
|
||||
"@floating-ui/dom" "^0.5.2"
|
||||
"@popperjs/core" "npm:@sxzz/popperjs-es@^2.11.7"
|
||||
"@types/lodash" "^4.14.182"
|
||||
"@types/lodash-es" "^4.17.6"
|
||||
"@vueuse/core" "^8.6.0"
|
||||
async-validator "^4.1.1"
|
||||
dayjs "^1.11.3"
|
||||
escape-html "^1.0.3"
|
||||
lodash "^4.17.21"
|
||||
lodash-es "^4.17.21"
|
||||
lodash-unified "^1.0.2"
|
||||
memoize-one "^6.0.0"
|
||||
normalize-wheel-es "^1.1.2"
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
@ -3006,6 +3080,22 @@ end-of-stream@^1.1.0:
|
||||
dependencies:
|
||||
once "^1.4.0"
|
||||
|
||||
engine.io-client@~6.2.1:
|
||||
version "6.2.2"
|
||||
resolved "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.2.tgz#c6c5243167f5943dcd9c4abee1bfc634aa2cbdd0"
|
||||
integrity sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==
|
||||
dependencies:
|
||||
"@socket.io/component-emitter" "~3.1.0"
|
||||
debug "~4.3.1"
|
||||
engine.io-parser "~5.0.3"
|
||||
ws "~8.2.3"
|
||||
xmlhttprequest-ssl "~2.0.0"
|
||||
|
||||
engine.io-parser@~5.0.3:
|
||||
version "5.0.4"
|
||||
resolved "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.4.tgz#0b13f704fa9271b3ec4f33112410d8f3f41d0fc0"
|
||||
integrity sha512-+nVFp+5z1E3HcToEnO7ZIj3g+3k9389DvWtvJZz0T6/eOCPIyyxehFcedoYrZQrp0LgQbD9pPXhpMBKMd5QURg==
|
||||
|
||||
enhanced-resolve@^5.0.0, enhanced-resolve@^5.9.2:
|
||||
version "5.9.2"
|
||||
resolved "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.9.2.tgz#0224dcd6a43389ebfb2d55efee517e5466772dd9"
|
||||
@ -5746,6 +5836,24 @@ snapdragon@^0.8.1:
|
||||
source-map-resolve "^0.5.0"
|
||||
use "^3.1.0"
|
||||
|
||||
socket.io-client@^4.5.1:
|
||||
version "4.5.1"
|
||||
resolved "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.1.tgz#cab8da71976a300d3090414e28c2203a47884d84"
|
||||
integrity sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==
|
||||
dependencies:
|
||||
"@socket.io/component-emitter" "~3.1.0"
|
||||
debug "~4.3.2"
|
||||
engine.io-client "~6.2.1"
|
||||
socket.io-parser "~4.2.0"
|
||||
|
||||
socket.io-parser@~4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.0.tgz#3f01e5bc525d94aa52a97ed5cbc12e229bbc4d6b"
|
||||
integrity sha512-tLfmEwcEwnlQTxFB7jibL/q2+q8dlVQzj4JdRLJ/W/G1+Fu9VSxCx1Lo+n1HvXxKnM//dUuD0xgiA7tQf57Vng==
|
||||
dependencies:
|
||||
"@socket.io/component-emitter" "~3.1.0"
|
||||
debug "~4.3.1"
|
||||
|
||||
sortablejs@1.14.0:
|
||||
version "1.14.0"
|
||||
resolved "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz#6d2e17ccbdb25f464734df621d4f35d4ab35b3d8"
|
||||
@ -6616,6 +6724,11 @@ wrappy@1:
|
||||
resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
|
||||
|
||||
ws@~8.2.3:
|
||||
version "8.2.3"
|
||||
resolved "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba"
|
||||
integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==
|
||||
|
||||
xlsx@^0.16.9:
|
||||
version "0.16.9"
|
||||
resolved "https://registry.npmjs.org/xlsx/-/xlsx-0.16.9.tgz#dacd5bb46bda6dd3743940c9c3dc1e2171826256"
|
||||
@ -6632,6 +6745,11 @@ xlsx@^0.16.9:
|
||||
wmf "~1.0.1"
|
||||
word "~0.3.0"
|
||||
|
||||
xmlhttprequest-ssl@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67"
|
||||
integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==
|
||||
|
||||
yallist@^2.1.2:
|
||||
version "2.1.2"
|
||||
resolved "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
|
||||
|
Loading…
Reference in New Issue
Block a user