using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Text.Json; using System.Text.Json.Serialization; using System.Drawing.Text; namespace ddq { public partial class FundQ : Form { private string fundId; private int userId = 123; private DataTable fundInfoTable; public FundQ(string fundId) { InitializeComponent(); this.fundId = fundId; InitializeData(); } private void InitializeData() { DataTable dt = DataAccess.Get_fund_info(fundId, null); if (dt == null || dt.Rows.Count <= 0) return; this.lblFundName.Text = dt.Rows[0].Field("fund_short_name"); //this.lblMainCode.Text = "Code: " + dt.Rows[0].Field("register_number"); this.lblMainCode.Text = "Code: " + fundId; this.lblCategory.Text = "Category: " + dt.Rows[0].Field("strategy"); this.lblInceptionDate.Text = "Launched: " + dt.Rows[0].Field("inception_date")?.ToString("yyyy-MM-dd"); this.lblDomicile.Text = "Domicile: "; fundInfoTable = DataAccess.Get_dd_fund_info(fundId, null, 1); bool hasPM = false; DataTable dtPM; bool hasTER = false; DataTable dtTER; if (fundInfoTable != null && fundInfoTable.Rows.Count > 0) { string jsonString = fundInfoTable.Rows[0].Field("info").Trim(); JsonDocument document = JsonDocument.Parse(jsonString); JsonElement root = document.RootElement; if (root.ValueKind != JsonValueKind.Undefined) { this.txtInvestmentObjective.Text = Json2Text(root, "investmentObjective"); this.txtBenchmark.Text = Json2Text(root, "benchmark"); this.txtInvestmentPhilosophy.Text = Json2Text(root, "investmentPhilosophy"); JsonElement elmPM; hasPM = root.TryGetProperty("portfolioManagers", out elmPM); if (hasPM == true) { dtPM = Json2Table(elmPM); InitPortfolioManagerGrid(dtPM); } JsonElement elmTER; hasTER = root.TryGetProperty("ter", out elmTER); if (hasTER == true) { dtTER = Json2Table(elmTER); InitTERGrid(dtTER); } } } if (hasPM == false) { dtPM = new DataTable(); // 没有基金经理数据时,初始化表 dtPM.Columns.Add("name", typeof(string)); dtPM.Columns.Add("startDate", typeof(DateTime)); dtPM.Columns.Add("endDate", typeof(DateTime)); InitPortfolioManagerGrid(dtPM); } if (hasTER == false) { dtTER = new DataTable(); dtTER.Columns.Add("year", typeof(int)); dtTER.Columns.Add("ter", typeof(decimal)); int year = DateTime.Today.Year - 1; for (int i = 0; i < 5; i++) { DataRow row = dtTER.NewRow(); row["year"] = year - i; dtTER.Rows.Add(row); } InitTERGrid(dtTER); } } private void InitPortfolioManagerGrid(DataTable dt) { this.grdPortfolioManager.DataSource = dt; this.grdPortfolioManager.Columns["name"].HeaderText = "Manager Name"; this.grdPortfolioManager.Columns["name"].DisplayIndex = 0; this.grdPortfolioManager.Columns["startDate"].HeaderText = "Start Date"; this.grdPortfolioManager.Columns["startDate"].DefaultCellStyle.Format = "yyyy-MM-dd"; this.grdPortfolioManager.Columns["startDate"].DisplayIndex = 1; this.grdPortfolioManager.Columns["endDate"].HeaderText = "End Date"; this.grdPortfolioManager.Columns["endDate"].DefaultCellStyle.Format = "yyyy-MM-dd"; this.grdPortfolioManager.Columns["endDate"].DisplayIndex = 2; } private void InitTERGrid(DataTable dt) { this.grdTER.DataSource = dt; this.grdTER.Columns["year"].HeaderText = "Year"; this.grdTER.Columns["year"].ReadOnly = true; this.grdTER.Columns["year"].DisplayIndex = 0; this.grdTER.Columns["ter"].HeaderText = "Total Expense Ratio %"; this.grdTER.Columns["ter"].ValueType = typeof(decimal); this.grdTER.Columns["ter"].DefaultCellStyle.Format = "N3"; this.grdTER.Columns["ter"].DisplayIndex = 1; } /// /// JsonElment 转为字符串,若输入为空则输出"" /// /// /// public static string Json2Text(JsonElement jsonElement, string propertyName) { string str = ""; JsonElement elm; if (propertyName == null) return str; bool hasProperty = jsonElement.TryGetProperty(propertyName, out elm); if (hasProperty == true && elm.ValueKind != JsonValueKind.Undefined) { str = elm.ToString().Trim(); } return str; } public static DataTable Json2Table(JsonElement jsonElement) { DataTable dataTable = new DataTable(); // 如果解析出的是数组 if (jsonElement.ValueKind == JsonValueKind.Array) { // 遍历数组元素 foreach (JsonElement element in jsonElement.EnumerateArray()) { // 如果是第一次遍历,元素包含列定义信息,需要创建列 if (dataTable.Columns.Count == 0) { // 遍历第一个对象的属性来创建列 foreach (JsonProperty property in element.EnumerateObject()) { dataTable.Columns.Add(property.Name); } } // 创建新行并填充数据 DataRow newRow = dataTable.NewRow(); foreach (JsonProperty property in element.EnumerateObject()) { newRow[property.Name] = property.Value.ToString(); } dataTable.Rows.Add(newRow); } } return dataTable; } public static List> DataTable2List(DataTable dataTable) { var records = new List>(); foreach (DataRow row in dataTable.Rows) { var record = new Dictionary(); foreach (DataColumn col in dataTable.Columns) { // 处理DBNull值 record[col.ColumnName] = row[col] == DBNull.Value ? null : row[col]; } records.Add(record); } return records; } private void FundQ_Load(object sender, EventArgs e) { } private void btnSaveGeneralInfo_Click(object sender, EventArgs e) { try { // 数据对象 var textData = new { fundId = this.fundId, investmentObjective = this.txtInvestmentObjective.Text, benchmark = this.txtBenchmark.Text, investmentPhilosophy = this.txtInvestmentPhilosophy.Text, portfolioManagers = DataTable2List((DataTable)this.grdPortfolioManager.DataSource), ter = DataTable2List((DataTable)this.grdTER.DataSource), updateTime = DateTime.Now }; // 序列化选项 var options = new JsonSerializerOptions { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; string jsonString = JsonSerializer.Serialize(textData, options); //MessageBox.Show($"Save JSON: \n{jsonString}", "Json Result"); int ret = DataAccess.Set_dd_fund_info(this.fundId, DateTime.Today, jsonString, 1, 1, userId); if (ret == 1) { this.Close(); } } catch (Exception ex) { MessageBox.Show($"Error: {ex.Message}", "Error"); } } private void grdTER_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) { string errMsg = "Please enter a number between 0 and 100, with up to 3 decimal digits"; if (grdTER.Columns[e.ColumnIndex].Name == "ter" && e.RowIndex >= 0) { // 先清除可能存在的旧错误提示 grdTER.Rows[e.RowIndex].ErrorText = ""; if (e.FormattedValue.ToString().Trim() == "") return; // 尝试将输入的值转换为小数 if (!decimal.TryParse(e.FormattedValue.ToString(), out decimal newValue)) { // 如果转换失败,说明输入的不是有效数字 e.Cancel = true; grdTER.Rows[e.RowIndex].ErrorText = errMsg; return; } // 验证数值范围(例如限制在0到100之间) if (newValue < 0 || newValue > 100) { e.Cancel = true; grdTER.Rows[e.RowIndex].ErrorText = errMsg; return; } // (可选) 自定义验证小数位数 string[] parts = e.FormattedValue.ToString().Split('.'); if (parts.Length > 1 && parts[1].Length > 3) // 检查小数点后的位数 { e.Cancel = true; grdTER.Rows[e.RowIndex].ErrorText = errMsg; } } } private void btnSaveFundProcess_Click(object sender, EventArgs e) { } } }