94分控件

This commit is contained in:
2026-08-08 16:55:22 +08:00
parent b21043e3b8
commit d289f8d6e2
14 changed files with 1115 additions and 302 deletions
+79 -3
View File
@@ -10,6 +10,7 @@ struct Config {
int count{3};
bool enabled{true};
std::string color{"#336699"};
std::string read_only{"fixed"};
};
}
namespace adminive {
@@ -17,18 +18,24 @@ template <>
struct Type_Descriptor<view_test::Config> {
static auto get() {
using T = view_test::Config;
return object<T>("view_config", "View Config", ADMINIVE_FIELD(T, name).editable().creatable().label("Name").text_input(), ADMINIVE_FIELD(T, count).editable().creatable().label("Count").number_input(), ADMINIVE_FIELD(T, enabled).editable().creatable().label("Enabled").boolean_input(), ADMINIVE_FIELD(T, color).editable().creatable().label("Color").color_input());
return object<T>("view_config", "View Config", ADMINIVE_FIELD(T, name).editable().creatable().label("Name").text_input(), ADMINIVE_FIELD(T, count).editable().creatable().label("Count").number_input(), ADMINIVE_FIELD(T, enabled).editable().creatable().label("Enabled").boolean_input(), ADMINIVE_FIELD(T, color).editable().creatable().label("Color").color_input(), ADMINIVE_FIELD(T, read_only).label("Read Only").text_input());
}
};
template <>
struct Type_View_Descriptor<view_test::Config> {
static Form_View edit() {
using T = view_test::Config;
return edit_form<T>(vertical(group("Identity", horizontal(use<&T::name>(), use<&T::enabled>())), grid(2, use<&T::count>(), card("Appearance", use<&T::color>())), flow(card("Name Card", use<&T::name>()), card("Count Card", use<&T::count>())), tabs(tab("General", use<&T::name>(), use<&T::count>()), tab("Visual", use<&T::color>())))).submit("Save");
return edit_form<T>(vertical(group("Identity", horizontal(use<&T::name>(), use<&T::enabled>(), use<&T::read_only>())), grid(2, use<&T::count>(), card("Appearance", use<&T::color>())), flow(card("Name Card", use<&T::name>()), card("Count Card", use<&T::count>())), tabs(tab("General", use<&T::name>(), use<&T::count>()), tab("Visual", use<&T::color>())))).submit("Save");
}
static Table_View table() {
using T = view_test::Config;
return table_view<T>(column<&T::name>("Name").search().fix(Table_Fixed::left), column<&T::count>("Count").sort(), column<&T::enabled>("Enabled").filter(), column<&T::color>("Color")).titled("Configs").default_sort("count", true).create_layout(grid(2, use<&T::name>(), use<&T::count>(), use<&T::enabled>(), use<&T::color>())).edit_layout(vertical(use<&T::name>(), horizontal(use<&T::count>(), use<&T::enabled>()), use<&T::color>()));
return table_view<T>(column<&T::name>("Name").search().fix(Table_Fixed::left), column<&T::count>("Count").sort(), column<&T::enabled>("Enabled").filter(), column<&T::color>("Color")).titled("Configs").default_sort("count", true).create_layout(grid(2, use<&T::name>(), use<&T::count>(), use<&T::enabled>(), use<&T::color>())).edit_layout(vertical(use<&T::name>(), horizontal(use<&T::count>(), use<&T::enabled>()), use<&T::color>(), use<&T::read_only>()));
}
static Collection_View collection() {
Collection_View result;
result.table = table();
result.table.name = "view_config_collection";
return result;
}
};
}
@@ -59,6 +66,12 @@ int main() {
assert(form_amis.at("body").at(2).at("items").at(1).at("type") == "container");
assert(form_amis.at("body").at(2).at("items").at(0).at("body").at(0).at("type") == "card");
assert(form_amis.at("body").at(3).at("type") == "tabs");
assert(form_amis.at("data").at("read_only") == "fixed");
assert(form_amis.at("api").at("data").at("name") == "${name}");
assert(form_amis.at("api").at("data").at("count") == "${count}");
assert(form_amis.at("api").at("data").at("enabled") == "${enabled}");
assert(form_amis.at("api").at("data").at("color") == "${color}");
assert(!form_amis.at("api").at("data").contains("read_only"));
const auto table_view = adminive::describe_table_view<Config>();
adminive::validate_table_view<Config>(table_view);
const auto table_json = adminive::to_view_json<Json, Config>(table_view);
@@ -76,6 +89,14 @@ int main() {
const auto composition_amis = adminive::to_amis_composition_schema<Json>(composition, {{"form", form_amis}, {"table", Json{{"type", "tpl"}, {"tpl", "table"}}}});
assert(composition_amis.at("body").at(0).at("type") == "tpl");
assert(composition_amis.at("body").at(1).at("type") == "grid");
const auto five_columns = adminive::composition_view("five_columns", adminive::compose::horizontal(adminive::compose::slot("a"), adminive::compose::slot("b"), adminive::compose::slot("c"), adminive::compose::slot("d"), adminive::compose::slot("e")));
const auto five_columns_amis = adminive::to_amis_composition_schema<Json>(five_columns, {{"a", Json{{"type", "tpl"}}}, {"b", Json{{"type", "tpl"}}}, {"c", Json{{"type", "tpl"}}}, {"d", Json{{"type", "tpl"}}}, {"e", Json{{"type", "tpl"}}}});
const auto& five_widths = five_columns_amis.at("body").at(0).at("columns");
assert(five_widths.at(0).at("md") == 3);
assert(five_widths.at(1).at("md") == 3);
assert(five_widths.at(2).at("md") == 2);
assert(five_widths.at(3).at("md") == 2);
assert(five_widths.at(4).at("md") == 2);
const auto flow_composition = adminive::composition_view("flow_page", adminive::compose::flow(adminive::compose::slot("left"), adminive::compose::slot("right")));
const auto flow_amis = adminive::to_amis_composition_schema<Json>(flow_composition, {{"left", Json{{"type", "tpl"}, {"tpl", "left"}}}, {"right", Json{{"type", "tpl"}, {"tpl", "right"}}}});
assert(flow_amis.at("body").at(0).at("type") == "flex");
@@ -92,6 +113,12 @@ int main() {
assert(frontend_composition_json.at("body").at("kind") == "frontend");
const auto frontend_composition_amis = adminive::to_amis_composition_schema<Json>(frontend_composition, {{"left", Json{{"type", "tpl"}, {"tpl", "left"}}}, {"right", Json{{"type", "tpl"}, {"tpl", "right"}}}});
assert(frontend_composition_amis.at("body").at(0).at("className") == "adminive-frontend-placement");
const std::vector<adminive::Composition_Slot_Contract> slot_contracts{{"left", "amis_schema", "/left/descriptor", "/left/view", "/left/data", "/left/amis"}, {"right", "amis_schema", "/right/descriptor", "/right/view", "/right/data", "/right/amis"}};
const auto manifest = adminive::to_composition_manifest_json<Json>(frontend_composition, slot_contracts, {{"left", Json{{"type", "tpl"}, {"tpl", "left"}}}, {"right", Json{{"type", "tpl"}, {"tpl", "right"}}}});
assert(manifest.at("protocol") == "adminive.composition-manifest");
assert(manifest.at("view").at("body").at("kind") == "frontend");
assert(manifest.at("slots").at("left").at("view_api") == "/left/view");
assert(manifest.at("slots").at("right").at("schema").at("tpl") == "right");
const auto frontend_form = adminive::edit_form<Config>(adminive::frontend(adminive::list(adminive::use<&Config::name>(), adminive::use<&Config::count>())));
const auto frontend_form_json = adminive::to_view_json<Json, Config>(frontend_form);
assert(frontend_form_json.at("body").at("kind") == "frontend");
@@ -101,6 +128,18 @@ int main() {
assert(table_amis.at("body").at(0).at("columns").at(1).at("searchable") == true);
assert(table_amis.at("body").at(0).at("columns").at(2).at("sortable") == true);
assert(table_amis.at("body").at(0).at("columns").at(3).at("filterable") == true);
const auto& create_submit_data = table_amis.at("body").at(0).at("headerToolbar").at(2).at("dialog").at("body").at("api").at("data");
assert(create_submit_data.at("name") == "${name}");
assert(create_submit_data.at("count") == "${count}");
assert(create_submit_data.at("enabled") == "${enabled}");
assert(create_submit_data.at("color") == "${color}");
assert(!create_submit_data.contains("read_only"));
const auto& edit_submit_data = table_amis.at("body").at(0).at("columns").back().at("buttons").at(0).at("dialog").at("body").at("api").at("data");
assert(edit_submit_data.at("name") == "${name}");
assert(edit_submit_data.at("count") == "${count}");
assert(edit_submit_data.at("enabled") == "${enabled}");
assert(edit_submit_data.at("color") == "${color}");
assert(!edit_submit_data.contains("read_only"));
const auto list_amis = adminive::to_amis_list_schema<Json, Config>("/configs", table_view, Json{{"title", "${name}"}});
assert(list_amis.at("body").at(0).at("mode") == "list");
assert(list_amis.at("body").at(0).at("id") == "view_config_table_crud_list");
@@ -116,6 +155,36 @@ int main() {
assert(cards_amis.at("body").at(0).at("columnsCount") == 2);
assert(cards_amis.at("body").at(0).at("card").at("actions").size() == 2);
assert(cards_amis.at("body").at(0).at("card").at("actions").at(1).at("reload") == "view_config_table_crud_cards");
const auto item_view = adminive::collection_item<&Config::name>().subtitle<&Config::color>().accent<&Config::color>().body<&Config::count, &Config::enabled>();
const auto collection_view = adminive::describe_collection_view<Config>();
const auto labeled_collection = collection_view.id_title("Record").create_title("Add").edit_title("Change").delete_title("Remove").actions_title("Operations").confirm_title("Apply").delete_confirmation("Remove record?").status_title("Status");
assert(labeled_collection.table.id_label == "Record");
assert(labeled_collection.table.create_label == "Add");
assert(labeled_collection.table.edit_label == "Change");
assert(labeled_collection.table.delete_label == "Remove");
assert(labeled_collection.table.actions_label == "Operations");
assert(labeled_collection.table.confirm_label == "Apply");
assert(labeled_collection.table.delete_confirm == "Remove record?");
assert(labeled_collection.table.view_status_label == "Status");
const auto semantic_list_view = collection_view.as_list(item_view);
const auto semantic_list_json = adminive::to_view_json<Json, Config>(semantic_list_view);
assert(semantic_list_json.at("kind") == "collection");
assert(semantic_list_json.at("mode") == "list");
assert(semantic_list_json.at("item").at("title_field") == "name");
assert(semantic_list_json.at("item").at("fields").at(0) == "count");
const auto semantic_list_amis = adminive::to_amis_collection_schema<Json, Config>("/configs", semantic_list_view);
assert(semantic_list_amis.at("body").at(0).at("id") == "view_config_collection_crud_list");
assert(semantic_list_amis.at("body").at(0).at("listItem").at("title") == "${name}");
assert(semantic_list_amis.at("body").at(0).at("listItem").at("actions").at(1).at("reload") == "view_config_collection_crud_list");
const auto semantic_cards_view = collection_view.as_cards(item_view, 4);
const auto semantic_cards_json = adminive::to_view_json<Json, Config>(semantic_cards_view);
assert(semantic_cards_json.at("mode") == "cards");
assert(semantic_cards_json.at("cards_columns") == 4);
const auto semantic_cards_amis = adminive::to_amis_collection_schema<Json, Config>("/configs", semantic_cards_view);
assert(semantic_cards_amis.at("body").at(0).at("id") == "view_config_collection_crud_cards");
assert(semantic_cards_amis.at("body").at(0).at("columnsCount") == 4);
const auto semantic_table_json = adminive::to_view_json<Json, Config>(collection_view.as_table());
assert(semantic_table_json.at("mode") == "table");
adminive::Collection_Service<Config, Json, adminive::No_Lock> collection("/configs", {Config{"Alpha", 3, true, "#111111"}, Config{"Beta", 7, false, "#222222"}, Config{"Alphabet", 5, true, "#333333"}});
adminive::Collection_Query query;
query.fields["name"] = "alpha";
@@ -138,6 +207,13 @@ int main() {
query.fields["color"] = "#111111";
response = collection.list_response(query);
assert(response.status == 400);
bool invalid_manifest{};
try {
adminive::to_composition_manifest_json<Json>(frontend_composition, {adminive::Composition_Slot_Contract{"left", "amis_schema", {}, {}, {}, {}}}, {{"left", Json{{"type", "tpl"}}}});
} catch(const std::invalid_argument&) {
invalid_manifest = true;
}
assert(invalid_manifest);
bool invalid_grid{};
try {
adminive::validate_form_view<Config>(adminive::edit_form<Config>(adminive::grid(0, adminive::use<&Config::name>())));