最近对人工智能感兴趣,查询之后发现了图灵,开放的机器人接口,自然要实现一把了。

当然了本人页面功底较差,(ps:毕竟主要java吗。)对话框,基本上样式抠的图灵的示例窗口,自己实现各种js的效果。

有什么不完善的地方,大家见谅啊。


一、aichart.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>aichart</title>
<script type="text/javascript" src="/mblog/assets/js/jquery.min.js"></script>
<script type="text/javascript" src="/mblog/assets/tl/tl.js"></script>
<style type="text/css">
.dialog{
width: 150px; 
height: 250px; 
position:fixed;
right:0;
top:10%
}
.dialog img{
 display: block;
    max-width: 100%;
    height: auto;
    width: auto\9;
}
.dialog a:-webkit-any-link {
    color: -webkit-link;
    text-decoration: underline;
    cursor: auto;
}
.dialog .dialog-right{
width:150px; 
height: 250px;
border: 2px solid #C6DAF5;
z-index:999;
    position: fixed;
    right: 0;
}
.dialog .dialog-left{
width:430px;
height: 250px;
 position: fixed;
border: 2px solid #C6DAF5;
z-index:998;
float: right;
right: -300px;
}
.dialog .dialog-right .right-title{
width:100%;
height: 10%;
font-size:12pt;
font-weight:bold;
text-align: center;
border: 2px solid #C6DAF5;
background-color: #C6DAF5;
}
.dialog .dialog-right .right-pic{
width:100%;
height: 90%;
background:url(assets/images/ai/timg.png) center;
}
.dialog-left .chart-area{
 width: 440px;
    height: 250px;
    border: #dbdada solid 1px;
    -ms-box-shadow: 0 0 5px 0 #dbdada;
    -moz-box-shadow: 0 0 5px 0 #dbdada;
    -webkit-box-shadow: 0 0 5px 0 #dbdada;
    -o-box-shadow: 0 0 5px 0 #dbdada;
    box-shadow: 0 0 5px 0 #dbdada;
    background: #fff;
    overflow: hidden;
    position: relative;
    z-index:998;
}
.dialog-left .chart-area .roll{
    width: 2px;
    height: 200px;
    position: absolute;
    right: 12px;
    top: 20px;
    background: #ededed;
    z-index: 5;
    display: none;
}
.chart-area .roll span {
    width: 6px;
    height: 26px;
    background: #ededed;
    position: absolute;
    left: -2px;
    top: 0px;
    -ms-border-radius: 3px;
    -moz-border-radius: 3px;
    -webkit-border-radius: 3px;
    -o-border-radius: 3px;
    border-radius: 3px;
    cursor: pointer;
}
.displayArea {
    margin-top: 3px;
    width: 430px;
    height: 200px;
    overflow-y: scroll;
    border-bottom: #f0f0f0 solid 1px;
    position: relative;
    overflow:auto;
 }
.rotWord {
width:100%;
overflow:hidden;
    margin-bottom: 8px;
}
.rotWord1 {
width:100%;
overflow:hidden;
    margin-bottom: 8px;
}
.rotWord span {
    background: url(assets/images/ai/timg.png) no-repeat;
    height: 30px;
    width: 30px;
    float: left;
    margin-left: 5px;
}
.rotWord1 span {
    background: url(assets/images/ai/timg.png) no-repeat;
    height: 30px;
    width: 30px;
    float: left;
    margin-left: 5px;
}
.rotWord1 .findMsg{
    float: left;
    margin-left: 14px;
    width: 210px;
    padding-bottom: 10px;
    background: #f1f1f1;
    -ms-border-radius: 8px;
    -moz-border-radius: 8px;
    -webkit-border-radius: 8px;
    -o-border-radius: 8px;
    border-radius: 8px;
    position: relative;
}
.rotWord1 .findMsg i{
    position: absolute;
    width: 0;
    height: 0;
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
    border-right: 6px solid #f1f1f1;
    left: -6px;
    top: 14px;
}
.rotWord1 .findMsg .main{
    width: 188px;
    border: #dcdcdc solid 1px;
    margin: 10px auto 0;
    -ms-border-radius: 4px;
    -moz-border-radius: 4px;
    -webkit-border-radius: 4px;
    -o-border-radius: 4px;
    border-radius: 4px;
}
.rotWord1 .findMsg .pic{
position: relative;
}
.rotWord1 .findMsg .pic img{
display: block;
    width: 188px;
    height: 74px;
}
.rotWord1 .findMsg p{
font-size: 12px;
    height: 16px;
    line-height: 16px;
    text-align: center;
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    background: rgba(0,0,0,0.5);
    color: #fff;
}
.rotWord1 .findMsg a{
text-decoration: none;
}
.rotWord1 .findMsg .info{
height: 36px;
    padding: 2px 6px;
    background: #fff;
}
.rotWord1 .findMsg .info img{
float: right;
    width: 25px;
    height: 25px;
    margin: 6px 7px 0 0;
}
.rotWord1 .findMsg .info .make{
float: left;
    width: 140px;
    line-height: 38px;
    height: 38px;
    font-size: 12px;
    color: #8e8c8c;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}
.rotWord1 .findMsg .line{
height: 1px;
    background: #dcdcdc;
}
.rotWord p {
    word-break: break-all;
    float: left;
    color: #333;
    font-size: 14px;
    padding: 3px 15px;
    line-height: 24px;
    background: #f1f1f1;
    -ms-border-radius: 6px;
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    -o-border-radius: 6px;
    border-radius: 6px;
    position: relative;
    max-width: 220px;
    margin: 0px 0px 0px 14px;
}
.rotWord p a{
color: #2373be;
text-decoration: none;
}
.rotWord p i{
position: absolute;
    width: 0;
    height: 0;
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
    border-right: 6px solid #f1f1f1;
    left: -6px;
    top: 10px;
}
.mWord {
width:100%;
overflow:hidden;
    margin-bottom: 5px;
}
.mWord span {
    background: url(assets/images/ai/timg.png) no-repeat;
    height: 30px;
    width: 30px;
    float: right;
    margin-right: 5px;
}
.mWord p {
    word-break: break-all;
    float: right;
    color: #fff;
    font-size: 14px;
    padding: 3px 15px;
    line-height: 24px;
    background: #19b955;
    -ms-border-radius: 6px;
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    -o-border-radius: 6px;
    border-radius: 6px;
    position: relative;
    max-width: 210px;
    margin: 0px 14px 0px 0px;
}
.mWord p i{
    position: absolute;
    width: 0;
    height: 0;
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
    border-left: 6px solid #19b955;
    right: -6px;
    top: 10px;
}
.writeArea {
    height: 30px;
    margin-top: 10px;
}
.writeArea input {
    width: 330px;
    height: 25px;
    line-height: 25px;
    float: left;
    margin-left: 12px;
    border: #d0cfcf solid 1px;
    -ms-border-radius: 4px;
    -moz-border-radius: 4px;
    -webkit-border-radius: 4px;
    -o-border-radius: 4px;
    border-radius: 4px;
    text-indent: 14px;
    -ms-box-shadow: 1px 1px 2px 0 #d0cfcf;
    -moz-box-shadow: 1px 1px 2px 0 #d0cfcf;
    -webkit-box-shadow: 1px 1px 2px 0 #d0cfcf;
    -o-box-shadow: 1px 1px 2px 0 #d0cfcf;
    box-shadow: 1px 1px 2px 0 #d0cfcf;
    font-size: 14px;
}
.writeArea span {
    cursor: pointer;
    float: left;
    margin-left: 12px;
    color: #fff;
    font-size: 14px;
    width: 40px;
    height: 25px;
    text-align: center;
    line-height: 25px;
    -ms-border-radius: 4px;
    -moz-border-radius: 4px;
    -webkit-border-radius: 4px;
    -o-border-radius: 4px;
    border-radius: 4px;
    background: #00a3f0;
}
</style>
</head>
<body style="height:1500px">
<div id="ai_chart_dialog" class="dialog">
<div class="dialog-right">
<div class="right-title">小智</div>
<div class="right-pic"></div>
</div>
<div class="dialog-left">
<div class="chart-area">
<div  class="roll" style="display: none;"><span class="point" style="top: 0px;"></span></div>
                <div class="displayArea" >
                    <div  class="diswap">
                        <div class="rotWord"> <span></span> <p id="member">小娜在此<i></i></p></div>
                    </div>
                </div>
                <div class="writeArea">
                    <input type="text" maxlength="200" placeholder="聊点什么吧">
                    <span >发 送</span>
                </div>
</div>
</div>
</div>
<script type="text/javascript">
var tuling_button = $('#ai_chart_dialog .dialog-left .writeArea span');//document.getElementById("tuling_button");
function getLen(val){
var len = 0;  
  for (var i=0; i<val.length; i++) {  
    if (val.charCodeAt(i)>127 || val.charCodeAt(i)==94) {  
       len += 2;  
     } else {  
       len ++;  
     }  
   }  
return len;
}
function talk(){
//获取输入值
var input = $('#ai_chart_dialog .dialog-left .writeArea input');//document.getElementById("tuling_input");
var val = input.val();
var tuling_dialog = $('#ai_chart_dialog .dialog-left .displayArea .diswap');//document.getElementById("tuling_dialog");
var len = getLen(val);
if(len <=0){
//添加机器人回话
tuling_dialog.append("<div class='rotWord' ><span></span><p>还是说点什么吧?<i></i></p></div>");
//滚动条自动到底
}else if(len >32){
//添加机器人回话
tuling_dialog.append("<div class='rotWord' ><span></span><p>好长的句子啊,理解不了了:(<i></i></p></div>");
}else{
//添加自己的问题
tuling_dialog.append("<div class='mWord'><span></span><p>"+val+"<i></i></p></div>");
//发送请求
$.post("AI/tl",{info:val},function(result){
var obj = eval('(' + result + ')');
    if(obj.code == 0){
    tuling_dialog.append(AITL.parseResult(AITL.toJson(obj.data)));
    $('#ai_chart_dialog .dialog-left .displayArea').scrollTop($('#ai_chart_dialog .dialog-left .displayArea')[0].scrollHeight);
    }else{
    alert("error");
    $('#ai_chart_dialog .dialog-left .displayArea').scrollTop($('#ai_chart_dialog .dialog-left .displayArea')[0].scrollHeight);
    }
  });
}
//滚动条自动到底
$('#ai_chart_dialog .dialog-left .displayArea').scrollTop($('#ai_chart_dialog .dialog-left .displayArea')[0].scrollHeight);// = $('#ai_chart_dialog .dialog-left .displayArea').height();
//清空输入值
input.val("");
}
//绑定回车输入
$('#ai_chart_dialog .dialog-left .writeArea input').bind('keyup', function(event) {
if (event.keyCode == "13") {
//回车执行查询
talk();
}
});
//绑定点击发送时间
$('#ai_chart_dialog .dialog-left .writeArea span').click(function(){
talk();
});
$(function(){
var expanded = true;
$('#ai_chart_dialog .dialog-right').click(function(){
if(expanded){
$('#ai_chart_dialog').width(600);
$('#ai_chart_dialog .dialog-left').animate({right:'150px'},100);
}else{
$('#ai_chart_dialog').width(150);
$('#ai_chart_dialog .dialog-left').animate({right:'-300px'},100);
}
expanded = !expanded;
});
});
</script>
</body>
</html>


二、tl.js


function AITL() {
function error(){
return "<div class='rotWord' ><span></span><p>小娜好像生病了,麻烦找找站长医生给看看吧:(<i></i></p></div>";
}
function isJson(resjson){
var isjson = typeof(obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == "[object object]" && !obj.length; 
return isjson;
};
this.parseText = function(resjson){
var res="";
if(isJson(resjson)){
res = error();
}else{
res = "<div class='rotWord' ><span></span><p>"+resjson.text+"<i></i></p></div>";
}
return res;
};
this.parseLink = function(resjson){
var res="";
if(isJson(resjson)){
res = error();
}else{
res = "<div class='rotWord' ><span></span><p>"+resjson.text+"<a href='"+resjson.url+"' target=\"_blank\">打开页面</a><i></i></p></div>";
}
return res;
};
this.parseNews = function(resjson){
var res="";
if(isJson(resjson)){
res = error();
}else{
 res = "<div class=\"rotWord1 \">"+
"<span></span> " +
"<div class=\"findMsg\"> " +
"<i></i> " +
"<div class=\"main\"> " ;
var newslist =  resjson.list;
for(var j=0;j<newslist.length;j++){
var news = newslist[j];
if(j==0){
res = res+
"<div class=\"pic\">" +
"<p>"+news.article+"</p> " +
"<a href=\"" + news.detailurl + "\" target=\"_blank\">" +
"<img src=\""+news.icon+"\" alt=\"\">" +
"</a> " +
"</div> ";
}else if(j==newslist.length-1){
res = res+
"<div class=\"info\"> " +
"<a href=\""+news.detailurl+"\" target=\"_blank\"> " +
"<div class=\"make\">"+news.article+"</div> " +
"</a>" +
"<a href=\""+news.detailurl+"\" target=\"_blank\">" +
"<img src=\""+news.icon+"\" alt=\"\">" +
"</a> " +
"</div> " +
"</div> " +
"</div> " +
"</div>";
}else{
res = res+
"<div class=\"info\"> " +
"<a href=\""+news.detailurl+"\" target=\"_blank\"> " +
"<div class=\"make\">"+news.article+"</div> " +
"</a>" +
"<a href=\""+news.detailurl+"\" target=\"_blank\">" +
"<img src=\""+news.icon+"\" alt=\"\">" +
"</a> " +
"</div> " +
"<div class=\"line\"></div> ";
}
}
}
return res;
};
this.parseFood = function(resjson){
var res="";
if(isJson(resjson)){
res = error();
}else{
res = "<div class=\"rotWord1 clearfix\"> " +
"<span></span> " +
"<div class=\"findMsg\"> " +
"<i></i> " +
"<div class=\"main\">";
var foodlist =  resjson.list;
for(var j=0;j<foodlist.length;j++){
var food = foodlist[j];
if(j==foodlist.length-1){
res = res +
"<div class=\"info\"> " +
"<a href=\""+food.detailurl+"\" target=\"_blank\"> " +
"<div class=\"make\">"+food.info+"</div> " +
"</a>" +
"</div>" +
"</div> " +
"</div> " +
"</div>";
}else{
res = res +
"<div class=\"info\"> " +
"<a href=\""+food.detailurl+"\" target=\"_blank\"> " +
"<div class=\"make\">"+food.info+"</div> " +
"</a>" +
"</div> " +
"<div class=\"line\"></div>";
}
}
}
return res;
};
this.parseErGe = function(resjson){
var res = "";
return res;
};
this.parseShiCi = function(resjson){
var res = "";
return res;
};
this.parseError = function(resjson){
var res = "";
if(isJson(resjson)){
res = error();
}else{
if(resjson.code == 40002){
res = "<div class='rotWord' ><span></span><p>还是说点什么吧。<i></i></p></div>";
}else if(resjson.code == 40004){
res = "<div class='rotWord' ><span></span><p>她下班了,明天再来玩吧。<i></i></p></div>";
}else{
res = error();
}
}
return res;
};
this.parseNOCODE = function(resjson){
var res = "";
if(isJson(resjson)){
res = error();
}else{
res = error();
}
return res;
};
};
AITL.toJson = function(str)
{
return JSON.parse(str);
};
AITL.parseResult = function(resjson)
{
var a = new AITL();
var code = resjson.code;
if (code == 100000) {
return a.parseText(resjson);
} else if (code == 200000) {
return a.parseLink(resjson);
} else if (code == 302000) {
return a.parseNews(resjson);
} else if (code == 308000) {
return a.parseFood(resjson);
} else if (code == 313000) {
return a.parseErGe(resjson);
} else if (code == 314000) {
return a.parseShiCi(resjson);
} else if (code == 40001 || code ==40002 || code == 40004 || code ==4007) {
return a.parseError(resjson);
} else{
return a.parseNOCODE(resjson);
}
}

三、后端java
controller 这个只给有用的部分吧,毕竟用什么框架的都有自己弄个就好了

String userid = request.getSession().getId();
//图灵网站上的secret
//待加密的json数据
String data = "{\"key\":\""+apiKey+"\",\"info\":\""+info+"\",\"userid\":\""+userid+"\"}";
//获取时间戳
String timestamp = String.valueOf(System.currentTimeMillis());
//生成密钥
String keyParam = secret+timestamp+apiKey;
String key = Md5.MD5(keyParam);
//加密
Aes mc = new Aes(key);
data = mc.encrypt(data);
//封装请求参数
JSONObject json = new JSONObject();
json.put("key", apiKey);
json.put("timestamp", timestamp);
json.put("data", data);
//请求图灵api
String result = PostServer.SendPost(json.toString(), url);

使用到的其他的类,是图灵给的demo里面的东西。也贴出来吧。

Aes.java
package org.mblog.tlai.util;
import java.security.Key;
import java.security.MessageDigest;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
/**
 * aes加密算法
 * @author 图灵机器人
 *
 */
public class Aes {
private Key key;
/**
 * AES CBC模式使用的Initialization Vector
 */
private IvParameterSpec iv;
/**
 * Cipher 物件
 */
private Cipher cipher;
/**
 * 构造方法
 * @param strKet 
 * 密钥
 */
public Aes(String strKey) {
try {
this.key = new SecretKeySpec(getHash("MD5", strKey), "AES");
this.iv = new IvParameterSpec(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 });
this.cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
} catch (final Exception ex) {
throw new RuntimeException(ex.getMessage());
}
}
/**
 * 加密方法
 * 
 * 说明:采用128位
 * 
 * @return 加密结果
 */
public String encrypt(String strContent) {
try {
byte[] data = strContent.getBytes("UTF-8");
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] encryptData = cipher.doFinal(data);
String encryptResult = new String(Base64.encodeBase64(
encryptData), "UTF-8");
return encryptResult;
} catch (Exception ex) {
throw new RuntimeException(ex.getMessage());
}
}
/**
 * 
 * @param algorithm
 * @param text
 * @return
 */
private static byte[] getHash(String algorithm, String text) {
try {
byte[] bytes = text.getBytes("UTF-8");
final MessageDigest digest = MessageDigest.getInstance(algorithm);
digest.update(bytes);
return digest.digest();
} catch (final Exception ex) {
throw new RuntimeException(ex.getMessage());
}
}
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Md5.java
package org.mblog.tlai.util;
import java.security.MessageDigest;
/**
 * md5加密
 * @author 图灵机器人
 *
 */
public class Md5 {
/**
 * MD5加密算法
 * 
 * 说明:32位加密算法
 * 
 * @param 待加密的数据
 * @return 加密结果,全小写的字符串
 */
public static String MD5(String s) {
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f' };
try {
byte[] btInput = s.getBytes("utf-8");
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
mdInst.update(btInput);
// 获得密文
byte[] md = mdInst.digest();
// 把密文转换成十六进制的字符串形式
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

++++++++++++++++++++++++++++++++++++++++++


PostServer.java
package org.mblog.tlai.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
/**
 * HTTP工具类
 * @author 图灵机器人
 *
 */
public class PostServer {
/**
 * 向后台发送post请求
 * @param param
 * @param url
 * @return
 */
public static String SendPost(String param, String url) {
OutputStreamWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) realUrl
.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setConnectTimeout(50000);
conn.setReadTimeout(50000);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Authorization", "token");
conn.setRequestProperty("tag", "htc_new");
conn.connect();
out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8");
out.write(param);
out.flush();
out.close();
//
in = new BufferedReader(new InputStreamReader(
conn.getInputStream(), "UTF-8"));
String line = "";
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
}




乐享:知识积累,快乐无限。