加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

angular版聊天室|仿微信界面IM聊天|NG2+Node聊天实例

发布时间:2020-12-17 17:08:38 所属栏目:安全 来源:网络整理
导读:一、项目介绍 运用angular+angular-cli+angular-router+ngrx/store+rxjs+webpack+node+wcPop等技术实现开发的仿微信angular版聊天室angular-chatroom实例项目,实现了下拉刷新、聊天消息右键菜单、发送消息、表情(动图),图片、视频预览,红包打赏等功能。

一、项目介绍

运用angular+angular-cli+angular-router+ngrx/store+rxjs+webpack+node+wcPop等技术实现开发的仿微信angular版聊天室angular-chatroom实例项目,实现了下拉刷新、聊天消息右键菜单、发送消息、表情(动图),图片、视频预览,红包打赏等功能。

二、技术实现

  • MVVM框架:angular8.0 / @angular/cli
  • 状态管理:@ngrx/store / rxjs
  • 地址路由:@angular/router
  • 弹窗组件:wcPop
  • 打包工具:webpack 2.0
  • 环境配置:node.js + cnpm
  • 图片预览:previewImage
  • 轮播滑动:swiper
{
  "name": "angular-chatroom","contact": "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","tslib": "^1.9.0","zone.js": "~0.9.1"
  },"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","typescript": "~3.4.3"
  }
}

◆ App主页面模板、app-routing路由地址配置

<div class="weChatIM__panel clearfix">
    <div class="we__chatIM-wrapper flexbox flex__direction-column">
        <!-- 顶部 -->
        <header-bar></header-bar>
        
        <!-- 主页面 -->
        <div class="wcim__container flex1">
            <router-outlet></router-outlet>
        </div>

        <!-- 底部 -->
        <tab-bar></tab-bar>
    </div>
</div>
/*
 *  angular/router路由配置
 */

import { NgModule } from ‘@angular/core‘
import { Routes,RouterModule } from ‘@angular/router‘

// 引入路由验证
import { Auth } from ‘../views/auth/auth‘

// 引入页面组件
import { NotFoundComponent } from ‘../components/404‘
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‘


export const routes: Routes = [
  {
    path: ‘‘,redirectTo: ‘index‘,pathMatch: ‘full‘,data: { showHeader: true,showTabBar: true },},// 登录、注册
  {
    path: ‘login‘,component: LoginComponent,{
    path: ‘register‘,component: RegisterComponent,// 首页、联系人、我
  {
    path: ‘index‘,component: IndexComponent,canActivate: [Auth],{
    path: ‘contact‘,component: ContactComponent,{
    path: ‘contact/uinfo‘,component: UinfoComponent
  },{
    path: ‘ucenter‘,component: UcenterComponent,data: { showHeader: false,// 聊天页面
  {
    path: ‘chat/group-chat‘,component: GroupChatComponent,canActivate: [Auth]
  },{
    path: ‘chat/single-chat‘,component: SingleChatComponent,{
    path: ‘chat/group-info‘,component: GroupInfoComponent,// 404
  {
    path: ‘**‘,component: NotFoundComponent,// ...
];

@NgModule({
  // imports: [RouterModule.forRoot(routes)],
  imports: [RouterModule.forRoot(routes,{ useHash: true })],//开启hash模式
  exports: [RouterModule],providers: [Auth]
})
export class AppRoutingModule {}

◆ angular + ngrx/store页面状态管理

◆ angular登录、注册验证

export class LoginComponent implements OnInit {
    private formField = {
        tel: ‘‘,pwd: ‘‘
    }
    
    private auth: any
    constructor(
        private router: Router,private store: Store<{}>
    ) {
        let that = this
        this.store.select(‘auth‘).subscribe(v => {
            console.log(v)
            that.auth = v;
        })
    }

    ngOnInit(): void {
        if(this.auth.token){
            this.router.navigate([‘/index‘])
        }
    }

    handleSubmit(){
        let that = this

        if(!this.formField.tel){
            wcPop({ content: ‘手机号不能为空!‘,style: ‘background:#eb5a5c;color:#fff;‘,time: 2 });
        }else if(!checkTel(this.formField.tel)){
            wcPop({ content: ‘手机号格式不正确!‘,time: 2 });
        }else if(!this.formField.pwd){
            wcPop({ content: ‘密码不能为空!‘,time: 2 });
        }else{
            this.store.dispatch(new actions.setToken(getToken(64)))
            this.store.dispatch(new actions.setUser(this.formField.tel))

            wcPop({
                content: ‘登录成功,跳转中...‘,style: ‘background:#378fe7;color:#fff;‘,time: 2,shadeClose: false,end: function () {
                    that.router.navigate([‘/index‘])
                }
            });
        }
    }
}

◆ 编辑器核心消息处理

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,"rn");
    html = html.replace(/<[^img].*?>/ig,"");
    html = html.replace(/&nbsp;/ig,"");
    return html.replace(/rn|n|r/,"").replace(/(?:^[ tnr]+)|(?:[ tnr]+$)/g,"") == "";
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读