Compare commits

...

18 Commits

Author SHA1 Message Date
d514e82e9b Merge branch 'main' of https://git.yum2.cc/luff/inventory_check 2025-03-17 16:32:41 +08:00
0c602a8ccd 更新 inventory_check/views.py 2025-03-17 16:30:43 +08:00
559af65260 更新 inventory_check/views.py 2025-02-27 08:50:46 +00:00
7e5eaa82e3 1.0.0 final 2025-02-26 17:24:55 +08:00
b1c336e43c ok 2025-02-26 17:21:03 +08:00
1f2c23c157 Merge branch 'main' of https://git.yum2.cc/luff/inventory_check 2025-02-26 17:13:47 +08:00
b88b78a946 Merge branch 'main' of https://git.yum2.cc/luff/inventory_check 2025-02-26 17:13:40 +08:00
d0faf8b8b2 Merge branch 'main' of https://git.yum2.cc/luff/inventory_check 2025-02-26 17:11:32 +08:00
d663087c41 Merge branch 'main' of https://git.yum2.cc/luff/inventory_check 2025-02-26 17:11:24 +08:00
6d01222ce4 Merge branch 'main' of https://git.yum2.cc/luff/inventory_check 2025-02-26 17:07:46 +08:00
d2965c64e1 Merge branch 'main' of https://git.yum2.cc/luff/inventory_check 2025-02-26 17:07:18 +08:00
232c7da723 Merge branch 'main' of https://git.yum2.cc/luff/inventory_check 2025-02-26 16:47:33 +08:00
446210ea4c response js_code 2025-02-26 16:47:22 +08:00
cf301559de response js_code 2025-02-26 16:37:17 +08:00
78d13ece36 上传文件至 inventory_check/static 2025-02-26 05:13:20 +00:00
57ade9911d simplify 2025-02-26 05:09:27 +00:00
330f8d3b8c Merge branch 'main' of https://git.yum2.cc/luff/inventory_check 2025-02-25 21:26:21 +08:00
4616650184 suit phone 2025-02-25 21:25:52 +08:00
15 changed files with 50 additions and 170 deletions

BIN
data.db

Binary file not shown.

BIN
data.xlsx

Binary file not shown.

View File

@@ -18,7 +18,6 @@ class Inventory(db.Model):
tag = db.Column(db.Text) tag = db.Column(db.Text)
amount = db.Column(db.Integer) amount = db.Column(db.Integer)
checked = db.Column(db.Boolean, default=False) checked = db.Column(db.Boolean, default=False)
name = db.Column(db.Text)
# mtime = db.Column(db.Date) # mtime = db.Column(db.Date)

View File

@@ -1,14 +1,17 @@
body {
background-color: azure;
}
main { main {
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
font-size: 25px; font-size: 18px;
} }
input { input {
width: 4ch; width: 4ch;
text-align: center; text-align: center;
} }
hr { hr {
width: 450px; width: 350px;
height: 3px; height: 3px;
} }
.grail{ .grail{
@@ -20,7 +23,7 @@ hr {
align-items: center; align-items: center;
} }
.handler { .handler {
width: 450px; width: 350px;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-content: space-between; align-content: space-between;
@@ -29,8 +32,8 @@ hr {
align-items: center; align-items: center;
} }
button, input { button, input {
font-size: 25px; font-size: 18px;
} }
form { form {
width:450px; width:350px;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 894 B

View File

@@ -16,8 +16,8 @@ function checknext() {
var id = parseInt(idelement.innerText, 10); // 第二个参数10表示解析的基数这里是十进制 var id = parseInt(idelement.innerText, 10); // 第二个参数10表示解析的基数这里是十进制
var tagelement = document.getElementById("inventory-tag"); var tagelement = document.getElementById("inventory-tag");
var tag = tagelement.innerText; var tag = tagelement.innerText;
var name = "A"
var msg = document.getElementById("flash-msg"); var msg = document.getElementById("flash-msg");
var location = document.getElementById("inventory-location");
// var params = new URLSearchParams({ // var params = new URLSearchParams({
// checked: 1, // checked: 1,
// id: id, // id: id,
@@ -29,7 +29,7 @@ function checknext() {
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json'
}, },
body: JSON.stringify({id: id, amount: amount.value, name: name}) body: JSON.stringify({id: id, amount: amount.value})
}) })
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
@@ -38,35 +38,14 @@ function checknext() {
tagelement.innerText = data.tag; tagelement.innerText = data.tag;
idelement.innerText = data.id; idelement.innerText = data.id;
msg.innerText = data.checkedone + " 盘点数 " + data.checkedamount; msg.innerText = data.checkedone + " 盘点数 " + data.checkedamount;
location.innerText = data.location;
}) })
.catch(error => console.error('Error:', error)); .catch(error => console.error('Error:', error));
} }
function apiAuth() {
if (!window.h5sdk) {
alert("请在飞书客户端中打开");
return;
}
window.h5sdk.ready(() => { function backtoroot(msg="已完成,返回") {
tt.requestAccess({ alert(msg);
appID: "your_app_id", location.href="/";
scopeList: [],
success(res) {
// 将 code 发送到服务端
fetch(`/callback?code=${res.code}`)
.then(response => response.json())
.then(data => {
console.log("用户信息:", data);
// 在页面上展示用户姓名
document.getElementById("username").innerText = data.name;
});
},
fail(err) {
console.error("获取授权码失败:", err);
}
});
});
} }
apiAuth();

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>盘库助手</title>
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}" type="text/css">
</head>
<body>
<script type="text/javascript" src="{{ url_for('static', filename='js/script.js') }}"></script>
<script>
backtoroot( "{{ msg }}" );
</script>
</body>
</html>

View File

@@ -16,14 +16,13 @@
{% block content %}{% endblock %} {% block content %}{% endblock %}
<footer> <footer>
{% block footer %} {% block footer %}
<small> &copy; 2025 <a href="http://yum2.cc" title="Written by luff">luff</a> / <small> 2025 &copy; SDHLMH
</small> </small>
<!-- <p><a id="bottom" href="#" title="Go Top">&uarr;</a></p> -->
{% endblock %} {% endblock %}
</footer> </footer>
</main> </main>
<script type="text/javascript" src="{{ url_for('static', filename='js/script.js') }}"></script> <script type="text/javascript" src="{{ url_for('static', filename='js/script.js') }}"></script>
{% block scripts %}{% endblock %}
</body> </body>
</html> </html>

View File

@@ -7,7 +7,7 @@
<div> <div>
<div class="handler"> <div class="handler">
<a href="/"><button type="button">返回</button></a> <a href="/"><button type="button">返回</button></a>
<div></div><div><p id="inventory-id" hidden>{{ inventory.id }}</p></div> <div id="inventory-location"></div><div><p id="inventory-id" hidden>{{ inventory.id }}</p></div>
</div> </div>
<h1 id="inventory-tag">{{ inventory.tag }}</h1> <h1 id="inventory-tag">{{ inventory.tag }}</h1>
<hr> <hr>

View File

@@ -5,9 +5,6 @@
<form method=get action="/upload"> <form method=get action="/upload">
<input style="width:150px;" type=submit value=上传XLSX> <input style="width:150px;" type=submit value=上传XLSX>
</form> </form>
<form method=get action="/list">
<input style="width:150px;" type=submit value=显示列表>
</form>
<form method=get action="/check"> <form method=get action="/check">
<input style="width:150px;" type=submit value=继续盘点> <input style="width:150px;" type=submit value=继续盘点>
</form> </form>

View File

@@ -1,62 +0,0 @@
{% extends 'base.html' %}
{% block content %}
<div id="flash-msg">
开始盘点>>>
</div>
<div>
<div class="handler">
<a href="/"><button type="button">返回</button></a>
<div></div><div><p id="inventory-id" hidden>0</p></div>
</div>
<div class="handler">
<button onclick="previousPage()" type="button">上页</button>
<div></div>
<button onclick="nextPage()" type="button">下页</button>
</div>
<table style="width:100%">
<tr>
<th>标签</th>
<th>数量</th>
<th>已盘</th>
</tr>
<tr>
<td id="tag1">一月</td>
<td id="amount1">¥3400</td>
<td id="checked1">¥3400</td>
</tr>
<tr>
<td id="tag2">一月</td>
<td id="amount2">¥3400</td>
<td id="checked2">¥3400</td>
</tr>
<tr>
<td id="tag3">一月</td>
<td id="amount3">¥3400</td>
<td id="checked3">¥3400</td>
</tr>
<tr>
<td id="tag4">一月</td>
<td id="amount4">¥3400</td>
<td id="checked4">¥3400</td>
</tr>
<tr>
<td id="tag5">一月</td>
<td id="amount5">¥3400</td>
<td id="checked5">¥3400</td>
</tr>
<tr>
<td id="tag6">一月</td>
<td id="amount6">¥3400</td>
<td id="checked6">¥3400</td>
</tr>
</table>
<div class="handler">
<button onclick="previousPage()" type="button">上页</button>
<div></div>
<button onclick="nextPage()" type="button">下页</button>
</div>
</div>
{% endblock %}

View File

@@ -3,11 +3,13 @@
{% block content %} {% block content %}
<h1>上传Excel XLSX文件</h1> <h1>上传Excel XLSX文件</h1>
<form method=get action="/"> <div class="handler">
<input style="width:150px;" type=submit value=返回> <a href="/"><button type="button">返回</button></a>
</form> <div></div><div></div>
</div>
<hr>
<form method=post enctype=multipart/form-data action="/import"> <form method=post enctype=multipart/form-data action="/import">
<div><input style="width:300px;" type=file name=选择></div> <div><input style="width:300px;" type=file name=file></div>
<div class="handler"><div></div><input style="width:100px;"type=submit value=上传></div> <div class="handler"><div></div><input style="width:100px;"type=submit value=上传></div>
</form> </form>
<div> <div>

View File

@@ -5,8 +5,9 @@
:copyright: © 2025 luffmims <luffmims@hotmaill.com> :copyright: © 2025 luffmims <luffmims@hotmaill.com>
:license: MIT, see LICENSE for more details. :license: MIT, see LICENSE for more details.
""" """
import time
from flask import jsonify, redirect, request, url_for, render_template, send_file from flask import jsonify, redirect, request, url_for, render_template, send_file
from flask import make_response, session from flask import make_response
from io import BytesIO from io import BytesIO
from openpyxl import Workbook from openpyxl import Workbook
from inventory_check import app, db from inventory_check import app, db
@@ -17,16 +18,11 @@ from werkzeug.exceptions import BadRequest
def index(): def index():
return render_template('index.html') return render_template('index.html')
@app.route('/list')
def list():
return render_template('list.html')
@app.route('/check', methods=['GET']) @app.route('/check', methods=['GET'])
def check(): def check():
inventory = Inventory.query.filter_by(checked=False).first() inventory = Inventory.query.filter_by(checked=False).first()
print(inventory)
if not inventory: if not inventory:
return "All checked" return render_template('after.html',msg="未导入或已盘完")
return render_template('check.html',inventory=inventory) return render_template('check.html',inventory=inventory)
@app.route('/get_inventory', methods=['POST']) @app.route('/get_inventory', methods=['POST'])
@@ -36,7 +32,6 @@ def update_inventory():
data = request.get_json() data = request.get_json()
inventory_id = data['id'] inventory_id = data['id']
amount = data['amount'] amount = data['amount']
name = data['name']
if not inventory_id or not amount: if not inventory_id or not amount:
raise BadRequest('Missing inventory id or amount') raise BadRequest('Missing inventory id or amount')
@@ -47,7 +42,6 @@ def update_inventory():
raise BadRequest('Inventory not found') raise BadRequest('Inventory not found')
checkedone = inventory.tag checkedone = inventory.tag
inventory.amount = amount inventory.amount = amount
inventory.name = name
inventory.checked = True inventory.checked = True
# 提交更改 # 提交更改
@@ -63,6 +57,7 @@ def update_inventory():
return jsonify({ return jsonify({
'id': inventory.id, 'id': inventory.id,
'tag': inventory.tag, 'tag': inventory.tag,
'location': inventory.location,
'amount': inventory.amount, 'amount': inventory.amount,
'checkedone': checkedone, 'checkedone': checkedone,
'checkedamount': amount 'checkedamount': amount
@@ -94,7 +89,7 @@ def import_file():
file_path = 'data.xlsx' file_path = 'data.xlsx'
file.save(file_path) file.save(file_path)
import_from_xlsx(file_path) import_from_xlsx(file_path)
return '文件导入成功! <a href="/">返回</a>' return render_template('after.html',msg="成功")
return redirect(url_for('upload_form')) return redirect(url_for('upload_form'))
@@ -102,6 +97,7 @@ def import_file():
@app.route('/download-xlsx') @app.route('/download-xlsx')
def download_xlsx(): def download_xlsx():
filename = "PD-" + time.strftime("%Y%m%d", time.localtime()) + ".xlsx"
# 创建一个 Excel 工作簿 # 创建一个 Excel 工作簿
inventorys = Inventory.query.all() # 查询所有数据, and sort data by sort inventorys = Inventory.query.all() # 查询所有数据, and sort data by sort
# 创建一个工作簿 # 创建一个工作簿
@@ -111,65 +107,16 @@ def download_xlsx():
# 设置工作表名称 # 设置工作表名称
ws.title = "Inventory" ws.title = "Inventory"
# 设置工作表列名 # 设置工作表列名
ws.append(["sort", "location", "tag", "amount", "checked", "name"]) ws.append(["序号", "位置", "标签", "数量", "已确认"])
# 写入数据 # 写入数据
for inventory in inventorys: for inventory in inventorys:
ws.append([inventory.sort, inventory.location, inventory.tag, inventory.amount, inventory.checked, inventory.name]) ws.append([inventory.sort, inventory.location, inventory.tag, inventory.amount, inventory.checked])
output = BytesIO() output = BytesIO()
wb.save(output) wb.save(output)
output.seek(0) # 移动到字节流的开头 output.seek(0) # 移动到字节流的开头
# 设置响应头,提供下载功能 # 设置响应头,提供下载功能
response = make_response(send_file(output, mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', as_attachment=True, download_name='example.xlsx')) response = make_response(send_file(output, mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', as_attachment=True, download_name=filename))
response.headers["Content-Disposition"] = "attachment; filename=example.xlsx" response.headers["Content-Disposition"] = "attachment; filename=" + filename
return response return response
# 应用凭证信息
APP_ID = "cli_a70da4f71bf1d00c"
APP_SECRET = "4zV9xcunWUE8E4kKS4hw5e3m6pgjoduz"
# 获取 app_access_token
def get_app_access_token():
url = "https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal/"
payload = {
"app_id": APP_ID,
"app_secret": APP_SECRET
}
response = request.post(url, json=payload)
return response.json().get("app_access_token")
# 获取 user_access_token
def get_user_access_token(app_access_token, code):
url = "https://open.feishu.cn/open-apis/authen/v1/access_token"
headers = {"Authorization": f"Bearer {app_access_token}"}
payload = {"grant_type": "authorization_code", "code": code}
response = request.post(url, headers=headers, json=payload)
return response.json().get("data", {}).get("access_token")
# 获取用户信息
def get_user_info(user_access_token):
url = "https://open.feishu.cn/open-apis/authen/v1/user_info"
headers = {"Authorization": f"Bearer {user_access_token}"}
response = request.get(url, headers=headers)
return response.json().get("data")
@app.route("/callback", methods=["GET"])
def callback():
code = request.args.get("code")
if not code:
return jsonify({"error": "Missing code parameter"}), 400
# 获取 app_access_token
app_access_token = get_app_access_token()
# 获取 user_access_token
user_access_token = get_user_access_token(app_access_token, code)
# 获取用户信息
user_info = get_user_info(user_access_token)
# 存储用户信息到 session
session["user_info"] = user_info
return jsonify(user_info)

BIN
sheet.xlsx Normal file

Binary file not shown.

Binary file not shown.