diff --git a/src/analyze/LSTMAna.py b/src/analyze/LSTMAna.py
new file mode 100644
index 0000000..749da41
--- /dev/null
+++ b/src/analyze/LSTMAna.py
@@ -0,0 +1,129 @@
+# 数据储存在wordle.xlsx中,数据字段:Date,Contest number,Word,Number of reported
+# results,Number in hard mode,1 try,2 tries,3 tries,4 tries,5 tries,6 tries,7 or more tries (X)
+# 其中1 try,2 tries,3 tries,4 tries,5 tries,6 tries,7 or more tries (X)为百分比数
+
+# Date格式为2022/1/7,Contest number为每天的序号,从202开始,每天增加1
+# Contest number从202开始,每天增加1,Number 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 try,2 tries,3 tries,4 tries,5 tries,6 tries,7 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)
diff --git a/src/hardware/face.py b/src/hardware/face.py
index b41b0ca..a29ddaf 100644
--- a/src/hardware/face.py
+++ b/src/hardware/face.py
@@ -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
diff --git a/src/hardware/rfid.py b/src/hardware/rfid.py
index e525a90..997f5ad 100644
--- a/src/hardware/rfid.py
+++ b/src/hardware/rfid.py
@@ -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()
\ No newline at end of file
+def readTest():
+ time.sleep(2)
+ random_id = random.randint(1, 1000000000)
+ random_value = random.randint(1, 4)
+ return random_id, str(random_value)
diff --git a/src/myapp/tests.py b/src/myapp/tests.py
index 7ce503c..4929020 100644
--- a/src/myapp/tests.py
+++ b/src/myapp/tests.py
@@ -1,3 +1,2 @@
-from django.test import TestCase
# Create your tests here.
diff --git a/src/myapp/views.py b/src/myapp/views.py
index 93bc23e..de6066f 100644
--- a/src/myapp/views.py
+++ b/src/myapp/views.py
@@ -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'})
+
diff --git a/src/smartshop_be/settings.py b/src/smartshop_be/settings.py
index 090c4b1..d1b2e57 100644
--- a/src/smartshop_be/settings.py
+++ b/src/smartshop_be/settings.py
@@ -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",
+
}
}
diff --git a/src/smartshop_be/urls.py b/src/smartshop_be/urls.py
index e9e81da..6928614 100644
--- a/src/smartshop_be/urls.py
+++ b/src/smartshop_be/urls.py
@@ -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'),
]
diff --git a/src/templates/back/base.html b/src/templates/back/base.html
index 96c432b..bf564b5 100644
--- a/src/templates/back/base.html
+++ b/src/templates/back/base.html
@@ -81,6 +81,7 @@ main {
用户管理
商品管理
订单管理
+ 销售历史情况分析
diff --git a/src/templates/back/history_analyze.html b/src/templates/back/history_analyze.html
new file mode 100644
index 0000000..c0a291e
--- /dev/null
+++ b/src/templates/back/history_analyze.html
@@ -0,0 +1,328 @@
+
+{% extends 'back/base.html' %}
+
+{% block content %}
+
+
+ 商品管理
+
+
+
+
+
+ ID |
+ 商品名 |
+ 单价(单位:分) |
+ 剩余库存 |
+ 操作 |
+
+
+
+{# {% for user_profile in user_profiles %}#}
+{# #}
+{# {{ user_profile.user.id }} | #}
+{# {{ user_profile.user.username }} | #}
+{# {{ user_profile.balance }} | #}
+{# {% if user_profile.is_vip %}是{% else %}否{% endif %} | #}
+{# {{ user_profile.face_id }} | #}
+{# #}
+{# #}
+{# #}
+{# | #}
+{#
#}
+{# {% endfor %}#}
+
+ 1 |
+ 可乐 |
+ 300 |
+ 20 |
+
+
+
+ |
+
+
+ 2 |
+ 雪碧 |
+ 300 |
+ 20 |
+
+
+
+ |
+
+
+
+
+
+
+
+
+

+

+
+
+
+

+
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/templates/front/css/logIn.css b/src/templates/front/css/logIn.css
new file mode 100644
index 0000000..8cc1623
--- /dev/null
+++ b/src/templates/front/css/logIn.css
@@ -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;
+ }
\ No newline at end of file
diff --git a/src/templates/front/css/shoppingCart.css b/src/templates/front/css/shoppingCart.css
index 19281ce..6afbe00 100755
--- a/src/templates/front/css/shoppingCart.css
+++ b/src/templates/front/css/shoppingCart.css
@@ -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;
+}
\ No newline at end of file
diff --git a/src/templates/front/css/signUp.css b/src/templates/front/css/signUp.css
new file mode 100644
index 0000000..fd82a92
--- /dev/null
+++ b/src/templates/front/css/signUp.css
@@ -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;
+ }
+
diff --git a/src/templates/front/css/userLogin.css b/src/templates/front/css/userLogin.css
index 3da4e09..1a872ba 100755
--- a/src/templates/front/css/userLogin.css
+++ b/src/templates/front/css/userLogin.css
@@ -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;
-}
\ No newline at end of file
+ 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;
+ }
\ No newline at end of file
diff --git a/src/templates/front/css/userSign.css b/src/templates/front/css/userSign.css
index ed57e05..b02fa0b 100755
--- a/src/templates/front/css/userSign.css
+++ b/src/templates/front/css/userSign.css
@@ -37,8 +37,6 @@ input{
transform: translateX(-50%);
/* 字体大小 */
font-size: 50px;
- /* 字体大小 */
- font-size: 50px;
/* 字体颜色 */
color: #7E7E7E;
/* 背景颜色 */
diff --git a/src/templates/front/html/logIn.html b/src/templates/front/html/logIn.html
new file mode 100644
index 0000000..96623c3
--- /dev/null
+++ b/src/templates/front/html/logIn.html
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+ 欢迎使用 - 无人超市
+
+
+
+
+
+
+

+
+ 无人超市
+ Smart Market
+
+
+
用户登录
+
+
+ 欢迎使用无人超市
+
+
+

+
+ 请靠近机器,以进行人脸识别
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/templates/front/html/shoppingCart.html b/src/templates/front/html/shoppingCart.html
index 77a921e..57daa36 100755
--- a/src/templates/front/html/shoppingCart.html
+++ b/src/templates/front/html/shoppingCart.html
@@ -1,50 +1,225 @@
-
+
-
- 无人超市--购物车
-
+
+
+
+ 购物车 - 无人超市
+
-
-
- 无人超市购物车
-
-
-
-
-
-

-
旺仔小馒头
-
好吃爱吃
-
¥4.50
+
+
+
+

+
+ 无人超市
+ Smart Market
+
+
+
DustinZ
+
+
+ 购物车(0件商品)
-
-
-

-
乐事薯片
-
好吃爱吃
-
¥5.50
+
+
+{# #}
+{#
#}
+{#
#}
+{#

#}
+{#
#}
+{# 旺仔小馒头#}
+{# 好吃,爱吃!#}
+{#
#}
+{#
#}
+{#
#}
+{# ¥2.33#}
+{#
#}
+{#
#}
+{# #}
+{#
#}
+{#
#}
+{#

#}
+{#
#}
+{# 旺仔牛奶#}
+{# 三年六班李子明推荐#}
+{#
#}
+{#
#}
+{#
#}
+{# ¥4.66#}
+{#
#}
+{#
#}
+{# #}
+{#
#}
+{#
#}
+{#

#}
+{#
#}
+{# 牛奶糖#}
+{# 奶香浓郁,回味无穷#}
+{#
#}
+{#
#}
+{#
#}
+{# ¥3.80#}
+{#
#}
+{#
#}
+{# #}
+{#
#}
+{#
#}
+{#

#}
+{#
#}
+{# 卫龙魔芋爽#}
+{# 爽滑轻弹,好吃不贵#}
+{#
#}
+{#
#}
+{#
#}
+{# ¥0.50#}
+{#
#}
+{#
#}
+{# #}
+
-
-

-
旺仔小馒头
-
好吃爱吃
-
¥4.50
-
-
-

-
旺仔小馒头
-
好吃爱吃
-
¥4.50
-
-
-
-
-
-
-
-
+
-
-
\ No newline at end of file
+
+
+