index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. <template>
  2. <div>
  3. <div class="imui-center qq-lemon-imui">
  4. <lemon-imui
  5. :width="windowWidth"
  6. :height="windowHeight"
  7. :user="user"
  8. ref="IMUI"
  9. :contextmenu="contextmenu"
  10. :contact-contextmenu="contactContextmenu"
  11. :theme="theme"
  12. :hide-menu="hideMenu"
  13. :hide-menu-avatar="hideMenuAvatar"
  14. :hide-message-name="hideMessageName"
  15. :hide-message-time="hideMessageTime"
  16. @change-menu="handleChangeMenu"
  17. @change-contact="handleChangeContact"
  18. @pull-messages="handlePullMessages"
  19. @message-click="handleMessageClick"
  20. @menu-avatar-click="handleMenuAvatarClick"
  21. @send="handleSend">
  22. <template #cover>
  23. <div class="cover">
  24. <i class="lemon-icon-message"></i>
  25. <p><b>自定义封面 Lemon</b> IMUI</p>
  26. </div>
  27. </template>
  28. <template #message-title="contact">
  29. <span>{{ contact.displayName }}</span>
  30. <small class="more" @click="changeDrawer(contact, $refs.IMUI)">{{
  31. ($refs.IMUI ? $refs.IMUI.drawerVisible : false) ? "关闭" : "打开"
  32. }}抽屉</small>
  33. <br />
  34. </template>
  35. </lemon-imui>
  36. </div>
  37. </div>
  38. </template>
  39. <script>
  40. import { getQrCode } from '@/api/qw/login';
  41. import { getDeviceId} from '@/api/qw/account';
  42. import Search from '@/components/HeaderSearch'
  43. import LemonMessageVoice from "@/components/LemonUI/components/lemon-message-voice";
  44. import ContactsData from "@/components/LemonUI/database/contacts";
  45. import MessagesData from "@/components/LemonUI/database/messages";
  46. import EmojiData from "@/components/LemonUI/database/emoji";
  47. import '@/components/LemonUI/index.css';
  48. const tip = `export default {
  49. //组件的name必须以lemonMessage开头,后面跟上 Message.type
  50. name: "lemonMessageVoice",
  51. inheritAttrs: false,
  52. //如果需要使用父组件的方法,可以使用注入。
  53. inject: ["IMUI"],
  54. render() {
  55. //lemon-message-basic 组件对气泡框、头像、事件等信息进行了公共的处理。
  56. return (
  57. <lemon-message-basic
  58. class="lemon-message-voice"
  59. props={{ ...this.$attrs }}
  60. scopedSlots={{
  61. content: props => {
  62. //返回HTML结构
  63. return <span>{props.content}&nbsp;🔈</span>
  64. }
  65. }}
  66. />
  67. );
  68. }
  69. };
  70. <style lang="stylus">
  71. .lemon-message.lemon-message-voice
  72. user-select none
  73. .lemon-message__content
  74. border 2px solid #000
  75. font-size 12px
  76. cursor pointer
  77. &::before
  78. display none
  79. </style>`;
  80. const getTime = () => {
  81. return new Date().getTime();
  82. };
  83. const generateRandId = () => {
  84. return Math.random()
  85. .toString(36)
  86. .substr(-8);
  87. };
  88. const generateRandWord = () => {
  89. return Math.random()
  90. .toString(36)
  91. .substr(2);
  92. };
  93. const generateMessage = (toContactId = "", fromUser) => {
  94. if (!fromUser) {
  95. fromUser = {
  96. id: "system",
  97. displayName: "系统测试",
  98. avatar: "http://upload.qqbodys.com/allimg/1710/1035512943-0.jpg",
  99. };
  100. }
  101. return {
  102. id: generateRandId(),
  103. status: "succeed",
  104. type: "text",
  105. sendTime: getTime(),
  106. content: generateRandWord(),
  107. //fileSize: 1231,
  108. //fileName: "asdasd.doc",
  109. toContactId,
  110. fromUser,
  111. };
  112. };
  113. export default {
  114. name: "qwChat",
  115. components: { LemonMessageVoice },
  116. data() {
  117. return {
  118. theme: "default",
  119. contactContextmenu: [
  120. {
  121. text: "删除该聊天",
  122. click: (e, instance, hide) => {
  123. const { IMUI, contact } = instance;
  124. IMUI.updateContact({
  125. id: contact.id,
  126. lastContent: null,
  127. });
  128. if (IMUI.currentContactId == contact.id) IMUI.changeContact(null);
  129. hide();
  130. },
  131. },
  132. {
  133. text: "设置备注和标签",
  134. },
  135. {
  136. text: "投诉",
  137. },
  138. {
  139. icon: "lemon-icon-message",
  140. text: "加入黑名单",
  141. render: (h, instance, hide) => {
  142. return (
  143. <div style="display:flex;justify-content:space-between;align-items:center;width:130px">
  144. <span>加入黑名单</span>
  145. <span>
  146. <input type="checkbox" id="switch" />
  147. <label id="switch-label" for="switch">
  148. Toggle
  149. </label>
  150. </span>
  151. </div>
  152. );
  153. },
  154. },
  155. {
  156. click(e, instance, hide) {
  157. const { IMUI, contact } = instance;
  158. IMUI.removeContact(contact.id);
  159. if (IMUI.currentContactId == contact.id) IMUI.changeContact(null);
  160. hide();
  161. },
  162. color: "red",
  163. text: "删除好友",
  164. },
  165. ],
  166. contextmenu: [
  167. {
  168. click: (e, instance, hide) => {
  169. const { IMUI, message } = instance;
  170. const data = {
  171. id: generateRandId(),
  172. type: "event",
  173. //使用 jsx 时 click必须使用箭头函数(使上下文停留在vue内)
  174. content: (
  175. <div>
  176. <span>
  177. 你撤回了一条消息{" "}
  178. <span
  179. v-show={message.type == "text"}
  180. style="color:#333;cursor:pointer"
  181. content={message.content}
  182. on-click={e => {
  183. IMUI.setEditorValue(e.target.getAttribute("content"));
  184. }}
  185. >
  186. 重新编辑
  187. </span>
  188. </span>
  189. </div>
  190. ),
  191. toContactId: message.toContactId,
  192. sendTime: getTime(),
  193. };
  194. IMUI.removeMessage(message.id);
  195. IMUI.appendMessage(data, true);
  196. hide();
  197. },
  198. visible: instance => {
  199. return instance.message.fromUser.id == this.user.id;
  200. },
  201. text: "撤回消息",
  202. },
  203. {
  204. visible: instance => {
  205. return instance.message.fromUser.id != this.user.id;
  206. },
  207. text: "举报",
  208. },
  209. {
  210. text: "转发",
  211. },
  212. {
  213. visible: instance => {
  214. return instance.message.type == "text";
  215. },
  216. text: "复制文字",
  217. },
  218. {
  219. visible: instance => {
  220. return instance.message.type == "image";
  221. },
  222. text: "下载图片",
  223. },
  224. {
  225. visible: instance => {
  226. return instance.message.type == "file";
  227. },
  228. text: "下载文件",
  229. },
  230. {
  231. click: (e, instance, hide) => {
  232. const { IMUI, message } = instance;
  233. IMUI.removeMessage(message.id);
  234. hide();
  235. },
  236. icon: "lemon-icon-folder",
  237. color: "red",
  238. text: "删除",
  239. },
  240. ],
  241. tip: tip,
  242. hideMenuAvatar: false,
  243. hideMenu: false,
  244. hideMessageName: false,
  245. hideMessageTime: true,
  246. user: {
  247. id: "1000",
  248. displayName: "June",
  249. avatar: "https://p.qqan.com/up/2018-4/15244505348390471.jpg",
  250. },
  251. windowWidth: document.documentElement.clientWidth*0.65, //实时屏幕宽度
  252. windowHeight: document.documentElement.clientHeight*0.7, //实时屏幕高度
  253. };
  254. },
  255. mounted() {
  256. const contactData1 = {
  257. id: "contact-1",
  258. displayName: "工作协作群",
  259. avatar: "http://upload.qqbodys.com/img/weixin/20170804/ji5qxg1am5ztm.jpg",
  260. index: "[1]群组",
  261. unread: 0,
  262. lastSendTime: 1566047865417,
  263. lastContent: "2",
  264. };
  265. const contactData2 = {
  266. id: "contact-2",
  267. displayName: "自定义内容",
  268. avatar: "http://upload.qqbodys.com/img/weixin/20170807/jibfvfd00npin.jpg",
  269. //index: "Z",
  270. click(next) {
  271. next();
  272. },
  273. renderContainer: () => {
  274. return <h1 style="text-indent:20px">自定义页面</h1>;
  275. },
  276. lastSendTime: 1345209465000,
  277. lastContent: "12312",
  278. unread: 2,
  279. };
  280. const contactData3 = {
  281. id: "contact-3",
  282. displayName: "铁牛",
  283. avatar: "http://upload.qqbodys.com/img/weixin/20170803/jiq4nzrkrnd0e.jpg",
  284. index: "T",
  285. unread: 32,
  286. lastSendTime: 3,
  287. lastContent: "你好123",
  288. };
  289. const contactData4 = {
  290. id: "contact-4",
  291. displayName: "如花",
  292. avatar:
  293. "https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=4275424924,2201401076&fm=111&gp=0.jpg",
  294. index: "",
  295. unread: 1,
  296. lastSendTime: 3,
  297. lastContent: "吃饭了嘛",
  298. };
  299. const { IMUI } = this.$refs;
  300. // setTimeout(() => {
  301. // var info = JSON.parse(
  302. // '{"type":0,"fromId":"666666666","toId":"8888888","fromName":"AAAA","toName":"BBBB","message":"您与客户[AAAA]建立连接","isError":false,"time":"2021-05-13T16:04:18.7158482+08:00","id":"666666666","avatar":"","displayName":"AAAA","unread":1,"lastSendTime":1620893058612,"lastContent":"您与客户[AAAA]建立连接"}',
  303. // );
  304. // console.log(info);
  305. // IMUI.appendContact(info);
  306. // setTimeout(() => {
  307. // var message = JSON.parse(
  308. // '{"type":"text","fromId":"666666666","toId":"8888888","fromName":"AAAA","toName":"BBBB","message":"我是消息123","isError":false,"time":"2021-05-13T16:04:19.0679223+08:00","id":"1426f5d4-0616-4d4b-93ac-499873f1b7ff","status":"succeed","sendTime":1620893057833,"content":"111","toContactId":"666666666","fromUser":{"type":0,"fromId":"666666666","toId":"8888888","fromName":"AAAA","toName":"BBBB","message":"您与客户[AAAA]建立连接","isError":false,"time":"2021-05-13T16:04:18.7158482+08:00","id":"666666666","avatar":"","displayName":"AAAA","unread":0,"lastSendTime":1620893058614,"lastContent":"[通知]","pageNum":0}}',
  309. // );
  310. // console.log("message", message);
  311. // IMUI.appendMessage(message);
  312. // }, 2000);
  313. // }, 1000);
  314. IMUI.setLastContentRender("event", message => {
  315. return `[自定义通知内容]`;
  316. });
  317. let contactList = [
  318. { ...contactData1 },
  319. { ...contactData2 },
  320. { ...contactData3 },
  321. ];
  322. //IMUI.initContacts(contactList);
  323. IMUI.initContacts(ContactsData);
  324. IMUI.initMenus([
  325. {
  326. name: "messages",
  327. },
  328. {
  329. name: "contacts",
  330. },
  331. {
  332. name: "custom1",
  333. title: "自定义按钮1",
  334. unread: 0,
  335. render: menu => {
  336. return <i class="lemon-icon-attah" />;
  337. },
  338. renderContainer: () => {
  339. return (
  340. <div class="article">
  341. <ul>
  342. <li class="article-item">
  343. <h2>人民日报谈网红带货:产品真的值得买吗?</h2>
  344. </li>
  345. <li class="article-item">
  346. 甘肃夏河县发生5.7级地震 暂未接到人员伤亡报告
  347. </li>
  348. <li class="article-item">
  349. 北方多地风力仍强沙尘相伴,东北内蒙古等地迎雨雪
  350. </li>
  351. <li class="article-item">
  352. 英货车案:越南警方采集疑死者家属DNA作比对
  353. </li>
  354. <li class="article-item">
  355. 知名连锁咖啡店的蛋糕吃出活虫 曝光内幕太震惊
  356. </li>
  357. </ul>
  358. <lemon-contact props={{ contact: contactData1 }} style="margin:20px"/>
  359. <lemon-contact props={{ contact: contactData3 }} style="margin:20px" />
  360. </div>
  361. );
  362. },
  363. isBottom: true,
  364. },
  365. {
  366. name: "custom2",
  367. title: "自定义按钮2",
  368. unread: 0,
  369. click: () => {
  370. alert("拦截导航点击事件");
  371. },
  372. render: menu => {
  373. return <i class="lemon-icon-group" />;
  374. },
  375. isBottom: true,
  376. },
  377. ]);
  378. IMUI.initEditorTools([
  379. {
  380. name: "emoji",
  381. },
  382. {
  383. name: "uploadFile",
  384. },
  385. {
  386. name: "uploadImage",
  387. },
  388. {
  389. name: "test1",
  390. click: () => {
  391. IMUI.$refs.editor.selectFile("application/vnd.ms-excel");
  392. },
  393. render: () => {
  394. return <span>Excel</span>;
  395. },
  396. },
  397. {
  398. name: "test1",
  399. click: () => {
  400. IMUI.initEditorTools([{ name: "uploadFile" }, { name: "emoji" }]);
  401. },
  402. render: () => {
  403. return <span>重制工具栏</span>;
  404. },
  405. },
  406. {
  407. name: "test2",
  408. isRight: true,
  409. title: "上传 Excel",
  410. click: () => {
  411. alert("点击了 ··· ");
  412. },
  413. render: () => {
  414. return <b>···</b>;
  415. },
  416. },
  417. ]);
  418. IMUI.initEmoji(EmojiData);
  419. IMUI.setLastContentRender("voice", message => {
  420. return <span>[语音]</span>;
  421. });
  422. setTimeout(() => {
  423. IMUI.changeContact("13");
  424. }, 500);
  425. },
  426. methods: {
  427. changeTheme() {
  428. this.theme = this.theme == "default" ? "blue" : "default";
  429. },
  430. scrollToTop() {
  431. document.body.scrollIntoView();
  432. },
  433. handleMenuAvatarClick() {
  434. console.log("Event:menu-avatar-click");
  435. },
  436. handleMessageClick(e, key, message, instance) {
  437. console.log("点击了消息", e, key, message);
  438. if (key == "status") {
  439. instance.updateMessage({
  440. id: message.id,
  441. status: "going",
  442. content: "正在重新发送消息...",
  443. });
  444. setTimeout(() => {
  445. instance.updateMessage({
  446. id: message.id,
  447. status: "succeed",
  448. content: "发送成功",
  449. });
  450. }, 2000);
  451. }
  452. },
  453. changeMenuAvatarVisible() {
  454. this.hideMenuAvatar = !this.hideMenuAvatar;
  455. },
  456. changeMenuVisible() {
  457. this.hideMenu = !this.hideMenu;
  458. },
  459. changeMessageNameVisible() {
  460. this.hideMessageName = !this.hideMessageName;
  461. },
  462. changeMessageTimeVisible() {
  463. this.hideMessageTime = !this.hideMessageTime;
  464. },
  465. removeMessage() {
  466. const { IMUI } = this.$refs;
  467. const messages = IMUI.getCurrentMessages();
  468. const id = messages[messages.length - 1].id;
  469. if (messages.length > 0) {
  470. IMUI.removeMessage(id);
  471. }
  472. },
  473. updateMessage() {
  474. const { IMUI } = this.$refs;
  475. const messages = IMUI.getCurrentMessages();
  476. const message = messages[messages.length - 1];
  477. if (messages.length > 0) {
  478. const update = {
  479. id: message.id,
  480. status: "succeed",
  481. type: "file",
  482. fileName: "被修改成文件了.txt",
  483. fileSize: "4200000",
  484. };
  485. if (message.type == "event") {
  486. update.fromUser = this.user;
  487. }
  488. IMUI.updateMessage(update);
  489. IMUI.messageViewToBottom();
  490. }
  491. },
  492. appendCustomMessage() {
  493. const { IMUI } = this.$refs;
  494. const message = {
  495. id: generateRandId(),
  496. status: "succeed",
  497. type: "voice",
  498. sendTime: getTime(),
  499. content: "语音消息",
  500. params1: "1",
  501. params2: "2",
  502. toContactId: "contact-1",
  503. fromUser: this.user,
  504. };
  505. IMUI.appendMessage(message, true);
  506. },
  507. appendMessage() {
  508. const { IMUI } = this.$refs;
  509. const contact = IMUI.currentContact;
  510. const message = generateMessage("contact-3");
  511. message.fromUser = {
  512. ...message.fromUser,
  513. ...this.user,
  514. };
  515. IMUI.appendMessage(message, true);
  516. console.log("🚀 ~ file: App.vue ~ line 1508 ~ appendMessage ~ message", message)
  517. },
  518. appendEventMessage() {
  519. const { IMUI } = this.$refs;
  520. const message = {
  521. id: generateRandId(),
  522. type: "event",
  523. content: (
  524. <span>
  525. 邀请你加入群聊{" "}
  526. <span
  527. style="color:#333;cursor:pointer"
  528. on-click={() => alert("OK")}
  529. >
  530. 接受
  531. </span>
  532. </span>
  533. ),
  534. toContactId: "contact-3",
  535. sendTime: getTime(),
  536. };
  537. IMUI.appendMessage(message, true);
  538. },
  539. updateContact() {
  540. this.$refs.IMUI.updateContact({
  541. id: "contact-3",
  542. unread: 10,
  543. displayName: generateRandWord(),
  544. lastSendTime: getTime(),
  545. lastContent: "修改昵称为随机字母",
  546. });
  547. },
  548. changeDrawer(contact, instance) {
  549. instance.changeDrawer({
  550. //width: 240,
  551. //height: "90%",
  552. //offsetX:0 ,
  553. //offsetY: ,
  554. //position: "center",
  555. // inside: true,
  556. // offsetX: -280,
  557. // offsetY: -100,
  558. render: () => {
  559. return (
  560. <div class="drawer-content">
  561. <p>
  562. <b>自定义抽屉</b>
  563. </p>
  564. <p>{contact.displayName}</p>
  565. </div>
  566. );
  567. },
  568. });
  569. },
  570. handleChangeContact(contact, instance) {
  571. console.log("Event:change-contact");
  572. instance.updateContact({
  573. id: contact.id,
  574. unread: 0,
  575. });
  576. instance.closeDrawer();
  577. },
  578. handleSend(message, next, file) {
  579. console.log(message, next, file);
  580. setTimeout(() => {
  581. next();
  582. }, 1000);
  583. },
  584. handlePullMessages(contact, next, instance) {
  585. const { IMUI } = this.$refs;
  586. setTimeout(() => {
  587. next(MessagesData[contact.id], true);
  588. }, 3000);
  589. return;
  590. const otheruser = {
  591. id: contact.id,
  592. displayName: contact.displayName,
  593. avatar: contact.avatar,
  594. };
  595. setTimeout(() => {
  596. const messages = [
  597. generateMessage(instance.currentContactId, this.user),
  598. generateMessage(instance.currentContactId, otheruser),
  599. generateMessage(instance.currentContactId, this.user),
  600. generateMessage(instance.currentContactId, otheruser),
  601. generateMessage(instance.currentContactId, this.user),
  602. generateMessage(instance.currentContactId, this.user),
  603. generateMessage(instance.currentContactId, otheruser),
  604. {
  605. ...generateMessage(instance.currentContactId, this.user),
  606. ...{ status: "failed" },
  607. },
  608. ];
  609. let isEnd = false;
  610. if (instance.getMessages(instance.currentContactId).length+messages.length >11)
  611. isEnd = true;
  612. next(messages, isEnd);
  613. }, 500);
  614. },
  615. handleChangeMenu() {
  616. console.log("Event:change-menu");
  617. },
  618. openCustomContainer() {
  619. },
  620. },
  621. };
  622. </script>
  623. <style lang="scss" scoped>
  624. .imui-center{
  625. margin-bottom:"60px";
  626. display: flex;
  627. align-items: center;
  628. justify-content: center;
  629. height: 80vh;
  630. }
  631. .lemon-wrapper{
  632. border:"1px solid #ddd";
  633. height: "60%" !important;
  634. }
  635. .lemon-drawer{
  636. border:"1px solid #ddd";
  637. border-left:"0";
  638. }
  639. .more {
  640. font-size: 12px;
  641. line-height: 24px;
  642. height: 24px;
  643. position: absolute;
  644. top: 14px;
  645. right: 14px;
  646. cursor: pointer;
  647. -webkit-user-select: none;
  648. -moz-user-select: none;
  649. -ms-user-select: none;
  650. user-select: none;
  651. color: #f1f1f1;
  652. display: inline-block;
  653. border-radius: 4px;
  654. background: #111;
  655. padding: 0 8px;
  656. }
  657. </style>