angular 版 IM 聊天室|仿微信 App 介面|angular 實戰開發

xiaoyan2015發表於2019-07-17

angular版IM聊天室|仿微信app介面|angular實戰開發

運用angular+@angular/cli+@angular/router+@ngrx/store等技術實現開發的移動端聊天室angular版,實現了下拉重新整理、長按右鍵選單、傳送訊息、表情(動圖),圖片、影片預覽,打賞、紅包等功能。
react版聊天IM:https://blog.csdn.net/yanxinyun1990/articl...

技術架構:

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

angular版IM聊天室|仿微信app介面|angular實戰開發

angular版IM聊天室|仿微信app介面|angular實戰開發

angular版IM聊天室|仿微信app介面|angular實戰開發

angular版IM聊天室|仿微信app介面|angular實戰開發

angular版IM聊天室|仿微信app介面|angular實戰開發

angular版IM聊天室|仿微信app介面|angular實戰開發

angular版IM聊天室|仿微信app介面|angular實戰開發

angular版IM聊天室|仿微信app介面|angular實戰開發

angular版IM聊天室|仿微信app介面|angular實戰開發

angular版IM聊天室|仿微信app介面|angular實戰開發

angular版IM聊天室|仿微信app介面|angular實戰開發

angular版IM聊天室|仿微信app介面|angular實戰開發

angular版IM聊天室|仿微信app介面|angular實戰開發

angular版IM聊天室|仿微信app介面|angular實戰開發

{
  "name": "angular-chatroom",
  "aboutMe": "QQ:282310962   wx:xy190310",

  "dependencies": {
    "@angular/animations": "~8.0.1",
    "@angular/common": "~8.0.1",
    "@angular/compiler": "~8.0.1",
    "@angular/core": "~8.0.1",
    "@angular/forms": "~8.0.1",
    "@angular/platform-browser": "~8.0.1",
    "@angular/platform-browser-dynamic": "~8.0.1",
    "@angular/router": "~8.0.1",
    "rxjs": "~6.4.0",
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.800.0",
    "@angular/cli": "~8.0.3",
    "@angular/compiler-cli": "~8.0.1",
    "@angular/language-service": "~8.0.1",
    "@ngrx/store": "^8.0.1",
    "@types/jasmine": "~3.3.8",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "~8.9.4",
    "@types/swiper": "^4.4.3",
    "codelyzer": "^5.0.0",
    "jasmine-core": "~3.4.0",
    "jasmine-spec-reporter": "~4.2.1",
    "jquery": "^2.2.3",
    "karma": "~4.1.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.1",
    "karma-jasmine": "~2.0.1",
    "karma-jasmine-html-reporter": "^1.4.0",
    "swiper": "^4.5.0",
  }
}
/*
 *  angular主模組配置
 */ 

import { BrowserModule } from '@angular/platform-browser'
import { NgModule } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { AppRoutingModule } from './app-routing.module'

// 引入狀態管理
import { StoreModule } from '@ngrx/store'
import { reducer } from '../ngrx'

// 載入公共元件(component)
import { HeaderComponent } from '../components/header'
import { TabBarComponent } from '../components/tabbar'
import { XtnScroll } from '../components/xtnScroll/Scroll'
import { NotFoundComponent } from '../components/404'
// 載入頁面元件(view)
import { AppComponent } from './app.component'
import { LoginComponent } from '../views/auth/login'
import { RegisterComponent } from '../views/auth/register'
import { IndexComponent } from '../views/index'
import { ContactComponent } from '../views/contact'
import { UinfoComponent } from '../views/contact/uinfo'
import { UcenterComponent } from '../views/ucenter'
import { GroupChatComponent } from '../views/chat/group-chat'
import { GroupInfoComponent } from '../views/chat/group-info'
import { SingleChatComponent } from '../views/chat/single-chat'

@NgModule({
  declarations: [
    // 公共元件
    HeaderComponent,
    TabBarComponent,
    XtnScroll,
    NotFoundComponent,

    // 頁面元件
    AppComponent,
    LoginComponent,
    RegisterComponent,
    IndexComponent,
    ContactComponent,
    UinfoComponent,
    UcenterComponent,
    GroupChatComponent,
    GroupInfoComponent,
    SingleChatComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,

    StoreModule.forRoot(reducer)
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
/*
 *  angular路由守衛(驗證token)
 */

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

declare var wcPop: any;

export class Auth implements CanActivate{
    constructor(private router: Router){}

    canActivate(){
        let that = this
        // 驗證token
        const token: boolean = window.sessionStorage.getItem('token') ? true : false

        if(!token){
            // 未登入授權
            /*
            wcPop({
                content: '還未登入授權!', anim: 'shake', style: 'background:#e03b30;color:#fff;', time: 2,
                end: function () {
                    that.router.navigate(['/login']);
                }
            });
            */
            that.router.navigate(['/login']);
        }
        return token
    }
}
/*
 *  @tmpl 登入模板
 */

import { Component, OnInit } from '@angular/core'
import { Router } from '@angular/router'

// 引入狀態管理
import { Store } from '@ngrx/store'
import { Observable } from 'rxjs'

import * as actions from '../../ngrx/action'

declare var wcPop: any;

import { getToken, checkTel } from '../../utils/common'

@Component({
    selector: 'app-login',
    template: `
        <div class="wcim__lgregWrapper flexbox flex__direction-column">
            <div class="wcim__lgregHeader flex1">
                <div class="slogan">
                    <div class="logo"><img src="../../assets/img/logo.png" /></div>
                    <h2>Angualr-chatRoom聊天室</h2>
                </div>
                <div class="forms">
                    <form (ngSubmit)="handleSubmit()">
                        <ul class="clearfix">
                            <li class="flexbox flex-alignc"><i class="iconfont icon-shouji"></i><input class="iptxt flex1" [(ngModel)]="formField.tel" name="tel" type="tel" placeholder="請輸入手機號" autoComplete="off" maxLength="11" /><em class="borLine"></em></li>
                            <li class="flexbox flex-alignc"><i class="iconfont icon-pass"></i><input class="iptxt flex1" [(ngModel)]="formField.pwd" name="pwd" type="password" placeholder="請輸入密碼" autoComplete="off" /><em class="borLine"></em></li>
                        </ul>

                        <div class="btns"><button class="wc__btn-primary btn__login" type="submit">登入</button></div>
                        <div class="lgregLink align-c clearfix">
                            <a routerLink="#">忘記密碼</a>
                            <a routerLink="/register">註冊使用者</a>
                        </div>
                    </form>
                </div>
            </div>
            <div class="wcim__lgregFooter">
                <p class="version">Angular-chatRoom v1.0</p>
            </div>
        </div>
    `,
    styles: [``]
})
function surrounds() {
    setTimeout(function () { //chrome
        var sel = window.getSelection();
        var anchorNode = sel.anchorNode;
        if (!anchorNode) return;
        if (sel.anchorNode === $(".J__wcEditor")[0] ||
            (sel.anchorNode.nodeType === 3 && sel.anchorNode.parentNode === $(".J__wcEditor")[0])) {

            var range = sel.getRangeAt(0);
            var p = document.createElement("p");
            range.surroundContents(p);
            range.selectNodeContents(p);
            range.insertNode(document.createElement("br")); //chrome
            sel.collapse(p, 0);

            (function clearBr() {
                var elems = [].slice.call($(".J__wcEditor")[0].children);
                for (var i = 0, len = elems.length; i < len; i++) {
                    var el = elems[i];
                    if (el.tagName.toLowerCase() == "br") {
                        $(".J__wcEditor")[0].removeChild(el);
                    }
                }
                elems.length = 0;
            })();
        }
    }, 10);
}

// 定義最後游標位置
var _lastRange = null, _sel = window.getSelection && window.getSelection();
var _rng = {
    getRange: function () {
        if (_sel && _sel.rangeCount > 0) {
            return _sel.getRangeAt(0);
        }
    },
    addRange: function () {
        if (_lastRange) {
            _sel.removeAllRanges();
            _sel.addRange(_lastRange);
        }
    }
}

// 訊息處理
function isEmpty() {
    // var html = $editor.html();
    var html = $(".J__wcEditor").html();
    html = html.replace(/<br[\s\/]{0,2}>/ig, "\r\n");
    html = html.replace(/<[^img].*?>/ig, "");
    html = html.replace(/&nbsp;/ig, "");
    return html.replace(/\r\n|\n|\r/, "").replace(/(?:^[ \t\n\r]+)|(?:[ \t\n\r]+$)/g, "") == "";
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結
本文為原創文章,未經作者允許不得轉載,歡迎大家一起交流 QQ(282310962) wx(xy190310)

相關文章