浏览代码

修复BUG,v-lemon-contextmenu支持左键触发

fan 4 年之前
父节点
当前提交
0e9504f9b4

文件差异内容过多而无法显示
+ 2416 - 3483
dist/index.common.js


文件差异内容过多而无法显示
+ 0 - 0
dist/index.css


文件差异内容过多而无法显示
+ 2416 - 3483
dist/index.umd.js


文件差异内容过多而无法显示
+ 0 - 0
dist/index.umd.min.js


+ 59 - 425
examples/App.vue

@@ -92,80 +92,8 @@
 
     <div style="display:flex;">
       <div>
-        <div class="title">插槽演示</div>
-        <div class="imui-center">
-          <lemon-imui
-            :user="user"
-            class="lemon-slot"
-            ref="SlotIMUI"
-            @pull-messages="handlePullMessages"
-            @message-click="handleMessageClick"
-            @change-contact="handleChangeContact"
-            @send="handleSend"
-            send-text="发送消息"
-            :send-key="e => e.ctrlKey == true"
-          >
-            <template #editor-footer>
-              按 ctrl 键发送消息
-            </template>
-            <template #cover>
-              <div class="cover">
-                <i class="lemon-icon-message"></i>
-                <p><b>自定义封面 Lemon</b> IMUI</p>
-              </div>
-            </template>
-            <template #message-title="contact">
-              <span>{{ contact.displayName }}</span>
-              <small class="more" @click="changeDrawer(contact, $refs.SlotIMUI)"
-                >{{
-                  ($refs.SlotIMUI
-                  ? $refs.SlotIMUI.drawerVisible
-                  : false)
-                    ? "关闭"
-                    : "打开"
-                }}抽屉</small
-              >
-            </template>
-            <template #message-after="message">
-              <span>未读</span>
-            </template>
-
-            <template #contact-info="contact">
-              自定义通讯录信息 {{ contact.displayName }}
-            </template>
-            <template #sidebar-message="contact">
-              <lemon-badge :count="contact.unread" style="width:100%">
-                <div>
-                  <p>
-                    <span>{{ contact.displayName }}</span>
-                  </p>
-                  <p
-                    class="lemon-contact__content"
-                    style="height:18px;font-size:12px;color:#aaa;"
-                  >
-                    最新消息:
-                    <span v-html="contact.lastContent"></span>
-                  </p>
-                </div>
-              </lemon-badge>
-            </template>
-            <template #sidebar-contact="contact">
-              <span>{{ contact.displayName }}</span>
-            </template>
-            <template #sidebar-message-top>
-              <div class="bar">最新消息顶部</div>
-            </template>
-            <template #sidebar-contact-top>
-              <div class="bar">联系人顶部</div>
-            </template>
-            <template #sidebar-message-fixedtop>
-              <div class="bar">最新消息顶部 Fixed</div>
-            </template>
-            <template #sidebar-contact-fixedtop>
-              <div class="bar">联系人顶部 Fixed</div>
-            </template>
-          </lemon-imui>
-        </div>
+        <div class="title">自定义</div>
+        <div class="imui-center"><qq-imui>12312312</qq-imui></div>
       </div>
 
       <div style="margin:0 55px;">
@@ -1041,8 +969,11 @@ WebSocket.onmessage = function(event) {
 <script>
 import Vue from "vue";
 import LemonMessageVoice from "./lemon-message-voice";
+import QQIMUI from "./qq";
 import packageData from "../package.json";
+import EmojiData from "./database/emoji";
 Vue.component(LemonMessageVoice.name, LemonMessageVoice);
+Vue.component(QQIMUI.name, QQIMUI);
 
 const tip = `export default {
   //组件的name必须以lemonMessage开头,后面跟上 Message.type
@@ -1094,7 +1025,7 @@ const generateMessage = (toContactId = "", fromUser) => {
     fromUser = {
       id: "system",
       displayName: "系统测试",
-      avatar: "http://upload.qqbodys.com/allimg/1710/1035512943-0.jpg"
+      avatar: "http://upload.qqbodys.com/allimg/1710/1035512943-0.jpg",
     };
   }
   return {
@@ -1106,7 +1037,7 @@ const generateMessage = (toContactId = "", fromUser) => {
     //fileSize: 1231,
     //fileName: "asdasd.doc",
     toContactId,
-    fromUser
+    fromUser,
   };
 };
 
@@ -1122,17 +1053,17 @@ export default {
             const { IMUI, contact } = instance;
             IMUI.updateContact({
               id: contact.id,
-              lastContent: null
+              lastContent: null,
             });
             if (IMUI.currentContactId == contact.id) IMUI.changeContact(null);
             hide();
-          }
+          },
         },
         {
-          text: "设置备注和标签"
+          text: "设置备注和标签",
         },
         {
-          text: "投诉"
+          text: "投诉",
         },
         {
           icon: "lemon-icon-message",
@@ -1148,7 +1079,7 @@ export default {
                 </span>
               </div>
             );
-          }
+          },
         },
         {
           click(e, instance, hide) {
@@ -1158,8 +1089,8 @@ export default {
             hide();
           },
           color: "red",
-          text: "删除好友"
-        }
+          text: "删除好友",
+        },
       ],
       contextmenu: [
         {
@@ -1188,7 +1119,7 @@ export default {
               ),
 
               toContactId: message.toContactId,
-              sendTime: getTime()
+              sendTime: getTime(),
             };
             IMUI.removeMessage(message.id);
             IMUI.appendMessage(data, true);
@@ -1197,34 +1128,34 @@ export default {
           visible: instance => {
             return instance.message.fromUser.id == this.user.id;
           },
-          text: "撤回消息"
+          text: "撤回消息",
         },
         {
           visible: instance => {
             return instance.message.fromUser.id != this.user.id;
           },
-          text: "举报"
+          text: "举报",
         },
         {
-          text: "转发"
+          text: "转发",
         },
         {
           visible: instance => {
             return instance.message.type == "text";
           },
-          text: "复制文字"
+          text: "复制文字",
         },
         {
           visible: instance => {
             return instance.message.type == "image";
           },
-          text: "下载图片"
+          text: "下载图片",
         },
         {
           visible: instance => {
             return instance.message.type == "file";
           },
-          text: "下载文件"
+          text: "下载文件",
         },
         {
           click: (e, instance, hide) => {
@@ -1234,8 +1165,8 @@ export default {
           },
           icon: "lemon-icon-folder",
           color: "red",
-          text: "删除"
-        }
+          text: "删除",
+        },
       ],
       tip: tip,
       packageData,
@@ -1246,8 +1177,8 @@ export default {
       user: {
         id: "1",
         displayName: "June",
-        avatar: ""
-      }
+        avatar: "",
+      },
     };
   },
   mounted() {
@@ -1258,7 +1189,7 @@ export default {
       index: "[1]群组",
       unread: 0,
       lastSendTime: 1566047865417,
-      lastContent: "2"
+      lastContent: "2",
     };
     const contactData2 = {
       id: "contact-2",
@@ -1273,7 +1204,7 @@ export default {
       },
       lastSendTime: 1345209465000,
       lastContent: "12312",
-      unread: 2
+      unread: 2,
     };
     const contactData3 = {
       id: "contact-3",
@@ -1282,7 +1213,7 @@ export default {
       index: "T",
       unread: 32,
       lastSendTime: 3,
-      lastContent: "你好123"
+      lastContent: "你好123",
     };
     const contactData4 = {
       id: "contact-4",
@@ -1292,12 +1223,12 @@ export default {
       index: "",
       unread: 1,
       lastSendTime: 3,
-      lastContent: "吃饭了嘛"
+      lastContent: "吃饭了嘛",
     };
 
     const { IMUI } = this.$refs;
     setTimeout(() => {
-      IMUI.changeContact('contact-1');
+      IMUI.changeContact("contact-1");
     }, 500);
 
     IMUI.setLastContentRender("event", message => {
@@ -1307,17 +1238,17 @@ export default {
     let contactList = [
       { ...contactData1 },
       { ...contactData2 },
-      { ...contactData3 }
+      { ...contactData3 },
       //...Array(100).fill(contactData1)
     ];
 
     IMUI.initContacts(contactList);
     IMUI.initMenus([
       {
-        name: "messages"
+        name: "messages",
       },
       {
-        name: "contacts"
+        name: "contacts",
       },
       {
         name: "custom1",
@@ -1357,7 +1288,7 @@ export default {
             </div>
           );
         },
-        isBottom: true
+        isBottom: true,
       },
       {
         name: "custom2",
@@ -1369,19 +1300,19 @@ export default {
         render: menu => {
           return <i class="lemon-icon-group" />;
         },
-        isBottom: true
-      }
+        isBottom: true,
+      },
     ]);
 
     IMUI.initEditorTools([
       {
-        name: "emoji"
+        name: "emoji",
       },
       {
-        name: "uploadFile"
+        name: "uploadFile",
       },
       {
-        name: "uploadImage"
+        name: "uploadImage",
       },
       {
         name: "test1",
@@ -1390,7 +1321,7 @@ export default {
         },
         render: () => {
           return <span>Excel</span>;
-        }
+        },
       },
       {
         name: "test1",
@@ -1399,7 +1330,7 @@ export default {
         },
         render: () => {
           return <span>重制工具栏</span>;
-        }
+        },
       },
       {
         name: "test2",
@@ -1410,302 +1341,10 @@ export default {
         },
         render: () => {
           return <b>···</b>;
-        }
-      }
-    ]);
-    let emojiData = [
-      {
-        label: "表情",
-        children: [
-          {
-            name: "1f600",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f600.png"
-          },
-          {
-            name: "1f62c",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f62c.png"
-          },
-          {
-            name: "1f601",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f601.png"
-          },
-          {
-            name: "1f602",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f602.png"
-          },
-          {
-            name: "1f923",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f923.png"
-          },
-          {
-            name: "1f973",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f973.png"
-          },
-          {
-            name: "1f603",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f603.png"
-          },
-          {
-            name: "1f604",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f604.png"
-          },
-          {
-            name: "1f605",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f605.png"
-          },
-          {
-            name: "1f606",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f606.png"
-          },
-          {
-            name: "1f607",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f607.png"
-          },
-          {
-            name: "1f609",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f609.png"
-          },
-          {
-            name: "1f60a",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f60a.png"
-          },
-          {
-            name: "1f642",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f642.png"
-          },
-          {
-            name: "1f643",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f643.png"
-          },
-          {
-            name: "1263a",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/263a.png"
-          },
-          {
-            name: "1f60b",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f60b.png"
-          },
-          {
-            name: "1f60c",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f60c.png"
-          },
-          {
-            name: "1f60d",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f60d.png"
-          },
-          {
-            name: "1f970",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f970.png"
-          },
-          {
-            name: "1f618",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f618.png"
-          },
-          {
-            name: "1f617",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f617.png"
-          },
-          {
-            name: "1f619",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f619.png"
-          },
-          {
-            name: "1f61a",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f61a.png"
-          },
-          {
-            name: "1f61c",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f61c.png"
-          },
-          {
-            name: "1f92a",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f92a.png"
-          },
-          {
-            name: "1f928",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f928.png"
-          },
-          {
-            name: "1f9d0",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f9d0.png"
-          },
-          {
-            name: "1f61d",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f61d.png"
-          },
-          {
-            name: "1f61b",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f61b.png"
-          },
-          {
-            name: "1f911",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f911.png"
-          },
-          {
-            name: "1f913",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f913.png"
-          },
-          {
-            name: "1f60e",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f60e.png"
-          },
-          {
-            name: "1f929",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f929.png"
-          },
-          {
-            name: "1f921",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f921.png"
-          },
-          {
-            name: "1f920",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f920.png"
-          },
-          {
-            name: "1f917",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f917.png"
-          },
-          {
-            name: "1f60f",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f60f.png"
-          },
-          {
-            name: "1f636",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f636.png"
-          },
-          {
-            name: "1f610",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f610.png"
-          },
-          {
-            name: "1f611",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f611.png"
-          },
-          {
-            name: "1f612",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f612.png"
-          },
-          {
-            name: "1f644",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f644.png"
-          },
-          {
-            name: "1f914",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f914.png"
-          },
-          {
-            name: "1f925",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f925.png"
-          },
-          {
-            name: "1f92d",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f92d.png"
-          },
-          {
-            name: "1f92b",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f92b.png"
-          },
-          {
-            name: "1f92c",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f92c.png"
-          },
-          {
-            name: "1f92f",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f92f.png"
-          },
-          {
-            name: "1f633",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f633.png"
-          },
-          {
-            name: "1f61e",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f61e.png"
-          },
-          {
-            name: "1f61f",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f61f.png"
-          },
-          {
-            name: "1f620",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f620.png"
-          },
-          {
-            name: "1f621",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f621.png"
-          }
-        ]
+        },
       },
-      {
-        label: "收藏",
-        children: [
-          {
-            name: "1f62c",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f62c.png"
-          },
-          {
-            name: "1f621",
-            title: "微笑",
-            src: "https://twemoji.maxcdn.com/2/72x72/1f621.png"
-          }
-        ]
-      }
-    ];
-    IMUI.initEmoji(emojiData);
+    ]);
+    IMUI.initEmoji(EmojiData);
 
     IMUI.setLastContentRender("voice", message => {
       return <span>[语音]</span>;
@@ -1714,13 +1353,8 @@ export default {
     const { SimpleIMUI } = this.$refs;
     contactData1.id = "11";
     SimpleIMUI.initContacts([contactData1]);
-    SimpleIMUI.initEmoji(emojiData);
+    SimpleIMUI.initEmoji(EmojiData);
     SimpleIMUI.changeContact(contactData1.id);
-
-    const { SlotIMUI } = this.$refs;
-    contactData3.id = "333";
-    SlotIMUI.initContacts([contactData4, contactData3]);
-    SlotIMUI.initEmoji(emojiData);
   },
   methods: {
     changeTheme() {
@@ -1739,13 +1373,13 @@ export default {
         instance.updateMessage({
           id: message.id,
           status: "going",
-          content: "正在重新发送消息..."
+          content: "正在重新发送消息...",
         });
         setTimeout(() => {
           instance.updateMessage({
             id: message.id,
             status: "succeed",
-            content: "发送成功"
+            content: "发送成功",
           });
         }, 2000);
       }
@@ -1780,7 +1414,7 @@ export default {
           status: "succeed",
           type: "file",
           fileName: "被修改成文件了.txt",
-          fileSize: "4200000"
+          fileSize: "4200000",
         };
         if (message.type == "event") {
           update.fromUser = this.user;
@@ -1800,7 +1434,7 @@ export default {
         params1: "1",
         params2: "2",
         toContactId: "contact-1",
-        fromUser: this.user
+        fromUser: this.user,
       };
       IMUI.appendMessage(message, true);
     },
@@ -1810,7 +1444,7 @@ export default {
       const message = generateMessage("contact-3");
       message.fromUser = {
         ...message.fromUser,
-        ...this.user
+        ...this.user,
       };
       IMUI.appendMessage(message, true);
     },
@@ -1831,7 +1465,7 @@ export default {
           </span>
         ),
         toContactId: "contact-3",
-        sendTime: getTime()
+        sendTime: getTime(),
       };
       IMUI.appendMessage(message, true);
     },
@@ -1841,7 +1475,7 @@ export default {
         unread: 10,
         displayName: generateRandWord(),
         lastSendTime: getTime(),
-        lastContent: "修改昵称为随机字母"
+        lastContent: "修改昵称为随机字母",
       });
     },
     changeDrawer(contact, instance) {
@@ -1863,14 +1497,14 @@ export default {
               <p>{contact.displayName}</p>
             </div>
           );
-        }
+        },
       });
     },
     handleChangeContact(contact, instance) {
       console.log("Event:change-contact");
       instance.updateContact({
         id: contact.id,
-        unread: 0
+        unread: 0,
       });
       instance.closeDrawer();
     },
@@ -1884,7 +1518,7 @@ export default {
       const otheruser = {
         id: contact.id,
         displayName: contact.displayName,
-        avatar: contact.avatar
+        avatar: contact.avatar,
       };
       setTimeout(() => {
         const messages = [
@@ -1897,8 +1531,8 @@ export default {
           generateMessage(instance.currentContactId, otheruser),
           {
             ...generateMessage(instance.currentContactId, this.user),
-            ...{ status: "failed" }
-          }
+            ...{ status: "failed" },
+          },
         ];
         let isEnd = false;
         if (
@@ -1913,8 +1547,8 @@ export default {
     handleChangeMenu() {
       console.log("Event:change-menu");
     },
-    openCustomContainer() {}
-  }
+    openCustomContainer() {},
+  },
 };
 </script>
 

+ 147 - 0
examples/database/contacts.js

@@ -0,0 +1,147 @@
+export default [
+  {
+    id: 1,
+    displayName: "像梦一样自由",
+    avatar: "https://p.qqan.com/up/2020-2/2020022821001845128.jpg",
+    index: "X",
+    unread: 0,
+    lastSendTime: 1566047865417,
+    lastContent: "你开心吗",
+  },
+  {
+    id: 2,
+    displayName: "梦醒时分、",
+    avatar: "https://p.qqan.com/up/2021-1/20211301122243621.jpg",
+    index: "M",
+    unread: 0,
+    lastSendTime: 1566047865417,
+    lastContent: "",
+  },
+  {
+    id: 3,
+    displayName: "凌云",
+    avatar: "https://p.qqan.com/up/2021-1/2021129102387841.jpg",
+    index: "L",
+    unread: 0,
+    lastSendTime: 1566047865417,
+    lastContent: "",
+  },
+  {
+    id: 4,
+    displayName: "小郭",
+    avatar: "https://p.qqan.com/up/2021-1/2021122135507881.jpg",
+    index: "X",
+    unread: 0,
+    lastSendTime: 1566047865417,
+    lastContent: "",
+  },
+  {
+    id: 5,
+    displayName: "杨玉泉",
+    avatar: "https://p.qqan.com/up/2021-1/20211211131598147.jpg",
+    index: "Y",
+    unread: 0,
+    lastSendTime: 1566047865417,
+    lastContent: "",
+  },
+  {
+    id: 6,
+    displayName: "森系Style",
+    avatar: "https://p.qqan.com/up/2021-1/2021113104111220.jpg",
+    index: "S",
+    unread: 0,
+    lastSendTime: 1566047865417,
+    lastContent: "",
+  },
+  {
+    id: 7,
+    displayName: "霸王花",
+    avatar: "https://p.qqan.com/up/2021-1/20211411391666.jpg",
+    index: "B",
+    unread: 0,
+    lastSendTime: 1566047865417,
+    lastContent: "你怎么还不睡呀?",
+  },
+  {
+    id: 8,
+    displayName: "曾平",
+    avatar: "https://p.qqan.com/up/2020-12/202012291044425822.jpg",
+    index: "Z",
+    unread: 0,
+    lastSendTime: 1566047865417,
+    lastContent: "",
+  },
+  {
+    id: 9,
+    displayName: "淡然",
+    avatar: "https://p.qqan.com/up/2020-12/202012141813343503.jpg",
+    index: "D",
+    unread: 0,
+    lastSendTime: 1566047865417,
+    lastContent: "",
+  },
+  {
+    id: 10,
+    displayName: "叶子。",
+    avatar: "https://p.qqan.com/up/2021-1/20211301122243621.jpg",
+    index: "Y",
+    unread: 0,
+    lastSendTime: 1566047865417,
+    lastContent: "",
+  },
+  {
+    id: 11,
+    displayName: "土豆",
+    avatar: "https://p.qqan.com/up/2020-12/202012111157268739.jpg",
+    index: "T",
+    unread: 0,
+    lastSendTime: 1566047865417,
+    lastContent: "",
+  },
+  {
+    id: 12,
+    displayName: "清沫",
+    avatar: "https://p.qqan.com/up/2020-12/202012415467996.jpg",
+    index: "Q",
+    unread: 0,
+    lastSendTime: 1566047865417,
+    lastContent: "",
+  },
+  {
+    id: 13,
+    displayName: "Lemon-imui交流群",
+    avatar: "https://p.qqan.com/up/2020-11/20201127157109035.jpg",
+    index: "L",
+    isGroup: true,
+    unread: 0,
+    lastSendTime: 1566047865417,
+    lastContent: "这个咋处理啊?",
+  },
+  {
+    id: 14,
+    displayName: "系统通知",
+    avatar: "https://p.qqan.com/up/2020-6/2020061117234279854.jpg",
+    index: "[1]系統通知",
+    unread: 0,
+    lastSendTime: 1566047865417,
+    lastContent: "宁静致远通过了你的好友请求",
+    renderContainer() {
+      return (
+        <div style="padding:15px;">
+          <div>宁静致远通过了你的好友请求</div>
+          <div>宁静致远通过了你的好友请求</div>
+          <div>宁静致远通过了你的好友请求</div>
+        </div>
+      );
+    },
+  },
+  {
+    id: 15,
+    displayName: "宁静致远。",
+    avatar: "https://p.qqan.com/up/2020-6/2020060308522797777.jpg",
+    index: "N",
+    unread: 0,
+    lastSendTime: 1566047865417,
+    lastContent: "",
+  },
+];

+ 292 - 0
examples/database/emoji.js

@@ -0,0 +1,292 @@
+export default [
+  {
+    label: "表情",
+    children: [
+      {
+        name: "1f600",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f600.png",
+      },
+      {
+        name: "1f62c",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f62c.png",
+      },
+      {
+        name: "1f601",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f601.png",
+      },
+      {
+        name: "1f602",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f602.png",
+      },
+      {
+        name: "1f923",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f923.png",
+      },
+      {
+        name: "1f973",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f973.png",
+      },
+      {
+        name: "1f603",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f603.png",
+      },
+      {
+        name: "1f604",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f604.png",
+      },
+      {
+        name: "1f605",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f605.png",
+      },
+      {
+        name: "1f606",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f606.png",
+      },
+      {
+        name: "1f607",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f607.png",
+      },
+      {
+        name: "1f609",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f609.png",
+      },
+      {
+        name: "1f60a",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f60a.png",
+      },
+      {
+        name: "1f642",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f642.png",
+      },
+      {
+        name: "1f643",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f643.png",
+      },
+      {
+        name: "1263a",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/263a.png",
+      },
+      {
+        name: "1f60b",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f60b.png",
+      },
+      {
+        name: "1f60c",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f60c.png",
+      },
+      {
+        name: "1f60d",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f60d.png",
+      },
+      {
+        name: "1f970",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f970.png",
+      },
+      {
+        name: "1f618",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f618.png",
+      },
+      {
+        name: "1f617",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f617.png",
+      },
+      {
+        name: "1f619",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f619.png",
+      },
+      {
+        name: "1f61a",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f61a.png",
+      },
+      {
+        name: "1f61c",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f61c.png",
+      },
+      {
+        name: "1f92a",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f92a.png",
+      },
+      {
+        name: "1f928",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f928.png",
+      },
+      {
+        name: "1f9d0",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f9d0.png",
+      },
+      {
+        name: "1f61d",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f61d.png",
+      },
+      {
+        name: "1f61b",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f61b.png",
+      },
+      {
+        name: "1f911",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f911.png",
+      },
+      {
+        name: "1f913",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f913.png",
+      },
+      {
+        name: "1f60e",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f60e.png",
+      },
+      {
+        name: "1f929",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f929.png",
+      },
+      {
+        name: "1f921",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f921.png",
+      },
+      {
+        name: "1f920",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f920.png",
+      },
+      {
+        name: "1f917",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f917.png",
+      },
+      {
+        name: "1f60f",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f60f.png",
+      },
+      {
+        name: "1f636",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f636.png",
+      },
+      {
+        name: "1f610",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f610.png",
+      },
+      {
+        name: "1f611",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f611.png",
+      },
+      {
+        name: "1f612",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f612.png",
+      },
+      {
+        name: "1f644",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f644.png",
+      },
+      {
+        name: "1f914",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f914.png",
+      },
+      {
+        name: "1f925",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f925.png",
+      },
+      {
+        name: "1f92d",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f92d.png",
+      },
+      {
+        name: "1f92b",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f92b.png",
+      },
+      {
+        name: "1f92c",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f92c.png",
+      },
+      {
+        name: "1f92f",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f92f.png",
+      },
+      {
+        name: "1f633",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f633.png",
+      },
+      {
+        name: "1f61e",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f61e.png",
+      },
+      {
+        name: "1f61f",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f61f.png",
+      },
+      {
+        name: "1f620",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f620.png",
+      },
+      {
+        name: "1f621",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f621.png",
+      },
+    ],
+  },
+  {
+    label: "收藏",
+    children: [
+      {
+        name: "1f62c",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f62c.png",
+      },
+      {
+        name: "1f621",
+        title: "微笑",
+        src: "https://twemoji.maxcdn.com/2/72x72/1f621.png",
+      },
+    ],
+  },
+];

+ 156 - 0
examples/database/messages.js

@@ -0,0 +1,156 @@
+import ContactsData from "./contacts";
+import UserData from "./user";
+const generateRandId = () => {
+  return Math.random()
+    .toString(36)
+    .substr(-8);
+};
+const getContact = id => {
+  const data = ContactsData.find(contact => contact.id == id);
+  return { id: data.id, avatar: data.avatar, displayName: data.displayName };
+};
+export default {
+  1: [
+    {
+      id: generateRandId(),
+      status: "succeed",
+      type: "text",
+      sendTime: 1566047865417,
+      content: "问你件事",
+      toContactId: 1,
+      fromUser: UserData,
+    },
+    {
+      id: generateRandId(),
+      status: "succeed",
+      type: "text",
+      sendTime: 1566047865417,
+      content: "啥子。",
+      toContactId: 1,
+      fromUser: getContact(1),
+    },
+    {
+      id: generateRandId(),
+      status: "succeed",
+      type: "text",
+      sendTime: 1566047865417,
+      content: "为什么",
+      toContactId: 1,
+      fromUser: UserData,
+    },
+    {
+      id: generateRandId(),
+      status: "succeed",
+      type: "text",
+      sendTime: 1566047865417,
+      content: "你穿了高跟鞋还这么矮",
+      toContactId: 1,
+      fromUser: UserData,
+    },
+    {
+      id: generateRandId(),
+      status: "succeed",
+      type: "text",
+      sendTime: 1566047865417,
+      content: "因为我矮啊。[!1f600][!1f600][!1f600]",
+      toContactId: 1,
+      fromUser: getContact(1),
+    },
+    {
+      id: generateRandId(),
+      status: "succeed",
+      type: "text",
+      sendTime: 1566047865417,
+      content: "你开心吗",
+      toContactId: 1,
+      fromUser: getContact(1),
+    },
+  ],
+  2: [],
+  3: [],
+  4: [],
+  5: [],
+  6: [],
+  7: [],
+  8: [],
+  9: [],
+  10: [],
+  11: [],
+  12: [],
+  13: [
+    {
+      id: generateRandId(),
+      status: "succeed",
+      type: "text",
+      sendTime: 1566047865417,
+      content: "我是测试时候看到的",
+      toContactId: 1,
+      fromUser: getContact(4),
+    },
+    {
+      id: generateRandId(),
+      status: "succeed",
+      type: "text",
+      sendTime: 1566047865417,
+      content: "上新版本了,玩玩",
+      toContactId: 1,
+      fromUser: getContact(4),
+    },
+    {
+      id: generateRandId(),
+      status: "succeed",
+      type: "text",
+      sendTime: 1566047865417,
+      content: "项目内没有搞这个",
+      toContactId: 1,
+      fromUser: getContact(4),
+    },
+    {
+      id: generateRandId(),
+      status: "succeed",
+      type: "text",
+      sendTime: 1566047865417,
+      content: "@awesome 最新的,不然哪有这功能",
+      toContactId: 1,
+      fromUser: getContact(5),
+    },
+    {
+      id: generateRandId(),
+      status: "succeed",
+      type: "text",
+      sendTime: 1566047865417,
+      content: "其实是跟你的遮罩层有冲突",
+      toContactId: 1,
+      fromUser: getContact(4),
+    },
+    {
+      id: generateRandId(),
+      status: "succeed",
+      type: "text",
+      sendTime: 1566047865417,
+      content: "自己修改index哈",
+      toContactId: 1,
+      fromUser: UserData,
+    },
+    {
+      id: generateRandId(),
+      status: "succeed",
+      type: "text",
+      sendTime: 1566047865417,
+      content: "你们升级到最近版了吗?",
+      toContactId: 1,
+      fromUser: getContact(6),
+    },
+    {
+      id: generateRandId(),
+      status: "succeed",
+      type: "text",
+      sendTime: 1566047865417,
+      content: "wo 现在用的142",
+      toContactId: 1,
+      fromUser: getContact(7),
+    },
+  ],
+  14: [],
+  15: [],
+};

+ 5 - 0
examples/database/user.js

@@ -0,0 +1,5 @@
+export default {
+  id: 1000,
+  avatar: "https://p.qqan.com/up/2018-4/15244505348390471.jpg",
+  displayName: "野火。",
+};

文件差异内容过多而无法显示
+ 0 - 0
examples/dist/css/index.4c3079e2.css


文件差异内容过多而无法显示
+ 0 - 0
examples/dist/css/index.ef88e8c1.css


+ 1 - 1
examples/dist/index.html

@@ -1 +1 @@
-<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>Lemon IMUI</title><link href=css/index.4c3079e2.css rel=preload as=style><link href=js/chunk-vendors.2abee366.js rel=preload as=script><link href=js/index.eb3bbc56.js rel=preload as=script><link href=css/index.4c3079e2.css rel=stylesheet></head><body><noscript><strong>We're sorry but flat-im doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=js/chunk-vendors.2abee366.js></script><script src=js/index.eb3bbc56.js></script></body></html>
+<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><link rel=icon href=favicon.ico><title>Lemon IMUI</title><link href=css/index.ef88e8c1.css rel=preload as=style><link href=js/chunk-vendors.e4810482.js rel=preload as=script><link href=js/index.1eaba05d.js rel=preload as=script><link href=css/index.ef88e8c1.css rel=stylesheet></head><body><noscript><strong>We're sorry but flat-im doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=js/chunk-vendors.e4810482.js></script><script src=js/index.1eaba05d.js></script></body></html>

文件差异内容过多而无法显示
+ 0 - 0
examples/dist/js/chunk-vendors.2abee366.js


文件差异内容过多而无法显示
+ 0 - 0
examples/dist/js/chunk-vendors.e4810482.js


文件差异内容过多而无法显示
+ 0 - 0
examples/dist/js/index.1eaba05d.js


文件差异内容过多而无法显示
+ 0 - 0
examples/dist/js/index.eb3bbc56.js


+ 200 - 0
examples/qq/index.vue

@@ -0,0 +1,200 @@
+<script>
+import UserData from "../database/user";
+import ContactsData from "../database/contacts";
+import MessagesData from "../database/messages";
+import EmojiData from "../database/emoji";
+export default {
+  name: "QqImui",
+  components: {},
+  data() {
+    return {};
+  },
+  render() {
+    return (
+      <div class="qq-lemon-imui">
+        <lemon-imui
+          class="lemon-slot"
+          user={UserData}
+          width={900}
+          avatar-cricle
+          hide-message-time
+          ref="IMUI"
+          on={{
+            "pull-messages": this.handlePullMessages,
+            "change-contact": this.handleChangeContact,
+            send: this.handleSend,
+          }}
+          scopedSlots={{
+            "message-title": contact => {
+              return (
+                <div>
+                  <div style="display:flex;justify-content:space-between">
+                    <span>{contact.displayName}</span>
+                    <span style="font-size:12px;">
+                      <span>打开抽屉:</span>
+                      <span
+                        class="cursor:pointer;"
+                        on-click={() => this.openDrawer("right")}
+                      >
+                        右侧 |{" "}
+                      </span>
+                      <span
+                        class="cursor:pointer;"
+                        on-click={() => this.openDrawer("rightInside")}
+                      >
+                        右侧内部 |{" "}
+                      </span>
+                      <span
+                        class="cursor:pointer;"
+                        on-click={() => this.openDrawer("center")}
+                      >
+                        居中
+                      </span>
+                    </span>
+                  </div>
+                  {contact.isGroup && (
+                    <div class="slot-group-menu">
+                      <span>聊天</span>
+                      <span>公告</span>
+                      <span>相册</span>
+                      <span>文件</span>
+                      <span>活动</span>
+                      <span
+                        v-lemon-contextmenu_click={[
+                          {
+                            text: "操作一",
+                          },
+                          {
+                            text: "操作二",
+                          },
+                        ]}
+                      >
+                        设置(左键弹出菜单)
+                      </span>
+                    </div>
+                  )}
+                </div>
+              );
+            },
+            "sidebar-contact-fixedtop": contact => {
+              return (
+                <div class="slot-contact-fixedtop">
+                  <input class="slot-search" placeholder="搜索通讯录" />
+                </div>
+              );
+            },
+            "message-side": contact => {
+              if (contact.isGroup) {
+                return (
+                  <div class="slot-group">
+                    <div class="slot-group-title">群通知</div>
+                    <div class="slot-group-notice">
+                      进群请改备注,格式,工作地点-姓名,请大家配合谢谢
+                    </div>
+                    <div class="slot-group-title">群成员</div>
+                    <div class="slot-group-panel">
+                      <input class="slot-search" placeholder="搜索群成员" />
+                      <div class="slot-group-member">河南-96-十里青山</div>
+                      <div class="slot-group-member">河南-96-十里青山</div>
+                      <div class="slot-group-member">河南-96-十里青山</div>
+                      <div class="slot-group-member">河南-96-十里青山</div>
+                      <div class="slot-group-member">河南-96-十里青山</div>
+                      <div class="slot-group-member">河南-96-十里青山</div>
+                      <div class="slot-group-member">河南-96-十里青山</div>
+                      <div class="slot-group-member">河南-96-十里青山</div>
+                      <div class="slot-group-member">河南-96-十里青山</div>
+                      <div class="slot-group-member">河南-96-十里青山</div>
+                    </div>
+                  </div>
+                );
+              }
+            },
+          }}
+        />
+      </div>
+    );
+  },
+  computed: {},
+  watch: {},
+  created() {},
+  mounted() {
+    const IMUI = this.$refs.IMUI;
+    //contactData3.id = "333";
+    IMUI.initContacts(ContactsData);
+    IMUI.changeContact(13);
+    //console.log(IMUI.getContacts());
+    // SlotIMUI.initEmoji(emojiData);
+  },
+  methods: {
+    openDrawer(position) {
+      const IMUI = this.$refs.IMUI;
+      const params = {
+        position,
+        render: contact => {
+          return (
+            <div style="padding:15px">
+              <h5>{contact.displayName}</h5>
+              <span on-click={IMUI.closeDrawer}>关闭抽屉</span>
+            </div>
+          );
+        },
+      };
+      if (position == "center") {
+        params.width = "50%";
+        params.height = "50%";
+      } else if (position == "rightInside") {
+        params.height = "90%";
+        params.offsetY = "10%";
+      }
+      IMUI.openDrawer(params);
+    },
+    handlePullMessages(contact, next) {
+      next(MessagesData[contact.id], true);
+    },
+    handleChangeContact() {},
+    handleSend(message, next, file) {
+      console.log(message, next, file);
+      setTimeout(() => {
+        next();
+      }, 1000);
+    },
+  },
+};
+</script>
+<style lang="stylus">
+.slot-group
+  width 170px
+  border-left 1px solid #ddd;
+  height 100%
+  box-sizing border-box
+  padding 10px
+  .slot-search
+    margin 5px 0
+.slot-group-notice
+  color #999
+  padding 6px 0
+  font-size 12px
+.slot-group-title
+  font-size 12px
+.slot-group-member
+  font-size 12px
+  line-height 18px
+.slot-group-menu span
+  display inline-block
+  cursor pointer
+  color #888
+  margin 4px 10px 0 0
+  border-bottom 2px solid transparent;
+  &:hover
+    color #000
+    border-color #333
+.slot-contact-fixedtop
+  padding 10px
+  border-bottom 1px solid #ddd
+.slot-search
+  width 100%
+  box-sizing border-box
+  font-size 14px
+  border 1px solid #bbb
+  padding 5px 10px
+</style>

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "lemon-imui",
-  "version": "1.6.7",
+  "version": "1.6.8",
   "main": "dist/index.umd.min.js",
   "description": "基于 VUE2.0 的 IM 聊天组件",
   "homepage": "http://june000.gitee.io/lemon-im/",

+ 9 - 8
packages/components/contact.vue

@@ -9,8 +9,8 @@ export default {
       from: "IMUI",
       default() {
         return this;
-      }
-    }
+      },
+    },
   },
   data() {
     return {};
@@ -22,19 +22,20 @@ export default {
       type: Function,
       default(val) {
         return timeFormat(val, isToday(val) ? "h:i" : "y/m/d");
-      }
-    }
+      },
+    },
   },
   render() {
     return (
       <div
         class={["lemon-contact", { "lemon-contact--name-center": this.simple }]}
+        title={this.contact.displayName}
         on-click={e => this._handleClick(e, this.contact)}
       >
         {useScopedSlot(
           this.$scopedSlots.default,
           this._renderInner(),
-          this.contact
+          this.contact,
         )}
       </div>
     );
@@ -71,13 +72,13 @@ export default {
               )}
             </p>
           )}
-        </div>
+        </div>,
       ];
     },
     _handleClick(e, data) {
       this.$emit("click", data);
-    }
-  }
+    },
+  },
 };
 </script>
 <style lang="stylus">

+ 86 - 81
packages/components/index.vue

@@ -5,7 +5,7 @@ import contextmenu from "../directives/contextmenu";
 import {
   DEFAULT_MENUS,
   DEFAULT_MENU_LASTMESSAGES,
-  DEFAULT_MENU_CONTACTS
+  DEFAULT_MENU_CONTACTS,
 } from "utils/constant";
 import lastContentRender from "../lastContentRender";
 
@@ -26,25 +26,25 @@ export default {
   name: "LemonImui",
   provide() {
     return {
-      IMUI: this
+      IMUI: this,
     };
   },
   props: {
     width: {
       type: [String, Number],
-      default: 850
+      default: 850,
     },
     height: {
       type: [String, Number],
-      default: 580
+      default: 580,
     },
     theme: {
       type: String,
-      default: "default"
+      default: "default",
     },
     simple: {
       type: Boolean,
-      default: false
+      default: false,
     },
     /**
      * 消息时间格式化规则
@@ -59,7 +59,7 @@ export default {
      */
     hideDrawer: {
       type: Boolean,
-      default: true
+      default: true,
     },
     /**
      * 是否隐藏导航按钮上的头像
@@ -83,8 +83,8 @@ export default {
       type: Object,
       default: () => {
         return {};
-      }
-    }
+      },
+    },
   },
   data() {
     this.CacheContactContainer = new MemoryCache();
@@ -98,7 +98,7 @@ export default {
       activeSidebar: DEFAULT_MENU_LASTMESSAGES,
       contacts: [],
       menus: [],
-      editorTools: []
+      editorTools: [],
     };
   },
 
@@ -108,7 +108,7 @@ export default {
       this._renderSidebarMessage(),
       this._renderSidebarContact(),
       this._renderContainer(),
-      this._renderDrawer()
+      this._renderDrawer(),
     ]);
   },
   created() {
@@ -133,10 +133,10 @@ export default {
         return a2.lastSendTime - a1.lastSendTime;
       });
       return data;
-    }
+    },
   },
   watch: {
-    activeSidebar() {}
+    activeSidebar() {},
   },
   methods: {
     _menuIsContacts() {
@@ -154,10 +154,10 @@ export default {
           sendTime: new Date().getTime(),
           toContactId: this.currentContactId,
           fromUser: {
-            ...this.user
-          }
+            ...this.user,
+          },
         },
-        ...message
+        ...message,
       };
     },
     /**
@@ -169,14 +169,14 @@ export default {
           id: message.toContactId,
           unread: "+1",
           lastSendTime: message.sendTime,
-          lastContent: this.lastContentRender(message)
+          lastContent: this.lastContentRender(message),
         });
       } else {
         this._addMessage(message, message.toContactId, 1);
         const updateContact = {
           id: message.toContactId,
           lastContent: this.lastContentRender(message),
-          lastSendTime: message.sendTime
+          lastSendTime: message.sendTime,
         };
         if (message.toContactId == this.currentContactId) {
           if (scrollToBottom == true) {
@@ -197,7 +197,7 @@ export default {
           next();
           this.updateMessage(Object.assign(message, replaceMessage));
         },
-        file
+        file,
       );
     },
     _handleSend(text) {
@@ -207,7 +207,7 @@ export default {
         this.updateContact({
           id: message.toContactId,
           lastContent: this.lastContentRender(message),
-          lastSendTime: message.sendTime
+          lastSendTime: message.sendTime,
         });
         this.CacheDraft.remove(message.toContactId);
       });
@@ -218,14 +218,14 @@ export default {
       if (imageTypes.includes(file.type)) {
         joinMessage = {
           type: "image",
-          content: URL.createObjectURL(file)
+          content: URL.createObjectURL(file),
         };
       } else {
         joinMessage = {
           type: "file",
           fileSize: file.size,
           fileName: file.name,
-          content: ""
+          content: "",
         };
       }
       const message = this._createMessage(joinMessage);
@@ -236,10 +236,10 @@ export default {
           this.updateContact({
             id: message.toContactId,
             lastContent: this.lastContentRender(message),
-            lastSendTime: message.sendTime
+            lastSendTime: message.sendTime,
           });
         },
-        file
+        file,
       );
     },
     _emitPullMessages(next) {
@@ -247,7 +247,7 @@ export default {
       this.$emit(
         "pull-messages",
         this.currentContact,
-        (messages, isEnd = false) => {
+        (messages = [], isEnd = false) => {
           this._addMessage(messages, this.currentContactId, 0);
           this.CacheMessageLoaded.set(this.currentContactId, isEnd);
           if (isEnd == true) this.$refs.messages.loaded();
@@ -255,7 +255,7 @@ export default {
           this._changeContactLock = false;
           next(isEnd);
         },
-        this
+        this,
       );
     },
     clearCacheContainer(name) {
@@ -267,14 +267,14 @@ export default {
         <div
           style={{
             width: toPx(this.width),
-            height: toPx(this.height)
+            height: toPx(this.height),
           }}
           ref="wrapper"
           class={[
             "lemon-wrapper",
             `lemon-wrapper--theme-${this.theme}`,
             { "lemon-wrapper--simple": this.simple },
-            this.drawerVisible && "lemon-wrapper--drawer-show"
+            this.drawerVisible && "lemon-wrapper--drawer-show",
           ]}
         >
           {children}
@@ -316,7 +316,7 @@ export default {
           <div
             class={[
               "lemon-menu__item",
-              { "lemon-menu__item--active": this.activeSidebar == name }
+              { "lemon-menu__item--active": this.activeSidebar == name },
             ]}
             on-click={() => {
               funCall(click, () => {
@@ -332,7 +332,7 @@ export default {
       });
       return {
         top,
-        bottom
+        bottom,
       };
     },
     _renderSidebarMessage() {
@@ -343,22 +343,26 @@ export default {
             return this._renderContact(
               {
                 contact,
-                timeFormat: this.contactTimeFormat
+                timeFormat: this.contactTimeFormat,
               },
               () => this.changeContact(contact.id),
-              this.$scopedSlots["sidebar-message"]
+              this.$scopedSlots["sidebar-message"],
             );
-          })
+          }),
         ],
         DEFAULT_MENU_LASTMESSAGES,
-        useScopedSlot(this.$scopedSlots["sidebar-message-fixedtop"], null, this)
+        useScopedSlot(
+          this.$scopedSlots["sidebar-message-fixedtop"],
+          null,
+          this,
+        ),
       );
     },
     _renderContact(props, onClick, slot) {
       const {
         click: customClick,
         renderContainer,
-        id: contactId
+        id: contactId,
       } = props.contact;
       const click = () => {
         funCall(customClick, () => {
@@ -366,7 +370,7 @@ export default {
           this._customContainerReady(
             renderContainer,
             this.CacheContactContainer,
-            contactId
+            contactId,
           );
         });
       };
@@ -374,13 +378,13 @@ export default {
       return (
         <lemon-contact
           class={{
-            "lemon-contact--active": this.currentContactId == props.contact.id
+            "lemon-contact--active": this.currentContactId == props.contact.id,
           }}
           v-lemon-contextmenu_contact={this.contactContextmenu}
           props={props}
           on-click={click}
           scopedSlots={{ default: slot }}
-        ></lemon-contact>
+        />
       );
     },
     _renderSidebarContact() {
@@ -398,20 +402,24 @@ export default {
               this._renderContact(
                 {
                   contact: contact,
-                  simple: true
+                  simple: true,
                 },
                 () => {
                   this.changeContact(contact.id);
                 },
-                this.$scopedSlots["sidebar-contact"]
-              )
+                this.$scopedSlots["sidebar-contact"],
+              ),
             ];
             prevIndex = contact.index;
             return node;
-          })
+          }),
         ],
         DEFAULT_MENU_CONTACTS,
-        useScopedSlot(this.$scopedSlots["sidebar-contact-fixedtop"], null, this)
+        useScopedSlot(
+          this.$scopedSlots["sidebar-contact-fixedtop"],
+          null,
+          this,
+        ),
       );
     },
     _renderSidebar(children, name, fixedtop) {
@@ -429,7 +437,7 @@ export default {
     _renderDrawer() {
       return this._menuIsMessages() && this.currentContactId ? (
         <div class="lemon-drawer" ref="drawer">
-          {renderDrawerContent()}
+          {renderDrawerContent(this.currentContact)}
           {useScopedSlot(this.$scopedSlots.drawer, "", this.currentContact)}
         </div>
       ) : (
@@ -450,7 +458,7 @@ export default {
         nodes.push(
           <div class={cls} v-show={show}>
             {this.CacheContactContainer.get(name)}
-          </div>
+          </div>,
         );
       }
       for (const name in this.CacheMenuContainer.get()) {
@@ -460,7 +468,7 @@ export default {
             v-show={this.activeSidebar == name && !this.currentIsDefSidebar}
           >
             {this.CacheMenuContainer.get(name)}
-          </div>
+          </div>,
         );
       }
 
@@ -475,7 +483,7 @@ export default {
               <div class="lemon-container__displayname">
                 {curact.displayName}
               </div>,
-              curact
+              curact,
             )}
           </div>
           <div class="lemon-vessel">
@@ -499,19 +507,15 @@ export default {
               />
             </div>
             <div class="lemon-vessel__right">
-              {useScopedSlot(
-                this.$scopedSlots["message-side"],
-                null,
-                curact
-              )}
+              {useScopedSlot(this.$scopedSlots["message-side"], null, curact)}
             </div>
           </div>
-        </div>
+        </div>,
       );
       nodes.push(
         <div class={cls} v-show={!curact.id && this.currentIsDefSidebar}>
           {this.$slots.cover}
-        </div>
+        </div>,
       );
       nodes.push(
         <div
@@ -528,7 +532,7 @@ export default {
                   if (isEmpty(curact.lastContent)) {
                     this.updateContact({
                       id: curact.id,
-                      lastContent: " "
+                      lastContent: " ",
                     });
                   }
                   this.changeContact(curact.id, DEFAULT_MENU_LASTMESSAGES);
@@ -537,9 +541,9 @@ export default {
                 发送消息
               </lemon-button>
             </div>,
-            curact
+            curact,
           )}
-        </div>
+        </div>,
       );
       return nodes;
     },
@@ -549,14 +553,14 @@ export default {
     _addContact(data, t) {
       const type = {
         0: "unshift",
-        1: "push"
+        1: "push",
       }[t];
       this.contacts[type](data);
     },
     _addMessage(data, contactId, t) {
       const type = {
         0: "unshift",
-        1: "push"
+        1: "push",
       }[t];
       if (!Array.isArray(data)) data = [data];
       allMessages[contactId] = allMessages[contactId] || [];
@@ -573,7 +577,9 @@ export default {
     lastContentRender(message) {
       if (!isFunction(lastContentRender[message.type])) {
         console.error(
-          `not found '${message.type}' of the latest message renderer,try to use ‘setLastContentRender()’`
+          `not found '${
+            message.type
+          }' of the latest message renderer,try to use ‘setLastContentRender()’`,
         );
         return "";
       }
@@ -615,13 +621,13 @@ export default {
       if (isEmpty(contact)) return false;
       this.CacheDraft.set(contactId, {
         editorValue: editorValue,
-        lastContent: contact.lastContent
+        lastContent: contact.lastContent,
       });
       this.updateContact({
         id: contactId,
         lastContent: `<span style="color:red;">[草稿]</span><span>${this.lastContentRender(
-          { type: "text", content: editorValue }
-        )}</span>`
+          { type: "text", content: editorValue },
+        )}</span>`,
       });
     },
     /**
@@ -632,7 +638,7 @@ export default {
       if (draft) {
         this.updateContact({
           id: contactId,
-          lastContent: draft.lastContent
+          lastContent: draft.lastContent,
         });
         this.CacheDraft.remove(contactId);
       }
@@ -696,7 +702,7 @@ export default {
       const message = this.findMessage(messageId);
       if (!message) return false;
       const index = allMessages[message.toContactId].findIndex(
-        ({ id }) => id == messageId
+        ({ id }) => id == messageId,
       );
       allMessages[message.toContactId].splice(index, 1);
       return true;
@@ -711,7 +717,7 @@ export default {
       let historyMessage = this.findMessage(message.id);
       if (!historyMessage) return false;
       historyMessage = Object.assign(historyMessage, message, {
-        toContactId: historyMessage.toContactId
+        toContactId: historyMessage.toContactId,
       });
       return true;
     },
@@ -726,7 +732,7 @@ export default {
         const components = this.$refs.messages.$refs.message;
         if (components) {
           const messageComponent = components.find(
-            com => com.$attrs.message.id == messageId
+            com => com.$attrs.message.id == messageId,
           );
           if (messageComponent) messageComponent.$forceUpdate();
         }
@@ -782,7 +788,7 @@ export default {
           render: menu => {
             return <i class="lemon-icon-message" />;
           },
-          isBottom: false
+          isBottom: false,
         },
         {
           name: DEFAULT_MENU_CONTACTS,
@@ -792,14 +798,14 @@ export default {
           render: menu => {
             return <i class="lemon-icon-addressbook" />;
           },
-          isBottom: false
-        }
+          isBottom: false,
+        },
       ];
       let menus = [];
       if (Array.isArray(data)) {
         const indexMap = {
           messages: 0,
-          contacts: 1
+          contacts: 1,
         };
         const indexKeys = Object.keys(indexMap);
         menus = data.map(item => {
@@ -807,7 +813,7 @@ export default {
             return {
               ...defaultMenus[indexMap[item.name]],
               ...item,
-              ...{ renderContainer: null }
+              ...{ renderContainer: null },
             };
           }
 
@@ -815,7 +821,7 @@ export default {
             this._customContainerReady(
               item.renderContainer,
               this.CacheMenuContainer,
-              item.name
+              item.name,
             );
           }
 
@@ -859,10 +865,10 @@ export default {
             index: "",
             unread: 0,
             lastSendTime: "",
-            lastContent: ""
+            lastContent: "",
           },
-          contact
-        )
+          contact,
+        ),
       );
       return true;
     },
@@ -893,7 +899,7 @@ export default {
         }
         this.$set(this.contacts, index, {
           ...this.contacts[index],
-          ...data
+          ...data,
         });
       }
     },
@@ -1000,8 +1006,8 @@ export default {
     },
     closeDrawer() {
       this.drawerVisible = false;
-    }
-  }
+    },
+  },
 };
 </script>
 <style lang="stylus">
@@ -1093,7 +1099,7 @@ bezier = cubic-bezier(0.645, 0.045, 0.355, 1)
     height 100%
     flex 1
   +e(right)
-    flex 0
+    flex none
 +b(lemon-messages)
   flex 1
   height auto
@@ -1102,7 +1108,6 @@ bezier = cubic-bezier(0.645, 0.045, 0.355, 1)
   top 0
   overflow hidden
   background #f6f6f6
-  transition width .4s bezier
   z-index 11
   display none
 +b(lemon-wrapper)

+ 26 - 23
packages/components/message/basic.vue

@@ -7,8 +7,8 @@ export default {
       from: "IMUI",
       default() {
         return this;
-      }
-    }
+      },
+    },
   },
   props: {
     contextmenu: Array,
@@ -16,21 +16,22 @@ export default {
       type: Object,
       default: () => {
         return {};
-      }
+      },
     },
     timeFormat: {
       type: Function,
-      default: () => ""
+      default: () => "",
     },
     reverse: Boolean,
     hideName: Boolean,
-    hideTime: Boolean
+    hideTime: Boolean,
   },
   data() {
     return {};
   },
   render() {
     const { fromUser, status, sendTime } = this.message;
+    const hideTitle = this.hideName == true && this.hideTime == true;
     return (
       <div
         class={[
@@ -38,8 +39,8 @@ export default {
           `lemon-message--status-${status}`,
           {
             "lemon-message--reverse": this.reverse,
-            "lemon-message--hide-name": this.hideName
-          }
+            "lemon-message--hide-title": hideTitle,
+          },
         ]}
       >
         <div class="lemon-message__avatar">
@@ -54,14 +55,16 @@ export default {
         </div>
         <div class="lemon-message__inner">
           <div class="lemon-message__title">
-            <span
-              on-click={e => {
-                this._emitClick(e, "displayName");
-              }}
-            >
-              {fromUser.displayName}
-            </span>
-            {this.hideTime == true && (
+            {this.hideName == false && (
+              <span
+                on-click={e => {
+                  this._emitClick(e, "displayName");
+                }}
+              >
+                {fromUser.displayName}
+              </span>
+            )}
+            {this.hideTime == false && (
               <span
                 class="lemon-message__time"
                 on-click={e => {
@@ -86,7 +89,7 @@ export default {
               {useScopedSlot(
                 this.IMUI.$scopedSlots["message-after"],
                 null,
-                this.message
+                this.message,
               )}
             </div>
             <div
@@ -101,7 +104,7 @@ export default {
                 title="重发消息"
                 style={{
                   color: "#ff2525",
-                  cursor: "pointer"
+                  cursor: "pointer",
                 }}
               />
             </div>
@@ -117,8 +120,8 @@ export default {
   methods: {
     _emitClick(e, key) {
       this.IMUI.$emit("message-click", e, key, this.message, this.IMUI);
-    }
-  }
+    },
+  },
 };
 </script>
 <style lang="stylus">
@@ -223,12 +226,12 @@ arrow()
     +e(avatar)
       padding-right 0
       padding-left 10px
-  +m(hide-name)
+  +m(hide-title)
     +e(status)
-      top 3px
-    +e(title)
-      display none
+      top 5px
     +e(content)
+      position relative
+      top -5px
       &:before
         top 14px
 </style>

+ 14 - 14
packages/components/messages.vue

@@ -9,26 +9,26 @@ export default {
     hideName: Boolean,
     //是否隐藏显示消息时间
     hideTime: Boolean,
-    reverseUserId: String,
+    reverseUserId: [String, Number],
     timeRange: {
       type: Number,
-      default: 1
+      default: 1,
     },
     timeFormat: {
       type: Function,
       default(val) {
         return hoursTimeFormat(val);
-      }
+      },
     },
     messages: {
       type: Array,
-      default: () => []
-    }
+      default: () => [],
+    },
   },
   data() {
     return {
       _loading: false,
-      _loadend: false
+      _loadend: false,
     };
   },
   render() {
@@ -37,7 +37,7 @@ export default {
         <div
           class={[
             "lemon-messages__load",
-            `lemon-messages__load--${this._loadend ? "end" : "ing"}`
+            `lemon-messages__load--${this._loadend ? "end" : "ing"}`,
           ]}
         >
           {this._loadend ? this._renderLoadEnd() : this._renderLoading()}
@@ -57,10 +57,10 @@ export default {
                   message: {
                     id: "__time__",
                     type: "event",
-                    content: hoursTimeFormat(message.sendTime)
-                  }
+                    content: hoursTimeFormat(message.sendTime),
+                  },
                 }}
-              />
+              />,
             );
           }
 
@@ -73,7 +73,7 @@ export default {
               message: message,
               reverse: this.reverseUserId == message.fromUser.id,
               hideTime: this.hideTime,
-              hideName: this.hideName
+              hideName: this.hideName,
             };
           }
           node.push(<tagName ref="message" refInFor={true} attrs={attrs} />);
@@ -85,7 +85,7 @@ export default {
   computed: {
     msecRange() {
       return this.timeRange * 1000 * 60;
-    }
+    },
   },
   watch: {},
   methods: {
@@ -129,10 +129,10 @@ export default {
       if (wrap) {
         wrap.scrollTop = wrap.scrollHeight;
       }
-    }
+    },
   },
   created() {},
-  mounted() {}
+  mounted() {},
 };
 </script>
 <style lang="stylus">

+ 60 - 51
packages/directives/contextmenu.js

@@ -15,60 +15,69 @@ document.addEventListener("click", e => {
 export default {
   hide: hidePopover,
   bind(el, binding, vnode) {
-    el.addEventListener("contextmenu", e => {
-      if (isEmpty(binding.value) || !Array.isArray(binding.value)) return;
-      e.preventDefault();
-      LemonPopover.methods.closeAll();
-      let component;
-      let visibleItems = [];
-      if (binding.modifiers.message) component = vnode.context;
-      else if (binding.modifiers.contact) component = vnode.child;
-      if (!popover) {
-        popover = document.createElement("div");
-        popover.className = "lemon-contextmenu";
-        document.body.appendChild(popover);
-      }
-      popover.innerHTML = binding.value
-        .map(item => {
-          let visible;
-          if (isFunction(item.visible)) {
-            visible = item.visible(component);
-          } else {
-            visible = item.visible === undefined ? true : item.visible;
-          }
-
-          if (visible) {
-            visibleItems.push(item);
-            const icon = item.icon
-              ? `<i class="lemon-contextmenu__icon ${item.icon}"></i>`
-              : "";
-            return `<div style="color:${item.color}" title="${item.text}" class="lemon-contextmenu__item">${icon}<span>${item.text}</span></div>`;
-          }
-          return "";
-        })
-        .join("");
-      popover.style.top = `${e.pageY}px`;
-      popover.style.left = `${e.pageX}px`;
-
-      popover.childNodes.forEach((node, index) => {
-        const { click, render } = visibleItems[index];
-        node.addEventListener("click", e => {
-          e.stopPropagation();
-          if (isFunction(click)) click(e, component, hidePopover);
-        });
+    el.addEventListener(
+      binding.modifiers.click ? "click" : "contextmenu",
+      e => {
+        if (isEmpty(binding.value) || !Array.isArray(binding.value)) return;
+        e.stopPropagation();
+        e.preventDefault();
+        LemonPopover.methods.closeAll();
+        let component;
+        let visibleItems = [];
+        if (binding.modifiers.message) component = vnode.context;
+        else if (binding.modifiers.contact) component = vnode.child;
+        if (!popover) {
+          popover = document.createElement("div");
+          popover.className = "lemon-contextmenu";
+          document.body.appendChild(popover);
+        }
+        popover.innerHTML = binding.value
+          .map(item => {
+            let visible;
+            if (isFunction(item.visible)) {
+              visible = item.visible(component);
+            } else {
+              visible = item.visible === undefined ? true : item.visible;
+            }
 
-        if (isFunction(render)) {
-          const ins = Vue.extend({
-            render: h => {
-              return render(h, component, hidePopover);
+            if (visible) {
+              visibleItems.push(item);
+              const icon = item.icon
+                ? `<i class="lemon-contextmenu__icon ${item.icon}"></i>`
+                : "";
+              return `<div style="color:${item.color}" title="${
+                item.text
+              }" class="lemon-contextmenu__item">${icon}<span>${
+                item.text
+              }</span></div>`;
             }
+            return "";
+          })
+          .join("");
+        popover.style.top = `${e.pageY}px`;
+        popover.style.left = `${e.pageX}px`;
+
+        popover.childNodes.forEach((node, index) => {
+          const { click, render } = visibleItems[index];
+          node.addEventListener("click", e => {
+            e.stopPropagation();
+            if (isFunction(click)) click(e, component, hidePopover);
           });
-          const renderComponent = new ins().$mount();
-          node.querySelector("span").innerHTML = renderComponent.$el.outerHTML;
-        }
-      });
 
-      showPopover();
-    });
+          if (isFunction(render)) {
+            const ins = Vue.extend({
+              render: h => {
+                return render(h, component, hidePopover);
+              },
+            });
+            const renderComponent = new ins().$mount();
+            node.querySelector("span").innerHTML =
+              renderComponent.$el.outerHTML;
+          }
+        });
+
+        showPopover();
+      },
+    );
   },
 };

+ 11 - 0
prettier.config.js

@@ -0,0 +1,11 @@
+module.exports = {
+  printWidth: 80, // 每行代码长度(默认80)
+  tabWidth: 2, // 每个tab相当于多少个空格(默认2)
+  useTabs: false, // 是否使用tab进行缩进(默认false)
+  singleQuote: false, // 使用单引号(默认false)
+  semi: true, // 声明结尾使用分号(默认true)
+  trailingComma: 'all', // 多行使用拖尾逗号(默认none)
+  bracketSpacing: true, // 对象字面量的大括号间使用空格(默认true)
+  jsxBracketSameLine: false, // 多行JSX中的>放置在最后一行的结尾,而不是另起一行(默认false)
+  arrowParens: 'avoid', // 只有一个参数的箭头函数的参数是否带圆括号(默认avoid)
+};

部分文件因为文件数量过多而无法显示