ab56a9bcf7
SVN-Revision: r240
516 lines
22 KiB
C#
516 lines
22 KiB
C#
using DevExpress.XtraGrid.Columns;
|
|
using Lskj.Business;
|
|
using Lskj.Business.Impl;
|
|
using Lskj.Control;
|
|
using Lskj.Control.Model;
|
|
using Lskj.Core;
|
|
using Lskj.Data;
|
|
using Lskj.Model;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
|
|
namespace Lskj.PubModulePrivate
|
|
{
|
|
public partial class FrmMain : Form
|
|
{
|
|
/// <summary>
|
|
/// 全部的私密模块设置
|
|
/// </summary>
|
|
public DataTable AllPrivateSettings;
|
|
public FrmMain()
|
|
{
|
|
InitializeComponent();
|
|
this.Load += FrmMain_Load;
|
|
}
|
|
/// <summary>
|
|
/// 窗体加载时
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void FrmMain_Load(object sender, EventArgs e)
|
|
{
|
|
if (CheckPrivateTable() && SystemInfo.Instance.IsDogVerify)
|
|
{
|
|
this.AllPrivateSettings = MainImpl.GetPrivatesByUserId();
|
|
InitComboBox();
|
|
InitGrid();
|
|
InitBtn();
|
|
SetPrivateLevelOneDirectory();
|
|
this.PrimaryDirectory.SelectedIndex = 0;//初始化选中
|
|
|
|
}
|
|
else
|
|
{
|
|
Lskj.Control.MessageUtil.Show("私有模块数据表不存在或功能未开启,请联系管理员");
|
|
return;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 初始化菜单目录
|
|
/// </summary>
|
|
private void InitComboBox()
|
|
{
|
|
this.PrimaryDirectory.SelectedValueChanged += new EventHandler(PrivatePrimaryDirectoryValueChanged);
|
|
this.PrimaryDirectory.SelectedIndex = 0;
|
|
}
|
|
private void InitBtn()
|
|
{
|
|
this.Save.Click += new EventHandler(OnPrivateSave);
|
|
this.SetRemovePermissions.Click += new EventHandler(OnPrivateDeleteClick);
|
|
this.SetPassBtn.Click += OnSetPassBtnClick;
|
|
}
|
|
/// <summary>
|
|
/// 初始化左侧表格
|
|
/// </summary>
|
|
private void InitGrid()
|
|
{
|
|
GridColumn MenuIdColumn = new GridColumn();
|
|
MenuIdColumn.Caption = "编号";
|
|
MenuIdColumn.FieldName = "MenuId";
|
|
MenuIdColumn.VisibleIndex = 1;
|
|
|
|
GridColumn MenuStructColumn = new GridColumn();
|
|
MenuStructColumn.Caption = "菜单号";
|
|
MenuStructColumn.FieldName = "MenuStruct";
|
|
MenuStructColumn.VisibleIndex = 2;
|
|
|
|
GridColumn MenuCaptionColumn = new GridColumn();
|
|
MenuCaptionColumn.Caption = "菜单名称";
|
|
MenuCaptionColumn.FieldName = "MenuCaption";
|
|
MenuCaptionColumn.VisibleIndex = 3;
|
|
|
|
this.gridLeft.GridView.Columns.AddRange(new GridColumn[] {
|
|
//subsysidColumn,
|
|
MenuIdColumn,
|
|
MenuStructColumn,
|
|
MenuCaptionColumn
|
|
});
|
|
|
|
GridColumn priTreeListColumnName = new GridColumn();
|
|
priTreeListColumnName.Caption = "系统名称";
|
|
priTreeListColumnName.FieldName = "DllShowCaption";
|
|
priTreeListColumnName.MinWidth = 38;
|
|
priTreeListColumnName.Visible = true;
|
|
priTreeListColumnName.VisibleIndex = 0;
|
|
priTreeListColumnName.Width = 300;
|
|
|
|
GridColumn priTreeListColumnMenuId = new GridColumn();
|
|
priTreeListColumnMenuId.Caption = "菜单id";
|
|
priTreeListColumnMenuId.FieldName = "LMenuid";
|
|
priTreeListColumnMenuId.Visible = true;
|
|
priTreeListColumnMenuId.VisibleIndex = 1;
|
|
|
|
GridColumn priTreeListColumnModuleId = new GridColumn();
|
|
priTreeListColumnModuleId.Caption = "模块编号";
|
|
priTreeListColumnModuleId.FieldName = "PurviewId";
|
|
priTreeListColumnModuleId.Visible = true;
|
|
priTreeListColumnModuleId.VisibleIndex = 2;
|
|
|
|
this.AllQuickControlEx.GridView.Columns.AddRange(new GridColumn[] {
|
|
priTreeListColumnName,
|
|
priTreeListColumnMenuId,
|
|
priTreeListColumnModuleId
|
|
});
|
|
|
|
this.checkGrid.GridView.Columns.AddVisible("DllShowCaption", "系统名称");
|
|
this.checkGrid.GridView.Columns.AddVisible("LMenuid", "菜单id");
|
|
this.checkGrid.GridView.Columns.AddVisible("PurviewId", "模块编号");
|
|
|
|
this.AllQuickControlEx.GridView.BestFitColumns();//设置根据内容填充列宽
|
|
this.AllQuickControlEx.GridView.OptionsBehavior.EditorShowMode = DevExpress.Utils.EditorShowMode.MouseDown;
|
|
|
|
GridDragGrid dragPrivateGrid = new GridDragGrid(this.AllQuickControlEx.GridView, this.checkGrid.GridView);
|
|
GridDragGrid dragPrivateGridNew = new GridDragGrid(this.checkGrid.GridView, this.AllQuickControlEx.GridView);
|
|
|
|
GridDragGrid.GridAddCheckBox(this.checkGrid.GridView);
|
|
|
|
GridDragGrid.GridAddCheckBox(this.AllQuickControlEx.GridView);
|
|
GridDragGrid.GridAddCheckBox(this.AllQuickControlEx.GridView);
|
|
this.gridLeft.GridView.Click += new EventHandler(OnPrivateGridLeftGridViewClick);
|
|
|
|
this.checkGrid.GridView.OptionsSelection.EnableAppearanceFocusedCell = false;
|
|
this.AllQuickControlEx.GridControl.AllowDrop = true;
|
|
this.checkGrid.GridControl.AllowDrop = true;
|
|
this.AllQuickControlEx.GridView.OptionsBehavior.Editable = false;
|
|
this.checkGrid.GridView.OptionsBehavior.Editable = false;
|
|
|
|
DataRow[] OperatingDr = AllPrivateSettings.Select("privateTag=1");
|
|
DataTable OperatingDt = AllPrivateSettings.Clone();
|
|
if (OperatingDr != null && OperatingDr.Length > 0)
|
|
{
|
|
foreach (DataRow row in OperatingDr)
|
|
{
|
|
OperatingDt.ImportRow(row);
|
|
}
|
|
}
|
|
this.checkGrid.GridControl.DataSource = OperatingDt;
|
|
}
|
|
public void PrivateAccessPermissions(DataRow rowItem, string privateTag)
|
|
{
|
|
DataRow dr = AllPrivateSettings.NewRow();
|
|
dr["LMenuid"] = rowItem["LMenuid"] + "";
|
|
dr["ObjDll"] = rowItem["DllFilename"] + "";
|
|
dr["DllShowCaption"] = rowItem["DllShowCaption"] + "";
|
|
dr["Lsubsysid"] = (this.PrimaryDirectory.EditValue + "").Split('.')[0];
|
|
dr["PrivateTag"] = privateTag;
|
|
|
|
//数据源如果原本不存在选中行,则增加
|
|
if ((AllPrivateSettings.Rows.Cast<DataRow>().Where(x => x["LMenuid"] + "" == dr["LMenuid"] + "")).Count() == 0)
|
|
{
|
|
this.AllPrivateSettings.Rows.Add(dr);
|
|
DataTable QoDt = this.checkGrid.gridControl.DataSource as DataTable;
|
|
QoDt.Rows.Add(dr.ItemArray);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 设置一级目录,创建二级目录的表格列
|
|
/// </summary>
|
|
protected void SetPrivateLevelOneDirectory()
|
|
{
|
|
//获取一级目录
|
|
DataTable treeTable = SqlHelper.ExecuteDataTable("select subsysid,subsysname from P_SubSystemTab where useed=1");
|
|
string text = string.Empty;
|
|
foreach (DataRow dr in treeTable.Rows)
|
|
{
|
|
text = string.Empty;
|
|
text = dr["subsysid"] + "." + dr["subsysname"];
|
|
PrimaryDirectory.Properties.Items.Add(text);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 判断私有模块权限表格是否存在
|
|
/// </summary>
|
|
private bool CheckPrivateTable()
|
|
{
|
|
try
|
|
{
|
|
//日志表列名
|
|
Dictionary<string, string> colDic = new Dictionary<string, string>();
|
|
colDic.Add("ObjDll", "varchar(1000)");
|
|
colDic.Add("DllShowCaption", "varchar(1000)");
|
|
colDic.Add("LMenuid", "int");
|
|
colDic.Add("Lsubsysid", "int");
|
|
colDic.Add("PrivateTag", "int");
|
|
string isExitApiTab = "select top 1 * from sysObjects where Id=OBJECT_ID(N'P_PrivateDllTab') and xtype='U'";
|
|
DataTable apiTab = SqlHelper.ExecuteDataTable(isExitApiTab);
|
|
if (apiTab.Rows.Count > 0)//存在日志表
|
|
{
|
|
DataTable columnsTab = SqlHelper.ExecuteDataTable(string.Format("select name from syscolumns where id=object_id('P_PrivateDllTab')"));
|
|
foreach (KeyValuePair<string, string> colunmField in colDic)
|
|
{
|
|
DataRow[] dataRows = columnsTab.Select().Where(n => (n["name"] + "").Equals(colunmField.Key)).ToArray();
|
|
if (dataRows.Length == 0)
|
|
{
|
|
string addColSql = string.Format("alter table P_PrivateDllTab add {0} {1}", colunmField.Key, colunmField.Value);
|
|
SqlHelper.ExecuteNonQuery(addColSql);//添加列
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
string createTabSql = "create table P_PrivateDllTab(id int IDENTITY(1,1) NOT NULL,{0})";
|
|
string createCol = string.Empty;
|
|
foreach (KeyValuePair<string, string> colunmField in colDic)
|
|
{
|
|
createCol += string.Format("{0} {1},", colunmField.Key, colunmField.Value);
|
|
}
|
|
createTabSql = string.Format(createTabSql, createCol.TrimEnd(','));
|
|
SqlHelper.ExecuteNonQuery(createTabSql);//创建表
|
|
}
|
|
return true;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 下方数据删除,上方取消勾选
|
|
/// </summary>
|
|
/// <param name="rowItem"></param>
|
|
public void RemovePermissions(DataRow rowItem)
|
|
{
|
|
string menuid = rowItem["LMenuid"] + "";
|
|
DataRow[] dr = AllPrivateSettings.Select(string.Format("LMenuid='{0}'", menuid));
|
|
if (dr.Length == 1)
|
|
{
|
|
AllPrivateSettings.Rows.Remove(dr[0]);
|
|
}
|
|
}
|
|
#region 事件
|
|
private void PrivatePrimaryDirectoryValueChanged(object sender, EventArgs e)
|
|
{
|
|
string text = (this.PrimaryDirectory.EditValue + "").Split('.')[0];
|
|
DataTable dt = SqlHelper.ExecuteDataTable(string.Format("select * from P_FormMenuConfigTab where len(menustruct)=2 and subsysid='{0}' order by menustruct", text));
|
|
if (dt.Rows.Count > 0)
|
|
{
|
|
this.gridLeft.gridControl.DataSource = dt;
|
|
this.gridLeft.GridView.SelectRowHandler(0);
|
|
OnPrivateGridLeftGridViewClick(null, null);
|
|
}
|
|
else
|
|
{
|
|
this.gridLeft.gridControl.DataSource = null;
|
|
this.AllQuickControlEx.gridControl.DataSource = null;
|
|
this.checkGrid.gridControl.DataSource = null;
|
|
}
|
|
}
|
|
private void OnPrivateGridLeftGridViewClick(object sender, EventArgs e)
|
|
{
|
|
DataRow mSelectRow = this.gridLeft.GridView.GetFocusedDataRow();
|
|
if (mSelectRow != null)
|
|
{
|
|
string sql = string.Format("select MenuId as LMenuid,MenuCaption as DllShowCaption,PurviewId,subsysid,Menustruct,DllFilename from P_FormMenuConfigTab where subsysid='{0}' and left(menustruct,2)='{1}' and menustruct!='{1}' and useFlag='1' and len(menustruct)=4 ", mSelectRow["subsysid"] + "", mSelectRow["menustruct"] + "");
|
|
DataTable Alldt = SqlHelper.ExecuteDataTable(sql);
|
|
|
|
string menuid = string.Empty;
|
|
//DataTable HasBeenSetDt = Alldt.Clone();//已设置快捷通道的模块
|
|
List<string> primaryKeys = new List<string>();
|
|
//DataTable IsNotSetDt = Alldt.Clone();//为设置快捷通道的模块
|
|
for (int i = 0; i < Alldt.Rows.Count; i++)
|
|
{
|
|
menuid = Alldt.Rows[i]["LMenuid"] + "";
|
|
if (string.IsNullOrWhiteSpace(menuid)) continue;
|
|
|
|
//判断已有的快捷通道设置中是否有当前模块id
|
|
if ((AllPrivateSettings.Rows.Cast<DataRow>().Where(x => x["LMenuid"] + "" == menuid)).Count() > 0)
|
|
{
|
|
//HasBeenSetDt.Rows.Add(Alldt.Rows[i].ItemArray);
|
|
primaryKeys.Add(Alldt.Rows[i]["LMenuid"] + "");
|
|
}
|
|
else
|
|
{
|
|
//IsNotSetDt.Rows.Add(Alldt.Rows[i].ItemArray);
|
|
}
|
|
}
|
|
//this.AllQuickControlEx.gridControl.DataSource = IsNotSetDt;
|
|
this.AllQuickControlEx.gridControl.DataSource = Alldt;
|
|
for (int i = 0; i < Alldt.Rows.Count; i++)
|
|
{
|
|
if (primaryKeys.Contains(Alldt.Rows[i]["LMenuid"] + "")) this.AllQuickControlEx.GridView.SelectRow(i);
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 设置私密权限保存事件
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void OnPrivateSave(object sender, EventArgs e)
|
|
{
|
|
if (!CheckPassWord())
|
|
{
|
|
return;
|
|
}
|
|
int[] rowNumbers = this.AllQuickControlEx.GridView.GetSelectedRows();
|
|
List<DataRow> addRows = new List<DataRow>();
|
|
foreach (int rowIndex in rowNumbers)
|
|
{
|
|
DataRow rowItem = this.AllQuickControlEx.GridView.GetDataRow(rowIndex);
|
|
addRows.Add(rowItem);
|
|
}
|
|
foreach (DataRow dr in addRows)
|
|
{
|
|
PrivateAccessPermissions(dr, "1");
|
|
}
|
|
SaveProvate();
|
|
}
|
|
//删除权限 QuickOperationControlEx表
|
|
private void OnPrivateDeleteClick(object sender, EventArgs e)
|
|
{
|
|
if (!CheckPassWord())
|
|
{
|
|
return;
|
|
}
|
|
int[] rowNumbers = this.checkGrid.GridView.GetSelectedRows();
|
|
if (rowNumbers.Length == 0) return;
|
|
List<DataRow> deleteRows = new List<DataRow>();
|
|
List<string> primaryKeys = new List<string>();
|
|
|
|
foreach (int rowIndex in rowNumbers)
|
|
{
|
|
DataRow rowItem = this.checkGrid.GridView.GetDataRow(rowIndex);
|
|
deleteRows.Add(rowItem);
|
|
primaryKeys.Add(rowItem["LMenuid"] + "");
|
|
}
|
|
|
|
DataTable gcDetailDt = this.checkGrid.gridControl.DataSource as DataTable;
|
|
foreach (DataRow dr in deleteRows)
|
|
{
|
|
RemovePermissions(dr);
|
|
gcDetailDt.Rows.Remove(dr);
|
|
}
|
|
|
|
DataTable gcMainDt = this.AllQuickControlEx.gridControl.DataSource as DataTable;
|
|
for (int i = 0; i < gcMainDt.Rows.Count; i++)
|
|
{
|
|
if (primaryKeys.Contains(gcMainDt.Rows[i]["LMenuid"] + "")) this.AllQuickControlEx.GridView.UnselectRow(i);
|
|
}
|
|
SaveProvate();
|
|
}
|
|
/// <summary>
|
|
/// 设置U盾密码点击
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void OnSetPassBtnClick(object sender, EventArgs e)
|
|
{
|
|
FrmPassword frmPassword = new FrmPassword();
|
|
int keyHandle = ERPInfo.Instance.keyHandles[0];
|
|
int uPin1 = Convert.ToInt32("0x987F6BCD", 16);
|
|
int uPin2 = Convert.ToInt32("0xE193C5B2", 16);
|
|
int uPin3 = Convert.ToInt32("0xD507CC28", 16);
|
|
int uPin4 = Convert.ToInt32("0x4B125AF6", 16);
|
|
int rtn = SmartX1Api.SmartX1Open(keyHandle, uPin1, uPin2, uPin3, uPin4);
|
|
if (rtn == 0)
|
|
{
|
|
frmPassword.ShowDialog();
|
|
}
|
|
else
|
|
{
|
|
MessageUtil.Show("U盾数据获取失败,请重试或联系管理员");
|
|
return;
|
|
}
|
|
frmPassword.Dispose();
|
|
}
|
|
/// <summary>
|
|
/// 检查密码状态
|
|
/// </summary>
|
|
private bool CheckPassWord()
|
|
{
|
|
bool isCheck = false;
|
|
int keyHandle = ERPInfo.Instance.keyHandles[0];
|
|
int uPin1 = Convert.ToInt32("0x987F6BCD", 16);
|
|
int uPin2 = Convert.ToInt32("0xE193C5B2", 16);
|
|
int uPin3 = Convert.ToInt32("0xD507CC28", 16);
|
|
int uPin4 = Convert.ToInt32("0x4B125AF6", 16);
|
|
int rtn = SmartX1Api.SmartX1Open(keyHandle, uPin1, uPin2, uPin3, uPin4);
|
|
if (rtn == 0)
|
|
{
|
|
byte[] readBuffer = new byte[256];
|
|
int add = 0;
|
|
int len = 256;
|
|
int readPageRtn = SmartX1Api.SmartX1ReadPage(keyHandle, 0, add, ref len, readBuffer);
|
|
if (readPageRtn == 0)
|
|
{
|
|
string savePassword = Encoding.Default.GetString(readBuffer);
|
|
if (savePassword.Equals(ERPInfo.Instance.dogVerifyPasswordDefault) || string.IsNullOrWhiteSpace(savePassword.Replace("\0", "")))
|
|
{
|
|
MessageUtil.Show("当前未设置U盾密码,请设置后重试");
|
|
}
|
|
else
|
|
{
|
|
isCheck = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageUtil.Show("U盾数据获取失败,请重试或联系管理员");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageUtil.Show("U盾数据获取失败,请重试或联系管理员");
|
|
}
|
|
SmartX1Api.SmartX1Close(keyHandle);
|
|
return isCheck;
|
|
}
|
|
private void SaveProvate()
|
|
{
|
|
|
|
WaitForm.ShowForm(ResourceKeys.DataSaving);
|
|
try
|
|
{
|
|
string TableName = "P_PrivateDllTab";
|
|
string deleteSql = string.Format("truncate table {0}", TableName);
|
|
|
|
string sql = string.Empty;
|
|
string writeStr = string.Empty;
|
|
foreach (DataRow dr in AllPrivateSettings.Rows)
|
|
{
|
|
sql += string.Format("insert into {0} (ObjDll,DllShowCaption,LMenuid,Lsubsysid,PrivateTag) values ('{1}','{2}','{3}','{4}','{5}');\r\n", TableName, dr["ObjDll"], dr["DllShowCaption"], dr["LMenuid"], dr["Lsubsysid"], dr["PrivateTag"]);
|
|
writeStr += string.Format("{0},", dr["LMenuid"] + "");
|
|
}
|
|
int keyHandle = ERPInfo.Instance.keyHandles[0];
|
|
int uPin1 = Convert.ToInt32("0x987F6BCD", 16);
|
|
int uPin2 = Convert.ToInt32("0xE193C5B2", 16);
|
|
int uPin3 = Convert.ToInt32("0xD507CC28", 16);
|
|
int uPin4 = Convert.ToInt32("0x4B125AF6", 16);
|
|
int rtn = SmartX1Api.SmartX1Open(keyHandle, uPin1, uPin2, uPin3, uPin4);
|
|
if (rtn == 0)
|
|
{
|
|
SqlHelper.ExecuteNonQuery(deleteSql);
|
|
SqlHelper.ExecuteNonQuery(string.Format("{0};{1}", deleteSql, sql));
|
|
string writeKey = string.Format("{0}_{1}", DBConfig.Instance.ServerName, DBConfig.Instance.DataBase);
|
|
byte[] readBuffer = new byte[4096];
|
|
int readRtn = SmartX1Api.SmartX1ReadStorage(keyHandle, 0, 4096, readBuffer);
|
|
if (readRtn == 0)
|
|
{
|
|
Dictionary<string, string> readKeysValues = new Dictionary<string, string>();
|
|
string readVerifyStr = Encoding.Default.GetString(readBuffer);
|
|
string[] readVerifyStrArray = readVerifyStr.Replace("\0", "").Split(';');//获取多个账套设置
|
|
foreach (string readVerify in readVerifyStrArray)
|
|
{
|
|
string[] readKeyValue = readVerify.Split('^');//获取单个账套
|
|
if (readKeyValue.Length == 2)
|
|
{
|
|
readKeysValues.Add(readKeyValue[0], readKeyValue[1]);
|
|
}
|
|
}
|
|
if (readKeysValues.ContainsKey(writeKey))//如果存在当前账套
|
|
{
|
|
readKeysValues[writeKey] = writeStr.TrimEnd(',');
|
|
}
|
|
else
|
|
{
|
|
readKeysValues.Add(writeKey, writeStr.TrimEnd(','));
|
|
}
|
|
string allWriteStr = string.Empty;
|
|
foreach (string key in readKeysValues.Keys)
|
|
{
|
|
allWriteStr += string.Format("{0}^{1};", key, readKeysValues[key]);
|
|
}
|
|
byte[] writeBuffer = Encoding.Default.GetBytes(allWriteStr);
|
|
int writeRtn = SmartX1Api.SmartX1WriteStorage(keyHandle, 0, 4096, writeBuffer);
|
|
if (writeRtn == 0)
|
|
{
|
|
MessageUtil.Show("保存成功");
|
|
}
|
|
else
|
|
{
|
|
MessageUtil.Show("U盾数据获取失败,请重试或联系管理员");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageUtil.Show("U盾数据获取失败,请重试或联系管理员");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageUtil.Show("U盾验证失败,请重试或联系管理员");
|
|
return;
|
|
}
|
|
SmartX1Api.SmartX1Close(keyHandle);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
MessageUtil.Show("保存失败");
|
|
}
|
|
finally
|
|
{
|
|
WaitForm.HideForm();
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
}
|