angular仿微信聊天|angular手機端IM聊天室|仿微信界面|angular聊天

【源碼下載地址】:  碼雲地址:https://gitee.com/wangdefu/angular_chat?_from=gitee_search

有不足之處還望各位多多指點

【演示效果】:這是打包之後上傳服務器的ng效果,首次加載速度會有點慢,請耐心等待 http://www.bester.wang

【升級版本】:整合ionic4,支持打包雙系統app,接近原生app的體驗,真正的即時通訊,真正的聊天app,對任何想整合im的項目都是零侵入性,隨時隨地整合聊天系統到你的原有項目,就是這麼簡單

【後端im技術簡介】:springboot+cloud,讓開發更簡單,微服務讓分佈式和集羣更簡單,支持不停機更新,基於業界標杆netty進行im核心開發,性能爆表

【angualr前端模板簡介】:採用angular+@angular/cli+@angular/router+@ngrx/store等技術開發的angular版仿微信界面聊天室,主要實現了下拉刷新、長按右鍵菜單、發送消息、表情(動圖),圖片、視頻預覽,打賞、紅包等功能。

技術架構:

  • MVVM框架:angular8 + @angular/cli + @angular/router
  • 狀態管理:@ngrx/store + rxjs
  • 地址路由:@angular/router
  • 彈窗組件:wcPop
  • 打包工具:webpack 2.0
  • 環境配置:node.js + cnpm
  • 圖片預覽:previewImage
  • 輪播滑動:swiper

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

學習不停歇、研發不終止,近段時間一直在搗鼓angular框架技術,發現並沒有想象的那麼難,不過也踩過一些坑,之前有使用vue開發過仿微信聊天,想着基於angular+angular-cli+angular-router+ngrx/store+rxjs+webpack+node+wcPop等技術開發的仿微信angular-chatroom聊天室實戰項目,實現了下拉刷新、聊天消息右鍵菜單、發送消息、表情(動圖),圖片、視頻預覽,紅包打賞等功能

技術架構:

  • MVVM框架:angular8.0 / @angular/cli
  • 狀態管理:@ngrx/store / rxjs
  • 地址路由:@angular/router
  • 彈窗組件:wcPop
  • 打包工具:webpack 2.0
  • 環境配置:node.js + cnpm
  • 圖片預覽:previewImage
  • 輪播滑動:swiper

 

 

 

 

 

 

 

 

package.json依賴安裝:


 
  1. {

  2. "name": "angular-chatroom",

  3. "aboutMe": "QQ:282310962 wx:xy190310",

  4.  
  5. "dependencies": {

  6. "@angular/animations": "~8.0.1",

  7. "@angular/common": "~8.0.1",

  8. "@angular/compiler": "~8.0.1",

  9. "@angular/core": "~8.0.1",

  10. "@angular/forms": "~8.0.1",

  11. "@angular/platform-browser": "~8.0.1",

  12. "@angular/platform-browser-dynamic": "~8.0.1",

  13. "@angular/router": "~8.0.1",

  14. "rxjs": "~6.4.0",

  15. },

  16. "devDependencies": {

  17. "@angular-devkit/build-angular": "~0.800.0",

  18. "@angular/cli": "~8.0.3",

  19. "@angular/compiler-cli": "~8.0.1",

  20. "@angular/language-service": "~8.0.1",

  21. "@ngrx/store": "^8.0.1",

  22. "@types/jasmine": "~3.3.8",

  23. "@types/jasminewd2": "~2.0.3",

  24. "@types/node": "~8.9.4",

  25. "@types/swiper": "^4.4.3",

  26. "codelyzer": "^5.0.0",

  27. "jasmine-core": "~3.4.0",

  28. "jasmine-spec-reporter": "~4.2.1",

  29. "jquery": "^2.2.3",

  30. "karma": "~4.1.0",

  31. "karma-chrome-launcher": "~2.2.0",

  32. "karma-coverage-istanbul-reporter": "~2.0.1",

  33. "karma-jasmine": "~2.0.1",

  34. "karma-jasmine-html-reporter": "^1.4.0",

  35. "swiper": "^4.5.0",

  36. }

  37. }


 
  1. /*

  2. * angular/router路由配置

  3. */

  4.  
  5. import { NgModule } from '@angular/core'

  6. import { Routes, RouterModule } from '@angular/router'

  7.  
  8. // 引入路由驗證

  9. import { Auth } from '../views/auth/auth'

  10.  
  11. // 引入頁面組件

  12. import { NotFoundComponent } from '../components/404'

  13. import { LoginComponent } from '../views/auth/login'

  14. import { RegisterComponent } from '../views/auth/register'

  15. import { IndexComponent } from '../views/index'

  16. import { ContactComponent } from '../views/contact'

  17. import { UinfoComponent } from '../views/contact/uinfo'

  18. import { UcenterComponent } from '../views/ucenter'

  19. import { GroupChatComponent } from '../views/chat/group-chat'

  20. import { GroupInfoComponent } from '../views/chat/group-info'

  21. import { SingleChatComponent } from '../views/chat/single-chat'

  22.  
  23.  
  24. export const routes: Routes = [

  25. {

  26. path: '', redirectTo: 'index', pathMatch: 'full',

  27. data: { showHeader: true, showTabBar: true },

  28. },

  29.  
  30. // 登錄、註冊

  31. {

  32. path: 'login', component: LoginComponent,

  33. },

  34. {

  35. path: 'register', component: RegisterComponent,

  36. },

  37.  
  38. // 首頁、聯繫人、我

  39. {

  40. path: 'index', component: IndexComponent, canActivate: [Auth],

  41. data: { showHeader: true, showTabBar: true },

  42. },

  43. {

  44. path: 'contact', component: ContactComponent, canActivate: [Auth],

  45. data: { showHeader: true, showTabBar: true },

  46. },

  47. {

  48. path: 'contact/uinfo', component: UinfoComponent

  49. },

  50. {

  51. path: 'ucenter', component: UcenterComponent, canActivate: [Auth],

  52. data: { showHeader: false, showTabBar: true },

  53. },

  54.  
  55. // 聊天頁面

  56. {

  57. path: 'chat/group-chat', component: GroupChatComponent, canActivate: [Auth]

  58. },

  59. {

  60. path: 'chat/single-chat', component: SingleChatComponent, canActivate: [Auth]

  61. },

  62. {

  63. path: 'chat/group-info', component: GroupInfoComponent, canActivate: [Auth]

  64. },

  65.  
  66. // 404

  67. {

  68. path: '**', component: NotFoundComponent,

  69. },

  70.  
  71. // ...

  72. ];

  73.  
  74. @NgModule({

  75. // imports: [RouterModule.forRoot(routes)],

  76. imports: [RouterModule.forRoot(routes, { useHash: true })], //開啓hash模式

  77. exports: [RouterModule],

  78. providers: [Auth]

  79. })

  80. export class AppRoutingModule {}


 
  1. export class LoginComponent implements OnInit {

  2. private formField = {

  3. tel: '',

  4. pwd: ''

  5. }

  6.  
  7. private auth: any

  8. constructor(

  9. private router: Router,

  10. private store: Store<{}>

  11. ) {

  12. let that = this

  13. this.store.select('auth').subscribe(v => {

  14. console.log(v)

  15. that.auth = v;

  16. })

  17. }

  18.  
  19. ngOnInit(): void {

  20. if(this.auth.token){

  21. this.router.navigate(['/index'])

  22. }

  23. }

  24.  
  25. handleSubmit(){

  26. let that = this

  27.  
  28. if(!this.formField.tel){

  29. wcPop({ content: '手機號不能爲空!', style: 'background:#eb5a5c;color:#fff;', time: 2 });

  30. }else if(!checkTel(this.formField.tel)){

  31. wcPop({ content: '手機號格式不正確!', style: 'background:#eb5a5c;color:#fff;', time: 2 });

  32. }else if(!this.formField.pwd){

  33. wcPop({ content: '密碼不能爲空!', style: 'background:#eb5a5c;color:#fff;', time: 2 });

  34. }else{

  35. this.store.dispatch(new actions.setToken(getToken(64)))

  36. this.store.dispatch(new actions.setUser(this.formField.tel))

  37.  
  38. wcPop({

  39. content: '登錄成功,跳轉中...', style: 'background:#378fe7;color:#fff;', time: 2, shadeClose: false,

  40. end: function () {

  41. that.router.navigate(['/index'])

  42. }

  43. });

  44. }

  45. }

  46. }


 
  1. function surrounds() {

  2. setTimeout(function () { //chrome

  3. var sel = window.getSelection();

  4. var anchorNode = sel.anchorNode;

  5. if (!anchorNode) return;

  6. if (sel.anchorNode === $(".J__wcEditor")[0] ||

  7. (sel.anchorNode.nodeType === 3 && sel.anchorNode.parentNode === $(".J__wcEditor")[0])) {

  8.  
  9. var range = sel.getRangeAt(0);

  10. var p = document.createElement("p");

  11. range.surroundContents(p);

  12. range.selectNodeContents(p);

  13. range.insertNode(document.createElement("br")); //chrome

  14. sel.collapse(p, 0);

  15.  
  16. (function clearBr() {

  17. var elems = [].slice.call($(".J__wcEditor")[0].children);

  18. for (var i = 0, len = elems.length; i < len; i++) {

  19. var el = elems[i];

  20. if (el.tagName.toLowerCase() == "br") {

  21. $(".J__wcEditor")[0].removeChild(el);

  22. }

  23. }

  24. elems.length = 0;

  25. })();

  26. }

  27. }, 10);

  28. }

  29.  
  30. // 定義最後光標位置

  31. var _lastRange = null, _sel = window.getSelection && window.getSelection();

  32. var _rng = {

  33. getRange: function () {

  34. if (_sel && _sel.rangeCount > 0) {

  35. return _sel.getRangeAt(0);

  36. }

  37. },

  38. addRange: function () {

  39. if (_lastRange) {

  40. _sel.removeAllRanges();

  41. _sel.addRange(_lastRange);

  42. }

  43. }

  44. }

  45.  
  46. // 消息處理

  47. function isEmpty() {

  48. // var html = $editor.html();

  49. var html = $(".J__wcEditor").html();

  50. html = html.replace(/<br[\s\/]{0,2}>/ig, "\r\n");

  51. html = html.replace(/<[^img].*?>/ig, "");

  52. html = html.replace(/&nbsp;/ig, "");

  53. return html.replace(/\r\n|\n|\r/, "").replace(/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g, "") == "";

  54. }


 
  1. /*

  2. * angular路由守衛(驗證token)

  3. */

  4.  
  5. import { Router, CanActivate } from '@angular/router'

  6.  
  7. declare var wcPop: any;

  8.  
  9. export class Auth implements CanActivate{

  10. constructor(private router: Router){}

  11.  
  12. canActivate(){

  13. let that = this

  14. // 驗證token

  15. const token: boolean = window.sessionStorage.getItem('token') ? true : false

  16.  
  17. if(!token){

  18. // 未登錄授權

  19. /*

  20. wcPop({

  21. content: '還未登錄授權!', anim: 'shake', style: 'background:#e03b30;color:#fff;', time: 2,

  22. end: function () {

  23. that.router.navigate(['/login']);

  24. }

  25. });

  26. */

  27. that.router.navigate(['/login']);

  28. }

  29. return token

  30. }

  31. }

【技術交流】:個人技術交流微信   xw2876001800 提供前端和後端技術支持(java/php均可支持)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章