From 8c530ff59932573af4395f749d75cc426f6c4c0e Mon Sep 17 00:00:00 2001 From: Viajero <2737079298@qq.com> Date: Thu, 2 Oct 2025 15:49:36 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E2=80=9C=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=BC=96=E8=BE=91=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ESConnect.py | 46 +++++++++++++++++++++ app.py | 100 +++++++++++++++++++++++++++++++++++++++++++++ templates/all.html | 22 ++++++++-- 3 files changed, 164 insertions(+), 4 deletions(-) diff --git a/ESConnect.py b/ESConnect.py index 3c93b03..f7d83db 100644 --- a/ESConnect.py +++ b/ESConnect.py @@ -40,6 +40,9 @@ def create_index_with_mapping(): else: print(f"索引 {index_name} 已存在") +def update_document(es, index_name, doc_id=None, updated_doc=None): + """更新指定ID的文档""" + es.update(index=index_name, id=doc_id, body={"doc": updated_doc}) def get_doc_id(data): @@ -122,6 +125,49 @@ def delete_by_id(doc_id): print("删除失败:", str(e)) return False +def update_by_id(doc_id, updated_data): + """ + 根据文档ID更新数据 + + 参数: + doc_id (str): 要更新的文档ID + updated_data (dict): 更新的数据内容 + + 返回: + bool: 更新成功返回True,失败返回False + """ + try: + # 执行更新操作 + es.update(index=index_name, id=doc_id, body={"doc": updated_data}) + print(f"文档 {doc_id} 更新成功") + return True + except Exception as e: + print(f"更新失败: {str(e)}") + return False + +def get_by_id(doc_id): + """ + 根据文档ID获取单个文档 + + 参数: + doc_id (str): 要获取的文档ID + + 返回: + dict or None: 成功返回文档数据,失败返回None + """ + try: + # 执行获取操作 + result = es.get(index=index_name, id=doc_id) + if result['found']: + return { + "_id": result['_id'], + **result['_source'] + } + return None + except Exception as e: + print(f"获取文档失败: {str(e)}") + return None + def search_by_any_field(keyword): """全字段模糊搜索(支持拼写错误)""" try: diff --git a/app.py b/app.py index 2d5b7f7..23ce270 100644 --- a/app.py +++ b/app.py @@ -276,6 +276,83 @@ def show_all(): return render_template('all.html', data=processed_data) +# 编辑数据页面路由 +@app.route('/edit/') +def edit_entry(doc_id): + """ + 渲染编辑页面 + + 参数: + doc_id (str): 要编辑的文档ID + + 返回: + str: 渲染后的编辑页面或错误信息 + """ + # 获取要编辑的文档数据 + document = get_by_id(doc_id) + if not document: + return "文档不存在", 404 + + # 保持原始数据格式,不进行JSON转换 + # 直接传递包含data字段的原始文档 + return render_template('edit.html', document=document) + +# 更新数据路由 +@app.route('/update/', methods=['POST']) +def update_entry(doc_id): + """ + 处理数据更新请求 + + 参数: + doc_id (str): 要更新的文档ID + + 返回: + 重定向到所有数据页面或错误信息 + """ + # 获取原文档的图片信息 + original_doc = get_by_id(doc_id) + if not original_doc: + return "文档不存在", 404 + + # 从表单中获取所有字段数据 + data_parts = [] + i = 1 + while True: + key_name = request.form.get(f'key_{i}') + field_value = request.form.get(f'field_{i}') + + if not key_name or not field_value: + break + + # 处理字段值(如果是列表格式,用|##|分隔) + if ',' in field_value: + # 如果是逗号分隔的值,转换为列表格式 + items = [item.strip() for item in field_value.split(',') if item.strip()] + if len(items) > 1: + field_value = f"[{'|##|'.join(items)}]" + + data_parts.append(f"{key_name}:{field_value}") + i += 1 + + # 验证是否有数据 + if not data_parts: + return "没有可更新的数据", 400 + + # 构建新的数据字符串 + data_value = "|###|".join(data_parts) + + # 构造更新数据 + updated_data = { + 'data': data_value, + 'image': original_doc.get('image', '') # 保持原图片 + } + + # 更新文档 + if update_by_id(doc_id, updated_data): + return redirect(url_for('show_all')) + else: + return "更新失败", 500 + # 删除数据路由 @app.route('/delete/', methods=['POST']) def delete_entry(doc_id): @@ -295,6 +372,29 @@ def delete_entry(doc_id): +# 提供图片访问的路由 +@app.route('/image/') +def serve_image(filename): + """ + 提供image目录下图片的访问服务 + + 参数: + filename (str): 图片文件名 + + 返回: + 图片文件或404错误 + """ + import os + from flask import send_from_directory + + # 确保文件存在 + image_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'image') + if not os.path.exists(os.path.join(image_dir, filename)): + return "图片不存在", 404 + + # 发送图片文件 + return send_from_directory(image_dir, filename) + # 主程序入口 if __name__ == '__main__': # 创建Elasticsearch索引 diff --git a/templates/all.html b/templates/all.html index 1624534..06a4d28 100644 --- a/templates/all.html +++ b/templates/all.html @@ -81,6 +81,17 @@ cursor: pointer; font-weight: 500; transition: all 0.3s; + margin: 0 2px; + } + + .edit-btn { + background: linear-gradient(to right, #4CAF50, #45a049); + color: white; + } + + .edit-btn:hover { + transform: translateY(-2px); + box-shadow: 0 4px 8px rgba(76, 175, 80, 0.3); } .delete-btn { @@ -122,7 +133,7 @@

所有已录入的奖项信息

-

在此页面可以查看所有已录入的成果信息,并进行删除操作

+

在此页面可以查看所有已录入的成果信息,并进行编辑和删除操作

@@ -144,9 +155,12 @@ {% endfor %} From 5a6f7990590adc1672cb67b403463e18c965dc88 Mon Sep 17 00:00:00 2001 From: Viajero <2737079298@qq.com> Date: Mon, 6 Oct 2025 22:04:48 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E2=80=9C=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=BC=96=E8=BE=91=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- templates/edit.html | 256 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 templates/edit.html diff --git a/templates/edit.html b/templates/edit.html new file mode 100644 index 0000000..b8e6c00 --- /dev/null +++ b/templates/edit.html @@ -0,0 +1,256 @@ +{% extends "base.html" %} + +{% block title %}编辑数据 - 紫金·稷下薪火·云枢智海师生成果共创系统{% endblock %} + +{% block content %} + + +
+

编辑成果信息

+ +
+
+ {% if document.data %} + {# 从原始数据中解析字段 #} + {% set data_string = document.data %} + {% set pairs = data_string.split('|###|') %} + + {% for pair in pairs %} + {% if ':' in pair %} + {% set key_value = pair.split(':', 1) %} + {% set field_key = key_value[0].strip() %} + {% set field_value = key_value[1].strip() %} + + {# 处理列表格式 [item1|##|item2] #} + {% if field_value.startswith('[') and field_value.endswith(']') %} + {% set list_content = field_value[1:-1] %} + {% set field_value = list_content.split('|##|')|join(', ') %} + {% endif %} + +
+ + + +
+ {% endif %} + {% endfor %} + {% else %} + {# 如果没有data字段,显示提示信息 #} +
+

该记录没有可编辑的数据

+
+ {% endif %} + + {% if document.image %} +
+ +
+ 原图片 +
+
当前关联的图片,编辑时无法修改图片
+
+ {% endif %} + +
+ + 取消返回 + +
+ +
+
+ + +{% endblock %} \ No newline at end of file From 263b39614274457786f0c415c10d5d95210e79ba Mon Sep 17 00:00:00 2001 From: Viajero <2737079298@qq.com> Date: Tue, 14 Oct 2025 14:26:36 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E2=80=9C=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=BC=96=E8=BE=91=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/app.py b/app.py index 0510ee9..23ce270 100644 --- a/app.py +++ b/app.py @@ -281,10 +281,10 @@ def show_all(): def edit_entry(doc_id): """ 渲染编辑页面 - + 参数: doc_id (str): 要编辑的文档ID - + 返回: str: 渲染后的编辑页面或错误信息 """ @@ -292,7 +292,7 @@ def edit_entry(doc_id): document = get_by_id(doc_id) if not document: return "文档不存在", 404 - + # 保持原始数据格式,不进行JSON转换 # 直接传递包含data字段的原始文档 return render_template('edit.html', document=document) @@ -302,10 +302,10 @@ def edit_entry(doc_id): def update_entry(doc_id): """ 处理数据更新请求 - + 参数: doc_id (str): 要更新的文档ID - + 返回: 重定向到所有数据页面或错误信息 """ @@ -313,40 +313,40 @@ def update_entry(doc_id): original_doc = get_by_id(doc_id) if not original_doc: return "文档不存在", 404 - + # 从表单中获取所有字段数据 data_parts = [] i = 1 while True: key_name = request.form.get(f'key_{i}') field_value = request.form.get(f'field_{i}') - + if not key_name or not field_value: break - + # 处理字段值(如果是列表格式,用|##|分隔) if ',' in field_value: # 如果是逗号分隔的值,转换为列表格式 items = [item.strip() for item in field_value.split(',') if item.strip()] if len(items) > 1: field_value = f"[{'|##|'.join(items)}]" - + data_parts.append(f"{key_name}:{field_value}") i += 1 - + # 验证是否有数据 if not data_parts: return "没有可更新的数据", 400 - + # 构建新的数据字符串 data_value = "|###|".join(data_parts) - + # 构造更新数据 updated_data = { 'data': data_value, 'image': original_doc.get('image', '') # 保持原图片 } - + # 更新文档 if update_by_id(doc_id, updated_data): return redirect(url_for('show_all')) @@ -377,21 +377,21 @@ def delete_entry(doc_id): def serve_image(filename): """ 提供image目录下图片的访问服务 - + 参数: filename (str): 图片文件名 - + 返回: 图片文件或404错误 """ import os from flask import send_from_directory - + # 确保文件存在 image_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'image') if not os.path.exists(os.path.join(image_dir, filename)): return "图片不存在", 404 - + # 发送图片文件 return send_from_directory(image_dir, filename) From 81f1eae2d5be4e575e8db2da8916b1ea281d5d24 Mon Sep 17 00:00:00 2001 From: Viajero <2737079298@qq.com> Date: Tue, 14 Oct 2025 15:01:14 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E2=80=9C=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=BC=96=E8=BE=91=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 23 ++++ templates/all.html | 307 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 264 insertions(+), 66 deletions(-) diff --git a/app.py b/app.py index 23ce270..19fd0d6 100644 --- a/app.py +++ b/app.py @@ -370,6 +370,29 @@ def delete_entry(doc_id): else: return "删除失败", 500 +# 批量删除数据路由 +@app.route('/batch_delete', methods=['POST']) +def batch_delete(): + """ + 批量删除数据 + + 返回: + 重定向到所有数据页面或错误信息 + """ + doc_ids = request.form.getlist('doc_ids') + if not doc_ids: + return "没有选择要删除的文档", 400 + + success_count = 0 + for doc_id in doc_ids: + if delete_by_id(doc_id): + success_count += 1 + + if success_count == len(doc_ids): + return redirect(url_for('show_all')) + else: + return f"成功删除 {success_count} 条记录,失败 {len(doc_ids) - success_count} 条", 500 + # 提供图片访问的路由 diff --git a/templates/all.html b/templates/all.html index 06a4d28..514e9b5 100644 --- a/templates/all.html +++ b/templates/all.html @@ -27,50 +27,87 @@ margin-bottom: 15px; } - /* 表格容器 - 顶部边距调整 */ - .table-container { - overflow-x: auto; - margin-top: 15px; /* 减少顶部间距 */ + /* 卡片容器样式 */ + .data-cards { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(400px, 1fr)); + gap: 20px; + margin-bottom: 20px; + } + + /* 卡片样式 */ + .data-card { + background-color: white; border-radius: 8px; - box-shadow: 0 4px 6px rgba(0,0,0,0.1); + box-shadow: 0 2px 8px rgba(0,0,0,0.1); + padding: 20px; + border: 1px solid #e0e0e0; + transition: transform 0.3s, box-shadow 0.3s; } - /* 表格样式 */ - table { - width: 100%; - border-collapse: collapse; - font-family: 'Segoe UI', Arial, sans-serif; + .data-card:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0,0,0,0.15); } - /* 表头样式 */ - thead { - background: linear-gradient(135deg, #3498db, #1a5276); - color: white; + /* 卡片头部样式 */ + .card-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 15px; + padding-bottom: 15px; + border-bottom: 1px solid #f0f0f0; } - th { - padding: 16px 12px; - text-align: left; + .card-header h3 { + margin: 0; + color: #333; + font-size: 18px; + } + + .card-actions { + display: flex; + gap: 8px; + } + + /* 卡片内容样式 */ + .card-content { + margin-bottom: 15px; + } + + .field-item { + display: flex; + margin-bottom: 10px; + line-height: 1.5; + } + + .field-key { font-weight: 600; + color: #333; + min-width: 120px; + margin-right: 10px; } - /* 表格行样式 */ - tbody tr { - border-bottom: 1px solid #eef1f5; - transition: background-color 0.3s; + .field-value { + color: #666; + flex: 1; + word-break: break-word; } - tbody tr:nth-child(even) { - background-color: #f8fafc; + /* 卡片图片样式 */ + .card-image { + text-align: center; + margin-top: 15px; + padding-top: 15px; + border-top: 1px solid #f0f0f0; } - tbody tr:hover { - background-color: #e3f2fd; - } - - td { - padding: 14px 12px; - color: #4a5568; + .card-image img { + max-width: 100%; + max-height: 200px; + border-radius: 4px; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); } /* 操作按钮样式 */ @@ -128,6 +165,33 @@ padding: 40px 0; color: #a0aec0; font-style: italic; + grid-column: 1 / -1; + } + + /* 响应式设计 */ + @media (max-width: 768px) { + .data-cards { + grid-template-columns: 1fr; + } + + .card-header { + flex-direction: column; + align-items: flex-start; + gap: 10px; + } + + .card-actions { + align-self: flex-end; + } + + .field-item { + flex-direction: column; + } + + .field-key { + min-width: auto; + margin-bottom: 5px; + } } @@ -135,44 +199,155 @@

所有已录入的奖项信息

在此页面可以查看所有已录入的成果信息,并进行编辑和删除操作

-
-
{% if item.students is string %}{{ item.students or '无' }}{% else %}{{ item.students|join(', ') if item.students else '无' }}{% endif %} {% if item.teacher is string %}{{ item.teacher or '无' }}{% else %}{{ item.teacher|join(', ') if item.teacher else '无' }}{% endif %} -
- -
+
+ 编辑 +
+ +
+
- - - - - - - - - - - {% if data %} - {% for item in data %} - - - - - - - - {% endfor %} - {% else %} - - - - {% endif %} - -
比赛/论文名称项目名称学生指导老师操作
{{ item.id or '无' }}{{ item.name or '无' }}{% if item.students is string %}{{ item.students or '无' }}{% else %}{{ item.students|join(', ') if item.students else '无' }}{% endif %}{% if item.teacher is string %}{{ item.teacher or '无' }}{% else %}{{ item.teacher|join(', ') if item.teacher else '无' }}{% endif %} -
- 编辑 -
- -
-
-
暂无数据
+ +
+
+
+ + +
+ + 已选择 0 项 +
+
+ +
+ {% if data %} + {% for item in data %} +
+
+
+ +

记录 {{ loop.index }}

+
+
+ 编辑 +
+
+ +
+ {% if item.data %} + {# 从原始数据中解析字段 #} + {% set data_string = item.data %} + {% set pairs = data_string.split('|###|') %} + + {% for pair in pairs %} + {% if ':' in pair %} + {% set key_value = pair.split(':', 1) %} + {% set field_key = key_value[0].strip() %} + {% set field_value = key_value[1].strip() %} + + {# 处理列表格式 [item1|##|item2] #} + {% if field_value.startswith('[') and field_value.endswith(']') %} + {% set list_content = field_value[1:-1] %} + {% set field_value = list_content.split('|##|')|join(', ') %} + {% endif %} + +
+ {{ field_key }}: + {{ field_value or '无' }} +
+ {% endif %} + {% endfor %} + {% else %} + {# 如果没有data字段,显示解析后的字段 #} + {% for key, value in item.items() %} + {% if key not in ['_id', 'image'] %} +
+ {{ key }}: + + {% if value is sequence and value is not string %} + {{ value|join(', ') if value else '无' }} + {% else %} + {{ value or '无' }} + {% endif %} + +
+ {% endif %} + {% endfor %} + {% endif %} +
+ + +
+ {% endfor %} + {% else %} +
暂无数据
+ {% endif %}
返回首页
+ + + {% endblock %} \ No newline at end of file From aa6b1dec3f1f1cdbd13766dad6c64845fa6e5ce0 Mon Sep 17 00:00:00 2001 From: Viajero <2737079298@qq.com> Date: Tue, 14 Oct 2025 15:35:32 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E2=80=9C=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=BC=96=E8=BE=91=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 2 +- templates/edited.html | 256 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 257 insertions(+), 1 deletion(-) create mode 100644 templates/edited.html diff --git a/app.py b/app.py index 19fd0d6..e40026c 100644 --- a/app.py +++ b/app.py @@ -295,7 +295,7 @@ def edit_entry(doc_id): # 保持原始数据格式,不进行JSON转换 # 直接传递包含data字段的原始文档 - return render_template('edit.html', document=document) + return render_template('edited.html', document=document) # 更新数据路由 @app.route('/update/', methods=['POST']) diff --git a/templates/edited.html b/templates/edited.html new file mode 100644 index 0000000..8125021 --- /dev/null +++ b/templates/edited.html @@ -0,0 +1,256 @@ +{% extends "base.html" %} + +{% block title %}编辑成果信息 - 紫金·稷下薪火·云枢智海师生成果共创系统{% endblock %} + +{% block content %} + + +
+

编辑成果信息

+ +
+
+ {% if document.data %} + {# 从原始数据中解析字段 #} + {% set data_string = document.data %} + {% set pairs = data_string.split('|###|') %} + + {% for pair in pairs %} + {% if ':' in pair %} + {% set key_value = pair.split(':', 1) %} + {% set field_key = key_value[0].strip() %} + {% set field_value = key_value[1].strip() %} + + {# 处理列表格式 [item1|##|item2] #} + {% if field_value.startswith('[') and field_value.endswith(']') %} + {% set list_content = field_value[1:-1] %} + {% set field_value = list_content.split('|##|')|join(', ') %} + {% endif %} + +
+ + + +
+ {% endif %} + {% endfor %} + {% else %} + {# 如果没有data字段,显示提示信息 #} +
+

该记录没有可编辑的数据

+
+ {% endif %} + + {% if document.image %} +
+ +
+ 原图片 +
+
当前关联的图片,编辑时无法修改图片
+
+ {% endif %} + +
+ + 取消返回 + +
+
+
+
+ + +{% endblock %} \ No newline at end of file From 9c011dfc8c08328d5f362129b954036c15227e4b Mon Sep 17 00:00:00 2001 From: Viajero <2737079298@qq.com> Date: Tue, 14 Oct 2025 15:37:22 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E2=80=9C=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=BC=96=E8=BE=91=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- templates/edit.html | 256 -------------------------------------------- 1 file changed, 256 deletions(-) delete mode 100644 templates/edit.html diff --git a/templates/edit.html b/templates/edit.html deleted file mode 100644 index b8e6c00..0000000 --- a/templates/edit.html +++ /dev/null @@ -1,256 +0,0 @@ -{% extends "base.html" %} - -{% block title %}编辑数据 - 紫金·稷下薪火·云枢智海师生成果共创系统{% endblock %} - -{% block content %} - - -
-

编辑成果信息

- -
-
- {% if document.data %} - {# 从原始数据中解析字段 #} - {% set data_string = document.data %} - {% set pairs = data_string.split('|###|') %} - - {% for pair in pairs %} - {% if ':' in pair %} - {% set key_value = pair.split(':', 1) %} - {% set field_key = key_value[0].strip() %} - {% set field_value = key_value[1].strip() %} - - {# 处理列表格式 [item1|##|item2] #} - {% if field_value.startswith('[') and field_value.endswith(']') %} - {% set list_content = field_value[1:-1] %} - {% set field_value = list_content.split('|##|')|join(', ') %} - {% endif %} - -
- - - -
- {% endif %} - {% endfor %} - {% else %} - {# 如果没有data字段,显示提示信息 #} -
-

该记录没有可编辑的数据

-
- {% endif %} - - {% if document.image %} -
- -
- 原图片 -
-
当前关联的图片,编辑时无法修改图片
-
- {% endif %} - -
- - 取消返回 - -
-
-
-
- - -{% endblock %} \ No newline at end of file