using Grpc.Core;
|
using HotelPms.Client.Blazor.Dialog;
|
using HotelPms.Client.Blazor.Models;
|
using HotelPms.Client.Blazor.Util;
|
using HotelPms.Data.Common;
|
using HotelPms.Share.IO;
|
using HotelPms.Share.Util;
|
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components.Web;
|
using MudBlazor;
|
using System.Data;
|
using static HotelPms.Client.Blazor.Util.SystemEnum;
|
using static System.Net.Mime.MediaTypeNames;
|
|
namespace HotelPms.Client.Blazor.Pages.UseDetail;
|
|
public partial class RoomTypeInput : ComponentBase
|
{
|
#region ★★★★★ Parameter ★★★★★
|
|
[Parameter] public ViewModel.UseInput? Data { get; set; }
|
|
/// <summary>
|
/// 親Pageの再表示
|
/// </summary>
|
[Parameter] public Action OnRefresh { get; set; }
|
|
#endregion
|
|
#region ★★★★★ Declare ★★★★★
|
/// <summary>
|
/// 异步锁
|
/// ■ロック追加前
|
/// Leave⇒Start
|
/// Leave⇒Row:1 Col:0 enterPush:False, orgText:, text:1
|
/// 【10:07:06 046】SendAsync begin:10:07:06 046
|
/// 【10:07:06 047】SendAsync Url⇒/HotelPms.Data.GrpcTableCore/GetData
|
/// Enter⇒Row:0 Col:0 Text:1
|
/// 【10:07:06 095】SendAsync End:10:07:06 095
|
/// 該当部屋タイプが既に存在します。
|
/// Leave⇒End
|
///
|
/// ■追加後
|
/// Leave⇒Start
|
/// Leave⇒Row:1 Col:0 enterPush:False, text:1
|
/// 【10:26:02 811】SendAsync begin:10:26:02 811
|
/// 【10:26:02 811】SendAsync Url⇒/HotelPms.Data.GrpcTableCore/GetData
|
/// 【10:26:02 860】SendAsync End:10:26:02 860
|
/// 該当部屋タイプが既に存在します。
|
/// Leave⇒End
|
/// Enter⇒Row:0 Col:0
|
///
|
/// Semaphore(int initialCount, int maximumCount);
|
/// initialCount代表还分配几个线程,比如是1,那就是还能允许一个线程继续跑锁起来的代码
|
/// maximumCount代表最大允许数, 比如是1, 那就是进去1个线程, 就会锁起来
|
/// </summary>
|
private System.Threading.SemaphoreSlim slimlock = new SemaphoreSlim(1, 1);
|
|
private int selRow = 0;
|
private int selectedRowNumber = -1;
|
private MudTable<RoomTypeInputRow> mudRoomTypeInputTable;
|
|
private bool keyDownPreventDefault = false;
|
private bool keyPressPreventDefault = false;
|
private bool enterPush = false;
|
private bool arrowUpPush = false;
|
|
private EditGridFocusEventArgs m_CurrentFocusData = new EditGridFocusEventArgs();
|
|
#endregion
|
|
#region ★★★★★ Property ★★★★★
|
|
private RoomTypeInputRow m_SelRoomTypeInputRow = null;
|
|
/// <summary>
|
/// 選択されている行
|
/// </summary>
|
public RoomTypeInputRow SelRoomTypeInputRow
|
{
|
get { return m_SelRoomTypeInputRow; }
|
set
|
{
|
m_SelRoomTypeInputRow = value;
|
EnvironmentSetting.Debug($"Change:{m_SelRoomTypeInputRow.ID}");
|
}
|
}
|
|
#endregion
|
|
#region ★★★★★ Class Event ★★★★★
|
|
protected override void OnInitialized()
|
{
|
//EnvironmentSetting.Debug($"【{DateTime.Now.ToString("HH:mm:ss fff")}】RoomTypeInput.OnInitialized開始:");
|
base.OnInitialized();
|
}
|
|
protected override void OnAfterRender(bool firstRender)
|
{
|
//EnvironmentSetting.Debug($"【{DateTime.Now.ToString("HH:mm:ss fff")}】RoomTypeInput.OnAfterRender開始:{firstRender}");
|
base.OnAfterRender(firstRender);
|
}
|
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
{
|
await slimlock.WaitAsync();
|
EnvironmentSetting.Debug($"RoomTypeInput.OnAfterRenderAsync開始:{firstRender}");
|
await ShowFocus();
|
EnvironmentSetting.Debug($"RoomTypeInput.OnAfterRenderAsync終了:{firstRender}");
|
slimlock.Release();
|
}
|
|
protected override void OnParametersSet()
|
{
|
//EnvironmentSetting.Debug($"【{DateTime.Now.ToString("HH:mm:ss fff")}】RoomTypeInput.OnParametersSet開始:");
|
base.OnParametersSet();
|
}
|
|
protected override bool ShouldRender()
|
{
|
EnvironmentSetting.Debug($"RoomTypeInput.ShouldRender開始:");
|
return base.ShouldRender();
|
}
|
|
#endregion
|
|
#region ★★★★★ Control Event ★★★★★
|
|
private async Task Enter(int index, RoomTypeInputRow data, FocusEventArgs e)
|
{
|
await slimlock.WaitAsync();
|
int rowIdx = GetRowIndex(data);
|
Console.WriteLine($"Enter⇒Row:{rowIdx} Col:{index}");
|
slimlock.Release();
|
}
|
|
private async Task Leave(int index, RoomTypeInputRow data, FocusEventArgs e)
|
{
|
string text = string.Empty;
|
try
|
{
|
await slimlock.WaitAsync();
|
Console.WriteLine($"Leave⇒Start");
|
int rowIdx = GetRowIndex(data);
|
text = data.GetCellText(index);
|
Console.WriteLine($"Leave⇒Row:{rowIdx} Col:{index} enterPush:{enterPush}, text:{text}");
|
|
if (enterPush)
|
{
|
//Enterキーを押した時にも既にチェック済
|
enterPush = false;
|
}
|
else
|
{
|
//値変更したら、イベント発生
|
if (!data.IsValueChanged(index, text))
|
{
|
//必須判断:初期表示時:OrgTextは空白のため、値変更しないまま
|
return;
|
}
|
|
//通常チェックを行う
|
if (!await IsValid(index, text, data, false))
|
{
|
return;
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
OperationLog.Instance.WriteLog(ex.Message);
|
}
|
finally
|
{
|
//Refresh(); //UI更新(binding値変更通知)
|
Console.WriteLine($"Leave⇒End");
|
slimlock.Release();
|
}
|
}
|
|
/// <summary>
|
/// ※Backspaceここに来る
|
/// </summary>
|
/// <param name="index"></param>
|
/// <param name="data"></param>
|
/// <param name="e"></param>
|
/// <returns></returns>
|
private async Task KeyDown(int index, RoomTypeInputRow data, KeyboardEventArgs e)
|
{
|
if (e.Key == "ArrowUp")
|
{
|
try
|
{
|
EnvironmentSetting.Debug($"ArrowUp:{index}");
|
if (SetAutoNextFocus(index, false, data))
|
{
|
//BlazorのBugでEnterのパラメータ変数できない!
|
//Uncaught Error: System.ArgumentException: There is no event handler associated with this event. EventId: '290'. (Parameter 'eventHandlerId')
|
//mkArtakMSFT modified the milestones: Next sprint planning, 6.0-preview4 on 20 Mar ← Net6.0-preview4対応だそう
|
keyDownPreventDefault = true;
|
arrowUpPush = true;
|
}
|
else
|
{
|
keyDownPreventDefault = false;
|
arrowUpPush = false;
|
}
|
}
|
catch (Exception ex)
|
{
|
OperationLog.Instance.WriteLog($"KeyDown:{ex.Message}");
|
}
|
finally
|
{
|
Refresh("KeyDown⇒↑"); //UI更新(binding値変更通知)
|
}
|
}
|
else if (e.Key == "End")
|
{
|
if (data.Cells[index].ShowStyle == EShowStyle.ShowList)
|
{
|
data.ActiveCol = index;
|
if (index == (int)RoomTypeInputRow.ColType.ID)
|
{
|
using DataTable dt = await MasterCore.GetRoomTypeList();
|
var parameters = new DialogParameters { ["Data"] = dt };
|
var dialog = DialogService.Show<SelectList>($"部屋タイプ一覧", parameters);
|
var ret = await dialog.Result;
|
if (!ret.Cancelled)
|
{
|
var row = ret.Data as DataRow;
|
EnvironmentSetting.Debug(row[0].ToString());
|
data.Cells[index].Text = row[0].ToString();
|
data.Cells[(int)RoomTypeInputRow.ColType.Name].Text = row[1].ToString();
|
await KeyPress(index, data, new KeyboardEventArgs { Key = "Enter" });
|
//Refresh("KeyDown⇒End");
|
}
|
}
|
}
|
}
|
else if (e.Key == "Delete")
|
{
|
if (index == (int)RoomTypeInputRow.ColType.ID)
|
{
|
int rowIdx = GetRowIndex(data);
|
List<RoomTypeInputRow> list = (Data.RoomTypeList as List<RoomTypeInputRow>);
|
bool isLastRow = rowIdx == (list.Count - 1);
|
if (isLastRow) { return; }
|
SetFocus(rowIdx, (int)RoomTypeInputRow.ColType.ID);
|
EnvironmentSetting.Debug($"削除前件数:{list.Count}");
|
list.Remove(data);
|
EnvironmentSetting.Debug($"削除後件数:{list.Count}");
|
keyDownPreventDefault = false;
|
arrowUpPush = false;
|
}
|
}
|
else
|
{
|
keyDownPreventDefault = false;
|
arrowUpPush = false;
|
}
|
}
|
|
/// <summary>
|
/// ※Backspaceここに来ない
|
/// </summary>
|
/// <param name="index"></param>
|
/// <param name="data"></param>
|
/// <param name="e"></param>
|
/// <returns></returns>
|
private async Task KeyPress(int index, RoomTypeInputRow data, KeyboardEventArgs e)
|
{
|
if (e.Key == "Enter")
|
{
|
try
|
{
|
int rowIdx = GetRowIndex(data);
|
Console.WriteLine($"Row:{rowIdx} Col:{index}");
|
Console.WriteLine("Data:" + CConvert.ToJsonText<RoomTypeInputRow>(data));
|
|
//※その時、Fields[index].Textの値まだ変っていない!!!!!
|
string text = await data.GetInputValue(index, JSRuntime);
|
EnvironmentSetting.Debug($"Return:{index}⇒{text}");
|
keyPressPreventDefault = true; //イベント中止
|
enterPush = true; //Enterを押した知らせ
|
|
//値変更したら、イベント発生
|
if (data.IsValueChanged(index, text))
|
{
|
//通常チェックを行う
|
if (!await IsValid(index, text, data, true)) { return; }
|
}
|
else
|
{
|
//必須判断:初期表示時:OrgTextは空白のため、値変更しないまま
|
if (text.Trim().Length == 0)
|
{
|
//最終行となるはず
|
}
|
}
|
|
if (!SetAutoNextFocus(index, true, data)) { return; }
|
}
|
catch (Exception ex)
|
{
|
EnvironmentSetting.Debug(ex.Message);
|
}
|
finally
|
{
|
Refresh("KeyPress⇒Enter"); //UI更新(binding値変更通知)
|
}
|
}
|
else
|
{
|
if (CConvert.IsNumPress(e.Key))
|
{
|
keyPressPreventDefault = false;
|
}
|
else
|
{
|
keyPressPreventDefault = true; //入力禁止(※:IMEモードで入力したものをここでは通らないため、防げない)
|
}
|
enterPush = false;
|
}
|
}
|
|
#endregion
|
|
#region ★★★★★ Private Method ★★★★★
|
|
private RenderFragment RenderWidget(string msg) => builder =>
|
{
|
builder.OpenComponent(0, typeof(MessageContext));
|
builder.AddAttribute(1, "Text", msg);
|
builder.CloseComponent();
|
};
|
|
/// <summary>
|
/// フォーカス移動準備
|
/// </summary>
|
/// <param name="row"></param>
|
/// <param name="col"></param>
|
/// <param name="action">EditModeの場合、自動で次のフォーカス移動する</param>
|
private void SetFocus(int row, int col, EditGridFocusEventArgs.ActionType action = EditGridFocusEventArgs.ActionType.Focus)
|
{
|
EnvironmentSetting.Debug($"フォーカス移動準備:開始⇒Row:{row},Col:{col},Action:{action},Enabled:{m_CurrentFocusData.Enabled}");
|
m_CurrentFocusData.Row = row;
|
m_CurrentFocusData.Col = col;
|
m_CurrentFocusData.Action = action;
|
m_CurrentFocusData.Enabled = true;
|
EnvironmentSetting.Debug($"フォーカス移動準備:完了⇒Row:{row},Col:{col},Action:{action},Enabled:{m_CurrentFocusData.Enabled}");
|
}
|
|
/// <summary>
|
/// OnAfterRenderAsync時フォーカスを設定
|
/// </summary>
|
private async Task<bool> ShowFocus()
|
{
|
try
|
{
|
EnvironmentSetting.Debug($"SaleInput.FocusAsync行Before:Row={m_CurrentFocusData.Row},Col={m_CurrentFocusData.Col},Action={m_CurrentFocusData.Action},Enabled={m_CurrentFocusData.Enabled}");
|
if (!m_CurrentFocusData.Enabled)
|
{
|
EnvironmentSetting.Debug($"OnAfterRenderAsync⇒return false");
|
return false;
|
}
|
m_CurrentFocusData.Enabled = false;
|
|
EnvironmentSetting.Debug($"ShowFocus処理:Row={m_CurrentFocusData.Row},Col={m_CurrentFocusData.Col},Action={m_CurrentFocusData.Action},Enabled={m_CurrentFocusData.Enabled}");
|
if (m_CurrentFocusData.Action == EditGridFocusEventArgs.ActionType.Focus && m_CurrentFocusData.Row != -1 && m_CurrentFocusData.Col != -1)
|
{
|
//この時点Grid編集状態ですので、フォーカス可能になる
|
EnvironmentSetting.Debug($"フォーカスへ開始:Row = {m_CurrentFocusData.Row}, Col = {m_CurrentFocusData.Col}");
|
await (Data.RoomTypeList as List<RoomTypeInputRow>)[m_CurrentFocusData.Row].Cells[m_CurrentFocusData.Col].Ref.FocusAsync(); //ここに再度OnAfterRenderAsyncに入るが、EnabledはFalseのため、ShowFocusの動作がしない
|
EnvironmentSetting.Debug($"フォーカスへ完了:Row = {m_CurrentFocusData.Row}, Col = {m_CurrentFocusData.Col}");
|
}
|
return true;
|
}
|
catch (Exception ex)
|
{
|
EnvironmentSetting.Debug(ex.Message);
|
return false;
|
}
|
}
|
|
|
|
private int GetRowIndex(RoomTypeInputRow data)
|
{
|
return (Data.RoomTypeList as List<RoomTypeInputRow>).IndexOf(data);
|
}
|
|
/// <summary>
|
/// フォーカス移動
|
/// </summary>
|
/// <param name="index">列Index</param>
|
/// <param name="isEnter"></param>
|
/// <returns></returns>
|
private bool SetAutoNextFocus(int index, bool isEnter, RoomTypeInputRow data)
|
{
|
try
|
{
|
int rowIdx = GetRowIndex(data);
|
List<RoomTypeInputRow> list = (Data.RoomTypeList as List<RoomTypeInputRow>);
|
if (isEnter)
|
{
|
if (index == (int)RoomTypeInputRow.ColType.ID)
|
{
|
SetFocus(rowIdx, (int)RoomTypeInputRow.ColType.Count);
|
}
|
else
|
{
|
if (rowIdx == -1)
|
{
|
//削除された場合
|
//await list[list.Count - 1].RefID.FocusAsync();
|
}
|
else
|
{
|
if (rowIdx < (list.Count - 1))
|
{
|
SetFocus(rowIdx + 1, (int)RoomTypeInputRow.ColType.ID);
|
}
|
}
|
}
|
}
|
else
|
{
|
if (index == (int)RoomTypeInputRow.ColType.ID)
|
{
|
if (rowIdx > 0) { SetFocus(rowIdx - 1, (int)RoomTypeInputRow.ColType.Count); }
|
}
|
else
|
{
|
SetFocus(rowIdx, (int)RoomTypeInputRow.ColType.ID);
|
}
|
}
|
return true;
|
}
|
catch
|
{
|
return false;
|
}
|
}
|
|
/// <summary>
|
/// 入力されたIDが存在したかどうか
|
/// </summary>
|
/// <param name="rowIdx"></param>
|
/// <param name="id"></param>
|
/// <returns></returns>
|
private bool IsExistsID(int rowIdx, int id)
|
{
|
List<RoomTypeInputRow> list = (Data.RoomTypeList as List<RoomTypeInputRow>);
|
int i = 0;
|
foreach (RoomTypeInputRow row in list)
|
{
|
if (i == rowIdx) { continue; }
|
if (CConvert.ToInt(row.ID) == id)
|
{
|
return true;
|
}
|
i++;
|
}
|
return false;
|
}
|
|
/// <summary>
|
/// 業務チェック
|
/// </summary>
|
/// <param name="index"></param>
|
/// <param name="inputText"></param>
|
/// <param name="data"></param>
|
/// <param name="isEnter"></param>
|
/// <returns></returns>
|
private async Task<bool> IsValid(int index, string inputText, RoomTypeInputRow data, bool isEnter)
|
{
|
int rowIdx = GetRowIndex(data);
|
//最終行判断
|
List<RoomTypeInputRow> list = (Data.RoomTypeList as List<RoomTypeInputRow>);
|
bool isLastRow = rowIdx == (list.Count - 1);
|
|
if (index == (int)RoomTypeInputRow.ColType.ID)
|
{
|
int id = CConvert.ToInt(inputText);
|
RoomTypeBase typeBase = await MasterCore.GetRoomTypeBase(id);
|
if (typeBase == null)
|
{
|
if (isEnter)
|
{
|
Message.Show(RenderMessage("該当データが存在しません。"));
|
}
|
else
|
{
|
Console.WriteLine("該当データが存在しません。");
|
}
|
data.RestoreText(RoomTypeInputRow.ColType.ID);
|
return false;
|
}
|
|
if (IsExistsID(rowIdx, id))
|
{
|
if (isEnter)
|
{
|
Message.Show(RenderMessage("該当部屋タイプが既に存在します。"));
|
}
|
else
|
{
|
Console.WriteLine("該当部屋タイプが既に存在します。");
|
}
|
data.RestoreText(RoomTypeInputRow.ColType.ID);
|
return false;
|
}
|
data.SetCellText((int)RoomTypeInputRow.ColType.Name, typeBase.Name);
|
|
if (isLastRow)
|
{
|
//新規
|
data.SetCellText((int)RoomTypeInputRow.ColType.Count, "1");
|
|
//UseRoomを追加:当日
|
var useRoom = await Data.CreateUseRoom(id, typeBase.Kind);
|
data.DataList.Add(useRoom);
|
|
//一番したの新規行表示
|
list.Add(new RoomTypeInputRow());
|
}
|
else
|
{
|
//部屋タイプ変更(データ更新)
|
foreach (var item in data.DataList)
|
{
|
item.RoomTypeID = id;
|
item.RoomKind = typeBase.Kind;
|
}
|
|
//画面表示更新
|
data.SetCellText((int)RoomTypeInputRow.ColType.ID, id.ToString());
|
}
|
}
|
else if (index == (int)RoomTypeInputRow.ColType.Count)
|
{
|
if (isLastRow) { return false; }
|
//0の場合、完全に削除する
|
int orgCount = data.DataList.Count;
|
int newCount = CConvert.ToInt(inputText);
|
|
//UseRoomの±
|
int count = newCount - orgCount;
|
if (count > 0)
|
{
|
for (int i = 0; i < count; i++)
|
{
|
var useRoom = await Data.CreateUseRoom(data.DataList[0].RoomTypeID, data.DataList[0].RoomKind);
|
data.DataList.Add(useRoom);
|
}
|
}
|
else
|
{
|
Data.RemoveUseRoom(data.DataList, -count);
|
}
|
|
if (newCount == 0)
|
{
|
list.Remove(data);
|
if (rowIdx >= list.Count)
|
{
|
SetFocus(list.Count - 1, (int)RoomTypeInputRow.ColType.ID);
|
}
|
else
|
{
|
SetFocus(rowIdx, (int)RoomTypeInputRow.ColType.ID);
|
}
|
return false;
|
}
|
|
data.SetCellText(index, CConvert.ToInt(inputText).ToString());
|
}
|
return true;
|
}
|
|
#endregion
|
|
#region ★★★★★ Public Method ★★★★★
|
|
/// <summary>
|
/// コントロール再表示
|
/// </summary>
|
public void Refresh(string type)
|
{
|
EnvironmentSetting.Debug($"再表示へ開始:{type}");
|
StateHasChanged();
|
EnvironmentSetting.Debug($"再表示へ終了:{type}");
|
if(OnRefresh != null) { OnRefresh(); }
|
}
|
|
#endregion
|
}
|