Initial commit

This commit is contained in:
2025-11-06 10:29:13 +08:00
commit 0becd14830
318 changed files with 7145 additions and 0 deletions

View File

@@ -0,0 +1,127 @@
# 角色设定
你是一位经验丰富的软件开发专家与编码助手,精通所有主流编程语言与框架。你的用户是一名独立开发者,正在进行个人或自由职业项目开发。你的职责是协助生成高质量代码、优化性能、并主动发现和解决技术问题。
---
# 核心目标
高效协助用户开发代码,并在无需反复提示的前提下主动解决问题。关注以下核心任务:
- 编写代码
- 优化代码
- 调试与问题解决
确保所有解决方案都清晰易懂,逻辑严密。
---
## 阶段一:初始评估
1. 用户发出请求时,优先检查项目中的 `README.md` 文档以理解整体架构与目标。
2. 若无文档,主动创建一份 `README.md`,包括功能说明、使用方式和核心参数。
3. 利用已有上下文(文件、代码)充分理解需求,避免偏差。
---
## 阶段二:代码实现
### 1. 明确需求
- 主动确认需求是否清晰,若有疑问,应立即询问。
- 推荐最简单有效的方案,避免不必要的复杂设计。
### 2. 编写代码
- 阅读现有代码,明确实现步骤。
- 选择合适语言与框架,并遵循最佳实践(如 SOLID 原则)。
- 编写简洁、可读、带注释的代码。
- 优化可维护性与性能。
- 按需提供单元测试。
- 遵循语言标准编码规范(如 Python 使用 PEP 8
### 3. 调试与问题解决
- 系统化分析问题,找出根因。
- 明确说明问题来源及解决方式。
- 在问题解决过程中持续与用户沟通,如需求变动能快速适应。
---
## 阶段三:完成与总结
1. 清晰总结本轮改动、完成目标与优化内容。
2. 标注潜在风险或需留意的边界情况。
3. 更新项目文档(如 `README.md`)以反映最新进展。
---
# 最佳实践
### Sequential Thinking逐步思考工具
使用 [Sequential Thinking](https://github.com/smithery-ai/reference-servers/tree/main/src/sequentialthinking) 工具,以结构化的思维方式处理复杂、开放性问题。
- 将任务拆解为若干 **思维步骤thought steps**
- 每一步应包括:
1.**明确当前目标或假设**(如:“分析登录方案”,“优化状态管理结构”)。
2.**调用合适的 MCP 工具**(如 `search_docs``code_generator``error_explainer`用于执行查文档、生成代码或解释错误等操作。Sequential Thinking 本身不产出代码,而是协调过程。
3.**清晰记录本步骤的结果与输出**。
4.**确定下一步目标或是否分支**,并继续流程。
- 在面对不确定或模糊任务时:
- 使用“分支思考”探索多种方案。
- 比较不同路径的优劣,必要时回滚或修改已完成的步骤。
- 每个步骤可带有如下结构化元数据:
-`thought`: 当前思考内容
-`thoughtNumber`: 当前步骤编号
-`totalThoughts`: 预估总步骤数
-`nextThoughtNeeded`, `needsMoreThoughts`: 是否需要继续思考
-`isRevision`, `revisesThought`: 是否为修订行为,及其修订对象
-`branchFromThought`, `branchId`: 分支起点编号及标识
- 推荐在以下场景使用:
- 问题范围模糊或随需求变化
- 需要不断迭代、修订、探索多解
- 跨步骤上下文保持一致尤为重要
- 需要过滤不相关或干扰性信息
---
### Context7最新文档集成工具
使用 [Context7](https://github.com/upstash/context7) 工具获取特定版本的最新官方文档与代码示例,用于提升生成代码的准确性与当前性。
-**目的**:解决模型知识过时问题,避免生成已废弃或错误的 API 用法。
-**使用方式**
1.**调用方式**:在提示词中加入 `use context7` 触发文档检索。如果不确定部分用法时也建议自动使用。
2.**获取文档**Context7 会拉取当前使用框架/库的相关文档片段。
3.**集成内容**:将获取的示例与说明合理集成到你的代码生成或分析中。
-**按需使用****仅在需要时调用 Context7**,例如遇到 API 模糊、版本差异大或用户请求查阅官方用法。避免不必要的调用,以节省 token 并提高响应效率。
-**集成方式**
- 支持 Cursor、Claude Desktop、Windsurf 等 MCP 客户端。
- 通过配置服务端集成 Context7即可在上下文中获取最新参考资料。
-**优势**
- 提升代码准确性,减少因知识过时造成的幻觉与报错。
- 避免依赖训练时已过期的框架信息。
- 提供明确、权威的技术参考材料。
---
# 沟通规范
- 除非用户要求以另一种语言回答,否则所有内容必须使用用户向你发出请求时使用的语言交流(包括代码注释)。
- 遇到不清楚的内容应立即向用户提问。
- 表达清晰、简洁、技术准确。
- 在代码中应添加必要的注释解释关键逻辑。
- 无论何时你想提问,总是调用 MCP mcp-feedback-enhancedinteractive_feedback命令
# MCP Interactive Feedback 规则
1. 在任何流程、任务、对话进行时,无论是询问、回复、或完成阶段性任务,皆必须调用 MCP mcp-feedback-enhanced。
2. 每当收到用户反馈,若反馈内容非空,必须再次调用 MCP mcp-feedback-enhanced并根据反馈内容调整行为。
3. 仅当用户明确表示「结束」或「不再需要交互」时,才可停止调用 MCP mcp-feedback-enhanced流程才算结束。
4. 除非收到结束指令,否则所有步骤都必须重复调用 MCP mcp-feedback-enhanced。
5. 完成任务前,必须使用 MCP mcp-feedback-enhanced 工具向用户询问反馈。

38
BankSystem/.gitignore vendored Normal file
View File

@@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

10
BankSystem/.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,10 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# 依赖于环境的 Maven 主目录路径
/mavenHomeManager.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

7
BankSystem/.idea/encodings.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
</component>
</project>

14
BankSystem/.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@@ -0,0 +1,9 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="BankSystem" type="Application" factoryName="Application" singleton="false">
<option name="MAIN_CLASS_NAME" value="BankSystem" />
<module name="BankSystem" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
</component>

124
BankSystem/.idea/uiDesigner.xml generated Normal file
View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

4
BankSystem/.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings" defaultProject="true" />
</project>

76
BankSystem/README.md Normal file
View File

@@ -0,0 +1,76 @@
# 简易银行管理系统
这是一个使用 Java Swing 构建的简单银行账户管理系统。
## 功能
* **账户管理**
* 开户创建一个新的银行账户系统会自动生成唯一的账户ID。
* 销户:删除一个现有账户。只有当账户余额为零时才能成功销户。
* 查询根据账户ID查询账户的详细信息包括账户持有人姓名和当前余额。
* **资金管理**
* 存款:向指定账户存入金额。
* 取款:从指定账户取出金额,账户余额必须充足。
* 转账:在两个指定账户之间转移金额,源账户余额必须充足。
## 使用方式
1. 运行 `BankSystem.java` 文件启动应用程序。
2. **开户**
* 点击“开户”按钮。
* 在弹出的对话框中输入账户持有人姓名。
* 系统会提示账户创建成功并显示新生成的账户ID。
3. **查询账户**
* 在“账户号”输入框中输入要查询的账户ID。
* 点击“查询”按钮。
* 如果账户存在,其姓名和余额将显示在相应的不可编辑字段中。
4. **存款**
* 首先查询一个账户或在“账户号”输入框中输入账户ID。
* 点击“存款”按钮。
* 在弹出的对话框中输入存款金额。
* 操作成功后,账户余额会自动更新(如果当前查询的是该账户)。
5. **取款**
* 首先查询一个账户或在“账户号”输入框中输入账户ID。
* 点击“取款”按钮。
* 在弹出的对话框中输入取款金额。
* 操作成功后,账户余额会自动更新(如果当前查询的是该账户)。
6. **转账**
* 首先查询源账户或在“账户号”输入框中输入源账户ID。
* 点击“转账”按钮。
* 在弹出的第一个对话框中输入目标账户ID。
* 在弹出的第二个对话框中输入转账金额。
* 操作成功后,源账户余额会自动更新(如果当前查询的是源账户)。
7. **销户**
* 首先查询一个账户或在“账户号”输入框中输入要销户的账户ID。
* 点击“销户”按钮。
* 系统会要求确认操作。
* 只有当账户余额为零时,销户才能成功。成功后,界面上的账户信息字段将被清空。
## 数据存储
所有账户数据都存储在项目根目录下的 `accounts.json` 文件中。每个账户对象包含以下键:
```json
[
{
"accountId": "ACC16228383922",
"name": "张三",
"balance": 1000.50
},
{
"accountId": "ACC16228383950",
"name": "李四",
"balance": 500.00
}
]
```
* `accountId`: (String) 唯一的账户标识符。
* `name`: (String) 账户持有人的姓名。
* `balance`: (double) 账户的当前余额。
## 技术栈
* Java
* Swing (用于GUI)
* Gson (用于JSON数据处理)

1
BankSystem/accounts.json Normal file
View File

@@ -0,0 +1 @@
[{"accountId":"ACC1749542730783","name":"lisi","balance":1.0},{"accountId":"ACC1749553162251","name":"zhangsan","balance":50.0},{"accountId":"ACC1749560275526","name":"张三","balance":10.0}]

30
BankSystem/pom.xml Normal file
View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.momokko</groupId>
<artifactId>BankSystem</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.13.1</version>
</dependency>
<dependency>
<groupId>com.formdev</groupId>
<artifactId>flatlaf</artifactId>
<version>3.6</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,12 @@
import com.formdev.flatlaf.FlatDarculaLaf;
public class BankSystem {
public static void main(String[] args) {
FlatDarculaLaf.setup();
javax.swing.SwingUtilities.invokeLater(() -> {
BankSystemUI ui = new BankSystemUI();
ui.pack();
ui.setVisible(true);
});
}
}

View File

@@ -0,0 +1,241 @@
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class BankSystemCore {
private final Gson gson = new Gson();
private static final String ACCOUNTS_FILE_PATH = "accounts.json";
private List<Account> loadAccounts() {
if (!Files.exists(Paths.get(ACCOUNTS_FILE_PATH))) {
return new ArrayList<>();
}
try (FileReader reader = new FileReader(ACCOUNTS_FILE_PATH)) {
Type accountListType = new TypeToken<ArrayList<Account>>() {}.getType();
List<Account> accounts = gson.fromJson(reader, accountListType);
return accounts == null ? new ArrayList<>() : accounts;
} catch (IOException e) {
e.printStackTrace();
return new ArrayList<>();
}
}
private boolean saveAccounts(List<Account> accounts) {
try (FileWriter writer = new FileWriter(ACCOUNTS_FILE_PATH)) {
gson.toJson(accounts, writer);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
Account CreateAccount(String name) {
if (name == null || name.trim().isEmpty()) {
return null;
}
List<Account> accounts = loadAccounts();
String accountId = "ACC" + System.currentTimeMillis();
Account newAccount = new Account(accountId, name.trim(), 0.0);
accounts.add(newAccount);
if (saveAccounts(accounts)) {
return newAccount;
} else {
return null;
}
}
Account QueryAccount(String accountId) throws AccountNotFoundException {
if (accountId == null || accountId.trim().isEmpty()) {
throw new AccountNotFoundException("账户ID不能为空。");
}
List<Account> accounts = loadAccounts();
Optional<Account> accountOpt = accounts.stream()
.filter(acc -> acc.getAccountId().equals(accountId.trim()))
.findFirst();
if (accountOpt.isPresent()) {
return accountOpt.get();
} else {
throw new AccountNotFoundException("账户 " + accountId + " 未找到。");
}
}
void DeleteAccount(String accountId) throws AccountNotFoundException, AccountOperationException {
if (accountId == null || accountId.trim().isEmpty()) {
throw new AccountNotFoundException("账户ID不能为空。");
}
List<Account> accounts = loadAccounts();
Optional<Account> accountOpt = accounts.stream()
.filter(acc -> acc.getAccountId().equals(accountId.trim()))
.findFirst();
if (accountOpt.isPresent()) {
Account accountToDelete = accountOpt.get();
if (accountToDelete.getBalance() == 0.0) {
accounts.remove(accountToDelete);
if (!saveAccounts(accounts)) {
throw new AccountOperationException("删除账户 " + accountId + " 时保存失败。");
}
} else {
throw new AccountOperationException("账户 " + accountId + " 余额不为零,无法删除。");
}
} else {
throw new AccountNotFoundException("要删除的账户 " + accountId + " 未找到。");
}
}
void Deposit(String accountId, double amount) throws AccountNotFoundException, InvalidAmountException, AccountOperationException {
if (accountId == null || accountId.trim().isEmpty()) {
throw new AccountNotFoundException("账户ID不能为空。");
}
if (amount <= 0) {
throw new InvalidAmountException("存款金额必须为正数。");
}
List<Account> accounts = loadAccounts();
Optional<Account> accountOpt = accounts.stream()
.filter(acc -> acc.getAccountId().equals(accountId.trim()))
.findFirst();
if (accountOpt.isPresent()) {
Account account = accountOpt.get();
accounts.remove(account);
Account updatedAccount = new Account(account.getAccountId(), account.getName(), account.getBalance() + amount);
accounts.add(updatedAccount);
if (!saveAccounts(accounts)) {
throw new AccountOperationException("存款到账户 " + accountId + " 时保存失败。");
}
} else {
throw new AccountNotFoundException("存款账户 " + accountId + " 未找到。");
}
}
void Withdraw(String accountId, double amount) throws AccountNotFoundException, InvalidAmountException, InsufficientBalanceException, AccountOperationException {
if (accountId == null || accountId.trim().isEmpty()) {
throw new AccountNotFoundException("账户ID不能为空。");
}
if (amount <= 0) {
throw new InvalidAmountException("取款金额必须为正数。");
}
List<Account> accounts = loadAccounts();
Optional<Account> accountOpt = accounts.stream()
.filter(acc -> acc.getAccountId().equals(accountId.trim()))
.findFirst();
if (accountOpt.isPresent()) {
Account account = accountOpt.get();
if (account.getBalance() >= amount) {
accounts.remove(account);
Account updatedAccount = new Account(account.getAccountId(), account.getName(), account.getBalance() - amount);
accounts.add(updatedAccount);
if (!saveAccounts(accounts)) {
throw new AccountOperationException("从账户 " + accountId + " 取款时保存失败。");
}
} else {
throw new InsufficientBalanceException("账户 " + accountId + " 余额不足。当前余额: " + account.getBalance() + ", 取款金额: " + amount);
}
} else {
throw new AccountNotFoundException("取款账户 " + accountId + " 未找到。");
}
}
void Transfer(String fromAccountId, String toAccountId, double amount) throws AccountNotFoundException, InvalidAmountException, InsufficientBalanceException, AccountOperationException {
if (fromAccountId == null || fromAccountId.trim().isEmpty()) {
throw new AccountNotFoundException("源账户ID不能为空。");
}
if (toAccountId == null || toAccountId.trim().isEmpty()) {
throw new AccountNotFoundException("目标账户ID不能为空。");
}
if (fromAccountId.trim().equals(toAccountId.trim())) {
throw new AccountOperationException("源账户和目标账户不能相同。");
}
if (amount <= 0) {
throw new InvalidAmountException("转账金额必须为正数。");
}
List<Account> accounts = loadAccounts();
Account fromAccount = accounts.stream()
.filter(acc -> acc.getAccountId().equals(fromAccountId.trim()))
.findFirst()
.orElseThrow(() -> new AccountNotFoundException("源账户 " + fromAccountId + " 未找到。"));
Account toAccount = accounts.stream()
.filter(acc -> acc.getAccountId().equals(toAccountId.trim()))
.findFirst()
.orElseThrow(() -> new AccountNotFoundException("目标账户 " + toAccountId + " 未找到。"));
if (fromAccount.getBalance() >= amount) {
accounts.remove(fromAccount);
accounts.remove(toAccount);
Account updatedFromAccount = new Account(fromAccount.getAccountId(), fromAccount.getName(), fromAccount.getBalance() - amount);
Account updatedToAccount = new Account(toAccount.getAccountId(), toAccount.getName(), toAccount.getBalance() + amount);
accounts.add(updatedFromAccount);
accounts.add(updatedToAccount);
if (!saveAccounts(accounts)) {
throw new AccountOperationException("转账时保存账户信息失败。");
}
} else {
throw new InsufficientBalanceException("源账户 " + fromAccountId + " 余额不足。当前余额: " + fromAccount.getBalance() + ", 转账金额: " + amount);
}
}
}
// Custom Exception Classes
class AccountNotFoundException extends Exception {
public AccountNotFoundException(String message) {
super(message);
}
}
class InsufficientBalanceException extends Exception {
public InsufficientBalanceException(String message) {
super(message);
}
}
class InvalidAmountException extends Exception {
public InvalidAmountException(String message) {
super(message);
}
}
class AccountOperationException extends Exception {
public AccountOperationException(String message) {
super(message);
}
}
class Account {
private String accountId;
private String name;
private double balance;
public Account(String accountId, String name, double balance) {
this.accountId = accountId;
this.name = name;
this.balance = balance;
}
public String getAccountId() {
return accountId;
}
public String getName() {
return name;
}
public double getBalance() {
return balance;
}
}

View File

@@ -0,0 +1,128 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="BankSystemUI">
<grid id="27dc6" binding="contentPane" layout-manager="GridLayoutManager" row-count="4" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="286a" class="javax.swing.JTextField" binding="accountIdField">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="ecf1" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="账户号"/>
</properties>
</component>
<component id="4efa6" class="javax.swing.JButton" binding="QueryButton">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="查询"/>
</properties>
</component>
<component id="fd2f8" class="javax.swing.JButton" binding="CreateButton">
<constraints>
<grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="开户"/>
</properties>
</component>
<component id="ea349" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="姓名"/>
</properties>
</component>
<component id="63a1c" class="javax.swing.JTextField" binding="NameField">
<constraints>
<grid row="1" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties>
<editable value="false"/>
</properties>
</component>
<component id="67ce4" class="javax.swing.JLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="余额"/>
</properties>
</component>
<component id="1c909" class="javax.swing.JTextField" binding="BalanceField">
<constraints>
<grid row="2" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties>
<editable value="false"/>
</properties>
</component>
<grid id="41396" layout-manager="GridLayoutManager" row-count="2" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="3" column="0" row-span="1" col-span="4" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="b7d15" class="javax.swing.JButton" binding="DepositButton">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="存款"/>
</properties>
</component>
<vspacer id="e9d2e">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="5b666" class="javax.swing.JButton" binding="WithdrawButton">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="取款"/>
</properties>
</component>
<component id="98815" class="javax.swing.JButton" binding="TransferButton">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="转账"/>
</properties>
</component>
<component id="8faef" class="javax.swing.JButton" binding="DeleteButton">
<constraints>
<grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="销户"/>
</properties>
</component>
</children>
</grid>
</children>
</grid>
</form>

View File

@@ -0,0 +1,142 @@
import javax.swing.*;
public class BankSystemUI extends JDialog {
private JTextField accountIdField;
private JButton QueryButton, CreateButton, DepositButton, WithdrawButton, TransferButton, DeleteButton;
private JTextField NameField, BalanceField;
private JPanel contentPane;
private BankSystemCore core = new BankSystemCore();
public BankSystemUI() {
setResizable(false);
setContentPane(contentPane);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setTitle("简易银行系统");
QueryButton.addActionListener(e -> queryAccountAction());
CreateButton.addActionListener(e -> {
String name = JOptionPane.showInputDialog(this, "请输入账户名:", "创建账户", JOptionPane.PLAIN_MESSAGE);
if (name == null || name.trim().isEmpty()) {
if (name != null) {
JOptionPane.showMessageDialog(this, "账户名不能为空。", "创建账户错误", JOptionPane.ERROR_MESSAGE);
}
return;
}
try {
Account account = core.CreateAccount(name.trim());
if (account != null) {
JOptionPane.showMessageDialog(this, "账户创建成功!\n账户ID: " + account.getAccountId(), "创建账户成功", JOptionPane.INFORMATION_MESSAGE);
accountIdField.setText(account.getAccountId());
queryAccountAction();
} else {
JOptionPane.showMessageDialog(this, "创建账户失败。", "创建账户错误", JOptionPane.ERROR_MESSAGE);
}
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, "创建账户时发生错误: " + ex.getMessage(), "创建账户错误", JOptionPane.ERROR_MESSAGE);
}
});
DepositButton.addActionListener(e -> {
String id = accountIdField.getText().trim();
if (id.isEmpty()) {
JOptionPane.showMessageDialog(this, "请输入账户ID。", "存款错误", JOptionPane.ERROR_MESSAGE);
return;
}
String amt = JOptionPane.showInputDialog(this, "请输入存款金额:", "存款", JOptionPane.PLAIN_MESSAGE);
if (amt == null || amt.trim().isEmpty()) return;
try {
core.Deposit(id, Double.parseDouble(amt.trim()));
JOptionPane.showMessageDialog(this, "存款成功。", "存款成功", JOptionPane.INFORMATION_MESSAGE);
queryAccountAction();
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(this, "无效的金额格式。", "存款错误", JOptionPane.ERROR_MESSAGE);
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "存款错误", JOptionPane.ERROR_MESSAGE);
}
});
WithdrawButton.addActionListener(e -> {
String id = accountIdField.getText().trim();
if (id.isEmpty()) {
JOptionPane.showMessageDialog(this, "请输入账户ID。", "取款错误", JOptionPane.ERROR_MESSAGE);
return;
}
String amt = JOptionPane.showInputDialog(this, "请输入取款金额:", "取款", JOptionPane.PLAIN_MESSAGE);
if (amt == null || amt.trim().isEmpty()) return;
try {
core.Withdraw(id, Double.parseDouble(amt.trim()));
JOptionPane.showMessageDialog(this, "取款成功。", "取款成功", JOptionPane.INFORMATION_MESSAGE);
queryAccountAction();
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(this, "无效的金额格式。", "取款错误", JOptionPane.ERROR_MESSAGE);
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "取款错误", JOptionPane.ERROR_MESSAGE);
}
});
TransferButton.addActionListener(e -> {
String from = accountIdField.getText().trim();
if (from.isEmpty()) {
JOptionPane.showMessageDialog(this, "请输入源账户ID。", "转账错误", JOptionPane.ERROR_MESSAGE);
return;
}
String to = JOptionPane.showInputDialog(this, "请输入目标账户ID:", "转账", JOptionPane.PLAIN_MESSAGE);
if (to == null || to.trim().isEmpty()) return;
String amt = JOptionPane.showInputDialog(this, "请输入转账金额:", "转账", JOptionPane.PLAIN_MESSAGE);
if (amt == null || amt.trim().isEmpty()) return;
try {
core.Transfer(from, to.trim(), Double.parseDouble(amt.trim()));
JOptionPane.showMessageDialog(this, "转账成功。", "转账成功", JOptionPane.INFORMATION_MESSAGE);
queryAccountAction();
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(this, "无效的金额格式。", "转账错误", JOptionPane.ERROR_MESSAGE);
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "转账错误", JOptionPane.ERROR_MESSAGE);
}
});
DeleteButton.addActionListener(e -> {
String id = accountIdField.getText().trim();
if (id.isEmpty()) {
JOptionPane.showMessageDialog(this, "请输入要删除的账户ID。", "删除错误", JOptionPane.ERROR_MESSAGE);
return;
}
int res = JOptionPane.showConfirmDialog(this, "确认删除账户 " + id + "", "删除确认", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
if (res == JOptionPane.YES_OPTION) {
try {
core.DeleteAccount(id);
JOptionPane.showMessageDialog(this, "删除成功。", "删除成功", JOptionPane.INFORMATION_MESSAGE);
accountIdField.setText("");
clearFields();
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "删除错误", JOptionPane.ERROR_MESSAGE);
}
}
});
}
private void queryAccountAction() {
String id = accountIdField.getText().trim();
if (id.isEmpty()) {
JOptionPane.showMessageDialog(this, "账户ID不能为空。", "查询错误", JOptionPane.ERROR_MESSAGE);
clearFields();
return;
}
try {
Account acc = core.QueryAccount(id);
NameField.setText(acc.getName());
BalanceField.setText(String.format("%.2f", acc.getBalance()));
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, ex.getMessage(), "查询错误", JOptionPane.ERROR_MESSAGE);
clearFields();
}
}
private void clearFields() {
NameField.setText("");
BalanceField.setText("");
}
}

Binary file not shown.