目前使用 paozhu全家桶开发企业管理后台,遇到的需要后台功能也顺手添加了 paozhu 对AI还是非常友好,基本上可以让AI在paozhu框架基础上生成立即,马上可以使用后台。
你一行代码都不用写,先把系统设计文档、数据库设计好,然后放到项目docx目录,然后AI读取并开工。
1 本次主要更新了ORM文件和view视图问题更新方式
./bin/paozhu_cli view 是更新所有需要更新的视图文件
./bin/paozhu_cli orm 更新数据库表结构到CPP文件, 是conf/orm.conf 里面 [dbtag] 的数据库标签
./bin/paozhu_cli json 是框架搜索libs目录下 struct 结构体生成 json_encode json_decode,或者根据json文件生成相应的 c++结构体,然后再生成json_encode json_decode 让json和结构体互相转化
2 添加webpay,支持微信和支付宝,阿里云和腾讯云短信接口
std::string out_trade_no = get_date("%Y%m%d%H%M%S") + rand_string(4, 4);
pay::wxpay wp;
wp.setAppId("你的微信APPID");
wp.setMchId("你的微信商户号");
wp.setPrivateKey("你的微信商户私钥路径或内容");
wp.setPublicKey("你的微信平台证书路径或内容");
wp.setApiKey("你的微信API密钥");
wp.setSerialNo("你的证书序列号");
wp.setOutTradeNo(out_trade_no);
wp.setDescription("测试商品");
wp.setTotalAmount("1");
wp.setNotifyUrl("https://yourdomain.com/wxpaynotify");
std::string response = wp.createNative();
client.output = response;
3 添加图表生成,满足企业后台开发需要,支持20种图表,算法来自echarts, 目前使用纯c++生成svg图片,添加了正态分布 九宫格 乔哈里视窗图等
// ============================================================
// 三、KernelDensity 测试(原始数据)
// ============================================================
client << "<h3>KernelDensity 测试</h3>";
{
std::ostringstream oss;
oss << std::fixed << std::setprecision(4);
std::vector<double> data = {1.0, 2.0, 2.5, 3.0, 3.5, 4.0, 5.0};
KernelDensity kde(data, 0);
oss << " 原始数据: ";
for (size_t i = 0; i < data.size(); ++i)
{
oss << data[i] << " ";
}
oss << "<br>";
oss << " density(2.5) = " << kde.density(2.5) << "<br>";
double q50 = kde.quantile(0.5);
oss << " quantile(0.5) = " << q50 << " (data range: " << kde.dataMin() << " ~ " << kde.dataMax() << ")<br>";
oss << " generateCurve(10).size() = " << kde.generateCurve(10).size() << "<br>";
auto ci = kde.centralInterval(0.5);
oss << " centralInterval(0.5) = (" << ci.first << ", " << ci.second << ")<br><br>";
client << "<pre>" << oss.str() << "</pre>";
}
// ============================================================
// 四、LinearRegression 单元测试
// ============================================================
client << "<h3>LinearRegression 单元测试</h3>";
{
std::ostringstream oss;
oss << std::fixed << std::setprecision(4);
// Test 1: Simple linear regression y = 2x + 1
{
std::vector<std::vector<double>> data = {
{1, 3},
{2, 5},
{3, 7},
{4, 9},
{5, 11}};
auto result = LinearRegression::linear(data);
bool pass = std::abs(result.parameters.gradient - 2.0) < 0.01 && std::abs(result.parameters.intercept - 1.0) < 0.01;
oss << " " << (pass ? "PASS" : "FAIL") << ": linear y = 2x + 1, "
<< "a=" << result.parameters.gradient << " b=" << result.parameters.intercept << "<br>";
}
// Test 2: Linear through origin y = 3x
{
std::vector<std::vector<double>> data = {
{1, 3},
{2, 6},
{3, 9},
{4, 12},
{5, 15}};
LinearRegression::Config config;
config.method = LinearRegression::LINEAR_THROUGH_ORIGIN;
auto result = LinearRegression::run(data, config);
bool pass = std::abs(result.parameters.gradient - 3.0) < 0.01;
oss << " " << (pass ? "PASS" : "FAIL") << ": linear through origin y = 3x, "
<< "a=" << result.parameters.gradient << "<br>";
}
// Test 3: Exponential regression y = 2 * e^(0.5*x)
{
std::vector<std::vector<double>> data;
for (int i = 1; i <= 10; ++i)
{
data.push_back({static_cast<double>(i), 2.0 * std::exp(0.5 * i)});
}
auto result = LinearRegression::exponential(data);
bool pass = std::abs(result.parameters.gradient - 0.5) < 0.05 && std::abs(result.parameters.intercept - 2.0) < 0.5;
oss << " " << (pass ? "PASS" : "FAIL") << ": exponential y = 2e^(0.5x), "
<< "a=" << result.parameters.intercept << " b=" << result.parameters.gradient << "<br>";
}
// Test 4: Logarithmic regression y = 1 + 2*ln(x)
{
std::vector<std::vector<double>> data;
for (int i = 1; i <= 10; ++i)
{
data.push_back({static_cast<double>(i), 1.0 + 2.0 * std::log(i)});
}
auto result = LinearRegression::logarithmic(data);
bool pass = std::abs(result.parameters.intercept - 1.0) < 0.01 && std::abs(result.parameters.gradient - 2.0) < 0.01;
oss << " " << (pass ? "PASS" : "FAIL") << ": logarithmic y = 1 + 2ln(x), "
<< "a=" << result.parameters.intercept << " b=" << result.parameters.gradient << "<br>";
}
// Test 5: Polynomial regression y = x^2
{
std::vector<std::vector<double>> data;
for (int i = 0; i <= 5; ++i)
{
data.push_back({static_cast<double>(i), static_cast<double>(i * i)});
}
auto result = LinearRegression::polynomial(data, 2);
bool pass = result.parameters.coefficients.size() == 3 && std::abs(result.parameters.coefficients[2] - 1.0) < 0.01;
oss << " " << (pass ? "PASS" : "FAIL") << ": polynomial y = x^2, "
<< "a2=" << result.parameters.coefficients[2] << "<br>";
}
// Test 6: Real-world data (ECharts example)
{
std::vector<std::vector<double>> data = {
{1, 4862.4},
{2, 5294.7},
{3, 5934.5},
{4, 7171.0},
{5, 8964.4},
{6, 10202.2},
{7, 11962.5},
{8, 14928.3},
{9, 16909.2},
{10, 18547.9},
{11, 21617.8},
{12, 26638.1},
{13, 34634.4},
{14, 46759.4},
{15, 58478.1},
{16, 67884.6},
{17, 74462.6},
{18, 79395.7}};
auto result = LinearRegression::exponential(data);
bool pass = result.points.size() == 18;
oss << " " << (pass ? "PASS" : "FAIL") << ": real-world exponential (18 points), "
<< "expression=" << result.expression << "<br>";
}
oss << "<br>";
client << "<pre>" << oss.str() << "</pre>";
}
// ============================================================
// 五、Clustering 单元测试
// ============================================================
client << "<h3>Clustering 单元测试</h3>";
{
std::ostringstream oss;
oss << std::fixed << std::setprecision(4);
// Test 1: Two clearly separated clusters
{
std::vector<std::vector<double>> data = {
{0.1, 0.2},
{0.2, 0.1},
{0.3, 0.3},
{0.1, 0.4},
{0.5, 0.2},
{9.8, 9.9},
{9.9, 9.8},
{10.1, 10.0},
{10.0, 10.2},
{9.7, 10.1}};
auto result = ClusteringProcess::simpleKMeans(data, 2);
int c0 = result.clusterAssigned[0].clusterIndex;
int c1 = result.clusterAssigned[5].clusterIndex;
bool pass = result.centroids.size() == 2 && c0 != c1;
oss << " " << (pass ? "PASS" : "FAIL") << ": 2-cluster separation (c0=" << c0 << " c1=" << c1 << ")<br>";
}
// Test 2: Three clusters
{
std::vector<std::vector<double>> data = {
{0.1, 0.2},
{0.2, 0.3},
{0.3, 0.1},
{5.0, 5.1},
{5.1, 5.0},
{4.9, 5.2},
{9.8, 9.9},
{9.9, 9.7},
{10.0, 10.1}};
auto result = ClusteringProcess::simpleKMeans(data, 3);
bool allNonEmpty = true;
for (size_t c = 0; c < result.pointsInCluster.size(); ++c)
{
if (result.pointsInCluster[c].size() < 1)
allNonEmpty = false;
}
bool pass = result.centroids.size() == 3 && allNonEmpty;
oss << " " << (pass ? "PASS" : "FAIL") << ": 3-cluster, all non-empty<br>";
}
// Test 3: Multi-dimensional data
{
std::vector<std::vector<double>> data = {
{1.0, 2.0, 3.0},
{1.1, 2.1, 3.1},
{10.0, 20.0, 30.0},
{10.1, 20.1, 30.1}};
auto result = ClusteringProcess::simpleKMeans(data, 2);
bool pass = result.centroids.size() == 2 && result.clusterAssigned[0].clusterIndex != result.clusterAssigned[2].clusterIndex;
oss << " " << (pass ? "PASS" : "FAIL") << ": 3D clustering<br>";
}
// Test 4: Edge case - tight data
{
std::vector<std::vector<double>> data = {
{1.0, 2.0},
{1.1, 2.1},
{0.9, 1.9}};
auto result = ClusteringProcess::simpleKMeans(data, 2);
bool pass = result.centroids.size() >= 1;
oss << " " << (pass ? "PASS" : "FAIL") << ": tight data edge case<br>";
}
oss << "<br>";
client << "<pre>" << oss.str() << "</pre>";
}
// ============================================================
// 六、SVG 图表输出
// ============================================================
client << "<hr><h2>========== SVG 图表 ==========</h2>";
client << "<p>21. 线性回归图 - 房价预测</p>";
{
SvgRegressionChart chart(800, 500);
chart.setTitle("Linear Regression - House Price Prediction");
chart.setData({{50, 150}, {60, 175}, {70, 210}, {80, 240}, {90, 270}, {100, 300}, {110, 330}, {120, 360}, {130, 390}, {140, 420}});
chart.setMethod(LinearRegression::LINEAR);
chart.setPointColor(SvgColor(84, 112, 198));
chart.setLineColor(SvgColor(238, 102, 102));
client << chart.render();
}
client << "<p>22. 指数回归图 - GDP 增长</p>";
{
SvgRegressionChart chart(800, 500);
chart.setTitle("Exponential Regression - GDP Growth");
chart.setData({{1, 2.1}, {2, 2.5}, {3, 3.1}, {4, 4.0}, {5, 5.2}, {6, 6.8}, {7, 8.9}, {8, 11.5}, {9, 14.8}, {10, 19.0}});
chart.setMethod(LinearRegression::EXPONENTIAL);
chart.setPointColor(SvgColor(60, 162, 131));
chart.setLineColor(SvgColor(238, 102, 102));
client << chart.render();
}
client << "<p>23. 对数回归图 - 学习曲线</p>";
{
SvgRegressionChart chart(800, 500);
chart.setTitle("Logarithmic Regression - Learning Curve");
chart.setData({{1, 20}, {2, 35}, {3, 45}, {4, 52}, {5, 57}, {6, 61}, {8, 67}, {10, 71}, {15, 78}, {20, 83}});
chart.setMethod(LinearRegression::LOGARITHMIC);
chart.setPointColor(SvgColor(250, 200, 88));
chart.setLineColor(SvgColor(238, 102, 102));
client << chart.render();
}
client << "<p>24. 多项式回归图 - 二次曲线</p>";
{
SvgRegressionChart chart(800, 500);
chart.setTitle("Polynomial Regression - Quadratic");
chart.setData({{0, 2.1}, {1, 7.7}, {2, 13.6}, {3, 27.2}, {4, 40.9}, {5, 61.1}, {6, 82.3}, {7, 108.5}, {8, 138.2}, {9, 170.0}});
chart.setMethod(LinearRegression::POLYNOMIAL);
chart.setPolynomialOrder(2);
chart.setPointColor(SvgColor(154, 96, 180));
chart.setLineColor(SvgColor(238, 102, 102));
client << chart.render();
}
client << "<p>25. 聚类散点图 - 客户分群 (3 类)</p>";
{
SvgClusteringChart chart(800, 500);
chart.setTitle("K-Means Clustering - Customer Segmentation");
chart.setData({{2, 1}, {3, 2}, {2.5, 1.5}, {4, 3}, {3.5, 2.5}, {1.5, 1}, {2, 2.5}, {3, 1.5}, {12, 8}, {15, 10}, {14, 7}, {13, 9}, {16, 11}, {11, 8}, {15, 8.5}, {14, 10}, {45, 25}, {50, 30}, {48, 28}, {52, 32}, {55, 30}, {47, 26}, {50, 27}, {53, 31}});
chart.setClusterCount(3);
chart.setPointSize(7);
chart.setCentroidSize(12);
client << chart.render();
}
client << "<p>26. 聚类散点图 - 4 类</p>";
{
SvgClusteringChart chart(800, 500);
chart.setTitle("K-Means Clustering - 4 Clusters");
chart.setData({{5, 5}, {6, 4}, {4, 6}, {5, 7}, {6, 5}, {7, 4}, {4, 5}, {5, 25}, {6, 26}, {4, 24}, {5, 27}, {7, 25}, {6, 24}, {4, 26}, {25, 5}, {26, 4}, {24, 6}, {25, 7}, {27, 5}, {26, 6}, {24, 5}, {25, 25}, {26, 26}, {24, 24}, {25, 27}, {27, 25}, {26, 24}, {24, 26}});
chart.setClusterCount(4);
chart.setPointSize(7);
chart.setCentroidSize(12);
client << chart.render();
}
client << "<p>27. 多元线性回归 - 房价预测(面积+卧室数+房龄)</p>";
{
SvgRegressionChart chart(800, 500);
chart.setTitle("Multivariate Linear Regression - House Price");
chart.setData({{60, 2, 20, 180},
{80, 2, 15, 230},
{100, 3, 10, 310},
{120, 3, 8, 360},
{140, 3, 5, 420},
{160, 4, 15, 440},
{180, 4, 12, 500},
{200, 4, 10, 560},
{90, 2, 25, 200},
{110, 3, 18, 290},
{130, 3, 20, 340},
{150, 4, 8, 430},
{170, 4, 6, 490},
{190, 4, 5, 530},
{70, 2, 30, 160},
{85, 3, 22, 250},
{105, 3, 12, 320},
{125, 3, 7, 380},
{145, 4, 10, 410},
{165, 4, 8, 470}});
chart.setMethod(LinearRegression::MULTIVARIATE_LINEAR);
chart.setPointColor(SvgColor(84, 112, 198));
chart.setLineColor(SvgColor(238, 102, 102));
chart.setPointSize(6);
client << chart.render();
}
4 添加pzword html转word(docx格式) word(docx格式)到html, 支持文字颜色 大小 表格和图片简单核心功能读写
server_loaclvar &static_server_var = get_server_global_var();
if (static_server_var.config_path.size() < 5)
{
client << "<p> static_server_var.config_path empty </p>";
return "";
}
std::string file_conf = dir_name(static_server_var.config_path);
if (file_conf.size() > 0 && file_conf.back() != '/')
{
file_conf.push_back('/');
}
file_conf.append("docs/");
std::string zipfile;
zipfile = file_conf + "ww.docx";
client << "<p>=== Reading " << zipfile << " ===</p></p>";
pz::word pzw;
if (!pzw.read(zipfile))
{
client << "Read error: " << pzw.error_msg;
client << "Trying to read from unzipped directory...";
if (!pzw.read_from_unzipped("."))
{
client << "Read from unzipped error: " << pzw.error_msg;
return "";
}
else
{
client << "Read from unzipped directory success";
}
}
else
{
client << "Read from docx file success";
}
std::string html = pzw.to_html();
std::ofstream html_file(file_conf + "word.html");
if (html_file)
{
html_file << html;
html_file.close();
client << "\n=== HTML saved to word.html ===";
}
else
{
client << "Error: Unable to write word.html";
}
pz::word pzww;
if (!pzww.read_html(file_conf + "word.html"))
{
client << "Read HTML error: " << pzww.error_msg;
return "";
}
if (!pzww.write(file_conf + "www.docx"))
{
client << "Write DOCX error: " << pzww.error_msg;
return "";
}
client << "<p>Successfully wrote www.docx</p>";
client << html;
5 支持验证码和图片绘文字功能
6 支持SSE 收发,目前可以使用deepseek api
7 添加zip文件 压缩和解压
8 添加新的admin后台,目前是演示,以后慢慢使用新的后台
更多可以看官方地址
https://github.com/hggq/paozhu