浏览器太低级了

守口如瓶,笑脸相迎。叩首问路,码梦为生。 --Vace

和一群聊天机器人一起聊天吧

2015/12/31    前端


目前有很多机器人聊天的接口,如果做个小玩具拉上三五机器人,自己再偶尔插嘴,那么会聊出什么样搞笑的对话呢,本程序只涉及前端开发,机器人聊天可以用市面上一些机器人聊天的接口实现- -.

结果展示

结果展示

前期构思

很简单,我们希望这款应用具备以下功能

  • 拉机器人进入讨论组
  • 踢出机器人
  • 机器人能根据当前聊天信息做出回复
  • 我也能参与聊天
  • 简单的实现一些特殊功能,表情(TODO)
  • 有个不错的界面(0_0 我这个聊天的UI,是照着MAC上的QQ裸切的…😄)

实现

文件结构

.
├── README.md
├── dist  # 程序打包记录
├── index.html # 应用入口
├── node_modules
├── package.json
├── src # 应用目录
│   ├── app.vue
│   ├── assets # 静态资源
│   ├── brick # 聊天窗口组件
│   │   ├── friend.vue # 好友栏
│   │   ├── message.vue # 消息栏
│   │   └── status.vue # 状态栏
│   ├── main.js # 入口
│   └── model # 聊天数据model
│       └── message.ts # 消息管理
├── tsconfig.json # typescript 配置文件
└── webpack.config.js # webpack 配置文件

应用基本结构

分析应用我们发现其实主要分为三个部分, 左侧状态栏,中间好友管理,右侧聊天窗口,那么我们希望的应用应该是这样的:

<div class="chat-app">
	<!-- 状态栏 -->
   <status-box></status-box>
   <!-- 好友栏 -->
   <friend-box></friend-box>
   <!-- 消息栏 -->
   <message-box></message-box>
</div>

我们需要的一些数据模型

约定数据类型

  • 消息类型
enum MSG_TYPE { 
	USER,  // 我的消息
	REBOT, // 机器人消息
	NOTIFY, // 通知消息
	SYSTEM,  //系统消息
	SHAKE,  // 抖动消息
	IMAGE , // 图片消息
	FACE  //表情消息
};
  • 消息结构
interface MessageContent{
	// 消息唯一编号
	id:number,
	// 发送者id
	uid:number,
	// 消息类型
	type:number,
	// 发送人名字
	name:string,
	// 发送时间
	time:Date,
	// 发送者头像
	head:string,
	// 发送内容
	content:string
}
  • 聊天参与者结构
interface UserStruct{
	//用户编号
	uid:number,
	//用户名称
	name:string,
	//用户类型
	type:number,
	//用户头像
	head:string,
	//用户消息统计
	count:number,
	//用户加入时间
	enter:Date,
	//用户离开时间
	leave:Date
}

讨论组成员基类

对于讨论组内每个成员都继承的基类

class Talker{
	public user: UserStruct;
	
	/**
	 * [constructor 构造方法]
	 * @param  {[type]}  name:string     [讨论者名字]
	 * @param  {Boolean} isRebot:boolean [是否为机器人]
	 * @return {[Talker]}                  [Talker]
	 */
	public constructor(name:string,isRobot:boolean=false){}

	/**
	 * [speak 说话]
	 * @param {string} content [说的内容]
	 */
	public speak(content:string){}

	/**
	 * [newmsg 新消息]
	 * @param {number} type    [消息类型]
	 * @param {string} content [消息内容]
	 */
	protected newmsg(type:number,content:string){}
	/**
	 * [用户进入加入聊天室]
	 */
	public enter(){}
	/**
	 * [leave 用户离开房间]
	 */
	public leave(){}
	// 获取用户Uid
	private get uid():number{}

创造机器人们

机器人比较简单,只需要继承Talker的全部方法就可以了

class Rebot extends Talker{
	/**
	 * [constructor 创造机器人]
	 * @param  {[type]} robotName:string [机器人名称]
	 * @return {[type]}                  [description]
	 */
	public constructor(robotName:string){
		super(robotName,true);
	}

}

创造我

对于一个聊天应用来说,我其实只有一个,所以我们继承Talker实现一个简单的单例模式吧,这个我由于开了会员具有一些特殊功能,发表情,发图片之类的,所以有一些扩展方法

class User extends Talker{
	/**
	 * [constructor 创建自己]
	 * @return {[type]} [description]
	 */
	public constructor(){
		super('我');
	}
	
	/**
	 * [send 发送特殊消息]
	 * @param  {[type]} type:number [消息类型]
	 */
	public send(type:number){}

	private static _instance: User;
	/**
	 * 单例模式获取实例
	 */
	public static getInstance():User{}
}

管理消息 Message

这个比较长建议大家直接去看源码吧,主要是收集模型中的消息和好友并且对外输出

聊天开局,创建一些机器人

//创建自己
var me = Message.markUser();
//创建三名机器人
var robots = [
  Message.markRebot('哆啦A梦'),
  Message.markRebot('野比大雄'),
  Message.markRebot('源静香'),
  Message.markRebot('骨川小夫')
];

给每个栏目绑定一些数据

上面的模型建立之后,把Message中的数据使用Vue绑定到视图上就可以啦

export default{
	//提供数据
   data () {
    return {
      user:me.user, // 我
      friends: Message.friends,//好友列表
      messages:Message.messages, //消息列表
      message_type:MSG_TYPE, //消息类型
      inputing:Message.inpitingUserInfo //当前输入者,TODO
    }
    //监听一些子组件的事件
    events:{
      /**
       * [speak 我说话]
       * @param  {[type]} msg [消息内容]
       */
      speak:function(msg){
        me.speak(msg);
      },
      /**
       * [send 我发送特殊消息]
       * @param  {[type]} type [消息类型]
       */
      send:function(type){
        me.send(type);
      },
      /**
       * [leave 某个用户离开房间或者被踢出]
       * @param  {[type]} uid [用户唯一编号]
       */
      leave:function(uid){
        Message.leaveRebot(uid);
      },
      /**
       * [createRebot 创建一个新的机器人]
       * @param  {[type]} name [机器人名称]
       */
      createRebot:function(name){
        Message.markRebot(name);
      }
    },
  },
}

接下来,我们要的基本结构就出来咯

<div class="chat-app">
	  <!-- 绑定自己数据信息 -->
      <status-box :user="user"></status-box>
      <!-- 绑定好友列表 -->
      <friend-box :friends="friends"></friend-box>
      <!-- 绑定消息和消息类型 -->
      <message-box :inputing="inputing" :messages="messages" :type="message_type"></message-box>
</div>

最后分别实现status-box,friend-box,message-box的一些数据绑定就ok咯.这三部分比较简单,可以自行查看源码

实现自动对话机制

这个机制目前比较简单,说一下基本原理吧

1.在Message内部实现一个周期为200ms,检测是否到下一个发言周期

this._intvalid = setInterval(() => {
	var _time: number = Date.now();
	if (this._nextreply >= 0 && this._nextreply < _time) {
		//触发回复消息
		this.robotReply();
		//设置下次交流时间
		this._nextreply = _time + this._replyinterval;
	}
},200);
  1. 如果满足发言条件,从消息列表拿到最后一条消息,通过ajax发送消息
let lastmsg:string = Message.messages[Message.messages.length-1].content;
  1. 每次发言成功后,重置发言周期,并且切换下次回答的机器人(切换条件为不能为自己,即不能自己接自己的话)

详细信息可以看演示版

webpack typescript vue

查看演示...

评论加载中...