INIT
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div class='lemon-contact-list'>
|
||||
<div class="lemon-contact-item"
|
||||
v-for="item in control.friends"
|
||||
:key="item.id"
|
||||
@click="control._changeMessageView(item)">
|
||||
{{item.diaplayName}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ContactList',
|
||||
inject: ["control"],
|
||||
data () {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
watch: {},
|
||||
methods: {
|
||||
|
||||
},
|
||||
created () {
|
||||
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang='scss'>
|
||||
@import '~styles/utils/index';
|
||||
@include b(contact-item) {
|
||||
padding: 10px 15px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: #000;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<div class=''>
|
||||
LemonGroupList
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'GroupList',
|
||||
components: {},
|
||||
data () {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
watch: {},
|
||||
methods: {
|
||||
|
||||
},
|
||||
created () {
|
||||
|
||||
},
|
||||
mounted () {
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang='scss'>
|
||||
</style>
|
||||
@@ -0,0 +1,226 @@
|
||||
<template>
|
||||
<el-container class="lemon-container lemon-container--center"
|
||||
ref="container">
|
||||
<el-aside class="lemon-sidebar"
|
||||
width="240px">
|
||||
<ul class="lemon-tab">
|
||||
<li v-for="item in tabList"
|
||||
:key="item.name"
|
||||
:tab-name="item.name"
|
||||
:class="['lemon-tab__item', item.name == currentTab && 'lemon-tab__item--active']"
|
||||
@click="tabChange(item.name)">
|
||||
<span :class="item.icon"></span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="lemon-tabview">
|
||||
<div class="lemon-tabview__item"
|
||||
v-for="item in tabList"
|
||||
v-show="item.name == currentTab"
|
||||
:key="item.name"
|
||||
:tabview-name="item.name">
|
||||
<component :is="item.componentName"
|
||||
@changeMessageView="_changeMessageView"></component>
|
||||
</div>
|
||||
</div>
|
||||
</el-aside>
|
||||
<el-container class="lemon-main">
|
||||
<el-header class="lemon-header"
|
||||
height="48px">
|
||||
宜宾劲越二手车市场(上江北) (500)
|
||||
</el-header>
|
||||
<el-main>
|
||||
<lemon-message-view></lemon-message-view>
|
||||
</el-main>
|
||||
<el-main>工具欄</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import LemonContactList from '../contact-list'
|
||||
import LemonGroupList from '../group-list'
|
||||
import LemonMessageList from '../message-list'
|
||||
import LemonMessageView from '../message-view'
|
||||
const components = {
|
||||
LemonContactList,
|
||||
LemonGroupList,
|
||||
LemonMessageList,
|
||||
LemonMessageView
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'LemonIm',
|
||||
components,
|
||||
provide () {
|
||||
return {
|
||||
control: this
|
||||
}
|
||||
},
|
||||
props: {
|
||||
friends: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
groups: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data () {
|
||||
this.tabList = [{
|
||||
name: 'message',
|
||||
icon: 'el-icon-s-comment',
|
||||
componentName: 'lemon-message-list',
|
||||
}, {
|
||||
name: 'contact',
|
||||
icon: 'el-icon-user-solid',
|
||||
componentName: 'lemon-contact-list',
|
||||
}, {
|
||||
name: 'group',
|
||||
icon: 'el-icon-message-solid',
|
||||
componentName: 'lemon-group-list',
|
||||
}]
|
||||
return {
|
||||
//当前会话对象的ID 根据 currentTab
|
||||
currentTab: 'contact',
|
||||
//当前聊天用户ID 根据聊天类型不一样 代表用户ID 群组ID 讨论组ID
|
||||
currentMessageId: null,
|
||||
//聊天视图是否加载中
|
||||
messageViewloading: true,
|
||||
//群聊天记录 groupId => [message]
|
||||
groupMessageData: {
|
||||
|
||||
},
|
||||
//好友聊天记录 friendId => [message]
|
||||
friendMessageData: {
|
||||
|
||||
}
|
||||
};
|
||||
},
|
||||
created () {
|
||||
},
|
||||
mounted () {
|
||||
this._initialize()
|
||||
},
|
||||
computed: {
|
||||
//聊天窗口中的数据
|
||||
messageViewData () {
|
||||
return this.friendMessageData[this.currentMessageId]
|
||||
}
|
||||
},
|
||||
watch: {},
|
||||
methods: {
|
||||
//左侧选项卡切换
|
||||
tabChange (name) {
|
||||
this.currentTab = name;
|
||||
this.findNode(`.lemon-tabview`).scrollTop = '0px'
|
||||
},
|
||||
//打开一个群组聊天窗口
|
||||
openGroupMessageView (group) {
|
||||
this._changeMessageViewComplete(group.id)
|
||||
},
|
||||
//打开普通聊天窗口
|
||||
openFriendMessageView (friend) {
|
||||
if (!this.friendMessageData[friend.id]) {
|
||||
this.$emit('pull-friends-message', friend, (newData) => {
|
||||
this._changeMessageViewComplete(friend.id)
|
||||
this.friendMessageData[friend.id] = [...newData]
|
||||
})
|
||||
} else {
|
||||
this._changeMessageViewComplete(friend.id)
|
||||
}
|
||||
},
|
||||
_changeMessageViewComplete (id) {
|
||||
this.messageViewloading = false
|
||||
this.currentMessageId = id
|
||||
},
|
||||
_changeMessageView (item) {
|
||||
this.openFriendMessageView(item)
|
||||
/**
|
||||
const resolve = (newData) => {
|
||||
this.messageViewloading = false
|
||||
this.
|
||||
}
|
||||
const reject = () => {
|
||||
this.messageViewloading = false
|
||||
}
|
||||
this.$emit('pullFriendsMessage', item, {
|
||||
resolve,
|
||||
reject
|
||||
})
|
||||
*/
|
||||
},
|
||||
_openMessageView () {
|
||||
|
||||
},
|
||||
findNode (query) {
|
||||
return this.$refs.container.$el.querySelector(query)
|
||||
},
|
||||
_initialize () {
|
||||
|
||||
},
|
||||
//将左侧的滚动条重置到顶部
|
||||
_tabviewScrollToTop () {
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='scss'>
|
||||
@import '~styles/utils/index';
|
||||
body {
|
||||
background: #8d9198;
|
||||
}
|
||||
|
||||
@include b(container) {
|
||||
width: 900px;
|
||||
height: 700px;
|
||||
@include m(center) {
|
||||
@include position-center(fixed);
|
||||
}
|
||||
}
|
||||
@include b(sidebar) {
|
||||
background: #1f252d;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: #fff;
|
||||
overflow: hidden;
|
||||
.el-tabs--card {
|
||||
.el-tabs__nav,
|
||||
.el-tabs__item,
|
||||
.el-tabs__header {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
@include b(tab) {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
@include e(item) {
|
||||
cursor: pointer;
|
||||
line-height: 56px;
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
transition: all ease-in-out 0.3s;
|
||||
font-size: 22px;
|
||||
color: #6d6d6d;
|
||||
@include m(active) {
|
||||
color: #11d207;
|
||||
}
|
||||
}
|
||||
}
|
||||
@include b(tabview) {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
@include scrollbar-dark();
|
||||
|
||||
@include e(item) {
|
||||
}
|
||||
}
|
||||
@include b(main) {
|
||||
background: #eceef1;
|
||||
}
|
||||
@include b(header) {
|
||||
line-height: 48px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<div class='lemon-message-list'>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'MessageList',
|
||||
inject: ["control"],
|
||||
data () {
|
||||
return {
|
||||
|
||||
};
|
||||
},
|
||||
created () {
|
||||
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
computed: {},
|
||||
watch: {},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='scss'>
|
||||
</style>
|
||||
@@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div class='lemon-message-view'
|
||||
v-loading="control.messageViewloading"
|
||||
element-loading-background="transparent">
|
||||
{{ control.messageViewData }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'MessageView',
|
||||
components: {},
|
||||
inject: ["control"],
|
||||
created () {
|
||||
|
||||
},
|
||||
mounted () {
|
||||
},
|
||||
computed: {},
|
||||
watch: {},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang='scss'>
|
||||
@import '~styles/utils/index';
|
||||
@include b(message-view) {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,24 @@
|
||||
import Vue from "vue";
|
||||
|
||||
import {
|
||||
Button,
|
||||
Icon,
|
||||
Row,
|
||||
Col,
|
||||
Container,
|
||||
Header,
|
||||
Main,
|
||||
Aside,
|
||||
Loading
|
||||
} from "element-ui";
|
||||
Vue.use(Button);
|
||||
Vue.use(Icon);
|
||||
Vue.use(Row);
|
||||
Vue.use(Col);
|
||||
Vue.use(Container);
|
||||
Vue.use(Header);
|
||||
Vue.use(Main);
|
||||
Vue.use(Aside);
|
||||
Vue.use(Loading.directive);
|
||||
|
||||
Vue.prototype.$loading = Loading.service;
|
||||
@@ -0,0 +1,19 @@
|
||||
import "./styles/common/index.scss";
|
||||
import "./element-ui";
|
||||
import Lemon from "./components/lemon";
|
||||
const version = "0.1";
|
||||
const components = [Lemon];
|
||||
const install = (Vue, opts = {}) => {
|
||||
components.forEach(component => {
|
||||
Vue.component(component.name, component);
|
||||
});
|
||||
};
|
||||
|
||||
if (typeof window !== "undefined" && window.Vue) {
|
||||
install(window.Vue);
|
||||
}
|
||||
|
||||
export default {
|
||||
version,
|
||||
install
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
*
|
||||
textMessage = {
|
||||
msgId: "msgid",
|
||||
status: "send_going",
|
||||
msgType: "text",
|
||||
isOutgoing: true,
|
||||
text: "text",
|
||||
fromUser: {},
|
||||
extras: {}// option
|
||||
}
|
||||
|
||||
imageMessage = {
|
||||
msgId: "msgid",
|
||||
msgType: "image",
|
||||
isOutGoing: true,
|
||||
mediaPath: "image path",
|
||||
fromUser: {},
|
||||
extras: {}// option
|
||||
}
|
||||
|
||||
videoMessage = { // video message
|
||||
msgId: "msgid",
|
||||
status: "send_failed",
|
||||
msgType: "video",
|
||||
isOutGoing: true,
|
||||
druation: number,
|
||||
mediaPath: "voice path",
|
||||
fromUser: {},
|
||||
extras: {}// option
|
||||
}
|
||||
customMessage = { // custom message
|
||||
msgId: "msgid",
|
||||
msgType: "custom",
|
||||
status: "send_failed",
|
||||
isOutgoing: true,
|
||||
contentSize: {height: 100, width: 100},
|
||||
content: "<h1>custom message will render html string</h1>", // content is html format, avoid to use <script>
|
||||
fromUser: {},
|
||||
extras: {}// option
|
||||
}
|
||||
eventMessage = { // event message
|
||||
msgId: "msgid",
|
||||
msgType: "event",
|
||||
text: "the event text"
|
||||
}
|
||||
|
||||
*/
|
||||
@@ -0,0 +1 @@
|
||||
@import './normalize';
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 基本样式入口
|
||||
*/
|
||||
|
||||
html {
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a,
|
||||
input,
|
||||
button,
|
||||
textarea {
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
textarea {
|
||||
font: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
@import './mixins';
|
||||
@import './var';
|
||||
@@ -0,0 +1,94 @@
|
||||
//BEM
|
||||
$fi-namespace: 'lemon';
|
||||
|
||||
@mixin b($block) {
|
||||
$selector: $fi-namespace + '-' + $block;
|
||||
.#{$selector} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
@mixin e($element) {
|
||||
$selector: '__' + $element;
|
||||
&#{$selector} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
@mixin m($modifier) {
|
||||
$selector: '--' + $modifier;
|
||||
&#{$selector} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin bem($block, $element: false, $modifier: false) {
|
||||
$selector: '.';
|
||||
@if $block {
|
||||
$selector: $fi-namespace + '-' + $block;
|
||||
}
|
||||
@if $element {
|
||||
$selector: $selector + '__' + $element;
|
||||
}
|
||||
@if $modifier {
|
||||
$selector: $selector + '--' + $modifier;
|
||||
}
|
||||
& .#{$selector} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin user-select($value) {
|
||||
-moz-user-select: $value;
|
||||
-webkit-user-select: $value;
|
||||
-ms-user-select: $value;
|
||||
}
|
||||
|
||||
@mixin scrollbar-theme($color: #1f252d, $background: #6d6d6d) {
|
||||
&::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
}
|
||||
&::-webkit-scrollbar-track-piece {
|
||||
background-color: $background;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb:vertical {
|
||||
height: 5px;
|
||||
background-color: $color;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb:horizontal {
|
||||
width: 5px;
|
||||
background-color: $background;
|
||||
}
|
||||
}
|
||||
@mixin scrollbar-dark() {
|
||||
@include scrollbar-theme();
|
||||
}
|
||||
@mixin scrollbar-light() {
|
||||
@include scrollbar-theme(#aaa, #fff);
|
||||
}
|
||||
|
||||
@mixin vertical-center {
|
||||
$selector: &;
|
||||
@at-root {
|
||||
#{$selector}::after {
|
||||
display: inline-block;
|
||||
content: '';
|
||||
height: 100%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
@mixin position-center($type: fixed) {
|
||||
position: $type;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
@mixin ellipsis {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@mixin arrow {
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
//$color-primary: #2977fa;
|
||||
$color-primary: #1bc213;
|
||||
$color-light: #fff;
|
||||
/* 头像 */
|
||||
$avatar-size: 45px;
|
||||
$avatar-radius: 50%;
|
||||
|
||||
/** 标题 */
|
||||
$title-background: $color-primary;
|
||||
$title-color: $color-light;
|
||||
$title-height: 44px;
|
||||
/* 气泡 */
|
||||
$bubble-background: $color-primary;
|
||||
$bubble-color: $color-light;
|
||||
$bubble-radius: 12px;
|
||||
|
||||
$bubble-self-background: #e7ebef;
|
||||
$bubble-self-color: #606d84;
|
||||
|
||||
/* 输入框 */
|
||||
$editor-textarea-height: 40px;
|
||||
$editor-textarea-radius: 5px;
|
||||
|
||||
$editor-submit-disable-color: #bcbcbc;
|
||||
$editor-submit-disable-background: #ebebeb;
|
||||
$editor-submit-radius: $editor-textarea-radius;
|
||||
/*
|
||||
$bubble-self-background: #e7ebef;
|
||||
$bubble-self-color: #3a465d;
|
||||
*/
|
||||
@@ -0,0 +1,3 @@
|
||||
export default function(a, b) {
|
||||
return a.filter(x => b.includes(x));
|
||||
}
|
||||
Reference in New Issue
Block a user