大三小学期分到了最不喜欢的课题——机房在线机位预定系统,课题要求较多,功能繁琐。真心羡慕别人分到Android开发,简单实现几个图像滤镜就可以放纵了。OK,发完牢骚,面对现实...
先看课题要求:
一、设计目标
为了更方便地规范学生课外上机,且增加自主选时的灵活性,设计实现一个能够进行在线机位预订的系统。学生根据系统提供的时间段、机房等信息,在可视化“机位分布图”上选择位置,预订机位。管理员可以按日期、时间段、机房、班级等信息,进行查询统计,为机房资源管理以及学生课外上机管理提供方便。
二、课设要求
此系统作为一个用来进行机位管理的应用软件,在对机房管理需求进行分析的基础上,需要充分考虑系统的可用性和有效性,联系实际应用,从而得到合理的图形界面的应用软件。具体功能要求如下:
1 设置、修改密码及退出系统
为本系统设置密码、可以修改密码,能够正常退出系统。
2 机位信息管理
l 设定机位信息
机房的座位是固定的,机位信息也是固定的。机房固定机位信息包括日期(年、月、日)、星期、时间(时、分)、机位号。
l 机位预订
机位预订是指学生预订机位,采用实名制。
学生办理预订时,系统可以按所要求的日期、时间、机房随机分配给他具有相应机位号的机位,并在“机位分布图”上做出标识;或者自己在“机位分布图”上选择机位。若学生预订机位成功,则应生成相应的“机位预订确认单”。
l “机位预订确认单”生成
学生每次预订成功之后,都要有相应的“机位预订确认单”,像电影票一样。
l 机位退订
当学生想退掉已经预订的机位时,要办理退订业务。
3 查询统计
l 信息查询
按照不同查询条件分别输出相应的机位信息、机位数量信息、预订信息等,查询到的信息以列表形式显示,要求显示全部符合条件的信息。
l 信息统计
按照不同统计条件分别统计出相应的机位、学生预订、班级预订等信息的相关总数量,将统计到的信息以列表形式全部显示。可以图形方式展示,如饼图、折线图等。
l 汇总报表
按照不同查询、统计条件,分别以报表形式显示相应的机位信息、机位数量信息、预订信息等。以月为单位,为每个班级准备一份报表。根据实际情况,可以有多种汇总报表,以满足不同需求,自己酌情增加。
4 机位分布图
为各个机房设计一个动态的机位分布以及实时机位预订示意图,能够直观展示机位的预订、剩余分布情况。
5 条形码或二维码(选作)
每个机位预订确认单上加入一个条形码或二维码。
6 收费管理(选作)
学生每预订一次机位,要计费。在相应的各个环节中加入费用项,包括单价、总费用。
OK,基本功能了解,开始考虑用什么开发,首选当然是Windows窗体应用程序了,拖拖控件、绑定数据库、简单撸点代码完事。但是....................我偏要用Unity开发,没错,Unity!主要是因为大四想找个Unity游戏客户端开发的实习工作,趁此机会多研究研究Unity,项目需要图表(Chart)、日期时间选择(DateTimePicker)等功能,这些在Windows窗体应用程序中都有相应的控件,用Unity就需要自己造轮子了。
[2017/6/24更新]
1.SQL Server数据库的设计
①用户信息表
id | password | name | class | sex | permission |
账号 | 密码 | 名字 | 班级 | 性别 | 权限 |
②机房信息表
roomNumber | computerCount | eveyRowCount | startTime | endTime |
机房号 | 机位总数 | 每排机位数 | 机房开放时间 | 机房关闭时间 |
③预定信息表
paymentID | userID | dateTime | roomNumber | computerNumber | startTime | endTime |
订单号 | 用户ID | 日期 | 机房号 | 机位号 | 开始时间 | 结束时间 |
2.Unity连接SQL Server数据库
①把Unity安装目录下Unity\Editor\Data\Mono\lib\mono\unity以下几个依赖文件复制到Unity项目的Assets目录
I18N.CJK.dll
I18N.dll
I18N.West.dll
System.Data.dll
②启动SQL Server服务,创建好相关的数据库及表
③Unity连接SQL Server数据库代码
string connectStr = "Server=127.0.0.1,1579;" +
"Database=AppDatabase;" +
"User ID=sa;" +
"Password=sa;";
SqlConnection sqlConnect = new SqlConnection(connectStr);
sqlConnect.Open();
string commandStr = "select * from [AppDatabase].[dbo].[User]";
SqlCommand command = new SqlCommand(commandStr, sqlConnect);
SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
Debug.Log(reader[i].ToString());
}
}
reader.Close();
【Warning】
connectionString中Server一定要指定端口号并且启用SQL Server的TCP/IP协议,否则会出现报错:“Server does not exist or connection refused. SocketException: 由于目标计算机积极拒绝,无法连接。”
查看端口号:
3.用户登陆/用户注册/修改密码
①用户登陆:
如果数据库中存在账号且密码正确,然后查询该登陆用户的权限(属于管理员还是普通用户)
如果是管理员,切换到带有管理功能的管理界面(可以对机房信息、用户信息、班级信息等进行修改)。如果是普通用户切换到普通界面(只能进行机房等信息的查询,以及机位预定)
②用户注册:
用户注册需要填写必要的用户信息,其中班级信息列表是由管理员添加到数据库的,客户端需要从数据库读取全部班级填充到下拉列表以便选取
代码实现:
var reader = DataManager.Instance().getData("select class from [AppDatabase].[dbo].[Class]");
List<Dropdown.OptionData> dataList = new List<Dropdown.OptionData>();
while (reader.Read())
{
dataList.Add(new Dropdown.OptionData(reader[0].ToString()));
}
classDropdown.AddOptions(dataList);
reader.Close();
③修改密码:
如果输入原密码正确,并且两次输入新密码匹配则修改数据库中当前用户的密码4.可视化机位分布/空闲查询/机位预定
①按照条件查询机位:
用户根据日期、时段、机房等信息查询机房中的所有机位在对应时段时的预定状态,如果该时段已被预定,则对应机位显示灰色(不可预定)
②机位分布List View:
根据用户选择的日期、时段、机房等信息,显示出对应机位信息,每个机位有预定、空闲查询的功能:
1.初始化选择列表:
读取机房信息表中的信息,填充到选择列表中,供用户按照条件选择机位
2.初始化机位分布图:
根据机房信息表中的机位总数、每排机位数修改List View的Grid Layout Group的列数,然后向List View中添加Item预制体
基本逻辑代码:
//显示机位分布
void InitComputerView()
{
//判断选择的时段是否在机房开放时段
//如果在开放时段 显示机位预定状态
if (DateTimeAvailable())
{
//获取当前选择的条件
dateStr = System.Text.RegularExpressions.Regex.Replace(
dateDropdown.captionText.text, "[(][A-Za-z]*[)]", "");
roomNumStr = roomDropdown.captionText.text;
startTime = timePick.startTime;
endTime = timePick.endTime;
//先清空List View
foreach (Transform obj in content.transform)
{
Destroy(obj.gameObject);
}
string commandStr = string.Format(
"select computerCount,everyRowCount from [dbo].[ComputerRoom] where roomNumber='{0}'",
roomDropdown.captionText.text);
var reader = DataManager.Instance().getData(commandStr);
if (reader.Read())
{
var layout = content.GetComponent<GridLayoutGroup>();
int result = 12;
int.TryParse(reader[1].ToString(), out result);
layout.constraintCount = result;
int roomCount = 72;
int.TryParse(reader[0].ToString(), out roomCount);
reader.Close();
GameObject newItem = null;
Button[] bts = null;
//Text pcNumText = null;
for (int i = 1; i <= roomCount; i++)
{
newItem = Instantiate<GameObject>(pcItemPrefab);
var pcNumText = newItem.GetComponentInChildren<Text>();
pcNumText.text = string.Format("{0}", i);
newItem.transform.SetParent(content.transform);
bts = newItem.GetComponentsInChildren<Button>();
bts[0].onClick.AddListener(delegate ()
{
//空闲查询,弹出对话框 显示对应机位对应日期的所有空间时段
Debug.Log("查询机位:" + pcNumText.text);
});
bts[1].onClick.AddListener(delegate ()
{
//订购响应事件
Dialog dialogWin = new Dialog();
string contentStr = string.Format(
"订单信息{0}机房:{1}{2}机位:{3}{4}时间:{5}到{6}",
Environment.NewLine, roomNumStr, Environment.NewLine,
int.Parse(pcNumText.text), Environment.NewLine,
startTime,endTime);
dialogWin.SetContent(contentStr);
dialogWin.SetPositiveEvent(delegate ()
{
CreatePaymentInfo(dateStr, roomNumStr, int.Parse(pcNumText.text), startTime, endTime);
});
dialogWin.SetVisible(true);
});
var imageObj = newItem.transform.Find("Image");
if (imageObj)
{
var icon = imageObj.GetComponent<Image>();
//判断该机位是否空闲并设置电脑图标和预定按钮的状态
if (ComputerAvailable(dateStr, startTime, endTime, roomNumStr, i))
{
icon.overrideSprite = ableTex;
bts[1].interactable = true;
}
else
{
icon.overrideSprite = unableTex;
bts[1].interactable = false;
}
}
}
}
else
{
Debug.Log("读取机位总数,每排机位数失败");
}
}
}
【Warning】
Build出exe文件想测试一下,结果运行.exe后报错There should be '<exe File Name>_Data' folder next to the executable, 纳尼?明明是有这个文件夹的,为啥说找不到?在Stack Overflow上查到把Player Setting中Api Compatibility Level改成.Net 2.0就正常了