commit
6dd58ae5e3
4 changed files with 181 additions and 0 deletions
@ -0,0 +1,36 @@ |
|||||
|
from flask import Flask, jsonify, send_from_directory |
||||
|
|
||||
|
app = Flask(__name__, static_folder="public", static_url_path="") |
||||
|
|
||||
|
# 根路径返回 index.html |
||||
|
@app.route("/") |
||||
|
def serve_index(): |
||||
|
return send_from_directory(app.static_folder, "index.html") |
||||
|
|
||||
|
# API 子路径,提供菏泽宣传数据 |
||||
|
@app.route("/api/heze") |
||||
|
def api_heze(): |
||||
|
heze_data = { |
||||
|
"message": "欢迎来到山东菏泽", |
||||
|
"data": { |
||||
|
"about": "菏泽是中国牡丹之都,位于山东省西南部,以其丰富的历史文化和美丽的自然景观而闻名。", |
||||
|
"places": [ |
||||
|
{"name": "曹州牡丹园", "description": "世界上最大的牡丹园,每年春季举办牡丹花会,吸引众多游客。"}, |
||||
|
{"name": "孙膑旅游城", "description": "以古代军事家孙膑为主题的文化旅游区,展示了丰富的历史遗迹。"}, |
||||
|
{"name": "水浒好汉城", "description": "以《水浒传》为背景的文化景区,重现了宋朝时期的建筑和民俗。"} |
||||
|
], |
||||
|
"food": [ |
||||
|
{"name": "菏泽酱菜", "description": "菏泽特色酱菜,口感爽脆,风味独特。"}, |
||||
|
{"name": "曹州烧饼", "description": "菏泽传统小吃,外皮酥脆,内馅丰富。"}, |
||||
|
{"name": "牡丹饼", "description": "以牡丹花瓣为原料制作的特色糕点,香气扑鼻。"} |
||||
|
], |
||||
|
"culture": [ |
||||
|
{"name": "菏泽戏曲", "description": "菏泽是山东梆子、大平调等多种戏曲的发源地,戏曲文化丰富多彩。"}, |
||||
|
{"name": "菏泽剪纸", "description": "菏泽剪纸是中国非物质文化遗产之一,技艺精湛,图案精美。"} |
||||
|
] |
||||
|
} |
||||
|
} |
||||
|
return jsonify(heze_data) |
||||
|
|
||||
|
if __name__ == "__main__": |
||||
|
app.run(debug=True, port=80) |
@ -0,0 +1,28 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang="en"> |
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
||||
|
<title>宣传我的家乡:山东菏泽</title> |
||||
|
<link rel="stylesheet" href="styles.css"> |
||||
|
</head> |
||||
|
<body> |
||||
|
<div class="container"> |
||||
|
<h1>欢迎来到山东菏泽</h1> |
||||
|
<p id="about"></p> |
||||
|
<div class="section"> |
||||
|
<h2>特色景点</h2> |
||||
|
<div id="places-container"></div> |
||||
|
</div> |
||||
|
<div class="section"> |
||||
|
<h2>菏泽美食</h2> |
||||
|
<div id="food-container"></div> |
||||
|
</div> |
||||
|
<div class="section"> |
||||
|
<h2>菏泽文化</h2> |
||||
|
<div id="culture-container"></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<script src="script.js"></script> |
||||
|
</body> |
||||
|
</html> |
@ -0,0 +1,72 @@ |
|||||
|
document.addEventListener("DOMContentLoaded", function () { |
||||
|
fetch("/api/heze") |
||||
|
.then(response => response.json()) |
||||
|
.then(data => { |
||||
|
const about = document.getElementById("about"); |
||||
|
about.textContent = data.data.about; |
||||
|
|
||||
|
const placesContainer = document.getElementById("places-container"); |
||||
|
const foodContainer = document.getElementById("food-container"); |
||||
|
const cultureContainer = document.getElementById("culture-container"); |
||||
|
|
||||
|
// 渲染景点
|
||||
|
data.data.places.forEach(place => { |
||||
|
const placeItem = document.createElement("div"); |
||||
|
placeItem.classList.add("item"); |
||||
|
|
||||
|
const placeName = document.createElement("div"); |
||||
|
placeName.classList.add("item-name"); |
||||
|
placeName.textContent = place.name; |
||||
|
|
||||
|
const placeDescription = document.createElement("div"); |
||||
|
placeDescription.classList.add("item-description"); |
||||
|
placeDescription.textContent = place.description; |
||||
|
|
||||
|
placeItem.appendChild(placeName); |
||||
|
placeItem.appendChild(placeDescription); |
||||
|
|
||||
|
placesContainer.appendChild(placeItem); |
||||
|
}); |
||||
|
|
||||
|
// 渲染美食
|
||||
|
data.data.food.forEach(food => { |
||||
|
const foodItem = document.createElement("div"); |
||||
|
foodItem.classList.add("item"); |
||||
|
|
||||
|
const foodName = document.createElement("div"); |
||||
|
foodName.classList.add("item-name"); |
||||
|
foodName.textContent = food.name; |
||||
|
|
||||
|
const foodDescription = document.createElement("div"); |
||||
|
foodDescription.classList.add("item-description"); |
||||
|
foodDescription.textContent = food.description; |
||||
|
|
||||
|
foodItem.appendChild(foodName); |
||||
|
foodItem.appendChild(foodDescription); |
||||
|
|
||||
|
foodContainer.appendChild(foodItem); |
||||
|
}); |
||||
|
|
||||
|
// 渲染文化
|
||||
|
data.data.culture.forEach(culture => { |
||||
|
const cultureItem = document.createElement("div"); |
||||
|
cultureItem.classList.add("item"); |
||||
|
|
||||
|
const cultureName = document.createElement("div"); |
||||
|
cultureName.classList.add("item-name"); |
||||
|
cultureName.textContent = culture.name; |
||||
|
|
||||
|
const cultureDescription = document.createElement("div"); |
||||
|
cultureDescription.classList.add("item-description"); |
||||
|
cultureDescription.textContent = culture.description; |
||||
|
|
||||
|
cultureItem.appendChild(cultureName); |
||||
|
cultureItem.appendChild(cultureDescription); |
||||
|
|
||||
|
cultureContainer.appendChild(cultureItem); |
||||
|
}); |
||||
|
}) |
||||
|
.catch(error => { |
||||
|
console.error("Error fetching data:", error); |
||||
|
}); |
||||
|
}); |
@ -0,0 +1,45 @@ |
|||||
|
body { |
||||
|
font-family: Arial, sans-serif; |
||||
|
background-color: #f4f4f9; |
||||
|
margin: 0; |
||||
|
padding: 0; |
||||
|
} |
||||
|
|
||||
|
.container { |
||||
|
max-width: 800px; |
||||
|
margin: 20px auto; |
||||
|
padding: 20px; |
||||
|
background: #fff; |
||||
|
border-radius: 8px; |
||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); |
||||
|
} |
||||
|
|
||||
|
h1, h2 { |
||||
|
text-align: center; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.section { |
||||
|
margin-top: 20px; |
||||
|
} |
||||
|
|
||||
|
.item { |
||||
|
margin-bottom: 15px; |
||||
|
padding: 10px; |
||||
|
border-bottom: 1px solid #ddd; |
||||
|
} |
||||
|
|
||||
|
.item:last-child { |
||||
|
border-bottom: none; |
||||
|
} |
||||
|
|
||||
|
.item-name { |
||||
|
font-size: 1.2em; |
||||
|
font-weight: bold; |
||||
|
color: #444; |
||||
|
} |
||||
|
|
||||
|
.item-description { |
||||
|
font-size: 0.9em; |
||||
|
color: #666; |
||||
|
} |
Loading…
Reference in new issue