XMWAI 0.3.1__py3-none-any.whl → 0.3.2__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 XMWAI might be problematic. Click here for more details.
- XMWAI/__init__.py +2 -2
- XMWAI/templates/nutrition_pie.html +186 -0
- XMWAI/templates//321/205/320/230/320/253/321/206/320/224/320/237/321/210/320/237/320/254/321/210/342/226/221/342/226/222.html +60 -0
- XMWAI/web_core.py +213 -0
- XMWAI/xmw_photo/bg.jpeg +0 -0
- {xmwai-0.3.1.dist-info → xmwai-0.3.2.dist-info}/METADATA +2 -1
- {xmwai-0.3.1.dist-info → xmwai-0.3.2.dist-info}/RECORD +10 -8
- XMWAI/cookbook_core.py +0 -148
- {xmwai-0.3.1.dist-info → xmwai-0.3.2.dist-info}/WHEEL +0 -0
- {xmwai-0.3.1.dist-info → xmwai-0.3.2.dist-info}/licenses/LICENSE.txt +0 -0
- {xmwai-0.3.1.dist-info → xmwai-0.3.2.dist-info}/top_level.txt +0 -0
XMWAI/__init__.py
CHANGED
|
@@ -3,9 +3,9 @@ from .magic_core import birthday # 从子模块导入函数到顶层
|
|
|
3
3
|
from .bomb_core import bomb # 从子模块导入函数到顶层
|
|
4
4
|
from .idiom_core import idiom, searchIdiom, get_json_path # 从子模块导入函数到顶层
|
|
5
5
|
from .trial_class import make, get_file_content_as_base64, save_pic, detect_windows_scale, get_file_content_as_base64_2, cartoon # 从子模块导入函数到顶层
|
|
6
|
-
from .web_core import burger # 从子模块导入函数到顶层
|
|
6
|
+
from .web_core import burger, cookbook # 从子模块导入函数到顶层
|
|
7
7
|
|
|
8
8
|
__all__ = ["story", "photo", "reply", "poem", 'birthday', 'bomb',
|
|
9
9
|
"idiom", "searchIdiom", "get_json_path", "crack",
|
|
10
10
|
"make", "get_file_content_as_base64", "save_pic", "detect_windows_scale",
|
|
11
|
-
"get_file_content_as_base64_2", "cartoon", "burger"] # 可选:明确导出的内容
|
|
11
|
+
"get_file_content_as_base64_2", "cartoon", "burger", "cookbook"] # 可选:明确导出的内容
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Awesome-pyecharts</title>
|
|
6
|
+
<script type="text/javascript" src="https://assets.pyecharts.org/assets/v5/echarts.min.js"></script>
|
|
7
|
+
|
|
8
|
+
</head>
|
|
9
|
+
<body >
|
|
10
|
+
<div id="445b48e3071c494088a3b3494b4d73f3" class="chart-container" style="width:1100px; height:500px; "></div>
|
|
11
|
+
<script>
|
|
12
|
+
var chart_445b48e3071c494088a3b3494b4d73f3 = echarts.init(
|
|
13
|
+
document.getElementById('445b48e3071c494088a3b3494b4d73f3'), 'white', {renderer: 'canvas'});
|
|
14
|
+
var option_445b48e3071c494088a3b3494b4d73f3 = {
|
|
15
|
+
"animation": true,
|
|
16
|
+
"animationThreshold": 2000,
|
|
17
|
+
"animationDuration": 1000,
|
|
18
|
+
"animationEasing": "cubicOut",
|
|
19
|
+
"animationDelay": 0,
|
|
20
|
+
"animationDurationUpdate": 300,
|
|
21
|
+
"animationEasingUpdate": "cubicOut",
|
|
22
|
+
"animationDelayUpdate": 0,
|
|
23
|
+
"aria": {
|
|
24
|
+
"enabled": false
|
|
25
|
+
},
|
|
26
|
+
"color": [
|
|
27
|
+
"#5470c6",
|
|
28
|
+
"#91cc75",
|
|
29
|
+
"#fac858",
|
|
30
|
+
"#ee6666",
|
|
31
|
+
"#73c0de",
|
|
32
|
+
"#3ba272",
|
|
33
|
+
"#fc8452",
|
|
34
|
+
"#9a60b4",
|
|
35
|
+
"#ea7ccc"
|
|
36
|
+
],
|
|
37
|
+
"series": [
|
|
38
|
+
{
|
|
39
|
+
"type": "pie",
|
|
40
|
+
"colorBy": "data",
|
|
41
|
+
"legendHoverLink": true,
|
|
42
|
+
"selectedMode": false,
|
|
43
|
+
"selectedOffset": 10,
|
|
44
|
+
"clockwise": true,
|
|
45
|
+
"startAngle": 90,
|
|
46
|
+
"minAngle": 0,
|
|
47
|
+
"minShowLabelAngle": 0,
|
|
48
|
+
"avoidLabelOverlap": true,
|
|
49
|
+
"stillShowZeroSum": true,
|
|
50
|
+
"percentPrecision": 2,
|
|
51
|
+
"showEmptyCircle": true,
|
|
52
|
+
"emptyCircleStyle": {
|
|
53
|
+
"color": "lightgray",
|
|
54
|
+
"borderColor": "#000",
|
|
55
|
+
"borderWidth": 0,
|
|
56
|
+
"borderType": "solid",
|
|
57
|
+
"borderDashOffset": 0,
|
|
58
|
+
"borderCap": "butt",
|
|
59
|
+
"borderJoin": "bevel",
|
|
60
|
+
"borderMiterLimit": 10,
|
|
61
|
+
"opacity": 1
|
|
62
|
+
},
|
|
63
|
+
"data": [
|
|
64
|
+
{
|
|
65
|
+
"name": "\u86cb\u767d\u8d28",
|
|
66
|
+
"value": 28.5
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "\u8102\u80aa",
|
|
70
|
+
"value": 18.2
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"name": "\u78b3\u6c34\u5316\u5408\u7269",
|
|
74
|
+
"value": 42.3
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "\u7ef4\u751f\u7d20",
|
|
78
|
+
"value": 6.0
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"name": "\u77ff\u7269\u8d28",
|
|
82
|
+
"value": 3.2
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
"radius": [
|
|
86
|
+
"0%",
|
|
87
|
+
"75%"
|
|
88
|
+
],
|
|
89
|
+
"center": [
|
|
90
|
+
"50%",
|
|
91
|
+
"50%"
|
|
92
|
+
],
|
|
93
|
+
"label": {
|
|
94
|
+
"show": true,
|
|
95
|
+
"margin": 8,
|
|
96
|
+
"formatter": "{b}: {c}"
|
|
97
|
+
},
|
|
98
|
+
"labelLine": {
|
|
99
|
+
"show": true,
|
|
100
|
+
"showAbove": false,
|
|
101
|
+
"length": 15,
|
|
102
|
+
"length2": 15,
|
|
103
|
+
"smooth": false,
|
|
104
|
+
"minTurnAngle": 90,
|
|
105
|
+
"maxSurfaceAngle": 90
|
|
106
|
+
},
|
|
107
|
+
"rippleEffect": {
|
|
108
|
+
"show": true,
|
|
109
|
+
"brushType": "stroke",
|
|
110
|
+
"scale": 2.5,
|
|
111
|
+
"period": 4
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
"legend": [
|
|
116
|
+
{
|
|
117
|
+
"data": [
|
|
118
|
+
"\u86cb\u767d\u8d28",
|
|
119
|
+
"\u8102\u80aa",
|
|
120
|
+
"\u78b3\u6c34\u5316\u5408\u7269",
|
|
121
|
+
"\u7ef4\u751f\u7d20",
|
|
122
|
+
"\u77ff\u7269\u8d28"
|
|
123
|
+
],
|
|
124
|
+
"selected": {},
|
|
125
|
+
"show": true,
|
|
126
|
+
"padding": 5,
|
|
127
|
+
"itemGap": 10,
|
|
128
|
+
"itemWidth": 25,
|
|
129
|
+
"itemHeight": 14,
|
|
130
|
+
"backgroundColor": "transparent",
|
|
131
|
+
"borderColor": "#ccc",
|
|
132
|
+
"borderWidth": 1,
|
|
133
|
+
"borderRadius": 0,
|
|
134
|
+
"pageButtonItemGap": 5,
|
|
135
|
+
"pageButtonPosition": "end",
|
|
136
|
+
"pageFormatter": "{current}/{total}",
|
|
137
|
+
"pageIconColor": "#2f4554",
|
|
138
|
+
"pageIconInactiveColor": "#aaa",
|
|
139
|
+
"pageIconSize": 15,
|
|
140
|
+
"animationDurationUpdate": 800,
|
|
141
|
+
"selector": false,
|
|
142
|
+
"selectorPosition": "auto",
|
|
143
|
+
"selectorItemGap": 7,
|
|
144
|
+
"selectorButtonGap": 10
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
"tooltip": {
|
|
148
|
+
"show": true,
|
|
149
|
+
"trigger": "item",
|
|
150
|
+
"triggerOn": "mousemove|click",
|
|
151
|
+
"axisPointer": {
|
|
152
|
+
"type": "line"
|
|
153
|
+
},
|
|
154
|
+
"showContent": true,
|
|
155
|
+
"alwaysShowContent": false,
|
|
156
|
+
"showDelay": 0,
|
|
157
|
+
"hideDelay": 100,
|
|
158
|
+
"enterable": false,
|
|
159
|
+
"confine": false,
|
|
160
|
+
"appendToBody": false,
|
|
161
|
+
"transitionDuration": 0.4,
|
|
162
|
+
"textStyle": {
|
|
163
|
+
"fontSize": 14
|
|
164
|
+
},
|
|
165
|
+
"borderWidth": 0,
|
|
166
|
+
"padding": 5,
|
|
167
|
+
"order": "seriesAsc"
|
|
168
|
+
},
|
|
169
|
+
"title": [
|
|
170
|
+
{
|
|
171
|
+
"show": true,
|
|
172
|
+
"text": "\u8425\u517b\u4ef7\u503c\u5206\u5e03",
|
|
173
|
+
"target": "blank",
|
|
174
|
+
"subtarget": "blank",
|
|
175
|
+
"padding": 5,
|
|
176
|
+
"itemGap": 10,
|
|
177
|
+
"textAlign": "auto",
|
|
178
|
+
"textVerticalAlign": "auto",
|
|
179
|
+
"triggerEvent": false
|
|
180
|
+
}
|
|
181
|
+
]
|
|
182
|
+
};
|
|
183
|
+
chart_445b48e3071c494088a3b3494b4d73f3.setOption(option_445b48e3071c494088a3b3494b4d73f3);
|
|
184
|
+
</script>
|
|
185
|
+
</body>
|
|
186
|
+
</html>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
|
|
2
|
+
<!DOCTYPE html>
|
|
3
|
+
<html lang="zh">
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<title>创意菜谱</title>
|
|
7
|
+
<style>
|
|
8
|
+
html, body { margin:0; padding:0; width:100%; height:100%; overflow-x:hidden; }
|
|
9
|
+
body { font-family:"微软雅黑",sans-serif; background:#2c2c2c url('bg.jpeg') no-repeat center center fixed; background-size:cover; color:#333; }
|
|
10
|
+
.container { max-width:1200px; margin:30px auto; background:rgba(255,248,220,0.95); border-radius:15px; padding:30px; box-shadow:0 0 20px rgba(0,0,0,0.2); }
|
|
11
|
+
.banner { width:100%; height:220px; background:url('bg.jpeg') center/cover no-repeat; border-radius:15px 15px 0 0; display:flex; align-items:center; justify-content:center; }
|
|
12
|
+
.banner h1 { color:#fff; font-size:28px; text-shadow:1px 1px 3px #666; }
|
|
13
|
+
p { font-size:18px; margin:8px 0; }
|
|
14
|
+
.step-card { background:#fff0b3; margin:10px 0; border-radius:12px; overflow:hidden; opacity:0; transform:translateY(20px) scale(0.98); animation:fadeInUp 0.6s forwards; }
|
|
15
|
+
.step-title { font-weight:bold; padding:10px 15px; cursor:pointer; background:#ffb347; color:#fff; border-bottom:1px solid #ffd27f; }
|
|
16
|
+
.step-content { padding:10px 15px; display:block; font-size:16px; opacity:0; max-height:0; overflow:hidden; transition: opacity 0.4s ease, max-height 0.4s ease; }
|
|
17
|
+
.step-card.hover .step-content { opacity:1; max-height:800px; }
|
|
18
|
+
iframe { width:100%; height:500px; border:none; margin-top:20px; }
|
|
19
|
+
@keyframes fadeInUp { to { opacity:1; transform:translateY(0) scale(1); } }
|
|
20
|
+
</style>
|
|
21
|
+
</head>
|
|
22
|
+
<body>
|
|
23
|
+
<div class="container">
|
|
24
|
+
<div class="banner"><h1>🍽 羊肉炸香蕉</h1></div>
|
|
25
|
+
<p>🍖 <strong>主菜:</strong>羊肉</p>
|
|
26
|
+
<p>🥗 <strong>配菜:</strong>🍌 香蕉</p>
|
|
27
|
+
<p>👩🍳 <strong>做法:</strong>🍟 炸</p>
|
|
28
|
+
|
|
29
|
+
<div class="step-card" style="animation-delay:0.2s;">
|
|
30
|
+
<div class="step-title">Step 1 📝 食材搭配的营养价值</div>
|
|
31
|
+
<div class="step-content">根据食材搭配生成的营养价值饼图如下 ⬇️</div>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div class="step-card" style="animation-delay:0.4s;">
|
|
35
|
+
<div class="step-title">Step 2 📝 创意灵感</div>
|
|
36
|
+
<div class="step-content">这道创意菜灵感来源于食材的碰撞实验,将传统咸香风味的羊肉与热带水果的清甜进行融合,通过高温油🍟 炸形成外酥里嫩的口感反差。🍌 香蕉经过🍟 炸制后会产生焦糖化反应,其绵密质地与羊肉的纤维感形成层次对比,搭配特制香料粉激发出东南亚风情的味觉体验,突破常规肉类与水果的搭配边界。</div>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<div class="step-card" style="animation-delay:0.6000000000000001s;">
|
|
40
|
+
<div class="step-title">Step 3 📝 食材清单</div>
|
|
41
|
+
<div class="step-content">主料:羊腿肉300克(🔪 切1.5cm立方块)<br>配菜:成熟🍌 香蕉2根(🔪 切1cm厚片)<br>裹粉:🌽 玉米淀粉50克、🍗 🥚 鸡蛋1个、🍞 面包糠80克<br>调味料:辣椒粉3克、孜然粉5克、蒜粉2克、盐4克、黑胡椒碎2克<br>辅料:食用油500毫升(实耗约80毫升)<br>装饰:新鲜薄荷叶5片、柠檬角2个</div>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div class="step-card" style="animation-delay:0.8s;">
|
|
45
|
+
<div class="step-title">Step 4 📝 制作步骤</div>
|
|
46
|
+
<div class="step-content">1 预处理:羊肉块用2克盐、1克黑胡椒、蒜粉🫙 腌制15分钟;🍌 香蕉片裹薄层🌽 玉米淀粉备用<br>2 调制裹粉:🍗 🥚 鸡蛋打散与剩余🌽 玉米淀粉混合成蛋糊,🍞 面包糠与辣椒粉、孜然粉、2克盐、1克黑胡椒混合<br>3 双阶段🍟 炸制:<br>- 羊肉块先蘸蛋糊再裹香料🍞 面包糠,160℃油温初🍟 炸3分钟定型<br>- 🍌 香蕉片直接裹香料🍞 面包糠,180℃油温速🍟 炸1分钟至金黄<br>4 复🍟 炸提脆:羊肉块200℃高温复🍟 炸1分钟至外壳酥脆<br>5 装盘艺术:羊肉与🍌 香蕉片间隔堆叠,撒剩余香料粉,配薄荷叶与柠檬角</div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<iframe src="nutrition_pie.html"></iframe>
|
|
50
|
+
</div>
|
|
51
|
+
<script>
|
|
52
|
+
const steps = document.querySelectorAll('.step-card');
|
|
53
|
+
steps.forEach(card => {
|
|
54
|
+
card.addEventListener('mouseenter', () => { card.classList.add('hover'); });
|
|
55
|
+
card.addEventListener('mouseleave', () => { card.classList.remove('hover'); });
|
|
56
|
+
});
|
|
57
|
+
</script>
|
|
58
|
+
</body>
|
|
59
|
+
</html>
|
|
60
|
+
|
XMWAI/web_core.py
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import json
|
|
3
|
+
import requests
|
|
2
4
|
from flask import Flask, render_template
|
|
5
|
+
import re
|
|
6
|
+
from pyecharts import options as opts
|
|
7
|
+
from pyecharts.charts import Pie
|
|
3
8
|
import webbrowser
|
|
4
9
|
import threading
|
|
5
10
|
import time
|
|
11
|
+
from importlib.resources import files
|
|
12
|
+
from pathlib import Path
|
|
6
13
|
|
|
7
14
|
|
|
8
15
|
'''Super堡'''
|
|
@@ -67,3 +74,209 @@ def start_server(port=5050):
|
|
|
67
74
|
server_thread.join()
|
|
68
75
|
except KeyboardInterrupt:
|
|
69
76
|
pass
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
'''Random料理屋'''
|
|
80
|
+
# 食材对应 emoji
|
|
81
|
+
emoji_dict = {
|
|
82
|
+
"鸡": "🍗", "牛": "🥩", "猪": "🥓", "鱼": "🐟", "虾": "🦐", "蟹": "🦀",
|
|
83
|
+
"豆腐": "🧈", "土豆": "🥔", "胡萝卜": "🥕", "西红柿": "🍅", "青菜": "🥬",
|
|
84
|
+
"菠菜": "🥬", "蘑菇": "🍄", "玉米": "🌽", "米饭": "🍚", "面条": "🍜",
|
|
85
|
+
"面包": "🍞", "奶酪": "🧀", "鸡蛋": "🥚", "牛奶": "🥛", "橙子": "🍊",
|
|
86
|
+
"苹果": "🍎", "香蕉": "🍌"
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
# 动作对应 emoji
|
|
90
|
+
action_dict = {
|
|
91
|
+
"炒": "🍳", "煮": "🍲", "烤": "🔥", "蒸": "♨️", "炸": "🍟", "拌": "🥣",
|
|
92
|
+
"切": "🔪", "腌": "🫙", "炖": "🥘"
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def add_emoji_to_text(text):
|
|
97
|
+
for key, val in action_dict.items():
|
|
98
|
+
text = re.sub(f'({key})', f'{val} \\1', text)
|
|
99
|
+
for key, val in emoji_dict.items():
|
|
100
|
+
text = re.sub(f'({key})', f'{val} \\1', text)
|
|
101
|
+
return text
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def format_section_steps(text):
|
|
105
|
+
lines = [line.strip() for line in text.strip().split("\n") if line.strip()]
|
|
106
|
+
lines = lines[:50]
|
|
107
|
+
return "<br>".join(add_emoji_to_text(line) for line in lines)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def parse_nutrition_section(text):
|
|
111
|
+
"""解析 API 返回的营养 JSON 并提取数值"""
|
|
112
|
+
default_data = {"蛋白质": 30, "脂肪": 20, "碳水化合物": 50, "维生素": 10, "矿物质": 5}
|
|
113
|
+
|
|
114
|
+
def extract_number(val):
|
|
115
|
+
if isinstance(val, (int, float)):
|
|
116
|
+
return val
|
|
117
|
+
if isinstance(val, str):
|
|
118
|
+
match = re.search(r"(\d+(\.\d+)?)", val)
|
|
119
|
+
if match:
|
|
120
|
+
return float(match.group(1))
|
|
121
|
+
return 0
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
match = re.search(r"\{.*\}", text, re.S)
|
|
125
|
+
if match:
|
|
126
|
+
parsed = json.loads(match.group())
|
|
127
|
+
result = {}
|
|
128
|
+
for key in default_data.keys():
|
|
129
|
+
if key in parsed:
|
|
130
|
+
val = parsed[key]
|
|
131
|
+
if isinstance(val, dict):
|
|
132
|
+
total = sum(extract_number(v) for v in val.values())
|
|
133
|
+
result[key] = total
|
|
134
|
+
else:
|
|
135
|
+
result[key] = extract_number(val)
|
|
136
|
+
else:
|
|
137
|
+
result[key] = default_data[key]
|
|
138
|
+
return result
|
|
139
|
+
except Exception as e:
|
|
140
|
+
print("JSON解析失败:", e)
|
|
141
|
+
return default_data
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def generate_pie_chart(data_dict, filename: Path):
|
|
145
|
+
data = [(k, v) for k, v in data_dict.items()]
|
|
146
|
+
pie = (
|
|
147
|
+
Pie(init_opts=opts.InitOpts(width="1100px", height="500px"))
|
|
148
|
+
.add("", data)
|
|
149
|
+
.set_global_opts(title_opts=opts.TitleOpts(title="营养价值分布"))
|
|
150
|
+
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
|
|
151
|
+
)
|
|
152
|
+
pie.render(str(filename))
|
|
153
|
+
return filename
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def cookbook(m, t, s, key):
|
|
157
|
+
if key != "CaJQ":
|
|
158
|
+
return "密钥错误,无法生成食谱。"
|
|
159
|
+
|
|
160
|
+
# 调用 API 生成创意菜谱
|
|
161
|
+
messagesList = [
|
|
162
|
+
{"role": "system", "content": "天马行空的创意菜厨师"},
|
|
163
|
+
{"role": "user", "content": f"请以{m}为主菜,{s}为配菜,{t}为烹饪方式写一个创意食谱,"
|
|
164
|
+
"结果中不要*,并且结果只需要创意灵感、食材清单、制作步骤、"
|
|
165
|
+
"食材搭配的营养价值四种大标题内容。食材搭配的营养价值部分请输出标准 JSON,"
|
|
166
|
+
"键为蛋白质、脂肪、碳水化合物、维生素、矿物质,值为数值及说明。"}
|
|
167
|
+
]
|
|
168
|
+
|
|
169
|
+
url = "https://qianfan.baidubce.com/v2/chat/completions"
|
|
170
|
+
payload = json.dumps({"model": "ernie-4.5-turbo-32k",
|
|
171
|
+
"messages": messagesList}, ensure_ascii=False)
|
|
172
|
+
headers = {
|
|
173
|
+
"Content-Type": "application/json",
|
|
174
|
+
"appid": "",
|
|
175
|
+
"Authorization": "Bearer bce-v3/ALTAK-cGbxpVA5AbSz6h8nbLaFh/b539762075d55c76d93dc78bcf0a91beeaf0490a"
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
try:
|
|
179
|
+
response = requests.post(url, headers=headers,
|
|
180
|
+
data=payload.encode("utf-8"))
|
|
181
|
+
response_data = response.json()
|
|
182
|
+
content = response_data["choices"][0]["message"]["content"]
|
|
183
|
+
except Exception as e:
|
|
184
|
+
return f"接口调用失败:{e}"
|
|
185
|
+
|
|
186
|
+
# 分割内容
|
|
187
|
+
sections = re.split(r"(创意灵感|食材清单|制作步骤|食材搭配的营养价值)", content)
|
|
188
|
+
body_sections = [""]*4
|
|
189
|
+
title_map = {"创意灵感": 0, "食材清单": 1, "制作步骤": 2, "食材搭配的营养价值": 3}
|
|
190
|
+
i = 1
|
|
191
|
+
while i < len(sections):
|
|
192
|
+
header = sections[i]
|
|
193
|
+
text_sec = sections[i+1] if i+1 < len(sections) else ""
|
|
194
|
+
idx = title_map.get(header.strip(), None)
|
|
195
|
+
if idx is not None:
|
|
196
|
+
body_sections[idx] = text_sec.strip()
|
|
197
|
+
i += 2
|
|
198
|
+
|
|
199
|
+
# 获取包内模板和图片目录
|
|
200
|
+
templates_dir = Path(files("XMWAI").joinpath("templates"))
|
|
201
|
+
templates_dir.mkdir(exist_ok=True)
|
|
202
|
+
photo_dir = Path(files("XMWAI").joinpath("xmw_photo"))
|
|
203
|
+
|
|
204
|
+
# 生成饼图文件
|
|
205
|
+
pie_chart_file = templates_dir / "nutrition_pie.html"
|
|
206
|
+
nutrient_data = parse_nutrition_section(body_sections[3])
|
|
207
|
+
generate_pie_chart(nutrient_data, pie_chart_file)
|
|
208
|
+
|
|
209
|
+
# 添加 emoji
|
|
210
|
+
m_emoji = add_emoji_to_text(m)
|
|
211
|
+
s_emoji = add_emoji_to_text(s)
|
|
212
|
+
t_emoji = add_emoji_to_text(t)
|
|
213
|
+
|
|
214
|
+
# 步骤顺序 HTML
|
|
215
|
+
step_titles = ["食材搭配的营养价值", "创意灵感", "食材清单", "制作步骤"]
|
|
216
|
+
steps_order = [3, 0, 1, 2]
|
|
217
|
+
steps_html = ""
|
|
218
|
+
for i, idx in enumerate(steps_order):
|
|
219
|
+
if idx == 3:
|
|
220
|
+
section_content_html = "根据食材搭配生成的营养价值饼图如下 ⬇️"
|
|
221
|
+
else:
|
|
222
|
+
section_content_html = format_section_steps(body_sections[idx])
|
|
223
|
+
steps_html += f"""
|
|
224
|
+
<div class="step-card" style="animation-delay:{(i+1)*0.2}s;">
|
|
225
|
+
<div class="step-title">Step {i+1} 📝 {step_titles[i]}</div>
|
|
226
|
+
<div class="step-content">{section_content_html}</div>
|
|
227
|
+
</div>
|
|
228
|
+
"""
|
|
229
|
+
|
|
230
|
+
# HTML 页面
|
|
231
|
+
bg_path = photo_dir / "bg.jpeg"
|
|
232
|
+
html = f"""
|
|
233
|
+
<!DOCTYPE html>
|
|
234
|
+
<html lang="zh">
|
|
235
|
+
<head>
|
|
236
|
+
<meta charset="UTF-8">
|
|
237
|
+
<title>创意菜谱</title>
|
|
238
|
+
<style>
|
|
239
|
+
html, body {{ margin:0; padding:0; width:100%; height:100%; overflow-x:hidden; }}
|
|
240
|
+
body {{ font-family:"微软雅黑",sans-serif; background:#2c2c2c url('{bg_path.resolve()}') no-repeat center center fixed; background-size:cover; color:#333; }}
|
|
241
|
+
.container {{ max-width:1200px; margin:30px auto; background:rgba(255,248,220,0.95); border-radius:15px; padding:30px; box-shadow:0 0 20px rgba(0,0,0,0.2); }}
|
|
242
|
+
.banner {{ width:100%; height:220px; background:url('{bg_path.resolve()}') center/cover no-repeat; border-radius:15px 15px 0 0; display:flex; align-items:center; justify-content:center; }}
|
|
243
|
+
.banner h1 {{ color:#fff; font-size:28px; text-shadow:1px 1px 3px #666; }}
|
|
244
|
+
p {{ font-size:18px; margin:8px 0; }}
|
|
245
|
+
.step-card {{ background:#fff0b3; margin:10px 0; border-radius:12px; overflow:hidden; opacity:0; transform:translateY(20px) scale(0.98); animation:fadeInUp 0.6s forwards; }}
|
|
246
|
+
.step-title {{ font-weight:bold; padding:10px 15px; cursor:pointer; background:#ffb347; color:#fff; border-bottom:1px solid #ffd27f; }}
|
|
247
|
+
.step-content {{ padding:10px 15px; display:block; font-size:16px; opacity:0; max-height:0; overflow:hidden; transition: opacity 0.4s ease, max-height 0.4s ease; }}
|
|
248
|
+
.step-card.hover .step-content {{ opacity:1; max-height:800px; }}
|
|
249
|
+
iframe {{ width:100%; height:500px; border:none; margin-top:20px; }}
|
|
250
|
+
@keyframes fadeInUp {{ to {{ opacity:1; transform:translateY(0) scale(1); }} }}
|
|
251
|
+
</style>
|
|
252
|
+
</head>
|
|
253
|
+
<body>
|
|
254
|
+
<div class="container">
|
|
255
|
+
<div class="banner"><h1>🍽 {m+t+s}</h1></div>
|
|
256
|
+
<p>🍖 <strong>主菜:</strong>{m_emoji}</p>
|
|
257
|
+
<p>🥗 <strong>配菜:</strong>{s_emoji}</p>
|
|
258
|
+
<p>👩🍳 <strong>做法:</strong>{t_emoji}</p>
|
|
259
|
+
{steps_html}
|
|
260
|
+
<iframe src="{pie_chart_file.resolve()}"></iframe>
|
|
261
|
+
</div>
|
|
262
|
+
<script>
|
|
263
|
+
const steps = document.querySelectorAll('.step-card');
|
|
264
|
+
steps.forEach(card => {{
|
|
265
|
+
card.addEventListener('mouseenter', () => {{ card.classList.add('hover'); }});
|
|
266
|
+
card.addEventListener('mouseleave', () => {{ card.classList.remove('hover'); }});
|
|
267
|
+
}});
|
|
268
|
+
</script>
|
|
269
|
+
</body>
|
|
270
|
+
</html>
|
|
271
|
+
"""
|
|
272
|
+
|
|
273
|
+
# 保存 HTML 文件到包内 templates
|
|
274
|
+
safe_title = re.sub(r'[\/\\:*?"<>|]', "", m+t+s)
|
|
275
|
+
html_file = templates_dir / f"{safe_title}_菜谱.html"
|
|
276
|
+
with open(html_file, "w", encoding="utf-8") as f:
|
|
277
|
+
f.write(html)
|
|
278
|
+
|
|
279
|
+
# 打开浏览器
|
|
280
|
+
webbrowser.open(f"file://{html_file.resolve()}")
|
|
281
|
+
|
|
282
|
+
return content
|
XMWAI/xmw_photo/bg.jpeg
ADDED
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: XMWAI
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Small code King AI related library
|
|
5
5
|
Home-page: https://github.com/Tonykai88/XMWAI.git
|
|
6
6
|
Author: pydevelopment
|
|
@@ -16,6 +16,7 @@ Requires-Dist: Pillow>=11.1.0
|
|
|
16
16
|
Requires-Dist: opencv-python>=3.4.18.65
|
|
17
17
|
Requires-Dist: numpy>=1.26.0
|
|
18
18
|
Requires-Dist: flask>=3.1.0
|
|
19
|
+
Requires-Dist: pyecharts>=2.0.8
|
|
19
20
|
Dynamic: author
|
|
20
21
|
Dynamic: author-email
|
|
21
22
|
Dynamic: classifier
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
XMWAI/__init__.py,sha256=
|
|
1
|
+
XMWAI/__init__.py,sha256=69tPF0KjWUGjkOOUxytGpipUu9jGuYSJgiyn1lYo0uY,894
|
|
2
2
|
XMWAI/bomb_core.py,sha256=h2ZPH3SuoG2L_XOf1dcK8p3lhw5QzhneWl2yMLj1RiU,1819
|
|
3
|
-
XMWAI/cookbook_core.py,sha256=mo3IYgh_bYD_3vH2Stkjwo9okFOb4abooZeJ-Djx6VU,3675
|
|
4
3
|
XMWAI/core.py,sha256=SxzfbOW7WZALuA5fQ4dGieJR2-roxufjXQ_mqwGDg3E,7905
|
|
5
4
|
XMWAI/idiom_core.py,sha256=yU-VHhqqoutVm6GVikcjL3m9yuB1hUsFBpPYvwY4n5g,1689
|
|
6
5
|
XMWAI/magic_core.py,sha256=Ms4b12PJ8rjsmceg1VUqWCWx2ebvdhLp4sIF6K_Vaok,3491
|
|
7
6
|
XMWAI/trial_class.py,sha256=GRDEe24a-DYMRyoTLgJbE5dCSQY0CbYqB5ALsBfYmtA,10226
|
|
8
|
-
XMWAI/web_core.py,sha256=
|
|
7
|
+
XMWAI/web_core.py,sha256=Get1cm_rGSJlRoNXLSkMxLBSnC-AXkJ9XzViTDmpqSM,10771
|
|
9
8
|
XMWAI/file/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
9
|
XMWAI/file/idiom.json,sha256=HUtPRUzhxBbWoasjadbmbA_5ngQ5AXLu9weQSZ4hzhk,10319857
|
|
11
10
|
XMWAI/gif/0.gif,sha256=LGpAReVTyZEb1J-bWYTpxxHbIxmLJ-3wA0lw4cBqdsY,303
|
|
@@ -105,8 +104,11 @@ XMWAI/static/images/lettuce.png,sha256=ngj3nQe9Zqv-GfXpooaD0g0QtLW1cwC_7TwXSoaff
|
|
|
105
104
|
XMWAI/static/images/sauce.png,sha256=w3Nt3TXSibPAlosvnKYbD61BEtV69UQPupfawTUNQ7Y,4906
|
|
106
105
|
XMWAI/static/images/tomato.png,sha256=FEOEAOdUhW_BDFgTpxOkYc0I5Iu29_gtHb3RIPEej0Y,4254
|
|
107
106
|
XMWAI/templates/burger.html,sha256=vDnxpSW8phetyScySsalScZnFKl3LNpy5lJjKxGXgbI,3320
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
xmwai-0.3.
|
|
112
|
-
xmwai-0.3.
|
|
107
|
+
XMWAI/templates/nutrition_pie.html,sha256=yJVXI28i-UfvF0xOXGSNLMb8oCJNhh2J3zoRDr5_7DM,5567
|
|
108
|
+
XMWAI/templates/创意菜谱.html,sha256=RcDgH58QLyUJ9A59wobu3wvchGBY1snVsXcZQZam5M0,4805
|
|
109
|
+
XMWAI/xmw_photo/bg.jpeg,sha256=pYLeliPNhHQp7JlLRbVpz-v_MPs02n9rFrvH1Uxps6s,81475
|
|
110
|
+
xmwai-0.3.2.dist-info/licenses/LICENSE.txt,sha256=bcaIQMrIhdQ3O-PoZlexjmW6h-wLGvHxh5Oksl4ohtc,1066
|
|
111
|
+
xmwai-0.3.2.dist-info/METADATA,sha256=qOYGlM6zurzuS3ZYPJnEERGY_vc6t84ERAAnQHVrZD0,1197
|
|
112
|
+
xmwai-0.3.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
113
|
+
xmwai-0.3.2.dist-info/top_level.txt,sha256=yvGcDI-sggK5jqd9wz0saipZvk3oIE3hNGHlqUjxf0c,6
|
|
114
|
+
xmwai-0.3.2.dist-info/RECORD,,
|
XMWAI/cookbook_core.py
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import requests
|
|
2
|
-
import json
|
|
3
|
-
import webbrowser
|
|
4
|
-
import re
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def cookbook(m, t, s, key):
|
|
8
|
-
if key != "CaJQ":
|
|
9
|
-
return "密钥错误,无法生成食谱。"
|
|
10
|
-
|
|
11
|
-
messagesList = [
|
|
12
|
-
{
|
|
13
|
-
"role": "system",
|
|
14
|
-
"content": "天马行空的创意菜厨师"
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
"role": "user",
|
|
18
|
-
"content": f"请以{m}为主菜,{s}为配菜,{t}为烹饪方式写一个创意食谱,结果中不要*"
|
|
19
|
-
}
|
|
20
|
-
]
|
|
21
|
-
|
|
22
|
-
url = "https://qianfan.baidubce.com/v2/chat/completions"
|
|
23
|
-
payload = json.dumps({
|
|
24
|
-
"model": "ernie-4.5-turbo-32k",
|
|
25
|
-
"messages": messagesList
|
|
26
|
-
}, ensure_ascii=False)
|
|
27
|
-
|
|
28
|
-
headers = {
|
|
29
|
-
'Content-Type': 'application/json',
|
|
30
|
-
'appid': '',
|
|
31
|
-
'Authorization': 'Bearer bce-v3/ALTAK-cGbxpVA5AbSz6h8nbLaFh/b539762075d55c76d93dc78bcf0a91beeaf0490a'
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
try:
|
|
35
|
-
response = requests.post(url, headers=headers, data=payload.encode("utf-8"))
|
|
36
|
-
response_data = json.loads(response.text)
|
|
37
|
-
content = response_data["choices"][0]["message"]["content"]
|
|
38
|
-
except Exception as e:
|
|
39
|
-
return f"接口调用失败:{e}"
|
|
40
|
-
|
|
41
|
-
# 提取标题和正文(防止 IndexError)
|
|
42
|
-
lines = content.strip().split("\n")
|
|
43
|
-
title = lines[0] if len(lines) >= 1 else "创意菜谱"
|
|
44
|
-
content_body = "\n".join(lines[1:]) if len(lines) >= 2 else "(无正文内容)"
|
|
45
|
-
|
|
46
|
-
# 构造 HTML
|
|
47
|
-
html = f"""
|
|
48
|
-
<!DOCTYPE html>
|
|
49
|
-
<html lang="zh">
|
|
50
|
-
<head>
|
|
51
|
-
<meta charset="UTF-8">
|
|
52
|
-
<title>{title}</title>
|
|
53
|
-
<style>
|
|
54
|
-
body {{
|
|
55
|
-
margin: 0;
|
|
56
|
-
padding: 0;
|
|
57
|
-
font-family: "微软雅黑", sans-serif;
|
|
58
|
-
background: #2c2c2c url('bg.jpeg') no-repeat center center fixed;
|
|
59
|
-
background-size: cover;
|
|
60
|
-
color: #eee;
|
|
61
|
-
}}
|
|
62
|
-
|
|
63
|
-
.container {{
|
|
64
|
-
max-width: 800px;
|
|
65
|
-
margin: 40px auto;
|
|
66
|
-
background: rgba(255, 255, 255, 0.95);
|
|
67
|
-
border-radius: 15px;
|
|
68
|
-
padding: 40px 40px 30px 40px;
|
|
69
|
-
box-shadow: 0 0 25px rgba(0, 0, 0, 0.3);
|
|
70
|
-
color: #333;
|
|
71
|
-
}}
|
|
72
|
-
|
|
73
|
-
.banner {{
|
|
74
|
-
position: relative;
|
|
75
|
-
width: 100%;
|
|
76
|
-
height: 250px;
|
|
77
|
-
background-image: url('bg.jpeg');
|
|
78
|
-
background-size: cover;
|
|
79
|
-
background-position: center;
|
|
80
|
-
border-radius: 15px 15px 0 0;
|
|
81
|
-
display: flex;
|
|
82
|
-
align-items: center;
|
|
83
|
-
justify-content: center;
|
|
84
|
-
}}
|
|
85
|
-
|
|
86
|
-
.banner::after {{
|
|
87
|
-
content: "";
|
|
88
|
-
position: absolute;
|
|
89
|
-
top: 0; left: 0; right: 0; bottom: 0;
|
|
90
|
-
background: rgba(0, 0, 0, 0.4);
|
|
91
|
-
border-radius: 15px 15px 0 0;
|
|
92
|
-
}}
|
|
93
|
-
|
|
94
|
-
.banner h1 {{
|
|
95
|
-
position: relative;
|
|
96
|
-
color: #fff;
|
|
97
|
-
font-size: 28px;
|
|
98
|
-
text-shadow: 1px 1px 4px #000;
|
|
99
|
-
z-index: 1;
|
|
100
|
-
}}
|
|
101
|
-
|
|
102
|
-
h2 {{
|
|
103
|
-
color: #555;
|
|
104
|
-
border-bottom: 1px solid #ddd;
|
|
105
|
-
padding-bottom: 5px;
|
|
106
|
-
margin-top: 20px;
|
|
107
|
-
}}
|
|
108
|
-
|
|
109
|
-
p {{
|
|
110
|
-
font-size: 18px;
|
|
111
|
-
margin: 10px 0;
|
|
112
|
-
}}
|
|
113
|
-
|
|
114
|
-
pre {{
|
|
115
|
-
background: #f8f8f8;
|
|
116
|
-
padding: 15px;
|
|
117
|
-
border-radius: 8px;
|
|
118
|
-
overflow-x: auto;
|
|
119
|
-
font-family: "Courier New", monospace;
|
|
120
|
-
font-size: 16px;
|
|
121
|
-
}}
|
|
122
|
-
</style>
|
|
123
|
-
</head>
|
|
124
|
-
<body>
|
|
125
|
-
<div class="container">
|
|
126
|
-
<div class="banner">
|
|
127
|
-
<h1>🍽 {title}</h1>
|
|
128
|
-
</div>
|
|
129
|
-
<p><strong>主菜:</strong>{m}</p>
|
|
130
|
-
<p><strong>配菜:</strong>{s}</p>
|
|
131
|
-
<p><strong>做法:</strong>{t}</p>
|
|
132
|
-
<h2>生成的食谱:</h2>
|
|
133
|
-
<pre>{content_body}</pre>
|
|
134
|
-
</div>
|
|
135
|
-
</body>
|
|
136
|
-
</html>
|
|
137
|
-
"""
|
|
138
|
-
|
|
139
|
-
# 保存为 HTML 文件
|
|
140
|
-
filename = title.strip().replace(" ", "_").replace(":", "").replace(":", "") + ".html"
|
|
141
|
-
filename = re.sub(r'[\/\\\:\*\?\"\<\>\|]', '', f"{title}.html")
|
|
142
|
-
with open(filename, "w", encoding="utf-8") as f:
|
|
143
|
-
f.write(html)
|
|
144
|
-
|
|
145
|
-
# 自动打开网页
|
|
146
|
-
webbrowser.open(filename)
|
|
147
|
-
|
|
148
|
-
return content + "\n"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|