完成页面应用管理、用户管理

This commit is contained in:
falcon 2020-05-18 11:09:31 +08:00
parent 791f7d48f3
commit 57554f1ae3
17 changed files with 12341 additions and 90 deletions

View File

@ -1,9 +1,7 @@
using System;
using System.Threading.Tasks;
using FAuth.Extensions;
using FAuth.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
namespace FAuth.Controllers.api

View File

@ -51,14 +51,14 @@ namespace FAuth.Controllers.api
/// <summary>
/// 删除一个应用
/// </summary>
/// <param name="appName">应用名称</param>
/// <param name="id">应用编号</param>
/// <returns>删除结果</returns>
[HttpPost]
public bool RemoveApp(string appName) {
if(appName.IsNullOrEmpty()) {
throw new ApiArgumentNullException(nameof(appName));
public bool RemoveApp(int id) {
if(id == 1) {
throw new ApiException("系统应用不可以删除");
}
var qu = this.Db.Apps.Where(m => m.Name == appName);
var qu = this.Db.Apps.Where(m => m.Id == id);
foreach(var item in qu) {
this.Db.Entry(item).State = EntityState.Deleted;
}
@ -95,6 +95,7 @@ namespace FAuth.Controllers.api
if(this.Account.IsNotSystemAdmin(adminTicket)) {
throw new ApiException("需要提供管理员票据");
}
var list = this.Cache.GetObj<List<Apps>>("");
var qu = this.Db.Apps;
return qu.ToList();
}

View File

@ -113,21 +113,36 @@ namespace FAuth.Controllers.api
/// <summary>
/// 获取用户信息列表
/// </summary>
/// <param name="userName">登录用户名</param>
/// <param name="name">用户名</param>
/// <returns>用户信息列表</returns>
[HttpGet]
[ProducesResponseType(typeof(IEnumerable<UserInfo>),200)]
public IEnumerable<UserInfo> GetUsers() {
var key = "FAuth:Users";
var obj = this.Cache?.GetObj<List<UserInfo>>(key);
if(obj == null) {
obj = this.Db.Users
.Select(m => new UserInfo {
Id = m.Id,
UserName = m.UserName,
}).ToList();
this.Cache?.SetCache(key,obj,new TimeSpan(0,5,0));
public IEnumerable<UserInfo> GetUsers(string userName,string name) {
var key = $"FAuth:Users:userName:{userName}:name:{name}";
List<UserInfo> result = null;// this.Cache?.GetObj<List<UserInfo>>(key);
if(result == null) {
var qu = this.Db.Users
.Select(m => new UserInfo {
Id = m.Id,
UserName = m.UserName,
Name = m.Name,
LastLoginDatetime = m.LastLoginDatetime,
Status =
!m.LastLoginDatetime.HasValue ? "未登陆" :
!m.LastLogoutDatetime.HasValue ? "在线" :
m.LastLoginDatetime.Value > m.LastLogoutDatetime.Value ? "在线" : "离线",
});
if(userName.IsNotNullOrEmpty()) {
qu = qu.Where(m => m.UserName == userName);
}
if(name.IsNotNullOrEmpty()) {
qu = qu.Where(m => m.Name == name);
}
result = qu.ToList();
this.Cache?.SetCache(key,result,new TimeSpan(0,5,0));
}
return obj;
return result;
}
/// <summary>
@ -163,7 +178,8 @@ namespace FAuth.Controllers.api
/// <param name="password">用户密码</param>
/// <returns>是否成功</returns>
[HttpPost]
public bool AddNewUser(string adminTicket,string userName,string name,string password) {
[ProducesResponseType(typeof(UserInfo),200)]
public UserInfo AddNewUser(string adminTicket,string userName,string name,string password) {
if(adminTicket is null)
throw new ApiArgumentNullException(nameof(adminTicket));
if(userName is null)
@ -186,7 +202,12 @@ namespace FAuth.Controllers.api
this.Db.Entry(nUser).State = EntityState.Added;
this.Db.SaveChangesAsync().Wait();
this.Logger.LogInformation($"用户{nUser.Id}:{nUser.UserName}:{nUser.Name}添加成功!");
return true;
return new UserInfo {
Id = nUser.Id,
UserName = nUser.UserName,
Name = nUser.Name,
LastLoginDatetime = nUser.LastLoginDatetime,
};
}
/// <summary>
@ -218,5 +239,24 @@ namespace FAuth.Controllers.api
this.Db.SaveChangesAsync().Wait();
return true;
}
/// <summary>
/// 删除用户
/// </summary>
/// <param name="adminTicket">管理员凭据</param>
/// <param name="id">要删除的用户编号</param>
/// <returns>删除结果</returns>
[HttpPost, ProducesResponseType(typeof(ApiBoolResult),200)]
public ApiBoolResult RemoveUser(string adminTicket,int id) {
var user = this.Account.TicketDryptor.Decrypt(adminTicket);
if(user.Id == id) {
throw new ApiException("当前用户不能删除");
}
this.Db.Users.Attach(new FUser {
Id = id,
}).State = EntityState.Deleted;
this.Db.SaveChangesAsync().Wait();
return new ApiBoolResult { Result = true };
}
}
}

View File

@ -0,0 +1,32 @@
using System;
using Falcon.Extend;
using FAuth.Extensions;
using FAuth.Extensions.Account;
using FAuth.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using api = FAuth.Controllers.api;
namespace FAuth.Controllers.web
{
/// <summary>
/// Ó¦ÓÿØÖÆÆ÷
/// </summary>
public class AppController:WebControllerBase<AppController>
{
public AccountHelper Account { get; set; }
public AppController(ILogger<AppController> logger,IServiceProvider service) : base(logger,service) {
this.Account = this.Services.GetService<AccountHelper>();
}
public IActionResult Index() {
return PartialView();
}
public IActionResult AddNew() {
return PartialView();
}
}
}

View File

@ -1,15 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using FAuth.Models;
using FAuth.Extensions;
using Microsoft.Extensions.DependencyInjection;
using api = FAuth.Controllers.api;
using Falcon.Extend;
namespace FAuth.Controllers.web
{

View File

@ -0,0 +1,13 @@
namespace FAuth.Models
{
/// <summary>
/// api返回bool结果
/// </summary>
public class ApiBoolResult
{
/// <summary>
/// 是否成功
/// </summary>
public bool Result { get; set; }
}
}

View File

@ -26,5 +26,9 @@ namespace FAuth.Models
/// 上次登录时间
/// </summary>
public DateTimeOffset? LastLoginDatetime { get; set; }
/// <summary>
/// 账户状态
/// </summary>
public string Status { get; set; }
}
}

View File

@ -105,7 +105,7 @@ namespace FAuth
db.InitSync().Wait();
}
app.UseHttpsRedirection();
//app.UseHttpsRedirection();
app.UseStaticFiles();

View File

@ -0,0 +1,28 @@
<fieldset id="app_addNew">
<legend>新增应用</legend>
<label>应用名称:<input type="text" v-model="appName" /></label>
<label>应用说明:<input type="text" v-model="description" /></label>
<input type="button" value="提交" v-on:click="submit" />
</fieldset>
<script type="text/javascript">
mydata.app_new = new Vue({
el: '#app_addNew',
data: {
userTicket: myJs.getTicket(),
appName: "",
description: "",
},
methods: {
submit() {
debugger;
var url = myJs.url.app.AddNewApp;
myJs.post(url, { appName: this.appName, description: this.description }, function (d) {
if (mydata.app_index.rows) mydata.app_index.rows.push(d);
$("#app_addNew").html("");
}, function (s, i, m) {
myJs.msg(m);
});
},
},
});
</script>

View File

@ -1,7 +1,70 @@

@{
ViewData["Title"] = "Index";
}
<h1>AppController Index</h1>
<div id="app_index">
<fieldset>
<legend>查询应用</legend>
<label>应用名称:<input type="text" name="appName" v-model="appNameValue" /></label>
<input type="button" value="查询" id="search" v-on:click="search" />
<a fajax-updata="#newdlg" asp-controller="app" asp-action="AddNew">新增</a>
</fieldset>
<table class="table" v-if="rows.length > 0">
<thead>
<tr>
<td>应用编号</td>
<td>应用名称</td>
<td>说明</td>
<td>操作</td>
</tr>
</thead>
<tbody>
<tr v-for="r in rows">
<td>{{r.Id}}</td>
<td>{{r.Name}}</td>
<td>{{r.Description}}</td>
<td><input type="button" value="删除" v-on:click="remove(r.Id)" /></td>
</tr>
</tbody>
</table>
<div id="newdlg"></div>
</div>
<script type="text/javascript">
mydata.app_index = new Vue({
el: '#app_index',
data: {
userTicket: myJs.getTicket(),
appNameValue: "全部",
rows: [],
},
methods: {
search() {
if (this.appNameValue == "全部" || this.appNameValue == "") {
var url = myJs.url.app.GetAppList;
myJs.get(url, { adminTicket: this.userTicket }, function (d) {
mydata.app_index.rows = d;
}, function (s, i, m) {
myJs.msg(m);
});
} else {
var url = myJs.url.app.GetApps;
myJs.post(url, { adminTicket: this.userTicket, appName: this.appNameValue, }, function (d) {
mydata.app_index.rows = new Array(d);
}, function (s, i, m) {
myJs.msg(m);
});
}
},
remove(id) {
var url = myJs.url.app.RemoveApp;
myJs.post(url, { id: id }, function (d) {
var nArr = [];
$.each(mydata.app_index.rows, function () {
if (this.Id != id) {
nArr.push(this);
}
});
mydata.app_index.rows = nArr;
}, function (s, i, m) {
myJs.msg(m);
});
},
},
});
</script>

View File

@ -62,57 +62,57 @@
</div>
</footer>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/vue/vue.min.js"></script>
<script src="~/lib/jquery.cookie/jquery.cookie-1.4.1.min.js"></script>
<script src="~/lib/jquery.unobtrusive-ajax/jquery.unobtrusive-ajax.min.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<script type="text/javascript">
//设置用户key
myJs.userKey="@CKD.Value.UserKey";
//设置用户key
myJs.userKey = "@CKD.Value.UserKey";
//刷新用户条
function RefreshUserBar() {
var ticket =myJs.getTicket();
if (!ticket) {
//刷新用户条
function RefreshUserBar() {
var ticket =myJs.getTicket();
if (!ticket) {
$("#logout").hide();
$("#login").show();
}
if (ticket) {
var url = "/api/User/GetUserByTicket";
var data = { ticket: ticket };
myJs.get(url, data, function (d) {
$("#userName").html(d.Name);
$("#logout").show();
$("#login").hide();
}, function (c,i,m) {
$("#logout").hide();
$("#login").show();
}
if (ticket) {
var url = "/api/User/GetUserByTicket";
var data = { ticket: ticket };
myJs.get(url, data, function (d) {
$("#userName").html(d.Name);
$("#logout").show();
$("#login").hide();
}, function (c,i,m) {
$("#logout").hide();
$("#login").show();
myJs.msg(m);
myJs.removeTicket();
});
}
}
function logOut() {
var ticket = myJs.getTicket();
var url = "/api/User/Logout";
var data = { ticket: ticket };
myJs.post(url, data, function (d) {
myJs.removeTicket(ticket);
RefreshUserBar();
}, function (s,i,m) {
myJs.msg(m);
myJs.msg(m);
myJs.removeTicket();
});
}
$(function () {
RefreshUserBar();
}
$("#logOut").click(function () {
logOut();
return false;
});
function logOut() {
var ticket = myJs.getTicket();
var url = "/api/User/Logout";
var data = { ticket: ticket };
myJs.post(url, data, function (d) {
myJs.removeTicket(ticket);
RefreshUserBar();
}, function (s,i,m) {
myJs.msg(m);
});
}
$(function () {
RefreshUserBar();
$("#logOut").click(function () {
logOut();
return false;
});
});
</script>
@RenderSection("Scripts",required: false)
</body>

View File

@ -1,7 +1,81 @@

@{
ViewData["Title"] = "Index";
}
<h1>User Index</h1>
<div id="user_index">
<fieldset>
<legend>用户查询</legend>
<label>登录名:<input type="text" v-model="userName" /></label>
<label>用户名:<input type="text" v-model="name" /></label>
<input type="button" v-on:click="userSearch" value="查询" />
<input type="button" v-on:click="clear" value="清空" />
<input type="button" v-on:click="addNew" value="新增" />
</fieldset>
<table class="table" v-if="tableShow">
<thead>
<tr>
<th>用户编号</th>
<th>用户登录名</th>
<th>用户姓名</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="u in users">
<td>{{u.Id}}</td>
<td>{{u.UserName}}</td>
<td>{{u.Name}}</td>
<td>{{u.Status}}</td>
<td><input type="button" value="删除" v-on:click="removeUser(u.Id)" /></td>
</tr>
</tbody>
</table>
</div>
<script type="text/javascript">
var userIndex = new Vue({
el: "#user_index",
data: {
userName: "",
name: "",
tableShow: false,
users: [],
ticket: myJs.getTicket(),
},
methods: {
userSearch() {
myJs.get(myJs.url.user.GetUsers, { userName: this.userName, name: this.name, }, function (d) {
userIndex.users = d;
userIndex.tableShow = true;
}, function (s, i, m) {
myJs.msg(m);
});
},
clear() {
this.userName = "";
this.name = "";
this.tableShow = false;
this.users = [];
},
addNew() {
debugger;
myJs.post(myJs.url.user.AddNewUser, {
adminTicket: this.ticket,
userName: this.userName,
name: this.name,
password: this.userName,
}, function (d) {
userIndex.users.push(d);
userIndex.tableShow = true;
});
},
removeUser(id) {
myJs.post(myJs.url.user.RemoveUser, { adminTicket: this.ticket, id: id }, function (d) {
var nArr = [];
$.each(userIndex.users, function () {
if (this.Id != id) {
nArr.push(this);
}
});
userIndex.users = nArr;
});
},
}
});
</script>

View File

@ -68,4 +68,4 @@ body {
width: 100%;
white-space: nowrap;
line-height: 60px; /* Vertically center the text there */
}
}

View File

@ -1,9 +1,4 @@
// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
// for details on configuring this project to bundle and minify static web assets.
// Write your JavaScript code.
var myJs = {};
var myJs = {};
myJs.get = function (url, data, success, error) {
$.ajax({
url: url,
@ -13,6 +8,11 @@ myJs.get = function (url, data, success, error) {
success(d);
},
error: function (d) {
if (!error) {
error = function (s, i, m) {
myJs.msg(m);
};
}
error(d.status, d.responseJSON.Id, d.responseJSON.Message)
},
});
@ -26,6 +26,11 @@ myJs.post = function (url, data, success, error) {
success(d);
},
error: function (d) {
if (!error) {
error = function (s, i, m) {
myJs.msg(m);
};
}
error(d.status, d.responseJSON.Id, d.responseJSON.Message)
},
});
@ -42,4 +47,21 @@ myJs.getTicket = function () {
//移除用户登录票据
myJs.removeTicket = function () {
$.removeCookie(myJs.userKey);
}
}
myJs.url = {
app: {
AddNewApp: "api/app/AddNewApp",
RemoveApp: "api/app/RemoveApp",
GetApps: "api/app/GetApps",
GetAppList: "api/app/GetAppList",
},
user: {
GetUsers: "/api/User/GetUsers",
AddNewUser: "/api/User/AddNewUser",
RemoveUser: "/api/User/RemoveUser",
},
};
var mydata = {}

View File

@ -0,0 +1,7 @@
var vm = new Vue({
el: "div",
data: {
},
methods: {
}
});

11972
FAuth/wwwroot/lib/vue/vue.js Normal file

File diff suppressed because it is too large Load Diff

6
FAuth/wwwroot/lib/vue/vue.min.js vendored Normal file

File diff suppressed because one or more lines are too long