websocket
This commit is contained in:
parent
1e6317c597
commit
ea5478c2fb
172
app/Services/WebSocketService.php
Normal file
172
app/Services/WebSocketService.php
Normal file
@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
@error_reporting(E_ALL & ~E_NOTICE);
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\WebSocket;
|
||||
use App\Module\Base;
|
||||
use App\Tasks\PushTask;
|
||||
use Cache;
|
||||
use Hhxsv5\LaravelS\Swoole\WebSocketHandlerInterface;
|
||||
use Swoole\Http\Request;
|
||||
use Swoole\WebSocket\Frame;
|
||||
use Swoole\WebSocket\Server;
|
||||
|
||||
/**
|
||||
* @see https://wiki.swoole.com/#/start/start_ws_server
|
||||
*/
|
||||
class WebSocketService implements WebSocketHandlerInterface
|
||||
{
|
||||
/**
|
||||
* 声明没有参数的构造函数
|
||||
* WebSocketService constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接建立时触发
|
||||
* @param Server $server
|
||||
* @param Request $request
|
||||
*/
|
||||
public function onOpen(Server $server, Request $request)
|
||||
{
|
||||
global $_A;
|
||||
$_A = [
|
||||
'__static_langdata' => [],
|
||||
];
|
||||
$fd = $request->fd;
|
||||
$data = Base::newTrim($request->get);
|
||||
$action = $data['action'];
|
||||
switch ($action) {
|
||||
/**
|
||||
* 网页访问
|
||||
*/
|
||||
case 'web':
|
||||
{
|
||||
// 判断token参数
|
||||
$token = $data['token'];
|
||||
$cacheKey = "ws::token:" . md5($token);
|
||||
$userid = Cache::remember($cacheKey, now()->addSeconds(1), function () use ($token) {
|
||||
$authInfo = User::authFind('all', $token);
|
||||
if ($authInfo['userid'] > 0) {
|
||||
if (User::whereUserid($authInfo['userid'])->whereEmail($authInfo['email'])->whereEncrypt($authInfo['encrypt'])->exists()) {
|
||||
return $authInfo['userid'];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
if (empty($userid)) {
|
||||
Cache::forget($cacheKey);
|
||||
$server->push($fd, Base::array2json([
|
||||
'type' => 'error',
|
||||
'data' => [
|
||||
'error' => '会员不存在!'
|
||||
],
|
||||
]));
|
||||
$server->close($fd);
|
||||
$this->deleteUser($fd);
|
||||
return;
|
||||
}
|
||||
// 保存用户、发送open事件
|
||||
$this->saveUser($fd, $userid);
|
||||
$server->push($fd, Base::array2json([
|
||||
'type' => 'open',
|
||||
'data' => [
|
||||
'fd' => $fd,
|
||||
],
|
||||
]));
|
||||
// 重试发送失败的消息
|
||||
PushTask::resendTmpMsgForUserid($userid);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到消息时触发
|
||||
* @param Server $server
|
||||
* @param Frame $frame
|
||||
*/
|
||||
public function onMessage(Server $server, Frame $frame)
|
||||
{
|
||||
global $_A;
|
||||
$_A = [
|
||||
'__static_langdata' => [],
|
||||
];
|
||||
//
|
||||
$msg = Base::json2array($frame->data);
|
||||
$type = $msg['type']; // 消息类型
|
||||
$to = $msg['to']; // 发给谁
|
||||
$msgId = $msg['msgId']; // 消息ID(用于回调)
|
||||
$data = $msg['data']; // 消息详情
|
||||
//
|
||||
$reData = [];
|
||||
switch ($type) {
|
||||
/**
|
||||
* 收到回执
|
||||
*/
|
||||
case 'receipt':
|
||||
|
||||
return;
|
||||
}
|
||||
//
|
||||
if ($msgId) {
|
||||
PushTask::push([
|
||||
'fd' => $frame->fd,
|
||||
'msg' => [
|
||||
'type' => 'receipt',
|
||||
'msgId' => $msgId,
|
||||
'data' => $reData,
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭连接时触发
|
||||
* @param Server $server
|
||||
* @param $fd
|
||||
* @param $reactorId
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function onClose(Server $server, $fd, $reactorId)
|
||||
{
|
||||
$this->deleteUser($fd);
|
||||
}
|
||||
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
/** ****************************************************************************** */
|
||||
|
||||
/**
|
||||
* 保存用户
|
||||
* @param $fd
|
||||
* @param $userid
|
||||
*/
|
||||
private function saveUser($fd, $userid)
|
||||
{
|
||||
WebSocket::updateInsert([
|
||||
'key' => md5($fd . '@' . $userid)
|
||||
], [
|
||||
'fd' => $fd,
|
||||
'userid' => $userid,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除用户
|
||||
* @param $fd
|
||||
*/
|
||||
private function deleteUser($fd)
|
||||
{
|
||||
WebSocket::whereFd($fd)->delete();
|
||||
}
|
||||
}
|
@ -52,14 +52,14 @@ class IhttpTask extends AbstractTask
|
||||
{
|
||||
$res = Ihttp::ihttp_request($this->url, $this->post, $this->extra);
|
||||
if ($this->apiWebsocket && $this->apiUserid) {
|
||||
$body = Base::isSuccess($res) ? Base::json2array($res['data']) : $res;
|
||||
$data = Base::isSuccess($res) ? Base::json2array($res['data']) : $res;
|
||||
PushTask::push([
|
||||
'userid' => $this->apiUserid,
|
||||
'msg' => [
|
||||
'messageType' => 'apiWebsocket',
|
||||
'type' => 'apiWebsocket',
|
||||
'apiWebsocket' => $this->apiWebsocket,
|
||||
'apiSuccess' => Base::isSuccess($res),
|
||||
'body' => $body,
|
||||
'data' => $data,
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
@ -112,8 +112,8 @@ class PushTask extends AbstractTask
|
||||
if (!is_array($msg)) {
|
||||
continue;
|
||||
}
|
||||
$messageType = $msg['messageType'];
|
||||
if (empty($messageType)) {
|
||||
$type = $msg['type'];
|
||||
if (empty($type)) {
|
||||
continue;
|
||||
}
|
||||
// 发送对象
|
||||
@ -149,7 +149,7 @@ class PushTask extends AbstractTask
|
||||
$userFail[] = WebSocket::whereFd($fid)->value('userid');
|
||||
}
|
||||
} else {
|
||||
$key = "PUSH::" . $fid . ":" . $messageType . ":" . $key;
|
||||
$key = "PUSH::" . $fid . ":" . $type . ":" . $key;
|
||||
Cache::put($key, [
|
||||
'fd' => $fid,
|
||||
'msg' => $msg,
|
||||
|
25
resources/assets/js/app.js
vendored
25
resources/assets/js/app.js
vendored
@ -38,7 +38,7 @@ const router = new VueRouter({
|
||||
routes
|
||||
});
|
||||
|
||||
//进度条配置
|
||||
// 进度条配置
|
||||
ViewUI.LoadingBar.config({
|
||||
color: '#3fcc25',
|
||||
failedColor: '#ff0000'
|
||||
@ -51,28 +51,27 @@ router.afterEach((to, from, next) => {
|
||||
ViewUI.LoadingBar.finish();
|
||||
});
|
||||
|
||||
//加载函数
|
||||
// 加载函数
|
||||
Vue.prototype.goForward = function(location, isReplace) {
|
||||
if (typeof location === 'string') location = {name: location};
|
||||
if (isReplace === true) {
|
||||
this.$router.replace(location);
|
||||
app.$router.replace(location).then(() => {});
|
||||
}else{
|
||||
this.$router.push(location);
|
||||
app.$router.push(location).then(() => {});
|
||||
}
|
||||
};
|
||||
|
||||
//返回函数
|
||||
// 返回函数
|
||||
Vue.prototype.goBack = function (number) {
|
||||
let history = $A.jsonParse(window.sessionStorage['__history__'] || '{}');
|
||||
if ($A.runNum(history['::count']) > 2) {
|
||||
this.$router.go(typeof number === 'number' ? number : -1);
|
||||
app.$router.go(typeof number === 'number' ? number : -1);
|
||||
} else {
|
||||
this.$router.replace(typeof number === "object" ? number : {path: '/'});
|
||||
app.$router.replace(typeof number === "object" ? number : {path: '/'}).then(() => {});
|
||||
}
|
||||
};
|
||||
|
||||
Vue.prototype.$A = $A;
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
const app = new Vue({
|
||||
@ -83,4 +82,12 @@ const app = new Vue({
|
||||
components: { App }
|
||||
});
|
||||
|
||||
$A.app = app;
|
||||
|
||||
$A.goForward = app.goForward;
|
||||
$A.goBack = app.goBack;
|
||||
$A.getLanguage = app.getLanguage;
|
||||
$A.Message = app.$Message;
|
||||
$A.Notice = app.$Notice;
|
||||
$A.Modal = app.$Modal;
|
||||
$A.store = app.$store;
|
||||
$A.L = app.$L;
|
||||
|
67
resources/assets/js/functions/common.js
vendored
67
resources/assets/js/functions/common.js
vendored
@ -1264,65 +1264,14 @@
|
||||
if (typeof params.method === 'undefined') params.method = 'GET';
|
||||
if (typeof params.timeout === 'undefined') params.timeout = 30000;
|
||||
if (typeof params.dataType === 'undefined') params.dataType = 'json';
|
||||
if (typeof params.beforeSend === 'undefined') params.beforeSend = () => { };
|
||||
if (typeof params.before === 'undefined') params.before = () => { };
|
||||
if (typeof params.complete === 'undefined') params.complete = () => { };
|
||||
if (typeof params.afterComplete === 'undefined') params.afterComplete = () => { };
|
||||
if (typeof params.after === 'undefined') params.after = () => { };
|
||||
if (typeof params.success === 'undefined') params.success = () => { };
|
||||
if (typeof params.error === 'undefined') params.error = () => { };
|
||||
if (typeof params.header == 'undefined') params.header = {};
|
||||
//
|
||||
let loadText = "数据加载中.....";
|
||||
let busyNetwork = "网络繁忙,请稍后再试!";
|
||||
if (typeof $A.app === 'object' && typeof $A.app.$L === 'function') {
|
||||
loadText = $A.app.$L(loadText);
|
||||
busyNetwork = $A.app.$L(busyNetwork);
|
||||
}
|
||||
//
|
||||
let toastID = null, beforeTitle = '', errorTitle = '';
|
||||
if (typeof $A.app === 'object' && typeof $A.app.$Message === 'object') {
|
||||
if (typeof params.beforeSend === 'string') {
|
||||
beforeTitle = params.beforeSend;
|
||||
params.beforeSend = () => { toastID = $A.app.$Message.loading({content:beforeTitle, duration: 0}); };
|
||||
}else if (params.beforeSend === true) {
|
||||
params.beforeSend = () => { toastID = $A.app.$Message.loading({content:loadText, duration: 0}); };
|
||||
}
|
||||
if (typeof params.error === 'string') {
|
||||
errorTitle = params.error;
|
||||
params.error = () => { $A.app.$Message.error({content:errorTitle, duration: 5}); };
|
||||
}else if (params.error === true) {
|
||||
params.error = () => { $A.app.$Message.error({content:busyNetwork, duration: 5}); };
|
||||
}
|
||||
if (params.complete === true) {
|
||||
params.complete = () => { toastID?toastID():'' };
|
||||
}
|
||||
}else{
|
||||
if (typeof params.beforeSend === 'string') {
|
||||
beforeTitle = params.beforeSend;
|
||||
params.beforeSend = () => { toastID = $A.toast({title:beforeTitle, fixed: true, timeout: false}); };
|
||||
}else if (params.beforeSend === true) {
|
||||
params.beforeSend = () => { toastID = $A.toast({title:loadText, fixed: true, timeout: false}); };
|
||||
}
|
||||
if (typeof params.error === 'string') {
|
||||
errorTitle = params.error;
|
||||
params.error = () => { $A.toast(errorTitle, "danger"); };
|
||||
}else if (params.error === true) {
|
||||
params.error = () => { $A.toast(busyNetwork, "danger"); };
|
||||
}
|
||||
if (params.complete === true) {
|
||||
params.complete = () => { toastID?$A.toast(toastID):'' };
|
||||
}
|
||||
}
|
||||
//
|
||||
let language = window.localStorage['__language:type__'] || 'en';
|
||||
if (typeof $A.app === 'object') {
|
||||
language = $A.app.languageType || language;
|
||||
}
|
||||
//
|
||||
if (typeof params.header !== 'object') params.header = {};
|
||||
params.header['Content-Type'] = 'application/json';
|
||||
params.header['language'] = language;
|
||||
//
|
||||
params.data['__Access-Control-Allow-Origin'] = true;
|
||||
params.beforeSend();
|
||||
params.before();
|
||||
$A.ihttp({
|
||||
url: params.url,
|
||||
data: params.data,
|
||||
@ -1333,15 +1282,15 @@
|
||||
crossDomain: true,
|
||||
dataType: params.dataType,
|
||||
timeout: params.timeout,
|
||||
success: function(data, status, xhr) {
|
||||
success: function (data, status, xhr) {
|
||||
params.complete();
|
||||
params.success(data, status, xhr);
|
||||
params.afterComplete(true);
|
||||
params.after(true);
|
||||
},
|
||||
error: function(xhr, status) {
|
||||
error: function (xhr, status) {
|
||||
params.complete();
|
||||
params.error(xhr, status);
|
||||
params.afterComplete(false);
|
||||
params.after(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
566
resources/assets/js/functions/web.js
vendored
566
resources/assets/js/functions/web.js
vendored
@ -35,32 +35,28 @@
|
||||
},
|
||||
|
||||
apiAjax(params) {
|
||||
if (typeof params !== 'object') return false;
|
||||
if (!$A.isJson(params)) return false;
|
||||
if (typeof params.success === 'undefined') params.success = () => { };
|
||||
if (typeof params.header !== 'object') params.header = {};
|
||||
if (typeof params.header === 'undefined') params.header = {};
|
||||
params.url = this.apiUrl(params.url);
|
||||
params.header['token'] = $A.app.$store.state.userToken;
|
||||
params.header['Content-Type'] = 'application/json';
|
||||
params.header['language'] = $A.getLanguage();
|
||||
params.header['token'] = $A.store.state.userToken;
|
||||
//
|
||||
let beforeCall = params.beforeSend;
|
||||
params.beforeSend = () => {
|
||||
let beforeCall = params.before;
|
||||
params.before = () => {
|
||||
$A.aAjaxLoadNum++;
|
||||
$A(".w-spinner").show();
|
||||
//
|
||||
if (typeof beforeCall == "function") {
|
||||
beforeCall();
|
||||
}
|
||||
$A(".common-spinner").show();
|
||||
typeof beforeCall == "function" && beforeCall();
|
||||
};
|
||||
//
|
||||
let completeCall = params.complete;
|
||||
params.complete = () => {
|
||||
$A.aAjaxLoadNum--;
|
||||
if ($A.aAjaxLoadNum <= 0) {
|
||||
$A(".w-spinner").hide();
|
||||
}
|
||||
//
|
||||
if (typeof completeCall == "function") {
|
||||
completeCall();
|
||||
$A(".common-spinner").hide();
|
||||
}
|
||||
typeof completeCall == "function" && completeCall();
|
||||
};
|
||||
//
|
||||
let callback = params.success;
|
||||
@ -71,7 +67,7 @@
|
||||
$A.modalError({
|
||||
content: data.msg,
|
||||
onOk: () => {
|
||||
$A.userLogout();
|
||||
$A.logout();
|
||||
}
|
||||
});
|
||||
return;
|
||||
@ -79,7 +75,7 @@
|
||||
if (data.ret === -2 && params.role !== false) {
|
||||
//没有权限
|
||||
$A.modalError({
|
||||
content: data.msg ? data.msg : "你没有相关的权限查看或编辑!"
|
||||
content: data.msg || "你没有相关的权限查看或编辑!"
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -96,46 +92,47 @@
|
||||
if (WListener) {
|
||||
WListener.complete();
|
||||
WListener.error("timeout");
|
||||
WListener.afterComplete();
|
||||
WListener.after();
|
||||
}
|
||||
}, params.timeout || 30000);
|
||||
$A.aAjaxWsListener.push({
|
||||
apiWebsocket: apiWebsocket,
|
||||
complete: typeof params.complete === "function" ? params.complete : () => { },
|
||||
afterComplete: typeof params.afterComplete === "function" ? params.afterComplete : () => { },
|
||||
after: typeof params.after === "function" ? params.after : () => { },
|
||||
success: typeof params.success === "function" ? params.success : () => { },
|
||||
error: typeof params.error === "function" ? params.error : () => { },
|
||||
});
|
||||
//
|
||||
params.complete = () => { };
|
||||
params.afterComplete = () => { };
|
||||
params.after = () => { };
|
||||
params.success = () => { };
|
||||
params.error = () => { };
|
||||
params.header['Api-Websocket'] = apiWebsocket;
|
||||
//
|
||||
if ($A.aAjaxWsReady === false) {
|
||||
$A.aAjaxWsReady = true;
|
||||
$A.WSOB.setOnMsgListener("apiWebsocket", [
|
||||
'apiWebsocket',
|
||||
], (msgDetail) => {
|
||||
switch (msgDetail.messageType) {
|
||||
case 'apiWebsocket':
|
||||
clearTimeout(apiTimeout);
|
||||
const apiWebsocket = msgDetail.apiWebsocket;
|
||||
const apiSuccess = msgDetail.apiSuccess;
|
||||
const apiResult = msgDetail.body;
|
||||
const WListener = $A.aAjaxWsListener.find((item) => item.apiWebsocket == apiWebsocket);
|
||||
$A.aAjaxWsListener = $A.aAjaxWsListener.filter((item) => item.apiWebsocket != apiWebsocket);
|
||||
if (WListener) {
|
||||
WListener.complete();
|
||||
if (apiSuccess) {
|
||||
WListener.success(apiResult);
|
||||
} else {
|
||||
WListener.error(apiResult);
|
||||
$A.store.commit("wsMsgListener", {
|
||||
name: "apiWebsocket",
|
||||
callback: (msg) => {
|
||||
switch (msg.type) {
|
||||
case 'apiWebsocket':
|
||||
clearTimeout(apiTimeout);
|
||||
const apiWebsocket = msg.apiWebsocket;
|
||||
const apiSuccess = msg.apiSuccess;
|
||||
const apiResult = msg.data;
|
||||
const WListener = $A.aAjaxWsListener.find((item) => item.apiWebsocket == apiWebsocket);
|
||||
$A.aAjaxWsListener = $A.aAjaxWsListener.filter((item) => item.apiWebsocket != apiWebsocket);
|
||||
if (WListener) {
|
||||
WListener.complete();
|
||||
if (apiSuccess) {
|
||||
WListener.success(apiResult);
|
||||
} else {
|
||||
WListener.error(apiResult);
|
||||
}
|
||||
WListener.after();
|
||||
}
|
||||
WListener.afterComplete();
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -148,454 +145,13 @@
|
||||
aAjaxWsListener: [],
|
||||
|
||||
/**
|
||||
* 打开登录页面
|
||||
* 登出(打开登录页面)
|
||||
*/
|
||||
userLogout() {
|
||||
logout() {
|
||||
const from = window.location.pathname == '/' ? '' : encodeURIComponent(window.location.href);
|
||||
$A.app.$store.commit('setUserInfo', {});
|
||||
$A.app.goForward({path: '/login', query: from ? {from: from} : {}}, true);
|
||||
$A.store.commit('setUserInfo', {});
|
||||
$A.goForward({path: '/login', query: from ? {from: from} : {}}, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* 权限是否通过
|
||||
* @param role
|
||||
* @returns {boolean}
|
||||
*/
|
||||
identityCheck(role) {
|
||||
const userInfo = $A.app.$store.state.userInfo;
|
||||
return $A.identityRaw(role, userInfo.identity);
|
||||
},
|
||||
|
||||
/**
|
||||
* 权限是否通过
|
||||
* @param role
|
||||
* @param identity
|
||||
* @returns {boolean}
|
||||
*/
|
||||
identityRaw(role, identity) {
|
||||
let isRole = false;
|
||||
$A.each(identity, (index, res) => {
|
||||
if (res === role) {
|
||||
isRole = true;
|
||||
}
|
||||
});
|
||||
return isRole;
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* =============================================================================
|
||||
* **************************** websocket assist ***************************
|
||||
* =============================================================================
|
||||
*/
|
||||
$.extend({
|
||||
/**
|
||||
* @param config {userid, url, token, logCallback}
|
||||
*/
|
||||
WTWS: function (config) {
|
||||
this.__instance = null;
|
||||
this.__connected = false;
|
||||
this.__callbackid = {};
|
||||
this.__openNum = 0;
|
||||
this.__autoNum = 0;
|
||||
this.__lastSend = 0;
|
||||
|
||||
this.__autoLine = function (timeout) {
|
||||
var tempNum = this.__autoNum;
|
||||
var thas = this;
|
||||
setTimeout(function () {
|
||||
if (tempNum === thas.__autoNum) {
|
||||
thas.__autoNum++
|
||||
if (!thas.__config.token) {
|
||||
thas.__log("[WS] No token");
|
||||
thas.__autoLine(timeout);
|
||||
} else {
|
||||
// 发refresh之前判断10秒内没有使用过sendTo的再发送refresh
|
||||
if (thas.__lastSend + 10 < Math.round(new Date().getTime() / 1000)) {
|
||||
thas.sendTo('refresh', function (res) {
|
||||
thas.__log("[WS] Connection " + (res.status ? 'success' : 'error'));
|
||||
thas.__autoLine(timeout);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}, Math.min(timeout, 30) * 1000);
|
||||
}
|
||||
this.__log = function (text, event) {
|
||||
typeof this.__config.logCallback === "function" && this.__config.logCallback(text, event);
|
||||
}
|
||||
this.__lExists = function (string, find, lower) {
|
||||
string += "";
|
||||
find += "";
|
||||
if (lower !== true) {
|
||||
string = string.toLowerCase();
|
||||
find = find.toLowerCase();
|
||||
}
|
||||
return (string.substring(0, find.length) === find);
|
||||
}
|
||||
this.__rNum = function (str, fixed) {
|
||||
var _s = Number(str);
|
||||
if (_s + "" === "NaN") {
|
||||
_s = 0;
|
||||
}
|
||||
if (/^[0-9]*[1-9][0-9]*$/.test(fixed)) {
|
||||
_s = _s.toFixed(fixed);
|
||||
var rs = _s.indexOf('.');
|
||||
if (rs < 0) {
|
||||
_s += ".";
|
||||
for (var i = 0; i < fixed; i++) {
|
||||
_s += "0";
|
||||
}
|
||||
}
|
||||
}
|
||||
return _s;
|
||||
}
|
||||
this.__jParse = function (str, defaultVal) {
|
||||
if (str === null) {
|
||||
return defaultVal ? defaultVal : {};
|
||||
}
|
||||
if (typeof str === "object") {
|
||||
return str;
|
||||
}
|
||||
try {
|
||||
return JSON.parse(str);
|
||||
} catch (e) {
|
||||
return defaultVal ? defaultVal : {};
|
||||
}
|
||||
}
|
||||
this.__randString = function (len) {
|
||||
len = len || 32;
|
||||
var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678oOLl9gqVvUuI1';
|
||||
var maxPos = $chars.length;
|
||||
var pwd = '';
|
||||
for (var i = 0; i < len; i++) {
|
||||
pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
|
||||
}
|
||||
return pwd;
|
||||
}
|
||||
this.__urlParams = function(url, params) {
|
||||
if (typeof params === "object" && params !== null) {
|
||||
url+= "";
|
||||
url+= url.indexOf("?") === -1 ? '?' : '';
|
||||
for (var key in params) {
|
||||
if (!params.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
url+= '&' + key + '=' + params[key];
|
||||
}
|
||||
}
|
||||
return url.replace("?&", "?");
|
||||
}
|
||||
this.__isArr = function (obj){
|
||||
return Object.prototype.toString.call(obj)=='[object Array]';
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置参数
|
||||
* @param config
|
||||
*/
|
||||
this.config = function (config) {
|
||||
if (typeof config !== "object" || config === null) {
|
||||
config = {};
|
||||
}
|
||||
config.userid = config.userid || '';
|
||||
config.url = config.url || '';
|
||||
config.token = config.token || '';
|
||||
config.logCallback = config.logCallback || null;
|
||||
this.__config = config;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接
|
||||
* @param force
|
||||
*/
|
||||
this.connection = function (force) {
|
||||
if (!this.__lExists(this.__config.url, "ws://") && !this.__lExists(this.__config.url, "wss://")) {
|
||||
this.__log("[WS] No connection address");
|
||||
return this;
|
||||
}
|
||||
|
||||
if (!this.__config.token) {
|
||||
this.__log("[WS] No connected token");
|
||||
return this;
|
||||
}
|
||||
|
||||
if (this.__instance !== null && force !== true) {
|
||||
this.__log("[WS] Connection exists");
|
||||
return this;
|
||||
}
|
||||
|
||||
var thas = this;
|
||||
|
||||
// 初始化客户端套接字并建立连接
|
||||
this.__instance = new WebSocket(this.__urlParams(this.__config.url, {
|
||||
mode: 'console',
|
||||
token: this.__config.token,
|
||||
}));
|
||||
|
||||
// 连接建立时触发
|
||||
this.__instance.onopen = function (event) {
|
||||
thas.__log("[WS] Connection opened", event);
|
||||
}
|
||||
|
||||
// 接收到服务端推送时执行
|
||||
this.__instance.onmessage = function (event) {
|
||||
thas.__log("[WS] Message", event);
|
||||
var msgDetail = thas.__jParse(event.data);
|
||||
if (msgDetail.messageType === 'open') {
|
||||
thas.__log("[WS] Connection connected");
|
||||
msgDetail.openNum = thas.__openNum;
|
||||
msgDetail.config = thas.__config;
|
||||
thas.__openNum++;
|
||||
thas.__connected = true;
|
||||
thas.__autoLine(30);
|
||||
} else if (msgDetail.messageType === 'back') {
|
||||
typeof thas.__callbackid[msgDetail.messageId] === "function" && thas.__callbackid[msgDetail.messageId](msgDetail.body);
|
||||
delete thas.__callbackid[msgDetail.messageId];
|
||||
return;
|
||||
}
|
||||
if (thas.__rNum(msgDetail.contentId) > 0) {
|
||||
thas.sendTo('roger', msgDetail.contentId);
|
||||
}
|
||||
thas.triggerMsgListener(msgDetail);
|
||||
};
|
||||
|
||||
// 连接关闭时触发
|
||||
this.__instance.onclose = function (event) {
|
||||
thas.__log("[WS] Connection closed", event);
|
||||
thas.__connected = false;
|
||||
thas.__instance = null;
|
||||
thas.__autoLine(3);
|
||||
}
|
||||
|
||||
// 连接出错
|
||||
this.__instance.onerror = function (event) {
|
||||
thas.__log("[WS] Connection error", event);
|
||||
thas.__connected = false;
|
||||
thas.__instance = null;
|
||||
thas.__autoLine(3);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加消息监听
|
||||
* @param listenerName
|
||||
* @param listenerType
|
||||
* @param callback
|
||||
*/
|
||||
this.setOnMsgListener = function (listenerName, listenerType, callback) {
|
||||
if (typeof listenerName != "string") {
|
||||
return this;
|
||||
}
|
||||
if (typeof listenerType === "function") {
|
||||
callback = listenerType;
|
||||
listenerType = [];
|
||||
}
|
||||
if (!this.__isArr(listenerType)) {
|
||||
listenerType = [listenerType];
|
||||
}
|
||||
if (typeof callback === "function") {
|
||||
window.webSocketConfig.LISTENER[listenerName] = {
|
||||
callback: callback,
|
||||
listenerType: listenerType,
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
this.triggerMsgListener = function (msgDetail) {
|
||||
var key, item;
|
||||
for (key in window.webSocketConfig.LISTENER) {
|
||||
if (!window.webSocketConfig.LISTENER.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
item = window.webSocketConfig.LISTENER[key];
|
||||
if (item.listenerType.length > 0 && item.listenerType.indexOf(msgDetail.messageType) === -1) {
|
||||
continue;
|
||||
}
|
||||
if (typeof item.callback === "function") {
|
||||
try {
|
||||
item.callback(msgDetail);
|
||||
} catch (e) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
* @param messageType 会话类型
|
||||
* - refresh: 刷新
|
||||
* @param target 发送目标
|
||||
* @param body 发送内容(对象或数组)
|
||||
* @param callback 发送回调
|
||||
* @param againNum
|
||||
*/
|
||||
this.sendTo = function (messageType, target, body, callback, againNum = 0) {
|
||||
if (typeof target === "object" && typeof body === "undefined") {
|
||||
body = target;
|
||||
target = null;
|
||||
}
|
||||
if (typeof target === "function") {
|
||||
body = target;
|
||||
target = null;
|
||||
}
|
||||
if (typeof body === "function") {
|
||||
callback = body;
|
||||
body = null;
|
||||
}
|
||||
if (body === null || typeof body !== "object") {
|
||||
body = {};
|
||||
}
|
||||
//
|
||||
var thas = this;
|
||||
if (this.__instance === null || this.__connected === false) {
|
||||
if (againNum < 10 && messageType != 'team') {
|
||||
setTimeout(function () {
|
||||
thas.sendTo(messageType, target, body, callback, thas.__rNum(againNum) + 1)
|
||||
}, 600);
|
||||
if (againNum === 0) {
|
||||
this.connection();
|
||||
}
|
||||
} else {
|
||||
if (this.__instance === null) {
|
||||
this.__log("[WS] Service not connected");
|
||||
typeof callback === "function" && callback({status: 0, message: '服务未连接'});
|
||||
} else {
|
||||
this.__log("[WS] Failed connection");
|
||||
typeof callback === "function" && callback({status: 0, message: '未连接成功'});
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
if (['refresh', 'notificationStatus'].indexOf(messageType) === -1) {
|
||||
this.__log("[WS] Wrong message messageType: " + messageType);
|
||||
typeof callback === "function" && callback({status: 0, message: '错误的消息类型: ' + messageType});
|
||||
return this;
|
||||
}
|
||||
//
|
||||
var contentId = 0;
|
||||
if (messageType === 'roger') {
|
||||
contentId = target;
|
||||
target = null;
|
||||
}
|
||||
var messageId = '';
|
||||
if (typeof callback === "function") {
|
||||
messageId = this.__randString(16);
|
||||
this.__callbackid[messageId] = callback;
|
||||
}
|
||||
this.__lastSend = Math.round(new Date().getTime()/1000);
|
||||
this.__instance.send(JSON.stringify({
|
||||
messageType: messageType,
|
||||
messageId: messageId,
|
||||
contentId: contentId,
|
||||
userid: this.__config.userid,
|
||||
target: target,
|
||||
body: body,
|
||||
time: this.__lastSend,
|
||||
}));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭连接
|
||||
*/
|
||||
this.close = function () {
|
||||
if (this.__instance === null) {
|
||||
this.__log("[WS] Service not connected");
|
||||
return this;
|
||||
}
|
||||
if (this.__connected === false) {
|
||||
this.__log("[WS] Failed connection");
|
||||
return this;
|
||||
}
|
||||
this.__instance.close();
|
||||
return this;
|
||||
}
|
||||
|
||||
return this.config(config);
|
||||
},
|
||||
|
||||
WSOB: {
|
||||
instance: null,
|
||||
isClose: false,
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
initialize() {
|
||||
let url = window.webSocketConfig.URL;
|
||||
if (!url) {
|
||||
url = window.location.origin;
|
||||
url = url.replace("https://", "wss://");
|
||||
url = url.replace("http://", "ws://");
|
||||
url+= "/ws";
|
||||
}
|
||||
let config = {
|
||||
userid: $A.app.$store.state.userInfo.userid,
|
||||
url: url,
|
||||
token: $A.app.$store.state.userToken,
|
||||
};
|
||||
if (window.webSocketConfig.DEBUG) {
|
||||
config.logCallback = function (msg) {
|
||||
console.log(msg);
|
||||
};
|
||||
}
|
||||
if (this.instance === null) {
|
||||
this.instance = new $A.WTWS(config);
|
||||
this.instance.connection()
|
||||
} else {
|
||||
this.instance.config(config);
|
||||
if (this.isClose) {
|
||||
this.isClose = false
|
||||
this.instance.connection();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 主动连接
|
||||
*/
|
||||
connection() {
|
||||
this.initialize();
|
||||
this.instance.connection();
|
||||
},
|
||||
|
||||
/**
|
||||
* 监听消息
|
||||
* @param listenerName
|
||||
* @param listenerType
|
||||
* @param callback
|
||||
*/
|
||||
setOnMsgListener(listenerName, listenerType, callback) {
|
||||
this.initialize();
|
||||
this.instance.setOnMsgListener(listenerName, listenerType, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
* @param messageType
|
||||
* @param target
|
||||
* @param body
|
||||
* @param callback
|
||||
*/
|
||||
sendTo(messageType, target, body, callback) {
|
||||
this.initialize();
|
||||
this.instance.sendTo(messageType, target, body, callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* 关闭连接
|
||||
*/
|
||||
close() {
|
||||
if (this.instance === null) {
|
||||
return;
|
||||
}
|
||||
this.isClose = true
|
||||
this.instance.config(null).close();
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
@ -611,10 +167,10 @@
|
||||
content: config
|
||||
};
|
||||
}
|
||||
config.title = $A.app.$L(config.title || (typeof config.render === 'undefined' ? '温馨提示' : ''));
|
||||
config.content = $A.app.$L(config.content || '');
|
||||
config.okText = $A.app.$L(config.okText || '确定');
|
||||
config.cancelText = $A.app.$L(config.cancelText || '取消');
|
||||
config.title = $A.L(config.title || (typeof config.render === 'undefined' ? '温馨提示' : ''));
|
||||
config.content = $A.L(config.content || '');
|
||||
config.okText = $A.L(config.okText || '确定');
|
||||
config.cancelText = $A.L(config.cancelText || '取消');
|
||||
return config;
|
||||
},
|
||||
|
||||
@ -623,7 +179,7 @@
|
||||
setTimeout(() => { $A.modalConfirm(config) }, millisecond);
|
||||
return;
|
||||
}
|
||||
$A.app.$Modal.confirm($A.modalConfig(config));
|
||||
$A.Modal.confirm($A.modalConfig(config));
|
||||
},
|
||||
|
||||
modalSuccess(config, millisecond = 0) {
|
||||
@ -631,7 +187,7 @@
|
||||
setTimeout(() => { $A.modalSuccess(config) }, millisecond);
|
||||
return;
|
||||
}
|
||||
$A.app.$Modal.success($A.modalConfig(config));
|
||||
$A.Modal.success($A.modalConfig(config));
|
||||
},
|
||||
|
||||
modalInfo(config, millisecond = 0) {
|
||||
@ -639,7 +195,7 @@
|
||||
setTimeout(() => { $A.modalInfo(config) }, millisecond);
|
||||
return;
|
||||
}
|
||||
$A.app.$Modal.info($A.modalConfig(config));
|
||||
$A.Modal.info($A.modalConfig(config));
|
||||
},
|
||||
|
||||
modalWarning(config, millisecond = 0) {
|
||||
@ -647,7 +203,7 @@
|
||||
setTimeout(() => { $A.modalWarning(config) }, millisecond);
|
||||
return;
|
||||
}
|
||||
$A.app.$Modal.warning($A.modalConfig(config));
|
||||
$A.Modal.warning($A.modalConfig(config));
|
||||
},
|
||||
|
||||
modalError(config, millisecond = 0) {
|
||||
@ -655,7 +211,7 @@
|
||||
setTimeout(() => { $A.modalError(config) }, millisecond);
|
||||
return;
|
||||
}
|
||||
$A.app.$Modal.error($A.modalConfig(config));
|
||||
$A.Modal.error($A.modalConfig(config));
|
||||
},
|
||||
|
||||
modalInfoShow(title, data, addConfig) {
|
||||
@ -670,30 +226,30 @@
|
||||
let config = {
|
||||
title: title,
|
||||
content: content,
|
||||
okText: $A.app.$L('关闭'),
|
||||
okText: $A.L('关闭'),
|
||||
closable: true
|
||||
};
|
||||
if (typeof addConfig == 'object' && addConfig) {
|
||||
config = Object.assign(config, addConfig);
|
||||
}
|
||||
this.app.$Modal.info(config);
|
||||
this.Modal.info(config);
|
||||
},
|
||||
|
||||
modalAlert(msg) {
|
||||
alert($A.app.$L(msg));
|
||||
alert($A.L(msg));
|
||||
},
|
||||
|
||||
//提示
|
||||
messageSuccess(msg) {
|
||||
$A.app.$Message.success($A.app.$L(msg));
|
||||
$A.Message.success($A.L(msg));
|
||||
},
|
||||
|
||||
messageWarning(msg) {
|
||||
$A.app.$Message.warning($A.app.$L(msg));
|
||||
$A.Message.warning($A.L(msg));
|
||||
},
|
||||
|
||||
messageError(msg) {
|
||||
$A.app.$Message.error($A.app.$L(msg));
|
||||
$A.Message.error($A.L(msg));
|
||||
},
|
||||
|
||||
//通知
|
||||
@ -703,17 +259,17 @@
|
||||
desc: config
|
||||
};
|
||||
}
|
||||
config.title = $A.app.$L(config.title || (typeof config.render === 'undefined' ? '温馨提示' : ''));
|
||||
config.desc = $A.app.$L(config.desc || '');
|
||||
config.title = $A.L(config.title || (typeof config.render === 'undefined' ? '温馨提示' : ''));
|
||||
config.desc = $A.L(config.desc || '');
|
||||
return config;
|
||||
},
|
||||
|
||||
noticeSuccess(config) {
|
||||
$A.app.$Notice.success($A.noticeConfig(config));
|
||||
$A.Notice.success($A.noticeConfig(config));
|
||||
},
|
||||
|
||||
noticeWarning(config) {
|
||||
$A.app.$Notice.warning($A.noticeConfig(config));
|
||||
$A.Notice.warning($A.noticeConfig(config));
|
||||
},
|
||||
|
||||
noticeError(config) {
|
||||
@ -723,7 +279,7 @@
|
||||
duration: 6
|
||||
};
|
||||
}
|
||||
$A.app.$Notice.error($A.noticeConfig(config));
|
||||
$A.Notice.error($A.noticeConfig(config));
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
</div>
|
||||
</Tooltip>
|
||||
</li>
|
||||
<li :class="['project-icon', $store.state.projectChatShow ? 'active' : '']" @click="$store.commit('toggleProjectChatShow')">
|
||||
<li :class="['project-icon', $store.state.projectChatShow ? 'active' : '']" @click="$store.commit('toggleBoolean', 'projectChatShow')">
|
||||
<Icon type="ios-chatbubbles" />
|
||||
<Badge :count="projectMsgUnread"></Badge>
|
||||
</li>
|
||||
@ -41,7 +41,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
<div class="project-switch">
|
||||
<div :class="['project-switch-button', $store.state.projectListPanel ? 'menu' : '']" @click="$store.commit('toggleProjectListPanel')">
|
||||
<div :class="['project-switch-button', $store.state.projectListPanel ? 'menu' : '']" @click="$store.commit('toggleBoolean', 'projectListPanel')">
|
||||
<div><i class="iconfont"></i></div>
|
||||
<div><i class="iconfont"></i></div>
|
||||
</div>
|
||||
@ -104,7 +104,7 @@
|
||||
</div>
|
||||
<!--我的任务-->
|
||||
<div :class="['project-table-body', !$store.state.taskMyShow ? 'project-table-hide' : '']">
|
||||
<div @click="$store.commit('toggleTaskMyShow')">
|
||||
<div @click="$store.commit('toggleBoolean', 'taskMyShow')">
|
||||
<Row class="project-row">
|
||||
<Col span="12" class="row-title">
|
||||
<i class="iconfont"></i>
|
||||
@ -162,7 +162,7 @@
|
||||
</div>
|
||||
<!--未完成任务-->
|
||||
<div :class="['project-table-body', !$store.state.taskUndoneShow ? 'project-table-hide' : '']">
|
||||
<div @click="$store.commit('toggleTaskUndoneShow')">
|
||||
<div @click="$store.commit('toggleBoolean', 'taskUndoneShow')">
|
||||
<Row class="project-row">
|
||||
<Col span="12" class="row-title">
|
||||
<i class="iconfont"></i>
|
||||
@ -209,7 +209,7 @@
|
||||
</div>
|
||||
<!--已完成任务-->
|
||||
<div :class="['project-table-body', !$store.state.taskCompletedShow ? 'project-table-hide' : '']">
|
||||
<div @click="$store.commit('toggleTaskCompletedShow')">
|
||||
<div @click="$store.commit('toggleBoolean', 'taskCompletedShow')">
|
||||
<Row class="project-row">
|
||||
<Col span="12" class="row-title">
|
||||
<i class="iconfont"></i>
|
||||
|
188
resources/assets/js/store/mutations.js
vendored
188
resources/assets/js/store/mutations.js
vendored
@ -1,47 +1,12 @@
|
||||
export default {
|
||||
/**
|
||||
* 切换项目聊天显隐
|
||||
* 切换Boolean变量
|
||||
* @param state
|
||||
* @param key
|
||||
*/
|
||||
toggleProjectChatShow(state) {
|
||||
state.projectChatShow = !state.projectChatShow
|
||||
state.setStorage('projectChatShow', state.projectChatShow);
|
||||
},
|
||||
|
||||
/**
|
||||
* 切换项目面板显示类型
|
||||
* @param state
|
||||
*/
|
||||
toggleProjectListPanel(state) {
|
||||
state.projectListPanel = !state.projectListPanel
|
||||
state.setStorage('projectListPanel', state.projectListPanel);
|
||||
},
|
||||
|
||||
/**
|
||||
* 切换项目面板显示显示我的任务
|
||||
* @param state
|
||||
*/
|
||||
toggleTaskMyShow(state) {
|
||||
state.taskMyShow = !state.taskMyShow
|
||||
state.setStorage('taskMyShow', state.taskMyShow);
|
||||
},
|
||||
|
||||
/**
|
||||
* 切换项目面板显示显示未完成任务
|
||||
* @param state
|
||||
*/
|
||||
toggleTaskUndoneShow(state) {
|
||||
state.taskUndoneShow = !state.taskUndoneShow
|
||||
state.setStorage('taskUndoneShow', state.taskUndoneShow);
|
||||
},
|
||||
|
||||
/**
|
||||
* 切换项目面板显示显示已完成任务
|
||||
* @param state
|
||||
*/
|
||||
toggleTaskCompletedShow(state) {
|
||||
state.taskCompletedShow = !state.taskCompletedShow
|
||||
state.setStorage('taskCompletedShow', state.taskCompletedShow);
|
||||
toggleBoolean(state, key) {
|
||||
state[key] = !state[key]
|
||||
state.method.setStorage('boolean:' + key, state[key]);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -71,7 +36,7 @@ export default {
|
||||
$A.apiAjax({
|
||||
url: 'users/info',
|
||||
error: () => {
|
||||
$A.userLogout();
|
||||
$A.logout();
|
||||
},
|
||||
success: ({ret, data, msg}) => {
|
||||
if (ret === 1) {
|
||||
@ -89,14 +54,16 @@ export default {
|
||||
* @param info
|
||||
*/
|
||||
setUserInfo(state, info) {
|
||||
const userInfo = state._cloneJSON(info);
|
||||
userInfo.userid = state._runNum(userInfo.userid);
|
||||
const userInfo = state.method.cloneJSON(info);
|
||||
userInfo.userid = state.method.runNum(userInfo.userid);
|
||||
userInfo.token = userInfo.userid > 0 ? (userInfo.token || state.userToken) : '';
|
||||
state.userInfo = userInfo;
|
||||
state.userId = userInfo.userid;
|
||||
state.userToken = userInfo.token;
|
||||
state.setStorage('userInfo', state.userInfo);
|
||||
state.userIsAdmin = state.method.inArray('admin', userInfo.identity);
|
||||
state.method.setStorage('userInfo', state.userInfo);
|
||||
this.commit('getProjectList');
|
||||
this.commit('wsConnection');
|
||||
},
|
||||
|
||||
/**
|
||||
@ -131,10 +98,10 @@ export default {
|
||||
* @param project_id
|
||||
*/
|
||||
getProjectDetail(state, project_id) {
|
||||
if (state._runNum(project_id) === 0) {
|
||||
if (state.method.runNum(project_id) === 0) {
|
||||
return;
|
||||
}
|
||||
if (state._isJson(state.cacheProject[project_id])) {
|
||||
if (state.method.isJson(state.cacheProject[project_id])) {
|
||||
state.projectDetail = state.cacheProject[project_id];
|
||||
}
|
||||
state.projectDetail.id = project_id;
|
||||
@ -173,13 +140,13 @@ export default {
|
||||
* @param params {userid, success, complete}
|
||||
*/
|
||||
getUserBasic(state, params) {
|
||||
if (!state._isJson(params)) {
|
||||
if (!state.method.isJson(params)) {
|
||||
return;
|
||||
}
|
||||
const {userid, success, complete} = params;
|
||||
const time = Math.round(new Date().getTime() / 1000);
|
||||
const array = [];
|
||||
(state._isArray(userid) ? userid : [userid]).some((uid) => {
|
||||
(state.method.isArray(userid) ? userid : [userid]).some((uid) => {
|
||||
if (state.cacheUserBasic[uid]) {
|
||||
typeof success === "function" && success(state.cacheUserBasic[uid].data, false);
|
||||
if (time - state.cacheUserBasic[uid].time <= 10) {
|
||||
@ -223,5 +190,130 @@ export default {
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 初始化 websocket
|
||||
* @param state
|
||||
*/
|
||||
wsConnection(state) {
|
||||
clearTimeout(state.wsTimeout);
|
||||
if (state.userId === 0) {
|
||||
if (state.ws) {
|
||||
state.ws.close();
|
||||
state.ws = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
let url = window.webSocketConfig.URL;
|
||||
if (!url) {
|
||||
url = window.location.origin;
|
||||
url = url.replace("https://", "wss://");
|
||||
url = url.replace("http://", "ws://");
|
||||
url += "/ws";
|
||||
}
|
||||
url += "?action=web&token=" + state.userToken;
|
||||
//
|
||||
state.ws = new WebSocket(url);
|
||||
state.ws.onopen = (e) => {
|
||||
console.log("[WS] Open", e)
|
||||
};
|
||||
state.ws.onclose = (e) => {
|
||||
console.log("[WS] Close", e);
|
||||
state.ws = null;
|
||||
//
|
||||
clearTimeout(state.wsTimeout);
|
||||
state.wsTimeout = setTimeout(() => {
|
||||
this.commit('wsConnection');
|
||||
}, 3000);
|
||||
};
|
||||
state.ws.onerror = (e) => {
|
||||
console.log("[WS] Error", e);
|
||||
state.ws = null;
|
||||
//
|
||||
clearTimeout(state.wsTimeout);
|
||||
state.wsTimeout = setTimeout(() => {
|
||||
this.commit('wsConnection');
|
||||
}, 3000);
|
||||
};
|
||||
state.ws.onmessage = (e) => {
|
||||
console.log("[WS] Message", e);
|
||||
const msgDetail = state.method.jsonParse(event.data);
|
||||
const {type, msgId} = msgDetail;
|
||||
switch (type) {
|
||||
case "open":
|
||||
break
|
||||
|
||||
case "receipt":
|
||||
typeof state.wsCall[msgId] === "function" && state.wsCall[msgId](msgDetail.body, true);
|
||||
delete state.wsCall[msgId];
|
||||
break
|
||||
|
||||
default:
|
||||
msgId && this.commit('wsSend', {type: 'receipt', msgId});
|
||||
state.wsMsg = msgDetail;
|
||||
Object.values(state.wsListener).forEach((call) => {
|
||||
if (typeof call === "function") {
|
||||
try {
|
||||
call(msgDetail);
|
||||
} catch (err) {
|
||||
console.log("[WS] Callerr", err);
|
||||
}
|
||||
}
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 发送 websocket 消息
|
||||
* @param state
|
||||
* @param params {type, to, data, callback}
|
||||
*/
|
||||
wsSend(state, params) {
|
||||
if (!state.method.isJson(params)) {
|
||||
return;
|
||||
}
|
||||
const {type, to, data, callback} = params;
|
||||
if (!state.ws) {
|
||||
typeof callback === "function" && callback(null, false)
|
||||
return;
|
||||
}
|
||||
if (typeof callback === "function") {
|
||||
params.msgId = state.method.randomString(16)
|
||||
state.wsCall[params.msgId] = callback;
|
||||
}
|
||||
try {
|
||||
state.ws.send(JSON.stringify({
|
||||
type,
|
||||
to,
|
||||
data
|
||||
}));
|
||||
} catch (e) {
|
||||
typeof callback === "function" && callback(null, false)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 监听消息
|
||||
* @param state
|
||||
* @param params {name, callback}
|
||||
*/
|
||||
wsMsgListener(state, params) {
|
||||
const {name, callback} = params;
|
||||
if (typeof callback === "function") {
|
||||
state.wsListener[name] = callback;
|
||||
} else {
|
||||
state.wsListener[name] && delete state.wsListener[name];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 关闭 websocket
|
||||
* @param state
|
||||
*/
|
||||
wsClose(state) {
|
||||
state.ws && state.ws.close();
|
||||
}
|
||||
}
|
||||
|
130
resources/assets/js/store/state.js
vendored
130
resources/assets/js/store/state.js
vendored
@ -1,56 +1,63 @@
|
||||
const stateCommon = {
|
||||
const method = {
|
||||
setStorage(key, value) {
|
||||
return this._storage(key, value);
|
||||
return this.storage(key, value);
|
||||
},
|
||||
|
||||
getStorage(key, def = null) {
|
||||
let value = this._storage(key);
|
||||
let value = this.storage(key);
|
||||
return value || def;
|
||||
},
|
||||
|
||||
getStorageString(key, def = '') {
|
||||
let value = this._storage(key);
|
||||
let value = this.storage(key);
|
||||
return typeof value === "string" || typeof value === "number" ? value : def;
|
||||
},
|
||||
|
||||
getStorageNumber(key, def = 0) {
|
||||
let value = this._storage(key);
|
||||
let value = this.storage(key);
|
||||
return typeof value === "number" ? value : def;
|
||||
},
|
||||
|
||||
getStorageBoolean(key, def = false) {
|
||||
let value = this._storage(key);
|
||||
let value = this.storage(key);
|
||||
return typeof value === "boolean" ? value : def;
|
||||
},
|
||||
|
||||
getStorageArray(key, def = {}) {
|
||||
let value = this._storage(key);
|
||||
return this._isArray(value) ? value : def;
|
||||
let value = this.storage(key);
|
||||
return this.isArray(value) ? value : def;
|
||||
},
|
||||
|
||||
getStorageJson(key, def = {}) {
|
||||
let value = this._storage(key);
|
||||
return this._isJson(value) ? value : def;
|
||||
let value = this.storage(key);
|
||||
return this.isJson(value) ? value : def;
|
||||
},
|
||||
|
||||
_isArray(obj) {
|
||||
isArray(obj) {
|
||||
return typeof (obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == '[object array]' && typeof obj.length == "number";
|
||||
},
|
||||
|
||||
_isJson(obj) {
|
||||
isJson(obj) {
|
||||
return typeof (obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == "[object object]" && typeof obj.length == "undefined";
|
||||
},
|
||||
|
||||
_storage(key, value) {
|
||||
inArray(key, array) {
|
||||
if (!this.isArray(array)) {
|
||||
return false;
|
||||
}
|
||||
return array.includes(key);
|
||||
},
|
||||
|
||||
storage(key, value) {
|
||||
let keyName = 'state';
|
||||
if (typeof value === 'undefined') {
|
||||
return this._loadFromlLocal('__::', key, '', '__' + keyName + '__');
|
||||
return this.loadFromlLocal('__::', key, '', '__' + keyName + '__');
|
||||
} else {
|
||||
this._savaToLocal('__::', key, value, '__' + keyName + '__');
|
||||
this.savaToLocal('__::', key, value, '__' + keyName + '__');
|
||||
}
|
||||
},
|
||||
|
||||
_savaToLocal(id, key, value, keyName) {
|
||||
savaToLocal(id, key, value, keyName) {
|
||||
try {
|
||||
if (typeof keyName === 'undefined') keyName = '__seller__';
|
||||
let seller = window.localStorage[keyName];
|
||||
@ -69,7 +76,7 @@ const stateCommon = {
|
||||
}
|
||||
},
|
||||
|
||||
_loadFromlLocal(id, key, def, keyName) {
|
||||
loadFromlLocal(id, key, def, keyName) {
|
||||
try {
|
||||
if (typeof keyName === 'undefined') keyName = '__seller__';
|
||||
let seller = window.localStorage[keyName];
|
||||
@ -86,29 +93,7 @@ const stateCommon = {
|
||||
}
|
||||
},
|
||||
|
||||
_count(obj) {
|
||||
try {
|
||||
if (typeof obj === "undefined") {
|
||||
return 0;
|
||||
}
|
||||
if (typeof obj === "number") {
|
||||
obj += "";
|
||||
}
|
||||
if (typeof obj.length === 'number') {
|
||||
return obj.length;
|
||||
} else {
|
||||
let i = 0, key;
|
||||
for (key in obj) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
} catch (e) {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
|
||||
_runNum(str, fixed) {
|
||||
runNum(str, fixed) {
|
||||
let _s = Number(str);
|
||||
if (_s + "" === "NaN") {
|
||||
_s = 0;
|
||||
@ -126,13 +111,13 @@ const stateCommon = {
|
||||
return _s;
|
||||
},
|
||||
|
||||
_cloneJSON(myObj) {
|
||||
if(typeof(myObj) !== 'object') return myObj;
|
||||
if(myObj === null) return myObj;
|
||||
return this._jsonParse(this._jsonStringify(myObj))
|
||||
cloneJSON(myObj) {
|
||||
if (typeof (myObj) !== 'object') return myObj;
|
||||
if (myObj === null) return myObj;
|
||||
return this.jsonParse(this.jsonStringify(myObj))
|
||||
},
|
||||
|
||||
_jsonParse(str, defaultVal) {
|
||||
jsonParse(str, defaultVal) {
|
||||
if (str === null) {
|
||||
return defaultVal ? defaultVal : {};
|
||||
}
|
||||
@ -140,47 +125,54 @@ const stateCommon = {
|
||||
return str;
|
||||
}
|
||||
try {
|
||||
return JSON.parse(str.replace(/\n/g,"\\n").replace(/\r/g,"\\r"));
|
||||
return JSON.parse(str.replace(/\n/g, "\\n").replace(/\r/g, "\\r"));
|
||||
} catch (e) {
|
||||
return defaultVal ? defaultVal : {};
|
||||
}
|
||||
},
|
||||
|
||||
_jsonStringify(json, defaultVal) {
|
||||
jsonStringify(json, defaultVal) {
|
||||
if (typeof json !== 'object') {
|
||||
return json;
|
||||
}
|
||||
try{
|
||||
try {
|
||||
return JSON.stringify(json);
|
||||
}catch (e) {
|
||||
} catch (e) {
|
||||
return defaultVal ? defaultVal : "";
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
const projectChatShow = stateCommon.getStorageBoolean('projectChatShow', true);
|
||||
const projectListPanel = stateCommon.getStorageBoolean('projectListPanel', true);
|
||||
// 方法类
|
||||
const state = {
|
||||
method
|
||||
};
|
||||
|
||||
const taskMyShow = stateCommon.getStorageBoolean('taskMyShow', true);
|
||||
const taskUndoneShow = stateCommon.getStorageBoolean('taskUndoneShow', true);
|
||||
const taskCompletedShow = stateCommon.getStorageBoolean('taskCompletedShow', true);
|
||||
// Boolean变量
|
||||
[
|
||||
'projectChatShow', // 项目聊天显示
|
||||
'projectListPanel', // 项目面板显示类型
|
||||
'taskMyShow', // 项目面板显示我的任务
|
||||
'taskUndoneShow', // 项目面板显示未完成任务
|
||||
'taskCompletedShow' // 项目面板显示已完成任务
|
||||
].forEach((key) => {
|
||||
state[key] = state.method.getStorageBoolean('boolean:' + key, true)
|
||||
})
|
||||
|
||||
const userInfo = stateCommon.getStorageJson('userInfo');
|
||||
const userId = userInfo.userid = stateCommon._runNum(userInfo.userid);
|
||||
const userToken = userInfo.token;
|
||||
// 会员信息
|
||||
state.userInfo = state.method.getStorageJson('userInfo');
|
||||
state.userId = state.userInfo.userid = state.method.runNum(state.userInfo.userid);
|
||||
state.userToken = state.userInfo.token;
|
||||
state.userIsAdmin = state.method.inArray('admin', state.userInfo.identity);
|
||||
|
||||
export default Object.assign(stateCommon, {
|
||||
projectChatShow,
|
||||
projectListPanel,
|
||||
|
||||
taskMyShow,
|
||||
taskUndoneShow,
|
||||
taskCompletedShow,
|
||||
|
||||
userId,
|
||||
userInfo,
|
||||
userToken,
|
||||
// Websocket
|
||||
state.ws = null;
|
||||
state.wsMsg = {};
|
||||
state.wsCall = {};
|
||||
state.wsTimeout = null;
|
||||
state.wsListener = {};
|
||||
|
||||
export default Object.assign(state, {
|
||||
cacheProject: {},
|
||||
cacheUserBasic: {},
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user