一、背景介绍
最近在学习开源规则引擎EasyRule,然后发现目前没有合适的规则引擎界面,于是我准备用大模型来帮助我做一个EasyRule规则引擎可视化的UI配置界面,没想到大模型非常轻松的帮助我做了一个UI可视化配置界面,真的太强大了,一步步调教后,效果非常不错,如下所示:
非Vue版:
Vue.js版本:
二、如何做的
2.1、让大模型学习知识
1、首先我们访问ChatGPT,目前ChatGPT是每天有免费的使用的额度的,所以完全可以每天用用GPT,首先我把EasyRule这个开源项目下的ReadMe文档中的使用示例给了他,让他给我写篇文章,与我对它说
这个是开源项目easy rule规则引擎的使用说明的例子:First, define your rule..
Either in a declarative way using annotations:
@Rule(name = "weather rule", description = "if it rains then take an umbrella")
public class WeatherRule {
@Condition
public boolean itRains(@Fact("rain") boolean rain) {
return rain;
}
@Action
public void takeAnUmbrella() {
System.out.println("It rains, take an umbrella!");
}
}
Or in a programmatic way with a fluent API:
Rule weatherRule = new RuleBuilder()
.name("weather rule")
.description("if it rains then take an umbrella")
.when(facts -> facts.get("rain").equals(true))
.then(facts -> System.out.println("It rains, take an umbrella!"))
.build();
Or using an Expression Language:
Rule weatherRule = new MVELRule()
.name("weather rule")
.description("if it rains then take an umbrella")
.when("rain == true")
.then("System.out.println(\"It rains, take an umbrella!\");");
Or using a rule descriptor:
Like in the following weather-rule.yml example file:
name: "weather rule"
description: "if it rains then take an umbrella"
condition: "rain == true"
actions:
- "System.out.println(\"It rains, take an umbrella!\");"
MVELRuleFactory ruleFactory = new MVELRuleFactory(new YamlRuleDefinitionReader());
Rule weatherRule = ruleFactory.createRule(new FileReader("weather-rule.yml"));
2. Then, fire it!
public class Test {
public static void main(String[] args) {
// define facts
Facts facts = new Facts();
facts.put("rain", true);
// define rules
Rule weatherRule = ...
Rules rules = new Rules();
rules.register(weatherRule);
// fire rules on known facts
RulesEngine rulesEngine = new DefaultRulesEngine();
rulesEngine.fire(rules, facts);
}
}
This is the hello world of Easy Rules.
You can find other examples like the Shop, Airco or WebApp tutorials in the wiki.
。而我想基于这个例子给其他没有接触过的人将明白,并通过文章的形式让大家学会如何使用.
请你基于我的目标和例子,给我写篇文章
这样在这个聊天历史中,大模型就具备了这个知识和上下文。
2.2、第1次给大模型提出需求
接下来我问它这句话:
好,我想开发个easyrule的可视化的前端配置界面,在配置界面中可以配置这个规则的相关内容,通过简单的方式设置规则,然后生成对应的easyrule后端java的配置,你看看帮我实现下吧。前端用HTML文件和JS文件就行,不用vue和react,同时不要返回后端代码,只返回前端的,前端有某个按钮,单击生成,可以出现代码弹窗
然后大模型的第一次返回结果如下:
你可以使用纯 HTML 和 JavaScript 来创建一个简单的可视化配置界面。在这个界面中,用户可以输入规则的名称、描述、条件、动作,然后点击按钮生成相应的 Easy Rules Java 代码。生成的代码将显示在一个弹窗中,用户可以直接复制使用。
下面是实现这个功能的 HTML 和 JavaScript 代码:
1. HTML 代码(index.html)
html复制代码<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Easy Rules 可视化配置</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
}
label {
display: block;
margin: 10px 0 5px;
}
input[type="text"], textarea {
width: 100%;
padding: 8px;
margin-bottom: 10px;
}
button {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
/* 弹窗样式 */
#codeModal {
display: none;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
padding: 20px;
background-color: white;
border: 2px solid #333;
z-index: 1000;
}
#codeModal pre {
white-space: pre-wrap;
word-wrap: break-word;
background-color: #f4f4f4;
padding: 15px;
border: 1px solid #ddd;
}
#closeModal {
margin-top: 10px;
padding: 8px;
background-color: #f44336;
color: white;
border: none;
cursor: pointer;
}
</style>
</head>
<body>
<h2>Easy Rules 可视化配置界面</h2>
<!-- 表单部分 -->
<form id="ruleForm">
<label for="name">规则名称:</label>
<input type="text" id="name" placeholder="请输入规则名称">
<label for="description">规则描述:</label>
<input type="text" id="description" placeholder="请输入规则描述">
<label for="condition">条件 (e.g., "rain == true"):</label>
<input type="text" id="condition" placeholder="请输入条件">
<label for="action">动作 (e.g., "System.out.println('Take an umbrella!')"):</label>
<textarea id="action" rows="4" placeholder="请输入Java动作代码"></textarea>
<button type="button" id="generateCode">生成代码</button>
</form>
<!-- 弹窗部分 -->
<div id="codeModal">
<h3>生成的 Java 规则代码:</h3>
<pre id="generatedCode"></pre>
<button id="closeModal">关闭</button>
</div>
<script src="script.js"></script>
</body>
</html>
2. JavaScript 代码(script.js)
javascript复制代码// 获取表单元素
const nameInput = document.getElementById('name');
const descriptionInput = document.getElementById('description');
const conditionInput = document.getElementById('condition');
const actionInput = document.getElementById('action');
// 获取按钮和弹窗相关元素
const generateButton = document.getElementById('generateCode');
const codeModal = document.getElementById('codeModal');
const generatedCodePre = document.getElementById('generatedCode');
const closeModalButton = document.getElementById('closeModal');
// 点击生成按钮时生成代码并显示弹窗
generateButton.addEventListener('click', function () {
// 获取输入的值
const ruleName = nameInput.value;
const ruleDescription = descriptionInput.value;
const ruleCondition = conditionInput.value;
const ruleAction = actionInput.value;
// 生成规则的 Java 代码
const generatedCode = `
@Rule(name = "${ruleName}", description = "${ruleDescription}")
public class GeneratedRule {
@Condition
public boolean evaluate(@Fact("fact") Object fact) {
return ${ruleCondition};
}
@Action
public void execute() {
${ruleAction};
}
}
`;
// 将生成的代码放入弹窗
generatedCodePre.textContent = generatedCode;
// 显示弹窗
codeModal.style.display = 'block';
});
// 关闭弹窗
closeModalButton.addEventListener('click', function () {
codeModal.style.display = 'none';
});
3. 功能说明
a. 输入部分
用户可以在页面上输入以下内容:
- 规则名称
- 规则描述
- 规则条件(例如
rain == true
) - 动作(例如
System.out.println("It rains, take an umbrella!");
)
b. 生成规则代码
点击“生成代码”按钮后,会生成如下格式的 Java 规则代码并在弹窗中显示:
java复制代码@Rule(name = "yourRuleName", description = "yourRuleDescription")
public class GeneratedRule {
@Condition
public boolean evaluate(@Fact("fact") Object fact) {
return yourCondition;
}
@Action
public void execute() {
yourAction;
}
}
c. 弹窗显示
生成的代码会通过弹窗展示,用户可以直接复制。点击“关闭”按钮可以隐藏弹窗。
4. 使用说明
- 将
index.html
文件和script.js
文件保存在同一目录下。 - 用浏览器打开
index.html
文件,就可以看到可视化配置界面。 - 输入规则的相关信息后,点击“生成代码”按钮,系统会自动生成对应的 Java 规则代码并弹窗显示,方便用户复制。
5. 扩展建议
- 代码导出:可以添加一个按钮将生成的代码导出为文件,方便后续使用。
- 表单验证:可以加入输入校验,确保用户输入正确的 Java 表达式。
- 多种生成方式:扩展代码生成方式,如 YAML、流式 API 等。
这样一个简单、直观的前端界面,能有效帮助用户无需编写代码就能快速生成 Easy Rules 规则代码,并且可以直接复制到后端项目中使用。
经过了第一次的运行后,效果如下:
2.3、第2次给大模型提出需求
接下来我问它这句话:
太棒了,我想把条件那块做成类似QueryBuilder的效果,不需要用户自己手动输入条件,而是选择的方式,你看看修改下
于是大模型的又返回了新的结果:
为了让条件部分更加友好,可以将条件输入变成类似 QueryBuilder 的形式,让用户通过选择字段、运算符和输入值来生成条件,而不是手动输入条件表达式。下面我会通过修改前端的 index.html
和 script.js
,实现这个效果。
1. 修改思路
- 条件部分 将由三个部分组成:
- 字段选择:用户可以选择预定义的字段(例如
rain
、temperature
等)。 - 运算符选择:用户可以选择运算符(例如
==
,!=
,>
,<
等)。 - 值输入:用户可以输入具体的值(例如
true
、30
等)。
- 字段选择:用户可以选择预定义的字段(例如
- 当用户选择完字段、运算符和输入值后,系统将根据这些信息自动生成条件。
2. 修改后的 HTML 代码
html复制代码<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Easy Rules 可视化配置</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
}
label {
display: block;
margin: 10px 0 5px;
}
input[type="text"], textarea, select {
width: 100%;
padding: 8px;
margin-bottom: 10px;
}
button {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
/* 弹窗样式 */
#codeModal {
display: none;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
padding: 20px;
background-color: white;
border: 2px solid #333;
z-index: 1000;
}
#codeModal pre {
white-space: pre-wrap;
word-wrap: break-word;
background-color: #f4f4f4;
padding: 15px;
border: 1px solid #ddd;
}
#closeModal {
margin-top: 10px;
padding: 8px;
background-color: #f44336;
color: white;
border: none;
cursor: pointer;
}
</style>
</head>
<body>
<h2>Easy Rules 可视化配置界面</h2>
<!-- 表单部分 -->
<form id="ruleForm">
<label for="name">规则名称:</label>
<input type="text" id="name" placeholder="请输入规则名称">
<label for="description">规则描述:</label>
<input type="text" id="description" placeholder="请输入规则描述">
<!-- 条件部分:字段、运算符、值 -->
<label for="field">条件字段:</label>
<select id="field">
<option value="rain">rain</option>
<option value="temperature">temperature</option>
<option value="humidity">humidity</option>
</select>
<label for="operator">运算符:</label>
<select id="operator">
<option value="==">等于 (==)</option>
<option value="!=">不等于 (!=)</option>
<option value=">">大于 (>)</option>
<option value="<">小于 (<)</option>
<option value=">=">大于等于 (>=)</option>
<option value="<=">小于等于 (<=)</option>
</select>
<label for="value">条件值:</label>
<input type="text" id="value" placeholder="请输入条件值">
<label for="action">动作 (e.g., "System.out.println('Take an umbrella!')"):</label>
<textarea id="action" rows="4" placeholder="请输入Java动作代码"></textarea>
<button type="button" id="generateCode">生成代码</button>
</form>
<!-- 弹窗部分 -->
<div id="codeModal">
<h3>生成的 Java 规则代码:</h3>
<pre id="generatedCode"></pre>
<button id="closeModal">关闭</button>
</div>
<script src="script.js"></script>
</body>
</html>
3. 修改后的 JavaScript 代码(script.js)
javascript复制代码// 获取表单元素
const nameInput = document.getElementById('name');
const descriptionInput = document.getElementById('description');
const fieldInput = document.getElementById('field');
const operatorInput = document.getElementById('operator');
const valueInput = document.getElementById('value');
const actionInput = document.getElementById('action');
// 获取按钮和弹窗相关元素
const generateButton = document.getElementById('generateCode');
const codeModal = document.getElementById('codeModal');
const generatedCodePre = document.getElementById('generatedCode');
const closeModalButton = document.getElementById('closeModal');
// 点击生成按钮时生成代码并显示弹窗
generateButton.addEventListener('click', function () {
// 获取输入的值
const ruleName = nameInput.value;
const ruleDescription = descriptionInput.value;
const field = fieldInput.value;
const operator = operatorInput.value;
const value = valueInput.value;
const ruleAction = actionInput.value;
// 生成条件表达式
const condition = `${field} ${operator} ${value}`;
// 生成规则的 Java 代码
const generatedCode = `
@Rule(name = "${ruleName}", description = "${ruleDescription}")
public class GeneratedRule {
@Condition
public boolean evaluate(@Fact("fact") Object fact) {
return ${condition};
}
@Action
public void execute() {
${ruleAction};
}
}
`;
// 将生成的代码放入弹窗
generatedCodePre.textContent = generatedCode;
// 显示弹窗
codeModal.style.display = 'block';
});
// 关闭弹窗
closeModalButton.addEventListener('click', function () {
codeModal.style.display = 'none';
});
4. 功能说明
a. 条件输入部分
用户不再手动输入条件,而是通过选择来生成条件:
- 字段选择:通过下拉菜单选择字段(如
rain
,temperature
,humidity
等)。 - 运算符选择:通过下拉菜单选择条件运算符(如
==
,!=
,>
,<
等)。 - 值输入:用户手动输入条件值(如
true
,30
等)。
例如,如果用户选择了 rain == true
,系统会自动生成相应的条件表达式 rain == true
。
b. 生成规则代码
生成的 Java 代码示例:
java复制代码@Rule(name = "yourRuleName", description = "yourRuleDescription")
public class GeneratedRule {
@Condition
public boolean evaluate(@Fact("fact") Object fact) {
return rain == true;
}
@Action
public void execute() {
System.out.println("Take an umbrella!");
}
}
c. 弹窗显示
生成的代码会通过弹窗显示,用户可以直接复制并使用。点击“关闭”按钮后弹窗消失。
5. 使用说明
- 将
index.html
和script.js
文件保存在同一目录中。 - 使用浏览器打开
index.html
。 - 用户可以通过选择字段、运算符和输入值来生成条件,点击“生成代码”按钮后,自动生成对应的 Easy Rules Java 代码并通过弹窗显示。
6. 扩展建议
- 字段列表扩展:可以动态加载可用字段,支持自定义字段。
- 多条件支持:添加多条件支持,如 "AND" 和 "OR" 组合条件。
- 保存和导出功能:允许用户保存生成的规则为文件。
通过这样的方式,用户能够更加直观地创建条件,不需要手动输入 Java 表达式,大大简化了规则配置的复杂度。
我们看下第二次的效果:
2.4、第3次给大模型提出需求
接下来我问它这句话:
太强了,我想让这个界面变的好看一点,请你优化下CSS的样式,尤其是下拉框的样式,同时条件字段、运算符、条件值需要在一行显示。且支持多个条件进行并且的方式选择,从而形成条件组,在给我处理下吧
于是大模型的又返回了新的结果:
为了让界面变得更加美观,并且支持多个条件的组合(使用 "并且" 的方式),我将对 CSS 进行优化,尤其是 下拉框的样式 和 表单布局,同时实现多条件支持。这样用户可以选择多个条件来生成复杂的规则。
修改思路
- CSS 优化:下拉框美化,按钮样式调整,布局改进。
- 条件组:每个条件的字段、运算符和值在一行显示,并可以通过点击按钮添加更多条件。
- 多条件支持:使用“并且”的方式将条件组合起来生成规则。
1. 修改后的 HTML 代码
html复制代码<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Easy Rules 可视化配置</title>
<style>
body {
font-family: Arial, sans-serif;
padding: 20px;
background-color: #f7f7f7;
}
h2 {
color: #333;
}
label {
display: block;
margin: 10px 0 5px;
font-weight: bold;
}
.rule-group {
margin-bottom: 20px;
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.condition-row {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
}
select, input[type="text"], textarea {
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-color: #fff;
background-image: url('data:image/svg+xml;charset=US-ASCII,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4 5"><path fill="none" stroke="%23000" stroke-width=".8" d="M2 0L0 2h4zm0 5L0 3h4z"/></svg>');
background-repeat: no-repeat;
background-position: right 10px center;
background-size: 8px 10px;
padding-right: 20px;
}
button {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
button:hover {
background-color: #45a049;
}
.add-condition-btn {
margin-left: 10px;
background-color: #008CBA;
}
.remove-condition-btn {
margin-left: 10px;
background-color: #f44336;
}
/* 弹窗样式 */
#codeModal {
display: none;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
padding: 20px;
background-color: white;
border: 2px solid #333;
z-index: 1000;
width: 60%;
border-radius: 8px;
}
#codeModal pre {
white-space: pre-wrap;
word-wrap: break-word;
background-color: #f4f4f4;
padding: 15px;
border: 1px solid #ddd;
border-radius: 4px;
}
#closeModal {
margin-top: 10px;
padding: 8px;
background-color: #f44336;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
</head>
<body>
<h2>Easy Rules 可视化配置界面</h2>
<!-- 表单部分 -->
<div class="rule-group">
<form id="ruleForm">
<label for="name">规则名称:</label>
<input type="text" id="name" placeholder="请输入规则名称">
<label for="description">规则描述:</label>
<input type="text" id="description" placeholder="请输入规则描述">
<div id="conditions">
<!-- 动态添加条件组 -->
<div class="condition-row">
<select class="field">
<option value="rain">rain</option>
<option value="temperature">temperature</option>
<option value="humidity">humidity</option>
</select>
<select class="operator">
<option value="==">等于 (==)</option>
<option value="!=">不等于 (!=)</option>
<option value=">">大于 (>)</option>
<option value="<">小于 (<)</option>
<option value=">=">大于等于 (>=)</option>
<option value="<=">小于等于 (<=)</option>
</select>
<input type="text" class="value" placeholder="请输入条件值">
<button type="button" class="add-condition-btn">添加条件</button>
</div>
</div>
<label for="action">动作 (e.g., "System.out.println('Take an umbrella!')"):</label>
<textarea id="action" rows="4" placeholder="请输入Java动作代码"></textarea>
<button type="button" id="generateCode">生成代码</button>
</form>
</div>
<!-- 弹窗部分 -->
<div id="codeModal">
<h3>生成的 Java 规则代码:</h3>
<pre id="generatedCode"></pre>
<button id="closeModal">关闭</button>
</div>
<script src="script.js"></script>
</body>
</html>
2. 修改后的 JavaScript 代码(script.js)
javascript复制代码// 获取表单元素
const nameInput = document.getElementById('name');
const descriptionInput = document.getElementById('description');
const conditionsDiv = document.getElementById('conditions');
const actionInput = document.getElementById('action');
// 获取按钮和弹窗相关元素
const generateButton = document.getElementById('generateCode');
const codeModal = document.getElementById('codeModal');
const generatedCodePre = document.getElementById('generatedCode');
const closeModalButton = document.getElementById('closeModal');
// 添加条件按钮功能
conditionsDiv.addEventListener('click', function (e) {
if (e.target.classList.contains('add-condition-btn')) {
// 创建新的条件行
const conditionRow = document.createElement('div');
conditionRow.classList.add('condition-row');
conditionRow.innerHTML = `
<select class="field">
<option value="rain">rain</option>
<option value="temperature">temperature</option>
<option value="humidity">humidity</option>
</select>
<select class="operator">
<option value="==">等于 (==)</option>
<option value="!=">不等于 (!=)</option>
<option value=">">大于 (>)</option>
<option value="<">小于 (<)</option>
<option value=">=">大于等于 (>=)</option>
<option value="<=">小于等于 (<=)</option>
</select>
<input type="text" class="value" placeholder="请输入条件值">
<button type="button" class="remove-condition-btn">删除条件</button>
`;
conditionsDiv.appendChild(conditionRow);
}
// 删除条件按钮功能
if (e.target.classList.contains('remove-condition-btn')) {
e.target.parentElement.remove();
}
});
// 点击生成按钮时生成代码并显示弹窗
generateButton.addEventListener('click', function () {
const ruleName = nameInput.value;
const ruleDescription = descriptionInput.value;
const ruleAction = actionInput.value;
// 获取所有条件
const conditionRows = document.querySelectorAll('.condition-row');
let conditions = [];
conditionRows.forEach(row => {
const field = row.querySelector('.field').value;
const operator = row.querySelector('.operator').value;
const value = row.querySelector('.value').value;
conditions.push(`${field} ${operator} ${value}`);
});
// 将条件用 "&&" 连接起来
const conditionExpression = conditions.join(' && ');
// 生成规则的 Java 代码
const generatedCode = `
@Rule(name = "${ruleName}", description = "${ruleDescription}")
public class GeneratedRule {
@Condition
public boolean evaluate(@Fact("fact") Object fact) {
return ${conditionExpression};
}
@Action
public void execute() {
${ruleAction};
}
}
`;
// 将生成的代码放入弹窗
generatedCodePre.textContent = generatedCode;
// 显示弹窗
codeModal.style.display = 'block';
});
// 关闭弹窗
closeModalButton.addEventListener('click', function () {
codeModal.style.display = 'none';
});
3. 功能说明
a. 条件组布局
每个条件组(字段、运算符、值)现在会在同一行显示,用户可以通过点击“添加条件”按钮新增一个条件组,也可以通过“删除条件”按钮移除不需要的条件。
b. 美化的下拉框
下拉框使用了简单的 CSS 样式优化,添加了自定义的下拉箭头和调整了整体的视觉风格,确保看起来更现代。
c. 多条件支持
通过 "并且"(&&
) 方式将所有条件组合在一起。如果用户创建了多个条件,系统会自动将它们组合到条件表达式中。例如:
java复制代码return rain == true && temperature > 20;
d. 生成 Java 规则代码
生成的代码如下所示:
java复制代码@Rule(name = "yourRuleName", description = "yourRuleDescription")
public class GeneratedRule {
@Condition
public boolean evaluate(@Fact("fact") Object fact) {
return rain == true && temperature > 20;
}
@Action
public void execute() {
System.out.println("Take an umbrella!");
}
}
e. 弹窗展示生成的代码
用户点击“生成代码”后,弹窗会显示生成的 Java 代码。用户可以通过“关闭”按钮关闭弹窗。
4. 扩展建议
- 条件组扩展:支持不同的逻辑组合(如 "或者" 组合条件)。
- 复杂条件支持:可以让用户在生成的条件表达式中插入括号,形成更复杂的逻辑表达式。
- 动作配置扩展:可以支持多种动作(如多行代码)或者条件触发不同动作。
- 保存配置:可以添加保存配置的功能,将用户配置的条件组和规则保存为文件或者发送到后端进行处理。
通过这个优化后的界面,用户可以更直观、灵活地配置规则,并且代码生成过程也更加自动化和用户友好。
我们再来看看第三次的UI结果:
这样我们就有了可以操作的代码了。
三、最后
然后我们在跟大模型持续沟通下UI、交互、细节,最终就形成了如下样式界面:
单击生成代码后,可以生成EasyRule的代码:
这里面能做的还有非常多,比如添加条件组等等。感兴趣的小伙伴可以去尝试下。
我这里最终我自己优化后的代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Easy Rules 可视化配置</title>
<style>
/* 基本布局 */
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 0;
background-color: #f0f0f0;
}
/* 页面标题 */
h2 {
color: #333;
font-size: 24px;
margin-bottom: 20px;
text-align: center;
}
/* 规则组容器 */
.rule-group {
max-width: 1200px;
margin: 0 auto;
background-color: #ffffff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
/* 表单标签 */
label {
display: block;
margin: 10px 0 5px;
font-size: 16px;
color: #555;
}
/* 输入框和下拉菜单 */
input[type="text"],
textarea,
select {
width: 100%;
padding: 10px;
border: 1px solid #ccc;
border-radius: 0px;
box-sizing: border-box;
font-size: 14px;
background-color: #fff;
}
input[type="text"] {
width: 500px;
display: inline-block;
margin-right: 10px;
}
textarea {
resize: vertical;
}
/* 美化下拉框 */
select {
appearance: none;
background-color: #ffffff;
background-image: url('data:image/svg+xml;charset=US-ASCII,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 4 5"><path fill="none" stroke="%23000" stroke-width=".8" d="M2 0L0 2h4zm0 5L0 3h4z"/></svg>');
background-repeat: no-repeat;
background-position: right 10px center;
background-size: 12px 12px;
padding-right: 40px;
border: 1px solid #ccc;
}
/* 按钮 */
button {
padding: 10px 24px;
font-size: 14px;
border: none;
border-radius: 6px;
cursor: pointer;
width: 200px;
transition: background-color 0.3s ease, transform 0.3s ease;
}
button:hover {
opacity: 0.9;
transform: scale(1.02);
}
/* 添加条件按钮 */
.add-condition-btn {
background-color: #007bff;
color: #fff;
}
.add-condition-btn:hover {
background-color: #0056b3;
}
/* 删除条件按钮 */
.remove-condition-btn {
background-color: #dc3545;
color: #fff;
}
.remove-condition-btn:hover {
background-color: #c82333;
}
/* 条件行 */
.condition-row {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 15px;
padding: 15px;
background-color: #f9f9f9;
border: 1px solid #ddd;
border-radius: 6px;
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
}
.condition-row select,
.condition-row input[type="text"] {
margin-right: 10px;
flex: 1;
}
/* 逻辑操作符选择 */
.logical-operator {
width: auto;
margin: 0 10px;
}
/* 弹窗 */
#codeModal {
display: none;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: #ffffff;
padding: 20px;
border: 2px solid #333;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
z-index: 1000;
width: 70%;
max-width: 900px;
}
#codeModal h3 {
margin-top: 0;
color: #333;
font-size: 18px;
}
#codeModal pre {
white-space: pre-wrap;
word-wrap: break-word;
background-color: #f4f4f4;
padding: 15px;
border: 1px solid #ddd;
border-radius: 6px;
overflow-x: auto;
max-height: 300px;
overflow-y: auto;
}
#closeModal {
margin-top: 15px;
padding: 10px 20px;
background-color: #dc3545;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
}
#closeModal:hover {
background-color: #c82333;
}
/* 规则名称和描述对齐 */
.form-group {
display: flex;
justify-content: space-between;
gap: 10px;
margin-bottom:10px;
}
#generateCode{
background-color: #4CAF50;
}
</style>
</head>
<body>
<h2>Easy Rules 可视化配置界面</h2>
<!-- 表单部分 -->
<div class="rule-group">
<form id="ruleForm">
<div class="form-group">
<div>
<label for="name">规则名称:</label>
<input type="text" id="name" placeholder="请输入规则名称">
</div>
<div>
<label for="description">规则描述:</label>
<input type="text" id="description" placeholder="请输入规则描述">
</div>
</div>
<div id="conditions">
<!-- 动态添加条件组 -->
<div class="condition-row">
<select class="field">
<option value="userRiskScore">用户风险评分</option>
<option value="transactionFrequency">交易频率</option>
<option value="averageTransactionAmount">平均交易金额</option>
<option value="recentTransactionAmount">最近交易金额</option>
<option value="transactionVolume">交易量</option>
<option value="accountAge">账户年龄</option>
<option value="deviceId">设备ID</option>
<option value="loginFrequency">登录频率</option>
<option value="suspiciousActivity">可疑活动</option>
<option value="transactionLocation">交易地点</option>
</select>
<select class="operator">
<option value="==">等于 (==)</option>
<option value="!=">不等于 (!=)</option>
<option value=">">大于 (>)</option>
<option value="<">小于 (<)</option>
<option value=">=">大于等于 (>=)</option>
<option value="<=">小于等于 (<=)</option>
</select>
<input type="text" class="value" placeholder="请输入条件值">
<select class="logical-operator">
<option value="&&">AND</option>
<option value="||">OR</option>
</select>
<button type="button" class="add-condition-btn">添加条件</button>
</div>
</div>
<label for="action">动作 (e.g., "System.out.println('Take an umbrella!')"):</label>
<textarea id="action" rows="4" placeholder="请输入Java动作代码"></textarea>
<button type="button" id="generateCode">生成代码</button>
</form>
</div>
<!-- 弹窗部分 -->
<div id="codeModal">
<h3>生成的 Java 规则代码:</h3>
<pre id="generatedCode"></pre>
<button id="closeModal">关闭</button>
</div>
<script>
// 获取表单元素
const nameInput = document.getElementById('name');
const descriptionInput = document.getElementById('description');
const conditionsDiv = document.getElementById('conditions');
const actionInput = document.getElementById('action');
// 获取按钮和弹窗相关元素
const generateButton = document.getElementById('generateCode');
const codeModal = document.getElementById('codeModal');
const generatedCodePre = document.getElementById('generatedCode');
const closeModalButton = document.getElementById('closeModal');
// 添加
// 添加条件按钮功能
conditionsDiv.addEventListener('click', function (e) {
if (e.target.classList.contains('add-condition-btn')) {
// 创建新的条件行
const conditionRow = document.createElement('div');
conditionRow.classList.add('condition-row');
conditionRow.innerHTML = `
<select class="field">
<option value="userRiskScore">用户风险评分</option>
<option value="transactionFrequency">交易频率</option>
<option value="averageTransactionAmount">平均交易金额</option>
<option value="recentTransactionAmount">最近交易金额</option>
<option value="transactionVolume">交易量</option>
<option value="accountAge">账户年龄</option>
<option value="deviceId">设备ID</option>
<option value="loginFrequency">登录频率</option>
<option value="suspiciousActivity">可疑活动</option>
<option value="transactionLocation">交易地点</option>
</select>
<select class="operator">
<option value="==">等于 (==)</option>
<option value="!=">不等于 (!=)</option>
<option value=">">大于 (>)</option>
<option value="<">小于 (<)</option>
<option value=">=">大于等于 (>=)</option>
<option value="<=">小于等于 (<=)</option>
</select>
<input type="text" class="value" placeholder="请输入条件值">
<select class="logical-operator">
<option value="&&">AND</option>
<option value="||">OR</option>
</select>
<button type="button" class="remove-condition-btn">删除条件</button>
`;
conditionsDiv.appendChild(conditionRow);
}
// 删除条件按钮功能
if (e.target.classList.contains('remove-condition-btn')) {
e.target.parentElement.remove();
}
});
// 点击生成按钮时生成代码并显示弹窗
generateButton.addEventListener('click', function () {
const ruleName = nameInput.value;
const ruleDescription = descriptionInput.value;
const ruleAction = actionInput.value;
// 获取所有条件
const conditionRows = document.querySelectorAll('.condition-row');
let conditions = [];
conditionRows.forEach((row, index) => {
const field = row.querySelector('.field').value;
const operator = row.querySelector('.operator').value;
const value = row.querySelector('.value').value;
const logicalOperator = index < conditionRows.length - 1 ? row.querySelector('.logical-operator').value : '';
conditions.push(`${field} ${operator} ${value} ${logicalOperator}`);
});
// 将条件用逻辑操作符连接起来
const conditionExpression = conditions.join(' ').trim();
// 生成规则的 Java 代码
const generatedCode = `
@Rule(name = "${ruleName}", description = "${ruleDescription}")
public class GeneratedRule {
@Condition
public boolean evaluate(@Fact("fact") Object fact) {
return ${conditionExpression};
}
@Action
public void execute() {
${ruleAction};
}
}
`;
// 将生成的代码放入弹窗
generatedCodePre.textContent = generatedCode;
// 显示弹窗
codeModal.style.display = 'block';
});
// 关闭弹窗
closeModalButton.addEventListener('click', function () {
codeModal.style.display = 'none';
});
</script>
</body>
</html>
后来又让AI给我生成了Vue.js版本的界面,如下所示:
代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Easy Rules 可视化配置</title>
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- import Vue before Element -->
<script src="https://unpkg.com/vue@2/dist/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 0;
background-color: #f0f0f0;
}
h2 {
color: #333;
font-size: 24px;
margin-bottom: 20px;
text-align: center;
}
.rule-group {
max-width: 1200px;
margin: 0 auto;
background-color: #ffffff;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.condition-row {
display: flex;
align-items: center;
margin-bottom: 15px;
padding: 15px;
background-color: #f9f9f9;
border: 1px solid #ddd;
border-radius: 6px;
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
gap: 10px;
}
.condition-row > * {
flex: 1;
min-width: 0;
}
.condition-row el-select,
.condition-row el-input {
margin-right: 10px;
}
.dialog-footer {
text-align: right;
}
.add-button {
margin-bottom: 20px;
}
</style>
</head>
<body>
<div id="app" class="rule-group">
<h2>Easy Rules 可视化配置界面</h2>
<el-form :model="form" label-width="120px">
<el-form-item label="规则名称">
<el-input v-model="form.name" placeholder="请输入规则名称"></el-input>
</el-form-item>
<el-form-item label="规则描述">
<el-input v-model="form.description" placeholder="请输入规则描述"></el-input>
</el-form-item>
<el-form-item label="添加选择">
<div v-for="(condition, index) in conditions" :key="index" class="condition-row">
<el-select v-model="condition.field" placeholder="选择字段">
<el-option v-for="option in fieldOptions" :key="option.value" :label="option.label" :value="option.value"></el-option>
</el-select>
<el-select v-model="condition.operator" placeholder="选择操作符">
<el-option v-for="option in operatorOptions" :key="option.value" :label="option.label" :value="option.value"></el-option>
</el-select>
<el-input v-model="condition.value" placeholder="请输入条件值" style="width: 200px;"></el-input>
<el-select v-model="condition.logicalOperator" placeholder="选择逻辑操作符" v-if="index < conditions.length - 1">
<el-option v-for="option in logicalOperatorOptions" :key="option.value" :label="option.label" :value="option.value"></el-option>
</el-select>
<el-button @click="removeCondition(index)" type="danger">删除条件</el-button>
</div>
</el-form-item>
<el-form-item label="动作">
<el-input type="textarea" v-model="form.action" placeholder="请输入Java动作代码" rows="4"></el-input>
</el-form-item>
<el-form-item>
<el-button @click="generateCode" type="success">生成代码</el-button>
<el-button @click="addCondition" class="add-button" type="primary">添加条件</el-button>
</el-form-item>
</el-form>
<el-dialog title="生成的 Java 规则代码" :visible.sync="showModal" width="70%">
<pre>{{ generatedCode }}</pre>
<span slot="footer" class="dialog-footer">
<el-button @click="showModal = false">关闭</el-button>
</span>
</el-dialog>
</div>
<script>
new Vue({
el: '#app',
data() {
return {
form: {
name: '',
description: '',
action: ''
},
conditions: [
{ field: '', operator: '', value: '', logicalOperator: '' }
],
showModal: false,
generatedCode: '',
fieldOptions: [
{ value: 'userRiskScore', label: '用户风险评分' },
{ value: 'transactionFrequency', label: '交易频率' },
{ value: 'averageTransactionAmount', label: '平均交易金额' },
{ value: 'recentTransactionAmount', label: '最近交易金额' },
{ value: 'transactionVolume', label: '交易量' },
{ value: 'accountAge', label: '账户年龄' },
{ value: 'deviceId', label: '设备ID' },
{ value: 'loginFrequency', label: '登录频率' },
{ value: 'suspiciousActivity', label: '可疑活动' },
{ value: 'transactionLocation', label: '交易地点' }
],
operatorOptions: [
{ value: '==', label: '等于 (==)' },
{ value: '!=', label: '不等于 (!=)' },
{ value: '>', label: '大于 (>)' },
{ value: '<', label: '小于 (<)' },
{ value: '>=', label: '大于等于 (>=)' },
{ value: '<=', label: '小于等于 (<=)' }
],
logicalOperatorOptions: [
{ value: '&&', label: 'AND' },
{ value: '||', label: 'OR' }
]
};
},
methods: {
addCondition() {
this.conditions.push({ field: '', operator: '', value: '', logicalOperator: '' });
},
removeCondition(index) {
this.conditions.splice(index, 1);
},
generateCode() {
const conditions = this.conditions.map((condition, index) => {
const logicalOperator = index < this.conditions.length - 1 ? condition.logicalOperator : '';
return `${condition.field} ${condition.operator} ${condition.value} ${logicalOperator}`;
}).join(' ').trim();
this.generatedCode = `
@Rule(name = "${this.form.name}", description = "${this.form.description}")
public class GeneratedRule {
@Condition
public boolean evaluate(@Fact("fact") Object fact) {
return ${conditions};
}
@Action
public void execute() {
${this.form.action};
}
}
`;
this.showModal = true;
}
}
});
</script>
</body>
</html>
通过这个界面也是想让学习规则引擎的小伙伴理解下规则引擎。
欢迎和我一起沟通交流。