#include <graphics.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <time.h>
#include <windows.h>
#include <locale.h>
#include
#define MAX_MEDICINES 500
#define MAX_EMPLOYEES 100
#define MAX_RECORDS 1000
// 颜色定义
#define BACKGROUND_COLOR RGB(245, 245, 255)
#define BUTTON_COLOR RGB(70, 130, 180)
#define BUTTON_HOVER_COLOR RGB(100, 149, 237)
#define TEXT_COLOR RGB(255, 255, 255)
#define TITLE_COLOR RGB(25, 25, 112)
#define WARNING_COLOR RGB(220, 20, 60)
#define SUCCESS_COLOR RGB(0, 128, 0)
#define HEADER_COLOR RGB(176, 196, 222)
#define GRID_COLOR RGB(200, 200, 220)
// 全局变量
int saveflag = 0; // 是否需要保存
int width = 1000, height = 700;
int current_user_type = 0; // 0-未登录, 1-药房, 2-仓库, 3-人事
// 药品结构体
struct Medicine {
int id; // 药品编号
char name[50]; // 药品名称
int warehouse_qty; // 仓库库存
int pharmacy_qty; // 药房库存
float price_in; // 进价
float price_out; // 售价
};
// 员工结构体
struct Employee {
int id; // 员工ID
char name[20]; // 姓名
int age; // 年龄
char position[20]; // 岗位
float salary; // 工资
char username[20]; // 用户名
char password[20]; // 密码
};
// 进货记录
struct PurchaseRecord {
int id; // 记录ID
int med_id; // 药品ID
char med_name[50]; // 药品名称
char date[20]; // 进货日期
int employee_id; // 操作员工ID
int quantity; // 进货数量
float price; // 进货价格
};
// 销售记录
struct SalesRecord {
int id; // 记录ID
int med_id; // 药品ID
char med_name[50]; // 药品名称
char date[20]; // 销售日期
int employee_id; // 操作员工ID
int quantity; // 销售数量
float price; // 销售价格
float total; // 总金额
};
// 补货申请
struct Replenishment {
int id; // 申请ID
int med_id; // 药品ID
char med_name[50]; // 药品名称
int quantity; // 申请数量
char status[20]; // 状态
};
// 链表节点
typedef struct MedNode {
struct Medicine data;
struct MedNode* next;
} MedNode, * MedList;
typedef struct EmpNode {
struct Employee data;
struct EmpNode* next;
} EmpNode, * EmpList;
typedef struct PurchaseNode {
struct PurchaseRecord data;
struct PurchaseNode* next;
} PurchaseNode, * PurchaseList;
typedef struct SalesNode {
struct SalesRecord data;
struct SalesNode* next;
} SalesNode, * SalesList;
typedef struct ReplenishNode {
struct Replenishment data;
struct ReplenishNode* next;
} ReplenishNode, * ReplenishList;
// 全局链表
MedList medList = NULL;
EmpList empList = NULL;
PurchaseList purchaseList = NULL;
SalesList salesList = NULL;
ReplenishList replenishList = NULL;
// 按钮结构体
struct Button {
int x, y, width, height;
const wchar_t* text;
bool hover;
};
// 将多字节字符串转换为宽字符串
wchar_t* MBCS2Wide(const char* str) {
if (str == NULL) return NULL;
int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
wchar_t* wstr = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, str, -1, wstr, len);
return wstr;
}
// 按钮相关函数
void InitButton(Button* btn, int x, int y, int width, int height, const wchar_t* text) {
if (btn == nullptr) return;
btn->x = x;
btn->y = y;
btn->width = width;
btn->height = height;
btn->text = text;
btn->hover = false;
}
void DrawButton(Button* btn) {
if (btn == nullptr || btn->text == nullptr) return;
// 绘制按钮阴影 setfillcolor(RGB(50, 80, 120)); fillrectangle(btn->x + 3, btn->y + 3, btn->x + btn->width + 3, btn->y + btn->height + 3); // 绘制按钮主体 setfillcolor(btn->hover ? BUTTON_HOVER_COLOR : BUTTON_COLOR); fillroundrect(btn->x, btn->y, btn->x + btn->width, btn->y + btn->height, 10, 10); setbkmode(TRANSPARENT); settextcolor(TEXT_COLOR); settextstyle(20, 0, _T("微软雅黑")); RECT r = { btn->x, btn->y, btn->x + btn->width, btn->y + btn->height }; drawtext(btn->text, &r, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}
bool CheckButtonHover(Button* btn, int mouseX, int mouseY) {
if (btn == nullptr) return false;
btn->hover = (mouseX >= btn->x && mouseX <= btn->x + btn->width &&
mouseY >= btn->y && mouseY <= btn->y + btn->height);
return btn->hover;
}
// 显示消息框
void ShowMessageBox(const wchar_t* title, const wchar_t* message) {
MessageBox(GetHWnd(), message, title, MB_OK | MB_ICONINFORMATION);
}
// 输入框
void InputBox(char* buffer, int bufferSize, const wchar_t* prompt) {
wchar_t wbuffer[256];
InputBox(wbuffer, bufferSize, prompt);
WideCharToMultiByte(CP_ACP, 0, wbuffer, -1, buffer, bufferSize, NULL, NULL);
}
// 输入字符串验证
void S_input(char* t, int lens, const wchar_t* notice) {
char str[255];
do {
InputBox(str, 255, notice);
if (strlen(str) == 0) {
ShowMessageBox(L"错误", L"输入不能为空");
continue;
}
if (strlen(str) > lens) {
ShowMessageBox(L"错误", L"超过了要求长度,重新输入");
}
} while (strlen(str) == 0 || strlen(str) > lens);
strcpy_s(t, lens + 1, str);
}
// 输入数字
int Num_input(const wchar_t* notice) {
char str[20];
int a;
bool valid = false;
do {
InputBox(str, 20, notice);
a = atoi(str);
if (a < 0) {
ShowMessageBox(L"错误", L"必须输入正整数");
}
else {
valid = true;
}
} while (!valid);
return a;
}
// 输入浮点数
float Float_input(const wchar_t* notice) {
char str[20];
float a;
bool valid = false;
do {
InputBox(str, 20, notice);
a = atof(str);
if (a < 0) {
ShowMessageBox(L"错误", L"必须输入正数");
}
else {
valid = true;
}
} while (!valid);
return a;
}
// 添加药品
void AddMedicine() {
Medicine med;
med.id = Num_input(L"输入药品编号:");
// 检查药品是否已存在 MedNode* p = medList; while (p) { if (p->data.id == med.id) { ShowMessageBox(L"错误", L"药品编号已存在"); return; } p = p->next; } S_input(med.name, 49, L"输入药品名称:"); med.warehouse_qty = Num_input(L"输入仓库库存数量:"); med.pharmacy_qty = Num_input(L"输入药房库存数量:"); med.price_in = Float_input(L"输入药品进价:"); med.price_out = Float_input(L"输入药品售价:"); // 创建新节点 MedNode* newNode = (MedNode*)malloc(sizeof(MedNode)); if (!newNode) { ShowMessageBox(L"错误", L"内存分配失败"); return; } newNode->data = med; newNode->next = medList; medList = newNode; saveflag = 1; ShowMessageBox(L"成功", L"药品添加成功!");
}
// 添加员工
void AddEmployee() {
Employee emp;
emp.id = Num_input(L"输入员工ID:");
// 检查员工是否已存在 EmpNode* p = empList; while (p) { if (p->data.id == emp.id) { ShowMessageBox(L"错误", L"员工ID已存在"); return; } p = p->next; } S_input(emp.name, 19, L"输入员工姓名:"); emp.age = Num_input(L"输入员工年龄:"); S_input(emp.position, 19, L"输入员工岗位:"); emp.salary = Float_input(L"输入员工工资:"); S_input(emp.username, 19, L"输入用户名:"); S_input(emp.password, 19, L"输入密码:"); // 创建新节点 EmpNode* newNode = (EmpNode*)malloc(sizeof(EmpNode)); if (!newNode) { ShowMessageBox(L"错误", L"内存分配失败"); return; } newNode->data = emp; newNode->next = empList; empList = newNode; saveflag = 1; ShowMessageBox(L"成功", L"员工添加成功!");
}
// 仓库进货
void WarehousePurchase(int employee_id) {
PurchaseRecord pr;
pr.id = time(NULL); // 使用时间作为唯一ID
pr.med_id = Num_input(L"输入药品编号:");
// 检查药品是否存在 MedNode* med = medList; while (med) { if (med->data.id == pr.med_id) { strcpy_s(pr.med_name, med->data.name); break; } med = med->next; } if (!med) { ShowMessageBox(L"错误", L"药品不存在"); return; } pr.quantity = Num_input(L"输入进货数量:"); pr.price = Float_input(L"输入进货价格:"); pr.employee_id = employee_id; // 获取当前日期 time_t now = time(0); struct tm tstruct; localtime_s(&tstruct, &now); strftime(pr.date, sizeof(pr.date), "%Y-%m-%d", &tstruct); // 更新库存 med->data.warehouse_qty += pr.quantity; med->data.price_in = pr.price; // 创建新记录 PurchaseNode* newNode = (PurchaseNode*)malloc(sizeof(PurchaseNode)); if (!newNode) { ShowMessageBox(L"错误", L"内存分配失败"); return; } newNode->data = pr; newNode->next = purchaseList; purchaseList = newNode; saveflag = 1; ShowMessageBox(L"成功", L"进货记录添加成功!");
}
// 药房销售
void PharmacySale(int employee_id) {
SalesRecord sr;
sr.id = time(NULL); // 使用时间作为唯一ID
sr.med_id = Num_input(L"输入药品编号:");
// 检查药品是否存在 MedNode* med = medList; while (med) { if (med->data.id == sr.med_id) { strcpy_s(sr.med_name, med->data.name); break; } med = med->next; } if (!med) { ShowMessageBox(L"错误", L"药品不存在"); return; } sr.quantity = Num_input(L"输入销售数量:"); if (sr.quantity > med->data.pharmacy_qty) { ShowMessageBox(L"错误", L"药房库存不足"); return; } sr.price = med->data.price_out; sr.total = sr.quantity * sr.price; sr.employee_id = employee_id; // 获取当前日期 time_t now = time(0); struct tm tstruct; localtime_s(&tstruct, &now); strftime(sr.date, sizeof(sr.date), "%Y-%m-%d", &tstruct); // 更新库存 med->data.pharmacy_qty -= sr.quantity; // 创建新记录 SalesNode* newNode = (SalesNode*)malloc(sizeof(SalesNode)); if (!newNode) { ShowMessageBox(L"错误", L"内存分配失败"); return; } newNode->data = sr; newNode->next = salesList; salesList = newNode; saveflag = 1; wchar_t msg[100]; swprintf_s(msg, L"销售成功!总金额:%.2f", sr.total); ShowMessageBox(L"成功", msg);
}
// 药房申请补货
void PharmacyReplenish(int employee_id) {
Replenishment rep;
rep.id = time(NULL); // 使用时间作为唯一ID
rep.med_id = Num_input(L"输入药品编号:");
// 检查药品是否存在 MedNode* med = medList; while (med) { if (med->data.id == rep.med_id) { strcpy_s(rep.med_name, med->data.name); break; } med = med->next; } if (!med) { ShowMessageBox(L"错误", L"药品不存在"); return; } rep.quantity = Num_input(L"输入申请数量:"); strcpy_s(rep.status, "待处理"); // 创建新记录 ReplenishNode* newNode = (ReplenishNode*)malloc(sizeof(ReplenishNode)); if (!newNode) { ShowMessageBox(L"错误", L"内存分配失败"); return; } newNode->data = rep; newNode->next = replenishList; replenishList = newNode; saveflag = 1; ShowMessageBox(L"成功", L"补货申请已提交!");
}
// 仓库处理补货
void WarehouseReplenish(int employee_id) {
int rep_id = Num_input(L"输入补货申请ID:");
// 查找补货申请 ReplenishNode* repNode = replenishList; while (repNode) { if (repNode->data.id == rep_id) { if (strcmp(repNode->data.status, "已完成") == 0) { ShowMessageBox(L"提示", L"该申请已完成"); return; } // 查找药品 MedNode* med = medList; while (med) { if (med->data.id == repNode->data.med_id) { break; } med = med->next; } if (!med) { ShowMessageBox(L"错误", L"药品不存在"); return; } if (med->data.warehouse_qty < repNode->data.quantity) { strcpy_s(repNode->data.status, "库存不足"); ShowMessageBox(L"提示", L"仓库库存不足"); } else { // 更新库存 med->data.warehouse_qty -= repNode->data.quantity; med->data.pharmacy_qty += repNode->data.quantity; strcpy_s(repNode->data.status, "已完成"); ShowMessageBox(L"成功", L"补货已完成"); } saveflag = 1; return; } repNode = repNode->next; } ShowMessageBox(L"错误", L"未找到补货申请");
}
// 调整员工工资
void AdjustSalary() {
int emp_id = Num_input(L"输入员工ID:“);
float new_salary = Float_input(L"输入新工资:”);
// 查找员工 EmpNode* emp = empList; while (emp) { if (emp->data.id == emp_id) { emp->data.salary = new_salary; saveflag = 1; ShowMessageBox(L"成功", L"工资调整成功"); return; } emp = emp->next; } ShowMessageBox(L"错误", L"未找到员工");
}
// 调整员工岗位
void AdjustPosition() {
int emp_id = Num_input(L"输入员工ID:“);
char new_position[20];
S_input(new_position, 19, L"输入新岗位:”);
// 查找员工 EmpNode* emp = empList; while (emp) { if (emp->data.id == emp_id) { strcpy_s(emp->data.position, new_position); saveflag = 1; ShowMessageBox(L"成功", L"岗位调整成功"); return; } emp = emp->next; } ShowMessageBox(L"错误", L"未找到员工");
}
// 解雇员工
void FireEmployee() {
int emp_id = Num_input(L"输入员工ID:");
// 查找员工 EmpNode* prev = NULL; EmpNode* curr = empList; while (curr) { if (curr->data.id == emp_id) { if (prev) { prev->next = curr->next; } else { empList = curr->next; } free(curr); saveflag = 1; ShowMessageBox(L"成功", L"员工解雇成功"); return; } prev = curr; curr = curr->next; } ShowMessageBox(L"错误", L"未找到员工");
}
// 显示药品库存
void DisplayMedicines(bool isWarehouse) {
if (!medList) {
ShowMessageBox(L"提示", L"没有药品信息");
return;
}
// 计算滚动位置 static int scrollY = 0; const int rowHeight = 30; const int headerHeight = 80; const int visibleRows = (height - headerHeight - 50) / rowHeight; BeginBatchDraw(); cleardevice(); SetWindowText(GetHWnd(), isWarehouse ? L"仓库药品库存" : L"药房药品库存"); // 绘制背景 setbkcolor(BACKGROUND_COLOR); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 60); settextcolor(TITLE_COLOR); settextstyle(24, 0, _T("微软雅黑")); outtextxy(20, 20, isWarehouse ? L"仓库药品库存" : L"药房药品库存"); settextstyle(16, 0, _T("微软雅黑")); // 表头 const wchar_t* headers[] = { L"药品ID", L"药品名称", L"库存数量", L"进价", L"售价" }; int colWidths[] = { 100, 200, 150, 150, 150 }; int x = 20; for (int i = 0; i < 5; i++) { outtextxy(x, 70, headers[i]); x += colWidths[i] + 10; } // 绘制药品信息 settextstyle(14, 0, _T("微软雅黑")); settextcolor(RGB(50, 50, 50)); int y = 100; int count = 0; MedNode* p = medList; // 跳过滚动位置 for (int i = 0; i < scrollY && p; i++) { p = p->next; } while (p && y < height - 50 && count < visibleRows) { // 交替行颜色 setfillcolor(count % 2 == 0 ? RGB(255, 255, 255) : RGB(240, 245, 255)); fillrectangle(0, y, width, y + rowHeight); // 绘制网格线 setlinecolor(GRID_COLOR); line(0, y, width, y); // 转换字符串为宽字符 wchar_t wid[20]; swprintf_s(wid, L"%d", p->data.id); wchar_t* wname = MBCS2Wide(p->data.name); wchar_t wqty[20]; swprintf_s(wqty, L"%d", isWarehouse ? p->data.warehouse_qty : p->data.pharmacy_qty); wchar_t wprice_in[20]; swprintf_s(wprice_in, L"%.2f", p->data.price_in); wchar_t wprice_out[20]; swprintf_s(wprice_out, L"%.2f", p->data.price_out); // 绘制单元格 x = 20; // 药品ID outtextxy(x, y + 7, wid); x += 110; // 药品名称 outtextxy(x, y + 7, wname); x += 210; // 库存数量 outtextxy(x, y + 7, wqty); x += 160; // 进价 outtextxy(x, y + 7, wprice_in); x += 160; // 售价 outtextxy(x, y + 7, wprice_out); // 释放内存 delete[] wname; y += rowHeight; count++; p = p->next; } // 绘制底部背景 setfillcolor(HEADER_COLOR); fillrectangle(0, height - 50, width, height); Button btnReturn; InitButton(&btnReturn, width - 150, height - 40, 120, 35, L"返回"); DrawButton(&btnReturn); Button btnUp, btnDown; if (count > visibleRows) { InitButton(&btnUp, width - 50, height - 100, 35, 35, L"↑"); InitButton(&btnDown, width - 50, height - 60, 35, 35, L"↓"); DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); bool running = true; while (running) { if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (CheckButtonHover(&btnReturn, msg.x, msg.y)) { DrawButton(&btnReturn); FlushBatchDraw(); if (msg.uMsg == WM_LBUTTONDOWN) { running = false; scrollY = 0; } } else if (count > visibleRows && CheckButtonHover(&btnUp, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY > 0) { scrollY--; break; } } else if (count > visibleRows && CheckButtonHover(&btnDown, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY < count - visibleRows) { scrollY++; break; } } else { btnReturn.hover = false; DrawButton(&btnReturn); if (count > visibleRows) { btnUp.hover = false; btnDown.hover = false; DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); } } Sleep(10); } EndBatchDraw(); cleardevice();
}
// 显示员工信息
void DisplayEmployees() {
if (!empList) {
ShowMessageBox(L"提示", L"没有员工信息");
return;
}
// 计算滚动位置 static int scrollY = 0; const int rowHeight = 30; const int headerHeight = 80; const int visibleRows = (height - headerHeight - 50) / rowHeight; BeginBatchDraw(); cleardevice(); SetWindowText(GetHWnd(), L"员工信息"); // 绘制背景 setbkcolor(BACKGROUND_COLOR); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 60); settextcolor(TITLE_COLOR); settextstyle(24, 0, _T("微软雅黑")); outtextxy(20, 20, L"员工信息"); settextstyle(16, 0, _T("微软雅黑")); // 表头 const wchar_t* headers[] = { L"员工ID", L"姓名", L"年龄", L"岗位", L"工资" }; int colWidths[] = { 100, 150, 100, 150, 150 }; int x = 20; for (int i = 0; i < 5; i++) { outtextxy(x, 70, headers[i]); x += colWidths[i] + 10; } // 绘制员工信息 settextstyle(14, 0, _T("微软雅黑")); settextcolor(RGB(50, 50, 50)); int y = 100; int count = 0; EmpNode* p = empList; // 跳过滚动位置 for (int i = 0; i < scrollY && p; i++) { p = p->next; } while (p && y < height - 50 && count < visibleRows) { // 交替行颜色 setfillcolor(count % 2 == 0 ? RGB(255, 255, 255) : RGB(240, 245, 255)); fillrectangle(0, y, width, y + rowHeight); // 绘制网格线 setlinecolor(GRID_COLOR); line(0, y, width, y); // 转换字符串为宽字符 wchar_t wid[20]; swprintf_s(wid, L"%d", p->data.id); wchar_t* wname = MBCS2Wide(p->data.name); wchar_t wage[20]; swprintf_s(wage, L"%d", p->data.age); wchar_t* wposition = MBCS2Wide(p->data.position); wchar_t wsalary[20]; swprintf_s(wsalary, L"%.2f", p->data.salary); // 绘制单元格 x = 20; // 员工ID outtextxy(x, y + 7, wid); x += 110; // 姓名 outtextxy(x, y + 7, wname); x += 160; // 年龄 outtextxy(x, y + 7, wage); x += 110; // 岗位 outtextxy(x, y + 7, wposition); x += 160; // 工资 outtextxy(x, y + 7, wsalary); // 释放内存 delete[] wname; delete[] wposition; y += rowHeight; count++; p = p->next; } // 绘制底部背景 setfillcolor(HEADER_COLOR); fillrectangle(0, height - 50, width, height); Button btnReturn; InitButton(&btnReturn, width - 150, height - 40, 120, 35, L"返回"); DrawButton(&btnReturn); Button btnUp, btnDown; if (count > visibleRows) { InitButton(&btnUp, width - 50, height - 100, 35, 35, L"↑"); InitButton(&btnDown, width - 50, height - 60, 35, 35, L"↓"); DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); bool running = true; while (running) { if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (CheckButtonHover(&btnReturn, msg.x, msg.y)) { DrawButton(&btnReturn); FlushBatchDraw(); if (msg.uMsg == WM_LBUTTONDOWN) { running = false; scrollY = 0; } } else if (count > visibleRows && CheckButtonHover(&btnUp, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY > 0) { scrollY--; break; } } else if (count > visibleRows && CheckButtonHover(&btnDown, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY < count - visibleRows) { scrollY++; break; } } else { btnReturn.hover = false; DrawButton(&btnReturn); if (count > visibleRows) { btnUp.hover = false; btnDown.hover = false; DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); } } Sleep(10); } EndBatchDraw(); cleardevice();
}
// 显示销售记录
void DisplaySalesRecords() {
if (!salesList) {
ShowMessageBox(L"提示", L"没有销售记录");
return;
}
// 计算滚动位置 static int scrollY = 0; const int rowHeight = 30; const int headerHeight = 80; const int visibleRows = (height - headerHeight - 50) / rowHeight; BeginBatchDraw(); cleardevice(); SetWindowText(GetHWnd(), L"销售记录"); // 绘制背景 setbkcolor(BACKGROUND_COLOR); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 60); settextcolor(TITLE_COLOR); settextstyle(24, 0, _T("微软雅黑")); outtextxy(20, 20, L"销售记录"); settextstyle(16, 0, _T("微软雅黑")); // 表头 const wchar_t* headers[] = { L"记录ID", L"药品名称", L"数量", L"单价", L"总价", L"日期" }; int colWidths[] = { 150, 200, 100, 100, 100, 150 }; int x = 20; for (int i = 0; i < 6; i++) { outtextxy(x, 70, headers[i]); x += colWidths[i] + 10; } // 绘制销售记录 settextstyle(14, 0, _T("微软雅黑")); settextcolor(RGB(50, 50, 50)); int y = 100; int count = 0; SalesNode* p = salesList; // 跳过滚动位置 for (int i = 0; i < scrollY && p; i++) { p = p->next; } while (p && y < height - 50 && count < visibleRows) { // 交替行颜色 setfillcolor(count % 2 == 0 ? RGB(255, 255, 255) : RGB(240, 245, 255)); fillrectangle(0, y, width, y + rowHeight); // 绘制网格线 setlinecolor(GRID_COLOR); line(0, y, width, y); // 转换字符串为宽字符 wchar_t wid[20]; swprintf_s(wid, L"%d", p->data.id); wchar_t* wname = MBCS2Wide(p->data.med_name); wchar_t wqty[20]; swprintf_s(wqty, L"%d", p->data.quantity); wchar_t wprice[20]; swprintf_s(wprice, L"%.2f", p->data.price); wchar_t wtotal[20]; swprintf_s(wtotal, L"%.2f", p->data.total); wchar_t* wdate = MBCS2Wide(p->data.date); // 绘制单元格 x = 20; // 记录ID outtextxy(x, y + 7, wid); x += 160; // 药品名称 outtextxy(x, y + 7, wname); x += 210; // 数量 outtextxy(x, y + 7, wqty); x += 110; // 单价 outtextxy(x, y + 7, wprice); x += 110; // 总价 outtextxy(x, y + 7, wtotal); x += 110; // 日期 outtextxy(x, y + 7, wdate); // 释放内存 delete[] wname; delete[] wdate; y += rowHeight; count++; p = p->next; } // 绘制底部背景 setfillcolor(HEADER_COLOR); fillrectangle(0, height - 50, width, height); Button btnReturn; InitButton(&btnReturn, width - 150, height - 40, 120, 35, L"返回"); DrawButton(&btnReturn); Button btnUp, btnDown; if (count > visibleRows) { InitButton(&btnUp, width - 50, height - 100, 35, 35, L"↑"); InitButton(&btnDown, width - 50, height - 60, 35, 35, L"↓"); DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); bool running = true; while (running) { if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (CheckButtonHover(&btnReturn, msg.x, msg.y)) { DrawButton(&btnReturn); FlushBatchDraw(); if (msg.uMsg == WM_LBUTTONDOWN) { running = false; scrollY = 0; } } else if (count > visibleRows && CheckButtonHover(&btnUp, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY > 0) { scrollY--; break; } } else if (count > visibleRows && CheckButtonHover(&btnDown, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY < count - visibleRows) { scrollY++; break; } } else { btnReturn.hover = false; DrawButton(&btnReturn); if (count > visibleRows) { btnUp.hover = false; btnDown.hover = false; DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); } } Sleep(10); } EndBatchDraw(); cleardevice();
}
// 显示补货申请
void DisplayReplenishments() {
if (!replenishList) {
ShowMessageBox(L"提示", L"没有补货申请");
return;
}
// 计算滚动位置 static int scrollY = 0; const int rowHeight = 30; const int headerHeight = 80; const int visibleRows = (height - headerHeight - 50) / rowHeight; BeginBatchDraw(); cleardevice(); SetWindowText(GetHWnd(), L"补货申请"); // 绘制背景 setbkcolor(BACKGROUND_COLOR); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 60); settextcolor(TITLE_COLOR); settextstyle(24, 0, _T("微软雅黑")); outtextxy(20, 20, L"补货申请"); settextstyle(16, 0, _T("微软雅黑")); // 表头 const wchar_t* headers[] = { L"申请ID", L"药品名称", L"申请数量", L"状态" }; int colWidths[] = { 150, 300, 150, 200 }; int x = 20; for (int i = 0; i < 4; i++) { outtextxy(x, 70, headers[i]); x += colWidths[i] + 10; } // 绘制补货申请 settextstyle(14, 0, _T("微软雅黑")); settextcolor(RGB(50, 50, 50)); int y = 100; int count = 0; ReplenishNode* p = replenishList; // 跳过滚动位置 for (int i = 0; i < scrollY && p; i++) { p = p->next; } while (p && y < height - 50 && count < visibleRows) { // 交替行颜色 setfillcolor(count % 2 == 0 ? RGB(255, 255, 255) : RGB(240, 245, 255)); fillrectangle(0, y, width, y + rowHeight); // 绘制网格线 setlinecolor(GRID_COLOR); line(0, y, width, y); // 转换字符串为宽字符 wchar_t wid[20]; swprintf_s(wid, L"%d", p->data.id); wchar_t* wname = MBCS2Wide(p->data.med_name); wchar_t wqty[20]; swprintf_s(wqty, L"%d", p->data.quantity); wchar_t* wstatus = MBCS2Wide(p->data.status); // 绘制单元格 x = 20; // 申请ID outtextxy(x, y + 7, wid); x += 160; // 药品名称 outtextxy(x, y + 7, wname); x += 310; // 申请数量 outtextxy(x, y + 7, wqty); x += 160; // 状态 outtextxy(x, y + 7, wstatus); // 释放内存 delete[] wname; delete[] wstatus; y += rowHeight; count++; p = p->next; } // 绘制底部背景 setfillcolor(HEADER_COLOR); fillrectangle(0, height - 50, width, height); Button btnReturn; InitButton(&btnReturn, width - 150, height - 40, 120, 35, L"返回"); DrawButton(&btnReturn); Button btnUp, btnDown; if (count > visibleRows) { InitButton(&btnUp, width - 50, height - 100, 35, 35, L"↑"); InitButton(&btnDown, width - 50, height - 60, 35, 35, L"↓"); DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); bool running = true; while (running) { if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); if (CheckButtonHover(&btnReturn, msg.x, msg.y)) { DrawButton(&btnReturn); FlushBatchDraw(); if (msg.uMsg == WM_LBUTTONDOWN) { running = false; scrollY = 0; } } else if (count > visibleRows && CheckButtonHover(&btnUp, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY > 0) { scrollY--; break; } } else if (count > visibleRows && CheckButtonHover(&btnDown, msg.x, msg.y)) { if (msg.uMsg == WM_LBUTTONDOWN && scrollY < count - visibleRows) { scrollY++; break; } } else { btnReturn.hover = false; DrawButton(&btnReturn); if (count > visibleRows) { btnUp.hover = false; btnDown.hover = false; DrawButton(&btnUp); DrawButton(&btnDown); } FlushBatchDraw(); } } Sleep(10); } EndBatchDraw(); cleardevice();
}
// 计算盈利
float CalculateProfit() {
float profit = 0;
SalesNode* sale = salesList;
while (sale) {
// 查找药品进价
MedNode* med = medList;
while (med) {
if (med->data.id == sale->data.med_id) {
float cost = med->data.price_in * sale->data.quantity;
profit += sale->data.total - cost;
break;
}
med = med->next;
}
sale = sale->next;
}
return profit;
}
// 文件保存
void SaveFile() {
FILE* fp;
// 保存药品 errno_t err = fopen_s(&fp, "medicines.dat", "wb"); if (err == 0) { MedNode* p = medList; while (p) { fwrite(&p->data, sizeof(Medicine), 1, fp); p = p->next; } fclose(fp); } // 保存员工 err = fopen_s(&fp, "employees.dat", "wb"); if (err == 0) { EmpNode* p = empList; while (p) { fwrite(&p->data, sizeof(Employee), 1, fp); p = p->next; } fclose(fp); } // 保存进货记录 err = fopen_s(&fp, "purchases.dat", "wb"); if (err == 0) { PurchaseNode* p = purchaseList; while (p) { fwrite(&p->data, sizeof(PurchaseRecord), 1, fp); p = p->next; } fclose(fp); } // 保存销售记录 err = fopen_s(&fp, "sales.dat", "wb"); if (err == 0) { SalesNode* p = salesList; while (p) { fwrite(&p->data, sizeof(SalesRecord), 1, fp); p = p->next; } fclose(fp); } // 保存补货申请 err = fopen_s(&fp, "replenishments.dat", "wb"); if (err == 0) { ReplenishNode* p = replenishList; while (p) { fwrite(&p->data, sizeof(Replenishment), 1, fp); p = p->next; } fclose(fp); } saveflag = 0; ShowMessageBox(L"成功", L"所有数据已保存");
}
// 文件加载
void LoadFile() {
FILE* fp;
Medicine med;
Employee emp;
PurchaseRecord pr;
SalesRecord sr;
Replenishment rep;
// 加载药品 errno_t err = fopen_s(&fp, "medicines.dat", "rb"); if (err == 0) { while (fread(&med, sizeof(Medicine), 1, fp) == 1) { MedNode* newNode = (MedNode*)malloc(sizeof(MedNode)); if (newNode) { newNode->data = med; newNode->next = medList; medList = newNode; } } fclose(fp); } // 加载员工 err = fopen_s(&fp, "employees.dat", "rb"); if (err == 0) { while (fread(&emp, sizeof(Employee), 1, fp) == 1) { EmpNode* newNode = (EmpNode*)malloc(sizeof(EmpNode)); if (newNode) { newNode->data = emp; newNode->next = empList; empList = newNode; } } fclose(fp); } // 加载进货记录 err = fopen_s(&fp, "purchases.dat", "rb"); if (err == 0) { while (fread(&pr, sizeof(PurchaseRecord), 1, fp) == 1) { PurchaseNode* newNode = (PurchaseNode*)malloc(sizeof(PurchaseNode)); if (newNode) { newNode->data = pr; newNode->next = purchaseList; purchaseList = newNode; } } fclose(fp); } // 加载销售记录 err = fopen_s(&fp, "sales.dat", "rb"); if (err == 0) { while (fread(&sr, sizeof(SalesRecord), 1, fp) == 1) { SalesNode* newNode = (SalesNode*)malloc(sizeof(SalesNode)); if (newNode) { newNode->data = sr; newNode->next = salesList; salesList = newNode; } } fclose(fp); } // 加载补货申请 err = fopen_s(&fp, "replenishments.dat", "rb"); if (err == 0) { while (fread(&rep, sizeof(Replenishment), 1, fp) == 1) { ReplenishNode* newNode = (ReplenishNode*)malloc(sizeof(ReplenishNode)); if (newNode) { newNode->data = rep; newNode->next = replenishList; replenishList = newNode; } } fclose(fp); }
}
// 药房工作人员菜单
void PharmacyMenu(int employee_id) {
Button btnStock, btnSale, btnReplenish, btnBack, btnExit;
InitButton(&btnStock, width / 2 - 150, 180, 300, 50, L"查看药房库存");
InitButton(&btnSale, width / 2 - 150, 250, 300, 50, L"销售药品");
InitButton(&btnReplenish, width / 2 - 150, 320, 300, 50, L"申请补货");
InitButton(&btnBack, width / 2 - 150, 390, 300, 50, L"返回主菜单");
InitButton(&btnExit, width / 2 - 150, 460, 300, 50, L"退出系统");
BeginBatchDraw(); bool running = true; while (running) { // 绘制背景 setbkcolor(RGB(240, 248, 255)); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 100); settextcolor(TITLE_COLOR); settextstyle(28, 0, _T("微软雅黑")); outtextxy(width / 2 - textwidth(L"药房工作人员") / 2, 30, L"药房工作人员"); // 绘制按钮 DrawButton(&btnStock); DrawButton(&btnSale); DrawButton(&btnReplenish); DrawButton(&btnBack); DrawButton(&btnExit); FlushBatchDraw(); if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); CheckButtonHover(&btnStock, msg.x, msg.y); CheckButtonHover(&btnSale, msg.x, msg.y); CheckButtonHover(&btnReplenish, msg.x, msg.y); CheckButtonHover(&btnBack, msg.x, msg.y); CheckButtonHover(&btnExit, msg.x, msg.y); if (msg.uMsg == WM_LBUTTONDOWN) { if (btnStock.hover) DisplayMedicines(false); else if (btnSale.hover) PharmacySale(employee_id); else if (btnReplenish.hover) PharmacyReplenish(employee_id); else if (btnBack.hover) running = false; else if (btnExit.hover) exit(0); } } Sleep(10); } EndBatchDraw();
}
// 仓库工作人员菜单
void WarehouseMenu(int employee_id) {
Button btnStock, btnPurchase, btnReplenish, btnBack, btnExit;
InitButton(&btnStock, width / 2 - 150, 180, 300, 50, L"查看仓库库存");
InitButton(&btnPurchase, width / 2 - 150, 250, 300, 50, L"仓库进货");
InitButton(&btnReplenish, width / 2 - 150, 320, 300, 50, L"处理补货申请");
InitButton(&btnBack, width / 2 - 150, 390, 300, 50, L"返回主菜单");
InitButton(&btnExit, width / 2 - 150, 460, 300, 50, L"退出系统");
BeginBatchDraw(); bool running = true; while (running) { // 绘制背景 setbkcolor(RGB(240, 248, 255)); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 100); settextcolor(TITLE_COLOR); settextstyle(28, 0, _T("微软雅黑")); outtextxy(width / 2 - textwidth(L"仓库工作人员") / 2, 30, L"仓库工作人员"); // 绘制按钮 DrawButton(&btnStock); DrawButton(&btnPurchase); DrawButton(&btnReplenish); DrawButton(&btnBack); DrawButton(&btnExit); FlushBatchDraw(); if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); CheckButtonHover(&btnStock, msg.x, msg.y); CheckButtonHover(&btnPurchase, msg.x, msg.y); CheckButtonHover(&btnReplenish, msg.x, msg.y); CheckButtonHover(&btnBack, msg.x, msg.y); CheckButtonHover(&btnExit, msg.x, msg.y); if (msg.uMsg == WM_LBUTTONDOWN) { if (btnStock.hover) DisplayMedicines(true); else if (btnPurchase.hover) WarehousePurchase(employee_id); else if (btnReplenish.hover) WarehouseReplenish(employee_id); else if (btnBack.hover) running = false; else if (btnExit.hover) exit(0); } } Sleep(10); } EndBatchDraw();
}
// 人事管理菜单
void HRMenu() {
Button btnAddEmp, btnAdjustSalary, btnAdjustPos, btnFireEmp, btnViewEmp;
Button btnSales, btnProfit, btnBack, btnExit;
InitButton(&btnAddEmp, 50, 150, 200, 45, L"添加员工");
InitButton(&btnAdjustSalary, 50, 210, 200, 45, L"调整工资");
InitButton(&btnAdjustPos, 50, 270, 200, 45, L"调整岗位");
InitButton(&btnFireEmp, 50, 330, 200, 45, L"解雇员工");
InitButton(&btnViewEmp, 50, 390, 200, 45, L"查看员工");
InitButton(&btnSales, 280, 150, 200, 45, L"销售记录");
InitButton(&btnProfit, 280, 210, 200, 45, L"查看盈利");
InitButton(&btnBack, 280, 330, 200, 45, L"返回主菜单");
InitButton(&btnExit, 280, 390, 200, 45, L"退出系统");
BeginBatchDraw(); bool running = true; while (running) { // 绘制背景 setbkcolor(RGB(240, 248, 255)); cleardevice(); // 绘制标题背景 setfillcolor(HEADER_COLOR); fillrectangle(0, 0, width, 100); settextcolor(TITLE_COLOR); settextstyle(28, 0, _T("微软雅黑")); outtextxy(width / 2 - textwidth(L"人事管理") / 2, 30, L"人事管理"); // 绘制按钮 DrawButton(&btnAddEmp); DrawButton(&btnAdjustSalary); DrawButton(&btnAdjustPos); DrawButton(&btnFireEmp); DrawButton(&btnViewEmp); DrawButton(&btnSales); DrawButton(&btnProfit); DrawButton(&btnBack); DrawButton(&btnExit); FlushBatchDraw(); if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); CheckButtonHover(&btnAddEmp, msg.x, msg.y); CheckButtonHover(&btnAdjustSalary, msg.x, msg.y); CheckButtonHover(&btnAdjustPos, msg.x, msg.y); CheckButtonHover(&btnFireEmp, msg.x, msg.y); CheckButtonHover(&btnViewEmp, msg.x, msg.y); CheckButtonHover(&btnSales, msg.x, msg.y); CheckButtonHover(&btnProfit, msg.x, msg.y); CheckButtonHover(&btnBack, msg.x, msg.y); CheckButtonHover(&btnExit, msg.x, msg.y); if (msg.uMsg == WM_LBUTTONDOWN) { if (btnAddEmp.hover) AddEmployee(); else if (btnAdjustSalary.hover) AdjustSalary(); else if (btnAdjustPos.hover) AdjustPosition(); else if (btnFireEmp.hover) FireEmployee(); else if (btnViewEmp.hover) DisplayEmployees(); else if (btnSales.hover) DisplaySalesRecords(); else if (btnProfit.hover) { float profit = CalculateProfit(); wchar_t msg[100]; swprintf_s(msg, L"总盈利:%.2f", profit); ShowMessageBox(L"盈利情况", msg); } else if (btnBack.hover) running = false; else if (btnExit.hover) exit(0); } } Sleep(10); } EndBatchDraw();
}
// 用户登录
void UserLogin() {
char username[20];
char password[20];
int employee_id = -1;
while (1) { S_input(username, 19, L"输入用户名:"); S_input(password, 19, L"输入密码:"); // 查找员工 EmpNode* p = empList; while (p) { if (strcmp(p->data.username, username) == 0 && strcmp(p->data.password, password) == 0) { employee_id = p->data.id; // 确定用户类型 if (strcmp(p->data.position, "药房") == 0) { current_user_type = 1; } else if (strcmp(p->data.position, "仓库") == 0) { current_user_type = 2; } else if (strcmp(p->data.position, "人事") == 0) { current_user_type = 3; } else { current_user_type = 0; } wchar_t welcome[100]; wchar_t* wname = MBCS2Wide(p->data.name); wchar_t* wposition = MBCS2Wide(p->data.position); swprintf_s(welcome, L"欢迎 %s (%s)", wname, wposition); ShowMessageBox(L"登录成功", welcome); // 释放内存 delete[] wname; delete[] wposition; // 进入对应菜单 if (current_user_type == 1) { PharmacyMenu(employee_id); } else if (current_user_type == 2) { WarehouseMenu(employee_id); } else if (current_user_type == 3) { HRMenu(); } return; } p = p->next; } ShowMessageBox(L"登录失败", L"用户名或密码错误"); }
}
// 主菜单
void MainMenu() {
Button btnLogin, btnAddMed, btnAddEmp, btnViewRep, btnSave, btnExit;
InitButton(&btnLogin, width / 2 - 150, 180, 300, 60, L"用户登录");
InitButton(&btnAddMed, width / 2 - 150, 260, 140, 60, L"添加药品");
InitButton(&btnAddEmp, width / 2 + 10, 260, 140, 60, L"添加员工");
InitButton(&btnViewRep, width / 2 - 150, 340, 140, 60, L"补货申请");
InitButton(&btnSave, width / 2 + 10, 340, 140, 60, L"保存数据");
InitButton(&btnExit, width / 2 - 150, 420, 300, 60, L"退出系统");
BeginBatchDraw(); bool running = true; while (running) { // 绘制背景 setbkcolor(RGB(240, 248, 255)); cleardevice(); // 绘制标题 settextcolor(TITLE_COLOR); settextstyle(36, 0, _T("微软雅黑")); outtextxy(width / 2 - textwidth(L"药品仓库管理系统") / 2, 60, L"药品仓库管理系统"); settextstyle(18, 0, _T("微软雅黑")); settextcolor(RGB(100, 100, 100)); outtextxy(width / 2 - textwidth(L"高效管理药品库存") / 2, 120, L"高效管理药品库存"); // 绘制按钮 DrawButton(&btnLogin); DrawButton(&btnAddMed); DrawButton(&btnAddEmp); DrawButton(&btnViewRep); DrawButton(&btnSave); DrawButton(&btnExit); // 绘制底部信息 settextstyle(14, 0, _T("微软雅黑")); settextcolor(RGB(120, 120, 120)); outtextxy(width / 2 - textwidth(L"© 2025 药品仓库管理系统") / 2, height - 30, L"© 2025 药品仓库管理系统"); FlushBatchDraw(); if (MouseHit()) { MOUSEMSG msg = GetMouseMsg(); CheckButtonHover(&btnLogin, msg.x, msg.y); CheckButtonHover(&btnAddMed, msg.x, msg.y); CheckButtonHover(&btnAddEmp, msg.x, msg.y); CheckButtonHover(&btnViewRep, msg.x, msg.y); CheckButtonHover(&btnSave, msg.x, msg.y); CheckButtonHover(&btnExit, msg.x, msg.y); if (msg.uMsg == WM_LBUTTONDOWN) { if (btnLogin.hover) UserLogin(); else if (btnAddMed.hover) AddMedicine(); else if (btnAddEmp.hover) AddEmployee(); else if (btnViewRep.hover) DisplayReplenishments(); else if (btnSave.hover) SaveFile(); else if (btnExit.hover) { if (saveflag) { if (MessageBox(GetHWnd(), L"是否保存更改?", L"提示", MB_YESNO | MB_ICONQUESTION) == IDYES) { SaveFile(); } } running = false; } } } Sleep(10); } EndBatchDraw();
}
int main() {
// 设置本地化环境以支持中文
setlocale(LC_ALL, “chs”);
// 加载数据 LoadFile(); // 初始化图形界面 initgraph(width, height); SetWindowText(GetHWnd(), L"药品仓库管理系统"); // 设置随机种子 srand((unsigned)time(NULL)); // 显示主菜单 while (1) { MainMenu(); } // 关闭图形界面 closegraph(); return 0;
}
将以上代码接入数据库,并给出修改后的完整版代码
最新发布