小型收银台项目浅析

目录

1、项目背景

2、核心功能

3、数据库设计

4、接口

5、项目中遇到的问题

6、扩展


1、项目背景

众所周知,收银台即各个商铺结算付款的地方,客户在此处完成结款并获得购物票据,也可以通过这个系统快速的查出顾客结账情况、商品信息、售货情况等,这也就是传统收银台的最主要功能。但与此同时,传统收银台也存在一些缺陷,比如:收款结算速度慢、易出差错、不宜进行商品调价、商品盘点效率低、用户体验感不好。基于以上描述,所以模拟实现了一个带有一些扩展功能的小型收银台项目。

2、核心功能

此次我做的小型收银台系统也结合传统收银台的功能,并在此基础上做了一定的扩展,主要功能包括:管理员可操作的员工管理与商品管理,以及售货员可操作的收银管理。整体功能框架如下:

小型收银台项目浅析_第1张图片

1、登录模块

管理员与售货员输入自己的用户名与密码进行登录。根据用户身份不同,所具有的权限也不同,将会登录进不同的功能页面。

小型收银台项目浅析_第2张图片

2、管理员界面

  • 员工操作

         查询员工基本信息、添加新员工、删除离职员工信息、更新员工信息

  • 商品操作

        按照条件查询商品信息、商品入库、过期商品的删除、商品信息变更、查看商品销售情况

3、售货员界面

         查询商品库存信息、客户商品出售及取消出售、新增销售记录

3、数据库设计

结合本项目的功能,简单设计了以下几个表格

1、职工表

create table Employee(
id int,                       -- 员工编号
name varchar(20),             -- 员工名字
gender varchar(3),            -- 员工性别
birthday Date,                -- 生日
password varchar(20),         -- 员工密码
position varchar(10),         -- 员工职位
telphone varchar(11),         -- 联系方式
salary double(9,2)            -- 联系方式
);

其中,将员工ID设置为主键,并添加非空、自增的属性

2、商品表

create table Goods(
GoodsID int,                     -- 商品编号
GoodsName varchar(20),           -- 商品名称
GoodsType varchar(20),           -- 商品类别:水果、烟酒、日常用品、副食等
ProductDate DATE,                -- 商品生产日期
DeadDate DATE,                   -- 商品过期日期
Price double(9,2),               -- 商品价格
Unit  varchar(3),                -- 计量单位
Inventory int,                   -- 库存量:商品剩余数量
AlarmValye int                   -- 报警值:低于该值时,应提醒管理员进货
);

3、售货记录表

create table SellRecord(
GoodsName varchar(20),    -- 商品名称
GoodsPrice double(9, 2),  -- 商品价格
Amount int,               -- 售出数量
Unit varchar(3),          -- 计量单位
SellTime Date,            -- 售出时间
Operator varchar(20);    -- 售货员 

4、接口

1、界面

使用Duilib界面库,首先我们看一下传统的MFC界面库与Duilib库的区别:

传统的MFC界面库存在以下缺陷:

  • 不美观
  • 界面细节处理不好
  • 开发效率低下
  • 生成程序体积大
  • MFC界面美化库使用HOOK技术,可能会导致系统不稳定或者引发其他错误

而Duilib是一款强大轻量级的界面开发工具,可以将用户界面和处理逻辑彻底分离,极大地提高用户界面的开发效率。提供所见即所得的开发工具UIDesigner,并且使用XML来描述界面风格,界面布局,具有以下技术特点:

  • 界面与业务逻辑分离
  • 使用XML配置界面
  • 界面布局方式灵活多样
  • 内置常用的控件
  • 支持自定义控件
  • 强大的控件组合能力,复杂功能可通过简单控件组合完成
  • 支持ansi和unicode,支持多国家语言
  • 内存占用小

此处只罗列部分Duilib库的优势点,但是要注意的是Duilib仅仅是基于Win32的一套UI库,并不是使用了Duilib后就不是Win32程序了,Duilib并不像MFC一样将所有东西全包了,它仅仅包装了UI部分,其它内容还需要Win32知识。

  • 管理员操作界面

小型收银台项目浅析_第3张图片

  •  售货员操作界面

小型收银台项目浅析_第4张图片

2、数据库操作类封装

class MySQL
{
public:
	MySQL();
	bool ConnectMySQL(const char* host, const char* user, const char* password, const char* dbName);
	~MySQL();
	bool Insert(const string& strSQL);
	bool Update(const string& strSQL);
	bool Delete(const string& strSQL);
	vector> Select(const string& strSQL);
private:
	MYSQL* _mySQL;//mysql连接的实例对象
};


 MySQL::MySQL()
{
	_mySQL = mysql_init(nullptr);
}
bool MySQL::ConnectMySQL(const char* host, const char* user, const char* password, const char* dbName)
{
	if (!mysql_real_connect(_mySQL, host, user, password, dbName, 3306, nullptr, 0))
	{
		cout << "数据库连接失败" << endl;
		return false;
	}
	mysql_query(_mySQL, "set names 'gbk'");
	return true;
}
vector> MySQL::Select(const string& strSQL)
{
	vector> vvRet;
	if (mysql_query(_mySQL, strSQL.c_str()))
	{
		//SQL命令响应失败
		cout << mysql_error(_mySQL) << endl;
		return vvRet;
	}
	//获取查询的记录集
	MYSQL_RES * mySQLRes = mysql_store_result(_mySQL);
	if (mySQLRes == nullptr)
	{
		cout << mysql_error(_mySQL) << endl;
		return vvRet;
	}
	//获取记录集中有多少个字段
	int itemCount = mysql_num_fields(mySQLRes);
	MYSQL_ROW mysqlRow;
	while (mysqlRow = mysql_fetch_row(mySQLRes))
	{
		//已经获取到一条记录
		vector vItem;
		for (size_t i = 0; i < itemCount; ++i)
		{
			vItem.push_back(mysqlRow[i]);
		}
		vvRet.push_back(vItem);
	}
	mysql_free_result(mySQLRes);
	return vvRet;
}
bool MySQL::Insert(const string& strSQL)
{
	if (mysql_query(_mySQL, strSQL.c_str()))
	{
		cout << mysql_error(_mySQL) << endl;
		return false;
	}
	return true;
}

bool MySQL::Delete(const string& strSQL)
{
	if (mysql_query(_mySQL, strSQL.c_str()))
	{
		cout << mysql_error(_mySQL) << endl;
		return false;
	}
	return true;
}

bool MySQL::Update(const string& strSQL)
{
	if (mysql_query(_mySQL, strSQL.c_str()))
	{
		cout << mysql_error(_mySQL) << endl;
		return false;
	}
	return true;
}
MySQL::~MySQL()
{
    mysql_close(_mySQL);
}

该项目中,主要是通过对数据库操作来达到项目需求,其他模块无非是构建相应的SQL语句,响应对应的控件完成各个界面具体的功能,这里就不过多的赘述了,下面简单的看一下如何借助Duilib库来创建一个窗口。

首先我们知道Duilib主打的界面制作方式是XML+UI引擎+win32框架,通过XML的方式来重写窗口,然后Duilib对XML进行解析,将窗口创建成功。

以员工操作窗口CCashierWnd为例,借助UIDesigner工具新建一个XML文件CCashierWnd.xml,具体内容如下所示,然后将该文件拷贝到exe所在目录下。



    
        
            

接下来让用户实现的窗口类继承自Duilib封装的:WindowImplBase类,该类是一个Duilib的基础框架类,封装了常用操作,方便使用。

class CCashierWnd :public WindowImplBase
{
public:
	CCashierWnd(MySQL* mysql = nullptr)
		:m_pMySQL(mysql)
		{}
protected:
	virtual void Notify(TNotifyUI& msg);

	//WindowImplBase:提供的三个纯虚函数
	//xml文件对应的目录
	virtual CDuiString GetSkinFolder();

	//xml文件的名字
	virtual CDuiString GetSkinFile();

	//窗口类的名字:在注册窗口时必须提供
	virtual LPCTSTR GetWindowClassName(void) const;

	void SelectGoods();
	void AddGoodsCount();
	void SubGoodsCount();
	void InsertGoodsList();
	void CancelOrder();
	void CommitOrder();


	//void DeleteEmployeeInfo();
private:
	MySQL* m_pMySQL;
};

对于XML中给出的控件,如何进行响应?我们只需要重写NotifyUI类中的Notify纯虚函数即可。

void CCashierWnd::Notify(TNotifyUI& msg)
{
	CDuiString strName = msg.pSender->GetName();
	if (msg.sType == _T("click"))
	{
		if (strName == _T("BTN_CLOSE"))
			Close();
		else if (strName == _T("BTN_MIN"))
			::SendMessage(m_hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
		else if (strName == _T("BTN_SELECT"))
			SelectGoods();
		else if (strName == _T("BTN_ADD"))
			AddGoodsCount();
		else if (strName == _T("BTN_SUB"))
			SubGoodsCount();
		else if (strName == _T("BTN_OK"))
			InsertGoodsList();
		else if (strName == _T("BTN_COMMIT"))
			CommitOrder();
		else if (strName == _T("BTN_CANCLE"))
			CancelOrder();
	}
}
...
//下面处理具体的控件响应内容
...

5、项目中遇到的问题

整体的代码因为过多,就不在此处过多展示了,另外上传至github中,接下来再看看整个项目完成的过程中所遇到的问题。

1、配置环境

因为项目需要对数据库进行操作,还要使用Duilib库,因此需要配置好这两部分的环境,需要注意的是要看数据库是32位还是64位的,相应的编译器也要配置到相同的位,Duilib库也要按相同的位编译,不然就会遇到各种各样的错误,最终不能够正确执行代码。

2、编码格式

C++连接mysql时,比如查询语句中含有中文,或者得到结果中含有中文,经常出现编译出错或乱码的问题,VS默认使用gbk编码,所以在这里设置mysql以gbk格式编码

mysql_query(_mySql, "set names 'gbk'");

3、 UIDesigner工具使用

前面介绍了很多Duilib库的优势,它还提供了界面设计工具,避免了我们直接去写XML语句的问题,但是这个工具也有一些缺陷,比如说会修改已画好界面中的一些内容,不知道什么原因的崩溃掉,所以在使用的时候要一边画一边保存。

6、扩展

因为时间原因,以及自身水平的不足,项目现在就具有之前功能框架中介绍的这些模块,在以后的时间,还可以进一步完善这个项目,如下:

1、增加店铺会员用户管理的模块,对不同客户进行不同优惠售卖,会员积分等等功能;

2、数据安全问题。对于这样一个系统,实际使用过程中,可能会存在多人同时操作的情况存在,但是在项目中并没有考虑这个问题,在之后的扩展中可以考虑如何保证数据安全的问题。

 

 

 

你可能感兴趣的:(项目浅析)