Forráskód Böngészése

添加 mock 数据,添加客服聊天

icssoa 4 éve
szülő
commit
9c96709e1e

+ 4 - 3
package.json

@@ -1,6 +1,6 @@
 {
 	"name": "cool-admin-vue",
-	"version": "3.0.2",
+	"version": "3.1.0",
 	"scripts": {
 		"serve": "vue-cli-service serve",
 		"build": "vue-cli-service build",
@@ -10,8 +10,8 @@
 	},
 	"dependencies": {
 		"axios": "^0.21.1",
-		"cl-admin": "^1.3.4",
-		"cl-admin-crud": "^1.6.0",
+		"cl-admin": "^1.4.0",
+		"cl-admin-crud": "^1.6.2",
 		"cl-admin-theme": "^0.0.4",
 		"clipboard": "^2.0.7",
 		"codemirror": "^5.59.4",
@@ -20,6 +20,7 @@
 		"echarts": "^4.5.0",
 		"element-ui": "^2.15.1",
 		"js-beautify": "^1.13.5",
+		"mockjs": "^1.1.0",
 		"nprogress": "^0.2.0",
 		"qs": "^6.9.1",
 		"quill": "^1.3.7",

+ 1 - 0
src/cool/index.js

@@ -25,6 +25,7 @@ export default {
 				}
 			}
 		},
+		"chat",
 		"task",
 		"copy",
 		"distpicker",

+ 1 - 1
src/cool/modules/base/components/route-nav/index.vue

@@ -66,7 +66,7 @@ export default {
 	},
 
 	computed: {
-		...mapGetters(["conf", "menuGroup"]),
+		...mapGetters(["menuGroup"]),
 
 		lastName() {
 			return _.last(this.list).name;

+ 72 - 59
src/cool/modules/chat/components/box.vue → src/cool/modules/chat/components/chat.vue

@@ -1,11 +1,11 @@
 <template>
-	<div class="chat-wrap">
+	<div class="cl-chat__wrap">
 		<!-- 聊天窗口 -->
 		<cl-dialog :visible.sync="visible" v-bind="conf">
-			<div class="chat-box">
+			<div class="cl-chat">
 				<!-- 会话区域 -->
-				<div class="chat-box__session">
-					<div class="chat-box__session-search">
+				<div class="cl-chat__session">
+					<div class="cl-chat__session-search">
 						<el-input
 							v-model="session.keyWord"
 							placeholder="搜索"
@@ -18,9 +18,9 @@
 					</div>
 
 					<!-- 会话列表 -->
-					<ul class="chat-box__session-list scroller1">
+					<ul class="cl-chat__session-list scroller1" v-if="sessionList.length > 0">
 						<li
-							class="chat-box__session-item"
+							class="cl-chat__session-item"
 							v-for="(item, index) in sessionList"
 							:key="index"
 							:class="{
@@ -47,18 +47,23 @@
 							</div>
 						</li>
 					</ul>
+
+					<!-- 空态 -->
+					<div class="cl-chat__session-empty" v-else>
+						没有搜索到内容...
+					</div>
 				</div>
 
 				<!-- 会话详情 -->
-				<div class="chat-box__detail">
+				<div class="cl-chat__detail">
 					<template v-if="session.current">
 						<div
-							class="chat-box__detail-container scroller1"
+							class="cl-chat__detail-container scroller1"
 							ref="scroller"
 							v-loading="message.loading"
 						>
 							<!-- 加载更多 -->
-							<div class="chat-box__detail-more" v-if="message.list.length > 0">
+							<div class="cl-chat__detail-more" v-if="message.list.length > 0">
 								<el-button
 									round
 									size="mini"
@@ -72,9 +77,9 @@
 							<message :list="message.list" />
 						</div>
 
-						<div class="chat-box__detail-footer">
+						<div class="cl-chat__detail-footer">
 							<!-- 工具栏 -->
-							<div class="chat-box__opbar">
+							<div class="cl-chat__opbar">
 								<ul>
 									<!-- 表情 -->
 									<li>
@@ -93,7 +98,7 @@
 										</el-popover>
 									</li>
 									<!-- 图片上传 -->
-									<li>
+									<li hidden>
 										<cl-upload
 											accept="image/*"
 											list-type
@@ -103,7 +108,7 @@
 										</cl-upload>
 									</li>
 									<!-- 视频上传 -->
-									<li>
+									<li hidden>
 										<cl-upload
 											accept="video/*"
 											list-type
@@ -126,7 +131,7 @@
 							</div>
 
 							<!-- 输入框,发送按钮 -->
-							<div class="chat-box__input">
+							<div class="cl-chat__input">
 								<el-input
 									v-model="message.value"
 									placeholder="请描述您想咨询的问题"
@@ -158,9 +163,9 @@
 
 <script>
 import dayjs from "dayjs";
-import io from "socket.io-client";
-import { isString, debounce } from "cl-admin/utils";
 import { mapGetters } from "vuex";
+import { isString, debounce } from "cl-admin/utils";
+import io from "socket.io-client";
 import { socketUrl } from "@/config/env";
 import Emoji from "./emoji";
 import Message from "./message";
@@ -180,14 +185,16 @@ export default {
 	data() {
 		return {
 			visible: false,
+			socket: null,
 			conf: {
 				title: "聊天对话框",
+				height: "650px",
+				width: "1000px",
 				props: {
 					modal: true,
-					"custom-class": "chat-box__wrap",
+					customClass: "cl-chat__dialog",
 					"append-to-body": true,
-					"close-on-click-modal": false,
-					width: "1000px"
+					"close-on-click-modal": false
 				}
 			},
 			message: {
@@ -212,8 +219,7 @@ export default {
 			},
 			emoji: {
 				visible: false
-			},
-			socket: null
+			}
 		};
 	},
 
@@ -233,28 +239,26 @@ export default {
 		}
 	},
 
-	mounted() {
-		this.socket = io(`${socketUrl}?isAdmin=true&token=${this.token}`);
-
-		this.socket.on("connect", () => {
-			console.log("socket connect");
-		});
-
-		this.socket.on("admin", msg => {
-			this.onMessage(msg);
-		});
-
-		this.socket.on("error", err => {
-			console.log(err);
-		});
-
-		this.socket.on("disconnect", () => {
-			console.log("disconnect connect");
-		});
+	created() {
+		// this.socket = io(`${socketUrl}?isAdmin=true&token=${this.token}`);
+		// this.socket.on("connect", () => {
+		// 	console.log("socket connect");
+		// });
+		// this.socket.on("admin", msg => {
+		// 	this.onMessage(msg);
+		// });
+		// this.socket.on("error", err => {
+		// 	console.log(err);
+		// });
+		// this.socket.on("disconnect", () => {
+		// 	console.log("disconnect connect");
+		// });
 	},
 
 	destroyed() {
-		this.socket.close();
+		if (this.socket) {
+			this.socket.close();
+		}
 	},
 
 	methods: {
@@ -342,7 +346,7 @@ export default {
 					order: "updateTime",
 					sort: "desc"
 				})
-				.then(async res => {
+				.then(res => {
 					this.session.list = res.list;
 					this.session.pagination = res.pagination;
 
@@ -411,7 +415,10 @@ export default {
 		scrollToBottom: debounce(function() {
 			this.$nextTick(() => {
 				if (this.$refs["scroller"]) {
-					this.$refs["scroller"].scrollTo(0, 999999);
+					this.$refs["scroller"].scrollTo({
+						top: 99999,
+						behavior: "smooth"
+					});
 				}
 			});
 		}, 300),
@@ -580,12 +587,14 @@ export default {
 				content
 			});
 
-			this.socket.emit(`user@${userId}`, {
-				contentType,
-				type: 0,
-				content: JSON.stringify(content),
-				sessionId: id
-			});
+			if (this.socket) {
+				this.socket.emit(`user@${userId}`, {
+					contentType,
+					type: 0,
+					content: JSON.stringify(content),
+					sessionId: id
+				});
+			}
 		},
 
 		/**
@@ -642,22 +651,22 @@ export default {
 </script>
 
 <style lang="scss">
-.chat-box__wrap {
-	height: 650px;
-	min-width: 1000px;
+.cl-chat__dialog {
 	margin-bottom: 0 !important;
+	min-width: 1000px;
 
 	.el-dialog__body {
-		height: calc(100% - 46px);
 		padding: 0;
+	}
 
+	&.is-fullscreen {
 		.cl-dialog__container {
-			height: 100%;
+			height: calc(100vh - 46px) !important;
 		}
 	}
 }
 
-.chat-box {
+.cl-chat {
 	display: flex;
 	height: 100%;
 	background-color: #f7f7f7;
@@ -673,7 +682,7 @@ export default {
 			padding: 10px;
 		}
 
-		ul {
+		&-list {
 			height: calc(100% - 52px);
 			overflow: auto;
 
@@ -684,14 +693,12 @@ export default {
 				border-left: 5px solid #fff;
 
 				.avatar {
-					height: 40px;
-					width: 40px;
 					margin-right: 12px;
 
 					img {
 						display: block;
-						height: 100%;
-						width: 100%;
+						height: 40px;
+						width: 40px;
 						border-radius: 3px;
 						background-color: #eee;
 					}
@@ -741,6 +748,11 @@ export default {
 				}
 			}
 		}
+
+		&-empty {
+			text-align: center;
+			margin-top: 10px;
+		}
 	}
 
 	&__detail {
@@ -779,6 +791,7 @@ export default {
 
 	&__opbar {
 		margin-bottom: 5px;
+
 		ul {
 			display: flex;
 			li {

+ 2 - 1
src/cool/modules/chat/components/index.js

@@ -1,3 +1,4 @@
 import Notice from "./notice";
+import Chat from "./chat";
 
-export default { Notice };
+export default { Notice, Chat };

+ 6 - 4
src/cool/modules/chat/components/message.vue

@@ -12,7 +12,7 @@
 
 			<div class="main">
 				<div class="avatar" @tap="toUserDetail(item)">
-					<el-image :src="item.avatarUrl"></el-image>
+					<img :src="item.avatarUrl" />
 				</div>
 
 				<div class="det">
@@ -185,11 +185,13 @@ export default {
 
 			.avatar {
 				flex-shrink: 0;
-				height: 40px;
-				width: 40px;
 
-				.el-image {
+				img {
+					display: block;
+					height: 40px;
+					width: 40px;
 					border-radius: 3px;
+					background-color: #fff;
 				}
 			}
 

+ 4 - 1
src/cool/modules/chat/service/message.js

@@ -1,6 +1,9 @@
 import { BaseService, Service, Permission } from "cl-admin";
 
-@Service("app/im/message")
+@Service({
+	namespace: "im/message",
+	mock: true
+})
 class ImMessage extends BaseService {
 	@Permission("read")
 	read(data) {

+ 4 - 1
src/cool/modules/chat/service/session.js

@@ -1,6 +1,9 @@
 import { BaseService, Service, Permission } from "cl-admin";
 
-@Service("app/im/session")
+@Service({
+	namespace: "im/session",
+	mock: true
+})
 class ImSession extends BaseService {
 	@Permission("unreadCount")
 	unreadCount() {

+ 3 - 0
src/main.js

@@ -9,6 +9,9 @@ import router from "@/router";
 // 缓存
 import store from "@/store";
 
+// mock
+import "@/mock";
+
 // 阻止显示生产模式的消息
 Vue.config.productionTip = false;
 

+ 75 - 0
src/mock/chat.js

@@ -0,0 +1,75 @@
+import Mock from "mockjs";
+
+Mock.mock("/im/session/page", "post", options => {
+	const { keyWord = "" } = JSON.parse(options.body);
+
+	const data = Mock.mock({
+		"list|20": [
+			{
+				id: "@id",
+				nickname: "@name",
+				createTime: "@datetime(yy-MM-dd HH:mm:ss)",
+				text: "@cparagraph(5)",
+				content() {
+					return JSON.stringify({ text: this.text });
+				},
+				"contentType|0-3": 0,
+				"serviceUnreadCount|0-10": 0,
+				headimgurl() {
+					return Mock.Random.image(
+						"40x40",
+						Mock.Random.color(),
+						"#FFF",
+						"png",
+						this.nickname[0]
+					);
+				}
+			}
+		]
+	});
+
+	return {
+		code: 1000,
+		data: {
+			list: data.list.filter(e => e.nickname.includes(keyWord)),
+			pagination: {}
+		}
+	};
+});
+
+Mock.mock("/im/session/unreadCount", "get", options => {
+	const data = Mock.mock({
+		"count|1-50": 1
+	});
+
+	return {
+		code: 1000,
+		data: data.count
+	};
+});
+
+Mock.mock("/im/message/page", "post", options => {
+	const data = Mock.mock({
+		"list|20": [
+			{
+				id: "@id",
+				nickname: "@name",
+				createTime: "@datetime",
+				text: "@cparagraph(1, 4)",
+				content() {
+					return JSON.stringify({ text: this.text });
+				},
+				contentType: 0,
+				"type|0-1": 1
+			}
+		]
+	});
+
+	return {
+		code: 1000,
+		data: {
+			list: data.list,
+			pagination: {}
+		}
+	};
+});

+ 1 - 0
src/mock/index.js

@@ -0,0 +1 @@
+import "./chat";