htmlgen-mcp 0.3.3__py3-none-any.whl → 0.3.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of htmlgen-mcp might be problematic. Click here for more details.
- htmlgen_mcp/agents/quick_generator.py +481 -63
- htmlgen_mcp/agents/smart_web_agent.py +707 -235
- htmlgen_mcp/agents/web_tools/__init__.py +41 -41
- htmlgen_mcp/agents/web_tools/css.py +148 -0
- htmlgen_mcp/agents/web_tools/js.py +12 -10
- htmlgen_mcp/agents/web_tools/navigation.py +2 -0
- htmlgen_mcp/agents/web_tools/project.py +0 -4
- htmlgen_mcp/config.py +9 -30
- htmlgen_mcp/nas_storage.py +356 -0
- htmlgen_mcp/progress_tools.py +194 -0
- htmlgen_mcp/progress_tracker.py +378 -0
- htmlgen_mcp/web_agent_server.py +13 -4
- {htmlgen_mcp-0.3.3.dist-info → htmlgen_mcp-0.3.4.dist-info}/METADATA +1 -1
- {htmlgen_mcp-0.3.3.dist-info → htmlgen_mcp-0.3.4.dist-info}/RECORD +17 -16
- htmlgen_mcp/agents/cluster_state.py +0 -414
- htmlgen_mcp/agents/cluster_storage.py +0 -341
- {htmlgen_mcp-0.3.3.dist-info → htmlgen_mcp-0.3.4.dist-info}/WHEEL +0 -0
- {htmlgen_mcp-0.3.3.dist-info → htmlgen_mcp-0.3.4.dist-info}/entry_points.txt +0 -0
- {htmlgen_mcp-0.3.3.dist-info → htmlgen_mcp-0.3.4.dist-info}/top_level.txt +0 -0
|
@@ -44,6 +44,7 @@ class SmartWebAgent:
|
|
|
44
44
|
verbose: bool = False,
|
|
45
45
|
show_plan_stream: bool = False,
|
|
46
46
|
save_output: bool = False,
|
|
47
|
+
force_single_page: bool = True,
|
|
47
48
|
):
|
|
48
49
|
self.project_directory = project_directory
|
|
49
50
|
self.model = model
|
|
@@ -51,6 +52,7 @@ class SmartWebAgent:
|
|
|
51
52
|
self.verbose = verbose # 新增:详细输出模式
|
|
52
53
|
self.show_plan_stream = show_plan_stream # 新增:流式显示计划生成
|
|
53
54
|
self.save_output = save_output # 新增:保存输出到日志
|
|
55
|
+
self.force_single_page = force_single_page
|
|
54
56
|
api_key, base_url = self._resolve_api_credentials()
|
|
55
57
|
self.client = self._build_client(api_key, base_url)
|
|
56
58
|
|
|
@@ -786,6 +788,9 @@ class SmartWebAgent:
|
|
|
786
788
|
2. 用户未列出具体的页面名称
|
|
787
789
|
3. 用户未要求复杂的功能
|
|
788
790
|
"""
|
|
791
|
+
if getattr(self, "force_single_page", False):
|
|
792
|
+
return True
|
|
793
|
+
|
|
789
794
|
lower_input = user_input.lower()
|
|
790
795
|
|
|
791
796
|
# 检查是否明确要求多页面
|
|
@@ -879,32 +884,51 @@ class SmartWebAgent:
|
|
|
879
884
|
"menu",
|
|
880
885
|
]
|
|
881
886
|
)
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
887
|
+
is_mall = any(
|
|
888
|
+
k in key
|
|
889
|
+
for k in [
|
|
890
|
+
"购物",
|
|
891
|
+
"商场",
|
|
892
|
+
"mall",
|
|
893
|
+
"plaza",
|
|
894
|
+
"零售",
|
|
895
|
+
"shopping",
|
|
889
896
|
]
|
|
897
|
+
)
|
|
898
|
+
|
|
899
|
+
single_page_mode = getattr(self, "force_single_page", False)
|
|
900
|
+
|
|
901
|
+
if not single_page_mode:
|
|
902
|
+
if is_restaurant:
|
|
903
|
+
nav_structure = [
|
|
904
|
+
{"name": "首页", "href": "index.html"},
|
|
905
|
+
{"name": "菜单", "href": "menu.html"},
|
|
906
|
+
{"name": "关于我们", "href": "about.html"},
|
|
907
|
+
{"name": "联系我们", "href": "contact.html"},
|
|
908
|
+
]
|
|
909
|
+
else:
|
|
910
|
+
nav_structure = [
|
|
911
|
+
{"name": "首页", "href": "index.html"},
|
|
912
|
+
{"name": "关于我们", "href": "about.html"},
|
|
913
|
+
{"name": "服务体系", "href": "services.html"},
|
|
914
|
+
{"name": "联系我们", "href": "contact.html"},
|
|
915
|
+
]
|
|
916
|
+
|
|
917
|
+
def build_nav(active_href: str) -> list:
|
|
918
|
+
return [
|
|
919
|
+
{**item, "active": item["href"] == active_href}
|
|
920
|
+
for item in nav_structure
|
|
921
|
+
]
|
|
890
922
|
else:
|
|
891
|
-
nav_structure = [
|
|
892
|
-
{"name": "首页", "href": "index.html"},
|
|
893
|
-
{"name": "关于我们", "href": "about.html"},
|
|
894
|
-
{"name": "服务体系", "href": "services.html"},
|
|
895
|
-
{"name": "联系我们", "href": "contact.html"},
|
|
896
|
-
]
|
|
923
|
+
nav_structure = []
|
|
897
924
|
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
{**item, "active": item["href"] == active_href}
|
|
901
|
-
for item in nav_structure
|
|
902
|
-
]
|
|
925
|
+
def build_nav(_: str) -> list:
|
|
926
|
+
return []
|
|
903
927
|
|
|
904
928
|
plan: dict = {
|
|
905
929
|
"task_analysis": "离线回退:根据描述创建现代化基础网站骨架",
|
|
906
930
|
"project_name": project_name,
|
|
907
|
-
"site_type": "restaurant" if is_restaurant else "basic-landing",
|
|
931
|
+
"site_type": "restaurant" if is_restaurant else ("shopping-mall" if is_mall else "basic-landing"),
|
|
908
932
|
"design_style": "modern, responsive, glassmorphism",
|
|
909
933
|
"color_scheme": {
|
|
910
934
|
"primary": "#0d6efd",
|
|
@@ -930,17 +954,19 @@ class SmartWebAgent:
|
|
|
930
954
|
}
|
|
931
955
|
)
|
|
932
956
|
# 为不同站点类型提供更有“品牌感”的默认配色
|
|
933
|
-
cafe_palette =
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
if
|
|
942
|
-
|
|
943
|
-
|
|
957
|
+
cafe_palette = {
|
|
958
|
+
"primary": "#6B4F3A",
|
|
959
|
+
"secondary": "#8C5E3C",
|
|
960
|
+
"accent": "#D0A97A",
|
|
961
|
+
"neutral_light": "#F7F3EE",
|
|
962
|
+
"neutral_dark": "#201A16",
|
|
963
|
+
} if is_restaurant else {
|
|
964
|
+
"primary": "#1E3A8A" if is_mall else "#0d6efd",
|
|
965
|
+
"secondary": "#4338CA" if is_mall else "#6c757d",
|
|
966
|
+
"accent": "#F59E0B" if is_mall else "#6610f2",
|
|
967
|
+
"neutral_light": "#F3F4F6",
|
|
968
|
+
"neutral_dark": "#111827" if is_mall else "#212529",
|
|
969
|
+
}
|
|
944
970
|
|
|
945
971
|
steps.append(
|
|
946
972
|
{
|
|
@@ -969,223 +995,639 @@ class SmartWebAgent:
|
|
|
969
995
|
)
|
|
970
996
|
|
|
971
997
|
# 页面创建
|
|
998
|
+
pretty_name = project_name.title()
|
|
999
|
+
|
|
1000
|
+
def build_single_page_sections() -> list[str]:
|
|
1001
|
+
"""生成单页滚动式布局的各个版块"""
|
|
1002
|
+
hero_topic = "artisanal coffee shop interior, warm light, cinematic"
|
|
1003
|
+
lead_text = "星光级烘焙、当季风味和沉浸式空间,打造城市中的第三生活场景。"
|
|
1004
|
+
primary_cta = "查看菜单"
|
|
1005
|
+
secondary_cta = "预订座位"
|
|
1006
|
+
if is_mall:
|
|
1007
|
+
hero_topic = "luxury shopping mall atrium at night, cinematic lighting, visitors"
|
|
1008
|
+
lead_text = "星光购物中心聚合潮流零售、夜间餐饮与家庭娱乐,一站式点亮城市生活。"
|
|
1009
|
+
primary_cta = "了解亮点"
|
|
1010
|
+
secondary_cta = "预约参观"
|
|
1011
|
+
elif not is_restaurant:
|
|
1012
|
+
hero_topic = "modern business hero, gradient lighting, professional team"
|
|
1013
|
+
lead_text = "用策略、设计与工程思维,为品牌打造兼顾颜值与增长的数字体验。"
|
|
1014
|
+
primary_cta = "查看服务"
|
|
1015
|
+
secondary_cta = "联系团队"
|
|
1016
|
+
|
|
1017
|
+
sections = [
|
|
1018
|
+
textwrap.dedent(
|
|
1019
|
+
f"""
|
|
1020
|
+
<header id="hero" class="hero hero-ultra hero-overlay section text-center" data-bg-topic="{hero_topic}" data-parallax="0.25">
|
|
1021
|
+
<div class="overlay"></div>
|
|
1022
|
+
<div class="container hero-inner">
|
|
1023
|
+
<span class="badge badge-soft mb-3">全新体验</span>
|
|
1024
|
+
<h1 class="display-5 mb-3">{pretty_name}</h1>
|
|
1025
|
+
<p class="section-lead mx-auto">{lead_text}</p>
|
|
1026
|
+
<div class="mt-4 d-flex justify-content-center gap-3 flex-wrap">
|
|
1027
|
+
<a class="btn btn-gradient btn-lg px-4" href="#services">{primary_cta}</a>
|
|
1028
|
+
<a class="btn btn-outline-light btn-lg px-4" href="#contact">{secondary_cta}</a>
|
|
1029
|
+
</div>
|
|
1030
|
+
</div>
|
|
1031
|
+
</header>
|
|
1032
|
+
"""
|
|
1033
|
+
).strip()
|
|
1034
|
+
]
|
|
1035
|
+
|
|
1036
|
+
if is_mall:
|
|
1037
|
+
sections.append(
|
|
1038
|
+
textwrap.dedent(
|
|
1039
|
+
"""
|
|
1040
|
+
<section id="services" class="section">
|
|
1041
|
+
<div class="container">
|
|
1042
|
+
<div class="row g-4">
|
|
1043
|
+
<div class="col-md-4">
|
|
1044
|
+
<div class="feature-card glass h-100 p-4 reveal" data-tilt>
|
|
1045
|
+
<div class="icon-badge bg-warning mb-3">🌃</div>
|
|
1046
|
+
<h2 class="h5 mb-2">夜色生活目的地</h2>
|
|
1047
|
+
<p class="text-muted small mb-0">夜间餐饮、潮玩市集与沉浸演出齐聚,打造城市夜经济主场。</p>
|
|
1048
|
+
</div>
|
|
1049
|
+
</div>
|
|
1050
|
+
<div class="col-md-4">
|
|
1051
|
+
<div class="feature-card glass h-100 p-4 reveal" data-tilt>
|
|
1052
|
+
<div class="icon-badge bg-primary mb-3">🛍️</div>
|
|
1053
|
+
<h2 class="h5 mb-2">国际品牌旗舰矩阵</h2>
|
|
1054
|
+
<p class="text-muted small mb-0">200+ 国际与设计师品牌入驻,专属造型顾问与会员定制服务。</p>
|
|
1055
|
+
</div>
|
|
1056
|
+
</div>
|
|
1057
|
+
<div class="col-md-4">
|
|
1058
|
+
<div class="feature-card glass h-100 p-4 reveal" data-tilt>
|
|
1059
|
+
<div class="icon-badge bg-success mb-3">🎡</div>
|
|
1060
|
+
<h2 class="h5 mb-2">家庭娱乐社交场</h2>
|
|
1061
|
+
<p class="text-muted small mb-0">亲子探索乐园、家庭影院与艺术展演,满足全龄客群周末生活。</p>
|
|
1062
|
+
</div>
|
|
1063
|
+
</div>
|
|
1064
|
+
</div>
|
|
1065
|
+
</div>
|
|
1066
|
+
</section>
|
|
1067
|
+
"""
|
|
1068
|
+
).strip()
|
|
1069
|
+
)
|
|
1070
|
+
sections.append(
|
|
1071
|
+
textwrap.dedent(
|
|
1072
|
+
"""
|
|
1073
|
+
<section id="flagship" class="section section-alt">
|
|
1074
|
+
<div class="container">
|
|
1075
|
+
<h2 class="h3 text-center mb-4">主力店铺</h2>
|
|
1076
|
+
<div class="row g-4">
|
|
1077
|
+
<article class="col-lg-4">
|
|
1078
|
+
<div class="card h-100 p-4 shadow-soft reveal" data-tilt>
|
|
1079
|
+
<img data-topic="luxury fashion flagship store interior" alt="星光旗舰时装馆" class="rounded-4 shadow-sm mb-3">
|
|
1080
|
+
<h3 class="h6 mb-2">星光旗舰时装馆</h3>
|
|
1081
|
+
<p class="text-muted small mb-0">轻奢首发系列、私享试衣间与造型顾问服务,重塑高端购物体验。</p>
|
|
1082
|
+
</div>
|
|
1083
|
+
</article>
|
|
1084
|
+
<article class="col-lg-4">
|
|
1085
|
+
<div class="card h-100 p-4 shadow-soft reveal" data-tilt>
|
|
1086
|
+
<img data-topic="gourmet food court night market neon" alt="夜焰美食街区" class="rounded-4 shadow-sm mb-3">
|
|
1087
|
+
<h3 class="h6 mb-2">夜焰美食街区</h3>
|
|
1088
|
+
<p class="text-muted small mb-0">40+ 全球料理、全天候营业与快闪主题活动,夜间精彩不停。</p>
|
|
1089
|
+
</div>
|
|
1090
|
+
</article>
|
|
1091
|
+
<article class="col-lg-4">
|
|
1092
|
+
<div class="card h-100 p-4 shadow-soft reveal" data-tilt>
|
|
1093
|
+
<img data-topic="family entertainment center modern play" alt="星空亲子探索乐园" class="rounded-4 shadow-sm mb-3">
|
|
1094
|
+
<h3 class="h6 mb-2">星空亲子探索乐园</h3>
|
|
1095
|
+
<p class="text-muted small mb-0">互动装置、科学实验与家庭影院,亲子共创灵感与回忆。</p>
|
|
1096
|
+
</div>
|
|
1097
|
+
</article>
|
|
1098
|
+
</div>
|
|
1099
|
+
</div>
|
|
1100
|
+
</section>
|
|
1101
|
+
"""
|
|
1102
|
+
).strip()
|
|
1103
|
+
)
|
|
1104
|
+
sections.append(
|
|
1105
|
+
textwrap.dedent(
|
|
1106
|
+
"""
|
|
1107
|
+
<section id="membership" class="section">
|
|
1108
|
+
<div class="container">
|
|
1109
|
+
<h2 class="h3 text-center mb-4">会员礼遇</h2>
|
|
1110
|
+
<div class="row g-4">
|
|
1111
|
+
<div class="col-md-4">
|
|
1112
|
+
<div class="membership-card shadow-soft h-100 p-4 border-gradient">
|
|
1113
|
+
<h3 class="h6 mb-3">星耀卡 · ¥699 / 年</h3>
|
|
1114
|
+
<p class="text-muted small mb-0">免费停车 120 小时 · 生日礼遇 · 合作品牌限量优惠券。</p>
|
|
1115
|
+
</div>
|
|
1116
|
+
</div>
|
|
1117
|
+
<div class="col-md-4">
|
|
1118
|
+
<div class="membership-card shadow-soft h-100 p-4 border-gradient highlight">
|
|
1119
|
+
<h3 class="h6 mb-3">星耀黑金卡 · ¥1999 / 年</h3>
|
|
1120
|
+
<p class="text-muted small mb-0">私人购物顾问 · VIP 休息室 · 礼宾代客泊车 · 首发活动优先席位。</p>
|
|
1121
|
+
</div>
|
|
1122
|
+
</div>
|
|
1123
|
+
<div class="col-md-4">
|
|
1124
|
+
<div class="membership-card shadow-soft h-100 p-4 border-gradient">
|
|
1125
|
+
<h3 class="h6 mb-3">星悦家庭卡 · ¥1299 / 年</h3>
|
|
1126
|
+
<p class="text-muted small mb-0">亲子乐园畅玩 · 周末家庭影院 · 主题课程折扣与节日惊喜。</p>
|
|
1127
|
+
</div>
|
|
1128
|
+
</div>
|
|
1129
|
+
</div>
|
|
1130
|
+
</div>
|
|
1131
|
+
</section>
|
|
1132
|
+
"""
|
|
1133
|
+
).strip()
|
|
1134
|
+
)
|
|
1135
|
+
sections.append(
|
|
1136
|
+
textwrap.dedent(
|
|
1137
|
+
"""
|
|
1138
|
+
<section id="stories" class="section section-alt">
|
|
1139
|
+
<div class="container">
|
|
1140
|
+
<h2 class="h3 text-center mb-4">顾客见证</h2>
|
|
1141
|
+
<div class="row g-4">
|
|
1142
|
+
<article class="col-md-6">
|
|
1143
|
+
<div class="testimonial-card glass h-100 p-4">
|
|
1144
|
+
<div class="d-flex align-items-center gap-3 mb-3">
|
|
1145
|
+
<img data-topic="fashion influencer portrait studio" alt="顾客" class="avatar rounded-circle shadow-sm">
|
|
1146
|
+
<div>
|
|
1147
|
+
<div class="fw-semibold">刘倩 · 时尚博主</div>
|
|
1148
|
+
<small class="text-muted">星耀黑金卡会员</small>
|
|
1149
|
+
</div>
|
|
1150
|
+
</div>
|
|
1151
|
+
<p class="text-muted small mb-0">“这里像是城市生活方式策展地,每月都能找到惊喜活动。”</p>
|
|
1152
|
+
</div>
|
|
1153
|
+
</article>
|
|
1154
|
+
<article class="col-md-6">
|
|
1155
|
+
<div class="testimonial-card glass h-100 p-4">
|
|
1156
|
+
<div class="d-flex align-items-center gap-3 mb-3">
|
|
1157
|
+
<img data-topic="happy asian family portrait lifestyle" alt="家庭用户" class="avatar rounded-circle shadow-sm">
|
|
1158
|
+
<div>
|
|
1159
|
+
<div class="fw-semibold">周末家庭 · 城市新锐</div>
|
|
1160
|
+
<small class="text-muted">星悦家庭卡会员</small>
|
|
1161
|
+
</div>
|
|
1162
|
+
</div>
|
|
1163
|
+
<p class="text-muted small mb-0">“亲子乐园与夜焰美食街已成为周末必打卡,活动福利超值。”</p>
|
|
1164
|
+
</div>
|
|
1165
|
+
</article>
|
|
1166
|
+
</div>
|
|
1167
|
+
</div>
|
|
1168
|
+
</section>
|
|
1169
|
+
"""
|
|
1170
|
+
).strip()
|
|
1171
|
+
)
|
|
1172
|
+
elif is_restaurant:
|
|
1173
|
+
sections.append(
|
|
1174
|
+
textwrap.dedent(
|
|
1175
|
+
"""
|
|
1176
|
+
<section id="menu" class="section">
|
|
1177
|
+
<div class="container">
|
|
1178
|
+
<div class="row align-items-center g-5">
|
|
1179
|
+
<div class="col-lg-5">
|
|
1180
|
+
<h2 class="h3 mb-3">招牌菜单 · 星光甄选</h2>
|
|
1181
|
+
<p class="text-muted">每日现烘豆种、季节限定特调与匠心甜点,恰到好处的甜与苦。</p>
|
|
1182
|
+
<ul class="list-unstyled vstack gap-3 mt-4 text-muted small">
|
|
1183
|
+
<li>☕️ 精品单品手冲 · 果酸层次丰富</li>
|
|
1184
|
+
<li>🥐 法式可颂每日新鲜出炉</li>
|
|
1185
|
+
<li>🥤 冷萃与气泡咖啡带来夏日灵感</li>
|
|
1186
|
+
</ul>
|
|
1187
|
+
</div>
|
|
1188
|
+
<div class="col-lg-7">
|
|
1189
|
+
<div class="row g-4">
|
|
1190
|
+
<article class="col-sm-6">
|
|
1191
|
+
<div class="glass p-4 h-100 reveal" data-tilt>
|
|
1192
|
+
<img data-topic="signature latte art, golden hour" alt="拿铁" class="rounded shadow-sm mb-3">
|
|
1193
|
+
<div class="d-flex justify-content-between">
|
|
1194
|
+
<h3 class="h5 mb-0">星光拿铁</h3>
|
|
1195
|
+
<span class="badge bg-primary-subtle text-primary fw-semibold">¥36</span>
|
|
1196
|
+
</div>
|
|
1197
|
+
<p class="text-muted mt-2 small">丝滑奶泡配自家烘焙浓缩,口感层层递进。</p>
|
|
1198
|
+
</div>
|
|
1199
|
+
</article>
|
|
1200
|
+
<article class="col-sm-6">
|
|
1201
|
+
<div class="glass p-4 h-100 reveal" data-tilt>
|
|
1202
|
+
<img data-topic="pour over coffee setup minimal" alt="手冲咖啡" class="rounded shadow-sm mb-3">
|
|
1203
|
+
<div class="d-flex justify-content-between">
|
|
1204
|
+
<h3 class="h5 mb-0">北海道手冲</h3>
|
|
1205
|
+
<span class="badge bg-primary-subtle text-primary fw-semibold">¥42</span>
|
|
1206
|
+
</div>
|
|
1207
|
+
<p class="text-muted mt-2 small">慢萃 16 小时带来清爽果香与轻盈坚果尾韵。</p>
|
|
1208
|
+
</div>
|
|
1209
|
+
</article>
|
|
1210
|
+
</div>
|
|
1211
|
+
</div>
|
|
1212
|
+
</div>
|
|
1213
|
+
</div>
|
|
1214
|
+
</section>
|
|
1215
|
+
"""
|
|
1216
|
+
).strip()
|
|
1217
|
+
)
|
|
1218
|
+
sections.append(
|
|
1219
|
+
textwrap.dedent(
|
|
1220
|
+
f"""
|
|
1221
|
+
<section id="about" class="section section-alt">
|
|
1222
|
+
<div class="container">
|
|
1223
|
+
<div class="row g-4 align-items-center">
|
|
1224
|
+
<div class="col-lg-6">
|
|
1225
|
+
<img data-topic="coffee roastery studio, warm tone" alt="{pretty_name} 空间" class="rounded-4 shadow-lg w-100">
|
|
1226
|
+
</div>
|
|
1227
|
+
<div class="col-lg-6">
|
|
1228
|
+
<h2 class="h3 mb-3">空间故事 · 一杯咖啡的旅程</h2>
|
|
1229
|
+
<p class="text-muted">我们从产地挑豆、烘焙到杯中,所有步骤都由资深咖啡师亲自把关,确保每一口都带着温度与惊喜。</p>
|
|
1230
|
+
<div class="row g-3 mt-4 text-muted small">
|
|
1231
|
+
<div class="col-sm-6"><div class="glass p-3 h-100">🌱 直采可持续农场</div></div>
|
|
1232
|
+
<div class="col-sm-6"><div class="glass p-3 h-100">👩🍳 世界冠军团队驻店</div></div>
|
|
1233
|
+
<div class="col-sm-6"><div class="glass p-3 h-100">🎵 手工黑胶沉浸配乐</div></div>
|
|
1234
|
+
<div class="col-sm-6"><div class="glass p-3 h-100">📍 城市中最松弛的角落</div></div>
|
|
1235
|
+
</div>
|
|
1236
|
+
</div>
|
|
1237
|
+
</div>
|
|
1238
|
+
</div>
|
|
1239
|
+
</section>
|
|
1240
|
+
"""
|
|
1241
|
+
).strip()
|
|
1242
|
+
)
|
|
1243
|
+
else:
|
|
1244
|
+
sections.append(
|
|
1245
|
+
textwrap.dedent(
|
|
1246
|
+
"""
|
|
1247
|
+
<section id="about" class="section">
|
|
1248
|
+
<div class="container">
|
|
1249
|
+
<div class="row g-4 align-items-center">
|
|
1250
|
+
<div class="col-lg-5">
|
|
1251
|
+
<h2 class="h3 mb-3">关于我们 · Strategy × Design × Tech</h2>
|
|
1252
|
+
<p class="text-muted">十年数字化品牌经验,聚焦增长体验、可持续设计系统与落地执行力。</p>
|
|
1253
|
+
<ul class="list-unstyled vstack gap-2 small text-muted">
|
|
1254
|
+
<li>✔️ 服务 80+ 创新品牌与上市企业</li>
|
|
1255
|
+
<li>✔️ 多端一致的组件化设计系统</li>
|
|
1256
|
+
<li>✔️ 数据驱动的转化优化闭环</li>
|
|
1257
|
+
</ul>
|
|
1258
|
+
</div>
|
|
1259
|
+
<div class="col-lg-7">
|
|
1260
|
+
<div class="row g-3">
|
|
1261
|
+
<div class="col-sm-6">
|
|
1262
|
+
<div class="glass p-4 h-100 reveal" data-tilt>
|
|
1263
|
+
<span class="display-5 fw-bold text-primary">98%</span>
|
|
1264
|
+
<p class="text-muted small mb-0">客户满意度,连续三年领跑行业。</p>
|
|
1265
|
+
</div>
|
|
1266
|
+
</div>
|
|
1267
|
+
<div class="col-sm-6">
|
|
1268
|
+
<div class="glass p-4 h-100 reveal" data-tilt>
|
|
1269
|
+
<span class="display-5 fw-bold text-primary">120+</span>
|
|
1270
|
+
<p class="text-muted small mb-0">完成项目,总计覆盖 12 个细分行业。</p>
|
|
1271
|
+
</div>
|
|
1272
|
+
</div>
|
|
1273
|
+
</div>
|
|
1274
|
+
</div>
|
|
1275
|
+
</div>
|
|
1276
|
+
</div>
|
|
1277
|
+
</section>
|
|
1278
|
+
"""
|
|
1279
|
+
).strip()
|
|
1280
|
+
)
|
|
1281
|
+
|
|
1282
|
+
if not is_mall:
|
|
1283
|
+
sections.append(
|
|
1284
|
+
textwrap.dedent(
|
|
1285
|
+
"""
|
|
1286
|
+
<section id="services" class="section">
|
|
1287
|
+
<div class="container">
|
|
1288
|
+
<h2 class="h3 text-center mb-3">服务矩阵</h2>
|
|
1289
|
+
<p class="section-lead text-center text-muted mb-5">从品牌策略、视觉系统到线上交付,一站式协同推进。</p>
|
|
1290
|
+
<div class="row g-4">
|
|
1291
|
+
<div class="col-md-4">
|
|
1292
|
+
<div class="service-card glass p-4 h-100 reveal" data-tilt>
|
|
1293
|
+
<img data-topic="creative workshop, design sprint" alt="策略工作坊" class="rounded shadow-sm mb-3">
|
|
1294
|
+
<h3 class="h5">策略定位</h3>
|
|
1295
|
+
<p class="text-muted small mb-0">品牌北极星梳理、价值主张共创与产品架构重构。</p>
|
|
1296
|
+
</div>
|
|
1297
|
+
</div>
|
|
1298
|
+
<div class="col-md-4">
|
|
1299
|
+
<div class="service-card glass p-4 h-100 reveal" data-tilt>
|
|
1300
|
+
<img data-topic="modern ui design system" alt="设计系统" class="rounded shadow-sm mb-3">
|
|
1301
|
+
<h3 class="h5">设计系统</h3>
|
|
1302
|
+
<p class="text-muted small mb-0">跨平台组件库、主题配色、动态规范与品牌资产管理。</p>
|
|
1303
|
+
</div>
|
|
1304
|
+
</div>
|
|
1305
|
+
<div class="col-md-4">
|
|
1306
|
+
<div class="service-card glass p-4 h-100 reveal" data-tilt>
|
|
1307
|
+
<img data-topic="web development team collaboration" alt="工程交付" class="rounded shadow-sm mb-3">
|
|
1308
|
+
<h3 class="h5">工程落地</h3>
|
|
1309
|
+
<p class="text-muted small mb-0">高性能前端、内容管理、可观测性与持续迭代机制。</p>
|
|
1310
|
+
</div>
|
|
1311
|
+
</div>
|
|
1312
|
+
</div>
|
|
1313
|
+
</div>
|
|
1314
|
+
</section>
|
|
1315
|
+
"""
|
|
1316
|
+
).strip()
|
|
1317
|
+
)
|
|
1318
|
+
|
|
1319
|
+
sections.append(
|
|
1320
|
+
textwrap.dedent(
|
|
1321
|
+
f"""
|
|
1322
|
+
<section id="contact" class="section section-sm">
|
|
1323
|
+
<div class="container">
|
|
1324
|
+
<div class="row g-4 align-items-center">
|
|
1325
|
+
<div class="col-lg-5">
|
|
1326
|
+
<h2 class="h4 mb-3">马上联系 · 预约体验</h2>
|
|
1327
|
+
<p class="text-muted">留下联系方式,我们将在 24 小时内回电,提供定制化方案。</p>
|
|
1328
|
+
<ul class="list-unstyled small text-muted">
|
|
1329
|
+
<li>📞 电话:400-123-4567</li>
|
|
1330
|
+
<li>📍 地址:上海市静安区星光路 88 号</li>
|
|
1331
|
+
<li>🕒 营业:周一至周日 09:00 - 22:00</li>
|
|
1332
|
+
</ul>
|
|
1333
|
+
</div>
|
|
1334
|
+
<div class="col-lg-7">
|
|
1335
|
+
<form class="glass p-4 rounded-4 shadow-sm row g-3">
|
|
1336
|
+
<div class="col-md-6">
|
|
1337
|
+
<label class="form-label">姓名</label>
|
|
1338
|
+
<input type="text" class="form-control" placeholder="请输入姓名" required>
|
|
1339
|
+
</div>
|
|
1340
|
+
<div class="col-md-6">
|
|
1341
|
+
<label class="form-label">联系方式</label>
|
|
1342
|
+
<input type="tel" class="form-control" placeholder="手机或邮箱" required>
|
|
1343
|
+
</div>
|
|
1344
|
+
<div class="col-12">
|
|
1345
|
+
<label class="form-label">需求概述</label>
|
|
1346
|
+
<textarea class="form-control" rows="3" placeholder="请说明项目类型、预算或时间节点"></textarea>
|
|
1347
|
+
</div>
|
|
1348
|
+
<div class="col-12 d-grid">
|
|
1349
|
+
<button class="btn btn-primary" type="submit">提交信息</button>
|
|
1350
|
+
</div>
|
|
1351
|
+
</form>
|
|
1352
|
+
</div>
|
|
1353
|
+
</div>
|
|
1354
|
+
</div>
|
|
1355
|
+
</section>
|
|
1356
|
+
"""
|
|
1357
|
+
).strip()
|
|
1358
|
+
)
|
|
1359
|
+
|
|
1360
|
+
sections.append(
|
|
1361
|
+
textwrap.dedent(
|
|
1362
|
+
f"""
|
|
1363
|
+
<footer class="footer-creative text-center py-4">
|
|
1364
|
+
<div class="container small text-muted">
|
|
1365
|
+
<div>{pretty_name} · 现代品牌体验实验室</div>
|
|
1366
|
+
<div class="mt-1">© {datetime.now().year} All rights reserved.</div>
|
|
1367
|
+
</div>
|
|
1368
|
+
</footer>
|
|
1369
|
+
"""
|
|
1370
|
+
).strip()
|
|
1371
|
+
)
|
|
1372
|
+
return sections
|
|
1373
|
+
|
|
1374
|
+
single_page_sections = build_single_page_sections() if single_page_mode else None
|
|
1375
|
+
|
|
1376
|
+
create_index_params = {
|
|
1377
|
+
"file_path": os.path.join(project_root, "index.html"),
|
|
1378
|
+
"title": pretty_name,
|
|
1379
|
+
"content": "",
|
|
1380
|
+
"style": "ultra_modern",
|
|
1381
|
+
}
|
|
1382
|
+
if single_page_sections:
|
|
1383
|
+
create_index_params["sections"] = single_page_sections
|
|
1384
|
+
|
|
972
1385
|
steps.append(
|
|
973
1386
|
{
|
|
974
1387
|
"step": 4,
|
|
975
1388
|
"tool": "create_html_file",
|
|
976
|
-
"params":
|
|
977
|
-
"file_path": os.path.join(project_root, "index.html"),
|
|
978
|
-
"title": project_name.title(),
|
|
979
|
-
"content": "",
|
|
980
|
-
"style": "ultra_modern",
|
|
981
|
-
},
|
|
1389
|
+
"params": create_index_params,
|
|
982
1390
|
"description": "创建首页",
|
|
983
1391
|
"rationale": "生成结构化HTML并挂接CSS/JS",
|
|
984
1392
|
}
|
|
985
1393
|
)
|
|
986
1394
|
|
|
987
|
-
if
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
"
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
"description": "创建菜单页面",
|
|
997
|
-
"rationale": "餐饮类站点专用模板,分类清晰、价格醒目",
|
|
998
|
-
}
|
|
999
|
-
)
|
|
1000
|
-
steps.append(
|
|
1001
|
-
{
|
|
1002
|
-
"step": 6,
|
|
1003
|
-
"tool": "create_about_page",
|
|
1004
|
-
"params": {
|
|
1005
|
-
"file_path": os.path.join(project_root, "about.html"),
|
|
1006
|
-
"project_name": project_name.title(),
|
|
1007
|
-
"context": {
|
|
1008
|
-
"site_type": "restaurant",
|
|
1009
|
-
"project_description": plan.get("task_analysis"),
|
|
1010
|
-
"nav_items": build_nav("about.html"),
|
|
1395
|
+
if not single_page_mode:
|
|
1396
|
+
if is_restaurant:
|
|
1397
|
+
steps.append(
|
|
1398
|
+
{
|
|
1399
|
+
"step": 5,
|
|
1400
|
+
"tool": "create_menu_page",
|
|
1401
|
+
"params": {
|
|
1402
|
+
"file_path": os.path.join(project_root, "menu.html"),
|
|
1403
|
+
"project_name": pretty_name,
|
|
1011
1404
|
},
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
)
|
|
1029
|
-
else:
|
|
1030
|
-
steps.append(
|
|
1031
|
-
{
|
|
1032
|
-
"step": 5,
|
|
1033
|
-
"tool": "create_about_page",
|
|
1034
|
-
"params": {
|
|
1035
|
-
"file_path": os.path.join(project_root, "about.html"),
|
|
1036
|
-
"project_name": project_name.title(),
|
|
1037
|
-
"context": {
|
|
1038
|
-
"site_type": plan.get("site_type"),
|
|
1039
|
-
"project_description": plan.get("task_analysis"),
|
|
1040
|
-
"nav_items": build_nav("about.html"),
|
|
1405
|
+
"description": "创建菜单页面",
|
|
1406
|
+
"rationale": "餐饮类站点专用模板,分类清晰、价格醒目",
|
|
1407
|
+
}
|
|
1408
|
+
)
|
|
1409
|
+
steps.append(
|
|
1410
|
+
{
|
|
1411
|
+
"step": 6,
|
|
1412
|
+
"tool": "create_about_page",
|
|
1413
|
+
"params": {
|
|
1414
|
+
"file_path": os.path.join(project_root, "about.html"),
|
|
1415
|
+
"project_name": pretty_name,
|
|
1416
|
+
"context": {
|
|
1417
|
+
"site_type": "restaurant",
|
|
1418
|
+
"project_description": plan.get("task_analysis"),
|
|
1419
|
+
"nav_items": build_nav("about.html"),
|
|
1420
|
+
},
|
|
1041
1421
|
},
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1422
|
+
"description": "创建关于页面",
|
|
1423
|
+
"rationale": "品牌故事、理念与团队展示",
|
|
1424
|
+
}
|
|
1425
|
+
)
|
|
1426
|
+
steps.append(
|
|
1427
|
+
{
|
|
1428
|
+
"step": 7,
|
|
1429
|
+
"tool": "create_contact_page",
|
|
1430
|
+
"params": {
|
|
1431
|
+
"file_path": os.path.join(project_root, "contact.html"),
|
|
1432
|
+
"project_name": pretty_name,
|
|
1433
|
+
},
|
|
1434
|
+
"description": "创建联系页面",
|
|
1435
|
+
"rationale": "营业时间、地址、联系表单与地图占位",
|
|
1436
|
+
}
|
|
1437
|
+
)
|
|
1438
|
+
else:
|
|
1439
|
+
steps.append(
|
|
1440
|
+
{
|
|
1441
|
+
"step": 5,
|
|
1442
|
+
"tool": "create_about_page",
|
|
1443
|
+
"params": {
|
|
1444
|
+
"file_path": os.path.join(project_root, "about.html"),
|
|
1445
|
+
"project_name": pretty_name,
|
|
1446
|
+
"context": {
|
|
1447
|
+
"site_type": plan.get("site_type"),
|
|
1448
|
+
"project_description": plan.get("task_analysis"),
|
|
1449
|
+
"nav_items": build_nav("about.html"),
|
|
1450
|
+
},
|
|
1451
|
+
},
|
|
1452
|
+
"description": "创建关于页面",
|
|
1453
|
+
"rationale": "补充团队故事、理念与品牌背景",
|
|
1454
|
+
}
|
|
1455
|
+
)
|
|
1456
|
+
steps.append(
|
|
1457
|
+
{
|
|
1458
|
+
"step": 6,
|
|
1459
|
+
"tool": "create_html_file",
|
|
1460
|
+
"params": {
|
|
1461
|
+
"file_path": os.path.join(project_root, "services.html"),
|
|
1462
|
+
"title": f"{pretty_name} · 服务体系",
|
|
1463
|
+
"content": "",
|
|
1464
|
+
"style": "creative_gradient",
|
|
1465
|
+
},
|
|
1466
|
+
"description": "创建服务页面",
|
|
1467
|
+
"rationale": "呈现产品/服务矩阵与亮点",
|
|
1468
|
+
}
|
|
1469
|
+
)
|
|
1470
|
+
steps.append(
|
|
1471
|
+
{
|
|
1472
|
+
"step": 7,
|
|
1473
|
+
"tool": "create_html_file",
|
|
1474
|
+
"params": {
|
|
1475
|
+
"file_path": os.path.join(project_root, "contact.html"),
|
|
1476
|
+
"title": f"{pretty_name} · 联系我们",
|
|
1477
|
+
"content": "",
|
|
1478
|
+
"style": "minimal_elegant",
|
|
1479
|
+
},
|
|
1480
|
+
"description": "创建联系页面",
|
|
1481
|
+
"rationale": "提供表单、地图与联系方式",
|
|
1482
|
+
}
|
|
1483
|
+
)
|
|
1484
|
+
|
|
1485
|
+
# 框架与导航
|
|
1486
|
+
steps.append(
|
|
1487
|
+
{
|
|
1488
|
+
"step": 5 if single_page_mode else 8,
|
|
1489
|
+
"tool": "add_bootstrap",
|
|
1490
|
+
"params": {"project_path": project_root},
|
|
1491
|
+
"description": "接入Bootstrap以增强组件与响应式",
|
|
1492
|
+
"rationale": "快速获得导航栏、栅格与表单样式",
|
|
1493
|
+
}
|
|
1494
|
+
)
|
|
1495
|
+
|
|
1496
|
+
if not single_page_mode:
|
|
1497
|
+
for idx, page in enumerate(
|
|
1498
|
+
["index.html"]
|
|
1499
|
+
+ (
|
|
1500
|
+
["menu.html", "about.html", "contact.html"]
|
|
1501
|
+
if is_restaurant
|
|
1502
|
+
else ["about.html", "services.html", "contact.html"]
|
|
1503
|
+
),
|
|
1504
|
+
start=9,
|
|
1505
|
+
):
|
|
1506
|
+
steps.append(
|
|
1507
|
+
{
|
|
1508
|
+
"step": idx,
|
|
1509
|
+
"tool": "create_responsive_navbar",
|
|
1510
|
+
"params": {
|
|
1511
|
+
"file_path": os.path.join(project_root, page),
|
|
1512
|
+
"brand_name": pretty_name,
|
|
1513
|
+
"nav_items": build_nav(page),
|
|
1514
|
+
},
|
|
1515
|
+
"description": f"同步 {page} 导航",
|
|
1516
|
+
"rationale": "保持跨页面导航一致、定位正确",
|
|
1517
|
+
}
|
|
1518
|
+
)
|
|
1519
|
+
|
|
1520
|
+
# 图片注入
|
|
1521
|
+
next_step = steps[-1]["step"] + 1
|
|
1522
|
+
if single_page_mode:
|
|
1523
|
+
if is_restaurant:
|
|
1524
|
+
sections_topics = ["signature coffee bar interior", "artisan baristas working", "minimalist cafe seating", "latte art macro"]
|
|
1525
|
+
elif is_mall:
|
|
1526
|
+
sections_topics = [
|
|
1527
|
+
"luxury shopping mall atrium night, cinematic lighting",
|
|
1528
|
+
"gourmet food court lifestyle photography",
|
|
1529
|
+
"vip shopping lounge interior, warm lighting",
|
|
1530
|
+
"family entertainment center vibrant"
|
|
1531
|
+
]
|
|
1532
|
+
else:
|
|
1533
|
+
sections_topics = ["modern business team collaboration", "digital product design workspace", "technology innovation hub", "professional meeting room"]
|
|
1047
1534
|
steps.append(
|
|
1048
1535
|
{
|
|
1049
|
-
"step":
|
|
1050
|
-
"tool": "
|
|
1536
|
+
"step": next_step,
|
|
1537
|
+
"tool": "inject_images",
|
|
1051
1538
|
"params": {
|
|
1052
|
-
"file_path": os.path.join(project_root, "
|
|
1053
|
-
"
|
|
1054
|
-
"
|
|
1055
|
-
"
|
|
1539
|
+
"file_path": os.path.join(project_root, "index.html"),
|
|
1540
|
+
"provider": "pollinations",
|
|
1541
|
+
"topics": sections_topics,
|
|
1542
|
+
"size": "1280x720",
|
|
1543
|
+
"seed": 42,
|
|
1544
|
+
"save": True,
|
|
1545
|
+
"subdir": "assets/images",
|
|
1546
|
+
"prefix": "index",
|
|
1056
1547
|
},
|
|
1057
|
-
"description": "
|
|
1058
|
-
"rationale": "
|
|
1548
|
+
"description": "注入首页图片",
|
|
1549
|
+
"rationale": "为单页面各版块填充视觉素材",
|
|
1059
1550
|
}
|
|
1060
1551
|
)
|
|
1552
|
+
next_step += 1
|
|
1553
|
+
else:
|
|
1061
1554
|
steps.append(
|
|
1062
1555
|
{
|
|
1063
|
-
"step":
|
|
1064
|
-
"tool": "
|
|
1556
|
+
"step": next_step,
|
|
1557
|
+
"tool": "inject_images",
|
|
1065
1558
|
"params": {
|
|
1066
|
-
"file_path": os.path.join(project_root, "
|
|
1067
|
-
"
|
|
1068
|
-
"
|
|
1069
|
-
"
|
|
1559
|
+
"file_path": os.path.join(project_root, "index.html"),
|
|
1560
|
+
"provider": "pollinations",
|
|
1561
|
+
"topics": ["cozy coffee hero, gradient glassmorphism"],
|
|
1562
|
+
"size": "1200x800",
|
|
1563
|
+
"seed": 42,
|
|
1564
|
+
"save": True,
|
|
1565
|
+
"subdir": "assets/images",
|
|
1566
|
+
"prefix": "img",
|
|
1070
1567
|
},
|
|
1071
|
-
"description": "
|
|
1072
|
-
"rationale": "
|
|
1568
|
+
"description": "首页图片注入",
|
|
1569
|
+
"rationale": "让页面更具视觉表现",
|
|
1073
1570
|
}
|
|
1074
1571
|
)
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1572
|
+
next_step += 1
|
|
1573
|
+
if is_restaurant:
|
|
1574
|
+
steps.append(
|
|
1575
|
+
{
|
|
1576
|
+
"step": next_step,
|
|
1577
|
+
"tool": "inject_images",
|
|
1578
|
+
"params": {
|
|
1579
|
+
"file_path": os.path.join(project_root, "menu.html"),
|
|
1580
|
+
"provider": "pollinations",
|
|
1581
|
+
"topics": ["latte art", "espresso shot", "pastry dessert"],
|
|
1582
|
+
"size": "1024x768",
|
|
1583
|
+
"seed": 7,
|
|
1584
|
+
"save": True,
|
|
1585
|
+
"subdir": "assets/images",
|
|
1586
|
+
"prefix": "menu",
|
|
1587
|
+
},
|
|
1588
|
+
"description": "为菜单页注入图片",
|
|
1589
|
+
"rationale": "展示咖啡/甜点,更贴合餐饮场景",
|
|
1590
|
+
}
|
|
1591
|
+
)
|
|
1592
|
+
next_step += 1
|
|
1096
1593
|
steps.append(
|
|
1097
1594
|
{
|
|
1098
|
-
"step":
|
|
1099
|
-
"tool": "
|
|
1595
|
+
"step": next_step,
|
|
1596
|
+
"tool": "inject_images",
|
|
1100
1597
|
"params": {
|
|
1101
|
-
"file_path": os.path.join(project_root,
|
|
1102
|
-
"
|
|
1103
|
-
"
|
|
1598
|
+
"file_path": os.path.join(project_root, "about.html"),
|
|
1599
|
+
"provider": "pollinations",
|
|
1600
|
+
"topics": ["barista portrait", "coffee roasting", "cafe community"],
|
|
1601
|
+
"size": "1024x768",
|
|
1602
|
+
"seed": 11,
|
|
1603
|
+
"save": True,
|
|
1604
|
+
"subdir": "assets/images",
|
|
1605
|
+
"prefix": "about",
|
|
1104
1606
|
},
|
|
1105
|
-
"description":
|
|
1106
|
-
"rationale": "
|
|
1607
|
+
"description": "关于页图片注入",
|
|
1608
|
+
"rationale": "呈现团队与品牌氛围",
|
|
1107
1609
|
}
|
|
1108
1610
|
)
|
|
1109
|
-
|
|
1110
|
-
# 图片注入
|
|
1111
|
-
next_step = steps[-1]["step"] + 1
|
|
1112
|
-
steps.append(
|
|
1113
|
-
{
|
|
1114
|
-
"step": next_step,
|
|
1115
|
-
"tool": "inject_images",
|
|
1116
|
-
"params": {
|
|
1117
|
-
"file_path": os.path.join(project_root, "index.html"),
|
|
1118
|
-
"provider": "pollinations",
|
|
1119
|
-
"topics": ["cozy coffee hero, gradient glassmorphism"],
|
|
1120
|
-
"size": "1200x800",
|
|
1121
|
-
"seed": 42,
|
|
1122
|
-
"save": True,
|
|
1123
|
-
"subdir": "assets/images",
|
|
1124
|
-
"prefix": "img",
|
|
1125
|
-
},
|
|
1126
|
-
"description": "首页图片注入",
|
|
1127
|
-
"rationale": "让页面更具视觉表现",
|
|
1128
|
-
}
|
|
1129
|
-
)
|
|
1130
|
-
next_step += 1
|
|
1131
|
-
if is_restaurant:
|
|
1611
|
+
next_step += 1
|
|
1132
1612
|
steps.append(
|
|
1133
1613
|
{
|
|
1134
1614
|
"step": next_step,
|
|
1135
1615
|
"tool": "inject_images",
|
|
1136
1616
|
"params": {
|
|
1137
|
-
"file_path": os.path.join(project_root, "
|
|
1617
|
+
"file_path": os.path.join(project_root, "contact.html"),
|
|
1138
1618
|
"provider": "pollinations",
|
|
1139
|
-
"topics": ["
|
|
1619
|
+
"topics": ["coffee shop storefront", "map pin"],
|
|
1140
1620
|
"size": "1024x768",
|
|
1141
|
-
"seed":
|
|
1621
|
+
"seed": 13,
|
|
1142
1622
|
"save": True,
|
|
1143
1623
|
"subdir": "assets/images",
|
|
1144
|
-
"prefix": "
|
|
1624
|
+
"prefix": "contact",
|
|
1145
1625
|
},
|
|
1146
|
-
"description": "
|
|
1147
|
-
"rationale": "
|
|
1626
|
+
"description": "联系页图片注入",
|
|
1627
|
+
"rationale": "增强门店信息表现",
|
|
1148
1628
|
}
|
|
1149
1629
|
)
|
|
1150
1630
|
next_step += 1
|
|
1151
|
-
steps.append(
|
|
1152
|
-
{
|
|
1153
|
-
"step": next_step,
|
|
1154
|
-
"tool": "inject_images",
|
|
1155
|
-
"params": {
|
|
1156
|
-
"file_path": os.path.join(project_root, "about.html"),
|
|
1157
|
-
"provider": "pollinations",
|
|
1158
|
-
"topics": ["barista portrait", "coffee roasting", "cafe community"],
|
|
1159
|
-
"size": "1024x768",
|
|
1160
|
-
"seed": 11,
|
|
1161
|
-
"save": True,
|
|
1162
|
-
"subdir": "assets/images",
|
|
1163
|
-
"prefix": "about",
|
|
1164
|
-
},
|
|
1165
|
-
"description": "关于页图片注入",
|
|
1166
|
-
"rationale": "呈现团队与品牌氛围",
|
|
1167
|
-
}
|
|
1168
|
-
)
|
|
1169
|
-
next_step += 1
|
|
1170
|
-
steps.append(
|
|
1171
|
-
{
|
|
1172
|
-
"step": next_step,
|
|
1173
|
-
"tool": "inject_images",
|
|
1174
|
-
"params": {
|
|
1175
|
-
"file_path": os.path.join(project_root, "contact.html"),
|
|
1176
|
-
"provider": "pollinations",
|
|
1177
|
-
"topics": ["coffee shop storefront", "map pin"],
|
|
1178
|
-
"size": "1024x768",
|
|
1179
|
-
"seed": 13,
|
|
1180
|
-
"save": True,
|
|
1181
|
-
"subdir": "assets/images",
|
|
1182
|
-
"prefix": "contact",
|
|
1183
|
-
},
|
|
1184
|
-
"description": "联系页图片注入",
|
|
1185
|
-
"rationale": "增强门店信息表现",
|
|
1186
|
-
}
|
|
1187
|
-
)
|
|
1188
|
-
next_step += 1
|
|
1189
1631
|
|
|
1190
1632
|
# 校验与预览
|
|
1191
1633
|
steps.append(
|
|
@@ -1239,6 +1681,8 @@ class SmartWebAgent:
|
|
|
1239
1681
|
if not isinstance(plan, dict):
|
|
1240
1682
|
return plan
|
|
1241
1683
|
|
|
1684
|
+
single_page_mode = getattr(self, "force_single_page", False)
|
|
1685
|
+
|
|
1242
1686
|
seq = plan.get("tools_sequence")
|
|
1243
1687
|
if not isinstance(seq, list):
|
|
1244
1688
|
seq = []
|
|
@@ -1286,6 +1730,25 @@ class SmartWebAgent:
|
|
|
1286
1730
|
obj["params"] = {"file_path": p} if isinstance(p, str) else {}
|
|
1287
1731
|
all_steps.append(obj)
|
|
1288
1732
|
|
|
1733
|
+
if single_page_mode:
|
|
1734
|
+
filtered_steps: list[dict] = []
|
|
1735
|
+
for obj in all_steps:
|
|
1736
|
+
tool = obj.get("tool")
|
|
1737
|
+
if tool in {
|
|
1738
|
+
"create_menu_page",
|
|
1739
|
+
"create_about_page",
|
|
1740
|
+
"create_contact_page",
|
|
1741
|
+
"create_responsive_navbar",
|
|
1742
|
+
}:
|
|
1743
|
+
continue
|
|
1744
|
+
params = obj.get("params") if isinstance(obj.get("params"), dict) else {}
|
|
1745
|
+
file_path = params.get("file_path")
|
|
1746
|
+
if file_path and str(file_path).lower().endswith(".html"):
|
|
1747
|
+
if os.path.basename(str(file_path)).lower() != "index.html":
|
|
1748
|
+
continue
|
|
1749
|
+
filtered_steps.append(obj)
|
|
1750
|
+
all_steps = filtered_steps
|
|
1751
|
+
|
|
1289
1752
|
# 为导航中引用的页面补齐生成步骤(若规划中缺失)
|
|
1290
1753
|
page_tools = {
|
|
1291
1754
|
"create_html_file",
|
|
@@ -1307,36 +1770,38 @@ class SmartWebAgent:
|
|
|
1307
1770
|
nav_required: dict[str, str] = {}
|
|
1308
1771
|
nav_step_refs: list[tuple[int, int]] = [] # (index, step)
|
|
1309
1772
|
nav_templates: list[dict[str, Any]] = []
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1773
|
+
|
|
1774
|
+
if not single_page_mode:
|
|
1775
|
+
for idx, obj in enumerate(all_steps):
|
|
1776
|
+
if obj.get("tool") != "create_responsive_navbar":
|
|
1777
|
+
continue
|
|
1778
|
+
params = obj.get("params") if isinstance(obj.get("params"), dict) else {}
|
|
1779
|
+
nav_items = params.get("nav_items") or []
|
|
1780
|
+
if isinstance(nav_items, list):
|
|
1781
|
+
cleaned_items = []
|
|
1782
|
+
for item in nav_items:
|
|
1783
|
+
if not isinstance(item, dict):
|
|
1784
|
+
cleaned_items.append(item)
|
|
1785
|
+
continue
|
|
1786
|
+
href = str(item.get("href", "")).strip()
|
|
1787
|
+
if href and href.lower().endswith(".html"):
|
|
1788
|
+
normalized = href.lstrip("./")
|
|
1789
|
+
basename = os.path.basename(normalized)
|
|
1790
|
+
if basename != href:
|
|
1791
|
+
item = dict(item)
|
|
1792
|
+
item["href"] = basename
|
|
1793
|
+
nav_required.setdefault(
|
|
1794
|
+
basename, str(item.get("name") or basename)
|
|
1795
|
+
)
|
|
1319
1796
|
cleaned_items.append(item)
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
nav_required.setdefault(
|
|
1329
|
-
basename, str(item.get("name") or basename)
|
|
1330
|
-
)
|
|
1331
|
-
cleaned_items.append(item)
|
|
1332
|
-
params["nav_items"] = cleaned_items
|
|
1333
|
-
nav_step_refs.append((idx, obj.get("step", idx + 1)))
|
|
1334
|
-
nav_templates.append(
|
|
1335
|
-
{
|
|
1336
|
-
"params": copy.deepcopy(params) if isinstance(params, dict) else {},
|
|
1337
|
-
"step": obj.get("step", idx + 1),
|
|
1338
|
-
}
|
|
1339
|
-
)
|
|
1797
|
+
params["nav_items"] = cleaned_items
|
|
1798
|
+
nav_step_refs.append((idx, obj.get("step", idx + 1)))
|
|
1799
|
+
nav_templates.append(
|
|
1800
|
+
{
|
|
1801
|
+
"params": copy.deepcopy(params) if isinstance(params, dict) else {},
|
|
1802
|
+
"step": obj.get("step", idx + 1),
|
|
1803
|
+
}
|
|
1804
|
+
)
|
|
1340
1805
|
|
|
1341
1806
|
if nav_required:
|
|
1342
1807
|
project_slug = plan.get("project_name") or "web-project"
|
|
@@ -2332,7 +2797,7 @@ class SmartWebAgent:
|
|
|
2332
2797
|
# 最后一步:按工具白名单过滤参数,剔除 description/rationale 等无关键
|
|
2333
2798
|
allowed = {
|
|
2334
2799
|
"create_project_structure": {"project_name", "project_path"},
|
|
2335
|
-
"create_html_file": {"file_path", "title", "content"},
|
|
2800
|
+
"create_html_file": {"file_path", "title", "content", "style", "sections"},
|
|
2336
2801
|
"create_css_file": {"file_path", "content"},
|
|
2337
2802
|
"create_js_file": {"file_path", "content"},
|
|
2338
2803
|
"add_bootstrap": {"project_path"},
|
|
@@ -2388,6 +2853,11 @@ class SmartWebAgent:
|
|
|
2388
2853
|
@click.option("--verbose", is_flag=True, help="显示详细执行信息")
|
|
2389
2854
|
@click.option("--save-output", is_flag=True, help="保存所有生成的内容到日志文件")
|
|
2390
2855
|
@click.option("--stream", is_flag=True, help="启用流式输出显示AI思考过程")
|
|
2856
|
+
@click.option(
|
|
2857
|
+
"--single-page/--multi-page",
|
|
2858
|
+
default=True,
|
|
2859
|
+
help="强制生成单页面滚动站点;如需保留多页面流程可切换为 --multi-page",
|
|
2860
|
+
)
|
|
2391
2861
|
def main(
|
|
2392
2862
|
project_directory,
|
|
2393
2863
|
model,
|
|
@@ -2398,6 +2868,7 @@ def main(
|
|
|
2398
2868
|
verbose,
|
|
2399
2869
|
save_output,
|
|
2400
2870
|
stream,
|
|
2871
|
+
single_page,
|
|
2401
2872
|
):
|
|
2402
2873
|
"""
|
|
2403
2874
|
🧠 智能批量Web Agent - 2025年最佳实践
|
|
@@ -2425,6 +2896,7 @@ def main(
|
|
|
2425
2896
|
verbose=verbose,
|
|
2426
2897
|
show_plan_stream=stream,
|
|
2427
2898
|
save_output=save_output,
|
|
2899
|
+
force_single_page=single_page,
|
|
2428
2900
|
)
|
|
2429
2901
|
|
|
2430
2902
|
print("🧠 智能批量Web Agent启动!")
|