新增signalR连接
This commit is contained in:
62
ZR.Admin.WebApi/Hubs/MessageHub.cs
Normal file
62
ZR.Admin.WebApi/Hubs/MessageHub.cs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Infrastructure.Model;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using ZR.Admin.WebApi.Filters;
|
||||||
|
using ZR.Model;
|
||||||
|
|
||||||
|
namespace ZR.Admin.WebApi.Hubs
|
||||||
|
{
|
||||||
|
[Verify]
|
||||||
|
public class MessageHub : Hub
|
||||||
|
{
|
||||||
|
//创建用户集合,用于存储所有链接的用户数据
|
||||||
|
private static readonly List<OnlineUsers> clientUsers = new();
|
||||||
|
|
||||||
|
#region 客户端连接
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 客户端连接的时候调用
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override Task OnConnectedAsync()
|
||||||
|
{
|
||||||
|
//name 获取不到有待研究
|
||||||
|
var name = Context.User.Identity.Name;
|
||||||
|
var user = clientUsers.Any(u => u.ConnnectionId == Context.ConnectionId);
|
||||||
|
//判断用户是否存在,否则添加集合
|
||||||
|
if (!user)
|
||||||
|
{
|
||||||
|
clientUsers.Add(new OnlineUsers(Context.ConnectionId, Context.User.Identity.Name));
|
||||||
|
Console.WriteLine($"{DateTime.Now}:{Context.User.Identity.Name},{Context.ConnectionId}连接服务端success,当前已连接{clientUsers.Count}个");
|
||||||
|
}
|
||||||
|
|
||||||
|
Clients.All.SendAsync("onlineNum", clientUsers.Count);
|
||||||
|
return base.OnConnectedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 连接终止时调用。
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override Task OnDisconnectedAsync(Exception exception)
|
||||||
|
{
|
||||||
|
var user = clientUsers.Where(p => p.ConnnectionId == Context.ConnectionId).FirstOrDefault();
|
||||||
|
//判断用户是否存在,否则添加集合
|
||||||
|
if (user != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"用户{user?.Name}离开了,当前已连接{clientUsers.Count}个");
|
||||||
|
clientUsers.Remove(user);
|
||||||
|
|
||||||
|
Clients.All.SendAsync("onlineNum", clientUsers.Count);
|
||||||
|
}
|
||||||
|
return base.OnDisconnectedAsync(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
27
ZR.Admin.WebApi/Hubs/OnlineUsers.cs
Normal file
27
ZR.Admin.WebApi/Hubs/OnlineUsers.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace ZR.Model
|
||||||
|
{
|
||||||
|
public class OnlineUsers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 客户端连接Id
|
||||||
|
/// </summary>
|
||||||
|
public string ConnnectionId { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 用户id
|
||||||
|
/// </summary>
|
||||||
|
public int Userid { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public DateTime LoginTime { get; set; }
|
||||||
|
|
||||||
|
public OnlineUsers(string clientid, string name)
|
||||||
|
{
|
||||||
|
ConnnectionId = clientid;
|
||||||
|
Name = name;
|
||||||
|
LoginTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,8 +15,8 @@ using System.Threading.Tasks;
|
|||||||
using ZR.Admin.WebApi.Extensions;
|
using ZR.Admin.WebApi.Extensions;
|
||||||
using ZR.Admin.WebApi.Filters;
|
using ZR.Admin.WebApi.Filters;
|
||||||
using ZR.Admin.WebApi.Framework;
|
using ZR.Admin.WebApi.Framework;
|
||||||
|
using ZR.Admin.WebApi.Hubs;
|
||||||
using ZR.Admin.WebApi.Middleware;
|
using ZR.Admin.WebApi.Middleware;
|
||||||
using ZR.Common.Cache;
|
|
||||||
|
|
||||||
namespace ZR.Admin.WebApi
|
namespace ZR.Admin.WebApi
|
||||||
{
|
{
|
||||||
@@ -43,6 +43,14 @@ namespace ZR.Admin.WebApi
|
|||||||
.AllowAnyMethod();//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ⷽ<EFBFBD><E2B7BD>
|
.AllowAnyMethod();//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ⷽ<EFBFBD><E2B7BD>
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
//ע<><D7A2>SignalRʵʱͨѶ<CDA8><D1B6>Ĭ<EFBFBD><C4AC><EFBFBD><EFBFBD>json<6F><6E><EFBFBD><EFBFBD>
|
||||||
|
services.AddSignalR(options =>
|
||||||
|
{
|
||||||
|
//<2F>ͻ<EFBFBD><CDBB>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><F3B5BDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EEB3A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>30<33>룬<EFBFBD>ij<EFBFBD>4<EFBFBD><34><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD>ҳ<EFBFBD><D2B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>connection.keepAliveIntervalInMilliseconds = 12e4;<3B><>2<EFBFBD><32><EFBFBD><EFBFBD>
|
||||||
|
//options.ClientTimeoutInterval = TimeSpan.FromMinutes(4);
|
||||||
|
//<2F><><EFBFBD><EFBFBD><EFBFBD>˷<EFBFBD><CBB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ<F3B5BDBF><CDBB>˼<EFBFBD><CBBC><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>15<31>룬<EFBFBD>ij<EFBFBD>2<EFBFBD><32><EFBFBD>ӣ<EFBFBD><D3A3><EFBFBD>ҳ<EFBFBD><D2B3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>connection.serverTimeoutInMilliseconds = 24e4;<3B><>4<EFBFBD><34><EFBFBD><EFBFBD>
|
||||||
|
//options.KeepAliveInterval = TimeSpan.FromMinutes(2);
|
||||||
|
});
|
||||||
//<2F><><EFBFBD><EFBFBD>Error unprotecting the session cookie<69><65><EFBFBD><EFBFBD>
|
//<2F><><EFBFBD><EFBFBD>Error unprotecting the session cookie<69><65><EFBFBD><EFBFBD>
|
||||||
services.AddDataProtection()
|
services.AddDataProtection()
|
||||||
.PersistKeysToFileSystem(new DirectoryInfo(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "DataProtection"));
|
.PersistKeysToFileSystem(new DirectoryInfo(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "DataProtection"));
|
||||||
@@ -96,7 +104,7 @@ namespace ZR.Admin.WebApi
|
|||||||
});
|
});
|
||||||
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>̬<EFBFBD>ļ<EFBFBD>/wwwrootĿ¼<C4BF>ļ<EFBFBD><C4BC><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>UseRoutingǰ<67><C7B0>
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD>̬<EFBFBD>ļ<EFBFBD>/wwwrootĿ¼<C4BF>ļ<EFBFBD><C4BC><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>UseRoutingǰ<67><C7B0>
|
||||||
app.UseStaticFiles();
|
app.UseStaticFiles();
|
||||||
|
//<2F><><EFBFBD><EFBFBD>·<EFBFBD>ɷ<EFBFBD><C9B7><EFBFBD>
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
app.UseCors("Policy");//Ҫ<><D2AA><EFBFBD><EFBFBD>app.UseEndpointsǰ<73><C7B0>
|
app.UseCors("Policy");//Ҫ<><D2AA><EFBFBD><EFBFBD>app.UseEndpointsǰ<73><C7B0>
|
||||||
|
|
||||||
@@ -107,12 +115,13 @@ namespace ZR.Admin.WebApi
|
|||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
//2.<2E>ٿ<EFBFBD><D9BF><EFBFBD><EFBFBD><EFBFBD>Ȩ
|
//2.<2E>ٿ<EFBFBD><D9BF><EFBFBD><EFBFBD><EFBFBD>Ȩ
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
//<2F><><EFBFBD><EFBFBD>session
|
||||||
app.UseSession();
|
app.UseSession();
|
||||||
|
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
app.UseResponseCaching();
|
app.UseResponseCaching();
|
||||||
|
//<2F>ָ<EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
// <20>ָ<EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
||||||
app.UseAddTaskSchedulers();
|
app.UseAddTaskSchedulers();
|
||||||
|
//ʹ<><CAB9>ȫ<EFBFBD><C8AB><EFBFBD>쳣<EFBFBD>м<EFBFBD><D0BC><EFBFBD>
|
||||||
app.UseMiddleware<GlobalExceptionMiddleware>();
|
app.UseMiddleware<GlobalExceptionMiddleware>();
|
||||||
|
|
||||||
app.UseEndpoints(endpoints =>
|
app.UseEndpoints(endpoints =>
|
||||||
@@ -120,6 +129,9 @@ namespace ZR.Admin.WebApi
|
|||||||
endpoints.MapControllerRoute(
|
endpoints.MapControllerRoute(
|
||||||
name: "default",
|
name: "default",
|
||||||
pattern: "{controller=Home}/{action=Index}/{id?}");
|
pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||||
|
|
||||||
|
//<2F><><EFBFBD><EFBFBD>socket<65><74><EFBFBD><EFBFBD>
|
||||||
|
endpoints.MapHub<MessageHub>("/msgHub");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ VUE_APP_TITLE = 'ZrAdmin.NET后台管理'
|
|||||||
# 开发环境
|
# 开发环境
|
||||||
VUE_APP_BASE_API = '/dev-api'
|
VUE_APP_BASE_API = '/dev-api'
|
||||||
|
|
||||||
|
#socket API
|
||||||
|
VUE_APP_SOCKET_API = '/msgHub'
|
||||||
|
|
||||||
# 路由前缀
|
# 路由前缀
|
||||||
VUE_APP_ROUTER_PREFIX = '/'
|
VUE_APP_ROUTER_PREFIX = '/'
|
||||||
|
|
||||||
|
|||||||
@@ -7,8 +7,11 @@ VUE_APP_TITLE = 'ZrAdmin.NET后台管理'
|
|||||||
# 生产环境
|
# 生产环境
|
||||||
VUE_APP_BASE_API = '/prod-api'
|
VUE_APP_BASE_API = '/prod-api'
|
||||||
|
|
||||||
|
#socket API
|
||||||
|
VUE_APP_SOCKET_API = '/msgHub'
|
||||||
|
|
||||||
# 路由前缀
|
# 路由前缀
|
||||||
VUE_APP_ROUTER_PREFIX = '/'
|
VUE_APP_ROUTER_PREFIX = '/'
|
||||||
|
|
||||||
# 默认上传地址
|
# 默认上传地址
|
||||||
VUE_APP_UPLOAD_URL = '/Common/UploadFile'
|
VUE_APP_UPLOAD_URL = '/Common/UploadFile'
|
||||||
@@ -7,6 +7,9 @@ VUE_APP_TITLE = 'ZrAdmin.NET后台管理'
|
|||||||
# 测试环境
|
# 测试环境
|
||||||
VUE_APP_BASE_API = '/stage-api'
|
VUE_APP_BASE_API = '/stage-api'
|
||||||
|
|
||||||
|
#socket API
|
||||||
|
VUE_APP_SOCKET_API = '/msgHub'
|
||||||
|
|
||||||
# 路由前缀
|
# 路由前缀
|
||||||
VUE_APP_ROUTER_PREFIX = '/'
|
VUE_APP_ROUTER_PREFIX = '/'
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@microsoft/signalr": "^6.0.2",
|
||||||
"@riophae/vue-treeselect": "0.4.0",
|
"@riophae/vue-treeselect": "0.4.0",
|
||||||
"axios": "^0.21.4",
|
"axios": "^0.21.4",
|
||||||
"clipboard": "2.0.8",
|
"clipboard": "2.0.8",
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import store from './store'
|
|||||||
import router from './router'
|
import router from './router'
|
||||||
import permission from './directive/permission'
|
import permission from './directive/permission'
|
||||||
import plugins from './plugins' // plugins
|
import plugins from './plugins' // plugins
|
||||||
|
import signalR from '@/utils/signalR'
|
||||||
|
|
||||||
import './assets/icons' // icon
|
import './assets/icons' // icon
|
||||||
import './permission' // permission control
|
import './permission' // permission control
|
||||||
@@ -43,6 +44,9 @@ Vue.prototype.selectDictLabels = selectDictLabels
|
|||||||
Vue.prototype.download = download
|
Vue.prototype.download = download
|
||||||
Vue.prototype.handleTree = handleTree
|
Vue.prototype.handleTree = handleTree
|
||||||
|
|
||||||
|
signalR.init(process.env.VUE_APP_SOCKET_API);
|
||||||
|
Vue.prototype.signalr = signalR
|
||||||
|
|
||||||
Vue.prototype.msgSuccess = function (msg) {
|
Vue.prototype.msgSuccess = function (msg) {
|
||||||
this.$message({ showClose: true, message: msg, type: "success" });
|
this.$message({ showClose: true, message: msg, type: "success" });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,21 @@
|
|||||||
const getters = {
|
const getters = {
|
||||||
sidebar: state => state.app.sidebar,
|
sidebar: state => state.app.sidebar,
|
||||||
size: state => state.app.size,
|
size: state => state.app.size,
|
||||||
device: state => state.app.device,
|
device: state => state.app.device,
|
||||||
visitedViews: state => state.tagsView.visitedViews,
|
visitedViews: state => state.tagsView.visitedViews,
|
||||||
cachedViews: state => state.tagsView.cachedViews,
|
cachedViews: state => state.tagsView.cachedViews,
|
||||||
token: state => state.user.token,
|
token: state => state.user.token,
|
||||||
avatar: state => state.user.avatar,
|
avatar: state => state.user.avatar,
|
||||||
name: state => state.user.name,
|
name: state => state.user.name,
|
||||||
userId: state => state.user.userInfo.userId,
|
userId: state => state.user.userInfo.userId,
|
||||||
introduction: state => state.user.introduction,
|
introduction: state => state.user.introduction,
|
||||||
roles: state => state.user.roles,
|
roles: state => state.user.roles,
|
||||||
permissions: state => state.user.permissions,
|
permissions: state => state.user.permissions,
|
||||||
permission_routes: state => state.permission.routes,
|
permission_routes: state => state.permission.routes,
|
||||||
userinfo: state => state.user.userInfo,
|
userinfo: state => state.user.userInfo,
|
||||||
topbarRouters: state => state.permission.topbarRouters,
|
topbarRouters: state => state.permission.topbarRouters,
|
||||||
defaultRoutes: state => state.permission.defaultRoutes,
|
defaultRoutes: state => state.permission.defaultRoutes,
|
||||||
sidebarRouters: state => state.permission.sidebarRouters,
|
sidebarRouters: state => state.permission.sidebarRouters,
|
||||||
|
onlineUserNum: state => state.socket.onlineNum
|
||||||
}
|
}
|
||||||
export default getters
|
export default getters
|
||||||
@@ -5,6 +5,7 @@ import user from './modules/user'
|
|||||||
import tagsView from './modules/tagsView'
|
import tagsView from './modules/tagsView'
|
||||||
import permission from './modules/permission'
|
import permission from './modules/permission'
|
||||||
import settings from './modules/settings'
|
import settings from './modules/settings'
|
||||||
|
import socket from './modules/socket'
|
||||||
import getters from './getters'
|
import getters from './getters'
|
||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
@@ -21,7 +22,8 @@ const store = new Vuex.Store({
|
|||||||
user,
|
user,
|
||||||
tagsView,
|
tagsView,
|
||||||
permission,
|
permission,
|
||||||
settings
|
settings,
|
||||||
|
socket
|
||||||
},
|
},
|
||||||
state: state,//这里放全局参数
|
state: state,//这里放全局参数
|
||||||
getters
|
getters
|
||||||
|
|||||||
22
ZR.Vue/src/store/modules/socket.js
Normal file
22
ZR.Vue/src/store/modules/socket.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
const state = {
|
||||||
|
onlineNum: 0
|
||||||
|
}
|
||||||
|
const mutations = {
|
||||||
|
SET_ONLINEUSER_NUM: (state, num) => {
|
||||||
|
state.onlineNum = num
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
//更新在线人数
|
||||||
|
changeOnlineNum({ commit }, data) {
|
||||||
|
commit('SET_ONLINEUSER_NUM', data)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
namespaced: true,
|
||||||
|
state,
|
||||||
|
mutations,
|
||||||
|
actions
|
||||||
|
}
|
||||||
49
ZR.Vue/src/utils/signalR.js
Normal file
49
ZR.Vue/src/utils/signalR.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// 官方文档:https://docs.microsoft.com/zh-cn/aspnet/core/signalr/javascript-client?view=aspnetcore-6.0&viewFallbackFrom=aspnetcore-2.2&tabs=visual-studio
|
||||||
|
import * as signalR from '@microsoft/signalr'
|
||||||
|
import store from '../store'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// signalR对象
|
||||||
|
SR: {},
|
||||||
|
// 失败连接重试次数
|
||||||
|
failNum: 4,
|
||||||
|
baseUrl: '',
|
||||||
|
init(url) {
|
||||||
|
const connection = new signalR.HubConnectionBuilder()
|
||||||
|
.withUrl(url)
|
||||||
|
.build();
|
||||||
|
// console.log('conn', connection);
|
||||||
|
this.SR = connection;
|
||||||
|
|
||||||
|
// 断线重连
|
||||||
|
connection.onclose(async () => {
|
||||||
|
await this.SR.start();
|
||||||
|
})
|
||||||
|
|
||||||
|
connection.on("onlineNum", (data) => {
|
||||||
|
store.dispatch("socket/changeOnlineNum", data);
|
||||||
|
});
|
||||||
|
// 启动
|
||||||
|
this.start();
|
||||||
|
},
|
||||||
|
async start() {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
try {
|
||||||
|
//使用async和await 或 promise的then 和catch 处理来自服务端的异常
|
||||||
|
|
||||||
|
await this.SR.start();
|
||||||
|
|
||||||
|
//console.assert(this.SR.state === signalR.HubConnectionState.Connected);
|
||||||
|
console.log('signalR 连接成功了', this.SR.state);
|
||||||
|
} catch (error) {
|
||||||
|
that.failNum--;
|
||||||
|
console.log(`失败重试剩余次数${that.failNum}`, error)
|
||||||
|
if (that.failNum > 0) {
|
||||||
|
setTimeout(async () => {
|
||||||
|
await this.SR.start()
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,9 +7,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-panel-description">
|
<div class="card-panel-description">
|
||||||
<div class="card-panel-text">
|
<div class="card-panel-text">
|
||||||
访客
|
在线用户
|
||||||
</div>
|
</div>
|
||||||
<count-to :start-val="0" :end-val="102400" :duration="2600" class="card-panel-num" />
|
<count-to :start-val="0" :end-val="onlineUserNum" :duration="2600" class="card-panel-num" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
@@ -56,18 +56,21 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CountTo from 'vue-count-to'
|
import CountTo from "vue-count-to";
|
||||||
|
import { mapGetters } from "vuex";
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
CountTo
|
CountTo,
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters(["onlineUserNum"]),
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleSetLineChartData(type) {
|
handleSetLineChartData(type) {
|
||||||
this.$emit('handleSetLineChartData', type)
|
this.$emit("handleSetLineChartData", type);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -86,8 +89,8 @@ export default {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: #666;
|
color: #666;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
|
box-shadow: 4px 4px 40px rgba(0, 0, 0, 0.05);
|
||||||
border-color: rgba(0, 0, 0, .05);
|
border-color: rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.card-panel-icon-wrapper {
|
.card-panel-icon-wrapper {
|
||||||
@@ -107,7 +110,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.icon-shopping {
|
.icon-shopping {
|
||||||
background: #34bfa3
|
background: #34bfa3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +127,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.icon-shopping {
|
.icon-shopping {
|
||||||
color: #34bfa3
|
color: #34bfa3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-panel-icon-wrapper {
|
.card-panel-icon-wrapper {
|
||||||
@@ -160,7 +163,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width:550px) {
|
@media (max-width: 550px) {
|
||||||
.card-panel-description {
|
.card-panel-description {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,56 +25,54 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import PanelGroup from './dashboard/PanelGroup'
|
import PanelGroup from "./dashboard/PanelGroup";
|
||||||
import LineChart from './dashboard/LineChart'
|
import LineChart from "./dashboard/LineChart";
|
||||||
import RaddarChart from './dashboard/RaddarChart'
|
import RaddarChart from "./dashboard/RaddarChart";
|
||||||
import PieChart from './dashboard/PieChart'
|
import PieChart from "./dashboard/PieChart";
|
||||||
import BarChart from './dashboard/BarChart'
|
import BarChart from "./dashboard/BarChart";
|
||||||
|
|
||||||
const lineChartData = {
|
const lineChartData = {
|
||||||
newVisitis: {
|
newVisitis: {
|
||||||
expectedData: [100, 120, 161, 134, 105, 160, 165],
|
expectedData: [100, 120, 161, 134, 105, 160, 165],
|
||||||
actualData: [120, 82, 91, 154, 162, 140, 145]
|
actualData: [120, 82, 91, 154, 162, 140, 145],
|
||||||
},
|
},
|
||||||
messages: {
|
messages: {
|
||||||
expectedData: [200, 192, 120, 144, 160, 130, 140],
|
expectedData: [200, 192, 120, 144, 160, 130, 140],
|
||||||
actualData: [180, 160, 151, 106, 145, 150, 130]
|
actualData: [180, 160, 151, 106, 145, 150, 130],
|
||||||
},
|
},
|
||||||
purchases: {
|
purchases: {
|
||||||
expectedData: [80, 100, 121, 104, 105, 90, 100],
|
expectedData: [80, 100, 121, 104, 105, 90, 100],
|
||||||
actualData: [120, 90, 100, 138, 142, 130, 130]
|
actualData: [120, 90, 100, 138, 142, 130, 130],
|
||||||
},
|
},
|
||||||
shoppings: {
|
shoppings: {
|
||||||
expectedData: [130, 140, 141, 142, 145, 150, 160],
|
expectedData: [130, 140, 141, 142, 145, 150, 160],
|
||||||
actualData: [120, 82, 91, 154, 162, 140, 130]
|
actualData: [120, 82, 91, 154, 162, 140, 130],
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Index',
|
name: "Index",
|
||||||
components: {
|
components: {
|
||||||
PanelGroup,
|
PanelGroup,
|
||||||
LineChart,
|
LineChart,
|
||||||
RaddarChart,
|
RaddarChart,
|
||||||
PieChart,
|
PieChart,
|
||||||
BarChart
|
BarChart,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
lineChartData: lineChartData.newVisitis
|
lineChartData: lineChartData.newVisitis,
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleSetLineChartData(type) {
|
handleSetLineChartData(type) {
|
||||||
this.lineChartData = lineChartData[type]
|
this.lineChartData = lineChartData[type];
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -90,7 +88,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width:1024px) {
|
@media (max-width: 1024px) {
|
||||||
.chart-wrapper {
|
.chart-wrapper {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,15 @@ module.exports = {
|
|||||||
pathRewrite: {
|
pathRewrite: {
|
||||||
['^' + process.env.VUE_APP_BASE_API]: '' //需要rewrite的
|
['^' + process.env.VUE_APP_BASE_API]: '' //需要rewrite的
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"msgHub": {
|
||||||
|
target: 'http://localhost:8888/msgHub',
|
||||||
|
ws: true,
|
||||||
|
changeOrigin: true,
|
||||||
|
pathRewrite: {
|
||||||
|
['^/msgHub']: '' //需要rewrite的
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
disableHostCheck: true
|
disableHostCheck: true
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user