initial
This commit is contained in:
249
src/DRS9.Dashboard.Server/Components/Pages/Applications.razor
Normal file
249
src/DRS9.Dashboard.Server/Components/Pages/Applications.razor
Normal file
@@ -0,0 +1,249 @@
|
||||
@page "/applications"
|
||||
@rendermode @(new InteractiveServerRenderMode())
|
||||
@inject Services.ApiClientService ApiClient
|
||||
@inject IJSRuntime JSRuntime
|
||||
|
||||
<PageTitle>内容管理 - DRS9 信息发布系统</PageTitle>
|
||||
|
||||
<h3 class="mb-4">内容管理</h3>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<span><i class="bi bi-grid"></i> 内容列表</span>
|
||||
<button class="btn btn-primary btn-sm" @onclick="ShowAddModal">
|
||||
<i class="bi bi-plus-lg"></i> 添加内容
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if (_applications == null)
|
||||
{
|
||||
<div class="text-center py-4">
|
||||
<div class="spinner-border text-primary" role="status"></div>
|
||||
</div>
|
||||
}
|
||||
else if (_applications.Count == 0)
|
||||
{
|
||||
<div class="text-center text-muted py-4">
|
||||
<i class="bi bi-inbox fs-1 d-block mb-3"></i>
|
||||
<p>暂无内容,点击上方按钮添加</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="row">
|
||||
@foreach (var app in _applications)
|
||||
{
|
||||
<div class="col-md-4 mb-3">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start">
|
||||
<div class="content-icon @GetAppTypeClass(app.Type)">
|
||||
<i class="bi @GetAppIcon(app.Type)"></i>
|
||||
</div>
|
||||
<div class="flex-grow-1">
|
||||
<h6 class="mb-1">@app.Name</h6>
|
||||
<p class="text-muted mb-2 small">@app.Type</p>
|
||||
<p class="mb-2 small">@app.Description</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer d-flex justify-content-end gap-2">
|
||||
<button class="btn btn-sm btn-outline-primary" @onclick="@(() => EditApp(app))">
|
||||
<i class="bi bi-pencil"></i> 编辑
|
||||
</button>
|
||||
<button class="btn btn-sm btn-outline-danger" @onclick="@(() => DeleteApp(app))">
|
||||
<i class="bi bi-trash"></i> 删除
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 添加/编辑 Modal -->
|
||||
@if (_showModal)
|
||||
{
|
||||
<div class="modal fade show d-block" style="background-color: rgba(0,0,0,0.5)" tabindex="-1" @onclick="CloseModal">
|
||||
<div class="modal-dialog" @onclick:stopPropagation="true">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(_editingApp?.Id == null ? "添加内容" : "编辑内容")</h5>
|
||||
<button type="button" class="btn-close" @onclick="CloseModal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@if (!string.IsNullOrEmpty(_errorMessage))
|
||||
{
|
||||
<div class="alert alert-danger" role="alert">
|
||||
@_errorMessage
|
||||
</div>
|
||||
}
|
||||
<div class="mb-3">
|
||||
<label class="form-label">内容名称</label>
|
||||
<input type="text" class="form-control" @bind="_appName" />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">内容类型</label>
|
||||
<select class="form-select" @bind="_appType" disabled="@(_editingApp != null)">
|
||||
<option value="">请选择...</option>
|
||||
<option value="Dashboard">Dashboard</option>
|
||||
<option value="WebRotator">WebRotator</option>
|
||||
<option value="Image">Image</option>
|
||||
<option value="Video">Video</option>
|
||||
</select>
|
||||
@if (_editingApp != null)
|
||||
{
|
||||
<small class="text-muted">内容类型创建后不可修改</small>
|
||||
}
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">内容 URL</label>
|
||||
<input type="url" class="form-control" @bind="_appContentUrl" placeholder="https://..." />
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">描述</label>
|
||||
<textarea class="form-control" @bind="_appDescription" rows="3"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" @onclick="CloseModal">取消</button>
|
||||
<button type="button" class="btn btn-primary" @onclick="SaveApp">保存</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
private List<ApplicationDto> _applications = new();
|
||||
private ApplicationDto? _editingApp;
|
||||
private string _appName = "";
|
||||
private string _appType = "";
|
||||
private string _appContentUrl = "";
|
||||
private string _appDescription = "";
|
||||
private bool _showModal = false;
|
||||
private string _errorMessage = "";
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_applications = await ApiClient.GetApplicationsAsync();
|
||||
}
|
||||
|
||||
private void ShowAddModal()
|
||||
{
|
||||
_editingApp = null;
|
||||
_appName = "";
|
||||
_appType = "";
|
||||
_appContentUrl = "";
|
||||
_appDescription = "";
|
||||
_errorMessage = "";
|
||||
_showModal = true;
|
||||
}
|
||||
|
||||
private void EditApp(ApplicationDto app)
|
||||
{
|
||||
_editingApp = app;
|
||||
_appName = app.Name;
|
||||
_appType = app.Type;
|
||||
_appContentUrl = app.ContentUrl;
|
||||
_appDescription = app.Description ?? "";
|
||||
_errorMessage = "";
|
||||
_showModal = true;
|
||||
}
|
||||
|
||||
private void CloseModal()
|
||||
{
|
||||
_showModal = false;
|
||||
_editingApp = null;
|
||||
_errorMessage = "";
|
||||
}
|
||||
|
||||
private async Task SaveApp()
|
||||
{
|
||||
// Validate inputs
|
||||
if (string.IsNullOrWhiteSpace(_appName))
|
||||
{
|
||||
_errorMessage = "请输入内容名称";
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(_appType))
|
||||
{
|
||||
_errorMessage = "请选择内容类型";
|
||||
return;
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(_appContentUrl))
|
||||
{
|
||||
_errorMessage = "请输入内容 URL";
|
||||
return;
|
||||
}
|
||||
|
||||
bool success;
|
||||
if (_editingApp == null)
|
||||
{
|
||||
success = await ApiClient.CreateApplicationAsync(new ApplicationCreateRequest
|
||||
{
|
||||
Name = _appName,
|
||||
Type = _appType,
|
||||
ContentUrl = _appContentUrl,
|
||||
Description = _appDescription
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
success = await ApiClient.UpdateApplicationAsync(_editingApp.Id, new ApplicationUpdateRequest
|
||||
{
|
||||
Name = _appName,
|
||||
Description = _appDescription,
|
||||
ContentUrl = _appContentUrl
|
||||
});
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
CloseModal();
|
||||
_applications = await ApiClient.GetApplicationsAsync();
|
||||
await JSRuntime.InvokeVoidAsync("alert", "保存成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
_errorMessage = "保存失败,请检查输入数据或稍后重试";
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteApp(ApplicationDto app)
|
||||
{
|
||||
if (await JSRuntime.InvokeAsync<bool>("confirm", $"确定要删除内容 '{app.Name}' 吗?"))
|
||||
{
|
||||
var success = await ApiClient.DeleteApplicationAsync(app.Id);
|
||||
if (success)
|
||||
{
|
||||
_applications = await ApiClient.GetApplicationsAsync();
|
||||
await JSRuntime.InvokeVoidAsync("alert", "删除成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("alert", "删除失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetAppTypeClass(string type) => type switch
|
||||
{
|
||||
"Dashboard" => "dashboard",
|
||||
"WebRotator" => "web",
|
||||
"Image" => "image",
|
||||
"Video" => "video",
|
||||
_ => ""
|
||||
};
|
||||
|
||||
private string GetAppIcon(string type) => type switch
|
||||
{
|
||||
"Dashboard" => "bi-bar-chart",
|
||||
"WebRotator" => "bi-arrow-repeat",
|
||||
"Image" => "bi-image",
|
||||
"Video" => "bi-play-circle",
|
||||
_ => "bi-file-earmark"
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user