This commit is contained in:
zel
2025-02-07 16:16:10 +08:00
parent 83aade6ac7
commit e38d4d76a2
24 changed files with 119 additions and 159 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -5,23 +5,14 @@
} }
<h3> <h3>
Forgot your password? 忘记密码?
</h3> </h3>
<p>Enter your email.</p>
<hr /> <hr />
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-4">
<form method="post"> 请联系系统管理员为您重置您的密码。
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
<div class="form-floating mb-3">
<input asp-for="Input.Email" class="form-control" autocomplete="username" aria-required="true" placeholder="name@example.com" />
<label asp-for="Input.Email" class="form-label"></label>
<span asp-validation-for="Input.Email" class="text-danger"></span>
</div>
<button type="submit" class="w-100 btn btn-lg btn-primary">Reset Password</button>
</form>
</div> </div>
</div> </div>

View File

@@ -5,7 +5,7 @@
} }
<h3> <h3>
Locked out 登出
</h3> </h3>
<p>This account has been locked out, please try again later.</p> <p>This account has been locked out, please try again later.</p>

View File

@@ -6,6 +6,12 @@
var sessionState = ViewData["SessionState"] as TightWiki.SessionState ?? throw new Exception("Wiki State Context cannot be null."); var sessionState = ViewData["SessionState"] as TightWiki.SessionState ?? throw new Exception("Wiki State Context cannot be null.");
} }
<style>
#forgot-password {
text-decoration: none;
}
</style>
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-8 col-lg-4"> <div class="col-sm-12 col-md-8 col-lg-4">
<section> <section>
@@ -24,7 +30,7 @@
<div class="checkbox mb-3"> <div class="checkbox mb-3">
<label asp-for="Input.RememberMe" class="form-label"> <label asp-for="Input.RememberMe" class="form-label">
<input class="form-check-input" asp-for="Input.RememberMe" /> <input class="form-check-input" asp-for="Input.RememberMe" />
@Html.DisplayNameFor(m => m.Input.RememberMe) 记住账号
</label> </label>
</div> </div>
<div> <div>
@@ -32,7 +38,7 @@
<br /> <br />
</div> </div>
<div> <div>
<p> <p style="margin-top:5px;">
<a id="forgot-password" asp-page="./ForgotPassword">忘记密码?</a> <a id="forgot-password" asp-page="./ForgotPassword">忘记密码?</a>
<br /> <br />
<br /> <br />
@@ -40,40 +46,6 @@
</div> </div>
</form> </form>
</section> </section>
<section>
@{
if ((Model.ExternalLogins?.Count ?? 0) > 0)
{
<form id="external-account" asp-page="./ExternalLogin" asp-route-returnUrl="@UrlEncoder.Default.Encode(Model.ReturnUrl)" method="post" class="form-horizontal">
<div>
<p>
@foreach (var provider in Model.ExternalLogins!)
{
if (provider.Name == "Google")
{
<button type="submit" class="btn w-100 mb-3 d-flex align-items-center" name="provider" value="@provider.Name" title="Log in using your Google account">
<img src="@GlobalConfiguration.BasePath/images/external/google-signin.svg" alt="Google" class="me-2" />
</button>
}
else if (provider.Name == "Microsoft")
{
<button type="submit" class="btn w-100 mb-3 d-flex align-items-center" name="provider" value="@provider.Name" title="Log in using your Microsoft account">
<img src="@GlobalConfiguration.BasePath/images/external/microsoft-signin.svg" alt="Microsoft" class="me-2" />
</button>
}
else
{
<button type="submit" class="btn btn-primary w-100 mb-3" name="provider" value="@provider.Name" title="Log in using your @provider.DisplayName account">
@provider.DisplayName
</button>
}
}
</p>
</div>
</form>
}
}
</section>
</div> </div>
</div> </div>

View File

@@ -5,11 +5,11 @@
} }
<h3> <h3>
Logout 退出
</h3> </h3>
<p> <p>
Logging out will make sure that others cant use this session to make changes to the wiki. You'll need to log back in before making changes.<br /><br /> 退出登录前确保其他人没有在使用当前会话,退出后您需要重新登录<br /><br />
</p> </p>
<hr /> <hr />
@@ -18,12 +18,12 @@
if (User.Identity?.IsAuthenticated ?? false) if (User.Identity?.IsAuthenticated ?? false)
{ {
<form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Page("/", new { area = "" })" method="post"> <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" asp-route-returnUrl="@Url.Page("/", new { area = "" })" method="post">
<button type="submit" class="btn btn-primary rounded-0">Logout</button> <button type="submit" class="btn btn-primary rounded-0">退出</button>
</form> </form>
} }
else else
{ {
<p>You have successfully logged out of the application.</p> <p>操作成功</p>
} }
} }
</header> </header>

View File

@@ -13,21 +13,21 @@
<form id="change-password-form" method="post"> <form id="change-password-form" method="post">
<div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div> <div asp-validation-summary="ModelOnly" class="text-danger" role="alert"></div>
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<input asp-for="Input.OldPassword" class="form-control" autocomplete="current-password" aria-required="true" placeholder="Please enter your old password." /> <input asp-for="Input.OldPassword" class="form-control" autocomplete="current-password" aria-required="true" placeholder="请输入旧密码." />
<label asp-for="Input.OldPassword" class="form-label"></label> <label asp-for="Input.OldPassword" class="form-label">旧密码</label>
<span asp-validation-for="Input.OldPassword" class="text-danger"></span> <span asp-validation-for="Input.OldPassword" class="text-danger"></span>
</div> </div>
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<input asp-for="Input.NewPassword" class="form-control" autocomplete="new-password" aria-required="true" placeholder="Please enter your new password." /> <input asp-for="Input.NewPassword" class="form-control" autocomplete="new-password" aria-required="true" placeholder="请输入新密码." />
<label asp-for="Input.NewPassword" class="form-label"></label> <label asp-for="Input.NewPassword" class="form-label">新密码</label>
<span asp-validation-for="Input.NewPassword" class="text-danger"></span> <span asp-validation-for="Input.NewPassword" class="text-danger"></span>
</div> </div>
<div class="form-floating mb-3"> <div class="form-floating mb-3">
<input asp-for="Input.ConfirmPassword" class="form-control" autocomplete="new-password" aria-required="true" placeholder="Please confirm your new password."/> <input asp-for="Input.ConfirmPassword" class="form-control" autocomplete="new-password" aria-required="true" placeholder="请再次输入新密码."/>
<label asp-for="Input.ConfirmPassword" class="form-label"></label> <label asp-for="Input.ConfirmPassword" class="form-label">请再次输入新密码</label>
<span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span> <span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
</div> </div>
<button type="submit" class="w-100 btn btn-lg btn-primary">Update password</button> <button type="submit" class="w-100 btn btn-lg btn-primary">确认修改</button>
</form> </form>
</div> </div>
</div> </div>

View File

@@ -12,7 +12,7 @@ namespace TightWiki.Areas.Identity.Pages.Account.Manage
{ {
public IActionResult OnGetAsync() public IActionResult OnGetAsync()
{ {
return Redirect($"{GlobalConfiguration.BasePath}/Identity/Account/Manage/Email"); return Redirect($"{GlobalConfiguration.BasePath}/Identity/Account/Manage/ChangePassword");
} }
} }
} }

View File

@@ -1,14 +1,9 @@
@inject SignInManager<IdentityUser> SignInManager @inject SignInManager<IdentityUser> SignInManager
@{ @{
var hasExternalLogins = (await SignInManager.GetExternalAuthenticationSchemesAsync()).Any();
var sessionState = ViewData["SessionState"] as TightWiki.SessionState ?? throw new Exception("Wiki State Context cannot be null."); var sessionState = ViewData["SessionState"] as TightWiki.SessionState ?? throw new Exception("Wiki State Context cannot be null.");
} }
<ul class="nav nav-pills flex-column"> <ul class="nav nav-pills flex-column">
<li class="nav-item"><a class="nav-link @ManageNavPages.EmailNavClass(ViewContext)" id="email" asp-page="./Email">Email</a></li> <li class="nav-item"><a class="nav-link @ManageNavPages.ChangePasswordNavClass(ViewContext)" id="change-password" asp-page="./ChangePassword">ÐÞ¸ÄÃÜÂë</a></li>
<li class="nav-item"><a class="nav-link @ManageNavPages.ChangePasswordNavClass(ViewContext)" id="change-password" asp-page="./ChangePassword">Password</a></li>
@if (hasExternalLogins)
{
<li id="external-logins" class="nav-item"><a id="external-login" class="nav-link @ManageNavPages.ExternalLoginsNavClass(ViewContext)" asp-page="./ExternalLogins">External logins</a></li>
}
<li class="nav-item"><a class="nav-link @ManageNavPages.TwoFactorAuthenticationNavClass(ViewContext)" id="two-factor" asp-page="./TwoFactorAuthentication">Two-factor authentication</a></li>
</ul> </ul>

View File

@@ -48,13 +48,13 @@ namespace TightWiki.Controllers
returnUrl ??= Url.Content("~/"); returnUrl ??= Url.Content("~/");
if (remoteError != null) if (remoteError != null)
{ {
return NotifyOfError($"Error from external provider: {remoteError}"); return NotifyOfError($"外部提供程序出错: {remoteError}");
} }
var info = await SignInManager.GetExternalLoginInfoAsync(); var info = await SignInManager.GetExternalLoginInfoAsync();
if (info == null) if (info == null)
{ {
return NotifyOfError($"Failed to get information from external provider"); return NotifyOfError($"无法从外部提供程序获取信息");
} }
var user = await UserManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey); var user = await UserManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey);
@@ -83,7 +83,7 @@ namespace TightWiki.Controllers
var email = info.Principal.FindFirstValue(ClaimTypes.Email).EnsureNotNull(); var email = info.Principal.FindFirstValue(ClaimTypes.Email).EnsureNotNull();
if (string.IsNullOrEmpty(email)) if (string.IsNullOrEmpty(email))
{ {
return NotifyOfError($"The email address was not supplied by the external provider."); return NotifyOfError($"电子邮件地址不是由外部提供商提供的.");
} }
user = await UserManager.FindByEmailAsync(email); user = await UserManager.FindByEmailAsync(email);

View File

@@ -81,23 +81,23 @@ namespace TightWiki.Controllers
case "Optimize": case "Optimize":
{ {
var resultText = SpannedRepository.OptimizeDatabase(database); var resultText = SpannedRepository.OptimizeDatabase(database);
return NotifyOfSuccess($"Optimization complete. {resultText}", model.YesRedirectURL); return NotifyOfSuccess($"操作成功 {resultText}", model.YesRedirectURL);
} }
case "Vacuum": case "Vacuum":
{ {
var resultText = SpannedRepository.OptimizeDatabase(database); var resultText = SpannedRepository.OptimizeDatabase(database);
return NotifyOfSuccess($"Vacuum complete. {resultText}", model.YesRedirectURL); return NotifyOfSuccess($"操作成功 {resultText}", model.YesRedirectURL);
} }
case "Verify": case "Verify":
{ {
var resultText = SpannedRepository.OptimizeDatabase(database); var resultText = SpannedRepository.OptimizeDatabase(database);
return NotifyOfSuccess($"Verification complete. {resultText}", model.YesRedirectURL); return NotifyOfSuccess($"验证完成 {resultText}", model.YesRedirectURL);
} }
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
return NotifyOfError($"Operation failed: {ex.Message}.", model.YesRedirectURL); return NotifyOfError($"操作失败: {ex.Message}.", model.YesRedirectURL);
} }
return NotifyOfError($"Unknown database action: '{databaseAction}'.", model.YesRedirectURL); return NotifyOfError($"Unknown database action: '{databaseAction}'.", model.YesRedirectURL);
@@ -138,7 +138,7 @@ namespace TightWiki.Controllers
if (model.UserSelection == true) if (model.UserSelection == true)
{ {
StatisticsRepository.PurgeCompilationStatistics(); StatisticsRepository.PurgeCompilationStatistics();
return NotifyOfSuccess("Compilation statistics purged.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -153,7 +153,7 @@ namespace TightWiki.Controllers
if (model.UserSelection == true) if (model.UserSelection == true)
{ {
WikiCache.Clear(); WikiCache.Clear();
return NotifyOfSuccess("Memory cache purged.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -367,12 +367,12 @@ namespace TightWiki.Controllers
int currentPageRevision = PageRepository.GetCurrentPageRevision(page.Id); int currentPageRevision = PageRepository.GetCurrentPageRevision(page.Id);
if (revision >= currentPageRevision) if (revision >= currentPageRevision)
{ {
return NotifyOfError("You cannot revert to the current page revision."); return NotifyOfError("操作失败");
} }
Engine.Implementation.Helpers.UpsertPage(tightEngine, page, SessionState); Engine.Implementation.Helpers.UpsertPage(tightEngine, page, SessionState);
return NotifyOfSuccess("The page has been reverted.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -396,7 +396,7 @@ namespace TightWiki.Controllers
var page = PageRepository.GetLimitedPageInfoByIdAndRevision(pageId); var page = PageRepository.GetLimitedPageInfoByIdAndRevision(pageId);
if (page == null) if (page == null)
{ {
return NotifyOfError("The specified page could not be found."); return NotifyOfError("找不到指定页面");
} }
model.Name = page.Name; model.Name = page.Name;
@@ -489,13 +489,13 @@ namespace TightWiki.Controllers
var page = PageRepository.GetPageInfoByNavigation(pageNavigation); var page = PageRepository.GetPageInfoByNavigation(pageNavigation);
if (page == null) if (page == null)
{ {
return NotifyOfError("The page could not be found."); return NotifyOfError("无法找到指定页面");
} }
int revisionCount = PageRepository.GetPageRevisionCountByPageId(page.Id); int revisionCount = PageRepository.GetPageRevisionCountByPageId(page.Id);
if (revisionCount <= 1) if (revisionCount <= 1)
{ {
return NotifyOfError("You cannot delete the only existing revision of a page, instead you would need to delete the entire page."); return NotifyOfError("唯一修订无法删除");
} }
//If we are deleting the latest revision, then we need to grab the previous //If we are deleting the latest revision, then we need to grab the previous
@@ -509,7 +509,7 @@ namespace TightWiki.Controllers
PageRepository.MovePageRevisionToDeletedById(page.Id, revision, SessionState.Profile.EnsureNotNull().UserId); PageRepository.MovePageRevisionToDeletedById(page.Id, revision, SessionState.Profile.EnsureNotNull().UserId);
return NotifyOfSuccess("Page revision has been moved to the deletion queue.", model.YesRedirectURL); return NotifyOfSuccess("操作成功页面修订已移至删除队列", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -575,7 +575,7 @@ namespace TightWiki.Controllers
{ {
Engine.Implementation.Helpers.RefreshPageMetadata(tightEngine, page, SessionState); Engine.Implementation.Helpers.RefreshPageMetadata(tightEngine, page, SessionState);
} }
return NotifyOfSuccess("All pages have been rebuilt.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -621,7 +621,7 @@ namespace TightWiki.Controllers
workload.WaitForCompletion(); workload.WaitForCompletion();
return NotifyOfSuccess("All pages have been cached.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -637,7 +637,7 @@ namespace TightWiki.Controllers
{ {
PageRepository.TruncateAllPageRevisions("YES"); PageRepository.TruncateAllPageRevisions("YES");
WikiCache.Clear(); WikiCache.Clear();
return NotifyOfSuccess("All page revisions have been truncated.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -652,7 +652,7 @@ namespace TightWiki.Controllers
if (model.UserSelection == true) if (model.UserSelection == true)
{ {
PageRepository.PurgeDeletedPageRevisionsByPageId(pageId); PageRepository.PurgeDeletedPageRevisionsByPageId(pageId);
return NotifyOfSuccess("The page deletion queue has been purged.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -667,7 +667,7 @@ namespace TightWiki.Controllers
if (model.UserSelection == true) if (model.UserSelection == true)
{ {
PageRepository.PurgeDeletedPageRevisionByPageIdAndRevision(pageId, revision); PageRepository.PurgeDeletedPageRevisionByPageIdAndRevision(pageId, revision);
return NotifyOfSuccess("The page revision has been purged from the deletion queue.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -682,7 +682,7 @@ namespace TightWiki.Controllers
if (model.UserSelection == true) if (model.UserSelection == true)
{ {
PageRepository.RestoreDeletedPageRevisionByPageIdAndRevision(pageId, revision); PageRepository.RestoreDeletedPageRevisionByPageIdAndRevision(pageId, revision);
return NotifyOfSuccess("The page revision has been restored.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -697,7 +697,7 @@ namespace TightWiki.Controllers
if (model.UserSelection == true) if (model.UserSelection == true)
{ {
PageRepository.PurgeDeletedPages(); PageRepository.PurgeDeletedPages();
return NotifyOfSuccess("The page deletion queue has been purged.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -712,7 +712,7 @@ namespace TightWiki.Controllers
if (model.UserSelection == true) if (model.UserSelection == true)
{ {
PageRepository.PurgeDeletedPageByPageId(pageId); PageRepository.PurgeDeletedPageByPageId(pageId);
return NotifyOfSuccess("The page has been purged from the deletion queue.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -727,7 +727,7 @@ namespace TightWiki.Controllers
if (model.UserSelection == true) if (model.UserSelection == true)
{ {
PageRepository.MovePageToDeletedById(pageId, SessionState.Profile.EnsureNotNull().UserId); PageRepository.MovePageToDeletedById(pageId, SessionState.Profile.EnsureNotNull().UserId);
return NotifyOfSuccess("The page has been moved to the deletion queue.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -747,7 +747,7 @@ namespace TightWiki.Controllers
{ {
Engine.Implementation.Helpers.RefreshPageMetadata(tightEngine, page, SessionState); Engine.Implementation.Helpers.RefreshPageMetadata(tightEngine, page, SessionState);
} }
return NotifyOfSuccess("The page has restored.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -798,7 +798,7 @@ namespace TightWiki.Controllers
if (model.UserSelection == true) if (model.UserSelection == true)
{ {
PageFileRepository.PurgeOrphanedPageAttachments(); PageFileRepository.PurgeOrphanedPageAttachments();
return NotifyOfSuccess("All orphaned page attachments have been purged.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -814,7 +814,7 @@ namespace TightWiki.Controllers
if (model.UserSelection == true) if (model.UserSelection == true)
{ {
PageFileRepository.PurgeOrphanedPageAttachment(pageFileId, revision); PageFileRepository.PurgeOrphanedPageAttachment(pageFileId, revision);
return NotifyOfSuccess("The pages orphaned attachments have been purged.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");
@@ -883,7 +883,7 @@ namespace TightWiki.Controllers
if (ConfigurationRepository.GetAllMenuItems().Where(o => o.Name.Equals(model.Name, StringComparison.InvariantCultureIgnoreCase) && o.Id != model.Id).Any()) if (ConfigurationRepository.GetAllMenuItems().Where(o => o.Name.Equals(model.Name, StringComparison.InvariantCultureIgnoreCase) && o.Id != model.Id).Any())
{ {
ModelState.AddModelError("Name", $"The menu name '{model.Name}' is already in use."); ModelState.AddModelError("Name", $"菜单名 '{model.Name}' 已被使用");
return View(model); return View(model);
} }
@@ -892,14 +892,14 @@ namespace TightWiki.Controllers
model.Id = ConfigurationRepository.InsertMenuItem(model.ToDataModel()); model.Id = ConfigurationRepository.InsertMenuItem(model.ToDataModel());
ModelState.Clear(); ModelState.Clear();
return NotifyOfSuccess("The menu item has been created.", $"/Admin/MenuItem/{model.Id}"); return NotifyOfSuccess("创建成功", $"/Admin/MenuItem/{model.Id}");
} }
else else
{ {
ConfigurationRepository.UpdateMenuItemById(model.ToDataModel()); ConfigurationRepository.UpdateMenuItemById(model.ToDataModel());
} }
model.SuccessMessage = "The menu item has been saved."; model.SuccessMessage = "操作成功!";
return View(model); return View(model);
} }
@@ -926,7 +926,7 @@ namespace TightWiki.Controllers
{ {
ConfigurationRepository.DeleteMenuItemById(model.Id); ConfigurationRepository.DeleteMenuItemById(model.Id);
return NotifyOfSuccess("The menu item has been deleted.", $"/Admin/MenuItems"); return NotifyOfSuccess("删除成功", $"/Admin/MenuItems");
} }
return Redirect($"{GlobalConfiguration.BasePath}/Admin/MenuItem/{model.Id}"); return Redirect($"{GlobalConfiguration.BasePath}/Admin/MenuItem/{model.Id}");
@@ -1057,7 +1057,7 @@ namespace TightWiki.Controllers
{ {
if (UsersRepository.DoesProfileAccountExist(model.AccountProfile.AccountName)) if (UsersRepository.DoesProfileAccountExist(model.AccountProfile.AccountName))
{ {
ModelState.AddModelError("AccountProfile.AccountName", "Account name is already in use."); ModelState.AddModelError("AccountProfile.AccountName", "用户名已经被使用");
return View(model); return View(model);
} }
} }
@@ -1066,7 +1066,7 @@ namespace TightWiki.Controllers
{ {
if (UsersRepository.DoesEmailAddressExist(model.AccountProfile.EmailAddress)) if (UsersRepository.DoesEmailAddressExist(model.AccountProfile.EmailAddress))
{ {
ModelState.AddModelError("AccountProfile.EmailAddress", "Email address is already in use."); ModelState.AddModelError("AccountProfile.EmailAddress", "该邮箱已经存在");
return View(model); return View(model);
} }
} }
@@ -1076,11 +1076,11 @@ namespace TightWiki.Controllers
{ {
if (GlobalConfiguration.AllowableImageTypes.Contains(file.ContentType.ToLower()) == false) if (GlobalConfiguration.AllowableImageTypes.Contains(file.ContentType.ToLower()) == false)
{ {
model.ErrorMessage += "Could not save the attached image, type not allowed.\r\n"; model.ErrorMessage += "无法保存附件图片, 不允许的格式.\r\n";
} }
else if (file.Length > GlobalConfiguration.MaxAvatarFileSize) else if (file.Length > GlobalConfiguration.MaxAvatarFileSize)
{ {
model.ErrorMessage += "Could not save the attached image, too large.\r\n"; model.ErrorMessage += "无法保存附件图片, 图片过大.\r\n";
} }
else else
{ {
@@ -1092,7 +1092,7 @@ namespace TightWiki.Controllers
} }
catch catch
{ {
model.ErrorMessage += "Could not save the attached image.\r\n"; model.ErrorMessage += "无法保存附件图片.\r\n";
} }
} }
} }
@@ -1167,7 +1167,7 @@ namespace TightWiki.Controllers
} }
} }
model.SuccessMessage = "Your profile has been saved successfully!"; model.SuccessMessage = "操作成功!";
return View(model); return View(model);
} }
@@ -1228,19 +1228,19 @@ namespace TightWiki.Controllers
if (string.IsNullOrWhiteSpace(model.AccountProfile.AccountName)) if (string.IsNullOrWhiteSpace(model.AccountProfile.AccountName))
{ {
ModelState.AddModelError("AccountProfile.AccountName", "Account name is required."); ModelState.AddModelError("AccountProfile.AccountName", "用户名为必填项");
return View(model); return View(model);
} }
if (UsersRepository.DoesProfileAccountExist(model.AccountProfile.AccountName)) if (UsersRepository.DoesProfileAccountExist(model.AccountProfile.AccountName))
{ {
ModelState.AddModelError("AccountProfile.AccountName", "Account name is already in use."); ModelState.AddModelError("AccountProfile.AccountName", "用户名已经在使用");
return View(model); return View(model);
} }
if (UsersRepository.DoesEmailAddressExist(model.AccountProfile.EmailAddress)) if (UsersRepository.DoesEmailAddressExist(model.AccountProfile.EmailAddress))
{ {
ModelState.AddModelError("AccountProfile.EmailAddress", "Email address is already in use."); ModelState.AddModelError("AccountProfile.EmailAddress", "邮箱已经被使用");
return View(model); return View(model);
} }
@@ -1298,11 +1298,11 @@ namespace TightWiki.Controllers
{ {
if (GlobalConfiguration.AllowableImageTypes.Contains(file.ContentType.ToLower()) == false) if (GlobalConfiguration.AllowableImageTypes.Contains(file.ContentType.ToLower()) == false)
{ {
model.ErrorMessage += "Could not save the attached image, type not allowed.\r\n"; model.ErrorMessage += "无法保存附件图片, 不支持的格式.\r\n";
} }
else if (file.Length > GlobalConfiguration.MaxAvatarFileSize) else if (file.Length > GlobalConfiguration.MaxAvatarFileSize)
{ {
model.ErrorMessage += "Could not save the attached image, too large.\r\n"; model.ErrorMessage += "无法保存附件图片, 图片过大.\r\n";
} }
else else
{ {
@@ -1314,12 +1314,12 @@ namespace TightWiki.Controllers
} }
catch catch
{ {
model.ErrorMessage += "Could not save the attached image."; model.ErrorMessage += "无法保存附件图片.";
} }
} }
} }
return NotifyOf("The account has been created.", model.ErrorMessage, $"/Admin/Account/{profile.Navigation}"); return NotifyOf("创建成功", model.ErrorMessage, $"/Admin/Account/{profile.Navigation}");
} }
[Authorize] [Authorize]
@@ -1367,7 +1367,7 @@ namespace TightWiki.Controllers
var user = UserManager.FindByIdAsync(profile.UserId.ToString()).Result; var user = UserManager.FindByIdAsync(profile.UserId.ToString()).Result;
if (user == null) if (user == null)
{ {
return NotFound("User not found."); return NotFound("404 404 404");
} }
var result = UserManager.DeleteAsync(user).Result; var result = UserManager.DeleteAsync(user).Result;
@@ -1384,10 +1384,10 @@ namespace TightWiki.Controllers
//We're deleting our own account. Oh boy... //We're deleting our own account. Oh boy...
SignInManager.SignOutAsync(); SignInManager.SignOutAsync();
return NotifyOfSuccess("Your account has been deleted.", $"/Profile/Deleted"); return NotifyOfSuccess("操作成功", $"/Profile/Deleted");
} }
return NotifyOfSuccess("The account has been deleted.", $"/Admin/Accounts"); return NotifyOfSuccess("操作成功", $"/Admin/Accounts");
} }
return Redirect($"{GlobalConfiguration.BasePath}/Admin/Account/{navigation}"); return Redirect($"{GlobalConfiguration.BasePath}/Admin/Account/{navigation}");
@@ -1498,7 +1498,7 @@ namespace TightWiki.Controllers
WikiCache.ClearCategory(WikiCache.Category.Configuration); WikiCache.ClearCategory(WikiCache.Category.Configuration);
model.SuccessMessage = "The configuration has been saved successfully!"; model.SuccessMessage = "操作成功!";
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -1577,7 +1577,7 @@ namespace TightWiki.Controllers
var checkName = EmojiRepository.GetEmojiByName(model.Emoji.Name.ToLowerInvariant()); var checkName = EmojiRepository.GetEmojiByName(model.Emoji.Name.ToLowerInvariant());
if (checkName != null) if (checkName != null)
{ {
ModelState.AddModelError("Emoji.Name", "Emoji name is already in use."); ModelState.AddModelError("Emoji.Name", "Emoji名称已经被使用");
return View(model); return View(model);
} }
} }
@@ -1594,7 +1594,7 @@ namespace TightWiki.Controllers
{ {
if (file.Length > GlobalConfiguration.MaxEmojiFileSize) if (file.Length > GlobalConfiguration.MaxEmojiFileSize)
{ {
model.ErrorMessage += "Could not save the attached image, too large."; model.ErrorMessage += "无法保存附件图片, 图片过大.";
} }
else else
{ {
@@ -1606,14 +1606,14 @@ namespace TightWiki.Controllers
} }
catch catch
{ {
model.ErrorMessage += "Could not save the attached image."; model.ErrorMessage += "无法保存附件图片.";
} }
} }
} }
emoji.Id = EmojiRepository.UpsertEmoji(emoji); emoji.Id = EmojiRepository.UpsertEmoji(emoji);
model.OriginalName = model.Emoji.Name; model.OriginalName = model.Emoji.Name;
model.SuccessMessage = "The emoji has been saved successfully!"; model.SuccessMessage = "操作成功!";
model.Emoji.Id = (int)emoji.Id; model.Emoji.Id = (int)emoji.Id;
ModelState.Clear(); ModelState.Clear();
@@ -1621,7 +1621,7 @@ namespace TightWiki.Controllers
if (nameChanged) if (nameChanged)
{ {
return NotifyOfSuccess("The emoji has been saved.", $"/Admin/Emoji/{Navigation.Clean(emoji.Name)}"); return NotifyOfSuccess("操作成功", $"/Admin/Emoji/{Navigation.Clean(emoji.Name)}");
} }
return View(model); return View(model);
@@ -1664,7 +1664,7 @@ namespace TightWiki.Controllers
var checkName = EmojiRepository.GetEmojiByName(model.Name.ToLower()); var checkName = EmojiRepository.GetEmojiByName(model.Name.ToLower());
if (checkName != null) if (checkName != null)
{ {
ModelState.AddModelError("Name", "Emoji name is already in use."); ModelState.AddModelError("Name", "Emoji名已经存在");
return View(model); return View(model);
} }
} }
@@ -1681,7 +1681,7 @@ namespace TightWiki.Controllers
{ {
if (file.Length > GlobalConfiguration.MaxEmojiFileSize) if (file.Length > GlobalConfiguration.MaxEmojiFileSize)
{ {
ModelState.AddModelError("Name", "Could not save the attached image, too large."); ModelState.AddModelError("Name", "无法保存附件图片, 图片过大.");
} }
else else
{ {
@@ -1693,14 +1693,14 @@ namespace TightWiki.Controllers
} }
catch catch
{ {
ModelState.AddModelError("Name", "Could not save the attached image."); ModelState.AddModelError("Name", "无法保存附件图片.");
} }
} }
} }
EmojiRepository.UpsertEmoji(emoji); EmojiRepository.UpsertEmoji(emoji);
return NotifyOfSuccess("The emoji has been created.", $"/Admin/Emoji/{Navigation.Clean(emoji.Name)}"); return NotifyOfSuccess("操作成功", $"/Admin/Emoji/{Navigation.Clean(emoji.Name)}");
} }
[Authorize] [Authorize]
@@ -1716,7 +1716,7 @@ namespace TightWiki.Controllers
{ {
EmojiRepository.DeleteById(emoji.Id); EmojiRepository.DeleteById(emoji.Id);
return NotifyOfSuccess("The emoji has been deleted.", $"/Admin/Emojis"); return NotifyOfSuccess("操作成功", $"/Admin/Emojis");
} }
return Redirect($"{GlobalConfiguration.BasePath}/Admin/Emoji/{name}"); return Redirect($"{GlobalConfiguration.BasePath}/Admin/Emoji/{name}");
@@ -1793,7 +1793,7 @@ namespace TightWiki.Controllers
if (model.UserSelection == true) if (model.UserSelection == true)
{ {
ExceptionRepository.PurgeExceptions(); ExceptionRepository.PurgeExceptions();
return NotifyOfSuccess("All exceptions have been purged.", model.YesRedirectURL); return NotifyOfSuccess("操作成功", model.YesRedirectURL);
} }
return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}"); return Redirect($"{GlobalConfiguration.BasePath}{model.NoRedirectURL}");

View File

@@ -19,7 +19,7 @@ namespace TightWiki.Controllers
: WikiControllerBase(signInManager, userManager) : WikiControllerBase(signInManager, userManager)
{ {
/// <summary> /// <summary>
/// Gets an image attached to a page. /// 获取附加到页面的图像
/// </summary> /// </summary>
/// <param name="givenPageNavigation">The navigation link of the page.</param> /// <param name="givenPageNavigation">The navigation link of the page.</param>
/// <param name="givenFileNavigation">The navigation link of the file.</param> /// <param name="givenFileNavigation">The navigation link of the file.</param>
@@ -97,7 +97,7 @@ namespace TightWiki.Controllers
} }
else else
{ {
return NotFound($"[{fileNavigation}] was not found on the page [{pageNavigation}]."); return NotFound($"[{fileNavigation}] 无法在页面 [{pageNavigation}] 中找到.");
} }
} }
@@ -176,7 +176,7 @@ namespace TightWiki.Controllers
} }
else else
{ {
return NotFound($"[{fileNavigation}] was not found on the page [{pageNavigation}]."); return NotFound($"[{fileNavigation}] 无法在页面 [{pageNavigation}] 中找到.");
} }
} }
@@ -205,7 +205,7 @@ namespace TightWiki.Controllers
else else
{ {
HttpContext.Response.StatusCode = 404; HttpContext.Response.StatusCode = 404;
return NotFound($"[{fileNavigation}] was not found on the page [{pageNavigation}]."); return NotFound($"[{fileNavigation}] 无法在页面 [ {pageNavigation} ] 中找到.");
} }
} }
@@ -288,7 +288,7 @@ namespace TightWiki.Controllers
{ {
if (fileSize > GlobalConfiguration.MaxAttachmentFileSize) if (fileSize > GlobalConfiguration.MaxAttachmentFileSize)
{ {
return Json(new { message = $"Could not attach file: [{file.FileName}], too large." }); return Json(new { message = $"无法保存文件: [{file.FileName}], 文件过大." });
} }
var fileName = HttpUtility.UrlDecode(file.FileName); var fileName = HttpUtility.UrlDecode(file.FileName);
@@ -310,8 +310,8 @@ namespace TightWiki.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
ExceptionRepository.InsertException(ex, "Failed to upload file."); ExceptionRepository.InsertException(ex, "文件上传失败.");
return StatusCode(500, new { success = false, message = $"An error occurred: {ex.Message}" }); return StatusCode(500, new { success = false, message = $"Error: {ex.Message}" });
} }
} }
@@ -337,7 +337,7 @@ namespace TightWiki.Controllers
{ {
if (fileSize > GlobalConfiguration.MaxAttachmentFileSize) if (fileSize > GlobalConfiguration.MaxAttachmentFileSize)
{ {
return Content("Could not save the attached file, too large"); return Content("附件无法保存, 文件过大");
} }
var fileName = HttpUtility.UrlDecode(fileData.FileName); var fileName = HttpUtility.UrlDecode(fileData.FileName);
@@ -353,11 +353,11 @@ namespace TightWiki.Controllers
ContentType = Utility.GetMimeType(fileName) ContentType = Utility.GetMimeType(fileName)
}, (SessionState.Profile?.UserId).EnsureNotNullOrEmpty()); }, (SessionState.Profile?.UserId).EnsureNotNullOrEmpty());
return Content("Success"); return Content("成功");
} }
} }
return Content("Failure"); return Content("失败");
} }
/// <summary> /// <summary>
@@ -415,7 +415,7 @@ namespace TightWiki.Controllers
if (emoji.ImageData == null) if (emoji.ImageData == null)
{ {
return NotFound($"Emoji {pageNavigation} was not found"); return NotFound($"Emoji {pageNavigation} 无法找到");
} }
WikiCache.Put(imageCacheKey, emoji.ImageData); WikiCache.Put(imageCacheKey, emoji.ImageData);
@@ -475,7 +475,7 @@ namespace TightWiki.Controllers
} }
} }
return NotFound($"Emoji {pageNavigation} was not found"); return NotFound($"Emoji {pageNavigation} 无法找到");
} }
} }
} }

View File

@@ -640,7 +640,7 @@ namespace TightWiki.Controllers
SessionState.SetPageId(page.Id); SessionState.SetPageId(page.Id);
model.SuccessMessage = "The page was saved."; model.SuccessMessage = "保存成功";
if (string.IsNullOrWhiteSpace(originalNavigation) == false) if (string.IsNullOrWhiteSpace(originalNavigation) == false)
{ {
@@ -736,7 +736,7 @@ namespace TightWiki.Controllers
} }
else else
{ {
return NotFound($"[{fileNavigation}] was not found on the page [{pageNavigation}]."); return NotFound($"[{fileNavigation}] 无法在页面 [ {pageNavigation} ] 中找到.");
} }
} }
@@ -802,7 +802,7 @@ namespace TightWiki.Controllers
} }
else else
{ {
return NotFound($"[{fileNavigation}] was not found on the page [{pageNavigation}]."); return NotFound($"[{fileNavigation}] 无法在页面 [{pageNavigation}] 中找到.");
} }
} }
@@ -830,7 +830,7 @@ namespace TightWiki.Controllers
else else
{ {
HttpContext.Response.StatusCode = 404; HttpContext.Response.StatusCode = 404;
return NotFound($"[{fileNavigation}] was not found on the page [{pageNavigation}]."); return NotFound($"[{fileNavigation}] 无法在页面 [{pageNavigation}] 中找到.");
} }
} }

View File

@@ -347,7 +347,7 @@ namespace TightWiki.Controllers
WikiCache.ClearCategory(WikiCacheKey.Build(WikiCache.Category.User, [profile.Navigation])); WikiCache.ClearCategory(WikiCacheKey.Build(WikiCache.Category.User, [profile.Navigation]));
WikiCache.ClearCategory(WikiCacheKey.Build(WikiCache.Category.User, [profile.UserId])); WikiCache.ClearCategory(WikiCacheKey.Build(WikiCache.Category.User, [profile.UserId]));
model.SuccessMessage = "Your profile has been saved."; model.SuccessMessage = "保存成功";
//This is not 100% necessary, I just want to prevent the user from needing to refresh to view the new theme. //This is not 100% necessary, I just want to prevent the user from needing to refresh to view the new theme.
SessionState.UserTheme = ConfigurationRepository.GetAllThemes().SingleOrDefault(o => o.Name == model.AccountProfile.Theme) ?? GlobalConfiguration.SystemTheme; SessionState.UserTheme = ConfigurationRepository.GetAllThemes().SingleOrDefault(o => o.Name == model.AccountProfile.Theme) ?? GlobalConfiguration.SystemTheme;
@@ -378,7 +378,7 @@ namespace TightWiki.Controllers
var user = UserManager.FindByIdAsync(profile.UserId.ToString()).Result; var user = UserManager.FindByIdAsync(profile.UserId.ToString()).Result;
if (user == null) if (user == null)
{ {
return NotFound("User not found."); return NotFound("User 404 404 404.");
} }
var result = UserManager.DeleteAsync(user).Result; var result = UserManager.DeleteAsync(user).Result;

View File

@@ -5,4 +5,4 @@
} }
<h1>@ViewData["Title"]</h1> <h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p> <p>隐私政策.</p>

View File

@@ -16,9 +16,9 @@
} }
else else
{ {
<li class="nav-item"> @* <li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">注册</a> <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">注册</a>
</li> </li> *@
<li class="nav-item"> <li class="nav-item">
<a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">登录</a> <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">登录</a>
</li> </li>

View File

@@ -6,11 +6,11 @@
} }
<h3> <h3>
Account 账号
</h3> </h3>
<p> <p>
Configuration for user account.<br /><br /> 设置您的账号<br /><br />
</p> </p>

View File

@@ -45,8 +45,8 @@
<thead> <thead>
<tr> <tr>
<td><strong><a href="?@QueryStringConverter.OrderHelper(sessionState, "Account")">Account</a></strong></td> <td><strong><a href="?@QueryStringConverter.OrderHelper(sessionState, "Account")">Account</a></strong></td>
<td><strong><a href="?@QueryStringConverter.OrderHelper(sessionState, "FirstName")">First Name</a></strong></td>
<td><strong><a href="?@QueryStringConverter.OrderHelper(sessionState, "LastName")">Last Name</a></strong></td> <td><strong><a href="?@QueryStringConverter.OrderHelper(sessionState, "LastName")">Last Name</a></strong></td>
<td><strong><a href="?@QueryStringConverter.OrderHelper(sessionState, "FirstName")">First Name</a></strong></td>
<td><strong><a href="?@QueryStringConverter.OrderHelper(sessionState, "Country")">Country</a></strong></td> <td><strong><a href="?@QueryStringConverter.OrderHelper(sessionState, "Country")">Country</a></strong></td>
<td><strong><a href="?@QueryStringConverter.OrderHelper(sessionState, "TimeZone")">TimeZone</a></strong></td> <td><strong><a href="?@QueryStringConverter.OrderHelper(sessionState, "TimeZone")">TimeZone</a></strong></td>
<td><strong><a href="?@QueryStringConverter.OrderHelper(sessionState, "EmailAddress")">EmailAddress</a></strong></td> <td><strong><a href="?@QueryStringConverter.OrderHelper(sessionState, "EmailAddress")">EmailAddress</a></strong></td>

View File

@@ -6,7 +6,7 @@
} }
<h3> <h3>
Add Account 新增账号
</h3> </h3>
<p> <p>

View File

@@ -19,18 +19,18 @@
{ {
<div class="card border-danger mb-3"> <div class="card border-danger mb-3">
<div class="card-header bg-danger text-white"> <div class="card-header bg-danger text-white">
<strong>Delete account "@Model.AccountName"?</strong> <strong>删除账号 "@Model.AccountName"?</strong>
</div> </div>
<div class="card-body"> <div class="card-body">
Deleting "@Model.AccountName" will permanently remove the account. All pages created or modified by this user will be attributed to a stand-in account. 删除 "@Model.AccountName" 将永久删除该账户.该用户创建的页面将属于一个代理账户.
<strong>You will not be able to revert this action.</strong> <strong>您将无法恢复此操作.</strong>
<br /><br /> <br /><br />
Are you sure you want to continue with this deletion?<br /><br /> 您确定要继续此删除操作吗?<br /><br />
@using (Html.BeginForm(null, null, FormMethod.Post, new { action = $"{GlobalConfiguration.BasePath}{Context.Request.Path}" })) @using (Html.BeginForm(null, null, FormMethod.Post, new { action = $"{GlobalConfiguration.BasePath}{Context.Request.Path}" }))
{ {
<div class="form-group"><button type="submit" class="btn btn-danger rounded-0" name="IsActionConfirmed" value="true">Yes</button>&nbsp;&nbsp;<button type="submit" class="btn btn-success rounded-0" name="IsActionConfirmed" value="false">No</button></div> <div class="form-group"><button type="submit" class="btn btn-danger rounded-0" name="IsActionConfirmed" value="true"></button>&nbsp;&nbsp;<button type="submit" class="btn btn-success rounded-0" name="IsActionConfirmed" value="false"></button></div>
} }
</div> </div>
</div> </div>

View File

@@ -203,4 +203,6 @@
} }
<br /> <br />
<form action="@GlobalConfiguration.BasePath/Profile/Delete"><button type="submit" class="btn btn-danger rounded-0">Delete Account</button></form> <form action="@GlobalConfiguration.BasePath/Profile/Delete">
<button type="submit" class="btn btn-danger rounded-0">删除账号</button>
</form>

View File

@@ -207,7 +207,7 @@
<div class="collapse navbar-collapse justify-content-end"> <div class="collapse navbar-collapse justify-content-end">
<form class="d-flex" role="search" method="GET" action="@GlobalConfiguration.BasePath/Page/Search"> <form class="d-flex" role="search" method="GET" action="@GlobalConfiguration.BasePath/Page/Search">
<input class="form-control me-2" type="search" placeholder="搜索" name="SearchString" aria-label="Search"> <input class="form-control me-2" type="search" placeholder="搜索" name="SearchString" aria-label="Search">
<button class="btn btn-outline-primary" type="submit">search</button> <button class="btn btn-outline-primary" style="word-break:keep-all;" type="submit">搜索</button>
</form> </form>
</div> </div>
</li> </li>