Index.vue 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949
  1. <template>
  2. <div class="chat-index">
  3. <!--左边选项-->
  4. <ul class="chat-menu">
  5. <li class="self">
  6. <img :src="userInfo.userimg">
  7. </li>
  8. <li :class="{active:chatTap=='dialog'}" @click="chatTap='dialog'">
  9. <Icon type="md-text" />
  10. <em v-if="unreadTotal > 0" class="chat-num">{{unreadTotal}}</em>
  11. </li>
  12. <li :class="{active:chatTap=='team'}" @click="chatTap='team'">
  13. <Icon type="md-person" />
  14. </li>
  15. </ul>
  16. <!--对话列表-->
  17. <ul v-if="chatTap=='dialog'" class="chat-user">
  18. <li class="sreach">
  19. <Input placeholder="搜索" prefix="ios-search"/>
  20. </li>
  21. <li v-for="(dialog, index) in dialogLists"
  22. :key="index"
  23. :class="{active:dialog.username==dialogTarget.username}"
  24. @click="openDialog(dialog)">
  25. <img :src="dialog.userimg">
  26. <div class="user-msg-box">
  27. <div class="user-msg-title">
  28. <span><user-view :username="dialog.username"/></span>
  29. <em>{{formatCDate(dialog.lastdate)}}</em>
  30. </div>
  31. <div class="user-msg-text">{{dialog.lasttext}}</div>
  32. </div>
  33. <em v-if="dialog.unread > 0" class="user-msg-num">{{dialog.unread}}</em>
  34. </li>
  35. <li v-if="dialogLists.length == 0" class="chat-none">{{dialogNoDataText}}</li>
  36. </ul>
  37. <!--联系人列表-->
  38. <ul v-else-if="chatTap=='team'" class="chat-team">
  39. <li class="sreach">
  40. <Input placeholder="搜索" prefix="ios-search"/>
  41. </li>
  42. <li v-for="(lists, key) in teamLists">
  43. <div class="team-label">{{key}}</div>
  44. <ul>
  45. <li v-for="(item, index) in lists" :key="index" @click="openDialog(item)">
  46. <img :src="item.userimg">
  47. <div class="team-username"><user-view :username="item.username"/></div>
  48. </li>
  49. </ul>
  50. </li>
  51. <li v-if="Object.keys(teamLists).length == 0" class="chat-none">{{teamNoDataText}}</li>
  52. </ul>
  53. <!--对话窗口-->
  54. <div v-if="chatTap=='dialog' && dialogTarget.username" class="chat-message">
  55. <div class="manage-title">
  56. <user-view :username="dialogTarget.username"/>
  57. <Dropdown class="manage-title-right" placement="bottom-end" trigger="click" transfer>
  58. <Icon type="ios-more"/>
  59. <DropdownMenu slot="list">
  60. <DropdownItem name="clear">清除聊天记录</DropdownItem>
  61. </DropdownMenu>
  62. </Dropdown>
  63. </div>
  64. <ScrollerY ref="manageLists" class="manage-lists" @on-scroll="messageListsScroll">
  65. <div ref="manageBody" class="manage-body">
  66. <chat-message v-for="(info, index) in messageLists" :key="index" :info="info"></chat-message>
  67. </div>
  68. <div class="manage-lists-message-new" v-if="messageNew > 0" @click="messageBottomGo(true)">有{{messageNew}}条新消息</div>
  69. </ScrollerY>
  70. <div class="manage-send" @click="clickDialog(dialogTarget.username)">
  71. <textarea ref="textarea" class="manage-input" v-model="messageText" placeholder="请输入要发送的消息" @keydown="messageSend($event)"></textarea>
  72. </div>
  73. <div class="manage-quick">
  74. <emoji-picker @emoji="messageInsertText" :search="messageEmojiSearch">
  75. <div slot="emoji-invoker" slot-scope="{ events: { click: clickEvent } }" @click.stop="clickEvent">
  76. <Icon class="quick-item" type="ios-happy-outline" />
  77. </div>
  78. <div slot="emoji-picker" slot-scope="{ emojis, insert, display }">
  79. <div class="emoji-box">
  80. <Input class="emoji-input" placeholder="搜索" v-model="messageEmojiSearch" prefix="ios-search"/>
  81. <div>
  82. <div v-for="(emojiGroup, category) in emojis" :key="category">
  83. <h5>{{ category }}</h5>
  84. <div class="emojis">
  85. <span v-for="(emoji, emojiName) in emojiGroup" :key="emojiName" @click="insert(emoji)" :title="emojiName">{{ emoji }}</span>
  86. </div>
  87. </div>
  88. </div>
  89. </div>
  90. </div>
  91. </emoji-picker>
  92. <Icon class="quick-item" type="ios-photos-outline" @click="$refs.messageUpload.handleClick()"/>
  93. <img-upload ref="messageUpload" class="message-upload" type="callback" @on-callback="messageInsertImage" num="3" :otherParams="{from:'chat'}"></img-upload>
  94. </div>
  95. </div>
  96. </div>
  97. </template>
  98. <style lang="scss">
  99. .chat-notice-box {
  100. display: flex;
  101. align-items: flex-start;
  102. .chat-notice-userimg {
  103. width: 42px;
  104. height: 42px;
  105. border-radius: 4px;
  106. }
  107. .ivu-notice-with-desc {
  108. flex: 1;
  109. padding: 0 12px;
  110. }
  111. .ivu-notice-desc {
  112. word-break:break-all;
  113. line-height: 1.3;
  114. text-overflow: ellipsis;
  115. display: -webkit-box;
  116. -webkit-line-clamp: 2;
  117. overflow:hidden;
  118. -webkit-box-orient: vertical;
  119. }
  120. }
  121. </style>
  122. <style lang="scss" scoped>
  123. .chat-index {
  124. display: flex;
  125. flex-direction: row;
  126. align-items: flex-start;
  127. position: absolute;
  128. top: 0;
  129. left: 0;
  130. right: 0;
  131. bottom: 0;
  132. .chat-none {
  133. height: auto;
  134. color: #666666;
  135. padding: 22px 8px;
  136. text-align: center;
  137. justify-content: center;
  138. &:before {
  139. display: none;
  140. }
  141. }
  142. .chat-menu {
  143. background-color: rgba(28, 29, 31, 0.92);
  144. width: 68px;
  145. height: 100%;
  146. padding-top: 20px;
  147. li {
  148. position: relative;
  149. padding: 12px 0;
  150. text-align: center;
  151. font-size: 28px;
  152. color: #919193;
  153. background-color: transparent;
  154. cursor: pointer;
  155. &.self {
  156. img {
  157. width: 36px;
  158. height: 36px;
  159. border-radius: 3px;
  160. }
  161. }
  162. &.active {
  163. color: #ffffff;
  164. background-color: rgba(255, 255, 255, 0.06);
  165. }
  166. .chat-num {
  167. position: absolute;
  168. top: 50%;
  169. left: 50%;
  170. height: auto;
  171. line-height: normal;
  172. color: #ffffff;
  173. background-color: #ff0000;
  174. text-align: center;
  175. border-radius: 10px;
  176. padding: 1px 5px;
  177. font-size: 12px;
  178. transform: scale(0.9) translate(5px, -20px);
  179. }
  180. }
  181. }
  182. .chat-user {
  183. width: 248px;
  184. height: 100%;
  185. background-color: #ffffff;
  186. border-right: 1px solid #ededed;
  187. li {
  188. display: flex;
  189. flex-direction: row;
  190. align-items: center;
  191. height: 70px;
  192. padding: 0 12px;
  193. position: relative;
  194. cursor: pointer;
  195. &:before {
  196. content: "";
  197. position: absolute;
  198. left: 0;
  199. right: 0;
  200. bottom: 0;
  201. height: 1px;
  202. background-color: rgba(0, 0, 0, 0.06);
  203. }
  204. &.sreach {
  205. height: 62px;
  206. }
  207. &.active {
  208. &:before {
  209. top: 0;
  210. height: 100%;
  211. }
  212. }
  213. img {
  214. width: 42px;
  215. height: 42px;
  216. border-radius: 4px;
  217. }
  218. .user-msg-box {
  219. flex: 1;
  220. display: flex;
  221. flex-direction: column;
  222. padding-left: 12px;
  223. .user-msg-title {
  224. display: flex;
  225. flex-direction: row;
  226. align-items: center;
  227. justify-content: space-between;
  228. line-height: 24px;
  229. span {
  230. flex: 1;
  231. max-width: 130px;
  232. color: #333333;
  233. font-size: 14px;
  234. white-space: nowrap;
  235. overflow: hidden;
  236. text-overflow: ellipsis;
  237. }
  238. em {
  239. color: #999999;
  240. font-size: 12px;
  241. }
  242. }
  243. .user-msg-text {
  244. max-width: 170px;
  245. color: #999999;
  246. font-size: 12px;
  247. line-height: 24px;
  248. white-space: nowrap;
  249. overflow: hidden;
  250. text-overflow: ellipsis;
  251. }
  252. }
  253. .user-msg-num {
  254. position: absolute;
  255. top: 6px;
  256. left: 44px;
  257. height: auto;
  258. line-height: normal;
  259. color: #ffffff;
  260. background-color: #ff0000;
  261. text-align: center;
  262. border-radius: 10px;
  263. padding: 1px 5px;
  264. font-size: 12px;
  265. transform: scale(0.9);
  266. border: 1px solid #ffffff;
  267. }
  268. }
  269. }
  270. .chat-team {
  271. width: 248px;
  272. height: 100%;
  273. background-color: #ffffff;
  274. border-right: 1px solid #ededed;
  275. > li {
  276. margin-left: 24px;
  277. position: relative;
  278. &.sreach {
  279. display: flex;
  280. flex-direction: row;
  281. align-items: center;
  282. height: 62px;
  283. margin: 0;
  284. padding: 0 12px;
  285. position: relative;
  286. cursor: pointer;
  287. &:before {
  288. content: "";
  289. position: absolute;
  290. left: 0;
  291. right: 0;
  292. bottom: 0;
  293. height: 1px;
  294. background-color: rgba(0, 0, 0, 0.06);
  295. }
  296. }
  297. .team-label {
  298. padding-left: 4px;
  299. margin-top: 6px;
  300. margin-bottom: 6px;
  301. height: 34px;
  302. line-height: 34px;
  303. border-bottom: 1px solid #efefef;
  304. }
  305. > ul {
  306. > li {
  307. display: flex;
  308. flex-direction: row;
  309. align-items: center;
  310. height: 52px;
  311. cursor: pointer;
  312. img {
  313. width: 30px;
  314. height: 30px;
  315. border-radius: 3px;
  316. }
  317. .team-username {
  318. padding: 0 12px;
  319. font-size: 14px;
  320. white-space: nowrap;
  321. overflow: hidden;
  322. text-overflow: ellipsis;
  323. }
  324. }
  325. }
  326. }
  327. }
  328. .chat-message {
  329. flex: 1;
  330. height: 100%;
  331. background-color: #F3F3F3;
  332. position: relative;
  333. .manage-title {
  334. position: absolute;
  335. top: 0;
  336. left: 0;
  337. z-index: 3;
  338. width: 100%;
  339. height: 62px;
  340. padding: 0 20px;
  341. line-height: 62px;
  342. font-size: 16px;
  343. font-weight: 500;
  344. text-align: left;
  345. background: #ffffff;
  346. border-bottom: 1px solid #ededed;
  347. .manage-title-right {
  348. position: absolute;
  349. top: 0;
  350. right: 0;
  351. z-index: 9;
  352. width: 62px;
  353. height: 62px;
  354. line-height: 62px;
  355. text-align: center;
  356. font-size: 22px;
  357. color: #242424;
  358. }
  359. }
  360. .manage-lists {
  361. position: absolute;
  362. left: 0;
  363. top: 62px;
  364. z-index: 1;
  365. bottom: 120px;
  366. width: 100%;
  367. overflow: auto;
  368. padding: 8px 0;
  369. background-color: #E8EBF2;
  370. .manage-lists-message-new {
  371. position: fixed;
  372. bottom: 130px;
  373. right: 20px;
  374. color: #ffffff;
  375. background-color: rgba(0, 0, 0, 0.6);
  376. padding: 6px 12px;
  377. border-radius: 16px;
  378. font-size: 12px;
  379. cursor: pointer;
  380. }
  381. }
  382. .manage-send {
  383. position: absolute;
  384. left: 0;
  385. bottom: 0;
  386. z-index: 2;
  387. display: flex;
  388. width: 100%;
  389. height: 120px;
  390. background-color: #ffffff;
  391. border-top: 1px solid #e4e4e4;
  392. .manage-input,.manage-input:focus {
  393. flex: 1;
  394. -webkit-appearance: none;
  395. font-size: 14px;
  396. box-sizing: border-box;
  397. padding: 0;
  398. margin: 38px 10px 6px;
  399. border: 0;
  400. line-height: 20px;
  401. box-shadow: none;
  402. resize:none;
  403. outline: 0;
  404. }
  405. .manage-join,
  406. .manage-spin {
  407. position: absolute;
  408. top: 0;
  409. left: 0;
  410. right: 0;
  411. bottom: 0;
  412. background: #ffffff;
  413. display: flex;
  414. align-items: center;
  415. justify-content: center;
  416. }
  417. }
  418. .manage-quick {
  419. position: absolute;
  420. z-index: 2;
  421. left: 0;
  422. right: 0;
  423. bottom: 79px;
  424. padding: 8px;
  425. display: flex;
  426. align-items: center;
  427. .quick-item {
  428. color: #444444;
  429. font-size: 24px;
  430. margin-right: 12px;
  431. }
  432. .emoji-box {
  433. position: absolute;
  434. left: 0;
  435. bottom: 40px;
  436. max-height: 320px;
  437. width: 100%;
  438. overflow: auto;
  439. background-color: #ffffff;
  440. padding: 12px;
  441. border-bottom: 1px solid #efefef;
  442. .emoji-input {
  443. margin: 6px 0;
  444. }
  445. h5 {
  446. padding: 0;
  447. margin: 8px 0 0 0;
  448. color: #b1b1b1;
  449. text-transform: uppercase;
  450. font-size: 14px;
  451. cursor: default;
  452. font-weight: normal;
  453. }
  454. .emojis {
  455. display: flex;
  456. flex-wrap: wrap;
  457. justify-content: space-between;
  458. &:after {
  459. content: "";
  460. flex: auto;
  461. }
  462. span {
  463. padding: 2px 4px;
  464. cursor: pointer;
  465. font-size: 22px;
  466. &:hover {
  467. background: #ececec;
  468. cursor: pointer;
  469. }
  470. }
  471. }
  472. }
  473. .message-upload {
  474. display: none;
  475. width: 0;
  476. height: 0;
  477. overflow: hidden;
  478. }
  479. }
  480. @media screen and (max-width: 768px) {
  481. .manage-lists {
  482. bottom: 96px;
  483. .manage-lists-message-new {
  484. bottom: 106px;
  485. }
  486. }
  487. .manage-send {
  488. height: 96px;
  489. }
  490. .manage-quick {
  491. bottom: 54px;
  492. .quick-item {
  493. font-size: 24px;
  494. margin-right: 8px;
  495. }
  496. }
  497. }
  498. }
  499. }
  500. </style>
  501. <script>
  502. import EmojiPicker from 'vue-emoji-picker'
  503. import DrawerTabsContainer from "../DrawerTabsContainer";
  504. import ScrollerY from "../../../_components/ScrollerY";
  505. import ChatMessage from "./message";
  506. import ImgUpload from "../ImgUpload";
  507. export default {
  508. name: 'ChatIndex',
  509. components: {ImgUpload, ChatMessage, EmojiPicker, ScrollerY, DrawerTabsContainer},
  510. props: {
  511. value: {
  512. default: 0
  513. },
  514. openWindow: {
  515. type: Boolean,
  516. default: false
  517. },
  518. },
  519. data () {
  520. return {
  521. loadIng: 0,
  522. userInfo: {},
  523. chatTap: 'dialog',
  524. dialogTarget: {},
  525. dialogLists: [],
  526. dialogNoDataText: '',
  527. teamReady: false,
  528. teamLists: {},
  529. teamNoDataText: '',
  530. autoBottom: true,
  531. messageNew: 0,
  532. messageText: '',
  533. messageLists: [],
  534. messageNoDataText: '',
  535. messageEmojiSearch: '',
  536. unreadTotal: 0,
  537. }
  538. },
  539. created() {
  540. this.dialogNoDataText = this.$L("数据加载中.....");
  541. this.teamNoDataText = this.$L("数据加载中.....");
  542. this.messageNoDataText = this.$L("数据加载中.....");
  543. },
  544. mounted() {
  545. let resCall = () => {
  546. if ($A.getToken() === false) {
  547. return;
  548. }
  549. $A.WS.sendTo('unread', (res) => {
  550. if (res.status === 1) {
  551. this.unreadTotal = $A.runNum(res.message);
  552. } else {
  553. this.unreadTotal = 0;
  554. }
  555. });
  556. this.getDialogLists();
  557. this.messageBottomAuto();
  558. };
  559. this.userInfo = $A.getUserInfo((res, isLogin) => {
  560. if (this.userInfo.id != res.id) {
  561. this.userInfo = res;
  562. resCall();
  563. }
  564. }, false);
  565. resCall();
  566. //
  567. $A.WS.setOnMsgListener("chat/index", (msgDetail) => {
  568. if (msgDetail.sender == $A.getUserName()) {
  569. return;
  570. }
  571. if (msgDetail.messageType != 'send') {
  572. return;
  573. }
  574. //
  575. let data = $A.jsonParse(msgDetail.content);
  576. let lasttext;
  577. switch (data.type) {
  578. case 'text':
  579. lasttext = data['text'];
  580. break;
  581. case 'image':
  582. lasttext = '[图片]';
  583. break;
  584. default:
  585. lasttext = '[未知类型]';
  586. break;
  587. }
  588. this.addDialog({
  589. username: data.username,
  590. userimg: data.userimg,
  591. lasttext: lasttext,
  592. lastdate: data.indate
  593. }, msgDetail.sender != this.dialogTarget.username || !this.openWindow);
  594. if (msgDetail.sender == this.dialogTarget.username) {
  595. this.addMessageData(data, true);
  596. }
  597. if (!this.openWindow) {
  598. this.$Notice.close('chat-notice');
  599. this.$Notice.open({
  600. name: 'chat-notice',
  601. duration: 0,
  602. render: h => {
  603. return h('div', {
  604. class: 'chat-notice-box',
  605. on: {
  606. click: () => {
  607. this.$Notice.close('chat-notice');
  608. this.$emit("on-open-notice", data.username);
  609. this.clickDialog(data.username);
  610. }
  611. }
  612. }, [
  613. h('img', { class: 'chat-notice-userimg', attrs: { src: data.userimg } }),
  614. h('div', { class: 'ivu-notice-with-desc' }, [
  615. h('div', { class: 'ivu-notice-title' }, [
  616. h('UserView', { props: { username: data.username } })
  617. ]),
  618. h('div', { class: 'ivu-notice-desc' }, lasttext)
  619. ])
  620. ])
  621. }
  622. });
  623. }
  624. });
  625. },
  626. watch: {
  627. chatTap(val) {
  628. if (val === 'team' && this.teamReady == false) {
  629. this.teamReady = true;
  630. this.getTeamLists();
  631. } else if (val === 'dialog') {
  632. this.autoBottom = true;
  633. this.$nextTick(() => {
  634. this.messageBottomGo();
  635. });
  636. }
  637. },
  638. unreadTotal(val) {
  639. if (val < 0) {
  640. this.unreadTotal = 0;
  641. return;
  642. }
  643. this.$emit('input', val);
  644. },
  645. dialogTarget: {
  646. handler: function () {
  647. this.getDialogMessage();
  648. },
  649. deep: true
  650. }
  651. },
  652. methods: {
  653. formatCDate(v) {
  654. let string = '';
  655. if ($A.runNum(v) > 0) {
  656. if ($A.formatDate('Ymd') === $A.formatDate('Ymd', v)) {
  657. string = $A.formatDate('H:i', v)
  658. } else if ($A.formatDate('Y') === $A.formatDate('Y', v)) {
  659. string = $A.formatDate('m-d', v)
  660. } else {
  661. string = $A.formatDate('Y-m-d', v)
  662. }
  663. }
  664. return string || '';
  665. },
  666. getDialogLists() {
  667. this.loadIng++;
  668. this.dialogNoDataText = this.$L("数据加载中.....");
  669. $A.aAjax({
  670. url: 'chat/dialog/lists',
  671. complete: () => {
  672. this.loadIng--;
  673. },
  674. error: () => {
  675. this.dialogNoDataText = this.$L("数据加载失败!");
  676. },
  677. success: (res) => {
  678. if (res.ret === 1) {
  679. this.dialogLists = res.data;
  680. this.dialogNoDataText = this.$L("没有相关的数据");
  681. } else {
  682. this.dialogLists = [];
  683. this.dialogNoDataText = res.msg
  684. }
  685. }
  686. });
  687. },
  688. getDialogMessage() {
  689. let username = this.dialogTarget.username;
  690. if (username === this.__dialogTargetUsername) {
  691. return;
  692. }
  693. this.__dialogTargetUsername = username;
  694. this.autoBottom = true;
  695. this.messageNew = 0;
  696. this.messageLists = [];
  697. //
  698. this.loadIng++;
  699. this.messageNoDataText = this.$L("数据加载中.....");
  700. $A.aAjax({
  701. url: 'chat/message/lists',
  702. data: {
  703. username: username,
  704. pagesize: 30
  705. },
  706. complete: () => {
  707. this.loadIng--;
  708. },
  709. error: () => {
  710. this.messageNoDataText = this.$L("数据加载失败!");
  711. },
  712. success: (res) => {
  713. if (username != this.dialogTarget.username) {
  714. return;
  715. }
  716. if (res.ret === 1) {
  717. res.data.lists.reverse().forEach((item) => {
  718. this.addMessageData(Object.assign(item.message, {
  719. id: item.id,
  720. username: item.username,
  721. userimg: item.userimg,
  722. indate: item.indate,
  723. }));
  724. });
  725. this.messageNoDataText = this.$L("没有相关的数据");
  726. } else {
  727. this.messageNoDataText = res.msg
  728. }
  729. }
  730. });
  731. },
  732. getTeamLists() {
  733. this.loadIng++;
  734. this.teamNoDataText = this.$L("数据加载中.....");
  735. $A.aAjax({
  736. url: 'users/team/lists',
  737. data: {
  738. sorts: {
  739. key: 'username',
  740. order: 'asc'
  741. },
  742. firstchart: 1,
  743. pagesize: 100,
  744. },
  745. complete: () => {
  746. this.loadIng--;
  747. },
  748. error: () => {
  749. this.teamNoDataText = this.$L("数据加载失败!");
  750. },
  751. success: (res) => {
  752. if (res.ret === 1) {
  753. res.data.lists.forEach((item) => {
  754. if (typeof this.teamLists[item.firstchart] === "undefined") {
  755. this.$set(this.teamLists, item.firstchart, []);
  756. }
  757. this.teamLists[item.firstchart].push(item);
  758. console.log(this.teamLists);
  759. });
  760. this.teamNoDataText = this.$L("没有相关的数据");
  761. } else {
  762. this.teamLists = {};
  763. this.teamNoDataText = res.msg
  764. }
  765. }
  766. });
  767. },
  768. addDialog(data, plusUnread = false) {
  769. if (!data.username) {
  770. return;
  771. }
  772. let lists = this.dialogLists.filter((item) => {return item.username == data.username});
  773. if (lists.length > 0) {
  774. data.unread = $A.runNum(lists[0].unread);
  775. this.dialogLists = this.dialogLists.filter((item) => {return item.username != data.username});
  776. } else {
  777. data.unread = 0;
  778. }
  779. if (plusUnread) {
  780. data.unread += 1;
  781. this.unreadTotal += 1;
  782. }
  783. this.dialogLists.unshift(data);
  784. },
  785. openDialog(user) {
  786. this.chatTap = 'dialog';
  787. this.dialogTarget = user;
  788. if (typeof user.unread === "number" && user.unread > 0) {
  789. this.unreadTotal -= user.unread;
  790. this.$set(user, 'unread', 0);
  791. $A.WS.sendTo('read', user.username);
  792. }
  793. },
  794. clickDialog(username) {
  795. let lists = this.dialogLists.filter((item) => {return item.username == username});
  796. if (lists.length > 0) {
  797. this.openDialog(lists[0]);
  798. }
  799. },
  800. messageListsScroll(res) {
  801. if (res.directionreal === 'up') {
  802. if (res.scrollE < 10) {
  803. this.autoBottom = true;
  804. }
  805. } else if (res.directionreal === 'down') {
  806. this.autoBottom = false;
  807. }
  808. },
  809. messageBottomAuto() {
  810. let randString = $A.randomString(8);
  811. window.__messageBottomAuto = randString;
  812. setTimeout(() => {
  813. if (randString === window.__messageBottomAuto) {
  814. window.__messageBottomAuto = null;
  815. if (this.autoBottom) {
  816. this.messageBottomGo();
  817. }
  818. this.messageBottomAuto();
  819. }
  820. }, 1000);
  821. },
  822. messageBottomGo(animation = false) {
  823. this.$nextTick(() => {
  824. this.messageNew = 0;
  825. if (typeof this.$refs.manageLists !== "undefined") {
  826. this.$refs.manageLists.scrollTo(this.$refs.manageBody.clientHeight, animation);
  827. this.autoBottom = true;
  828. }
  829. });
  830. },
  831. messageInsertText(emoji) {
  832. this.messageText+= emoji;
  833. },
  834. messageInsertImage(lists) {
  835. for (let i = 0; i < lists.length; i++) {
  836. let item = lists[i];
  837. if (typeof item === 'object' && typeof item.url === "string") {
  838. let data = {
  839. type: 'image',
  840. username: this.userInfo.username,
  841. userimg: this.userInfo.userimg,
  842. indate: Math.round(new Date().getTime() / 1000),
  843. url: item.url
  844. };
  845. $A.WS.sendTo('user', this.dialogTarget.username, data, (res) => {
  846. this.$set(data, res.status === 1 ? 'id' : 'error', res.message)
  847. });
  848. //
  849. this.addDialog(Object.assign(this.dialogTarget, {
  850. lasttext: '[图片]',
  851. lastdate: data.indate
  852. }));
  853. this.openDialog(this.dialogTarget);
  854. this.addMessageData(data, true);
  855. }
  856. }
  857. },
  858. addMessageData(data, animation = false) {
  859. data.self = data.username === this.userInfo.username;
  860. let sikp = false;
  861. if (data.id) {
  862. this.messageLists.some((item, index) => {
  863. if (item.id == data.id) {
  864. this.messageLists.splice(index, 1, data);
  865. return sikp = true;
  866. }
  867. });
  868. if (sikp) {
  869. return;
  870. }
  871. }
  872. this.messageLists.push(data);
  873. //
  874. if (this.autoBottom) {
  875. this.messageBottomGo(animation);
  876. } else {
  877. this.messageNew++;
  878. }
  879. },
  880. messageSend(e) {
  881. if (e.keyCode == 13) {
  882. if (e.shiftKey) {
  883. return;
  884. }
  885. e.preventDefault();
  886. this.messageSubmit();
  887. }
  888. },
  889. messageSubmit() {
  890. let text = this.messageText.trim();
  891. if ($A.count(text) > 0) {
  892. let data = {
  893. type: 'text',
  894. username: this.userInfo.username,
  895. userimg: this.userInfo.userimg,
  896. indate: Math.round(new Date().getTime() / 1000),
  897. text: text
  898. };
  899. $A.WS.sendTo('user', this.dialogTarget.username, data, (res) => {
  900. this.$set(data, res.status === 1 ? 'id' : 'error', res.message)
  901. });
  902. //
  903. this.addDialog(Object.assign(this.dialogTarget, {
  904. lasttext: text,
  905. lastdate: data.indate
  906. }));
  907. this.openDialog(this.dialogTarget);
  908. this.addMessageData(data, true);
  909. }
  910. this.$nextTick(() => {
  911. this.messageText = "";
  912. });
  913. },
  914. }
  915. }
  916. </script>