mirror of
https://github.com/cool-team-official/cool-admin-vue.git
synced 2024-11-01 14:10:27 +08:00
模块 chat 添加图片,视频上传
This commit is contained in:
parent
9edba6ebed
commit
58907611f6
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cool-admin-vue",
|
"name": "cool-admin-vue",
|
||||||
"version": "3.1.3",
|
"version": "3.1.4",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-cli-service build",
|
||||||
|
@ -13,7 +13,7 @@ export const host = "https://show.cool-admin.com";
|
|||||||
// Socket
|
// Socket
|
||||||
export const socketUrl = (isDev ? `${host}` : "") + "/socket";
|
export const socketUrl = (isDev ? `${host}` : "") + "/socket";
|
||||||
|
|
||||||
// 请求地址
|
// 请求地址,本地会使用代理请求
|
||||||
export const baseUrl = (function() {
|
export const baseUrl = (function() {
|
||||||
let proxy = getUrlParam("proxy");
|
let proxy = getUrlParam("proxy");
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ export default {
|
|||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
modes: ["text", "image", "emoji", "voice", "video"], // 消息类型
|
||||||
visible: false,
|
visible: false,
|
||||||
socket: null
|
socket: null
|
||||||
};
|
};
|
||||||
@ -95,7 +96,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
// this.socket = io(`${socketUrl}/?isAdmin=true&token=${token}`);
|
// this.socket = io(`${socketUrl}?isAdmin=true&token=${token}`);
|
||||||
// this.socket.on("connect", () => {
|
// this.socket.on("connect", () => {
|
||||||
// console.log("socket connect");
|
// console.log("socket connect");
|
||||||
// });
|
// });
|
||||||
@ -149,7 +150,7 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 追加消息
|
// 追加消息
|
||||||
eventBus.$emit("message-append", {
|
this.$store.commit("APPEND_MESSAGE_LIST", {
|
||||||
contentType,
|
contentType,
|
||||||
content: JSON.parse(content),
|
content: JSON.parse(content),
|
||||||
type: 1
|
type: 1
|
||||||
@ -177,7 +178,7 @@ export default {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// 刷新会话列表
|
// 刷新会话列表
|
||||||
eventBus.$emit("session-refresh");
|
eventBus.$emit("session.refresh");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("消息格式异常", e);
|
console.error("消息格式异常", e);
|
||||||
|
@ -8,13 +8,27 @@
|
|||||||
<emoji @select="onEmojiSelect" />
|
<emoji @select="onEmojiSelect" />
|
||||||
</li>
|
</li>
|
||||||
<!-- 图片上传 -->
|
<!-- 图片上传 -->
|
||||||
<li hidden>
|
<li>
|
||||||
<cl-upload accept="image/*" list-type :on-success="onImageSelect">
|
<cl-upload
|
||||||
|
accept="image/*"
|
||||||
|
list-type
|
||||||
|
:before-upload="
|
||||||
|
f => {
|
||||||
|
onBeforeUpload(f, 'image');
|
||||||
|
}
|
||||||
|
"
|
||||||
|
:on-progress="onUploadProgress"
|
||||||
|
:on-success="
|
||||||
|
(r, f) => {
|
||||||
|
onUploadSuccess(r, f, 'image');
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
<img src="../static/images/image.png" alt="" />
|
<img src="../static/images/image.png" alt="" />
|
||||||
</cl-upload>
|
</cl-upload>
|
||||||
</li>
|
</li>
|
||||||
<!-- 视频上传 -->
|
<!-- 视频上传 -->
|
||||||
<li hidden>
|
<li>
|
||||||
<cl-upload
|
<cl-upload
|
||||||
accept="video/*"
|
accept="video/*"
|
||||||
list-type
|
list-type
|
||||||
@ -57,7 +71,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import { mapGetters } from "vuex";
|
import { mapGetters } from "vuex";
|
||||||
import Emoji from "./emoji";
|
import Emoji from "./emoji";
|
||||||
import eventBus from "../utils/event-bus";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -76,29 +89,48 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(["session"])
|
...mapGetters(["session", "messageList"])
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
// 上传前
|
// 上传前,获取图片预览地址
|
||||||
onBeforeUpload(file, key) {
|
onBeforeUpload(file, key) {
|
||||||
|
const next = (options = {}) => {
|
||||||
const data = {
|
const data = {
|
||||||
content: {
|
content: {
|
||||||
[`${key}Url`]: ""
|
[`${key}Url`]: ""
|
||||||
},
|
},
|
||||||
type: 0,
|
type: 0,
|
||||||
contentType: MODES.indexOf(key),
|
|
||||||
uid: file.uid,
|
uid: file.uid,
|
||||||
loading: true,
|
loading: true,
|
||||||
progress: "0%"
|
progress: "0%",
|
||||||
|
contentType: this.chat.modes.indexOf(key),
|
||||||
|
...options
|
||||||
};
|
};
|
||||||
|
|
||||||
this.append(data);
|
this.append(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (key == "image") {
|
||||||
|
const fileReader = new FileReader();
|
||||||
|
|
||||||
|
fileReader.onload = e => {
|
||||||
|
next({
|
||||||
|
content: {
|
||||||
|
imageUrl: e.target.result
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
fileReader.readAsDataURL(file);
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 上传中
|
// 上传中
|
||||||
onUploadProgress(e, file) {
|
onUploadProgress(e, file) {
|
||||||
const item = this.message.list.find(e => e.uid == file.uid);
|
const item = this.messageList.find(e => e.uid == file.uid);
|
||||||
|
|
||||||
if (item) {
|
if (item) {
|
||||||
item.progress = e.percent + "%";
|
item.progress = e.percent + "%";
|
||||||
@ -107,7 +139,7 @@ export default {
|
|||||||
|
|
||||||
// 上传成功
|
// 上传成功
|
||||||
onUploadSuccess(res, file, key) {
|
onUploadSuccess(res, file, key) {
|
||||||
const item = this.message.list.find(e => e.uid == file.uid);
|
const item = this.messageList.find(e => e.uid == file.uid);
|
||||||
|
|
||||||
if (item) {
|
if (item) {
|
||||||
item.loading = false;
|
item.loading = false;
|
||||||
@ -204,7 +236,7 @@ export default {
|
|||||||
|
|
||||||
// 追加消息
|
// 追加消息
|
||||||
append(data) {
|
append(data) {
|
||||||
eventBus.$emit("message-append", data);
|
this.$store.commit("APPEND_MESSAGE_LIST", data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="cl-chat-message" v-loading="loading" element-loading-text="消息加载中">
|
<div class="cl-chat-message" v-loading="!visible && loading" element-loading-text="消息加载中">
|
||||||
<div
|
<div
|
||||||
class="cl-chat-message__scroller scroller1"
|
class="cl-chat-message__scroller scroller1"
|
||||||
ref="scroller"
|
ref="scroller"
|
||||||
@ -8,7 +8,7 @@
|
|||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<!-- 加载更多 -->
|
<!-- 加载更多 -->
|
||||||
<div class="cl-chat-message__more" v-if="list.length > 0">
|
<div class="cl-chat-message__more" v-show="list.length > 0">
|
||||||
<el-button round size="mini" :loading="loading" @click="onLoadmore"
|
<el-button round size="mini" :loading="loading" @click="onLoadmore"
|
||||||
>加载更多</el-button
|
>加载更多</el-button
|
||||||
>
|
>
|
||||||
@ -18,17 +18,19 @@
|
|||||||
<div class="cl-chat-message__list">
|
<div class="cl-chat-message__list">
|
||||||
<div
|
<div
|
||||||
class="cl-chat-message__item"
|
class="cl-chat-message__item"
|
||||||
v-for="item in messageList"
|
v-for="item in list"
|
||||||
:key="item.id || item.uid"
|
:key="item.id || item.uid"
|
||||||
:class="[item.type == 0 ? `is-right` : `is-left`, `is-${item.mode}`]"
|
:class="[item.type == 0 ? `is-right` : `is-left`, `is-${item.mode}`]"
|
||||||
>
|
>
|
||||||
|
<!-- 日期 -->
|
||||||
<div class="date" v-if="item._date">
|
<div class="date" v-if="item._date">
|
||||||
<span>{{ item._date }}</span>
|
<span>{{ item._date }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 内容 -->
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<!-- 头像 -->
|
<!-- 头像 -->
|
||||||
<div class="avatar" @tap="toUserDetail(item)">
|
<div class="avatar">
|
||||||
<img :src="item.avatarUrl" />
|
<img :src="item.avatarUrl" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -53,7 +55,17 @@
|
|||||||
:key="item.uid"
|
:key="item.uid"
|
||||||
:src="item.content.imageUrl"
|
:src="item.content.imageUrl"
|
||||||
:preview-src-list="[item.content.imageUrl]"
|
:preview-src-list="[item.content.imageUrl]"
|
||||||
></el-image>
|
:z-index="3000"
|
||||||
|
:style="item.style"
|
||||||
|
>
|
||||||
|
<template #placeholder>
|
||||||
|
<img
|
||||||
|
:src="item.content.imageUrl"
|
||||||
|
:style="item.style"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-image>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 表情 -->
|
<!-- 表情 -->
|
||||||
@ -90,7 +102,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- voice -->
|
<!-- 音频 -->
|
||||||
<div class="voice">
|
<div class="voice">
|
||||||
<audio style="display: none" ref="voice" :src="voice.url" controls></audio>
|
<audio style="display: none" ref="voice" :src="voice.url" controls></audio>
|
||||||
</div>
|
</div>
|
||||||
@ -106,19 +118,17 @@ import { isString } from "cl-admin/utils";
|
|||||||
import eventBus from "../utils/event-bus";
|
import eventBus from "../utils/event-bus";
|
||||||
import IconVoice from "./icon-voice";
|
import IconVoice from "./icon-voice";
|
||||||
|
|
||||||
// 消息类型
|
|
||||||
const ModeList = ["text", "image", "emoji", "voice", "video"];
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
IconVoice
|
IconVoice
|
||||||
},
|
},
|
||||||
|
|
||||||
|
inject: ["chat"],
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading: false,
|
loading: false,
|
||||||
visible: false,
|
visible: false,
|
||||||
list: [],
|
|
||||||
pagination: {
|
pagination: {
|
||||||
page: 1,
|
page: 1,
|
||||||
size: 20,
|
size: 20,
|
||||||
@ -140,12 +150,12 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(["userInfo", "session"]),
|
...mapGetters(["userInfo", "session", "messageList"]),
|
||||||
|
|
||||||
messageList() {
|
list() {
|
||||||
let date = "";
|
let date = "";
|
||||||
|
|
||||||
return this.list.map(e => {
|
return this.messageList.map(e => {
|
||||||
// 时间间隔
|
// 时间间隔
|
||||||
e._date = date
|
e._date = date
|
||||||
? dayjs(e.createTime).isBefore(dayjs(date).add(1, "minute"))
|
? dayjs(e.createTime).isBefore(dayjs(date).add(1, "minute"))
|
||||||
@ -178,15 +188,18 @@ export default {
|
|||||||
...e,
|
...e,
|
||||||
avatarUrl,
|
avatarUrl,
|
||||||
nickName,
|
nickName,
|
||||||
mode: ModeList[e.contentType]
|
mode: this.chat.modes[e.contentType]
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
created() {
|
created() {
|
||||||
eventBus.$on("message-refresh", this.refresh);
|
// 监听列表刷新
|
||||||
eventBus.$on("message-append", this.append);
|
eventBus.$on("message.refresh", this.refresh);
|
||||||
|
|
||||||
|
// 滚动到底部
|
||||||
|
eventBus.$on("message.scrollToBottom", this.scrollToBottom);
|
||||||
|
|
||||||
if (this.session) {
|
if (this.session) {
|
||||||
this.refresh();
|
this.refresh();
|
||||||
@ -196,7 +209,7 @@ export default {
|
|||||||
destroyed() {
|
destroyed() {
|
||||||
clearTimeout(this.voice.timer);
|
clearTimeout(this.voice.timer);
|
||||||
|
|
||||||
this.list.map(e => {
|
this.messageList.map(e => {
|
||||||
e.isPlay = false;
|
e.isPlay = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -206,7 +219,7 @@ export default {
|
|||||||
onTap(item) {
|
onTap(item) {
|
||||||
// 播放语音
|
// 播放语音
|
||||||
if (item.mode == "voice") {
|
if (item.mode == "voice") {
|
||||||
this.list.map(e => {
|
this.messageList.map(e => {
|
||||||
this.$set(e, "isPlay", e.id == item.id ? e.isPlay : false);
|
this.$set(e, "isPlay", e.id == item.id ? e.isPlay : false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -245,11 +258,13 @@ export default {
|
|||||||
sort: "desc"
|
sort: "desc"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 加载动画
|
||||||
|
this.loading = true;
|
||||||
|
|
||||||
// 首页处理
|
// 首页处理
|
||||||
if (data.page === 1) {
|
if (data.page === 1) {
|
||||||
this.loading = true;
|
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
this.list = [];
|
this.$store.commit("CLEAR_MESSAGE_LIST");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 完成
|
// 完成
|
||||||
@ -269,7 +284,7 @@ export default {
|
|||||||
// 分页信息
|
// 分页信息
|
||||||
this.pagination = res.pagination;
|
this.pagination = res.pagination;
|
||||||
// 追加数据
|
// 追加数据
|
||||||
this.prepend.apply(this, res.list);
|
this.$store.commit("PREPEND_MESSAGE_LIST", res.list);
|
||||||
|
|
||||||
if (data.page === 1) {
|
if (data.page === 1) {
|
||||||
this.scrollToBottom();
|
this.scrollToBottom();
|
||||||
@ -301,17 +316,6 @@ export default {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
|
||||||
|
|
||||||
// 追加数据到开头
|
|
||||||
prepend(...data) {
|
|
||||||
this.list.unshift(...data.reverse());
|
|
||||||
},
|
|
||||||
|
|
||||||
// 追加数据到结尾
|
|
||||||
append(...data) {
|
|
||||||
this.list.push(...data);
|
|
||||||
this.scrollToBottom();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -349,7 +353,7 @@ export default {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 2px 5px;
|
padding: 3px 5px 2px 5px;
|
||||||
letter-spacing: 1px;
|
letter-spacing: 1px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -474,8 +478,10 @@ export default {
|
|||||||
&.is-video {
|
&.is-video {
|
||||||
.item {
|
.item {
|
||||||
video {
|
video {
|
||||||
|
display: block;
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ export default {
|
|||||||
|
|
||||||
created() {
|
created() {
|
||||||
// 监听列表刷新
|
// 监听列表刷新
|
||||||
eventBus.$on("session-refresh", this.refresh);
|
eventBus.$on("session.refresh", this.refresh);
|
||||||
|
|
||||||
// PC 端下首次请求读取第一个消息
|
// PC 端下首次请求读取第一个消息
|
||||||
this.refresh().then(res => {
|
this.refresh().then(res => {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import session from "./session";
|
import session from "./session";
|
||||||
|
import message from "./message";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
session
|
session,
|
||||||
|
message
|
||||||
};
|
};
|
||||||
|
67
src/cool/modules/chat/store/message.js
Normal file
67
src/cool/modules/chat/store/message.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { isArray } from "cl-admin/utils";
|
||||||
|
import eventBus from "../utils/event-bus";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
state: {
|
||||||
|
list: []
|
||||||
|
},
|
||||||
|
|
||||||
|
getters: {
|
||||||
|
messageList: state => state.list
|
||||||
|
},
|
||||||
|
|
||||||
|
mutations: {
|
||||||
|
// 设置列表
|
||||||
|
SET_MESSAGE_LIST(state, data) {
|
||||||
|
state.list = data;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 追加数据
|
||||||
|
APPEND_MESSAGE_LIST(state, data) {
|
||||||
|
const next = options => {
|
||||||
|
state.list.push({
|
||||||
|
...data,
|
||||||
|
...options
|
||||||
|
});
|
||||||
|
eventBus.$emit("message.scrollToBottom");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 图片预览、大小处理
|
||||||
|
if (data.contentType === 1) {
|
||||||
|
const image = new Image();
|
||||||
|
|
||||||
|
image.onload = () => {
|
||||||
|
let height = 0;
|
||||||
|
let width = 0;
|
||||||
|
|
||||||
|
if (image.width > 200) {
|
||||||
|
width = 200;
|
||||||
|
height = (image.height * 200) / image.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
next({
|
||||||
|
style: {
|
||||||
|
height: height + "px",
|
||||||
|
width: width + "px"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
image.src = data.content.imageUrl;
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 追加数据到头部
|
||||||
|
PREPEND_MESSAGE_LIST(state, data) {
|
||||||
|
const list = isArray(data) ? data : [data];
|
||||||
|
state.list.unshift(...list.reverse());
|
||||||
|
},
|
||||||
|
|
||||||
|
// 清空列表
|
||||||
|
CLEAR_MESSAGE_LIST(state) {
|
||||||
|
state.list = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -22,7 +22,7 @@ export default {
|
|||||||
SET_SESSION(state, data) {
|
SET_SESSION(state, data) {
|
||||||
state.current = data;
|
state.current = data;
|
||||||
state.current.serviceUnreadCount = 0;
|
state.current.serviceUnreadCount = 0;
|
||||||
eventBus.$emit("message-refresh", { page: 1 });
|
eventBus.$emit("message.refresh", { page: 1 });
|
||||||
},
|
},
|
||||||
|
|
||||||
// 清空会话信息
|
// 清空会话信息
|
||||||
|
6
src/cool/modules/upload/filters/index.js
Normal file
6
src/cool/modules/upload/filters/index.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { video_poster, image_resize } from "./oss";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
video_poster,
|
||||||
|
image_resize
|
||||||
|
};
|
48
src/cool/modules/upload/filters/oss.js
Normal file
48
src/cool/modules/upload/filters/oss.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { isArray, isObject } from "cl-admin/utils";
|
||||||
|
|
||||||
|
function parse(rules, { url, size }) {
|
||||||
|
if (!url) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.indexOf("http") !== 0) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
let h = 0;
|
||||||
|
let w = 0;
|
||||||
|
|
||||||
|
if (isArray(size)) {
|
||||||
|
h = size[0];
|
||||||
|
w = size[1];
|
||||||
|
} else if (isObject(size)) {
|
||||||
|
h = size.h;
|
||||||
|
w = size.w;
|
||||||
|
|
||||||
|
if (size.m) {
|
||||||
|
rules.push(size.m);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
h = w = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
url += url.includes("?") ? "&" : "?";
|
||||||
|
|
||||||
|
if (h) {
|
||||||
|
rules.push(`h_${h}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w) {
|
||||||
|
rules.push(`w_${w}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${url}${rules.join(",")}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function video_poster(url, size) {
|
||||||
|
return parse(["x-oss-process=video/snapshot,t_1000,f_jpg"], { url, size });
|
||||||
|
}
|
||||||
|
|
||||||
|
export function image_resize(url, size) {
|
||||||
|
return parse(["x-oss-process=image/resize"], { url, size });
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import service from "./service";
|
import service from "./service";
|
||||||
import components from "./components";
|
import components from "./components";
|
||||||
|
import filters from "./filters";
|
||||||
|
|
||||||
export default { components, service };
|
export default { components, service, filters };
|
||||||
|
Loading…
Reference in New Issue
Block a user