简陋零食系统

实现了简易的零食系统,可以区分管理员和用户,管理员负责添加库存,用户可以购买零食,有简陋的网页交互,基于 gpt 编写^_^

明确需求

只有先明确了需求才能了解一个小项目的大纲,这样有助于我们逻辑清晰地完成目标,不至于缺漏。

基础

  1. 数据库设计:设计数据库模式,以存储用户信息、零食库存、进货记录和账单信息。使用 MySQL 或其他关系型数据库管理系统存储数据。
  2. 用户管理: 创建用户登录和身份验证系统,区分管理员和成员。使用 PHP 中的会话管理来跟踪用户的登录状态。
  3. 成员区分: 在用户数据库中,添加一个字段来区分实习成员和正式成员。字段用于计算购买折扣。
  4. 零食购买: 创建一个界面,允许用户浏览零食库存、选择要购买的零食和数量,根据用户身份(实习成员或正式成员)计算折扣,并生成账单。另外可以指定想要补充的零食名称和数量,选择性上传购买链接。
  5. 进货操作: 管理员有权向仓库添加零食库存。创建一个界面,管理员可以输入零食的名称、数量和进货价格来添加库存。
  6. 账单生成: 创建一个账单系统,记录每次购买的细节,包括零食名称、购买数量、单价、折扣和日期。在账单中跟踪实验室的余额,并记录每月的采购补贴。
  7. 实验室余额: 管理员应能够查看实验室的余额,根据进货和销售来更新余额。
  8. 数据展示: 创建一个界面,允许管理员和成员查看账单和库存情况,以便他们了解进货和购买的历史记录。

进阶

  1. 安全性考虑: 要确保系统的安全性,包括输入验证、防止 SQL 注入、密码加密和访问控制等方面。
  2. 用户界面: 设计用户友好的用户界面,以便成员和管理员可以轻松地执行操作和浏览信息。
  3. 数据备份: 定期备份数据库,以防止数据丢失。

实现流程

实现流程

创建数据库 snack 和数据库表 users、snacks、purchase_history

分别存储登录账号、零食信息、历史购买记录

table表展示

创建用户登录的 html 表单:userlogin.html

用于用户输入用户名和密码来进行登录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- <form method="post" action="userlogin_do.php"> -->
<style>
body {
text-align: center; /* 居中显示文本 */
padding: 20px; /* 增大上下行间距 */
margin-bottom: 20px;
}
label,
input {
margin-top: 10px; /* 增大上下行间距 */
margin-bottom: 10px; /* 增大上下行间距 */
}
</style>
<form method="post" action="http://localhost/userlogin_do.php">
<h1>登录页面</h1>
<br />
<input type="text" name="username" placeholder="输入你的登录名" />
<br />
<input type="password" name="password" placeholder="输入密码" />
<br />
<input type="submit" value="登录" />
</form>

创建 php 处理登录表单:userlogin_do.php

用于判断用户名和密码是否符合,并且要区分管理员和用户

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<?php
header("content-type:text/html; charset=GBK"); //设置编码
session_start();

if ($_SERVER["REQUEST_METHOD"] == "POST")
{
// 连接数据库,查询用户信息
// 这里需要使用适当的数据库连接方法和SQL查询来检查用户输入的用户名和密码是否匹配
$servername = "localhost"; // 数据库服务器主机名
$username = "root"; // 数据库用户名
$password = "root"; // 数据库密码
$database = "snack"; // 数据库名称

// 创建数据库连接
$conn = new mysqli($servername, $username, $password, $database);
// 检查连接是否成功
if ($conn->connect_error)
die("连接数据库失败: " . $conn->connect_error);

// 从用户提交的表单数据中获取用户名
// $_POST 是一个超全局数组,用于从 POST 请求中获取数据。POST 请求通常用于向服务器提交表单数据
$username = $_POST["username"];
$password = $_POST["password"];
if ($password == "")
{
echo "登陆失败,密码不能为空,请重试。";
exit;
}
$hashed_password = password_hash($password, PASSWORD_DEFAULT); // 哈希处理

// 查询user信息
$query = "SELECT * FROM users";
$result = $conn->query($query);

if($result->num_rows > 0)
{
while($row = $result->fetch_assoc())
{
$user_name = $row["username"];
$user_password = $row["password"];
$user_role = $row["role"];
if($user_name == $username)
break;
}
$user_hashed_password = password_hash($user_password, PASSWORD_DEFAULT); // 哈希处理

$user = $result->fetch_assoc();
// $stored_role = $user["role"];

if (password_verify($password, $user_hashed_password))
{
// 用户名和密码匹配,登录成功
$_SESSION["username"] = $username;
$_SESSION["role"] = $user_role;


// 根据用户的角色重定向到不同的页面
if (!strcmp($_SESSION["role"], "admin"))
{
header("Location: admin_dashboard.php");
}
else
{
header("Location: member_dashboard.php");
}
}
else
{
// 密码不匹配
echo "登录失败,请检查密码。";
}
}
else
{
// 用户名不存在
echo "登录失败,请检查用户名。";
}
}
?>

创建 php 处理不同身份的登录状况

用户和管理员登陆后所需要实现的功能不同

管理员端:admin_dashboard.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
header("content-type:text/html; charset=GBK"); //设置编码

session_start();
?>

<!DOCTYPE html>
<html>
<head>
<title>Admin Dashboard</title>
</head>
<body>
<h1>Welcome to the Admin Dashboard</h1>
<p>你好, 管理员。 <!-- 显示用户的用户名 -->
<!-- 在此添加成员仪表板的内容 -->

<a href="logout.php">Logout</a> <!-- 提供注销链接 -->
</body>
</html>

用户端:user_dashboard.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
header("content-type:text/html; charset=GBK"); //设置编码

session_start();
?>

<!DOCTYPE html>
<html>
<head>
<title>Member Dashboard</title>
</head>
<body>
<h1>Welcome to the Member Dashboard</h1>
<p>你好, <?php echo $_SESSION["username"]; ?>! <!-- 显示用户的用户名 -->
<!-- 在此添加成员仪表板的内容 -->

<a href="logout.php">Logout</a> <!-- 提供注销链接 -->
</body>
</html>

创建 php 提供注销功能:logout.php

1
2
3
4
5
6
7
<?php
session_start(); // 启动会话
session_unset(); // 清空会话数据
session_destroy(); // 销毁会话
header("Location: userlogin.html"); // 重定向到登录页面
exit;
?>

细化管理员端:admin_dashboard.php

实现库存展示、添加库存的功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Admin Dashboard</title>
<style>
body
{
text-align: center; /* 居中显示文本 */
padding: 20px; /* 增大上下行间距 */
margin-bottom : 20px;
}
form
{
display: inline-block; /* 使表单元素水平排列 */
}
label, input
{
margin-left : 5px; /* 增大上下行间距 */
margin-right : 5px; /* 增大上下行间距 */
}
</style>
</head>
<body>
<h1>Welcome to the Admin Dashboard</h1>
<p> 你好, 管理员。 <!-- 显示用户的用户名 -->
<!-- 在此添加成员仪表板的内容 -->

<a href="logout.php"> 退出登录 <br> <br> </a> <!-- 提供注销链接 -->

<?php
header("content-type:text/html; charset=utf-8"); //设置编码
session_start();

$servername = "localhost"; // 数据库服务器主机名
$username = "root"; // 数据库用户名
$password = "root"; // 数据库密码
$database = "snack"; // 数据库名称
// 创建数据库连接
$conn = new mysqli($servername, $username, $password, $database);

// 查询数据库中零食的信息,包括零食名称、snack_quantity 和 snack_sold
$query = "SELECT snack_name, snack_quantity, snack_sold FROM snacks";
$result = $conn->query($query); // conn是数据库连接对象,代表与数据库服务器的连接,query执行查询语句,返回一个结果集

if ($result->num_rows > 0)
{
while ($row = $result->fetch_assoc()) {
$snack_name = $row["snack_name"];
$snack_quantity = $row["snack_quantity"];
$snack_sold = $row["snack_sold"];
$remaining_quantity = $snack_quantity - $snack_sold;

// 在表单中显示零食名称和库存
echo "<label for='snack_$snack_name'>$snack_name (库存: $remaining_quantity) <br><br> </label> \n";
}
}
else
{
echo "查询到表单为空。";
}
?>

<!-- 添加库存 -->
<form method="post" action="admin_add_snack.php">
<label for="snack_name">零食名称:</label>
<input type="text" name="snack_name" id="snack_name" required>

<label for="snack_quantity">数量:</label>
<input type="number" name="snack_quantity" id="snack_quantity" required>

<label for="snack_price">进货价格:</label>
<input type="number" name="snack_price" id="snack_price" step="0.01" required>

<input type="submit" value="添加库存">
<br> <!-- 换行 -->
</form>

<!-- 实时更新,也许有用 -->
<script>
// 获取所有零食输入字段
var snackInputs = document.querySelectorAll('input[name^="snack_"]');

// 添加事件监听器以在输入字段更改时更新库存信息
snackInputs.forEach(function (input) {
input.addEventListener('input', function () {
// 获取零食名称和库存输入字段的值
var snackName = this.name.substring(6); // 去掉前缀 "snack_"
var remainingQuantity = parseInt(this.max) - parseInt(this.value);

// 更新显示的库存信息
var label = document.querySelector('label[for="snack_' + snackName + '"]');
label.innerHTML = snackName + ' (库存: ' + remainingQuantity + ')';
});
});
</script>

</body>
</html>

创建 php 实现添加库存功能:admin_add_snack.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<?php
header("content-type:text/html; charset=utf8"); // 设置编码
session_start();

if ($_SERVER["REQUEST_METHOD"] === "POST") {
// 获取表单提交的数据
$snack_name = $_POST["snack_name"];
$snack_quantity = $_POST["snack_quantity"];
$snack_price = $_POST["snack_price"];

$encoding = array('UTF-8', 'ASCII', 'GB2312', 'GBK');
$utf8_snack_name = mb_convert_encoding($snack_name, "UTF-8", mb_detect_encoding($snack_name, $encoding));

// 连接到数据库
$conn = mysqli_connect("localhost", "root", "root", "snack");

if (!$conn)
die("数据库连接失败: " . mysqli_connect_error());

$snackid = null; // 初始化 snackid

// 查询是否有同名零食存在
$query = "SELECT snack_id FROM snacks WHERE snack_name = ?";
$stmt0 = $conn->prepare($query);
$stmt0->bind_param("s", $utf8_snack_name);
$stmt0->execute();
$stmt0->store_result();
$stmt0->bind_result($snackid);

if ($stmt0->fetch())
{
// 零食已存在,执行更新操作
$stmt0->close();

$update_query = "UPDATE snacks SET snack_quantity = snack_quantity + ?, snack_price = snack_price + ? WHERE snack_id = ?";
$stmt = $conn->prepare($update_query);
$stmt->bind_param("idi", $snack_quantity, $snack_price, $snackid);

if ($stmt->execute())
echo "The snack was successfully added to inventory.";
else
echo "Error adding snacks: " . $stmt->error;
}
else
{
// 零食不存在,执行插入操作
$stmt0->close();

$insert_query = "INSERT INTO snacks (date, snack_name, snack_sold, snack_quantity, snack_price) VALUES (NULL, ?, 0, ?, ?)";
$stmt = $conn->prepare($insert_query);
$stmt->bind_param("sid", $utf8_snack_name, $snack_quantity, $snack_price);

if ($stmt->execute())
echo "The snack was successfully added to inventory.";
else
echo "Error adding snacks: " . $stmt->error;
}

header("Location: admin_dashboard.php");

$stmt->close();
$conn->close();
}
?>

细化用户端:user_dashboard.php

实现购买零食功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Member Dashboard</title>
<style>
body
{
text-align: center; /* 居中显示文本 */
padding: 20px; /* 增大上下行间距 */
margin-bottom : 20px;
}
form
{
display: inline-block; /* 使表单元素水平排列 */
}
label, input
{
margin-left : 5px; /* 增大上下行间距 */
margin-right : 5px; /* 增大上下行间距 */
}
</style>
</head>
<body>
<h1>Welcome to the Member Dashboard</h1>
<p>你好, <?php session_start(); echo $_SESSION["username"]; ?>! <!-- 显示用户的用户名 -->
<!-- 在此添加成员仪表板的内容 -->

<a href="logout.php"> 退出登录 <br> <br> </a> <!-- 提供注销链接 -->

<div class="inventory">
<h2>零食库存 <br> </h2>
<form method="post" action="member_purchase_snacks.php">
<?php
header("content-type:text/html; charset=utf-8"); //设置编码
session_start();

$servername = "localhost"; // 数据库服务器主机名
$username = "root"; // 数据库用户名
$password = "root"; // 数据库密码
$database = "snack"; // 数据库名称
// 创建数据库连接
$conn = new mysqli($servername, $username, $password, $database);

// 查询数据库中零食的信息,包括零食名称、snack_quantitysnack_price
$query = "SELECT snack_name, snack_sold, snack_quantity, snack_price FROM snacks";
$result = $conn->query($query);

if ($result->num_rows > 0)
{
while ($row = $result->fetch_assoc())
{
$snack_name = $row["snack_name"];
$snack_quantity = $row["snack_quantity"];
$snack_price = $row["snack_price"];
$snack_sold = $row["snack_sold"];
$remaining_quantity = $snack_quantity - $snack_sold;
$snack_monovalent = number_format($snack_price / $snack_quantity, 2); //单价,小数点后两位

// 在表单中显示零食信息,包括名称、数量、单价和让用户选择购买的数量
echo "<label for='snack_$snack_name'>$snack_name (库存: $remaining_quantity)</label>";
echo "<label>单价: $snack_monovalent</label>";
echo "<input type='number' name='snack_$snack_name' id='snack_$snack_name' value='0' min='0' max='$remaining_quantity'><br><br>";

}
}
else
{
echo "库存为空。";
}
?>
<br>
<input type="submit" value="购买">
</form>
</div>
</body>
</html>

创建 php 实现购买零食功能:member_purchase_snacks.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<?php
header("content-type:text/html; charset=utf8"); // 设置编码
session_start();

if ($_SERVER["REQUEST_METHOD"] === "POST") {
// 获取表单提交的数据
$snack_name = $_POST["snack_name"];
$snack_quantity = $_POST["snack_quantity"];
$snack_price = $_POST["snack_price"];

$encoding = array('UTF-8', 'ASCII', 'GB2312', 'GBK');
$utf8_snack_name = mb_convert_encoding($snack_name, "UTF-8", mb_detect_encoding($snack_name, $encoding));

// 连接到数据库
$conn = mysqli_connect("localhost", "root", "root", "snack");

if (!$conn)
die("数据库连接失败: " . mysqli_connect_error());

$snackid = null; // 初始化 snackid

// 查询是否有同名零食存在
$query = "SELECT snack_id FROM snacks WHERE snack_name = ?";
$stmt0 = $conn->prepare($query);
$stmt0->bind_param("s", $utf8_snack_name);
$stmt0->execute();
$stmt0->store_result();
$stmt0->bind_result($snackid);

if ($stmt0->fetch())
{
// 零食已存在,执行更新操作
$stmt0->close();

$update_query = "UPDATE snacks SET snack_quantity = snack_quantity + ?, snack_price = snack_price + ? WHERE snack_id = ?";
$stmt = $conn->prepare($update_query);
$stmt->bind_param("idi", $snack_quantity, $snack_price, $snackid);

if ($stmt->execute())
echo "The snack was successfully added to inventory.";
else
echo "Error adding snacks: " . $stmt->error;
}
else
{
// 零食不存在,执行插入操作
$stmt0->close();

$insert_query = "INSERT INTO snacks (date, snack_name, snack_sold, snack_quantity, snack_price) VALUES (NULL, ?, 0, ?, ?)";
$stmt = $conn->prepare($insert_query);
$stmt->bind_param("sid", $utf8_snack_name, $snack_quantity, $snack_price);

if ($stmt->execute())
echo "The snack was successfully added to inventory.";
else
echo "Error adding snacks: " . $stmt->error;
}

header("Location: admin_dashboard.php");

$stmt->close();
$conn->close();
}
?>

最终效果

最终创建的所有文件如下(hello world 省略):
文件展示