聊天服務器端,使用上一個文章里面提到的websocket服務器端,
通訊地址格式ws://ip:7878:/c/sec/userid
大致思路,首先去app的服務器登錄,回傳用戶資訊,里面含有用戶編號,通過獲取配置的方式,獲取聊天url,當然,在app里面寫死也可以,我是做成了一個后臺配置項,
app拿到鏈接地址,加上當前用戶的id,使用uni.connectSocket進行鏈接,使用uni.onSocketMessage接收用戶訊息,接收到訊息存到本地sqllite,
進入聊天界面,首先去查詢本地sqllite,顯示歷史訊息,然后通過回呼方式,監聽實時訊息,并顯示,
使用store存盤實時訊息,ws接收到訊息以后,推送到store,頁面對store里面的變數進行watch,實時更新頁面,
效果圖



關鍵代碼1:sqllite.js,完成資料庫初始化,資料操作,注意uniapp使用sqllite需要勾選對應插件,必須真機除錯,
/**
* 封裝了對sqllite基本操作
*/
module.exports = {
dbName: 'chatapp', // 資料庫名稱
dbPath: '_doc/chat.db', // 資料庫地址,推薦以下劃線為開頭 _doc/xxx.db
// 判斷資料庫是否打開
isOpen() {
// 資料庫打開了就回傳 true,否則回傳 false
var open = plus.sqlite.isOpenDatabase({
name: this.dbName, // 資料庫名稱
path: this.dbPath // 資料庫地址
})
return open;
},
// 創建資料庫 或 有該資料庫就打開
openSqlite() {
return new Promise((resolve, reject) => {
// 打開資料庫
plus.sqlite.openDatabase({
name: this.dbName,
path: this.dbPath,
success(e) {
console.log("open sql success")
resolve(e); // 成功回呼
},
fail(e) {
console.log("open database error")
reject(e); // 失敗回呼
}
})
})
},
// 關閉資料庫
closeSqlite() {
return new Promise((resolve, reject) => {
plus.sqlite.closeDatabase({
name: this.dbName,
success(e) {
resolve(e);
},
fail(e) {
reject(e);
}
})
})
},
/**執行增刪改,
* @param {Object} sql
*/
execQuery(sql){
var db=this;
if(this.isOpen()){
return new Promise((resolve, reject) => {
plus.sqlite.executeSql({
name: db.dbName,
sql: sql,
success(e) {
console.log("sql "+ sql+" exectue ok")
resolve(e);
},
fail(e) {
reject(e);
}
})
});
}
else{
return new Promise((resolve, reject) => {
db.openSqlite().then(res=>{
plus.sqlite.executeSql({
name: db.dbName,
sql: sql,
success(e) {
resolve(e);
},
fail(e) {
reject(e);
}
})
}).catch(res=>{
reject({code:1,msg:'open db '+db.dbName +' error'})
})
});
}
},
//查詢
selectQuery(sql){
var db=this;
if(this.isOpen()){
return new Promise((resolve, reject) => {
plus.sqlite.selectSql({
name: db.dbName,
sql: sql,
success(e) {
console.log("sql "+ sql+" exectue ok")
resolve(e);
},
fail(e) {
reject(e);
}
})
});
}
else{
return new Promise((resolve, reject) => {
db.openSqlite().then(res=>{
plus.sqlite.selectSql({
name: db.dbName,
sql: sql,
success(e) {
resolve(e);
},
fail(e) {
reject(e);
}
})
}).catch(res=>{
reject({code:1,msg:'open db '+db.dbName +' error'})
})
});
}
},
/**
* 創建快取表,
*/
createDB(){
var sql='create table if not exists temp("id" INTEGER PRIMARY KEY AUTOINCREMENT,"type" varchar(20),"val" varchar(20),"createtime" varchar(30))';
return this.execQuery(sql);
},
/**
* 創建聊天表
*/
createDBChat(){
var sql='create table if not exists chat("id" INTEGER PRIMARY KEY AUTOINCREMENT,"from" varchar(20),"to" varchar(20),"time" varchar(30),"msg" varchar(400))';
return this.execQuery(sql);
},
/**洗掉一個快取
* @param {Object} id
*/
deleteTemp(id){
return this.execQuery("delete from temp where id="+id);
},
deleteByTypeVal(tp,val){
return this.execQuery("delete from temp where val='"+val+"' and type='"+type+"'");
},
getTempByType(tp){
return this.selectQuery("select * from temp where type='"+tp+"'");
},
getTempByID(id){
return this.selectQuery("select * from temp where id='"+id+"'");
},
//修改資料
updateData(dbTable,data){
//var dbTable='temp';
var db=this;
var sql="update "+dbTable+" set ";
for(var k in data){
sql+="'"+k+"'='"+data[k]+"',"
}
sql=sql.substr(0,sql.length-1)+" where id="+data['id'];
console.log(sql);
return this.execQuery(sql);
},
//增加資料
insertTemp(data){
var dbTable='temp';
var db=this;
console.log(data);
var s1="select count(*) as c from "+dbTable +" where val='"+val+"' and type='"+type+"'";
this.selectQuery(s1).then(res=>{
if(res.length>0 && res[0].c==0){
data.createtime=db.getCurrentTime();
// 判斷傳的參是否有值
var sql="insert into "+dbTable +"(";
var sql2=" values (";
for(var k in data){
sql+="'"+k+"',";
sql2+="'"+data[k]+"',";
}
sql=sql.substr(0,sql.length-1)+")";
sql2=sql2.substr(0,sql2.length-1)+")";
sql=sql+sql2;
//console.log(sql);
db.execQuery(sql).then(res=>{});
}
})
},
//增加資料
insertChat(data){
var dbTable='chat';
var db=this;
console.log(data);
// 判斷傳的參是否有值
var sql="insert into "+dbTable +"(";
var sql2=" values (";
for(var k in data){
sql+="'"+k+"',";
sql2+="'"+data[k]+"',";
}
sql=sql.substr(0,sql.length-1)+")";
sql2=sql2.substr(0,sql2.length-1)+")";
sql=sql+sql2;
//console.log(sql);
return this.execQuery(sql);
},
getCurrentTime() {
var date = new Date();//當前時間
var month = this.zeroFill(date.getMonth() + 1);//月
var day = this.zeroFill(date.getDate());//日
var hour = this.zeroFill(date.getHours());//時
var minute = this.zeroFill(date.getMinutes());//分
var second = this.zeroFill(date.getSeconds());//秒
//當前時間
var curTime = date.getFullYear() + '-' + month + '-' + day + " " + hour + ':' + minute + ':' + second;
return curTime;
},
zeroFill(t){
if(t>=10)return t+"";
else return "0"+t;
}
}
關鍵代碼2:wsocket.js,完成socket鏈接,監聽,發送訊息
import DB from "./sqlite.js"
import store from '@/store/store.js'//引入store,有訊息直接存入
export default{
url:'',//鏈接地址
player:'',//用于播放訊息聲音
setUrl(u){//外部通過這個函式,開啟websocket監聽
var pg=this;
console.log("ws",u);
this.url=u;
uni.connectSocket({//鏈接到ws
url: u,
fail:(err)=>{
console.log("error",err);
},
success(r) {
console.log("success",r)
}
});
uni.onSocketMessage(res=>{
pg.onMessage(res);//把訊息交給當前物件處理
})
},
onMessage(d){
//當前物件處理訊息
this.playSound();//播放聲音
var msg=JSON.parse(d.data);//訊息物件轉換
store.commit('pushMsg',msg);//存入到store
DB.insertChat(msg);//存盤到資料庫
},
sendMessage(d){
//把訊息發出去
uni.sendSocketMessage({
data:JSON.stringify(d)
})
},
playSound(){
//播放聲音
if(this.player==''){
this.player=uni.createInnerAudioContext();//創建播放物件
this.player.autoplay = true;
this.player.onPlay(() => {
console.log('開始播放');
});
this.player.onError((res) => {
console.log("playerror",res);
});
}
this.player.src = '/static/msg.mp3';
}
}
關鍵代碼3,store.js 全域的訊息,供頁面監聽
//參考Vuex
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//實體store并匯出
export default new Vuex.Store({
state: {
count: 0,//用來觸發訊息串列更新,直接監聽chats無法觸發watch,
msg:{},//最后一條訊息,用來給頁面監聽
chats:{},//存盤全域的聊天串列,以用戶標識為key,
users:{},//全域存盤用戶串列,以用戶標識為key
},
mutations: {
pushMsg(state,msg){
/*訊息觸發 */
console.log("pushMsg",msg)
state.msg=msg;//訊息改變,觸發給前臺
state.count++;//計數器增加,為了讓頁面重繪
var cs=state.chats;//先存盤到一個陣列
var name=msg.from;//默認是用戶的標識
if(state.users[msg.from]!=null)name=state.users[msg.from].name;//顯示名稱使用存盤的用戶名
cs[msg.from]={user:name,lastmsg:msg.msg};//聊天資訊,姓名及最后訊息
state.chats=cs;//再保存回去
},
pushMsgTo(state,msg){
/*用戶主動發送訊息*/
state.msg=msg;//訊息改變,觸發給前臺
state.count++;//計數器增加,為了讓頁面重繪
var cs=state.chats;//先存盤到一個陣列
var name=msg.to;//默認是用戶的標識
if(state.users[msg.to]!=null)name=state.users[msg.to].name;//顯示名稱使用存盤的用戶名
cs[msg.to]={user:name,lastmsg:msg.msg};//聊天資訊,姓名及最后訊息
state.chats=cs;//再保存回去
},
setUsers(state,users){
/* 設定用戶串列 ,這個是有app頁面,發起請求,獲取用戶串列,全域存盤*/
for(var i=0;i<users.length;i++){
var u=users[i];
state.users[u.id]=users[i];//更新或者存盤用戶資訊
}
}
}
})
關鍵代碼4,main.js 將wssocket加入原型鏈,啟用store,
import Vue from 'vue'
import App from './App'
import store from './store/store.js'
import ws from "pages/components/wscoket.js"
Vue.config.productionTip = false
App.mpType = 'app'
Vue.prototype.$ws=ws;//掛載websocket
const app = new Vue({
...App,
store
})
app.$mount()
關鍵代碼4,在app.vue 里面對資料庫進行初始化
<script>
import DB from "pages/components/sqlite.js"
export default {
onLaunch: function() {
/**
* 資料庫初始化
*/
DB.createDB().then(res=>{
console.log(res);
DB.createDBChat().then(res=>{
console.log(res);
})
})
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style>
/*每個頁面公共css */
</style>
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/298914.html
標籤:其他
上一篇:mysql主從復制一鍵安裝
