ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(六)学生借阅/预约/查询书籍事务
前言:
本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作。
本系列文章主要参考资料:
微软文档:https://docs.microsoft.com/zh-cn/aspnet/core/getting-started/?view=aspnetcore-2.1&tabs=windows
《Pro ASP.NET MVC 5》、《锋利的 jQuery》
此系列皆使用 VS2017+C# 作为开发环境。如果有什么问题或者意见欢迎在留言区进行留言。
项目 github 地址:https://github.com/NanaseRuri/LibraryDemo
本章内容:自定义布局页、自定义 EditorFor 模板、EF 多对多数据的更新
一、自定义布局页
在 ASP.NET 中,默认将 HTML 页面的 body 元素一部分抽出来,该部分称作 RenderBody ;然后将这部分放到一个布局即大体页面框架中即可完成对同一系列的页面进行精简的布局实现。
默认布局页为 _Layout.cshtml,可在视图文件夹中根目录或各个控制器视图目录的 _ViewStart.cshtml 修改默认布局页,或者在每个 Razor 页面的开头中指定布局页:
@{
ViewData["Title"] = "EditLendingInfo";
Layout = "_LendingLayout";
}
之前一直使用的是 VS 的默认布局页,现在以该默认布局页为基础,添加自己所需要的信息:
@using Microsoft.AspNetCore.Http.Extensions
@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - LibraryDemo</title>
<environment include="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a asp-area="" asp-controller="BookInfo" asp-action="Index" class="navbar-brand">LibraryDemo</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a asp-area="" asp-controller="BookInfo" asp-action="Index">首页</a></li>
<li>
@if (User.Identity.IsAuthenticated)
{
<a asp-controller="BookInfo" asp-action="PersonalInfo">@User.Identity.Name</a>
}
else
{
<a asp-area="" asp-controller="StudentAccount" asp-action="Login"
asp-route-returnUrl="@(Context.Request.GetDisplayUrl())">登录</a>
}
</li>
<li><a asp-area="" asp-controller="BookInfo" asp-action="Recommend">推荐图书</a></li>
<li><a href="mailto:Nanase@cnblogs.com">联系我们</a></li>
@if (User.Identity.IsAuthenticated)
{
<li>
<a asp-action="Logout" asp-controller="StudentAccount" asp-route-returnUrl="@(Context.Request.GetDisplayUrl())">注销</a>
</li>
}
</ul>
</div>
</div>
</nav>
<div align="center">
<br />
<form action="@Url.Action("Search", "BookInfo")">
@Html.DropDownList("keyword", new List<SelectListItem>()
{
new SelectListItem("书名", "Name"),
new SelectListItem("ISBN", "ISBN"),
new SelectListItem("索书号", "FetchBookNumber"),
})
<input type="text" name="value"/>
<button type="submit"><span class="glyphicon glyphicon-search"></span></button>
</form> @if (TempData["message"] != null)
{
<br/>
<p class="text-success">@TempData["message"]</p>
<br/>
}
</div>
<partial name="_CookieConsentPartial" />
<div class="container body-content"> @RenderBody()
<hr />
</div> <div class="container" style="margin-top: 20px;">
<footer>
<p>© - LibraryDemo</p>
</footer>
</div>
<environment include="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment exclude="Development">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT"></script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
crossorigin="anonymous"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa"></script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>
@RenderSection("Scripts", required: false)
</body>
</html>
现在大体框架:
除了默认的 RenderBody 外,可以指定特定的部分放在页面的不同地方,在布局页中使用@RenderSection("SectionName"):
@RenderSection("SectionName")
且在视图页中使用指定特定的节@section SectionName{ };
@section SectionName{ };
则该视图页中的 SectionName 部分会被提取出来放到布局页对应的位置。
二、管理员编辑借阅信息
动作方法:
在此对数据库的表格使用 Include 方法使 EF 应用其导航属性以获得 KeepingBooks 列表,否则使用 Student 对象 KeepingBooks 属性只会返回空。
[Authorize(Roles = "Admin")]
public IActionResult EditLendingInfo(string barcode)
{
if (barcode == null)
{
return RedirectToAction("BookDetails");
}
Book book = _lendingInfoDbContext.Books.FirstOrDefault(b => b.BarCode == barcode);
return View(book);
} [HttpPost]
[Authorize(Roles = "Admin")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> EditLendingInfo([Bind("BarCode,ISBN,BorrowTime,KeeperId,AppointedLatestTime,State")]Book book)
{
if (ModelState.IsValid)
{
if (book.BorrowTime > DateTime.Now)
{
ModelState.AddModelError("", "请检查外借时间");
return View(book);
}
if (book.AppointedLatestTime.HasValue)
{
if (book.AppointedLatestTime < DateTime.Now)
{
ModelState.AddModelError("", "请检查预约时间");
return View(book);
} if (book.KeeperId == null)
{
ModelState.AddModelError("", "不存在该学生");
return View(book);
}
} StudentInfo student = await _lendingInfoDbContext.Students.Include(s => s.KeepingBooks).FirstOrDefaultAsync(s => s.UserName == book.KeeperId); Book addedBook = _lendingInfoDbContext.Books
.Include(b => b.Keeper).ThenInclude(k => k.KeepingBooks)
.FirstOrDefault(b => b.BarCode == book.BarCode);
if (addedBook == null)
{
return RedirectToAction("Books", new { isbn = book.ISBN });
} StudentInfo preStudent = addedBook.Keeper;
AppointmentOrLending targetLending =
preStudent?.KeepingBooks.FirstOrDefault(b => b.BookId == addedBook.BarCode); addedBook.AppointedLatestTime = book.AppointedLatestTime;
addedBook.State = book.State;
addedBook.BorrowTime = book.BorrowTime;
addedBook.MatureTime = null; preStudent?.KeepingBooks.Remove(targetLending); if (addedBook.BorrowTime.HasValue)
{
if (book.KeeperId == null)
{
ModelState.AddModelError("", "请检查借阅者");
return View(book);
} if (student == null)
{
ModelState.AddModelError("", "不存在该学生");
return View(book);
}
if (student != null)
{
if (student.KeepingBooks.Count >= student.MaxBooksNumber)
{
TempData["message"] = "该学生借书已超过上限";
} addedBook.State = BookState.Borrowed;
student.KeepingBooks.Add(new AppointmentOrLending()
{
BookId = addedBook.BarCode,
StudentId = student.UserName
});
addedBook.Keeper = student; }
addedBook.MatureTime = addedBook.BorrowTime + TimeSpan.FromDays();
} TempData["message"] = "保存成功";
await _lendingInfoDbContext.SaveChangesAsync();
return RedirectToAction("Books", new { isbn = book.ISBN });
}
return View(book);
}
将 BookState 枚举提取成分部视图 _BookStatePartial:
@using LibraryDemo.Models.DomainModels
@model Book
<div class="form-group">
@Html.LabelFor(b => b.State)
@Html.DropDownListFor(b => b.State, Enum.GetValues(typeof(BookState)).Cast<Enum>().Select(state =>
{
string enumVal = Enum.GetName(typeof(BookState), state);
string displayVal;
switch (enumVal)
{
case "Normal":
displayVal = "可借阅";
break;
case "Readonly":
displayVal = "馆内阅览";
break;
case "Borrowed":
displayVal = "已借出";
break;
case "ReBorrowed":
displayVal = "被续借";
break;
case "Appointed":
displayVal = "被预约";
break;
default:
displayVal = "";
break;
}
return new SelectListItem()
{
Text = displayVal,
Value = enumVal,
Selected = Model.State.ToString() == enumVal
};
}))
</div>
Html.DisplayFor 方法是 ASP.NET 内置对各种属性进行展示的方法,可以在项目的 Views 文件夹中的 Shared 文件夹创建对应类型的 Editor 模板供其使用:
在此创建一个 DateTime.cshtml,于是我们使用 Html.DisplayFor 用于展示 DateTime 数据时只会显示年份/月份/天数:
@model DateTime? @Model?.ToString("yyyy/M/dd")
视图中第 40 行使用 partial TagHelper 指定其 name 为 _BookStatePartial 以应用分部视图:
@model LibraryDemo.Models.DomainModels.Book
@{
ViewData["Title"] = "EditLendingInfo";
Layout="_LendingLayout";
} <h2>@Model.BarCode</h2>
<h3>@Model.Name</h3>
<br/> <script>
window.onload = function() {
$("input").addClass("form-control");
}
window.onbeforeunload = function (event) {
return "您的数据未保存,确定退出?";
}
function removeOnbeforeunload() {
window.onbeforeunload = "";
}
</script> @Html.ValidationSummary(false,"",new{@class="text-danger"}) <form asp-action="EditLendingInfo" method="post">
@Html.HiddenFor(b => b.BarCode)
@Html.HiddenFor(b => b.ISBN)
<div class="form-group">
@Html.LabelFor(b => b.KeeperId)
@Html.EditorFor(b => b.KeeperId)
</div>
<div class="form-group">
@Html.LabelFor(b => b.BorrowTime)
@Html.EditorFor(b => b.BorrowTime)
</div>
<div class="form-group">
@Html.LabelFor(b => b.AppointedLatestTime)
@Html.EditorFor(b => b.AppointedLatestTime)
</div>
<partial model="@Model" name="_BookStatePartial"/>
<input type="submit" onclick="return removeOnbeforeunload()" class="btn-primary"/>
</form>
结果:
三、查看个人信息
这里通过 User.Identity.Name 获取当前登录人的信息以选定当前登录的学生:
[Authorize]
public async Task<IActionResult> PersonalInfo()
{
StudentInfo student = await _lendingInfoDbContext.Students.Include(s => s.KeepingBooks).ThenInclude(k => k.Book)
.FirstOrDefaultAsync(s => s.UserName == User.Identity.Name);
decimal fine = ;
foreach (var book in student.KeepingBooks.Where(b => b.Book.MatureTime < DateTime.Now && !b.AppointingDateTime.HasValue))
{
fine += (DateTime.Now - book.Book.MatureTime.Value).Days * (decimal)0.2;
book.Book.State = book.Book.State == BookState.Appointed ? BookState.Appointed : BookState.Expired;
} student.Fine = fine;
PersonalInfoViewModel model = new PersonalInfoViewModel()
{
Student = student,
BookingBook = _lendingInfoDbContext.Books.FirstOrDefault(b => b.BarCode == student.AppointingBookBarCode)
};
return View(model);
}
视图:
@model LibraryDemo.Models.PersonalInfoViewModel
@{
ViewData["Title"] = "PersonalInfo";
Layout = "_LendingLayout";
}
<link rel="stylesheet" href="~/css/BookInfo.css" />
<script>
function ensureCancel() {
if (confirm("确定取消预约?")) {
return true;
}
return false;
}
</script> <h2>@Model.Student.Name</h2>
<br />
@if (Model.Student.KeepingBooks.Any(b => b.Book.MatureTime < DateTime.Now))
{
<table>
<thead>
<tr>
<th colspan="">过期书籍</th>
</tr>
</thead>
<tr>
<th>书名</th>
<th>条形码</th>
<th>状态</th>
<th>到期时间</th>
<th>索书号</th>
</tr> @foreach (var matureBook in Model.Student.KeepingBooks.Where(b => b.Book.MatureTime < DateTime.Now && !b.AppointingDateTime.HasValue))
{
<tr>
<td>@matureBook.Book.Name</td>
<td>@matureBook.Book.BarCode</td>
<td>@Html.DisplayFor(b => matureBook.Book.State)</td>
<td>@matureBook.Book.MatureTime?.ToString("yyyy/MM/dd")</td>
<td>@matureBook.Book.FetchBookNumber</td>
</tr>
}
<tfoot><tr><td colspan="">罚款:@Model.Student.Fine</td></tr></tfoot>
</table>
}
<form asp-action="ReBorrow" method="post">
<table>
<tr>
<th>续借</th>
<th>书名</th>
<th>条形码</th>
<th>状态</th>
<th>到期时间</th>
<th>索书号</th>
</tr>
@if (!Model.Student.KeepingBooks.Any())
{
<tr>
<td colspan="" style="text-align: center">未借阅书本</td>
</tr>
}
else
{
foreach (var keepingBook in Model.Student.KeepingBooks.Where(b=>!b.AppointingDateTime.HasValue))
{
<tr>
<td><input type="checkbox" value="@keepingBook.Book.BarCode" name="barcodes"/></td>
<td>@keepingBook.Book.Name</td>
<td>@keepingBook.Book.BarCode</td>
<td>@Html.DisplayFor(b=>keepingBook.Book.State)</td>
<td>@keepingBook.Book.MatureTime?.ToString("yyyy/MM/dd")</td>
<td>@keepingBook.Book.FetchBookNumber</td>
</tr>
}
}
</table>
<br/>
<input type="submit" class="btn-primary btn" value="续借"/>
</form> <br />
@if (Model.BookingBook != null)
{
<form asp-action="CancelAppointing">
<table>
<tr>
<th>书名</th>
<th>条形码</th>
<th>状态</th>
<th>预约时间</th>
<th>索书号</th>
</tr>
<book-info book="@Model.BookingBook" is-booking-book="true"></book-info>
</table>
<br />
<input type="hidden" name="barcode" value="@Model.BookingBook.BarCode"/>
<input type="submit" value="取消预约" class="btn btn-danger" onclick="return ensureCancel()"/>
</form>
}
结果:
四、借阅书籍
由于暂时未有获取二维码的接口,仅通过直接访问 Lending 模拟借阅:
[Authorize]
public async Task<IActionResult> Lending(string barcode)
{
Book targetBook=await _lendingInfoDbContext.Books.Include(b=>b.Appointments).FirstOrDefaultAsync(b => b.BarCode == barcode);
if (targetBook==null)
{
TempData["message"] = "请重新扫描书籍";
return RedirectToAction("PersonalInfo");
} if (targetBook.Appointments.Any(a=>a.AppointingDateTime.HasValue))
{
TempData["message"] = "此书已被预约";
return RedirectToAction("PersonalInfo");
} if (targetBook.State==BookState.Readonly)
{
TempData["message"] = "此书不供外借";
return RedirectToAction("PersonalInfo");
} targetBook.State = BookState.Borrowed;
targetBook.BorrowTime = DateTime.Now.Date;
targetBook.MatureTime = DateTime.Now.Date+TimeSpan.FromDays();
StudentInfo student =
await _lendingInfoDbContext.Students.Include(s=>s.KeepingBooks).FirstOrDefaultAsync(s => s.UserName == User.Identity.Name);
student.KeepingBooks.Add(new AppointmentOrLending()
{
BookId = targetBook.BarCode,
StudentId = student.UserName
});
await _lendingInfoDbContext.SaveChangesAsync();
TempData["message"] = "借书成功";
return RedirectToAction("PersonalInfo");
}
结果:
六、续借书籍
动作方法:
[Authorize]
[HttpPost]
public async Task<IActionResult> ReBorrow(IEnumerable<string> barcodes)
{
StringBuilder borrowSuccess = new StringBuilder();
StringBuilder borrowFail = new StringBuilder();
borrowSuccess.Append("成功续借书籍:");
borrowFail.Append("续借失败书籍:");
foreach (var barcode in barcodes)
{
Book reBorrowBook = _lendingInfoDbContext.Books.FirstOrDefault(b => b.BarCode == barcode);
if (reBorrowBook != null)
{
if (reBorrowBook.State == BookState.Borrowed && DateTime.Now-reBorrowBook.MatureTime?.Date<=TimeSpan.FromDays())
{
reBorrowBook.State = BookState.ReBorrowed;
reBorrowBook.BorrowTime = DateTime.Now.Date;
reBorrowBook.MatureTime = DateTime.Now.Date+TimeSpan.FromDays();
borrowSuccess.Append($"《{reBorrowBook.Name}》、");
}
else
{
borrowFail.Append($"《{reBorrowBook.Name}》、");
}
}
}
borrowSuccess.AppendLine(borrowFail.ToString());
await _lendingInfoDbContext.SaveChangesAsync();
TempData["message"] = borrowSuccess.ToString();
return RedirectToAction("PersonalInfo");
}
结果:
七、查询书籍
修改之前的 Search 方法使其通过当前用户的身份返回不同页面,以及在 _LendingInfoLayout 中添加搜索框部分:
19 行通过短路使未授权用户不用登录。
public async Task<IActionResult> Search(string keyWord, string value)
{
BookDetails bookDetails = new BookDetails();
switch (keyWord)
{
case "Name":
bookDetails = await _lendingInfoDbContext.BooksDetail.AsNoTracking().FirstOrDefaultAsync(b => b.Name == value);
break;
case "ISBN":
bookDetails = await _lendingInfoDbContext.BooksDetail.AsNoTracking().FirstOrDefaultAsync(b => b.ISBN == value);
break;
case "FetchBookNumber":
bookDetails = await _lendingInfoDbContext.BooksDetail.AsNoTracking().FirstOrDefaultAsync(b => b.FetchBookNumber == value);
break;
} if (bookDetails != null)
{
if (User.Identity.IsAuthenticated&& User.IsInRole("Admin"))
{
return RedirectToAction("EditBookDetails", new { isbn = bookDetails.ISBN });
}
else
{
return RedirectToAction("Detail", new {isbn = bookDetails.ISBN});
}
} TempData["message"] = "找不到该书籍";
return RedirectToAction("BookDetails");
}
结果:
ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(六)学生借阅/预约/查询书籍事务的更多相关文章
- ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(一) 基本模型以及数据库的建立
前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...
- ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(二)数据库初始化、基本登录页面以及授权逻辑的建立
前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...
- ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(七) 学生信息增删
前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...
- ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(五)外借/阅览图书信息的增删改查
前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...
- ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(四)图书信息的增删改查
前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/asp ...
- ASP.NET Core MVC 打造一个简单的图书馆管理系统 (修正版)(三)密码修改以及密码重置
前言: 本系列文章主要为我之前所学知识的一次微小的实践,以我学校图书馆管理系统为雏形所作. 本系列文章主要参考资料: 微软文档:https://docs.microsoft.com/zh-cn/as ...
- 002.Create a web API with ASP.NET Core MVC and Visual Studio for Windows -- 【在windows上用vs与asp.net core mvc 创建一个 web api 程序】
Create a web API with ASP.NET Core MVC and Visual Studio for Windows 在windows上用vs与asp.net core mvc 创 ...
- 在ASP.NET Core MVC中构建简单 Web Api
Getting Started 在 ASP.NET Core MVC 框架中,ASP.NET 团队为我们提供了一整套的用于构建一个 Web 中的各种部分所需的套件,那么有些时候我们只需要做一个简单的 ...
- Pro ASP.NET Core MVC 第6版 第二章(前半章)
目录 第二章 第一个MVC 应用程序 学习一个软件开发框架的最好方法是跳进他的内部并使用它.在本章,你将用ASP.NET Core MVC创建一个简单的数据登录应用.我将它一步一步地展示,以便你能看清 ...
随机推荐
- BUPT复试专题—树查找(2011)
https://www.nowcoder.com/practice/9a10d5e7d99c45e2a462644d46c428e4?tpId=67&tqId=29641&rp=0&a ...
- 解决ionic 上拉加载组件 ion-infinite-scroll自动调用多次的问题或禁止第一次加载
ionic 中一个上拉刷新的组件 ion-infinite-scroll,如果页面未填充满页面高度,会自动检测并无限调用多次加载更多的函数: 当然,主要会导致首次调用的时候,会执行几次加载更多的函数: ...
- Android Problem- android.content.res.Resources$NotFoundException: String resource ID #0xa
在使用listview时出现错误android.content.res.Resources$NotFoundException: String resource ID #0xa 经查证是在调用Text ...
- LA4043 - Ants(二分图完备最佳匹配KM)
option=com_onlinejudge&Itemid=8&page=show_problem&problem=2044">https://icpcarch ...
- Python爬取韩寒所有新浪博客
接上一篇,我们依据第一页的链接爬取了第一页的博客,我们不难发现,每一页的链接就仅仅有一处不同(页码序号),我们仅仅要在上一篇的代码外面加一个循环,这样就能够爬取全部博客分页的博文.也就是全部博文了. ...
- Android Camera系统深入理解
1. Android Camera系统架构 http://blog.csdn.net/myarrow/article/details/8489674
- CentOS7虚拟机桥接设置及问题
转载请注明出处:jiq•钦's technical Blog 今天在VMWare WorkStation9中安装了CentOS7虚拟机. 虚拟机与宿主机网络连接有三种方式:桥接模式.NAT模式和Ho ...
- 求a + aa + aaa + aaaa + aaaaa ...的值,例如:1 + 11 + 111,2 + 22 + 222 + 2222 + 22222
#include <stdio.h> unsigned superposition(unsigned m, unsigned n); int main() { printf("1 ...
- node-sass 安装失败win32-x64-48_binding.node
升级了nodejs的版本,原项目的node-sass模块启动安装不了. 下载对应的win32-x64-xx_binding.node https://github.com/sass/node-sass ...
- ubuntu gcc低版本过低引起错误
错误内容: 正在读取软件包列表... 完成正在分析软件包的依赖关系树 正在读取状态信息... 完成 您可能需要运行“apt-get -f install”来纠正下列错误:下列软件包有未满足的依赖关系: ...