[AntdUI] 12 Menu控件的创建

nanyi 12小时前 52 v 1.0.0.0 2026-07-01

import win.ui;
import dotNet.AntdUI;
import dotNet;
/*DSG{{*/
var winform = win.form(text="AntdUI Menu";right=960;bottom=650;bgcolor=0xF0F0F0;border="thin")
winform.add(
custom_base={cls="custom";left=0;top=0;right=962;bottom=652;ah=1;aw=1;db=1;disabled=1;dl=1;dr=1;dt=1;hide=1;z=1};
custom_breadcrumb={cls="custom";left=234;top=0;right=962;bottom=50;bgcolor=0xFFFFFF;dl=1;dr=1;dt=1;z=4};
custom_content={cls="custom";left=234;top=52;right=962;bottom=652;bgcolor=0xFFFFFF;db=1;dl=1;dr=1;dt=1;z=5};
custom_sidebar_logo={cls="custom";left=0;top=0;right=232;bottom=62;bgcolor=0xFFFFFF;dl=1;dt=1;z=2};
custom_sidebar_menu={cls="custom";left=0;top=64;right=232;bottom=652;bgcolor=0xFFFFFF;db=1;dl=1;dt=1;z=3}
)
/*}}*/

// ---------- AntdUI 容器 ----------
var baseForm = AntdUI.BaseForm();
baseForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
baseForm.Dock = System.Windows.Forms.DockStyle.Fill;
dotNet.setParent(baseForm, winform.custom_base);

// ---------- 字体 ----------
var fontLogo   = System.Drawing.Font("Microsoft YaHei", 16, System.Drawing.FontStyle.Bold);
var fontTitle  = System.Drawing.Font("Microsoft YaHei", 14, System.Drawing.FontStyle.Bold);
var fontNormal = System.Drawing.Font("Microsoft YaHei", 10);
var fontTip    = System.Drawing.Font("Microsoft YaHei", 9);

// ---------- 简化 SVG 图标 ----------
var svgDashboard = '<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path d="M128 512 512 160l384 352h-96v352H576V640H448v224H224V512z"/></svg>';
var svgSettings  = '<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path d="M512 320a192 192 0 1 0 0 384 192 192 0 0 0 0-384zm0-192 64 128 144 24 24 144 128 64-128 64-24 144-144 24-64 128-64-128-144-24-24-144-128-64 128-64 24-144 144-24z"/></svg>';
var svgContent   = '<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path d="M224 128h576v768H224zM320 256h384v64H320zm0 160h384v64H320zm0 160h256v64H320z"/></svg>';

// ============================================================
// 侧边栏 Logo
// ============================================================
var lblLogo = AntdUI.Label(winform.custom_sidebar_logo);
lblLogo.Text = "AntdUI Admin";
lblLogo.Font = fontLogo;
lblLogo.ForeColor = 0xFF1890FF;
lblLogo.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;

// ============================================================
// 左侧 Menu
// ============================================================
var menu = AntdUI.Menu(winform.custom_sidebar_menu);
menu.Mode = AntdUI.TMenuMode.Inline;
menu.Font = fontNormal;

// --- Dashboard ---
var mDashboard = AntdUI.MenuItem("Dashboard");
mDashboard.IconSvg = svgDashboard;
mDashboard.Tag = "Dashboard";
menu.Items.Add(mDashboard);

var mOverview = AntdUI.MenuItem("Overview");
mOverview.Tag = "Dashboard/Overview";
mDashboard.Sub.Add(mOverview);

var mAnalytics = AntdUI.MenuItem("Analytics");
mAnalytics.Tag = "Dashboard/Analytics";
mDashboard.Sub.Add(mAnalytics);

// --- Settings ---
var mSettings = AntdUI.MenuItem("Settings");
mSettings.IconSvg = svgSettings;
mSettings.Tag = "Settings";
menu.Items.Add(mSettings);

var mProfile = AntdUI.MenuItem("Profile");
mProfile.Tag = "Settings/Profile";
mSettings.Sub.Add(mProfile);

var mEditProfile = AntdUI.MenuItem("Edit Profile");
mEditProfile.Tag = "Settings/Profile/Edit Profile";
mProfile.Sub.Add(mEditProfile);

var mChangeAvatar = AntdUI.MenuItem("Change Avatar");
mChangeAvatar.Tag = "Settings/Profile/Change Avatar";
mProfile.Sub.Add(mChangeAvatar);

// --- Content ---
var mContent = AntdUI.MenuItem("Content");
mContent.IconSvg = svgContent;
mContent.Tag = "Content";
menu.Items.Add(mContent);

var mPosts = AntdUI.MenuItem("Posts");
mPosts.Tag = "Content/Posts";
mContent.Sub.Add(mPosts);

var mAllPosts = AntdUI.MenuItem("All Posts");
mAllPosts.Tag = "Content/Posts/All Posts";
mPosts.Sub.Add(mAllPosts);

var mAddNew = AntdUI.MenuItem("Add New");
mAddNew.Tag = "Content/Posts/Add New";
mPosts.Sub.Add(mAddNew);

var mCategories = AntdUI.MenuItem("Categories");
mCategories.Tag = "Content/Posts/Categories";
mPosts.Sub.Add(mCategories);

// ============================================================
// 右侧面包屑
// ============================================================
var bread = AntdUI.Breadcrumb(winform.custom_breadcrumb);
bread.Separator = "/";
bread.ForeActive = 0xFF1890FF;
bread.Font = fontNormal;

var biHome = AntdUI.BreadcrumbItem();
biHome.Text = "Home";
bread.Items.Add(biHome);

// ============================================================
// 右侧内容区 — Tabs(Card 风格,支持关闭)
// ============================================================
var tabs = AntdUI.Tabs();
tabs.Dock = System.Windows.Forms.DockStyle.Fill;
tabs.Font = fontNormal;
tabs.Type = AntdUI.TabType.Card;
tabs.Style.Closable = true;
dotNet.setParent(tabs, winform.custom_content);

// 统一生成 TabPage 唯一键。
// 重点:用十六进制编码路径,避免 /、空格等字符影响 .NET Control.Name。
var makeTabName = function(tag){
    return "tab_" ++ string.hex(tostring(tag));
};

// 根据菜单 tag 判断页面类型
var getPageType = function(tag){
    var parts = string.split(tostring(tag), "/");
    var first = parts[1];
    if(first == "Dashboard") return 1;
    if(first == "Settings") return 2;
    if(first == "Content") return 3;
    return 1;
};

// 更新面包屑
var updateBreadcrumb = function(pathArray){
    bread.Items.Clear();
    for(i=1;#pathArray;1){
        var bi = AntdUI.BreadcrumbItem();
        bi.Text = pathArray[i];
        bread.Items.Add(bi);
    }
};

// 在当前真实存在的 tabs.Pages 中按 Name 查找。
// 这是本示例最关键的函数:
// 1. 不用 openTabs 缓存表,避免关闭后留下旧引用。
// 2. 不用 Text 查找,因为不同菜单可能同名。
// 3. 不主要依赖 Tag 比较,避免 .NET object/string 互操作细节。
var findTabPageByTag = function(tag){
    var tabName = makeTabName(tag);
    var cnt = tabs.Pages.Count;           // 预计算 count
    for(i=0; cnt-1; 1){
        var page = tabs.Pages.Item(i);    // ✅ 圆括号调用 Item(i)
        if(page && page.Name == tabName){
            return page;
        }
    }
    return null;
};



// 在当前标签页中创建演示内容
var addDemoContent = function(page, pathArray, pageType){
    var pathStr = string.join(pathArray, " / ");
    var title = pathArray[#pathArray];

    var lbl = AntdUI.Label();
    lbl.Text = title;
    lbl.Font = fontTitle;
    lbl.ForeColor = 0xFF1890FF;
    lbl.SetBounds(40, 40, 500, 40);
    page.Controls.Add(lbl);

    var lblPath = AntdUI.Label();
    lblPath.Text = "Path: " + pathStr;
    lblPath.Font = fontTip;
    lblPath.ForeColor = 0xFF888888;
    lblPath.SetBounds(40, 90, 650, 24);
    page.Controls.Add(lblPath);

    if(pageType == 1){
        var input = AntdUI.Input();
        input.PlaceholderText = "Enter something for " + title;
        input.Font = fontNormal;
        input.SetBounds(40, 140, 340, 42);
        page.Controls.Add(input);

        var btn = AntdUI.Button();
        btn.Text = "Submit";
        btn.Type = AntdUI.TTypeMini.Primary;
        btn.Font = fontNormal;
        btn.SetBounds(40, 200, 120, 40);
        page.Controls.Add(btn);

        var lblResult = AntdUI.Label();
        lblResult.Text = "Result will appear here";
        lblResult.Font = fontTip;
        lblResult.ForeColor = 0xFFAAAAAA;
        lblResult.SetBounds(180, 200, 450, 40);
        lblResult.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
        page.Controls.Add(lblResult);

        btn.Click = function(s, e){
            var val = input.Text;
            if(val && #val){
                lblResult.Text = "✓ Submitted: " + val;
                lblResult.ForeColor = 0xFF52C41A;
                AntdUI.Message.success(baseForm, title + " — " + val);
            } else {
                lblResult.Text = "✗ Please enter some text first";
                lblResult.ForeColor = 0xFFFF4D4F;
            }
        };
    }
    elseif(pageType == 2){
        var alert = AntdUI.Alert();
        alert.Text = "这是一个 Settings 配置页面,下方可输入多行备注信息。";
        alert.Icon = AntdUI.TType.Success;
        alert.SetBounds(40, 140, 640, 45);
        page.Controls.Add(alert);

        var inputMulti = AntdUI.Input();
        inputMulti.Multiline = true;
        inputMulti.PlaceholderText = "请输入多行备注...";
        inputMulti.Font = fontNormal;
        inputMulti.SetBounds(40, 200, 640, 130);
        page.Controls.Add(inputMulti);

        var btn = AntdUI.Button();
        btn.Text = "保存备注";
        btn.Type = AntdUI.TTypeMini.Primary;
        btn.Font = fontNormal;
        btn.SetBounds(40, 345, 130, 40);
        page.Controls.Add(btn);

        var lblResult = AntdUI.Label();
        lblResult.Text = "备注内容将会显示在这里";
        lblResult.Font = fontTip;
        lblResult.ForeColor = 0xFFAAAAAA;
        lblResult.SetBounds(180, 345, 500, 40);
        lblResult.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
        page.Controls.Add(lblResult);

        btn.Click = function(s, e){
            var val = inputMulti.Text;
            if(val && #val){
                lblResult.Text = "✓ 备注已保存,长度: " ++ #val;
                lblResult.ForeColor = 0xFF52C41A;
                AntdUI.Message.success(baseForm, title + " — 备注保存成功");
            } else {
                lblResult.Text = "✗ 备注不能为空";
                lblResult.ForeColor = 0xFFFF4D4F;
            }
        };
    }
    elseif(pageType == 3){
        var chkPublish = AntdUI.Checkbox();
        chkPublish.Text = "发布文章";
        chkPublish.Font = fontNormal;
        chkPublish.Checked = true;
        chkPublish.SetBounds(40, 140, 200, 30);
        page.Controls.Add(chkPublish);

        var chkNotify = AntdUI.Checkbox();
        chkNotify.Text = "发送通知";
        chkNotify.Font = fontNormal;
        chkNotify.Checked = false;
        chkNotify.SetBounds(40, 180, 200, 30);
        page.Controls.Add(chkNotify);

        var btn = AntdUI.Button();
        btn.Text = "执行操作";
        btn.Type = AntdUI.TTypeMini.Primary;
        btn.Font = fontNormal;
        btn.SetBounds(40, 230, 130, 40);
        page.Controls.Add(btn);

        var lblResult = AntdUI.Label();
        lblResult.Text = "操作结果将显示在这里";
        lblResult.Font = fontTip;
        lblResult.ForeColor = 0xFFAAAAAA;
        lblResult.SetBounds(180, 230, 500, 40);
        lblResult.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
        page.Controls.Add(lblResult);

        btn.Click = function(s, e){
            var publish = chkPublish.Checked;
            var notify = chkNotify.Checked;
            var msg = "";
            if(publish && notify) msg = "已发布文章并发送通知";
            elseif(publish) msg = "已发布文章(未通知)";
            elseif(notify) msg = "已发送通知(未发布)";
            else msg = "未执行任何操作";
            lblResult.Text = "✓ " + msg;
            lblResult.ForeColor = 0xFF52C41A;
            AntdUI.Message.info(baseForm, title + " — " + msg);
        };
    }

    var lblHint = AntdUI.Label();
    lblHint.Text = "说明:重复点击左侧同一叶子菜单,应只激活当前标签页,不应重复新建。";
    lblHint.Font = fontTip;
    lblHint.ForeColor = 0xFFCCCCCC;
    lblHint.SetBounds(40, 430, 680, 24);
    page.Controls.Add(lblHint);
};

var openOrSwitchTab = function(tag, pathArray){
    tag = tostring(tag);

    var page = findTabPageByTag(tag);
    if(page){
        tabs.SelectedTab = page;
        return page;
    }

    page = AntdUI.TabPage();
    page.Text = pathArray[#pathArray];
    page.Name = makeTabName(tag);
    page.Tag = tag;
    addDemoContent(page, pathArray, getPageType(tag));
    tabs.Pages.Add(page);
    tabs.SelectedTab = page;
    return page;
};


// ============================================================
// 联动逻辑
// ============================================================

// Menu → Tabs + Breadcrumb
menu.SelectChanged = function(sender, e){
    var item = e.Value;
    if(!item || !item.Tag) return;

    var tag = tostring(item.Tag);
    var path = string.split(tag, "/");

    // 仅叶子节点创建/激活标签页。
    if(item.Sub.Count == 0){
        openOrSwitchTab(tag, path);
    }

    updateBreadcrumb(path);
};

// Tabs 切换 → 同步面包屑
tabs.SelectedIndexChanged = function(sender, e){
    var page = sender.SelectedTab;
    if(!page || !page.Tag) return;
    var path = string.split(tostring(page.Tag), "/");
    updateBreadcrumb(path);
};

// Breadcrumb 点击 → Message 提示
bread.ItemClick = function(sender, e){
    var item = e.getItem();
    if(item){
        AntdUI.Message.success(baseForm, "You clicked breadcrumb: «" + item.Text + "»");
    }
};

// ---------- 释放 ----------
winform.onClose = function(){
    fontLogo.Dispose();
    fontTitle.Dispose();
    fontNormal.Dispose();
    fontTip.Dispose();
};

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

最新回复 (4)
  • 我高兴 11小时前
    0 2
    持续收藏中
  • 光庆 10小时前
    0 3
    @nanyi 期待都完善后,封装一个完整的库。
  • nanyi 10小时前
    0 4
    光庆 @nanyi 期待都完善后,封装一个完整的库。
    你说的应该是组装成一个完整的示例吧。库的话,官方有扩展库了,但antdui一直在更新,就是有些函数不全,需要补充。
  • Mr_MAO 10小时前
    0 5
    👍👍👍
返回