aardio 文档

Calendar 项目排期日历

本页给出一个 Calendar 排期面板示例,演示 CalendarDateBadgeAlertButton 的组合用法。适合设备维保、课程安排、项目里程碑、值班计划等按日期组织的业务界面。

示例仍采用 aardio 推荐模式:在 /*DSG{{*/ ... /*}}*/ 中放置多个语义化 custom 宿主,再用 AntdUI.Control(winform.host) 自然嵌入控件。这样窗口缩放、DPI 缩放和边距固定由 aardio 设计器维护,不需要在 .NET 控件内部手写大量 SetBounds

完整示例

import win.ui;
import dotNet.AntdUI;
import System;
import System.Drawing;
/*DSG{{*/
var winform = win.form(text="项目排期日历";right=920;bottom=600;bgcolor=0xF7F8FA)
winform.add(
calendarHost={cls="custom";left=20;top=20;right=610;bottom=560;db=1;dl=1;dt=1;edge=1;z=1};
detailHost={cls="custom";left=630;top=20;right=900;bottom=190;dl=1;dr=1;dt=1;frame=1;z=2};
legendHost={cls="custom";left=630;top=410;right=900;bottom=560;db=1;dl=1;dr=1;dt=1;z=7};
nextHost={cls="custom";text="下一项";left=820;top=350;right=900;bottom=386;dr=1;dt=1;frame=1;z=6};
prevHost={cls="custom";text="上一项";left=630;top=350;right=710;bottom=386;dl=1;dt=1;frame=1;z=4};
summaryHost={cls="custom";left=630;top=205;right=900;bottom=330;dl=1;dr=1;dt=1;frame=1;z=3};
todayHost={cls="custom";text="今天";left=725;top=350;right=805;bottom=386;dl=1;dt=1;frame=1;z=5}
)
/*}}*/

// 业务数据使用普通 aardio 数组保存;Calendar 只负责展示与选择日期。
var plans = [
    {date="2026-07-06"; type="巡检"; title="核心机房巡检"; desc="检查 UPS、温湿度、告警面板和备份链路。"; color=0xFF1677FF},
    {date="2026-07-09"; type="保养"; title="冷却系统保养"; desc="更换滤网,复核冷却水压力与风机状态。"; color=0xFF52C41A},
    {date="2026-07-15"; type="评审"; title="月度容量评审"; desc="评估存储、带宽和计算资源的增长趋势。"; color=0xFFFAAD14},
    {date="2026-07-21"; type="发布"; title="网关策略发布"; desc="灰度发布新访问策略,观察 30 分钟后扩大范围。"; color=0xFF722ED1},
    {date="2026-07-28"; type="演练"; title="灾备切换演练"; desc="按预案切换到备站,并记录恢复时间。"; color=0xFFF5222D}
];

var parseDateText = function(dateText){
    var y,m,d = string.match(dateText,"^(\d+)-(\d+)-(\d+)$");

    if(!y) return System.DateTime.Now.Date;

    //tonumber 返回 2 个值,这样实际传了 4 个参数,会因参数类型不匹配找不到方法
    //System.DateTime(tonumber(y),tonumber(m),tonumber(d))

    y,m,d = tonumber(y),tonumber(m),tonumber(d)
    return System.DateTime(y,m,d);
}

var calendar = AntdUI.Calendar(winform.calendarHost);
calendar.Full = true;
calendar.ShowChinese = true;
calendar.ShowButtonToDay = true;
calendar.Radius = 8;
calendar.SetMinMax(System.DateTime(2026,7,1), System.DateTime(2026,7,31));

var detail = AntdUI.Alert(winform.detailHost);
detail.TextTitle = "选中日期";
detail.Text = "请选择日历中的日期查看安排。";
detail.Icon = AntdUI.TType.Info;
detail.CloseIcon = false;
detail.Radius = 8;
detail.BorderWidth = 1;

var summary = AntdUI.Alert(winform.summaryHost);
summary.TextTitle = "本月计划";
summary.Text = "共 " + #plans + " 项排期,徽标颜色表示不同类型。";
summary.Icon = AntdUI.TType.Success;
summary.CloseIcon = false;
summary.Radius = 8;

var btnPrev = AntdUI.Button(winform.prevHost);
btnPrev.Type = AntdUI.TTypeMini.Default;

var btnToday = AntdUI.Button(winform.todayHost);
btnToday.Type = AntdUI.TTypeMini.Primary;

var btnNext = AntdUI.Button(winform.nextHost);
btnNext.Type = AntdUI.TTypeMini.Default;

var legend = AntdUI.Alert(winform.legendHost);
legend.TextTitle = "图例";
legend.Text = '蓝色:巡检\r\n绿色:保养\r\n黄色:评审\r\n紫色:发布\r\n红色:演练';
legend.Icon = AntdUI.TType.Info;
legend.CloseIcon = false;
legend.Radius = 8;

var buildBadges = function(){
    var badges = dotNet.list("AntdUI.DateBadge");
    for i,item in plans {
        // DateBadge 的 date 参数使用 yyyy-MM-dd 字符串,content 是显示在日期上的徽标文本。
        var badge = AntdUI.DateBadge(item.date,item.type,item.color);
        badge.Radius = 4;
        badge.Size = 0.6; //相对 Calendar 字体的缩放比例,不是像素字号
        badges.Add(badge);
    }
    return badges;
}

calendar.SetBadge(buildBadges());
calendar.LoadBadge();

var findPlansByDate = function(dateText){
    var found = [];
    for i,item in plans {
        if(item.date == dateText) table.push(found,item);
    }
    return found;
}

var renderDate = function(dateText){
    var found = findPlansByDate(dateText);
    if(#found){
        var lines = [];
        for i,item in found {
            table.push(lines,item.type + " · " + item.title ++ '\r\n' ++ item.desc);
        }
        detail.Icon = AntdUI.TType.Success;
        detail.TextTitle = dateText + " · " + #found + " 项安排";
        detail.Text = string.join(lines,'\r\n\r\n');
    }
    else{
        detail.Icon = AntdUI.TType.Info;
        detail.TextTitle = dateText + " · 无安排";
        detail.Text = "这一天没有排期,可作为缓冲或临时维护窗口。";
    }
}

var currentPlanIndex = 1;
var jumpToPlan = function(index){
    if(index < 1) index = #plans;
    if(index > #plans) index = 1;
    currentPlanIndex = index;

    var item = plans[currentPlanIndex];
    calendar.SetDate(parseDateText(item.date));
    renderDate(item.date);
}

calendar.DateChanged = function(sender,value){
    renderDate(value.ToString("yyyy-MM-dd"));
}

btnPrev.Click = function(sender,e){
    jumpToPlan(currentPlanIndex - 1);
}

btnNext.Click = function(sender,e){
    jumpToPlan(currentPlanIndex + 1);
}

btnToday.Click = function(sender,e){
    var todayText = System.DateTime.Now.ToString("yyyy-MM-dd");
    calendar.SetDate(System.DateTime.Now.Date);
    renderDate(todayText);
}

jumpToPlan(1);
winform.show();
win.loopMessage();

关键模式

1. 业务数组是数据源,Calendar 只是视图

不要把业务数据塞进控件内部再从控件反推业务状态。示例中 plans 保存真实数据,DateBadge 只是把重要日期视觉化:

var badge = AntdUI.DateBadge(item.date,item.type,item.color);
badges.Add(badge);
calendar.SetBadge(badges);

2. DateBadge 使用字符串日期

当前 DLL 验证的 DateBadge 常用构造函数使用 yyyy-MM-dd 字符串作为日期参数,例如:

var badge = AntdUI.DateBadge("2026-07-06","巡检",0xFF1677FF);
badge.Radius = 4;
badge.Size = 0.6; //相对 Calendar 字体的缩放比例,不是像素字号

DateBadge 常用属性包括:

3. DateChanged 只负责联动显示

用户选择日期后,DateChanged 传入 System.DateTime,常用 value.ToString("yyyy-MM-dd") 转成业务 key:

calendar.DateChanged = function(sender,value){
    renderDate(value.ToString("yyyy-MM-dd"));
}

如果在代码中调用 calendar.SetDate(...) 后需要立即更新右侧详情,建议像示例一样主动调用 renderDate(dateText),不要依赖事件是否同步触发。

4. 日期范围与农历显示

calendar.SetMinMax(System.DateTime(2026,7,1), System.DateTime(2026,7,31));
calendar.ShowChinese = true;
calendar.ShowButtonToDay = true;

ShowChinese 适合排班、节假日、课程表等场景;如果是全球化业务系统,应根据用户区域决定是否启用。

Markdown 格式