提交最终版代码

master
ZhuRuimin 1 year ago
parent 60a4172c6a
commit 91a685d860

@ -0,0 +1,129 @@
# 数据储存在wordle.xlsx中数据字段Date,Contest numberWordNumber of reported
# resultsNumber in hard mode1 try2 tries3 tries4 tries5 tries6 tries7 or more tries (X)
# 其中1 try2 tries3 tries4 tries5 tries6 tries7 or more tries (X)为百分比数
# Date格式为2022/1/7Contest number为每天的序号从202开始每天增加1
# Contest number从202开始每天增加1Number of reported results为每天的报告结果数Number in hard mode为每天的hard mode的报告结果数
# Contest number=202表示2022年1月7日Contest number=203表示2022年1月8日以此类推
# 1针对Number of reported results进行lstm时间序列分析,预测2023年3月1日的Number of reported results
import matplotlib.pyplot as plt
# import numpy as np
import pandas as pd
from pandas import DataFrame
from pandas import concat
from sklearn.preprocessing import MinMaxScaler
from keras.models import Sequential
from keras.layers import LSTM, Dense, Dropout
from numpy import concatenate
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from math import sqrt
import tensorflow as tf
tf.random.set_seed(2)
# 导入数据xlsx
qy_data = pd.read_excel('history.xlsx')
# 1.针对Number of reported results进行时间序列分析,结合使用lstm和arima模型预测未来30天的Number of reported results
# 删除Word列
data1 = qy_data.drop(['ProductName'], axis=1)
# 将Date列转换为时间格式
data1['Date'] = pd.to_datetime(data1['Date'])
# 将Date列设置为索引
data1 = data1.set_index('Date')
# 画出Number of reported results的折线图
plt.figure(figsize=(20, 10))
plt.plot(data1['Number of reported sales'])
plt.title('Number of reported sales')
plt.xlabel('Date')
plt.ylabel('Number of reported sales')
plt.show()
# 将dataframe转换为array
values = data1.values
# 将数据归一化
scaler = MinMaxScaler(feature_range=(0, 1))
scaled = scaler.fit_transform(values)
# 将数据转换为监督学习问题
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
n_vars = 1 if type(data) is list else data.shape[1]
df = DataFrame(data)
cols, names = list(), list()
# 输入序列(t-n, ... t-1)
for i in range(n_in, 0, -1):
cols.append(df.shift(i))
names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
# 预测序列(t, t+1, ... t+n)
for i in range(0, n_out):
cols.append(df.shift(-i))
if i == 0:
names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
else:
names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
# 拼接
agg = concat(cols, axis=1)
agg.columns = names
# 删除空值
if dropnan:
agg.dropna(inplace=True)
return agg
reframed = series_to_supervised(scaled, 1, 1)
# 删除不需要的列
reframed.drop(reframed.columns[[7, 8, 9, 10, 11, 12, 13]], axis=1, inplace=True)# 这是指删除第7,8,9,10,11,12,13列分别是1 try2 tries3 tries4 tries5 tries6 tries7 or more tries (X)
print(reframed.head())
# 将数据分为训练集和测试集
values = reframed.values
n_train_days = 330
train = values[:n_train_days, :]
test = values[n_train_days:, :]
# 将数据分为输入和输出
train_X, train_y = train[:, :-1], train[:, -1]
test_X, test_y = test[:, :-1], test[:, -1]
# 将输入转换为3D格式[样本数,时间步长,特征数]
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
# 构建模型
model = Sequential()
model.add(LSTM(50, input_shape=(train_X.shape[1], train_X.shape[2])))
model.add(Dropout(0.2))
model.add(Dense(1))
model.compile(loss='mae', optimizer='adam')
# 模型训练
history = model.fit(train_X, train_y, epochs=10, batch_size=72, validation_data=(test_X, test_y), verbose=2, shuffle=False)
# 模型预测
yhat = model.predict(test_X)
test_X = test_X.reshape((test_X.shape[0], test_X.shape[2]))
# 反归一化
inv_yhat = concatenate((yhat, test_X[:, 1:]), axis=1)
# inv_yhat = scaler.inverse_transform(inv_yhat)
inv_yhat = inv_yhat[:,0]
test_y = test_y.reshape((len(test_y), 1))
inv_y = concatenate((test_y, test_X[:, 1:]), axis=1)
# inv_y = scaler.inverse_transform(inv_y)
inv_y = inv_y[:,0]
# 将预测得到的数据绘制成折线图
# 将y轴数据转换为整数
inv_y = inv_y*200000
inv_yhat = inv_yhat*200000
plt.figure(figsize=(20, 10))
plt.plot(inv_y, label='real')
plt.plot(inv_yhat, label='predict')
plt.legend()
plt.show()
# 模型评估
rmse = sqrt(mean_squared_error(inv_y, inv_yhat))
mae = mean_absolute_error(inv_y, inv_yhat)
r2 = r2_score(inv_y, inv_yhat)
print('Test RMSE: %.3f' % rmse)
print('Test MAE: %.3f' % mae)
print('Test R2: %.3f' % r2)

@ -1,3 +1,4 @@
import serial
error_codes = {
@ -74,7 +75,7 @@ def face_register(username, time):
def process_face_recognition_result(data, errorcode):
if errorcode == 0:
username = data[2:34].decode('utf-8')
print("用户名:", username)
return username
elif errorcode in error_codes:
print("error:", error_codes[errorcode])
else:
@ -89,6 +90,7 @@ def process_note_msg(command, errorcode, data):
def process_face_register_result(data, errorcode):
if errorcode == 0:
print("注册成功")
return "Success"
elif errorcode in error_codes:
print("error:", error_codes[errorcode])
else:
@ -97,7 +99,7 @@ def process_face_register_result(data, errorcode):
def process_reply_msg(command, errorcode, data):
if command == 0x12:
process_face_recognition_result(data, errorcode)
return process_face_recognition_result(data, errorcode)
elif command == 0x26:
process_face_register_result(data, errorcode)
else:
@ -106,9 +108,7 @@ def process_reply_msg(command, errorcode, data):
def process_command(status, command, errorcode, data):
if status == 0x00:
process_reply_msg(command, errorcode, data)
return 1
return process_reply_msg(command, errorcode, data)
elif status == 0x01:
process_note_msg(command, errorcode, data)
@ -128,14 +128,39 @@ def read_serial_data(ser):
return process_command(status, command, errorcode, data)
# 打开串口连接
faceserial = serial.Serial("COM21", 115200, timeout=0.5)
print("启动人脸识别")
faceserial.write(face_recognition(10))
# faceserial.write(face_register("username", 15))
while True:
if read_serial_data(faceserial) == 1:
break
faceserial.close()
def recognition(timeout):
# Call the face recognition function
faceserial = serial.Serial("/dev/ttyUSB0", 115200, timeout=0.5)
print("启动人脸识别")
faceserial.write(face_recognition(timeout))
username = ""
while username == "":
result = read_serial_data(faceserial)
if result:
username = result
faceserial.close()
username = username.rstrip('\u0000')
return username
# # 打开串口连接
# faceserial = serial.Serial("COM21", 115200, timeout=0.5)
# print("启动人脸识别")
# faceserial.write(face_recognition(10))
# # faceserial.write(face_register("username", 15))
#
# while True:
# if read_serial_data(faceserial) == 1:
# break
#
# faceserial.close()
def register(username):
faceserial = serial.Serial("/dev/ttyUSB0", 115200, timeout=0.5)
print("启动人脸识别")
faceserial.write(face_register(username, 15))
flag = 0
while flag is 0:
if read_serial_data(faceserial) == "Success":
flag = 1
break
faceserial.close()
return flag

@ -1,21 +1,21 @@
import RPi.GPIO as GPIO
from mfrc522 import SimpleMFRC522
# import RPi.GPIO as GPIO
# from mfrc522 import SimpleMFRC522
import random
import time
# reader = SimpleMFRC522()
reader = SimpleMFRC522()
def read():
try:
while True:
id, text = reader.read()
return id, text
finally:
GPIO.cleanup()
previous_id = None # 存储先前的卡号
try:
while True:
id, text = reader.read()
if id != previous_id:
print("===================================")
print("新卡号: {}".format(id))
print("===================================")
previous_id = id
print("文本信息: {}".format(text))
print("-----------------------------------")
finally:
GPIO.cleanup()
def readTest():
time.sleep(2)
random_id = random.randint(1, 1000000000)
random_value = random.randint(1, 4)
return random_id, str(random_value)

@ -1,3 +1,2 @@
from django.test import TestCase
# Create your tests here.

@ -1,7 +1,15 @@
# import time
import time
from turtle import delay
from django.http import JsonResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from hardware import face, rfid
product_list = []
productID_list = []
# Create your views here.
def index(request):
return render(request, "back/base.html")
@ -19,6 +27,10 @@ def order_management(request):
return render(request, "back/order_management.html")
def history_analyze(request):
return render(request, "back/history_analyze.html")
def add_user(request):
if request.method == 'POST':
# 处理添加用户的逻辑
@ -33,7 +45,7 @@ def add_user(request):
return JsonResponse({'status': 'success'})
# 如果不是POST请求直接渲染页面
return render(request, 'front/user_management.html')
return render(request, 'front/html/user_management.html')
def refresh_users(request):
@ -52,12 +64,67 @@ def refresh_users(request):
def login(request):
return render(request, "front/html/userLogin.html")
return render(request, "front/html/logIn.html")
def sign(request):
return render(request, "front/html/userSign.html")
return render(request, "front/html/signUp.html")
def cart(request):
return render(request, "front/html/shoppingCart.html")
def facerecognition(request):
#username = face.recognition(30)
username = 'Dustin'
#延时三秒
time.sleep(3)
return JsonResponse({'username': username})
@csrf_exempt
def faceregister(request):
# POST请求有username参数
if request.method == 'POST':
username = request.POST.get('username')
face.register(username)
return JsonResponse({'status': 'success'})
def getProd(request):
prodID = request.GET.get('prodID')
if prodID == '1':
return JsonResponse({'prodID': '1', 'prodName': '旺仔小馒头', 'prodPrice': '2.33', 'intro': '好吃,爱吃!'})
elif prodID == '2':
return JsonResponse({'prodID': '2', 'prodName': '旺仔牛奶', 'prodPrice': '4.66', 'intro': '三年六班李子明推荐'})
elif prodID == '3':
return JsonResponse({'prodID': '3', 'prodName': '牛奶糖', 'prodPrice': '3.80', 'intro': '奶香浓郁,回味无穷'})
elif prodID == '4':
return JsonResponse(
{'prodID': '4', 'prodName': '卫龙魔芋爽', 'prodPrice': '0.50', 'intro': '爽滑轻弹,好吃不贵'})
else:
return JsonResponse({'prodID': '0', 'prodName': '商品不存在', 'prodPrice': '0.00', 'intro': '商品不存在'})
#import multiprocessing
def updaterfid(request):
print("try to read")
newProdID, newProdText = rfid.readTest()
print("read success")
print("newProdID:", newProdID)
print("newProdText:", newProdText)
if newProdID not in productID_list:
productID_list.append(str(newProdID))
product_list.append(str(newProdText).rstrip())
print("add success")
# 在超时时间内完成了逻辑处理,直接返回响应
return JsonResponse({'product_list': product_list})
def cleanrfid(request):
productID_list.clear()
product_list.clear()
return JsonResponse({'Status': 'success'})

@ -25,7 +25,10 @@ SECRET_KEY = "django-insecure-$8)6@6t4p%(4-=f!q3mn$_!r9wl-s-h+!f+^xp=$&plwo3p670
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
ALLOWED_HOSTS = [
"0.0.0.0",
"127.0.0.1",
]
# Application definition
@ -77,10 +80,8 @@ WSGI_APPLICATION = "smartshop_be.wsgi.application"
DATABASES = {
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": "smartshop",
"USER": "root",
"PASSWORD": "Zrm5123856",
"ENGINE": "django.db.backends.sqlite3",
}
}

@ -27,9 +27,15 @@ urlpatterns = [
path("user_management/", views.user_management, name="user_management"),
path("product_management/", views.product_management, name="product_management"),
path("order_management/", views.order_management, name="order_management"),
path("history_analyze/", views.history_analyze, name="history_analyze"),
path('add_user/', views.add_user, name='add_user'),
path('refresh_users/', views.refresh_users, name='refresh_users'),
path('login/', views.login, name='login'),
path('sign/', views.sign, name='sign'),
path('cart/', views.cart, name='cart'),
path('rec/', views.facerecognition, name='rec'),
path('reg/', views.faceregister, name='reg'),
path('getProd/', views.getProd, name='getProd'),
path('updaterfid/', views.updaterfid, name='updaterfid'),
path('cleanrfid/', views.cleanrfid, name='cleanrfid'),
]

@ -81,6 +81,7 @@ main {
<li><a href="{% url 'user_management' %}">用户管理</a></li>
<li><a href="{% url 'product_management' %}">商品管理</a></li>
<li><a href="{% url 'order_management' %}">订单管理</a></li>
<li><a href="{% url 'history_analyze' %}">销售历史情况分析</a></li>
</ul>
</nav>
<main>

@ -0,0 +1,328 @@
<!-- product_management.html -->
{% extends 'back/base.html' %}
{% block content %}
<style>
/* 页面样式 */
body {
font-family: Arial, sans-serif;
}
h2 {
margin-bottom: 20px;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
padding: 10px;
text-align: left;
border-bottom: 1px solid #ddd;
}
th {
background-color: #f2f2f2;
}
#add-product-btn,
#refresh-button {
padding: 10px 20px;
margin-bottom: 10px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.modal {
display: none;
position: fixed;
z-index: 999;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgba(0, 0, 0, 0.4);
}
.modal-content {
background-color: #fefefe;
margin: 15% auto;
padding: 20px;
border: 1px solid #888;
width: 400px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
border-radius: 4px;
}
.close {
color: #888;
float: right;
font-size: 28px;
font-weight: bold;
cursor: pointer;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
#product-form label {
display: block;
margin-top: 10px;
}
#product-form input[type="text"],
#product-form input[type="number"],
#product-form input[type="checkbox"] {
width: 100%;
padding: 5px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
.modal-buttons {
margin-top: 20px;
text-align: right;
}
.modal-buttons button {
margin-left: 10px;
}
/* 其他样式 */
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
z-index: 999;
}
.loading{
position: fixed;
top: 60%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 999;
}
</style>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<h2>商品管理</h2>
<button id="add-product-btn" style="display: none">分析商品</button>
<button id="refresh-button">刷新</button>
<table id="product-table">
<thead>
<tr>
<th>ID</th>
<th>商品名</th>
<th>单价(单位:分)</th>
<th>剩余库存</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{# {% for user_profile in user_profiles %}#}
{# <tr>#}
{# <td>{{ user_profile.user.id }}</td>#}
{# <td>{{ user_profile.user.username }}</td>#}
{# <td>{{ user_profile.balance }}</td>#}
{# <td>{% if user_profile.is_vip %}是{% else %}否{% endif %}</td>#}
{# <td>{{ user_profile.face_id }}</td>#}
{# <td>#}
{# <button class="edit-button" data-user-id="{{ user_profile.user.id }}">修改</button>#}
{# <button class="delete-button" data-user-id="{{ user_profile.user.id }}">删除</button>#}
{# </td>#}
{# </tr>#}
{# {% endfor %}#}
<tr>
<td>1</td>
<td>可乐</td>
<td>300</td>
<td>20</td>
<td>
<button class="edit-button" data-product-id="1">分析</button>
<button class="delete-button" data-product-id="1">删除</button>
</td>
</tr>
<tr>
<td>2</td>
<td>雪碧</td>
<td>300</td>
<td>20</td>
<td>
<button class="edit-button" data-product-id="2">分析</button>
<button class="delete-button" data-product-id="2">删除</button>
</tr>
</tbody>
</table>
<!-- 弹窗 -->
<div id="product-modal" class="modal">
<div class="modal-content">
<span class="close">&times;</span>
<h3 id="modal-title">分析商品</h3>
<form id="product-form">
<!-- 商品信息表单字段 -->
<input type="hidden" id="product-id" name="product-id">
<label for="productname">商品名:</label>
<label for="productname">可乐</label>
<label for="price">单价(单位:分)</label>
<label for="price">3.00</label>
<label for="stock">库存:</label>
<label for="stock">20</label>
<br>
<label for="time">分析时间:</label>
<select name="time">
<option value="1">一个月</option>
<option value="2">一年</option>
</select>
<!-- 保存和取消按钮 -->
<div class="modal-buttons">
<button type="submit" class="save-button">分析</button>
<button type="button" class="cancel-button">取消</button>
</div>
</form>
</div>
</div>
<!-- 预测结果图片 -->
<div class="modal-img" style="display: none">
<img src="https://ooo.0x0.ooo/2023/11/14/OeRNLj.png" alt="预测结果" width="100%">
<img src="https://ooo.0x0.ooo/2023/11/14/OeRAFU.png" alt="预测结果" width="100%">
</div>
<div class="loading" style="display: none">
<img src="https://www.sucaijishi.com/uploadfile/2018/0919/20180919030732302.gif" alt="加载中..." >
</div>
<script>
// 弹窗显示和隐藏
var modal = document.getElementById("product-modal");
var btn = document.getElementById("add-product-btn");
var span = document.getElementsByClassName("close")[0];
var form = document.getElementById("product-form");
var modalTitle = document.getElementById("modal-title");
var productIdField = document.getElementById("product-id");
btn.onclick = function () {
modalTitle.textContent = "添加商品";
form.reset();
modal.style.display = "block";
}
span.onclick = function () {
modal.style.display = "none";
}
window.onclick = function (event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
// 刷新按钮点击事件
var refreshButton = document.getElementById("refresh-button");
refreshButton.addEventListener("click", function () {
// 在这里可以执行获取最新内容的操作
// 例如:通过 AJAX 请求获取最新的商品列表数据并刷新表格内容
});
// 页面加载完成后执行的操作
window.addEventListener("load", function () {
// 在这里可以执行页面加载完成后的操作
// 例如:初始化页面、获取初始数据等
});
// 修改按钮点击事件
var editButtons = document.querySelectorAll(".edit-button");
editButtons.forEach(function (button) {
button.addEventListener("click", function () {
var productId = button.getAttribute("data-product-id");
modalTitle.textContent = "分析商品";
productIdField.value = productId;
// 根据商品ID获取其他商品信息并填充到表单中
// 可以通过 AJAX 请求获取商品信息
// 然后将商品信息填充到表单字段中
modal.style.display = "block";
});
});
// 删除按钮点击事件
var deleteButtons = document.querySelectorAll(".delete-button");
deleteButtons.forEach(function (button) {
button.addEventListener("click", function () {
var productId = button.getAttribute("data-product-id");
// 根据商品ID执行删除商品操作
// 可以通过 AJAX 请求将商品ID发送到后端进行删除
// 然后可以根据返回的结果刷新商品列表或进行其他操作
});
});
// 添加/编辑商品表单提交
form.addEventListener("submit", function (event) {
event.preventDefault();
var productId = productIdField.value;
// 在这里可以通过 JavaScript 获取表单字段的值,进行保存等操作
// 例如:通过 AJAX 请求将表单数据发送到后端进行保存
// 然后可以根据返回的结果刷新商品列表或进行其他操作
modal.style.display = "none";
});
// 取消按钮点击事件
var cancelButton = document.querySelector(".cancel-button");
cancelButton.addEventListener("click", function () {
modal.style.display = "none";
});
$(document).ready(function() {
// 添加商品按钮点击事件
$('#add-product-btn').click(function() {
// 显示弹窗
$('#product-modal').show();
$('.overlay').show();
$('#modal-title').text('分析商品');
});
// 关闭弹窗按钮点击事件
$('.close').click(function() {
// 隐藏弹窗
$('#product-modal').hide();
$('.overlay').hide();
});
// 取消按钮点击事件
$('.cancel-button').click(function() {
// 隐藏弹窗
$('#product-modal').hide();
$('.overlay').hide();
});
//保存按钮点击事件
$('.save-button').click(function() {
// 隐藏弹窗
//控制台输出
console.log("分析商品");
$('.loading').show();
$('#product-modal').hide();
$('.overlay').hide();
//延时三秒
setTimeout(function() {
//显示图片
$('.loading').hide();
$('.modal-img').show();
}, 5000);
});
});
</script>
{% endblock %}

@ -0,0 +1,232 @@
/************************************************************
** CSS **
************************************************************/
html {
font-size: 16px;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans',
'Droid Sans', 'Helvetica Neue', 'Microsoft Yahei', sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
width: 100vw;
height: 100vh;
}
body * {
box-sizing: border-box;
flex-shrink: 0;
}
.flex-row {
display: flex;
flex-direction: row;
}
.flex-col {
display: flex;
flex-direction: column;
}
.justify-start {
justify-content: flex-start;
}
.justify-between {
justify-content: space-between;
}
.items-center {
align-items: center;
}
.self-center {
align-self: center;
}
/** 清理默认样式 **/
a {
color: unset;
text-decoration: unset;
}
button {
padding: unset;
border-style: unset;
background-color: unset;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: unset;
font-size: unset;
font-weight: unset;
}
input,
textarea {
padding: unset;
outline: unset;
border-style: unset;
background-color: unset;
resize: unset;
}
p {
margin: unset;
}
select {
outline: unset;
border-style: unset;
}
table {
border-spacing: unset;
}
ul,
ol {
margin: unset;
padding: unset;
list-style-type: none;
}
.page {
padding: 25px 14px 30px 17px;
background-image: linear-gradient(90deg, #e7e5c300 35.9%, #e6dfdc 64.1%);
width: 100%;
overflow-y: auto;
overflow-x: hidden;
height: 100%;
}
.space-y-26 > *:not(:first-child) {
margin-top: 26px;
}
.section {
padding: 22px 21px 22px 25px;
background-color: #43cf7ccc;
border-radius: 15px;
}
.space-x-24 > *:not(:first-child) {
margin-left: 24px;
}
.logo-img {
width: 157px;
height: 157px;
}
.space-y-16 > *:not(:first-child) {
margin-top: 16px;
}
.text {
color: #ffffff;
font-size: 72px;
font-family: SourceHanSansCN;
font-weight: 700;
line-height: 68.5px;
}
.text_3 {
color: #ffffff;
font-size: 40px;
font-family: HarmonyOSSansSC;
font-weight: 700;
line-height: 31px;
letter-spacing: 2px;
}
.text-wrapper {
padding: 32px 0 34px;
background-color: #00baad8a;
border-radius: 10px;
height: 139px;
}
.text_2 {
margin-left: 26px;
margin-right: 20px;
color: #ffffff;
font-size: 80px;
font-family: AlimamaShuHeiTi;
line-height: 74px;
}
.text-wrapper_2 {
padding: 28px 0 24px;
background-color: #00baad8a;
border-radius: 15px;
}
.font_1 {
font-size: 45px;
font-family: SourceHanSansCN;
font-weight: 800;
color: #ffffff;
}
.text_4 {
line-height: 43.5px;
}
.section_2 {
padding: 93px 134px 148px;
background-image: linear-gradient(225.1deg, #6d819c 21.1%, #55967e 79.8%);
border-radius: 15px;
}
.image_2 {
width: 480px;
height: 360px;
}
.text-wrapper_3 {
margin-top: 83px;
padding: 28px 0 22px;
background-color: #cccccca6;
border-radius: 15px;
}
.text_5 {
line-height: 46.5px;
letter-spacing: 1.5px;
}
.text-wrapper_4 {
align-self: center;
margin-top: 79px;
}
.view {
padding: 42px 0 40px;
background-color: #43cf7c99;
border-radius: 15px;
width: 399px;
}
.footer-img {
border-radius: 15px;
/* width: 1048px;
height: 492px;
margin: auto; */
max-width: 100%;
height: auto;
}
.button {
color: #ffffff;
font-size: 60px;
font-family: SourceHanSansCN;
font-weight: 800;
line-height: 58px;
letter-spacing: 2px;
cursor: pointer;
}
.button:hover {
background-color: #43cf7bdf;
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
}

@ -1,130 +1,258 @@
.welcome{
text-align: center;
/* 文字上下居中 */
line-height: 20vh;
/* font-size: 50px; */
color: #fff;
background-color: rgb(7, 193, 96);
/* 字体大小 */
font-size: 80px;
height: 20vh;
margin: 0 auto;
}
.product {
/* border: 1px solid #ccc; */
/* 边距 */
padding: 10px;
/* display: inline-block; */
/* 对齐方式 */
/* float: left; */
/* 宽度 */
width: 100vw;
/* text-align: center; */
/* 边框 */
border: 1px solid #ccc;
/* 有边框的box */
box-sizing: border-box;
display: inline-block;
height: 15vh;
}
.product img {
width: 15vh;
height: 15vh;
margin-bottom: 10px;
padding: 10px;
}
.product h3 {
margin: 0;
font-size: 50px;
}
.ProductInfo{
color: #888;
margin: 0;
font-size: 40px;
/************************************************************
** CSS **
************************************************************/
html {
font-size: 16px;
}
body {
height: 100%;
margin: 0;
padding: 0;
}
.container {
min-height: 100%;
position: dynamic;
}
.content {
padding-bottom: 50px; /* 为按钮预留空间 */
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
height: 50px;
background-color: #f5f5f5;
text-align: center;
}
.footer button {
margin-top: 10px;
}
*{
box-sizing: border-box;
background-color: rgb(202, 249, 224);
}
.ProductImage{
float: left;
margin-right: 10px;
}
.ProductName{
font-size: 30px;
margin-top: 0px;
margin-left: 0px;
}
.proceed{
/* 位于页面底部距离底部5vh,左右居中 */
position: fixed;
bottom: 3vh;
left: 50%;
transform: translateX(-50%);
/* 字体大小 */
font-size: 50px;
}
button{
/* 字体大小 */
font-size: 50px;
/* 字体颜色 */
color: #7E7E7E;
/* 背景颜色 */
background-color: rgb(202, 249, 224);
/* 居中 */
text-align: center;
/* 边框 */
/* 圆角 */
border-radius: 10px;
/* 边框比内部文字大一点 */
padding: 10px 20px;
}
.price{
position: absolute;
right: 5vw;
bottom: auto;
color: red;
font-size: 60px;
/* 文本加粗 */
font-weight: bold;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans',
'Droid Sans', 'Helvetica Neue', 'Microsoft Yahei', sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
width: 100vw;
height: 100vh;
}
body * {
box-sizing: border-box;
flex-shrink: 0;
}
.flex-row {
display: flex;
flex-direction: row;
}
.flex-col {
display: flex;
flex-direction: column;
}
.justify-start {
justify-content: flex-start;
}
.justify-between {
justify-content: space-between;
}
.items-center {
align-items: center;
}
.self-center {
align-self: center;
}
/** 清理默认样式 **/
a {
color: unset;
text-decoration: unset;
}
button {
padding: unset;
border-style: unset;
background-color: unset;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: unset;
font-size: unset;
font-weight: unset;
}
input,
textarea {
padding: unset;
outline: unset;
border-style: unset;
background-color: unset;
resize: unset;
}
p {
margin: unset;
}
select {
outline: unset;
border-style: unset;
}
table {
border-spacing: unset;
}
ul,
ol {
margin: unset;
padding: unset;
list-style-type: none;
}
.page {
padding: 25px 14px 29px 18px;
background-image: linear-gradient(90deg, #e7e5c300 35.9%, #e6dfdc 64.1%);
width: 100%;
overflow-y: auto;
overflow-x: hidden;
height: 100%;
}
.space-y-26 > *:not(:first-child) {
margin-top: 26px;
}
.section {
padding: 22px 21px 22px 25px;
background-color: #43cf7ccc;
border-radius: 15px;
}
.space-x-24 > *:not(:first-child) {
margin-left: 24px;
}
.logo-img {
width: 157px;
height: 157px;
}
.space-y-16 > *:not(:first-child) {
margin-top: 16px;
}
.text {
color: #ffffff;
font-size: 72px;
font-family: SourceHanSansCN;
font-weight: 700;
line-height: 68.5px;
}
.text_3 {
color: #ffffff;
font-size: 40px;
font-family: HarmonyOSSansSC;
font-weight: 700;
line-height: 31px;
letter-spacing: 2px;
}
.text-wrapper {
padding: 42px 0 34px;
background-color: #00baad8a;
border-radius: 10px;
height: 139px;
}
.text_2 {
margin-left: 40px;
margin-right: 28px;
color: #ffffff;
font-size: 80px;
font-family: AlimamaShuHeiTi;
line-height: 62.5px;
}
.text-wrapper_2 {
padding: 28px 0 24px;
background-color: #00baad8a;
border-radius: 15px;
}
.text_4 {
color: #ffffff;
font-size: 45px;
font-family: SourceHanSansCN;
font-weight: 800;
line-height: 43.5px;
}
.section_2 {
padding: 42px 0 42px;
background-image: linear-gradient(221.3deg, #6d819c 21.2%, #55967e 80%);
border-radius: 15px;
}
.list {
margin-left: 28px;
margin-right: 30px;
margin-top: -40px; /* 用魔法对抗魔法 */
}
.space-x-36 > *:not(:first-child) {
margin-left: 36px;
}
.font_1 {
font-size: 66px;
font-family: SourceHanSansCN;
letter-spacing: 2px;
line-height: 63px;
font-weight: 800;
color: #ffffff;
}
.font_2 {
font-size: 66px;
font-family: SourceHanSansCN;
letter-spacing: 2px;
line-height: 51px;
font-weight: 800;
color: #b04831cc;
}
.price {
margin-left: auto;
margin-right: 10px;
}
.section_3 {
margin-top: 46px;
}
.space-y-20 > *:not(:first-child) {
margin-top: 20px;
}
.view {
margin-left: 64px;
}
.space-x-58 > *:not(:first-child) {
margin-left: 58px;
}
.section_4 {
padding: 41px 0 33px;
background-color: #3b8686;
border-radius: 15px;
}
.text-wrapper_3 {
padding: 30px 0 24px;
background-color: #cccccc78;
border-radius: 20px;
width: 508px;
}
.sumPrice {
color: #b04831d9;
}
.text-wrapper_4 {
margin-top: 33px;
}
.view_2 {
padding: 44px 0 38px;
background-color: #43cf7c99;
border-radius: 15px;
width: 399px;
}
.button {
color: #ffffff;
font-size: 60px;
font-family: SourceHanSansCN;
font-weight: 800;
line-height: 57px;
letter-spacing: 2px;
cursor: pointer;
}
.button:hover {
background-color: #43cf7bdf;
}
/* 设置商品列表容器高度,使其可以滚动 */
.list {
height: 1100px; /* 设置合适的高度 */
overflow-y: scroll;
}

@ -0,0 +1,264 @@
/************************************************************
** CSS **
************************************************************/
html {
font-size: 16px;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans',
'Droid Sans', 'Helvetica Neue', 'Microsoft Yahei', sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
width: 100vw;
height: 100vh;
}
body * {
box-sizing: border-box;
flex-shrink: 0;
}
.flex-row {
display: flex;
flex-direction: row;
}
.flex-col {
display: flex;
flex-direction: column;
}
.justify-start {
justify-content: flex-start;
}
.justify-between {
justify-content: space-between;
}
.items-center {
align-items: center;
}
.self-center {
align-self: center;
}
/** 清理默认样式 **/
a {
color: unset;
text-decoration: unset;
}
button {
padding: unset;
border-style: unset;
background-color: unset;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: unset;
font-size: unset;
font-weight: unset;
}
input,
textarea {
padding: unset;
outline: unset;
border-style: unset;
background-color: unset;
resize: unset;
}
p {
margin: unset;
}
select {
outline: unset;
border-style: unset;
}
table {
border-spacing: unset;
}
ul,
ol {
margin: unset;
padding: unset;
list-style-type: none;
}
.page {
padding: 25px 14px 30px 17px;
background-image: linear-gradient(90deg, #e7e5c300 35.9%, #e6dfdc 64.1%);
width: 100%;
overflow-y: auto;
overflow-x: hidden;
height: 100%;
}
.space-y-26 > *:not(:first-child) {
margin-top: 26px;
}
.section {
padding: 22px 21px 22px 25px;
background-color: #43cf7ccc;
border-radius: 15px;
}
.space-x-24 > *:not(:first-child) {
margin-left: 24px;
}
.logo-img {
width: 157px;
height: 157px;
}
.space-y-16 > *:not(:first-child) {
margin-top: 16px;
}
.text {
color: #ffffff;
font-size: 72px;
font-family: SourceHanSansCN;
font-weight: 700;
line-height: 68.5px;
}
.text_3 {
color: #ffffff;
font-size: 40px;
font-family: SourceHanSansCN;
font-weight: 700;
line-height: 31px;
letter-spacing: 2px;
}
.text-wrapper {
padding: 32px 0 34px;
background-color: #00baad8a;
border-radius: 10px;
height: 139px;
}
.text_2 {
margin-left: 26px;
margin-right: 20px;
color: #ffffff;
font-size: 80px;
font-family: AlimamaShuHeiTi;
line-height: 74px;
}
.text-wrapper_2 {
padding: 28px 0 22px;
background-color: #00baad8a;
border-radius: 15px;
}
.font_1 {
font-size: 45px;
font-family: SourceHanSansCN;
letter-spacing: 2px;
line-height: 52px;
font-weight: 800;
color: #ffffff;
}
.text_4 {
line-height: 46px;
letter-spacing: unset;
}
.section_2 {
padding: 72px 248px 60px;
background-image: linear-gradient(225.1deg, #6d819c 21.1%, #55967e 79.8%);
border-radius: 15px;
}
.text_5 {
line-height: 51.5px;
}
.view_1 {
margin-right: 3px;
margin-top: 26px;
}
.text_6 {
margin-top: 40px;
}
.view {
margin-right: 4px;
margin-top: 26px;
}
.section_3 {
background-color: #cccccca6;
border-radius: 15px;
height: 96px;
}
.text_7 {
margin-top: 40px;
}
.text-wrapper_3 {
align-self: center;
margin-top: 54px;
}
.view_3 {
padding: 44px 0 38px;
background-color: #43cf7c99;
border-radius: 15px;
width: 315px;
}
.text_9 {
align-self: center;
margin-top: 36px;
color: #e5e5e5;
font-size: 36px;
font-family: SourceHanSansCN;
font-weight: 800;
line-height: 34.5px;
letter-spacing: 2px;
}
.text_9:hover {
color: #e5e5e597;
}
.footer-img {
border-radius: 15px;
/* width: 1048px;
height: 492px;
margin: auto; */
max-width: 100%;
height: auto;
}
.input {
padding: 10px 10px 10px 10px;
color: #ffffff;
font-size: 30px;
text-align: center;
}
.button {
color: #ffffff;
font-size: 60px;
font-family: SourceHanSansCN;
font-weight: 800;
line-height: 57.5px;
letter-spacing: 2px;
cursor: pointer;
}
.button:hover {
background-color: #43cf7bdf;
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 9999;
}

@ -27,9 +27,8 @@ main {
background-color: rgb(202, 249, 224);
/* 背景颜色无限延申 */
background-repeat: repeat;
margin: 0 auto;
/* 紧挨上文 */
margin-top: 0px;
margin: 0 auto;
}
footer {
@ -94,9 +93,20 @@ button:active{
.photo{
/* 上下居中 */
margin: 0 auto;
/* 放大 */
transform: scale(1.5);
/* 下移10vh */
margin-top: 15vh;
}
margin: 15vh auto 0;
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
}

@ -37,8 +37,6 @@ input{
transform: translateX(-50%);
/* 字体大小 */
font-size: 50px;
/* 字体大小 */
font-size: 50px;
/* 字体颜色 */
color: #7E7E7E;
/* 背景颜色 */

@ -0,0 +1,64 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>欢迎使用 - 无人超市</title>
<link rel="stylesheet" href="../static/css/logIn.css"/>
</head>
<body>
<div class="flex-col page space-y-26">
<div class="flex-row justify-between items-center section">
<div class="flex-row items-center space-x-24">
<img class="logo-img" src="../static/img/logo.png"/>
<div class="flex-col items-center space-y-16">
<span class="text">无人超市</span>
<span class="text_3">Smart Market</span>
</div>
</div>
<div class="flex-col justify-start text-wrapper"><span class="text_2">用户登录</span></div>
</div>
<div class="flex-col justify-start items-center text-wrapper_2">
<span class="font_1 text_4">欢迎使用无人超市</span>
</div>
<div class="flex-col section_2">
<img
class="self-center image_2"
src="../static/img/face-unscreen.gif"
/>
<div class="flex-col justify-start items-center text-wrapper_3">
<span class="font_1 text_5">请靠近机器,以进行人脸识别</span>
</div>
<button class="flex-col justify-start items-center text-wrapper_4 view button"
onclick="location.href=('../sign')">新用户注册
</button>
</div>
<img class="footer-img" src="../static/img/7x24.png"/>
</div>
</body>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
// JavaScript代码显示和隐藏蒙版
$(document).ready(function () {
// 发送GET请求到API
$.get('/rec/', function (data) {
if (data.error) {
alert('API请求失败');
} else {
$('.text_5').text('欢迎,' + data.username);
//三秒后跳转到/cart/
setTimeout(function () {
window.location.href = "/cart/?username=" + data.username;
$.get('/cleanrfid/', function (data) {
if (data.error) {
alert('API请求失败');
}
});
}, 3000);
}
});
});
</script>
</html>

@ -1,50 +1,225 @@
<!DOCTYPE html>
<html lang="en">
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>无人超市--购物车</title>
<link rel="stylesheet" href="../static/css/shoppingCart.css">
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>购物车 - 无人超市</title>
<link rel="stylesheet" href="../static/css/shoppingCart.css"/>
</head>
<main>
<h1 class="welcome">无人超市购物车</h1>
<!-- <canvas id="gifFace" width="300" height="300"> </canvas> -->
<!-- <div><img src="smartshop/img/face.gif" alt="face"></div> -->
</main>
<body>
<!-- 把下面的东西放入一个列表-->
<div class="product">
<img src="../static/img/product1.jpg" alt="Product Image" class="ProductImage">
<h3 class="ProductName">旺仔小馒头</h3>
<p class="ProductInfo">好吃爱吃</p>
<p class="price">¥4.50</p>
<div class="flex-col page space-y-26">
<div class="flex-row justify-between items-center section">
<div class="flex-row items-center space-x-24">
<img class="logo-img" src="../static/img/logo.png"/>
<div class="flex-col items-center space-y-16">
<span class="text">无人超市</span>
<span class="text_3">Smart Market</span>
</div>
</div>
<div class="flex-col justify-start text-wrapper"><span class="text_2 username">DustinZ</span></div>
</div>
<div class="flex-col justify-start items-center text-wrapper_2">
<span class="text_4" id="cartItemCount">购物车0件商品</span>
</div>
<div class="product">
<img src="../static/img/product2.jpg" alt="Product Image" class="ProductImage">
<h3 class="ProductName">乐事薯片</h3>
<p class="ProductInfo">好吃爱吃</p>
<p class="price">¥5.50</p>
<div class="flex-col justify-start section_2">
<div class="flex-col list">
{# <!-- 商品 1 开始 -->#}
{# <div class="flex-row items-center list-item section_3 space-x-58">#}
{# <div class="flex-row items-center flex-auto space-x-36">#}
{# <img class="shrink-0 item_img" src="../static/img/item1.png"/>#}
{# <div class="flex-col items-start flex-auto space-y-20">#}
{# <span class="font_1 prodName">旺仔小馒头</span>#}
{# <span class="font_3 intro">好吃,爱吃!</span>#}
{# </div>#}
{# </div>#}
{# <div class="flex-row items-center group">#}
{# <span class="font_2 price">¥2.33</span>#}
{# </div>#}
{# </div>#}
{# <!-- 商品 2 开始 -->#}
{# <div class="flex-row items-center list-item section_3 space-x-58">#}
{# <div class="flex-row items-center flex-auto space-x-36">#}
{# <img class="shrink-0 item_img" src="../static/img/item2.png"/>#}
{# <div class="flex-col items-start flex-auto space-y-20">#}
{# <span class="font_1 prodName">旺仔牛奶</span>#}
{# <span class="font_3 intro">三年六班李子明推荐</span>#}
{# </div>#}
{# </div>#}
{# <div class="flex-row items-center group">#}
{# <span class="font_2 price">¥4.66</span>#}
{# </div>#}
{# </div>#}
{# <!-- 商品 3 开始 -->#}
{# <div class="flex-row items-center list-item section_3 space-x-58">#}
{# <div class="flex-row items-center flex-auto space-x-36">#}
{# <img class="shrink-0 item_img" src="../static/img/item3.png"/>#}
{# <div class="flex-col items-start flex-auto space-y-20">#}
{# <span class="font_1 prodName">牛奶糖</span>#}
{# <span class="font_3 intro">奶香浓郁,回味无穷</span>#}
{# </div>#}
{# </div>#}
{# <div class="flex-row items-center group">#}
{# <span class="font_2 price">¥3.80</span>#}
{# </div>#}
{# </div>#}
{# <!-- 商品 4 开始 -->#}
{# <div class="flex-row items-center list-item section_3 space-x-58">#}
{# <div class="flex-row items-center flex-auto space-x-36">#}
{# <img class="shrink-0 item_img" src="../static/img/item4.png"/>#}
{# <div class="flex-col items-start flex-auto space-y-20">#}
{# <span class="font_1 prodName">卫龙魔芋爽</span>#}
{# <span class="font_3 intro">爽滑轻弹,好吃不贵</span>#}
{# </div>#}
{# </div>#}
{# <div class="flex-row items-center group">#}
{# <span class="font_2 price">¥0.50</span>#}
{# </div>#}
{# </div>#}
{# <!-- 商品 4 结束 -->#}
</div>
</div>
<div class="product">
<img src="../static/img/product1.jpg" alt="Product Image" class="ProductImage">
<h3 class="ProductName">旺仔小馒头</h3>
<p class="ProductInfo">好吃爱吃</p>
<p class="price">¥4.50</p>
</div>
<div class="product">
<img src="../static/img/product1.jpg" alt="Product Image" class="ProductImage">
<h3 class="ProductName">旺仔小馒头</h3>
<p class="ProductInfo">好吃爱吃</p>
<p class="price">¥4.50</p>
</div>
<div class="container">
<div class="content">
<!-- 页面内容 -->
</div>
<div>
<button class="proceed">确认支付</button>
</div>
<div class="flex-col items-center section_4">
<div class="flex-col justify-start items-center text-wrapper_3">
<span class="font_2 sumPrice" id="totalPrice">¥0.00</span>
</div>
<button class="flex-col justify-start items-center text-wrapper_4 view_2 button">确认支付</button>
</div>
</body>
</html>
</div>
</body>
</html>
<script>
// 计算并更新合计价格
function calculateTotalPrice() {
// 获取商品价格元素
var priceElements = document.getElementsByClassName("price");
var totalPrice = 0;
// 遍历所有价格元素,累加价格
for (var i = 0; i < priceElements.length; i++) {
var priceText = priceElements[i].innerText;
var price = parseFloat(priceText.substring(1)); // 去掉价格前面的人民币符号,并转换为浮点数
totalPrice += price;
}
// 更新合计价格元素
var totalPriceElement = document.getElementById("totalPrice");
totalPriceElement.innerText = "¥" + totalPrice.toFixed(2); // 保留两位小数
// 更新购物车件数
var cartItemCountElement = document.getElementById("cartItemCount");
var cartItemCount = priceElements.length;
cartItemCountElement.innerText = "购物车(" + cartItemCount + "件商品)";
// 将商品列表滚动到底部
var listElement = document.querySelector(".list");
listElement.scrollTop = listElement.scrollHeight;
// 如果需要,可以在这里执行其他操作,比如根据 totalPrice 的值做一些判断或其他计算
}
// 使用 MutationObserver 监听 DOM 变化
var observer = new MutationObserver(function () {
calculateTotalPrice();
});
// 监听购物车列表的变化
var listElement = document.querySelector(".list");
observer.observe(listElement, {childList: true, subtree: true});
// 初始化计算合计价格
calculateTotalPrice();
// 获取username参数的值
var username = new URLSearchParams(window.location.search).get("username");
// 查找具有class为username的元素
var usernameElements = document.getElementsByClassName("username");
// 遍历所有匹配的元素将其值修改为username参数的值
for (var i = 0; i < usernameElements.length; i++) {
usernameElements[i].textContent = username;
}
// 发送GET请求函数
function sendGetRequest(url, callback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
callback(xhr.responseText);
} else {
console.error('Error:', xhr.status);
}
}
};
xhr.open('GET', url, true);
xhr.send();
}
// 更新商品列表函数
function updateProductList() {
sendGetRequest('/updaterfid/', function (response) {
var data = JSON.parse(response);
var productList = data.product_list;
// 清空商品列表
var listContainer = document.querySelector('.list');
listContainer.innerHTML = '';
// 更新商品信息
productList.forEach(function (productID) {
var url = '/getProd?prodID=' + productID;
sendGetRequest(url, function (response) {
var productData = JSON.parse(response);
// 创建商品项
var listItem = document.createElement('div');
listItem.classList.add('flex-row', 'items-center', 'list-item', 'section_3', 'space-x-58');
// 创建商品图像
var itemImg = document.createElement('img');
itemImg.classList.add('shrink-0', 'item_img');
itemImg.src = '../static/img/item' + productData.prodID + '.png';
// 创建商品信息
var infoContainer = document.createElement('div');
infoContainer.classList.add('flex-col', 'items-start', 'flex-auto', 'space-y-20');
var prodName = document.createElement('span');
prodName.classList.add('font_1', 'prodName');
prodName.textContent = productData.prodName;
var intro = document.createElement('span');
intro.classList.add('font_3', 'intro');
intro.textContent = productData.intro;
infoContainer.appendChild(prodName);
infoContainer.appendChild(intro);
// 创建商品价格
var price = document.createElement('span');
price.classList.add('font_2', 'price');
price.textContent = '¥' + productData.prodPrice;
// 添加元素到商品项
listItem.appendChild(itemImg);
listItem.appendChild(infoContainer);
listItem.appendChild(price);
// 添加商品项到商品列表
listContainer.appendChild(listItem);
});
});
});
}
// 页面加载完成后执行更新商品列表
window.addEventListener('DOMContentLoaded', function () {
updateProductList();
});
// 每隔一段时间更新商品列表
setInterval(updateProductList, 8000); // 1000毫秒1秒
</script>

@ -0,0 +1,78 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>用户注册 - 无人超市</title>
<link rel="stylesheet" href="../static/css/signUp.css"/>
</head>
<body>
<div class="flex-col page space-y-26">
<div class="flex-row justify-between items-center section">
<div class="flex-row items-center space-x-24">
<img class="logo-img" src="../static/img/logo.png">
<div class="flex-col items-center space-y-16">
<span class="text">无人超市</span>
<span class="text_3">Smart Market</span>
</div>
</div>
<div class="flex-col justify-start text-wrapper"><span class="text_2">用户注册</span></div>
</div>
<div class="flex-col justify-start items-center text-wrapper_2">
<span class="font_1 text_4">注册会员,开始享受便捷的购物体验吧!</span>
</div>
<form onsubmit="return false;">
<div class="flex-col section_2">
<span class="self-center font_1 text_5">用户名 | User Name</span>
<input class="view_1 section_3 input" name="用户名" maxlength="12" type="text" value=""
placeholder="请输入用户名"/>
<span class="self-center font_1 text_6">密码 | Password</span>
<input class="view section_3 input" name="密码" maxlength="16" type="password" placeholder="请输入密码"/>
<span class="self-center font_1 text_7">确认密码 | Confirm</span>
<input class="view_1 section_3 input" name="确认密码" maxlength="16" type="password"
placeholder="请再次输入密码"/>
<button class="flex-col justify-start items-center text-wrapper_3 view_3 button" name="提交"
onclick="onClick()">提交
</button>
<a class="text_9" href="../login">返回登录</a>
</div>
</form>
<img class="footer-img" src="../static/img/7x24.png"/>
</div>
<div class="overlay">
<div class="flex-col section_2">
<img
class="self-center image_2"
src="../static/img/face-unscreen.gif"
/>
<div class="flex-col justify-start items-center text-wrapper_3">
<span class="font_1 text_5">请靠近机器,以进行人脸识别</span>
</div>
</div>
</div>
</body>
</html>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$('.overlay').hide();
function onClick() {
$('.overlay').show();
var username = document.querySelector('input[name="用户名"]').value;
var postData = {
username: username
};
$.post('/reg/', postData, function (data) {
if (data.error) {
alert('API请求失败');
} else {
$('.text_5').text('欢迎,' + postData.username);
//三秒后跳转到/cart/
setTimeout(function () {
window.location.href = "/login";
}, 3000);
}
});
}
</script>

@ -15,6 +15,10 @@
<!-- <br> -->
<p class="TextFace">请靠近识别人脸</p>
<button type="button" class="reg">注册新用户</button>
<div class="overlay">
<p class="welcome-message">Loading...</p>
</div>
</main>
<script>
//点击button后跳转到注册页面
@ -23,4 +27,25 @@
window.location.href = "/sign/";
}
</script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
// JavaScript代码显示和隐藏蒙版
$(document).ready(function () {
$('.overlay').hide(); // 隐藏蒙版
// 发送GET请求到API
$.get('/rec/', function (data) {
if (data.error) {
alert('API请求失败');
} else {
$('.overlay').show(); // 页面加载时显示蒙版
$('.welcome-message').text('欢迎,' + data.username);
//三秒后跳转到/cart/
setTimeout(function () {
window.location.href = "/cart/";
}, 3000);
}
});
});
</script>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Loading…
Cancel
Save