fix language

This commit is contained in:
2025-12-05 02:13:05 +08:00
parent 00dd4fa958
commit ac50b3fccd
7 changed files with 206 additions and 54 deletions

View File

@@ -23,7 +23,7 @@ namespace Atomx.Admin.Client.Models
public string Title { get; set; } = string.Empty; public string Title { get; set; } = string.Empty;
/// <summary> /// <summary>
/// 语言名称 /// 语言文化
/// </summary> /// </summary>
public string Culture { get; set; } = string.Empty; public string Culture { get; set; } = string.Empty;

View File

@@ -1,5 +1,4 @@
@page "/admin/list" @page "/admin/list"
@using Atomx.Common.Constants
@inject ILogger<AdminList> Logger @inject ILogger<AdminList> Logger
@* @attribute [Authorize] *@ @* @attribute [Authorize] *@
@@ -41,10 +40,10 @@
<ColumnDefinitions> <ColumnDefinitions>
<PropertyColumn Property="c => c.Username" Title="帐号"> <PropertyColumn Property="c => c.Username" Title="帐号">
</PropertyColumn> </PropertyColumn>
<PropertyColumn Property="c => c.Email" Title="邮件" Width="80px" Align="ColumnAlign.Center"> <PropertyColumn Property="c => c.Email" Title="邮件">
</PropertyColumn> </PropertyColumn>
<PropertyColumn Property="c => c.Mobile" Title="手机号" Width="100px" /> <PropertyColumn Property="c => c.Mobile" Title="手机号" />
<PropertyColumn Property="c => c.Status" Title="状态" Width="80px" Align="ColumnAlign.Center"> <PropertyColumn Property="c => c.Status" Title="状态" Width="80px" Align="ColumnAlign.Center">
@if (context.Status == 1) @if (context.Status == 1)
{ {
@@ -56,8 +55,8 @@
<Icon Type="close" Theme="IconThemeType.Outline" Width="1.3em" Height="1.3em" /> <Icon Type="close" Theme="IconThemeType.Outline" Width="1.3em" Height="1.3em" />
} }
</PropertyColumn> </PropertyColumn>
<PropertyColumn Property="c => c.LastLogin" Title="最后登录" Width="190px" /> <PropertyColumn Property="c => c.LastLogin" Title="最后登录" Width="120px" />
<PropertyColumn Property="c => c.UpdateTime" Title="最后更新" Width="190px" /> <PropertyColumn Property="c => c.UpdateTime" Title="最后更新" />
<ActionColumn Title="操作" Align="ColumnAlign.Right" Width="160px"> <ActionColumn Title="操作" Align="ColumnAlign.Right" Width="160px">
<Space> <Space>
<SpaceItem> <SpaceItem>
@@ -326,7 +325,7 @@
{ {
CloseDrawer(); CloseDrawer();
LoadList(); _= LoadList();
await ModalService.InfoAsync(new ConfirmOptions() { Title = "提示", Content = "数据提交成功!" }); await ModalService.InfoAsync(new ConfirmOptions() { Title = "提示", Content = "数据提交成功!" });
} }
else else

View File

@@ -16,12 +16,12 @@
</Flex> </Flex>
</TitleTemplate> </TitleTemplate>
<ColumnDefinitions> <ColumnDefinitions>
<PropertyColumn Property="c => c.Name" Title="帐号"> <PropertyColumn Property="c => c.Name" Title="语言名称">
</PropertyColumn> </PropertyColumn>
<PropertyColumn Property="c => c.Title" Title="邮件" Width="80px" Align="ColumnAlign.Center"> <PropertyColumn Property="c => c.Title" Title="语言标题">
</PropertyColumn> </PropertyColumn>
<PropertyColumn Property="c => c.Culture" Title="手机号" Width="100px" /> <PropertyColumn Property="c => c.Culture" Title="语言文化" Width="100px" />
<PropertyColumn Property="c => c.Enabled" Title="状态" Width="80px" Align="ColumnAlign.Center"> <PropertyColumn Property="c => c.Enabled" Title="状态" Width="80px" Align="ColumnAlign.Center">
@if (context.Enabled) @if (context.Enabled)
{ {
@@ -33,7 +33,7 @@
<Icon Type="close" Theme="IconThemeType.Outline" Width="1.3em" Height="1.3em" /> <Icon Type="close" Theme="IconThemeType.Outline" Width="1.3em" Height="1.3em" />
} }
</PropertyColumn> </PropertyColumn>
<PropertyColumn Property="c => c.ResourceVersion" Title="最后登录" Width="190px" /> <PropertyColumn Property="c => c.ResourceVersion" Title="资源版本" Width="190px" />
<PropertyColumn Property="c => c.UpdateTime" Title="最后更新" Width="190px" /> <PropertyColumn Property="c => c.UpdateTime" Title="最后更新" Width="190px" />
<ActionColumn Title="操作" Align="ColumnAlign.Right" Width="160px"> <ActionColumn Title="操作" Align="ColumnAlign.Right" Width="160px">
<Space> <Space>
@@ -69,22 +69,31 @@
</Table> </Table>
</Card> </Card>
<Drawer Closable="true" Width="520" Visible="drawerVisible" Title='(model.Id == 0 ? "新增帐号" : "编辑帐号")' OnClose="_ => CloseDrawer()"> <Drawer Closable="true" Width="520" Visible="drawerVisible" Title='(model.Id == 0 ? "新增语言" : "编辑语言")' OnClose="_ => CloseDrawer()">
<Form LabelColSpan="5" @ref="@editform" Model="@model" OnFinish="OnFormFinish"> <Form LabelColSpan="5" @ref="@editform" Model="@model" OnFinish="OnFormFinish">
<FluentValidationValidator /> <FluentValidationValidator />
<FormItem Label="语言标题">
<Input @bind-Value="model.Title" For="(()=>model.Title)" Placeholder="语言标题" />
</FormItem>
<FormItem Label="语言名称"> <FormItem Label="语言名称">
<Input @bind-Value="model.Name" For="(()=>model.Name)" Placeholder="语言名称" /> <Input @bind-Value="model.Name" For="(()=>model.Name)" Placeholder="语言名称" />
</FormItem> </FormItem>
<FormItem Label="语言标题"> <FormItem Label="语言文化">
<Input @bind-Value="model.Culture" For="(()=>model.Culture)" Placeholder="语言标题" /> <SimpleSelect @bind-Value="model.Culture" For="(()=>model.Culture)" Placeholder="语言文化">
<SelectOptions>
@foreach (var item in LanguageCultures)
{
<SimpleSelectOption Value="@item.Key" Label="@($"{item.Value} - {item.Key}")"></SimpleSelectOption>
}
</SelectOptions>
</SimpleSelect>
</FormItem> </FormItem>
<FormItem Label="手机号码"> <FormItem Label="显示排序">
<Input @bind-Value="model.FlagImage" For="(()=>model.FlagImage)" Placeholder="手机号码" /> <AntDesign.InputNumber @bind-Value="model.DisplayOrder" For="(()=>model.DisplayOrder)" Placeholder="显示排序" />
</FormItem> </FormItem>
<FormItem Label="可用状态">
@* <FormItem Label="可用状态">
<Checkbox T="bool" Label="启用" @bind-value="model.Enabled" Size="InputSize.Small" Class="ps-0" /> <Checkbox T="bool" Label="启用" @bind-value="model.Enabled" Size="InputSize.Small" Class="ps-0" />
</FormItem> *@ </FormItem>
<FormItem WrapperColOffset="4"> <FormItem WrapperColOffset="4">
<Button Type="ButtonType.Primary" HtmlType="submit" Style="width: 100%;">保存</Button> <Button Type="ButtonType.Primary" HtmlType="submit" Style="width: 100%;">保存</Button>
</FormItem> </FormItem>
@@ -105,6 +114,8 @@
LanguageModel model { get; set; } = new(); LanguageModel model { get; set; } = new();
Form<LanguageModel> editform = null!; Form<LanguageModel> editform = null!;
Dictionary<string, string> LanguageCultures = LanguageCulture.Descriptions.ToDictionary();
PagingList<Language> PagingList = new(); PagingList<Language> PagingList = new();
bool loading { get; set; } = true; bool loading { get; set; } = true;
@@ -117,13 +128,13 @@
protected override void OnParametersSet() protected override void OnParametersSet()
{ {
LoadList(); _ = LoadList();
base.OnParametersSet(); base.OnParametersSet();
} }
private async void LoadList() private async Task LoadList()
{ {
loading = true; loading = true;
@@ -169,7 +180,7 @@
void OnCreateClick() void OnCreateClick()
{ {
model = new(); model = new() { Culture = LanguageCulture.zhHans };
drawerVisible = true; drawerVisible = true;
} }
@@ -185,7 +196,7 @@
var apiResult = await HttpService.Post<ApiResult<string>>(url, new()); var apiResult = await HttpService.Post<ApiResult<string>>(url, new());
if (apiResult.Success) if (apiResult.Success)
{ {
LoadList(); _ = LoadList();
await ModalService.InfoAsync(new ConfirmOptions() { Title = "操作提示", Content = "删除数据成功" }); await ModalService.InfoAsync(new ConfirmOptions() { Title = "操作提示", Content = "删除数据成功" });
} }
else else
@@ -199,25 +210,23 @@
if (editform.Validate()) if (editform.Validate())
{ {
var result = new ApiResult<string>(); var url = $"api/language/save";
if (model.Id > 0) var result = await HttpService.Post<ApiResult<bool>>(url, model);
if (result.Success)
{ {
var url = $"api/language/edit"; if (result.Data)
result = await HttpService.Post<ApiResult<string>>(url, model); {
}
else CloseDrawer();
{ _ = LoadList();
var url = $"api/language/add"; await ModalService.InfoAsync(new ConfirmOptions() { Title = "提示", Content = "数据提交成功!" });
result = await HttpService.Post<ApiResult<string>>(url, model); }
else
{
await ModalService.ErrorAsync(new ConfirmOptions() { Title = "服务异常", Content = result.Message });
}
} }
if (result.Code == (int)ResultCode.Success)
{
CloseDrawer();
LoadList();
await ModalService.InfoAsync(new ConfirmOptions() { Title = "提示", Content = "数据提交成功!" });
}
else else
{ {
await ModalService.ErrorAsync(new ConfirmOptions() { Title = "服务异常", Content = result.Message }); await ModalService.ErrorAsync(new ConfirmOptions() { Title = "服务异常", Content = result.Message });

View File

@@ -1,6 +1,11 @@
@page "/system/locale/resource/list/{culture}" @page "/system/locale/resource/list/{Id:int}"
@inject ILogger<LocaleResourceList> Logger @inject ILogger<LocaleResourceList> Logger
<PageTitle>本地化语言资源</PageTitle>
<Spin Spinning="loading">
</Spin>
@code { @code {
[Parameter]
public long Id { get; set; }
bool loading = false;
} }

View File

@@ -7,7 +7,9 @@ namespace Atomx.Admin.Client.Validators
{ {
public LanguageModelValidator() public LanguageModelValidator()
{ {
RuleFor(p => p.Title).NotEmpty().WithMessage("请填写语言标题");
RuleFor(p => p.Name).NotEmpty().WithMessage("请填写语言名称"); RuleFor(p => p.Name).NotEmpty().WithMessage("请填写语言名称");
RuleFor(p => p.Culture).NotEmpty().WithMessage("请选择语言文化");
} }
} }
} }

View File

@@ -10,6 +10,7 @@ using Atomx.Utils.Models;
using MapsterMapper; using MapsterMapper;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace Atomx.Admin.Controllers namespace Atomx.Admin.Controllers
{ {
@@ -76,13 +77,13 @@ namespace Atomx.Admin.Controllers
/// <param name="size"></param> /// <param name="size"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost("search")] [HttpPost("search")]
public IActionResult LanguageList(LanguageSearch search, int page,int size = 20) public IActionResult LanguageList(LanguageSearch search, int page, int size = 20)
{ {
if (page < 1) if (page < 1)
{ {
page = 1; page = 1;
} }
var result = new Result<PagingList<Language>>(); var result = new ApiResult<PagingList<Language>>();
var list = new PagingList<Language>() { Index = page, Size = size }; var list = new PagingList<Language>() { Index = page, Size = size };
var query = from p in _dbContext.Languages var query = from p in _dbContext.Languages
select p; select p;
@@ -90,7 +91,7 @@ namespace Atomx.Admin.Controllers
list.Count = query.Count(); list.Count = query.Count();
list.Items = query.OrderByDescending(p => p.CreateTime).Skip((page - 1) * size).Take(size).ToList(); list.Items = query.OrderByDescending(p => p.CreateTime).Skip((page - 1) * size).Take(size).ToList();
result.Data = list; result = result.IsSuccess(list);
return new JsonResult(result); return new JsonResult(result);
} }
@@ -103,15 +104,16 @@ namespace Atomx.Admin.Controllers
[HttpGet("detail")] [HttpGet("detail")]
public IActionResult GetManufacturer(long id) public IActionResult GetManufacturer(long id)
{ {
var result = new Result<Language>(); var result = new ApiResult<Language>();
var data = _dbContext.Languages.SingleOrDefault(p => p.Id == id); var data = _dbContext.Languages.SingleOrDefault(p => p.Id == id);
if (data == null) if (data == null)
{ {
result = result.IsFail("数据不存在,请更换!");
return new JsonResult(result); return new JsonResult(result);
} }
result.Data = data; result = result.IsSuccess(data);
return new JsonResult(result); return new JsonResult(result);
} }
@@ -125,22 +127,32 @@ namespace Atomx.Admin.Controllers
[HttpPost("save")] [HttpPost("save")]
public async Task<IActionResult> LanguageEdit(LanguageModel model) public async Task<IActionResult> LanguageEdit(LanguageModel model)
{ {
var result = new Result<bool>(); var result = new ApiResult<bool>();
var validator = new LanguageModelValidator(); var validator = new LanguageModelValidator();
var validation = validator.Validate(model); var validation = validator.Validate(model);
if (!validation.IsValid) if (!validation.IsValid)
{ {
result.Message = ModelState.Values.First().Errors[0].ErrorMessage; result = result.IsFail(ModelState.Values.First().Errors[0].ErrorMessage);
result.Success = false; return new JsonResult(result);
}
var data = _dbContext.Languages.SingleOrDefault(p => p.Name == model.Name && p.Id != model.Id);
if (data != null)
{
result = result.IsFail("语言名称已存在,请更换!");
return new JsonResult(result);
}
data = _dbContext.Languages.SingleOrDefault(p => p.Culture == model.Culture && p.Id != model.Id);
if (data != null)
{
result = result.IsFail("语言文化已存在,请更换!");
return new JsonResult(result); return new JsonResult(result);
} }
if (model.IsEdit) if (model.IsEdit)
{ {
var data = _dbContext.Languages.SingleOrDefault(p => p.Id == model.Id); data = _dbContext.Languages.SingleOrDefault(p => p.Id == model.Id);
if (data == null) if (data == null)
{ {
result.Message = "数据不存在,请更换!"; result = result.IsFail("数据不存在,请更换!");
result.Success = false;
return new JsonResult(result); return new JsonResult(result);
} }
@@ -151,16 +163,40 @@ namespace Atomx.Admin.Controllers
} }
else else
{ {
var data = _mapper.Map<Language>(model); data = _mapper.Map<Language>(model);
data.CreateTime = DateTime.UtcNow; data.CreateTime = DateTime.UtcNow;
_dbContext.Languages.Add(data); _dbContext.Languages.Add(data);
_dbContext.SaveChanges(); _dbContext.SaveChanges();
await _cacheService.GetLanguageById(model.Id, data); await _cacheService.GetLanguageById(model.Id, data);
} }
result.Data = true; result = result.IsSuccess(true);
return new JsonResult(result); return new JsonResult(result);
} }
/// <summary>
/// 删除指定ID的数据
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpPost("delete/{id:long}")]
public IActionResult Delete(long id)
{
var result = new ApiResult<string>();
try
{
Console.WriteLine($"{id} deleted");
var count = _dbContext.Languages.Where(p => p.Id == id).ExecuteDelete();
result = result.IsSuccess(count.ToString());
}
catch (Exception ex)
{
result = result.IsFail(ex.Message);
_logger.LogError(ex.Message);
}
return new JsonResult(result);
}
} }
} }

View File

@@ -0,0 +1,101 @@
namespace Atomx.Common.Constants
{
public class LanguageCulture
{
/// <summary>
/// 阿拉伯语言
/// </summary>
public const string arEG = "ar_EG";
/// <summary>
/// 德语
/// </summary>
public const string deDE = "de_DE";
/// <summary>
/// 英语
/// </summary>
public const string enGB = "en_GB";
/// <summary>
/// 朝鲜语/韩语
/// </summary>
public const string koKR = "ko_KR";
/// <summary>
/// 孟加拉语
/// </summary>
public const string bnBD = "bn_BD";
/// <summary>
/// 日语
/// </summary>
public const string jaJP = "ja_JP";
/// <summary>
/// 马来语/马来西亚
/// </summary>
public const string msMY = "ms_MY";
/// <summary>
/// 西班牙语
/// </summary>
public const string esES = "es_ES";
/// <summary>
/// 葡萄牙语
/// </summary>
public const string ptPT = "pt_PT";
/// <summary>
/// 乌尔都语 (巴基斯坦)
/// </summary>
public const string urPK = "ur_PK";
/// <summary>
/// 法语
/// </summary>
public const string frFR = "fr_FR";
/// <summary>
/// 印地语
/// </summary>
public const string hiIN = "hi_IN";
/// <summary>
/// 印尼语/印度尼西亚语
/// </summary>
public const string idID = "id_ID";
/// <summary>
/// 越南语
/// </summary>
public const string viVN = "vi_VN";
/// <summary>
/// 俄语
/// </summary>
public const string ruRU = "ru_RU";
/// <summary>
/// 简体中文
/// </summary>
public const string zhHans = "zh_Hans";
/// <summary>
/// 繁体中文
/// </summary>
public const string ZhHant = "Zh-Hant";
private static readonly Dictionary<string, string> LanguageCultureDescriptions = new()
{
{ arEG, "阿拉伯语" },
{ deDE, "德语" },
{ enGB, "英语" },
{ koKR, "朝鲜语/韩语" },
{ bnBD, "孟加拉语" },
{ jaJP, "日语" },
{ msMY, "马来语/马来西亚" },
{ esES, "西班牙语" },
{ ptPT, "葡萄牙语" },
{ urPK, "乌尔都语 (巴基斯坦)" },
{ frFR, "法语" },
{ hiIN, "印地语" },
{ idID, "印尼语/印度尼西亚语" },
{ viVN, "越南语" },
{ ruRU, "俄语" },
{ zhHans, "简体中文" },
{ ZhHant, "繁体中文" }
};
/// <summary>
/// 语言代码对应的中文描述(只读)
/// </summary>
public static IReadOnlyDictionary<string, string> Descriptions => LanguageCultureDescriptions;
}
}