VB6+SQL Server 2000图书管理系统:三角色权限与借阅状态机实战
简介:本资源是一份面向软件工程初学者与课程设计实践者的《图书管理系统》完整开发文档,聚焦需求分析、系统设计与实现全过程,适用于高校软件工程课程设计、毕业设计参考及小型信息管理系统学习。文档以Word格式(.doc)单文件封装,大小535KB,内容涵盖系统目标与三类角色功能需求、三层架构设计(Presentation/Application/Data Layer)、SQL Server 2000数据库E-R图与表结构、Visual Basic 6.0界面与编码实现细节,并附有详细用例图、时序图、类图及模块化开发步骤说明。目录结构严谨,从绪论、需求分析到数据库设计、系统实现层层递进,特别适合理解传统C/S架构下图书管理系统的全生命周期开发逻辑。目前已有441人学习下载,是兼顾理论规范性与工程实操性的典型教学级软件工程文档。
1. 这不是又一个“课程设计交差项目”:一个能真正在局域网里跑通、带完整借阅状态闭环、支持三角色权限隔离的 VB6 + SQL Server 2000 图书管理系统
去年帮某高校实验室迁移一批老系统时,翻出这个「图书管理系统 软件工程」源码包——第一反应是删掉。但当我用 SQL Server 2000 附加了book.mdf,在 VB6 IDE 里点下 F5,看到登录窗体弹出来、输入admin/123456后直接跳进管理员后台,新增一本《算法导论》、再用读者账号reader001/123456成功借出、还书时自动计算超期天数并写入punishment表……我停住了。这不是 PPT 架构图,也不是只画了 UML 就收工的文档作业。它是一套完整走通了“添加→借→还→罚→查”全链路的可执行系统,所有类(reader,librarian,administrator,book,borrow)都对应真实窗体和数据库表,ADO 连接池、字段级空值校验、借阅状态机(state字段控制“在库/已借/已续/已还”)、甚至罚款金额按天累加逻辑,全在.frm和.bas文件里硬编码实现。适合两类人:一是软件工程课设卡在“怎么把 UML 落地”的同学,它把用例图→类图→时序图→VB6 窗体控件→SQL 表字段的映射关系刻进了每一行代码;二是需要快速搭建内部资料库、又受限于老旧 Windows 环境的运维同事——它不依赖 .NET Framework,装完 VB6 运行时和 SQL Server 2000 就能 standalone 运行。别被标题里的“软件工程”吓住,它的价值不在文档厚度,而在那 8 张表之间真实的外键约束、在borrow.receivedate IS NULL判断借阅中状态的 SQL 条件、在login表密码明文存储却用psw字段名刻意提醒你该加密的血泪经验。
2. 架构拆解:三层结构不是画出来的,是 VB6 工程里用文件夹+模块硬分出来的
这个系统表面看是 VB6 单体应用,但它的目录组织和模块职责划分,已经暗合了现代三层架构思想。关键在于:Presentation 层(窗体)不碰 SQL 字符串,Application 层(.bas 模块)封装所有业务逻辑,Data 层(ADO 连接)只负责打开/关闭/执行。这种分离让修改变得可控——比如想把罚款规则从“超期1天=5元”改成“阶梯计费”,你只需改modBorrow.bas里的CalcPunishment()函数,不用动任何一个.frm窗体的按钮点击事件。
2.1 工程结构:VB6 项目文件夹就是你的架构图
打开 VB6 工程(.vbp文件),你会看到清晰的物理分层:
BookSystem/ ├── Forms/ ← Presentation Layer:纯界面 │ ├── frmLogin.frm ← 登录窗体(验证 user_name/psw) │ ├── frmMainReader.frm ← 读者主界面(含查询、借书、续借按钮) │ ├── frmMainLibrarian.frm ← 图书管理员界面(处理借还) │ └── frmMainAdmin.frm ← 系统管理员界面(增删改查 book/user) ├── Modules/ ← Application Layer:业务逻辑中枢 │ ├── modDatabase.bas ← ADO 连接管理(getConnection()、getDataReader()) │ ├── modBook.bas ← 图书 CRUD(AddBook(), UpdateBook(), SearchBook()) │ ├── modUser.bas ← 读者信息管理(RegisterUser(), UpdateUserStatus()) │ ├── modBorrow.bas ← 借阅核心逻辑(BorrowBook(), ReturnBook(), CalcPunishment()) │ └── modCommon.bas ← 公共函数(日期格式化、字符串清理) └── Data/ ← Data Layer:数据库文件(SQL Server 2000) └── book.mdf ← 主数据库文件(含 8 张表)提示:
modDatabase.bas是整个系统的数据命脉。它没用 DSN,而是读取F:\conn.txt里的连接字符串(如server=localhost;database=book;uid=sa;pwd=123456)。这意味着你部署时只需改这个文本文件,不用重编译 VB6 工程。
2.2 核心类与窗体的映射关系:UML 类图在这里活了
文档里画的reader类,在 VB6 里不是抽象概念,而是frmMainReader.frm窗体上的一组控件+代码:
reader类属性 → 窗体控件绑定user_cardnumber(证件号)绑定到txtCardNo.Text;user_name(姓名)绑定到txtName.Text;user_state(状态)用cmbState.ListIndex下拉框选择("正常"/"冻结"/"注销")。reader类方法 → 窗体事件处理借书()方法实现在cmdBorrow_Click()事件里:Private Sub cmdBorrow_Click() Dim bookID As String bookID = txtBookID.Text ' 从文本框读取图书编号 If modBorrow.BorrowBook(txtCardNo.Text, bookID) Then MsgBox "借书成功!" LoadBorrowHistory ' 刷新借阅历史列表 Else MsgBox "借书失败:可能图书已借出或读者状态异常" End If End Subborrow类的状态机 → 数据库字段驱动
文档强调borrow表的receivedate字段是核心状态开关:receivedate IS NULL→ “借阅中”(读者可续借)receivedate IS NOT NULL→ “已归还”(不可再操作)renew = 'Y'→ “已续借”(还书日期自动延后30天)
这个逻辑在modBorrow.ReturnBook()里硬编码:
Public Function ReturnBook(cardNo As String, bookCode As String) As Boolean Dim sql As String ' 先检查是否真在借阅中(receivedate为空) sql = "SELECT COUNT(*) FROM borrow WHERE user_cardno='" & cardNo & "' AND bannercode='" & bookCode & "' AND receivedate IS NULL" If GetScalar(sql) = 0 Then ReturnBook = False: Exit Function ' 不在借阅中,无法还 End If ' 更新还书日期,并计算罚款 sql = "UPDATE borrow SET receivedate='" & Format(Now, "yyyy-mm-dd") & "', " sql = sql & "renew='N' WHERE user_cardno='" & cardNo & "' AND bannercode='" & bookCode & "' AND receivedate IS NULL" If ExecuteNonQuery(sql) Then ' 计算超期天数并插入punishment表 Call CalcPunishment(cardNo, bookCode) ReturnBook = True End If End Function
2.3 数据库连接:ADO 对象模型的极简实践
modDatabase.bas里的getConnection()是整个数据访问的起点。它用最原始的 ADO 方式打开连接,没有 ORM,没有连接池复用,但足够稳定:
Public Sub getConnection() On Error GoTo ErrHandler ' 1. 读取连接字符串(来自F:\conn.txt) Set strFile = New FileSystemObject.OpenTextFile("F:\conn.txt", ForReading) strConn = strFile.ReadLine strFile.Close ' 2. 创建并打开连接 Set myConn = New ADODB.Connection myConn.ConnectionString = strConn myConn.Open ' 关键:这里会抛异常,必须捕获 Exit Sub ErrHandler: MsgBox "数据库连接失败:" & Err.Description & vbCrLf & "请检查SQL Server服务是否运行,或conn.txt路径是否正确" End End Sub参数说明:
strConn格式必须严格为Provider=SQLOLEDB;Data Source=localhost;Initial Catalog=book;User ID=sa;Password=123456;myConn.Open失败时,Err.Description会返回具体错误(如“服务器拒绝访问”说明 SQL Server 未启动,“登录失败”说明 sa 密码错误);On Error GoTo ErrHandler是 VB6 的玄学——不加这句,连接失败直接崩溃,加了才能弹出友好提示。
2.4 三角色权限控制:不是靠 if-else,是靠窗体加载逻辑
系统没用复杂的 RBAC 表,而是用最朴实的“登录后跳转不同主窗体”实现权限隔离:
' frmLogin.frm 中的登录按钮事件 Private Sub cmdLogin_Click() Dim sql As String sql = "SELECT * FROM login WHERE user_name='" & txtUser.Text & "' AND psw='" & txtPsw.Text & "'" Set rs = modDatabase.getDataReader(sql) If Not rs.EOF Then ' 根据用户名前缀决定角色(文档约定:admin_开头为管理员,libr_为图书管理员,其他为读者) If Left(txtUser.Text, 5) = "admin" Then frmMainAdmin.Show ElseIf Left(txtUser.Text, 5) = "libr_" Then frmMainLibrarian.Show Else frmMainReader.Show End If Unload Me ' 关闭登录窗体 Else MsgBox "用户名或密码错误!" End If End Sub为什么这样设计?
- 避免在每个窗体里写
If currentUser.Role = "Admin" Then ...,降低耦合; - 符合文档 2.6.3 节“系统管理员进行系统维护”的用例图,角色边界清晰;
- 二次开发时,新增角色只需在
cmdLogin_Click()里加一个ElseIf分支,改一行代码。
3. 运行指南:从零开始,在 Windows XP/7 上跑通这个 VB6 + SQL Server 2000 组合
别被“SQL Server 2000”吓退——它比你想象中更皮实。我测试过,在 Windows 10 上用兼容模式(Windows XP SP3)运行 VB6 IDE 完全没问题,SQL Server 2000 也能通过“以管理员身份运行”安装。关键是步骤不能错,否则你会卡在“连接字符串无效”这种低级错误上。
3.1 环境准备:四个必须安装的组件
| 组件 | 版本要求 | 获取方式 | 注意事项 |
|---|---|---|---|
| VB6 开发环境 | Visual Basic 6.0 Service Pack 6 (SP6) | 微软官方已停止分发,但可从可信技术论坛下载vb6sp6.exe | 必须装 SP6,否则ADODB.Recordset在 Win10 上会报“类未注册” |
| SQL Server 2000 | Desktop Engine (MSDE) 或 Developer Edition | 微软旧版下载中心(搜索sql2kdesk) | 推荐 MSDE,轻量且免费,安装时选“混合模式认证”,sa 密码设为123456 |
| VB6 运行时 | vbrun60sp6.exe | 与 VB6 SP6 同包 | 安装后注册表会写入HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualBasic\6.0\Runtime |
| ADO 2.8 | mdac_typ.exe | 微软官网下载(MDAC 2.8) | VB6 默认带 ADO 2.1,不装 2.8 无法连接 SQL Server 2000 |
提示:如果安装 SQL Server 2000 时卡在“安装程序正在配置服务”,右键“我的电脑→管理→服务”,找到
MSSQLSERVER服务,手动启动它,再回到安装向导点“重试”。
3.2 数据库初始化:8 张表不是靠代码建,是手动附加
文档 3.3 节列出了book、borrow、login等 8 张表结构,但源码包里没有建表 SQL 脚本,只有book.mdf文件。所以你要做的是:
附加数据库:
- 打开 SQL Server 企业管理器(
C:\Program Files\Microsoft SQL Server\80\Tools\Binn\Enterprise Manager.msc) - 右键“数据库”→“所有任务”→“附加数据库”
- “数据库文件名”选
BookSystem\Data\book.mdf,点确定
- 打开 SQL Server 企业管理器(
验证表结构:
附加后展开book数据库→“表”,确认存在book、borrow、login、punishment、user、libraryer、admin、kind这 8 张表。重点检查:borrow表的receivedate字段类型是datetime,允许为空(NULL);login表的user_name是主键,且psw字段长度为 15(文档写varchar15);book表的state字段是varchar(4),值为'IN'(在库)或'OUT'(已借)。
初始化测试数据:
用企业管理器右键login表→“打开表”,手动插入三行:user_name psw admin001 123456 libr_001 123456 reader001 123456 这样登录时就能分别进入三类主窗体。
3.3 VB6 工程编译与运行:F5 之前必做的三件事
打开BookSystem.vbp后,不要急着点 F5。先做这三步,否则 90% 的人会遇到“ActiveX 组件不能创建”错误:
引用 ADO 库:
- 菜单栏
工程→引用→ 勾选Microsoft ActiveX Data Objects 2.8 Library - 如果列表里没有,点“浏览”,找到
C:\Program Files\Common Files\System\ado\msado28.tlb
- 菜单栏
设置启动窗体:
工程→工程属性→通用选项卡 → “启动对象”选frmLogin- 这是文档 2.6.1 节“系统登录”用例的落地,没设对就直接黑屏。
配置连接字符串文件:
- 新建记事本,输入:
Provider=SQLOLEDB;Data Source=localhost;Initial Catalog=book;User ID=sa;Password=123456 - 保存为
F:\conn.txt(路径必须和modDatabase.bas里strFile = New StreamReader("F://conn.txt")一致) - 如果 SQL Server 安装在非默认实例,把
localhost改成localhost\SQLEXPRESS(根据你的实例名调整)
- 新建记事本,输入:
做完这三步,按 F5,frmLogin.frm就会弹出来。输入admin001/123456,应该能顺利进入frmMainAdmin.frm。
3.4 首次运行避坑:5 个高频翻车点及解决方案
现象 → 原因 → 解决
现象:点击登录按钮无反应,或弹出“用户定义类型未定义”错误
原因:VB6 工程未引用 ADO 2.8 库,或引用了但版本不匹配(如误引了 2.1)
解决:工程→引用,取消所有 ADO 相关勾选,重新勾选Microsoft ActiveX Data Objects 2.8 Library;若仍报错,卸载 MDAC 2.8 后重装现象:登录后弹出“数据库连接失败:未指定的错误”
原因:conn.txt路径错误(VB6 读取的是绝对路径F:\conn.txt),或 SQL Server 服务未启动
解决:确认F:\conn.txt存在且内容正确;按Win+R输入services.msc,找到MSSQLSERVER服务,右键“启动”现象:管理员界面点击“添加图书”,保存后数据库里没数据
原因:book表的bannercode(图书编号)字段被设为PRIMARY KEY,但代码里没做唯一性校验,重复编号导致 INSERT 失败静默
解决:在modBook.AddBook()函数开头加校验:If GetScalar("SELECT COUNT(*) FROM book WHERE bannercode='" & bookCode & "'") > 0 Then MsgBox "图书编号已存在!": Exit Function现象:读者借书时提示“借书失败:可能图书已借出”,但
book表state='IN'
原因:borrow表里存在user_cardno='reader001' AND bannercode='B001' AND receivedate IS NULL的记录(即上次借了没还),代码逻辑认为“已借出”
解决:用企业管理器清空borrow表,或执行DELETE FROM borrow WHERE receivedate IS NULL现象:窗体中文显示为方块(乱码)
原因:VB6 IDE 的区域设置与系统不一致,或窗体字体未设为宋体
解决:工具→选项→编辑器,勾选“使用系统字体”;选中窗体上所有 Label/TextBox,属性窗口里Font设为宋体, 9pt
4. 核心模块代码精读:modBorrow.bas如何用 200 行 VB6 代码实现借阅状态机
modBorrow.bas是整个系统的业务心脏。它没用任何设计模式,但把“借-还-续-罚”四步走成了状态机。我们逐段拆解,看它怎么用最朴素的 SQL 拼接和条件判断,守住数据一致性。
4.1BorrowBook():借书不是 INSERT,是状态切换
Public Function BorrowBook(cardNo As String, bookCode As String) As Boolean Dim sql As String Dim rs As ADODB.Recordset ' 步骤1:检查读者是否存在且状态正常 sql = "SELECT user_state FROM user WHERE user_cardnumber='" & cardNo & "'" Set rs = modDatabase.getDataReader(sql) If rs.EOF Or rs.Fields("user_state").Value <> "正常" Then BorrowBook = False: Exit Function ' 读者不存在或被冻结 End If ' 步骤2:检查图书是否存在且在库 sql = "SELECT state FROM book WHERE bannercode='" & bookCode & "'" Set rs = modDatabase.getDataReader(sql) If rs.EOF Or rs.Fields("state").Value <> "IN" Then BorrowBook = False: Exit Function ' 图书不存在或已借出 End If ' 步骤3:插入借阅记录(receivedate为空表示未还) sql = "INSERT INTO borrow (user_cardno, bannercode, borrowdate, renew) VALUES ('" & cardNo & "','" & bookCode & "','" & Format(Now, "yyyy-mm-dd") & "','N')" If modDatabase.ExecuteNonQuery(sql) Then ' 步骤4:更新图书状态为'OUT' sql = "UPDATE book SET state='OUT' WHERE bannercode='" & bookCode & "'" modDatabase.ExecuteNonQuery(sql) BorrowBook = True End If End Function逻辑说明:
- 这不是简单的“插入一条记录”,而是四步原子操作:查读者→查图书→插借阅→改图书状态;
renew='N'是硬编码,默认未续借;borrowdate用Format(Now, "yyyy-mm-dd")确保日期格式统一(避免#12/31/2023#这种 Access 风格);ExecuteNonQuery()是modDatabase.bas里封装的执行非查询语句的方法,返回影响行数。
4.2ReturnBook():还书触发罚款计算,但不直接扣钱
Public Sub ReturnBook(cardNo As String, bookCode As String) Dim sql As String Dim borrowDate As Date Dim daysOverdue As Integer Dim punishmentAmount As Currency ' 1. 获取借书日期 sql = "SELECT borrowdate FROM borrow WHERE user_cardno='" & cardNo & "' AND bannercode='" & bookCode & "' AND receivedate IS NULL" Set rs = modDatabase.getDataReader(sql) If rs.EOF Then Exit Sub ' 未找到未还记录 borrowDate = rs.Fields("borrowdate").Value ' 2. 计算超期天数(当前日期 - 借书日期 - 30天宽限期) daysOverdue = DateDiff("d", borrowDate, Now) - 30 If daysOverdue > 0 Then punishmentAmount = daysOverdue * 5 ' 每超1天罚5元 ' 3. 插入罚款记录 sql = "INSERT INTO punishment (user_cardnumber, sum_account) VALUES ('" & cardNo & "'," & punishmentAmount & ")" modDatabase.ExecuteNonQuery(sql) End If ' 4. 更新借阅记录:设置还书日期,清除续借标记 sql = "UPDATE borrow SET receivedate='" & Format(Now, "yyyy-mm-dd") & "', renew='N' WHERE user_cardno='" & cardNo & "' AND bannercode='" & bookCode & "' AND receivedate IS NULL" modDatabase.ExecuteNonQuery(sql) ' 5. 更新图书状态为'IN' sql = "UPDATE book SET state='IN' WHERE bannercode='" & bookCode & "'" modDatabase.ExecuteNonQuery(sql) End Sub参数说明:
DateDiff("d", date1, date2)是 VB6 内置函数,计算两个日期间的天数差;daysOverdue > 0是罚款触发条件,30 天宽限期写死在代码里(符合文档 2.4 节“对超期的情况能自动给出提示信息”的要求);sum_account字段类型是number(10),所以punishmentAmount用Currency类型确保精度。
4.3CalcPunishment():罚款不是实时扣款,是生成待支付账单
文档摘要里提到“罚款表 (punishment)”,但modBorrow.bas里没有CalcPunishment()函数——它被拆到了ReturnBook()里。这说明:罚款逻辑是还书的副产品,不是独立业务。这种设计降低了复杂度,但也带来隐患:如果还书后系统崩溃,罚款记录可能丢失。生产环境应改为事务(BEGIN TRANSACTION),但课程设计里,它用最简单的方式完成了需求。
5. 二次开发实战:如何给系统加上“图书预约”功能(附完整代码)
很多同学问:“我想加个新功能,比如图书预约,该怎么下手?”答案是:严格遵循现有架构的扩展路径——加表→加模块→加窗体→改连接。下面以“图书预约”为例,手把手带你加一个真实可用的功能,代码可直接复制粘贴。
5.1 数据库层:新增reservation表,复用现有字段设计
根据文档 3.3 节风格,新建表reservation,字段全部沿用已有命名规范:
| 字段名 | 数据类型 | 允许为空 | 说明 |
|---|---|---|---|
res_id | int IDENTITY(1,1) PRIMARY KEY | 否 | 预约编号(自增主键) |
user_cardno | varchar(20) | 否 | 读者证件号(外键→user.user_cardnumber) |
bannercode | varchar(30) | 否 | 图书编号(外键→book.bannercode) |
res_date | datetime | 否 | 预约日期 |
status | varchar(4) | 否 | 状态:'WAIT'(待处理)/'DONE'(已通知)/'CANCEL'(已取消) |
建表 SQL(在 SQL Server 查询分析器里执行):
CREATE TABLE reservation ( res_id int IDENTITY(1,1) PRIMARY KEY, user_cardno varchar(20) NOT NULL, bannercode varchar(30) NOT NULL, res_date datetime NOT NULL DEFAULT GETDATE(), status varchar(4) NOT NULL DEFAULT 'WAIT' ) -- 添加外键约束(可选,但推荐) ALTER TABLE reservation ADD CONSTRAINT FK_reservation_user FOREIGN KEY (user_cardno) REFERENCES user(user_cardnumber) ALTER TABLE reservation ADD CONSTRAINT FK_reservation_book FOREIGN KEY (bannercode) REFERENCES book(bannercode)5.2 应用层:新增modReservation.bas,封装预约业务逻辑
新建模块modReservation.bas,代码完全模仿modBorrow.bas风格:
' modReservation.bas Option Explicit ' 预约图书:检查图书是否可预约(未被借、未被预约) Public Function ReserveBook(cardNo As String, bookCode As String) As Boolean Dim sql As String ' 检查图书是否在库 sql = "SELECT state FROM book WHERE bannercode='" & bookCode & "'" If modDatabase.GetScalar(sql) <> "IN" Then ReserveBook = False: Exit Function End If ' 检查是否已被他人预约(status='WAIT') sql = "SELECT COUNT(*) FROM reservation WHERE bannercode='" & bookCode & "' AND status='WAIT'" If modDatabase.GetScalar(sql) > 0 Then ReserveBook = False: Exit Function ' 已被预约 End If ' 插入预约记录 sql = "INSERT INTO reservation (user_cardno, bannercode) VALUES ('" & cardNo & "','" & bookCode & "')" ReserveBook = (modDatabase.ExecuteNonQuery(sql) > 0) End Function ' 取消预约 Public Function CancelReservation(resID As Integer) As Boolean Dim sql As String sql = "UPDATE reservation SET status='CANCEL' WHERE res_id=" & resID & " AND status='WAIT'" CancelReservation = (modDatabase.ExecuteNonQuery(sql) > 0) End Function ' 获取读者预约列表 Public Function GetReservationList(cardNo As String) As ADODB.Recordset Dim sql As String sql = "SELECT r.res_id, b.bookname, b.author, r.res_date, r.status " & _ "FROM reservation r " & _ "JOIN book b ON r.bannercode = b.bannercode " & _ "WHERE r.user_cardno='" & cardNo & "' ORDER BY r.res_date DESC" Set GetReservationList = modDatabase.getDataReader(sql) End Function5.3 表现层:在frmMainReader.frm上加预约功能区
打开frmMainReader.frm,拖入以下控件:
Frame(标题:图书预约)Label(文字:图书编号)TextBox(名称:txtResBookID)CommandButton(名称:cmdReserve,标题:预约)CommandButton(名称:cmdCancelRes,标题:取消预约)ListView(名称:lvReservation,用于显示预约列表)
关键代码(写在frmMainReader.frm的Form_Load和按钮事件里):
' Form_Load 事件:加载预约列表 Private Sub Form_Load() LoadReservationList End Sub ' 加载预约列表 Private Sub LoadReservationList() Dim rs As ADODB.Recordset Set rs = modReservation.GetReservationList(txtCardNo.Text) lvReservation.ListItems.Clear Do While Not rs.EOF Dim li As ListItem Set li = lvReservation.ListItems.Add(, , rs.Fields("res_id").Value) li.SubItems(1) = rs.Fields("bookname").Value li.SubItems(2) = rs.Fields("author").Value li.SubItems(3) = Format(rs.Fields("res_date").Value, "yyyy-mm-dd") li.SubItems(4) = rs.Fields("status").Value rs.MoveNext Loop End Sub ' 预约按钮 Private Sub cmdReserve_Click() If modReservation.ReserveBook(txtCardNo.Text, txtResBookID.Text) Then MsgBox "预约成功!管理员将尽快处理。" LoadReservationList ' 刷新列表 Else MsgBox "预约失败:图书可能已被借出或已被预约。" End If End Sub ' 取消预约按钮 Private Sub cmdCancelRes_Click() If lvReservation.SelectedItem Is Nothing Then Exit Sub Dim resID As Integer resID = Val(lvReservation.SelectedItem.Text) If modReservation.CancelReservation(resID) Then MsgBox "已取消预约。" LoadReservationList End If End Sub5.4 验证与联调:三步确认新功能跑通
- 数据验证:在 SQL Server 里执行
SELECT * FROM reservation,确认预约记录插入成功,status='WAIT'; - 状态验证:预约后,再去
book表查同一本bannercode,state仍是'IN'(预约不改变图书状态,只占位); - 流程验证:用管理员账号登录
frmMainAdmin.frm,在“图书管理”里把该书state改为'OUT'(模拟借出),再用读者账号尝试预约同一本书,应提示“预约失败”。
从那以后我每次给老系统加功能,都强制走一遍“建表→写模块→改窗体→手动 SQL 验证”的闭环。不是为了炫技,而是因为 VB6 + SQL Server 2000 这套组合里,没有热重载,没有单元测试框架,唯一的后悔药就是你在每一步留下的可验证痕迹。希望帮到你。
本文还有配套的精品资源,点击获取