当前位置: 首页 > news >正文

【数据库课程设计】网上投票管理系统

目录

前言:

一,系统需求分析

1,需求概述

2,系统功能图

3,业务流程图 

业务流程分析

业务流程图

4,数据流程图 

5,数据字典 

二,概念结构设计

1,实体分析

2,属性分析

3,联系分析

4,概念模型分析(CDM图) 

三,逻辑结构设计

逻辑结构模型

逻辑结构图 (LDM)

四,物理结构设计

1,表设计

2,建表sql语句

3,物理结构(PDM图)

五,数据库功能实现及界面展示

1,确定数据库需要创建的对象

视图

自定义函数 

存储过程 

触发器 

2,界面布局及实现

遇到的问题: 

源码:


前言:

开发环境:SQL Server 2022,Qt Creator 4.11.1 (Community)

源码在文章末尾

结果预览:

屏幕录制 2025-05-20 183909

一,系统需求分析

1,需求概述

(1)应用系统背景

随着互联网技术的发展,传统线下投票方式(如纸质投票、会议举手表决等)逐渐暴露出效率低、成本高、统计复杂、安全性差等问题。网上投票管理系统旨在通过数字化手段实现投票流程的自动化,支持多场景投票需求(如企业决策、校园活动、社会调研等),提供高效、安全、透明的投票服务。

系统目标

  1. 提高投票效率和准确性,减少人工统计错误;

  2. 支持匿名/实名投票、单选/多选、限时投票等多种模式;

  3. 保障数据安全性,防止刷票、篡改等恶意行为;

  4. 提供友好的用户界面和实时结果可视化功能。

(2)组织结构情况

  • 普通用户:参与投票、查看投票结果。

  • 管理员:创建/管理投票活动、审核用户身份、设置投票规则。

  • 审核员:对敏感投票内容进行人工审核。

  • 系统管理员:维护系统安全与数据库。

(3)需求分析过程

1,需求收集方法:

  • 问卷调查:面向企业、学校等潜在用户,收集投票场景需求。

  • 竞品分析:研究现有投票系统(如腾讯投票、问卷星)的功能优缺点。

  • 专家访谈:与信息安全专家讨论防刷票、数据加密方案。

2,核心需求整理

  • 功能性需求

    • 用户注册/登录(支持手机号、邮箱、第三方登录);

    • 投票创建(设置标题、选项、截止时间、投票规则);

    • 投票参与(匿名/实名模式、防重复提交);

    • 结果统计(实时图表展示、数据导出为Excel/PDF);

    • 审核机制(敏感词过滤、人工审核流程)。

  • 非功能性需求

    • 性能:支持1000人同时在线投票,响应时间<2秒;

    • 安全性:HTTPS传输、数据库加密、IP限制防刷票;

    • 兼容性:适配PC、手机浏览器及微信小程序。

2,系统功能图

3,业务流程图 

业务流程分析

1,用户注册与身份验证流程

  • 新用户通过邮箱/手机号注册,系统验证唯一性后创建账户。
  • 管理员可对用户信息进行审核。

2,投票创建与发布流程

  • 管理员填写投票基本信息(标题,选项,截止时间等等)
  • 审核通过后 ,投票进入“已发布”状态,用户可见。

3,用户参与投票流程

  • 用户选择投票活动,根据规则(实名/匿名)提交选择。
  • 系统校验用户权限。
  • 投票实时记录,并写入数据库。

4,投票处理流程

  • 投票时间到后,系统自动关闭并锁定数据。
  • 支持查看投票结果。

业务流程图

 

4,数据流程图 

5,数据字典 

1,用户表(User)

表说明
存储系统用户信息,支持角色权限管理。用户名和邮箱需唯一,密码加密存储。

字段名数据类型长度是否允许为空默认值键/索引说明
UserIDINT11主键用户唯一标识,自增
UsernameNVARCHAR50唯一索引用户名
PasswordNVARCHAR128密码
EmailNVARCHAR100用户邮箱
RoleNVARCHAR10'user'索引用户角色
CreatedAtDATETIME-GETDATE()用户注册时间

2,投票主表(Vote)

表说明
存储投票活动的基本信息,通过外键关联创建者。状态字段控制投票生命周期。

字段名数据类型长度是否允许为空默认值键/索引说明
VoteIDINT11主键投票唯一标识,自增
TitleNAVRCHAR100投票标题
CreatorIDINT11外键User投票创建者 ID
IsAnonymousBIT0是否匿名投票:0(实名),1(匿名)
MaxChoicesINT111用户最多可选选项数(单选/多选)
EndTimeDaATETIME否 索引投票结束时间
StatusNVARCHAR10'draft'联合索引状态:draft(草稿),published(已发布),closed(已关闭)

3,投票选项表(VoteOption)

表说明
存储投票的选项信息,每个投票可包含多个选项,通过外键关联投票主表。

字段名数据类型长度是否允许为空默认值键/索引说明
OptionIDINT11主键选项唯一标识,自增
VoteIDINT11外键->Vote关联的投票ID
OptionTextNVARCHAR200选项文本内容

 4,投票记录表(VoteRecord)

表说明
记录用户投票行为,匿名投票时UserID为NULL。通过唯一约束(UserID+VoteID)防止重复投票。

字段名数据类型长度是否允许为空默认值键/索引说明
RecordIDINT11主键投票记录唯一标识,自增
VoteIDINT11外键->Vote关联投票ID
UserIDINT11NULL外键->User投票用户ID,匿名时为NULL
OptionIDINT11外键->VoteOption用户选择的选项ID
VoteTimeDATETIMEGETDATE()索引投票提交时间
IPAddressNVARCHAR45用户投票时的投票IP

5,审核日志表 (AuditLog)

表说明
记录投票审核的操作日志,确保投票内容的合规性。

字段名数据类型长度是否允许为空默认值键/索引说明
LogIDINT11主键唯一标识 ,自增
VoteIDINT11外键->Vote被审核的投票ID
AuditorLogINT11外键->User审核员用户ID
ActionNVARCHAR10审核操作:通过,驳回
CommentNVARCHAR(MAX)NULL审核意见(文本)
AuditTimeDATETIMEGETTIME()审核时间

二,概念结构设计

数据库概念结构设计是指将系统需求转化为一个抽象的信息结构,即概念模型。

1,实体分析

实体识别,核心实体:

User(用户),Vote(投票),VoteOpston(投票选项),VoteRecord(投票记录),AyditLog(审核日志)

2,属性分析

实体特征:

为每个实体定义唯一标识符(主键)和描述性属性。

为每个实体定义唯一标识(主键约束),然后根据业务需求确立其他字段。(如非空、唯一性、默认值)。

  • User 实体UserID(主键)、UsernamePasswordRole

  • Vote 实体VoteID(主键)、TitleEndTimeStatus

3,联系分析

  • 根据业务流程分析实体间交互(如用户创建投票、用户选择选项)。

  • 确定关系基数(1:1、1:N、M:N)。

实体与实体之间的关系:

确定关系基数,用户:投票=1:n(一个用户可以创建多个投票活动)

投票:选项=1:n(一个投票包含多个选项)等等。

实体关系模型:E-R图如下

4,概念模型分析(CDM图) 

三,逻辑结构设计

数据库的逻辑设计的任务是把概念设计阶段设计好的基本E-R图转换为与选用的具体机器上的DBMS所支持的数据模型相符合的逻辑结构。根据ER图 写出关系模式,并标出主键外键。

1,实体到表的转换

每个实体映射为一张表,属性转换为表的字段。关系模型的基本映射规则(实体-表,属性-列)。示例:User实体->User表;Vote实体->Vote表。

2,关系处理

1:n关系:通过外键在“多”端表中引用“一”端表中的主键。

3,主键与唯一键约束

主键(Primary Key):每个表定义唯一标识符。如自增(auto increment)

唯一性约束:防止数据重复,如用户名唯一。

逻辑结构模型

1,用户表(User)

字段名数据类型约束说明
UserIDINTPRIMARY KEY IDENTITY用户唯一标识
UsernameNVARCHAR(50)UNIQUE NOT NULL用户名(唯一)
PasswordNVARCHAR(128)NOT NULL密码(加密)
EmailNVARCHAR(100)NOT NULL用户邮箱
RoleNVARCHAR(10)CHECK (Role IN ('user','admin','auditor')) DEFAULT 'user'用户角色
CreatorAtDATETIMEDEFAULT GETDATE()注册时间

2,投票主表(Vote)

字段名数据类型约束说明
VoteIDINTPRIMARY KEY IDENTITY投票唯一
TitleNVARCHAR(100)NOT NULL投票标题
CreatorIDINTFOREIGN KEY REFERENCES User(UserID) 创建者ID
IsAnonymousBITDEFAULT 0

0实名,

1匿名

MaxChoicesINTDEFAULT 1最多可选数
EndtimeDATETIMENOT NULL截止时间
StatusNVARCHAR(10)CHECK (Status IN ('draft','published','closed')) DEFAULT 'draft'投票状态

3,投票选项表(VoteOption)

字段名数据类型约束说明
OptionIDINTPRIMARY KEY IDENTITY选项唯一标识
VoteIDINTFOREIGN KEY REFERENCES Vote(VoteID)所属投票ID
OptionTextNVARCHAR(200)NOT NULL选项文本内容

4,投票记录表(OptionRecord)

字段名数据类型约束说明
RecordIDINTPRIMARY KEY INENTITY记录唯一标识
VoteIDINTFOREIGN KEY REFERENCES Vote(VoteID) 关联投票ID
UserIDINTFOREIGN KEY REFERENCES User(UserID)投票用户ID
OptionIDINTFOREIGN KEY REFERENCES VoteOption(OptionID)用户选择的选项ID
VoteTimeDATETIMEDEFAULT GETDATE()投票时间
IPAddressNVARCHAR(45)NOT NULL用户IP地址

5,审核日志表 (AuditLog)

字段名数据类型约束说明
LogIDINTPRIMARY KEY IDENTITY日志唯一标识
VoteIDINTFOREIGN KEY REFERENCES Vote(VoteID)被审核的投票ID
AuditorIDINTFOREIGN KEY REFERENCES User(UserID)审核员ID
ActionNVARCHAR(10)CHECK (Action IN ('approve','reject'))审核操作
CommentNVARCHAR(200)NULL审核意见
AuditTimeDATETIMEDEFAULT GETDATE()审核时间

逻辑结构图 (LDM)

四,物理结构设计

1,表设计

存储优化:

使用NVARCHAR存储多语言文本(如中文,符号等等)。

自增主键IEDNTITY(1,1)替身插入性能。

完整性约束:

级联删除:删除用户时自动清理其生成的投票(ON DELETE CASCADE)

索引策略:

高频查询字段:Vote表中的Status和EndTime联合索引,加速查询。

时间范围查询:VoteRecord表中的VoteTime创建索引。

安全设计:

密码字段使用SHA2_256(哈希算法)。

匿名投票时,强制IPAddress非空。

2,建表sql语句

注:下面 的建表语句中,有的表的名称 加上了[ ],目的是避免你创建的表,或查询与一些SQL SERVER自带的关键字发生冲突

比如下面创建了一个的User表,而系统中也包含这一张表,所以需要加上[ ],避免冲突。

-- 1. 用户表
CREATE TABLE [User](UserID INT IDENTITY(1,1) PRIMARY KEY,Username NVARCHAR(50) NOT NULL UNIQUE,Password NVARCHAR(128) NOT NULL,Email NVARCHAR(100),Role NVARCHAR(10) CHECK (Role IN ('user', 'admin', 'auditor')) DEFAULT 'user',CreatedAt DATETIME NOT NULL DEFAULT GETDATE()
);
GO-- 2. 投票主表
CREATE TABLE Vote (VoteID INT IDENTITY(1,1) PRIMARY KEY,Title NVARCHAR(100) NOT NULL,CreatorID INT NOT NULL FOREIGN KEY REFERENCES [User](UserID) ON DELETE CASCADE,IsAnonymous BIT NOT NULL DEFAULT 0,MaxChoices INT NOT NULL DEFAULT 1 CHECK (MaxChoices > 0),EndTime DATETIME NOT NULL,
);
GO-- 3. 投票选项表
CREATE TABLE VoteOption (OptionID INT IDENTITY(1,1) PRIMARY KEY,VoteID INT NOT NULL FOREIGN KEY REFERENCES Vote(VoteID) ON DELETE CASCADE,OptionText NVARCHAR(200) NOT NULL
);
GO-- 4. 投票记录表
CREATE TABLE VoteRecord (RecordID INT IDENTITY(1,1) PRIMARY KEY,VoteID INT NOT NULL FOREIGN KEY REFERENCES Vote(VoteID) ON DELETE NO ACTION ,UserID INT NULL FOREIGN KEY REFERENCES [User](UserID)  ON DELETE SET NULL,OptionID INT NOT NULL FOREIGN KEY REFERENCES VoteOption(OptionID) ON DELETE NO ACTION ,VoteTime DATETIME NOT NULL DEFAULT GETDATE(),IPAddress NVARCHAR(45) NOT NULL,-- 唯一约束防止重复投票(匿名投票需程序补充IP校验)CONSTRAINT UK_User_Vote UNIQUE (UserID, VoteID)
);
GO-- 5. 审核日志表
CREATE TABLE AuditLog (LogID INT IDENTITY(1,1) PRIMARY KEY,VoteID INT NOT NULL FOREIGN KEY REFERENCES Vote(VoteID) ON DELETE CASCADE,AuditorID INT NOT NULL FOREIGN KEY REFERENCES [User](UserID),Action NVARCHAR(10) NOT NULL CHECK (Action IN ('approve', 'reject')),Comment NVARCHAR(MAX) NULL,AuditTime DATETIME NOT NULL DEFAULT GETDATE()
);
GO-- 6. 索引设计
CREATE INDEX idx_User_Role ON [User] (Role);
CREATE INDEX idx_Vote_Status_EndTime ON Vote (Status, EndTime);
CREATE INDEX idx_VoteRecord_VoteTime ON VoteRecord (VoteTime);
CREATE INDEX idx_AuditLog_AuditTime ON AuditLog (AuditTime);

3,物理结构(PDM图)

五,数据库功能实现及界面展示

1,确定数据库需要创建的对象

视图

视图(views):简化复杂查询,如统计投票结果,显示待审核的投票。

投票结果视图:展示已发布投票的每个选项得票数

CREATE VIEW vw_VoteResults AS
SELECT v.VoteID,v.Title,vo.OptionID,vo.OptionText,COUNT(vr.OptionID) AS VoteCount
FROM Vote v
JOIN VoteOption vo ON v.VoteID = vo.VoteID
LEFT JOIN VoteRecord vr ON vo.OptionID = vr.OptionID
GROUP BY v.VoteID, v.Title, vo.OptionID, vo.OptionText;

待审核投票视图:列出所有状态为"草稿"的 视图,包含创建者及截止时间。

CREATE VIEW vw_PendingAudits AS
SELECT v.VoteID,v.Title,u.Username AS Creator,v.CreatedAt,v.EndTime
FROM Vote v
JOIN [User] u ON v.CreatorID = u.UserID
WHERE v.Status = 'draft';

用户投票记录视图:仅显示实名投票记录,包含用户,投票及选项信息。

CREATE VIEW vw_UserVoteHistory AS
SELECT u.UserID,u.Username,v.VoteID,v.Title,vo.OptionText AS VotedOption,vr.VoteTime
FROM VoteRecord vr
JOIN [User] u ON vr.UserID = u.UserID
JOIN Vote v ON vr.VoteID = v.VoteID
JOIN VoteOption vo ON vr.OptionID = vo.OptionID
WHERE v.IsAnonymous = 0;

删除投票视图

--CREATE PROCEDURE sp_DeleteVote
--    @VoteID INT,
--    @RequesterUserID INT
--AS
--BEGIN
--    BEGIN TRY
--        BEGIN TRANSACTION--        --  验证权限:仅管理员或创建者可删除
--        IF NOT EXISTS (
--            SELECT 1 
--            FROM Vote 
--            WHERE VoteID = @VoteID 
--            AND (
--                CreatorID = @RequesterUserID 
--                OR EXISTS (
--                    SELECT 1 
--                    FROM [User] 
--                    WHERE UserID = @RequesterUserID 
--                    AND Role = 'admin'
--                )
--            )  
--        )
--        BEGIN
--            RAISERROR('无权删除该投票', 16, 1)
--            RETURN
--        END--        -- 执行删除(触发器处理级联删除)
--        DELETE FROM Vote 
--        WHERE VoteID = @VoteID--        COMMIT TRANSACTION
--    END TRY
--    BEGIN CATCH
--        IF @@TRANCOUNT > 0
--            ROLLBACK TRANSACTION;
--        THROW;  -- 抛出原始错误
--    END CATCH
--END

自定义函数 

自定义函数::用于业务逻辑,如检查用户是否已投票、计算选项得票数。

检查用户是否已投票(防止重复投票)

CREATE FUNCTION dbo.fn_HasUserVoted (@UserID INT,@VoteID INT
)
RETURNS BIT
AS
BEGINDECLARE @Result BIT = 0;IF EXISTS (SELECT 1 FROM VoteRecord WHERE UserID = @UserID AND VoteID = @VoteID)SET @Result = 1;RETURN @Result;
END;

存储过程 

存储过程:封装业务操作,如创建投票、提交投票、审核投票。

创建投票:

CREATE PROCEDURE sp_CreateVote@Title NVARCHAR(100),@CreatorID INT,@IsAnonymous BIT,@MaxChoices INT,@EndTime DATETIME,@Options NVARCHAR(MAX) -- JSON格式: ["Option1", "Option2"]
AS
BEGINBEGIN TRANSACTION;-- 插入投票主表INSERT INTO Vote (Title, CreatorID, IsAnonymous, MaxChoices, EndTime)VALUES (@Title, @CreatorID, @IsAnonymous, @MaxChoices, @EndTime);DECLARE @VoteID INT = SCOPE_IDENTITY();-- 解析并插入选项INSERT INTO VoteOption (VoteID, OptionText)SELECT @VoteID, [value]FROM OPENJSON(@Options);-- 自动触发敏感词检测IF EXISTS (SELECT 1 FROM VoteOption WHERE VoteID = @VoteIDAND dbo.fn_CheckSensitiveWords(OptionText) = 1)BEGIN-- 存在敏感词,状态设为待审核UPDATE Vote SET Status = 'draft' WHERE VoteID = @VoteID;ENDELSEBEGIN-- 无敏感词,直接发布UPDATE Vote SET Status = 'published' WHERE VoteID = @VoteID;ENDCOMMIT TRANSACTION;
END;

用户提交投票:

CREATE PROCEDURE sp_SubmitVote@VoteID INT,@UserID INT, -- 匿名时为NULL@OptionIDs NVARCHAR(MAX), -- JSON格式: [1, 2]@IPAddress NVARCHAR(45)
AS
BEGINBEGIN TRYBEGIN TRANSACTION;-- 检查投票是否有效IF NOT EXISTS (SELECT 1 FROM Vote WHERE VoteID = @VoteID AND Status = 'published'AND EndTime > GETDATE())RAISERROR('投票不存在或已截止!', 16, 1);-- 检查选项数量DECLARE @OptionCount INT = (SELECT COUNT(*) FROM OPENJSON(@OptionIDs));IF @OptionCount > (SELECT MaxChoices FROM Vote WHERE VoteID = @VoteID)RAISERROR('超出最大可选数量!', 16, 1);-- 实名投票检查重复IF @UserID IS NOT NULL AND dbo.fn_HasUserVoted(@UserID, @VoteID) = 1RAISERROR('您已参与过本次投票!', 16, 1);-- 匿名投票检查IP限制IF @UserID IS NULL AND EXISTS (SELECT 1 FROM VoteRecord WHERE VoteID = @VoteID AND IPAddress = @IPAddressAND VoteTime >= DATEADD(HOUR, -24, GETDATE()))RAISERROR('同一IP24小时内仅能投票一次!', 16, 1);-- 插入投票记录INSERT INTO VoteRecord (VoteID, UserID, OptionID, IPAddress)SELECT @VoteID, @UserID, [value], @IPAddressFROM OPENJSON(@OptionIDs);COMMIT TRANSACTION;END TRYBEGIN CATCHROLLBACK TRANSACTION;THROW;END CATCH
END;

触发器 

触发器:触发器是一种特殊的存储过程,它会在特定的数据库事件(如插入,删除,更新等等)发生时自动执行。触发器与表直接关联,用于在数据变动时,完成某些业务逻辑,从而保证数据的一致性,完整性和自动化处理。

自动更新选项的票数:每次插入投票记录时,对应选项的 VoteCount字段自动+1

CREATE TRIGGER trg_UpdateVoteCount
ON VoteRecord
AFTER INSERT
AS
BEGINUPDATE voSET vo.VoteCount = vo.VoteCount + 1FROM VoteOption voJOIN inserted i ON vo.OptionID = i.OptionID;
END;

防止修改已结束的投票:拦截对已截止投票的修改操作,确保数据不可变性。

CREATE TRIGGER trg_PreventModifyClosedVote
ON Vote
INSTEAD OF UPDATE
AS
BEGINIF UPDATE(EndTime) OR UPDATE(Status)BEGINIF EXISTS (SELECT 1 FROM inserted iJOIN deleted d ON i.VoteID = d.VoteIDWHERE d.EndTime < GETDATE())RAISERROR('投票已截止,禁止修改!', 16, 1);ELSEUPDATE vSET Title = i.Title,EndTime = i.EndTime,Status = i.StatusFROM Vote vJOIN inserted i ON v.VoteID = i.VoteID;END
END;

2,界面布局及实现

程序开始界面

登录/注册界面

 
 

 

主页面

遇到的问题: 

在进行新建投票的操作过程中,出现userID冲突的过程。找了半天是在用户登录注册代码部分,获取userID时,由于通过map查找userID时,字符串大小写搞错了,一直获取的是同一个userID。

还有就是对于选项表,起初的想法是按照数组的特点,每个选项对应一个下标,运行后才发现这样做使得OptionID发生冲突,也就是发生主键冲突。解决办法是将每个选项的文本和它的选项ID拼接在一起,获取选项ID的时候,直接取选项的第一个字符然后转为整数(先这么做,这里看到会存在问题的)。

源码:

网上投票系统: 这是一个数据库课程设计,关于网上投票管理系统的,使用到的技术QT,使用的数据库SQL-Server - Gitee.com

相关文章:

  • 【Linux】进程间通信(三):命名管道
  • PyTorch进阶实战指南:01自定义神经网络组件开发
  • JavaScript 性能优化:调优策略与工具使用
  • Java转Go日记(四十四):Sql构建
  • 深入解析 HTTP 中的 GET 请求与 POST 请求​
  • Android Framework学习七:Handler、Looper、Message
  • 【DCGMI专题1】---DCGMI 在 Ubuntu 22.04 上的深度安装指南与原理分析(含架构图解)
  • 谷歌宣布推出 Android 的新安全功能,以防止诈骗和盗窃
  • Opencv常见学习链接(待分类补充)
  • 企业级物理服务器选型指南 - 网络架构优化篇
  • 【小明剑魔视频Viggle AI模仿的核心算法组成】
  • 什么是Rootfs
  • Python的蚁群优化算法实现与多维函数优化实战
  • 雷军:芯片,手机,平板,SUV一起发
  • Java 06API时间类
  • Backend - Oracle SQL
  • Sql刷题日志(day9)
  • Ansible模块——管理100台Linux的最佳实践
  • Ansible模块——通过 URL 下载文件
  • HTTP/HTTPS与SOCKS5协议在隧道代理中的兼容性设计解析
  • 秦洪看盘|热门股或将退潮,短线波动难免
  • 海南征集民生领域涉嫌垄断违法行为线索,包括行业协会等领域
  • 住建部:2019年至2024年,全国累计开工改造老旧小区28万个
  • 广州某科技公司遭网络攻击,境外“黑手”被锁定
  • 文化破冰,土耳其亚美尼亚合拍摄影大师阿拉·古勒传记片
  • 长沙至赣州高铁初步设计获批,可填补湘赣两省斜向交通空白