更新 聊天模块,添加响应式处理

This commit is contained in:
icssoa 2021-03-18 17:04:53 +08:00
parent 38d07a3361
commit f032afbb3c
25 changed files with 328 additions and 258 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "cool-admin-vue", "name": "cool-admin-vue",
"version": "3.1.0", "version": "3.1.1",
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "serve": "vue-cli-service serve",
"build": "vue-cli-service build", "build": "vue-cli-service build",
@ -10,8 +10,8 @@
}, },
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",
"cl-admin": "^1.4.0", "cl-admin": "^1.5.0",
"cl-admin-crud": "^1.6.2", "cl-admin-crud": "^1.6.4",
"cl-admin-theme": "^0.0.4", "cl-admin-theme": "^0.0.4",
"clipboard": "^2.0.7", "clipboard": "^2.0.7",
"codemirror": "^5.59.4", "codemirror": "^5.59.4",
@ -24,7 +24,7 @@
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"qs": "^6.9.1", "qs": "^6.9.1",
"quill": "^1.3.7", "quill": "^1.3.7",
"socket.io-client": "^3.1.2", "socket.io-client": "2.3.1",
"store": "^2.0.12", "store": "^2.0.12",
"uuid": "^8.3.2", "uuid": "^8.3.2",
"vue": "^2.6.11", "vue": "^2.6.11",

View File

@ -1,6 +1,7 @@
* { * {
padding: 0; padding: 0;
margin: 0; margin: 0;
outline: none;
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
"微软雅黑", Arial, sans-serif; "微软雅黑", Arial, sans-serif;
} }

View File

@ -3,7 +3,9 @@ import Theme from "cl-admin-theme";
export default { export default {
modules: [ modules: [
// 基础模块
"base", "base",
// 文件上传
{ {
name: "upload", name: "upload",
options: { options: {
@ -25,11 +27,17 @@ export default {
} }
} }
}, },
// 客服聊天
"chat", "chat",
// 任务管理
"task", "task",
// 复制指令
"copy", "copy",
// 省市区选择
"distpicker", "distpicker",
// 示例页
"demo", "demo",
// 主题切换
{ {
name: "theme", name: "theme",
value: Theme value: Theme

View File

@ -41,17 +41,11 @@ export const resize = () => {
} }
}); });
} }
store.commit("SET_BROWSER"); store.commit("SET_BROWSER");
}; };
window.onload = () => { window.onload = () => {
const observer = new MutationObserver(resize);
observer.observe(document.getElementById("app"), {
childList: true,
subtree: true
});
window.addEventListener("resize", resize); window.addEventListener("resize", resize);
resize(); resize();
}; };

View File

@ -10,7 +10,7 @@
</el-tooltip> </el-tooltip>
</li> </li>
<li v-if="drag && isPc"> <li v-if="drag && !browser.isMini">
<el-tooltip content="拖动排序"> <el-tooltip content="拖动排序">
<i class="el-icon-s-operation" @click="isDrag = true"></i> <i class="el-icon-s-operation" @click="isDrag = true"></i>
</el-tooltip> </el-tooltip>
@ -46,7 +46,7 @@
}}</span> }}</span>
<span <span
class="cl-dept-tree__node-icon" class="cl-dept-tree__node-icon"
v-if="!isPc" v-if="browser.isMini"
@click="openCM($event, data, node)" @click="openCM($event, data, node)"
> >
<i class="el-icon-more"></i> <i class="el-icon-more"></i>
@ -59,8 +59,9 @@
</template> </template>
<script> <script>
import { deepTree, isArray, revDeepTree, isPc } from "cl-admin/utils"; import { deepTree, isArray, revDeepTree } from "cl-admin/utils";
import { ContextMenu, Form } from "cl-admin-crud"; import { ContextMenu, Form } from "cl-admin-crud";
import { mapGetters } from "vuex";
export default { export default {
name: "cl-dept-tree", name: "cl-dept-tree",
@ -80,11 +81,14 @@ export default {
return { return {
list: [], list: [],
loading: false, loading: false,
isDrag: false, isDrag: false
isPc: isPc()
}; };
}, },
computed: {
...mapGetters(["browser"])
},
created() { created() {
this.refresh(); this.refresh();
}, },

View File

@ -81,7 +81,7 @@ export default {
default-active={this.$route.path} default-active={this.$route.path}
background-color="transparent" background-color="transparent"
collapse-transition={false} collapse-transition={false}
collapse={this.browser.isMobile ? false : this.menuCollapse} collapse={this.browser.isMini ? false : this.menuCollapse}
on-select={this.toView}> on-select={this.toView}>
{el} {el}
</el-menu> </el-menu>

View File

@ -7,9 +7,7 @@ export default {
info: { info: {
...app ...app
}, },
browser: { browser: {},
isMobile: false
},
collapse: false collapse: false
}, },
getters: { getters: {

View File

@ -1,83 +1,74 @@
<template> <template>
<div> <cl-crud ref="crud" @load="onLoad" :on-refresh="onRefresh">
<cl-crud ref="crud" @load="onLoad" :on-refresh="onRefresh"> <el-row type="flex">
<el-row type="flex"> <cl-refresh-btn />
<cl-refresh-btn /> <cl-add-btn />
<cl-add-btn /> </el-row>
</el-row>
<el-row> <el-row>
<cl-table ref="table" v-bind="table" @row-click="onRowClick"> <cl-table ref="table" v-bind="table" @row-click="onRowClick">
<!-- 名称 --> <!-- 名称 -->
<template #column-name="{ scope }"> <template #column-name="{ scope }">
<span>{{ scope.row.name }}</span> <span>{{ scope.row.name }}</span>
<el-tag <el-tag
size="mini" size="mini"
effect="dark" effect="dark"
type="danger" type="danger"
v-if="!scope.row.isShow" v-if="!scope.row.isShow"
style="margin-left: 10px" style="margin-left: 10px"
>隐藏</el-tag >隐藏</el-tag
> >
</template>
<!-- 图标 -->
<template #column-icon="{ scope }">
<icon-svg :name="scope.row.icon" size="16px" style="margin-top: 5px"></icon-svg>
</template>
<!-- 权限 -->
<template #column-perms="{ scope }">
<el-tag
v-for="(item, index) in scope.row.permList"
:key="index"
size="mini"
effect="dark"
style="margin: 2px; letter-spacing: 0.5px"
>{{ item }}</el-tag
>
</template>
<!-- 路由 -->
<template #column-router="{ scope }">
<el-link type="primary" :href="scope.row.router" v-if="scope.row.type == 1">{{
scope.row.router
}}</el-link>
<span v-else>{{ scope.row.router }}</span>
</template>
<!-- 路由缓存 -->
<template #column-keepAlive="{ scope }">
<template v-if="scope.row.type == 1">
<i class="el-icon-check" v-if="scope.row.keepAlive"></i>
<i class="el-icon-close" v-else></i>
</template> </template>
</template>
<!-- 图标 --> <!-- 行新增 -->
<template #column-icon="{ scope }"> <template #slot-add="{ scope }">
<icon-svg <el-button
:name="scope.row.icon" type="text"
size="16px" size="mini"
style="margin-top: 5px" @click="upsertAppend(scope.row)"
></icon-svg> v-if="scope.row.type != 2"
</template> >新增</el-button
>
</template>
</cl-table>
</el-row>
<!-- 权限 --> <!-- 编辑 -->
<template #column-perms="{ scope }"> <cl-upsert ref="upsert" v-bind="upsert"></cl-upsert>
<el-tag </cl-crud>
v-for="(item, index) in scope.row.permList"
:key="index"
size="mini"
effect="dark"
style="margin: 2px; letter-spacing: 0.5px"
>{{ item }}</el-tag
>
</template>
<!-- 路由 -->
<template #column-router="{ scope }">
<el-link
type="primary"
:href="scope.row.router"
v-if="scope.row.type == 1"
>{{ scope.row.router }}</el-link
>
<span v-else>{{ scope.row.router }}</span>
</template>
<!-- 路由缓存 -->
<template #column-keepAlive="{ scope }">
<template v-if="scope.row.type == 1">
<i class="el-icon-check" v-if="scope.row.keepAlive"></i>
<i class="el-icon-close" v-else></i>
</template>
</template>
<!-- 行新增 -->
<template #slot-add="{ scope }">
<el-button
type="text"
size="mini"
@click="upsertAppend(scope.row)"
v-if="scope.row.type != 2"
>新增</el-button
>
</template>
</cl-table>
</el-row>
<!-- 编辑 -->
<cl-upsert ref="upsert" v-bind="upsert" @open="onUpsertOpen"></cl-upsert>
</cl-crud>
</div>
</template> </template>
<script> <script>
@ -255,7 +246,7 @@ export default {
prop: "router", prop: "router",
label: "节点路由", label: "节点路由",
span: 24, span: 24,
hidden: true, hidden: ({ scope }) => scope.type != 1,
component: { component: {
name: "el-input", name: "el-input",
attrs: { attrs: {
@ -268,6 +259,7 @@ export default {
value: true, value: true,
label: "路由缓存", label: "路由缓存",
span: 24, span: 24,
hidden: ({ scope }) => scope.type != 1,
component: { component: {
name: "el-radio-group", name: "el-radio-group",
options: [ options: [
@ -287,7 +279,7 @@ export default {
label: "是否显示", label: "是否显示",
span: 24, span: 24,
value: true, value: true,
hidden: false, hidden: ({ scope }) => scope.type == 2,
flex: false, flex: false,
component: { component: {
name: "el-switch" name: "el-switch"
@ -297,7 +289,7 @@ export default {
prop: "viewPath", prop: "viewPath",
label: "文件路径", label: "文件路径",
span: 24, span: 24,
hidden: true, hidden: ({ scope }) => scope.type != 1,
component: { component: {
name: "cl-menu-file" name: "cl-menu-file"
} }
@ -306,6 +298,7 @@ export default {
prop: "icon", prop: "icon",
label: "节点图标", label: "节点图标",
span: 24, span: 24,
hidden: ({ scope }) => scope.type == 2,
component: { component: {
name: "cl-menu-icons" name: "cl-menu-icons"
} }
@ -329,7 +322,7 @@ export default {
prop: "perms", prop: "perms",
label: "权限", label: "权限",
span: 24, span: 24,
hidden: true, hidden: ({ scope }) => scope.type != 2,
component: { component: {
name: "cl-menu-perms" name: "cl-menu-perms"
} }
@ -341,14 +334,12 @@ export default {
methods: { methods: {
onLoad({ ctx, app }) { onLoad({ ctx, app }) {
ctx.service(this.$service.system.menu) ctx.service(this.$service.system.menu).done();
.set("dict", { api: { page: "list" } })
.done();
app.refresh(); app.refresh();
}, },
onRefresh(params, { render }) { onRefresh(_, { render }) {
this.$service.system.menu.list().then(list => { this.$service.system.menu.list().then(list => {
list.map(e => { list.map(e => {
e.permList = e.perms ? e.perms.split(",") : []; e.permList = e.perms ? e.perms.split(",") : [];
@ -364,10 +355,6 @@ export default {
} }
}, },
onUpsertOpen(isEdit, data) {
this.changeType(data ? data.type : 0);
},
upsertAppend({ type, id }) { upsertAppend({ type, id }) {
this.$refs["crud"].rowAppend({ this.$refs["crud"].rowAppend({
parentId: id, parentId: id,
@ -375,16 +362,6 @@ export default {
}); });
}, },
changeType(index) {
const { toggleItem } = this.$refs["upsert"];
toggleItem("router", index == 1);
toggleItem("viewPath", index == 1);
toggleItem("keepAlive", index == 1);
toggleItem("icon", index != 2);
toggleItem("perms", index == 2);
toggleItem("isShow", index != 2);
},
setPermission({ id }) { setPermission({ id }) {
this.$refs["crud"].rowAppend({ this.$refs["crud"].rowAppend({
parentId: id, parentId: id,

View File

@ -104,12 +104,11 @@
</template> </template>
<script> <script>
import { isPc } from "cl-admin/utils"; import { mapGetters } from "vuex";
export default { export default {
data() { data() {
return { return {
isExpand: isPc(), isExpand: true,
selects: { selects: {
dept: {}, dept: {},
ids: [] ids: []
@ -377,6 +376,19 @@ export default {
}; };
}, },
computed: {
...mapGetters(["browser"])
},
watch: {
"browser.isMini": {
immediate: true,
handler(val) {
this.isExpand = !val;
}
}
},
methods: { methods: {
refresh(params) { refresh(params) {
this.$refs["crud"].refresh(params); this.$refs["crud"].refresh(params);
@ -406,7 +418,7 @@ export default {
this.$refs["upsert"].toggleItem("tips", !isEdit); this.$refs["upsert"].toggleItem("tips", !isEdit);
}, },
onUpsertSubmit(isEdit, data, { next }) { onUpsertSubmit(_, data, { next }) {
let departmentId = data.departmentId; let departmentId = data.departmentId;
if (!departmentId) { if (!departmentId) {
@ -435,7 +447,8 @@ export default {
departmentIds: ids departmentIds: ids
}); });
if (!isPc()) { //
if (this.browser.isMini) {
this.isExpand = false; this.isExpand = false;
} }
}, },

View File

@ -6,18 +6,33 @@
:title="title" :title="title"
:height="height" :height="height"
:width="width" :width="width"
:props="conf" :props="{
modal: true,
customClass: 'cl-chat__dialog',
'append-to-body': true,
'close-on-click-modal': false
}"
:controls="['slot-session', 'cl-flex1', 'fullscreen', 'close']"
> >
<div class="cl-chat"> <div class="cl-chat">
<!-- 会话区域 -->
<chat-session /> <chat-session />
<!-- 会话详情 -->
<div class="cl-chat__detail" v-if="session"> <div class="cl-chat__detail" v-if="session">
<chat-message /> <chat-message />
<chat-input /> <chat-input />
</div> </div>
</div> </div>
<template #slot-session>
<button v-if="session">
<i
class="el-icon-notebook-2"
v-if="sessionVisible"
@click="CLOSE_SESSION()"
></i>
<i class="el-icon-arrow-left" v-else @click="OPEN_SESSION()"></i>
</button>
</template>
</cl-dialog> </cl-dialog>
<!-- MP3 --> <!-- MP3 -->
@ -29,18 +44,14 @@
<script> <script>
import dayjs from "dayjs"; import dayjs from "dayjs";
import { mapGetters } from "vuex"; import { mapGetters, mapMutations } from "vuex";
import { parseContent } from "../utils";
import io from "socket.io-client"; import io from "socket.io-client";
import { socketUrl } from "@/config/env"; import { socketUrl } from "@/config/env";
import Session from "./session"; import Session from "./session";
import Message from "./message"; import Message from "./message";
import Input from "./input"; import Input from "./input";
import eventBus from "../utils/event-bus"; import eventBus from "../utils/event-bus";
import { parseContent } from "../utils";
//
export default { export default {
name: "cl-chat", name: "cl-chat",
@ -65,24 +76,18 @@ export default {
data() { data() {
return { return {
visible: false, visible: false,
socket: null, socket: null
conf: {
modal: true,
customClass: "cl-chat__dialog",
"append-to-body": true,
"close-on-click-modal": false
}
}; };
}, },
provide() { provide() {
return { return {
socket: this.socket chat: this
}; };
}, },
computed: { computed: {
...mapGetters(["token", "session", "sessionList"]), ...mapGetters(["token", "session", "sessionList", "sessionVisible"]),
title() { title() {
return this.session ? `${this.session.nickname} 聊天中` : "聊天对话框"; return this.session ? `${this.session.nickname} 聊天中` : "聊天对话框";
@ -90,7 +95,7 @@ export default {
}, },
created() { created() {
// this.socket = io(`${socketUrl}?isAdmin=true&token=${this.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");
// }); // });
@ -112,6 +117,8 @@ export default {
}, },
methods: { methods: {
...mapMutations(["OPEN_SESSION", "CLOSE_SESSION", "UPDATE_SESSION"]),
open() { open() {
this.visible = true; this.visible = true;
}, },
@ -136,7 +143,7 @@ export default {
if (same) { if (same) {
// //
this.$store.commit("UPDATE_SESSION", { this.UPDATE_SESSION({
contentType, contentType,
content content
}); });
@ -148,10 +155,10 @@ export default {
type: 1 type: 1
}); });
// //
this.$service.im.message.read({ this.$service.im.message.read({
ids: [msgId], ids: [msgId],
session: this.session.current.id session: this.session.id
}); });
} }
@ -217,32 +224,23 @@ export default {
<style lang="scss"> <style lang="scss">
.cl-chat__dialog { .cl-chat__dialog {
margin-bottom: 0 !important;
min-width: 1000px;
.el-dialog__body { .el-dialog__body {
padding: 0; padding: 0;
} }
&.is-fullscreen {
.cl-dialog__container {
height: calc(100vh - 46px) !important;
}
}
} }
.cl-chat { .cl-chat {
display: flex; display: flex;
height: 100%; height: 100%;
background-color: #f7f7f7; background-color: #f7f7f7;
padding: 5px;
box-sizing: border-box;
&__detail { &__detail {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
flex: 1; flex: 1;
height: 100%; height: 100%;
padding: 5px;
box-sizing: border-box;
} }
} }
</style> </style>

View File

@ -1,15 +1,32 @@
<template> <template>
<div class="chat-emoji"> <el-popover
<div class="scroller"> v-model="visible"
<div class="block" v-for="(item, index) in list" :key="index" @click="select(item)"> placement="top"
<img :src="item" /> :width="popoverWidth"
trigger="click"
popper-class="popover-emoji"
>
<div class="tool-emoji">
<div class="tool-emoji__scroller scroller1">
<div
class="tool-emoji__item"
v-for="(item, index) in list"
:key="index"
@click="select(item)"
>
<img :src="item" />
</div>
</div> </div>
</div> </div>
</div>
<img slot="reference" src="../static/images/emoji.png" alt="" />
</el-popover>
</template> </template>
<script> <script>
let emoji = { import { mapGetters } from "vuex";
//
const emoji = {
url: "https://cool-comm.oss-cn-shenzhen.aliyuncs.com/show/imgs/chat/", url: "https://cool-comm.oss-cn-shenzhen.aliyuncs.com/show/imgs/chat/",
list: [ list: [
"angry-face.png", "angry-face.png",
@ -103,54 +120,66 @@ let emoji = {
] ]
}; };
emoji.list = emoji.list.map(e => emoji.url + e);
export default { export default {
data() { data() {
return { return {
list: emoji.list visible: false,
list: emoji.list.map(e => emoji.url + e)
}; };
}, },
methods: { computed: {
close() {}, ...mapGetters(["browser"]),
popoverWidth() {
return (this.browser.width > 500 ? 500 : this.browser.width) - 24;
}
},
methods: {
select(e) { select(e) {
this.$emit("select", e); this.$emit("select", e);
this.visible = false;
} }
} }
}; };
</script> </script>
<style lang="scss">
.popover-emoji {
padding: 5px;
}
</style>
<style lang="scss" scoped> <style lang="scss" scoped>
.chat-emoji { .tool-emoji {
height: 250px; height: 250px;
box-sizing: border-box; box-sizing: border-box;
.scroller { &__scroller {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
height: 100%; height: 100%;
overflow: auto; overflow: auto;
}
.block { &__item {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
height: 50px; height: 50px;
width: 50px; width: 50px;
cursor: pointer; cursor: pointer;
&:hover, &:hover,
&:active { &:active {
background-color: #f7f7f7; background-color: #f7f7f7;
} }
img { img {
display: inline-block; display: inline-block;
height: 25px; height: 25px;
width: 25px; width: 25px;
}
} }
} }
} }

View File

@ -5,15 +5,7 @@
<ul> <ul>
<!-- 表情 --> <!-- 表情 -->
<li> <li>
<el-popover <emoji @select="onEmojiSelect" />
v-model="emoji.visible"
placement="top-start"
width="470"
trigger="click"
>
<emoji @select="onEmojiSelect" />
<img slot="reference" src="../static/images/emoji.png" alt="" />
</el-popover>
</li> </li>
<!-- 图片上传 --> <!-- 图片上传 -->
<li hidden> <li hidden>
@ -50,6 +42,7 @@
v-model="value" v-model="value"
placeholder="请描述您想咨询的问题" placeholder="请描述您想咨询的问题"
type="textarea" type="textarea"
resize="none"
:rows="5" :rows="5"
@keyup.enter.native="onTextSend" @keyup.enter.native="onTextSend"
></el-input> ></el-input>
@ -71,7 +64,7 @@ export default {
Emoji Emoji
}, },
inject: ["socket"], inject: ["chat"],
data() { data() {
return { return {
@ -193,22 +186,15 @@ export default {
const { id, userId } = this.session; const { id, userId } = this.session;
// //
// this.updateSession({ this.$store.commit("UPDATE_SESSION", data);
// contentType,
// content
// });
if (this.socket) { if (this.chat.socket) {
this.socket.emit(`user@${userId}`, { this.chat.socket.emit(`user@${userId}`, {
contentType: data.contentType, contentType: data.contentType,
type: 0, type: 0,
content: JSON.stringify(data.content), content: JSON.stringify(data.content),
sessionId: id sessionId: id
}); });
if (isAppend) {
this.append(data);
}
} }
if (isAppend) { if (isAppend) {
@ -235,6 +221,7 @@ export default {
ul { ul {
display: flex; display: flex;
li { li {
list-style: none; list-style: none;
margin-right: 10px; margin-right: 10px;
@ -244,7 +231,7 @@ export default {
opacity: 0.7; opacity: 0.7;
} }
img { /deep/ img {
height: 26px; height: 26px;
width: 26px; width: 26px;
} }
@ -257,7 +244,7 @@ export default {
.el-button { .el-button {
position: absolute; position: absolute;
right: 10px; right: 15px;
bottom: 10px; bottom: 10px;
} }
} }

View File

@ -27,11 +27,13 @@
</div> </div>
<div class="main"> <div class="main">
<!-- 头像 -->
<div class="avatar" @tap="toUserDetail(item)"> <div class="avatar" @tap="toUserDetail(item)">
<img :src="item.avatarUrl" /> <img :src="item.avatarUrl" />
</div> </div>
<div class="det"> <div class="det">
<!-- 昵称 -->
<span class="name">{{ item.nickName }}</span> <span class="name">{{ item.nickName }}</span>
<div <div

View File

@ -1,5 +1,12 @@
<template> <template>
<div class="cl-chat-session"> <div
class="cl-chat-session"
:class="{
'is-position': browser.isMini,
'is-show': sessionVisible
}"
>
<!-- 关键字搜索 -->
<div class="cl-chat-session__search"> <div class="cl-chat-session__search">
<el-input <el-input
v-model="keyWord" v-model="keyWord"
@ -46,10 +53,11 @@
</template> </template>
<script> <script>
import { mapGetters } from "vuex"; import { mapGetters, mapMutations } from "vuex";
import { isEmpty } from "cl-admin/utils";
import { ContextMenu } from "cl-admin-crud";
import { parseContent } from "../utils"; import { parseContent } from "../utils";
import eventBus from "../utils/event-bus"; import eventBus from "../utils/event-bus";
import { ContextMenu } from "cl-admin-crud";
export default { export default {
data() { data() {
@ -65,8 +73,9 @@ export default {
}, },
computed: { computed: {
...mapGetters(["sessionList", "session"]), ...mapGetters(["sessionList", "session", "browser", "sessionVisible"]),
//
list() { list() {
return this.sessionList return this.sessionList
.map(e => { .map(e => {
@ -81,11 +90,20 @@ export default {
}, },
created() { created() {
//
eventBus.$on("session-refresh", this.refresh); eventBus.$on("session-refresh", this.refresh);
this.refresh();
// PC
this.refresh().then(res => {
if (!isEmpty(res.list) && !this.browser.isMini) {
this.SET_SESSION(res.list[0]);
}
});
}, },
methods: { methods: {
...mapMutations(["SET_SESSION_LIST", "SET_SESSION", "CLEAR_SESSION", "CLOSE_SESSION"]),
// //
openCM(e, id, index) { openCM(e, id, index) {
ContextMenu.open(e, { ContextMenu.open(e, {
@ -115,24 +133,29 @@ export default {
refresh(params) { refresh(params) {
this.loading = true; this.loading = true;
this.$service.im.session return new Promise((resolve, reject) => {
.page({ this.$service.im.session
...this.pagination, .page({
keyWord: this.keyWord, ...this.pagination,
params, keyWord: this.keyWord,
order: "updateTime", params,
sort: "desc" order: "updateTime",
}) sort: "desc"
.then(res => { })
this.$store.commit("SET_SESSION_LIST", res.list); .then(res => {
this.pagination = res.pagination; this.SET_SESSION_LIST(res.list);
}) this.pagination = res.pagination;
.catch(err => {
this.$message.error(err); resolve(res);
}) })
.done(() => { .catch(err => {
this.loading = false; this.$message.error(err);
}); reject(err);
})
.done(() => {
this.loading = false;
});
});
}, },
// //
@ -143,11 +166,15 @@ export default {
// //
toDetail(item) { toDetail(item) {
if (item) { if (item) {
//
if (this.browser.isMini) this.CLOSE_SESSION();
//
if (!this.session || this.session.id != item.id) { if (!this.session || this.session.id != item.id) {
this.$store.commit("SET_SESSION", item); this.SET_SESSION(item);
} }
} else { } else {
this.$store.commit("CLEAR_SESSION"); this.CLEAR_SESSION();
} }
} }
} }
@ -156,11 +183,30 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.cl-chat-session { .cl-chat-session {
height: calc(100% - 10px); height: 100%;
width: 250px; width: 0;
margin: 5px 0 5px 5px; transition: width 0.2s ease-in-out;
border-radius: 5px; border-radius: 5px;
background-color: #fff; background-color: #fff;
overflow: hidden;
&.is-show {
width: 250px;
max-width: 100%;
margin-right: 5px;
}
&.is-position {
position: absolute;
left: 5px;
top: 51px;
height: calc(100% - 56px);
z-index: 3000;
&.is-show {
width: calc(100% - 10px);
}
}
&__search { &__search {
padding: 10px; padding: 10px;

View File

@ -1,16 +1,20 @@
import eventBus from "../utils/event-bus"; import eventBus from "../utils/event-bus";
import { isBoolean } from "cl-admin/utils";
export default { export default {
state: { state: {
list: [], list: [],
current: null current: null,
visible: true
}, },
getters: { getters: {
// 当前会话 // 当前会话
session: state => state.current, session: state => state.current,
// 会话列表 // 会话列表
sessionList: state => state.list sessionList: state => state.list,
// 是否显示会话列表
sessionVisible: state => state.visible
}, },
mutations: { mutations: {
@ -39,6 +43,16 @@ export default {
// 清空会话列表 // 清空会话列表
CLEAR_SESSION_LIST(state) { CLEAR_SESSION_LIST(state) {
state.list = []; state.list = [];
},
// 打开会话列表
OPEN_SESSION(state, val) {
state.visible = isBoolean(val) ? val : !state.visible;
},
// 关闭会话列表
CLOSE_SESSION(state) {
state.visible = false;
} }
} }
}; };

View File

@ -1,9 +0,0 @@
{
"name": "upload",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"uuid": "^8.3.2"
}
}

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441306173" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8757" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M739.50933333 332.1632v-105.92746667L512 102.4 284.49066667 226.23573333l-1.5712 105.92746667 229.1488 106.1088 227.44213333-105.92746667v106.10986667L512 544.08533333l-0.52266667 0.18133334-226.98666666-105.83466667v-106.10986667L56.88746667 438.272v269.0848L285.01333333 813.19253333 512 925.4688v-0.34133333l227.41866667-111.84426667 227.6928-105.9264V438.272z" p-id="8758"></path></svg>

Before

Width:  |  Height:  |  Size: 767 B

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441295630" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7916" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M336.11889778 554.09208889h348.41941333v-87.09233778H336.11889778v87.09233778zM157.53671111 510.51178667c0-100.16768 78.34851555-178.57763555 178.58104889-178.57763556h130.66467555v-82.75057778H336.11889778c-143.74456889 0-261.32707555 117.58478222-261.32707556 261.32821334 0 143.74229333 117.58250667 261.32821333 261.32707556 261.32821333h130.66467555v-82.74830222H336.11889778c-100.23253333 0-178.58104889-78.47139555-178.58104889-178.57991111M684.53831111 249.18471111H553.87363555v82.75057778h130.66467556c100.16312889 0 178.51619555 78.40995555 178.51619556 178.57763556 0 100.10737778-78.35192889 178.57991111-178.51619556 178.5799111H553.87363555v82.74830223h130.66467556c143.74343111 0 261.32821333-117.58592 261.32821334-261.32821333 0-143.74343111-117.58478222-261.32821333-261.32821334-261.32821334" p-id="7917"></path></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441291674" class="icon" viewBox="0 0 1099 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7636" xmlns:xlink="http://www.w3.org/1999/xlink" width="137.375" height="128"><defs><style type="text/css"></style></defs><path d="M1011.81895111 373.64622222v-73.78868147l-87.5026963 0.24272592v-114.44527408c0-29.00574815-14.92764445-45.26838518-43.93339259-45.26838518h-105.46441481V50.82074075h-74.63822223v89.56586666h-112.13937777V50.82074075h-74.63822223l-0.12136296 89.56586666h-112.13937778l0.24272592-89.56586666h-75.00231111l0.12136297 89.56586666h-98.18263704c-36.0448 0-50.85108148 16.26263703-50.60835555 53.88515556l-0.72817778 105.8285037h-89.08041482V373.64622222h89.08041482v103.03715556l-89.08041482-0.12136296v74.63822221l89.08041482 0.24272594v104.61487406h-89.08041482v73.30322964h89.08041482v100.00308148c0 41.26340741 16.62672592 58.37558518 58.0114963 58.37558518h91.50767407l-0.12136297 85.92497778h74.51685926l0.3640889-85.92497778h112.13937777v85.92497778h74.88094815l-0.12136297-85.92497778h112.13937779l-0.24272593 85.92497778h74.88094814l0.12136297-85.92497778h99.88171852c33.49617778 0 49.51608889-29.4912 49.51608889-58.37558518v-100.00308148h87.50269629v-73.30322964h-87.74542222v-104.61487406h87.5026963v-74.51685927l-87.5026963-0.24272592V373.64622222h87.5026963z m-162.26228148 439.33392593h-597.7125926V215.14619259h597.83395555V812.98014815z m-472.83010371-94.29902223h358.99164444c14.32082963 0 19.53943703-9.8304 19.53943705-22.81623703V336.0237037c0-15.29173333-10.43721482-23.78714075-22.81623705-23.78714073h-359.47709628c-18.6898963 0-24.15122963 6.91768889-24.15122964 25.72894814v352.68077037c0 18.6898963 9.22358518 28.03484445 27.91348148 28.03484444z" p-id="7637"></path></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441335315" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10998" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M884.56851911 177.49090608C828.90296889 115.61278578 634.72222815 97.74815763 512 97.74815763s-316.90296889 17.86462815-372.56851911 79.74274845C130.11080533 181.37452089 123.63851852 190.43669333 123.63851852 201.31081482v647.26873126c0 10.87412148 6.47228682 19.93629392 15.79296237 23.81990874C195.09703111 934.27878875 389.27777185 952.14341689 512 952.14341689s316.90296889-17.86462815 372.56851911-79.74396207c9.32067555-3.88361482 15.79296237-12.94578725 15.79296237-23.81990874V201.31081482c0-10.87412148-6.47228682-19.93629392-15.79296237-23.81990874z m-35.98897303 450.49931851c-7.50751289 22.78468267-129.19451497 65.24472889-336.57954608 65.24472889-207.90325097 0-329.58903941-42.46004622-336.57954608-64.72650903V484.29647645C254.90469925 525.20429037 408.69584592 537.89036089 512 537.89036089s257.09530075-12.68607052 336.57954608-53.59388444v143.69374814z m0-207.12531437c-7.50751289 22.78346903-129.19451497 65.24472889-336.57954608 65.24472889-207.90325097 0-329.58903941-42.46125985-336.57954608-64.72772266V277.17116208c79.48424533 40.9066003 233.275392 53.59388445 336.57954608 53.59388444s257.09530075-12.68728415 336.57954608-53.59388444v143.69374814zM512 149.52887941c206.0900883 0 327.51858725 41.94304 336.57954608 64.72772267C839.77709037 237.04007111 718.34980503 278.98311111 512 278.98311111c-207.38503111 0-329.07203318-42.46125985-336.57954608-63.94978608v-0.25971673c7.50751289-22.78346903 129.19451497-65.24472889 336.57954608-65.24472889zM512 900.36148148c-207.90325097 0-329.58903941-42.46125985-336.57954608-64.72650903V691.42300445C254.90469925 732.33081837 408.69584592 745.01688889 512 745.01688889s257.09530075-12.68607052 336.57954608-53.59388444v143.69374814C841.07203318 857.90022163 719.38503111 900.36148148 512 900.36148148z" p-id="10999"></path></svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441319409" class="icon" viewBox="0 0 1099 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9737" xmlns:xlink="http://www.w3.org/1999/xlink" width="137.375" height="128"><defs><style type="text/css"></style></defs><path d="M427.85156025 795.07105396h113.36703157c13.53224006 0 23.33620992-7.87079269 23.3362099-21.1268646v-50.40069005c0-12.15139925-8.69929718-19.05560336-24.30279849-19.05560335h-113.22894749c-14.7749968 0-22.23153725 10.49439025-22.23153724 21.81728501v46.67241982c-0.13808409 10.63247434 11.46097883 22.09345317 23.06004175 22.09345317z m222.72962475 0h161.00603997c14.49882864 0 23.88854624-8.00887677 23.88854623-19.60793969v-50.40069004c0-12.01331517-8.28504494-20.57452827-24.30279849-20.57452827h-161.42029221c-14.36074457 0-23.47429398 8.28504494-23.47429398 20.43644418v44.32499042c0 14.08457639 8.42312903 25.8217234 24.30279848 25.8217234z m-342.17235594-746.20638078l-255.04130003 469.07162758v393.53963458c0 37.97312263 22.64578949 58.40956682 62.96634153 58.40956681h864.82060749c35.07335691 0 56.33830558-21.26494868 56.33830557-55.92405334V512.9652738l-255.86980452-464.10060062h-473.21415004z m424.05621675 77.18900201l214.72074799 384.14991696h-796.88323898l210.99247775-384.14991696h371.17001324z m222.17728843 765.95240454h-820.63370114V596.78231176h820.63370114v295.22376797z" p-id="9738"></path></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441299581" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8196" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M316.2048 750.35093333h398.3808v74.66666667H316.2048z m286.86506667-441.66933333l208.5632 361.23093333-64.66133334 37.33333334-208.5632-361.232z m-183.13173334 1.72906667l64.66133334 37.33333333-210.06186667 363.8272-64.66133333-37.33333333z" p-id="8197"></path><path d="M512 377.04746667c-79.4016 0-144-64.5984-144-144s64.5984-144 144-144 144 64.5984 144 144-64.5984 144-144 144z m0-213.33333334c-38.2304 0-69.33333333 31.10293333-69.33333333 69.33333334s31.10293333 69.33333333 69.33333333 69.33333333 69.33333333-31.10293333 69.33333333-69.33333333-31.10293333-69.33333333-69.33333333-69.33333334zM211.6832 922.66666667c-79.4016 0-144-64.5984-144-144s64.5984-144 144-144 144 64.5984 144 144-64.5984 144-144 144z m0-213.33333334c-38.2304 0-69.33333333 31.10293333-69.33333333 69.33333334s31.10293333 69.33333333 69.33333333 69.33333333 69.33333333-31.10293333 69.33333333-69.33333333-31.10293333-69.33333333-69.33333333-69.33333334z m604.22293333 213.33333334c-79.4016 0-144-64.5984-144-144s64.5984-144 144-144 144 64.5984 144 144-64.59733333 144-144 144z m0-213.33333334c-38.2304 0-69.33333333 31.10293333-69.33333333 69.33333334s31.10293333 69.33333333 69.33333333 69.33333333 69.33333333-31.10293333 69.33333334-69.33333333-31.10293333-69.33333333-69.33333334-69.33333334z" p-id="8198"></path></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1614441327777" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10438" xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128"><defs><style type="text/css"></style></defs><path d="M511.05215525 64.30416592c-247.06950637 0-448.32692148 200.94187141-448.32692147 448.32692149 0 247.07072 200.94065778 448.32692148 448.32692147 448.32692148s448.32692148-200.94065778 448.3269215-448.32692148c0-247.38505008-201.25741511-448.32692148-448.3269215-448.32692149z m0 817.35164208c-36.01810015 0-83.40912355-71.71944297-108.36984414-193.67465718l216.42293097 0.3155437c-24.64396325 121.63967052-72.03498667 193.35911348-108.05308683 193.35911348z m-120.05952473-272.66010075c-3.15907792-30.3310317-4.7392237-62.55775289-4.7392237-96.68016355 0-35.70134282 1.89568948-69.50699615 5.37152473-101.10262992l239.48553482 0.3155437c3.47583525 31.28009008 5.05598103 65.08574341 5.05598104 100.78708622 0 34.43795437-1.58014578 66.66467555-4.73922371 96.99570727l-240.43459318-0.31554372z m120.05952473-465.7036705c35.70134282 0 82.46127882 70.45605452 107.42199942 189.56652088l-214.84399882-0.31554371c24.96072059-119.11168 72.0362003-189.25097718 107.4219994-189.25097717z m199.04618193 268.55317807l156.39195497 0.3155437c9.1629037 31.91117748 13.90212741 65.71804445 13.9021274 100.47154251 0 33.80565333-4.42368 66.34913185-12.95428266 97.31125097l-156.7087123-0.3155437c2.84353422-31.59563378 4.42368-64.13789867 4.42368-96.99570727 0-34.43795437-1.89568948-68.24482133-5.05476741-100.78708621z m123.53414637-78.66989985l-134.59273955-0.31554372c-8.53060267-45.49654755-20.22028325-87.51725985-35.07025541-124.1664474-5.68706845-14.53442845-12.0052243-27.80425482-18.64135111-40.12623644 80.25125925 31.27887645 146.91593482 90.04525037 188.30434607 164.60822756zM376.77495941 168.56708741c-6.63491318 12.32198163-12.63752533 25.9073517-18.64135111 40.12502281-14.84875852 36.65040118-26.53843911 78.35435615-35.06904178 123.8509037l-134.27598222-0.3155437c41.70395497-73.93188978 108.05308682-132.38272 187.98637511-163.66038281zM155.92956208 411.21291378l156.07641125 0.3155437c-3.15907792 32.85902222-4.7392237 66.66467555-4.7392237 101.10384355 0 32.85780859 1.58014578 65.08452978 4.42368 96.67894994l-154.81302281-0.31554372v7.58275793c-9.79399111-32.85902222-14.84997215-67.92927763-14.84997215-103.94737777-0.3155437-35.38458548 4.7392237-69.19145245 13.90212741-101.41817363z m30.3310317 276.45269333l136.1716717 0.31554371c8.5318163 47.07669333 20.53704059 90.36079408 35.70255644 128.2745837 5.68706845 14.53321482 12.0052243 27.80304118 18.64135111 40.12502281-81.5146477-31.91117748-149.127168-92.25648355-190.51557925-168.71515022z m459.0675437 168.71515022c6.63612682-12.32198163 12.63873897-25.9073517 18.64135111-40.12502281 15.16551585-37.59824592 27.17195378-80.88234667 35.70255644-127.64228267l135.856128 0.3155437c-41.38841125 75.82757925-108.68538785 135.5405843-190.20003555 167.45176178z" p-id="10439"></path></svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -2,7 +2,7 @@
<div class="app-slider"> <div class="app-slider">
<div class="app-slider__logo" @click="toHome"> <div class="app-slider__logo" @click="toHome">
<img src="@/assets/icon/logo/silder-simple.png" /> <img src="@/assets/icon/logo/silder-simple.png" />
<span v-if="!menuCollapse || browser.isMobile">{{ app.name }}</span> <span v-if="!menuCollapse || browser.isMini">{{ app.name }}</span>
</div> </div>
<div class="app-slider__menu"> <div class="app-slider__menu">

View File

@ -17,14 +17,13 @@
<script> <script>
import VueEcharts from "vue-echarts"; import VueEcharts from "vue-echarts";
import { isPc } from "cl-admin/utils"; import { mapGetters } from "vuex";
const barWidth = isPc() ? 25 : 15;
export default { export default {
components: { components: {
VueEcharts VueEcharts
}, },
data() { data() {
return { return {
chartOptions: { chartOptions: {
@ -78,7 +77,7 @@ export default {
}, },
series: [ series: [
{ {
barWidth, barWidth: 25,
name: "付款笔数", name: "付款笔数",
type: "bar", type: "bar",
data: [], data: [],
@ -90,7 +89,7 @@ export default {
}, },
{ {
type: "bar", type: "bar",
barWidth, barWidth: 25,
xAxisIndex: 0, xAxisIndex: 0,
barGap: "-100%", barGap: "-100%",
data: [], data: [],
@ -105,6 +104,22 @@ export default {
} }
}; };
}, },
computed: {
...mapGetters(["browser"])
},
watch: {
"browser.isMini": {
immediate: true,
handler(v) {
this.chartOptions.series.map(e => {
e.barWidth = v ? 15 : 25;
});
}
}
},
created() { created() {
this.chartOptions.xAxis.data = new Array(12).fill(1).map((e, i) => i + 1 + "月"); this.chartOptions.xAxis.data = new Array(12).fill(1).map((e, i) => i + 1 + "月");
this.chartOptions.series[0].data = new Array(12) this.chartOptions.series[0].data = new Array(12)