소스 검색

feat: web新增关于页面

SongZihuan 3 년 전
부모
커밋
a6164413f8

+ 10 - 2
app/auth/views.py

@@ -2,11 +2,11 @@ from flask import render_template, Blueprint, Flask, request, url_for, redirect,
 from wtforms import StringField, PasswordField, SubmitField
 from wtforms import StringField, PasswordField, SubmitField
 from wtforms.validators import DataRequired
 from wtforms.validators import DataRequired
 from flask_wtf import FlaskForm
 from flask_wtf import FlaskForm
-from flask_login import LoginManager, login_required, login_user, logout_user
+from flask_login import LoginManager, login_required, login_user, logout_user, current_user
 
 
 from tool.type_ import *
 from tool.type_ import *
 from sql.db import DB
 from sql.db import DB
-from .web import AuthWebsite
+from .web import AuthWebsite, WebUser
 
 
 auth = Blueprint("auth", __name__)
 auth = Blueprint("auth", __name__)
 auth_website: Optional[AuthWebsite] = None
 auth_website: Optional[AuthWebsite] = None
@@ -54,6 +54,14 @@ def logout():
     return redirect(url_for("hello.index"))
     return redirect(url_for("hello.index"))
 
 
 
 
+@auth.route("/about")
+@login_required
+def about():
+    user: WebUser = current_user
+    user.update_info()
+    return render_template("auth/about.html")
+
+
 def creat_auth_website(app_: Flask, db: DB):
 def creat_auth_website(app_: Flask, db: DB):
     global auth_website, app
     global auth_website, app
     if auth_website is None:
     if auth_website is None:

+ 63 - 1
app/auth/web.py

@@ -1,9 +1,16 @@
 from flask import Flask
 from flask import Flask
+import datetime
+
+from conf import Config
 
 
 from tool.login import create_uid
 from tool.login import create_uid
+from tool.type_ import *
+
+from core.garbage import GarbageType
+
+from sql import DBBit
 from sql.db import DB
 from sql.db import DB
 from sql.user import find_user_by_name, find_user_by_id
 from sql.user import find_user_by_name, find_user_by_id
-from tool.type_ import *
 from . import views
 from . import views
 
 
 
 
@@ -14,12 +21,36 @@ class WebUser:
             self._uid = create_uid(name, passwd)
             self._uid = create_uid(name, passwd)
         else:
         else:
             self._uid = uid
             self._uid = uid
+        self.score = "0"
+        self.reputation = "0"
+        self.rubbish = "0"
+        self.group = "NormalUser"
         self.is_anonymous = False
         self.is_anonymous = False
 
 
+    def update_info(self):
+        user = views.auth_website.get_user_by_id(self._uid)
+        if user is None:
+            return
+        if user.is_manager():
+            self.group = "ManagerUser"
+            self.score = "0"
+            self.reputation = "0"
+            self.rubbish = "0"
+        else:
+            self.group = "NormalUser"
+            res = user.get_info()
+            self.score = res.get('score', '0')
+            self.reputation = res.get('reputation', '0')
+            self.rubbish = res.get('rubbish', '0')
+
     @property
     @property
     def name(self):
     def name(self):
         return self._name
         return self._name
 
 
+    @property
+    def uid(self):
+        return self._uid[:Config.tk_show_uid_len]
+
     @property
     @property
     def is_active(self):
     def is_active(self):
         return views.auth_website.load_user_by_id(self._uid) is not None
         return views.auth_website.load_user_by_id(self._uid) is not None
@@ -31,6 +62,9 @@ class WebUser:
     def get_id(self):
     def get_id(self):
         return self._uid
         return self._uid
 
 
+    def get_garbage_list(self):
+        return views.auth_website.get_user_garbage_list(self._uid, limit=20)
+
 
 
 class AuthWebsite:
 class AuthWebsite:
     def __init__(self, app: Flask, db: DB):
     def __init__(self, app: Flask, db: DB):
@@ -49,3 +83,31 @@ class AuthWebsite:
             return None
             return None
         name = user.get_name()
         name = user.get_name()
         return WebUser(name, uid=uid)
         return WebUser(name, uid=uid)
+
+    def get_user_garbage_list(self, uid: uid_t, limit: int):
+        cur = self._db.search(columns=["UseTime", "Location", "GarbageType", "CheckResult"],
+                              table="garbage",
+                              where=f"UserID='{uid}'",
+                              limit=limit)
+        if cur is None or cur.rowcount == 0:
+            return None
+        res = []
+        for i in range(cur.rowcount):
+            re: Tuple[datetime.datetime, str, bytes, Optional[bytes]] = cur.fetchone()
+            t = re[0].strftime("%Y-%m-%d %H:%M:%S")
+            loc = re[1]
+            type_ = GarbageType.GarbageTypeStrList_ch[int(re[2])]
+            if re[3] is None:
+                result = "待确定"
+                result_class = 'wait'
+            elif re[3] == DBBit.BIT_1:
+                result = "投放正确"
+                result_class = 'pass'
+            else:
+                result = "投放错误"
+                result_class = 'fail'
+            res.append((t, loc, type_, result, result_class))
+        return res
+
+    def get_user_by_id(self, uid: uid_t):
+        return find_user_by_id(uid, self._db)

+ 1 - 1
app/index/views.py

@@ -11,7 +11,7 @@ def start():
     return render_template("hello/start.html")
     return render_template("hello/start.html")
 
 
 
 
-@hello.route('/start')
+@hello.route('/index')
 def index():
 def index():
     return render_template("hello/index.html")
     return render_template("hello/index.html")
 
 

+ 65 - 0
app/static/styles/auth/about.css

@@ -0,0 +1,65 @@
+#about {
+    display: block;
+    width: 100%;
+}
+
+#user-info {
+    position: relative;
+    float: left;
+    width: calc(39% - 3px * 2 - 10px * 2);
+    background-color: #DDDDDD;
+    padding: 10px 10px;
+
+    border-radius: 10px;
+}
+
+.user-info-item {
+    font-size: 22px;
+    line-height: 30px;
+}
+
+.user-logout-btn {
+    font-size: 18px;
+    line-height: 35px;
+    height: 35px;
+    width: 100px;
+}
+
+.user-info-value {
+    text-decoration: underline;
+}
+
+#garbage-list {
+    float: right;
+    width: 59%;
+}
+
+.garbage-list-item {
+    display: block;
+
+    width: 100%;
+    height: 35px;
+    margin-bottom: 10px;
+
+    color: #FFFFFF;
+    font-size: 20px;
+    line-height: 35px;
+    text-align: center;
+
+    border-radius: 15px;
+    border-width: 5px;
+    border-style: ridge;
+    border-color: #333333;
+}
+
+.garbage-fail {
+    background-color: #FF4136;
+}
+
+.garbage-pass {
+    background-color: #2ECC40;
+}
+
+.garbage-wait {
+    background-color: #AAAAAA;
+}

+ 0 - 0
app/static/styles/login.css → app/static/styles/auth/login.css


+ 60 - 45
app/static/styles/base.css

@@ -1,31 +1,52 @@
+/* 全局设定相关 */
 html {
 html {
     font-size: 15px;
     font-size: 15px;
     font-family: 'Noto Sans SC', sans-serif;
     font-family: 'Noto Sans SC', sans-serif;
 }
 }
 
 
-section.top-nav {
-    position: fixed;
+body {
+    overflow-y: scroll; /* 总是显示滚动条 */
+}
+
+/* 顶菜单栏 */
+section.nav-top {
+    position: fixed; /* 固定布局 */
     top: 0;
     top: 0;
     left: 0;
     left: 0;
+
     width: 100%;
     width: 100%;
-    height: 80px;
+
     vertical-align: center;
     vertical-align: center;
-    background-color: rgba(240, 128, 128, 90%);
+    background-color: rgba(240, 128, 128, 90%); /* 带一点透明效果 */
     z-index: 10;
     z-index: 10;
 }
 }
 
 
-ul.top-nav {
-    display: inline-block;
-    position: absolute;
-    left: 50%;
-    transform: translateX(-50%);
+#nav-title {
+    display: block;
+    float: left;
+
+    font-size: 25px;
+    line-height: 80px;
+    font-weight: bold;
+    margin-left: 10px;
 }
 }
 
 
-li.top-nav-item {
+#nav-title, #nav-title:hover, #nav-title:active, #nav-title:link, #nav-title:visited {
+    text-decoration: underline;
+    color: #FFFFFF;
+}
+
+ul.nav-top {
+    display: block;
+    float: right;
+    margin-right: 10px;
+}
+
+li.nav-top-item {
     display: inline-block;
     display: inline-block;
 }
 }
 
 
-a.top-nav-item {
+a.nav-top-item {
     display: inline-block;
     display: inline-block;
     padding-left: 20px;
     padding-left: 20px;
     padding-right: 20px;
     padding-right: 20px;
@@ -35,22 +56,23 @@ a.top-nav-item {
     line-height: 80px;
     line-height: 80px;
 }
 }
 
 
-a.top-nav-item, a.top-nav-item:hover, a.top-nav-item:active, a.top-nav-item:link, a.top-nav-item:visited {
+a.nav-top-item, a.nav-top-item:hover, a.nav-top-item:active, a.nav-top-item:link, a.nav-top-item:visited {
     text-decoration: none;
     text-decoration: none;
     color: #FFFFFF;
     color: #FFFFFF;
 }
 }
 
 
-a.top-nav-item:hover, a.top-nav-item:active {
+a.nav-top-item:hover, a.nav-top-item:active {
     text-decoration: none;
     text-decoration: none;
     color: #800080;
     color: #800080;
 }
 }
 
 
+
 #start-p {
 #start-p {
     margin-top: 8%;
     margin-top: 8%;
 }
 }
 
 
-
-.top-flash-message {
+/* 闪现消息 */
+.top-msg {
     display: block;
     display: block;
     width: 60%;
     width: 60%;
     text-align: center;
     text-align: center;
@@ -64,22 +86,25 @@ a.top-nav-item:hover, a.top-nav-item:active {
     margin: 5px auto;
     margin: 5px auto;
 }
 }
 
 
-#top-title {
-    display: inline-block;
-    font-size: 25px;
-    position: relative;
-    left: 3%;
-    line-height: 80px;
-    height: 100%;
-    font-weight: bold;
+/* 内容 */
+@media all and (max-width: 992px) {
+    /* 小屏幕(手机) */
+    #main {
+        position: relative;
+        left: 3%;
+        width: 94%;
+    }
 }
 }
 
 
-#top-title, #top-title:hover, #top-title:active, #top-title:link, #top-title:visited {
-    text-decoration: underline;
-    color: #FFFFFF;
+@media not all and (max-width: 992px) {
+    #main {
+        position: relative;
+        left: 25%;
+        width: 50%;
+    }
 }
 }
 
 
-#bottom-nav {
+#nav-bottom {
     position: fixed;
     position: fixed;
     top: 95%;
     top: 95%;
     background-color: black;
     background-color: black;
@@ -91,18 +116,18 @@ a.top-nav-item:hover, a.top-nav-item:active {
 
 
 @media all and (max-width: 992px) {
 @media all and (max-width: 992px) {
     /* 小屏幕(手机) */
     /* 小屏幕(手机) */
-    #bottom-nav {
+    #nav-bottom {
         height: 8%;
         height: 8%;
     }
     }
 }
 }
 
 
 @media not all and (max-width: 992px) {
 @media not all and (max-width: 992px) {
-    #bottom-nav {
+    #nav-bottom {
         height: 5%;
         height: 5%;
     }
     }
 }
 }
 
 
-.bottom-nav-item {
+.nav-bottom-item {
     display: block;
     display: block;
     font-size: 15px;
     font-size: 15px;
     color: #FFFFFF;
     color: #FFFFFF;
@@ -122,19 +147,9 @@ a.top-nav-item:hover, a.top-nav-item:active {
     margin-top: 5%;
     margin-top: 5%;
 }
 }
 
 
-@media all and (max-width: 992px) {
-    /* 小屏幕(手机) */
-    #main {
-        position: relative;
-        left: 3%;
-        width: 94%;
-    }
+/* 用于解决父元素高度坍塌 */
+.clearfix::after {
+    display: block;
+    content: "";
+    clear: both;
 }
 }
-
-@media not all and (max-width: 992px) {
-    #main {
-        position: relative;
-        left: 30%;
-        width: 40%;
-    }
-}

+ 0 - 0
app/static/styles/start.css → app/static/styles/hello/index.css


+ 1 - 1
app/static/styles/index.css → app/static/styles/hello/start.css

@@ -1,5 +1,5 @@
 body {
 body {
-    background-image: url("../images/starry-sky.jpg");
+    background-image: url("../../images/starry-sky.jpg");
 }
 }
 
 
 #base {
 #base {

+ 1 - 0
app/static/styles/ranking.css → app/static/styles/rank/ranking.css

@@ -17,6 +17,7 @@ li#ranking-item-3 {
 }
 }
 
 
 li.ranking-item {
 li.ranking-item {
+    display: block;
     border-width: 2px;
     border-width: 2px;
     border-style: ridge;
     border-style: ridge;
     border-color: #F08080;
     border-color: #F08080;

+ 42 - 0
app/templates/auth/about.html

@@ -0,0 +1,42 @@
+{% extends "base.html" %}
+{% import "auth/about_macro.html" as about %}
+
+{% block style %}
+    {{ super() }}
+    <link href="{{ url_for('static', filename='styles/auth/about.css') }}" rel="stylesheet">
+{% endblock %}
+
+{% block title %} 关于 {% endblock %}
+{% block h1_title %} 你好, {{ current_user.name }}! {% endblock %}
+
+{% block content %}
+    <section id="about" class="clearfix">
+        <section id="user-info">
+            <p class="user-info-item"> 用户名: <span class="user-info-value"> {{ current_user.name }} </span></p>
+            <br>
+
+            <p class="user-info-item"> 用户ID: <span class="user-info-value"> {{ current_user.uid }} </span></p>
+            <br>
+
+            <p class="user-info-item"> 用户组: <span class="user-info-value"> {{ current_user.group }} </span></p>
+            <br>
+
+            <p class="user-info-item"> 目前积分: <span class="user-info-value"> {{ current_user.score }} </span></p>
+            <br>
+
+            <p class="user-info-item"> 垃圾分类信用: <span class="user-info-value"> {{ current_user.reputation }} </span></p>
+            <br>
+
+            <p class="user-info-item"> 最近7天垃圾量: <span class="user-info-value"> {{ current_user.rubbish }} </span></p>
+
+            <br>
+            <form method="get" action="{{ url_for("auth.logout") }}">
+                <input type="submit" class="user-logout-btn" value="退出登录">
+            </form>
+            <br>
+        </section>
+        <ul id="garbage-list">
+            {{ about.get_garbage_list(current_user.get_garbage_list()) }}
+        </ul>
+    </section>
+{% endblock %}

+ 10 - 0
app/templates/auth/about_macro.html

@@ -0,0 +1,10 @@
+{% macro get_garbage_list(info_lines) %}
+    {% if info_lines %}
+        {% for line in info_lines %}
+            <li class="garbage-list-item garbage-{{ line[4] }}">{{ line[0] }} {{ line[1] }}
+                <span> {{ line[2] }} </span> <span> {{ line[3] }} </span></li>
+        {% endfor %}
+    {% else %}
+        <li class="garbage-list-item garbage-wait"> 没有记录</li>
+    {% endif %}
+{% endmacro %}

+ 1 - 1
app/templates/auth/login.html

@@ -2,7 +2,7 @@
 
 
 {% block style %}
 {% block style %}
     {{ super() }}
     {{ super() }}
-    <link href="{{ url_for('static', filename='styles/login.css') }}" rel="stylesheet">
+    <link href="{{ url_for('static', filename='styles/auth/login.css') }}" rel="stylesheet">
 {% endblock %}
 {% endblock %}
 
 
 {% block title %} 用户登录 {% endblock %}
 {% block title %} 用户登录 {% endblock %}

+ 16 - 17
app/templates/base.html

@@ -23,7 +23,6 @@
     {% block style %}
     {% block style %}
         <link href="{{ url_for('static', filename='styles/reset.css') }}" rel="stylesheet">
         <link href="{{ url_for('static', filename='styles/reset.css') }}" rel="stylesheet">
         <link href="{{ url_for('static', filename='styles/base.css') }}" rel="stylesheet">
         <link href="{{ url_for('static', filename='styles/base.css') }}" rel="stylesheet">
-        <link href="{{ url_for('static', filename='styles/ranking.css') }}" rel="stylesheet">
     {% endblock %}
     {% endblock %}
 
 
     {% block head %} {% endblock %}
     {% block head %} {% endblock %}
@@ -35,20 +34,20 @@
 <body>
 <body>
 
 
 {% block nav %}
 {% block nav %}
-    <section class="top-nav">
-        <p id="top-title"> HGSSystem-{{ loc }} 在线 </p>
-        <ul class="top-nav">
-            <li class="top-nav-item"><a class="top-nav-item" href="{{ url_for('hello.index') }}"> 首页 </a></li>
-            <li class="top-nav-item"><a class="top-nav-item" href="{{ url_for('rank.rank_up', page=1) }}"> 高分榜 </a></li>
-            <li class="top-nav-item"><a class="top-nav-item" href="{{ url_for('rank.rank_down', page=1) }}"> 警告榜 </a>
+    <section class="nav-top">
+        <p id="nav-title"> HGSSystem-{{ loc }} 在线 </p>
+        <ul class="nav-top">
+            <li class="nav-top-item"><a class="nav-top-item" href="{{ url_for('hello.index') }}"> 首页 </a></li>
+            <li class="nav-top-item"><a class="nav-top-item" href="{{ url_for('rank.rank_up', page=1) }}"> 高分榜 </a></li>
+            <li class="nav-top-item"><a class="nav-top-item" href="{{ url_for('rank.rank_down', page=1) }}"> 警告榜 </a>
             </li>
             </li>
-            <li class="top-nav-item"><a class="top-nav-item"> 积分商城 </a></li>
-            <li class="top-nav-item"><a class="top-nav-item"> 新闻 </a></li>
+            <li class="nav-top-item"><a class="nav-top-item"> 积分商城 </a></li>
+            <li class="nav-top-item"><a class="nav-top-item"> 新闻 </a></li>
             {% if current_user.is_authenticated %}
             {% if current_user.is_authenticated %}
-                <li class="top-nav-item"><a class="top-nav-item" href="{{ url_for('auth.logout') }}">
-                    退出: {{ current_user.name }} </a></li>
+                <li class="nav-top-item"><a class="nav-top-item" href="{{ url_for('auth.about') }}">
+                    关于: {{ current_user.name }} </a></li>
             {% else %}
             {% else %}
-                <li class="top-nav-item"><a class="top-nav-item" href="{{ url_for('auth.login') }}"> 登录 </a></li>
+                <li class="nav-top-item"><a class="nav-top-item" href="{{ url_for('auth.login') }}"> 登录 </a></li>
             {% endif %}
             {% endif %}
         </ul>
         </ul>
     </section>
     </section>
@@ -58,15 +57,15 @@
 
 
 <article>
 <article>
     {% block flash %}
     {% block flash %}
-        <section class="top-flash">
+        <section class="top-msg-section">
             {% for message in get_flashed_messages() %}
             {% for message in get_flashed_messages() %}
-                <p class="top-flash-message"> {{ message }} </p>
+                <p class="top-msg"> {{ message }} </p>
             {% endfor %}
             {% endfor %}
             <script>
             <script>
                 console.log("doneA")
                 console.log("doneA")
                 setTimeout(function () {
                 setTimeout(function () {
                     console.log("doneB")
                     console.log("doneB")
-                    let p_flash = document.querySelectorAll("p.top-flash-message");
+                    let p_flash = document.querySelectorAll("p.top-msg");
                     for (let i = 0; i < p_flash.length; i += 1) {
                     for (let i = 0; i < p_flash.length; i += 1) {
                         p_flash[i].style.display = 'none';
                         p_flash[i].style.display = 'none';
                         console.log("doneC")
                         console.log("doneC")
@@ -91,8 +90,8 @@
 
 
 <p id="last-p"></p>  <!-- 占位作用 -->
 <p id="last-p"></p>  <!-- 占位作用 -->
 {% block bnav %}
 {% block bnav %}
-    <footer id="bottom-nav">
-        <p class="bottom-nav-item"> 版权归属 (c) {{ copy_right }}<br>在
+    <footer id="nav-bottom">
+        <p class="nav-bottom-item"> 版权归属 (c) {{ copy_right }}<br>在
             <a id="github-link" href="{{ github_link }}">Github</a>上查看</p>
             <a id="github-link" href="{{ github_link }}">Github</a>上查看</p>
     </footer>
     </footer>
 {% endblock %}
 {% endblock %}

+ 1 - 1
app/templates/hello/index.html

@@ -5,7 +5,7 @@
 
 
 {% block style %}
 {% block style %}
     {{ super() }}
     {{ super() }}
-    <link href="{{ url_for('static', filename='styles/start.css') }}" rel="stylesheet">
+    <link href="{{ url_for('static', filename='styles/hello/index.css') }}" rel="stylesheet">
 {% endblock %}
 {% endblock %}
 
 
 {% block content %}
 {% block content %}

+ 35 - 20
app/templates/hello/start.html

@@ -1,24 +1,39 @@
-{% extends "base.html" %}
+<!DOCTYPE html>
+<html lang="ch">
+<head>
+    <meta charset="UTF-8">
 
 
-{% block title %} Hello-HGSSystem {% endblock %}
+    <!-- 针对移动端的优化 width为设备大小, user-scalable不允许用户缩放 initial-scale首次加载缩放大小为1.0 -->
+    <meta name="viewport"
+          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
 
 
-{% block style %}
-    {{ super() }}
-    <link href="{{ url_for('static', filename='styles/index.css') }}" rel="stylesheet">
-{% endblock %}
+    <!--  针对ie的设置  -->
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
 
 
-{# 去除默认的内容 #}
-{% block flash %} {% endblock %}
-{% block nav %} {% endblock %}
-{% block bnav %} {% endblock %}
-{% block h1_title_ %} {% endblock %}
+    <!-- Google Font 字体设置 -->
+    <link rel="preconnect" href="https://fonts.googleapis.com">
+    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@100;300&display=swap" rel="stylesheet">
 
 
-{% block content_ %}
-    <section id="base">
-        <h1 id="title-1"> 欢迎,HGSSystem在线系统 </h1>
-        <h2 id="title-2"> {{ loc }} 站 </h2>
-        <form method="get" action="{{ url_for('hello.index') }}">
-            <input id="btn" type="submit" value="开始">
-        </form>
-    </section>
-{% endblock %}
+    <link href="{{ url_for('static', filename='styles/reset.css') }}" rel="stylesheet">
+    <link href="{{ url_for('static', filename='styles/hello/start.css') }}" rel="stylesheet">
+    <style>
+        body {
+        <!-- 不显示滚动条 --> overflow-y: hidden;
+            overflow-x: hidden;
+        }
+    </style>
+
+    <link rel="icon" href="{{ url_for('static', filename='images/favicon.ico') }}">
+    <title> Hello-HGSSystem </title>
+</head>
+
+<body>
+<h1 id="title-1"> 欢迎,HGSSystem在线系统 </h1>
+<h2 id="title-2"> Guangdong-KZ 站 </h2>
+<form method="get" action=" {{ url_for('hello.index') }} ">
+    <input id="btn" type="submit" value="开始">
+</form>
+
+</body>
+</html>

+ 1 - 1
app/templates/rank/ranking.html

@@ -3,7 +3,7 @@
 
 
 {% block style %}
 {% block style %}
     {{ super() }}
     {{ super() }}
-    <link href="{{ url_for('static', filename='styles/ranking.css') }}" rel="stylesheet">
+    <link href="{{ url_for('static', filename='styles/rank/ranking.css') }}" rel="stylesheet">
 {% endblock %}
 {% endblock %}
 
 
 {% block title %} {{ ranking_name }} {% endblock %}
 {% block title %} {{ ranking_name }} {% endblock %}