@aiyiran/myclaw 1.1.91 → 1.1.92

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.
Files changed (32) hide show
  1. package/assets/myclaw-artifacts.js +185 -8
  2. package/index.js +8 -5
  3. package/package.json +1 -1
  4. package/skills/yiran-course-template-pipeline/scripts/identify_template.py +2 -2
  5. package/skills/yiran-course-template-pipeline/template-index.json +183 -1
  6. package/skills/yiran-course-template-pipeline/template-index.md +63 -0
  7. package/skills/yiran-playground-template-use/prompts/remix-handoff.txt +24 -8
  8. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220/1.jpg +0 -0
  9. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220/2.jpg +0 -0
  10. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220/3.jpg +0 -0
  11. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220/4.jpg +0 -0
  12. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220/AI/344/270/215/347/224/250/347/234/213/347/232/204/345/216/237/345/247/213/346/217/220/347/244/272/350/257/215/344/272/272/347/261/273/347/234/213/__/351/200/211/351/242/230/345/274/225/346/223/216__.html +589 -0
  13. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220/AI/344/270/215/347/224/250/347/234/213/347/232/204/345/216/237/345/247/213/346/217/220/347/244/272/350/257/215/344/272/272/347/261/273/347/234/213//345/216/237/345/247/213/346/217/220/347/244/272/350/257/215.md +125 -0
  14. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220/AI/344/270/215/347/224/250/347/234/213/347/232/204/345/216/237/345/247/213/346/217/220/347/244/272/350/257/215/344/272/272/347/261/273/347/234/213//350/200/201/350/202/226/347/210/206/346/254/276/351/200/211/351/242/230/345/274/225/346/223/216.md +179 -0
  15. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220/AI/344/270/215/347/224/250/347/234/213/347/232/204/345/216/237/345/247/213/346/217/220/347/244/272/350/257/215/344/272/272/347/261/273/347/234/213//350/200/201/350/202/226/351/207/221/345/217/245/345/272/223v1.md +594 -0
  16. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220/__demo__.html +588 -0
  17. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220/__student-view__.html +77 -0
  18. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220/__student__.json +54 -0
  19. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220/__teacher-view__.html +52 -0
  20. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220/__teacher__.json +46 -0
  21. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220/index.html +148 -0
  22. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220//344/270/211/344/270/252/350/247/206/351/242/221/345/216/237/345/247/213/345/206/205/345/256/271/1-/344/273/200/344/271/210/346/230/257/344/274/230/347/247/200/347/232/204/345/255/251/345/255/220+/350/223/235/346/230/237/344/277/261/344/271/220/351/203/250/345/210/233/345/212/236+/347/210/266/346/257/215/345/244/251/350/201/214/357/274/210/351/200/220/345/255/227/347/250/277/357/274/211.md +48 -0
  23. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220//344/270/211/344/270/252/350/247/206/351/242/221/345/216/237/345/247/213/345/206/205/345/256/271/2-/350/277/207/347/250/213/345/206/231/344/275/234/350/257/276/347/250/213/345/210/206/344/272/253/357/274/210/351/200/220/345/255/227/347/250/277/357/274/211.md +27 -0
  24. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220//344/270/211/344/270/252/350/247/206/351/242/221/345/216/237/345/247/213/345/206/205/345/256/271/3-/350/202/262/345/204/277/345/273/272/350/256/256/357/274/232/345/242/236/351/207/217/344/277/241/346/201/257+/346/214/207/345/274/225vs/345/216/237/345/210/231+/345/210/206/344/272/253/347/224/237/346/264/273/347/273/206/350/212/202/357/274/210/351/200/220/345/255/227/347/250/277/357/274/211.md +204 -0
  25. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220//344/270/211/344/270/252/350/247/206/351/242/221/345/216/237/345/247/213/345/206/205/345/256/271//346/213/206/345/210/206/345/211/215/345/275/225/351/237/263/346/226/207/346/234/254.md +267 -0
  26. package//350/223/235/346/230/237/345/276/256/344/277/241/347/237/255/350/247/206/351/242/221/345/210/206/346/236/220//350/264/242/345/212/241/345/210/206/346/236/220.html +411 -0
  27. package//350/264/246/345/215/225/345/210/206/346/236/220/345/212/251/346/211/213/__demo__.html +411 -0
  28. package//350/264/246/345/215/225/345/210/206/346/236/220/345/212/251/346/211/213/__student-view__.html +77 -0
  29. package//350/264/246/345/215/225/345/210/206/346/236/220/345/212/251/346/211/213/__student__.json +54 -0
  30. package//350/264/246/345/215/225/345/210/206/346/236/220/345/212/251/346/211/213/__teacher-view__.html +52 -0
  31. package//350/264/246/345/215/225/345/210/206/346/236/220/345/212/251/346/211/213/__teacher__.json +50 -0
  32. package//350/264/246/345/215/225/345/210/206/346/236/220/345/212/251/346/211/213/index.html +148 -0
@@ -0,0 +1,411 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>5月支出财务分析</title>
7
+ <style>
8
+ :root {
9
+ --bg: #f5f7fb;
10
+ --card: #ffffff;
11
+ --text: #1f2937;
12
+ --muted: #6b7280;
13
+ --line: #e5e7eb;
14
+ --primary: #2563eb;
15
+ --good: #059669;
16
+ --warn: #d97706;
17
+ --danger: #dc2626;
18
+ }
19
+ * { box-sizing: border-box; }
20
+ body {
21
+ margin: 0;
22
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
23
+ background: var(--bg);
24
+ color: var(--text);
25
+ }
26
+ .wrap {
27
+ max-width: 1200px;
28
+ margin: 0 auto;
29
+ padding: 24px;
30
+ }
31
+ h1 {
32
+ margin: 0 0 8px;
33
+ font-size: 32px;
34
+ }
35
+ .sub {
36
+ color: var(--muted);
37
+ margin-bottom: 20px;
38
+ }
39
+ .grid {
40
+ display: grid;
41
+ grid-template-columns: repeat(4, 1fr);
42
+ gap: 16px;
43
+ margin-bottom: 20px;
44
+ }
45
+ .card {
46
+ background: var(--card);
47
+ border: 1px solid var(--line);
48
+ border-radius: 16px;
49
+ padding: 16px;
50
+ box-shadow: 0 6px 24px rgba(15, 23, 42, 0.05);
51
+ }
52
+ .card h3 {
53
+ margin: 0 0 8px;
54
+ font-size: 14px;
55
+ color: var(--muted);
56
+ font-weight: 600;
57
+ }
58
+ .big {
59
+ font-size: 28px;
60
+ font-weight: 700;
61
+ }
62
+ .filters {
63
+ display: grid;
64
+ grid-template-columns: repeat(6, 1fr);
65
+ gap: 12px;
66
+ margin-bottom: 20px;
67
+ }
68
+ label {
69
+ display: block;
70
+ font-size: 13px;
71
+ color: var(--muted);
72
+ margin-bottom: 6px;
73
+ }
74
+ input, select, button {
75
+ width: 100%;
76
+ padding: 10px 12px;
77
+ border: 1px solid var(--line);
78
+ border-radius: 10px;
79
+ font-size: 14px;
80
+ background: white;
81
+ }
82
+ button {
83
+ cursor: pointer;
84
+ background: var(--primary);
85
+ color: white;
86
+ border: none;
87
+ font-weight: 600;
88
+ margin-top: 20px;
89
+ }
90
+ button.secondary {
91
+ background: white;
92
+ color: var(--text);
93
+ border: 1px solid var(--line);
94
+ }
95
+ .table-wrap {
96
+ overflow: auto;
97
+ background: var(--card);
98
+ border: 1px solid var(--line);
99
+ border-radius: 16px;
100
+ }
101
+ table {
102
+ width: 100%;
103
+ border-collapse: collapse;
104
+ min-width: 900px;
105
+ }
106
+ th, td {
107
+ padding: 12px 14px;
108
+ border-bottom: 1px solid var(--line);
109
+ text-align: left;
110
+ font-size: 14px;
111
+ }
112
+ th {
113
+ background: #f8fafc;
114
+ color: #374151;
115
+ position: sticky;
116
+ top: 0;
117
+ }
118
+ .tag {
119
+ display: inline-block;
120
+ padding: 4px 8px;
121
+ border-radius: 999px;
122
+ font-size: 12px;
123
+ background: #eff6ff;
124
+ color: #1d4ed8;
125
+ }
126
+ .summary-list {
127
+ display: grid;
128
+ grid-template-columns: 1fr 1fr;
129
+ gap: 16px;
130
+ margin-top: 20px;
131
+ }
132
+ ul.rank {
133
+ margin: 0;
134
+ padding-left: 18px;
135
+ }
136
+ ul.rank li {
137
+ margin: 10px 0;
138
+ }
139
+ .hint {
140
+ color: var(--muted);
141
+ font-size: 13px;
142
+ margin-top: 8px;
143
+ }
144
+ @media (max-width: 960px) {
145
+ .grid, .filters, .summary-list { grid-template-columns: 1fr 1fr; }
146
+ }
147
+ @media (max-width: 640px) {
148
+ .grid, .filters, .summary-list { grid-template-columns: 1fr; }
149
+ h1 { font-size: 24px; }
150
+ }
151
+ </style>
152
+ </head>
153
+ <body>
154
+ <div class="wrap">
155
+ <h1>5月支出财务分析</h1>
156
+ <div class="sub">可以筛选、排序、看汇总,也能快速找出高消费项目。</div>
157
+
158
+ <div class="grid">
159
+ <div class="card">
160
+ <h3>总支出</h3>
161
+ <div class="big" id="totalExpense">0</div>
162
+ </div>
163
+ <div class="card">
164
+ <h3>记录条数</h3>
165
+ <div class="big" id="totalCount">0</div>
166
+ </div>
167
+ <div class="card">
168
+ <h3>单笔最高</h3>
169
+ <div class="big" id="maxExpense">0</div>
170
+ </div>
171
+ <div class="card">
172
+ <h3>笔均支出</h3>
173
+ <div class="big" id="avgExpense">0</div>
174
+ </div>
175
+ </div>
176
+
177
+ <div class="card" style="margin-bottom: 20px;">
178
+ <div class="filters">
179
+ <div>
180
+ <label>关键词</label>
181
+ <input id="keyword" placeholder="搜商户、备注、类别" />
182
+ </div>
183
+ <div>
184
+ <label>类别</label>
185
+ <select id="categoryFilter">
186
+ <option value="">全部类别</option>
187
+ </select>
188
+ </div>
189
+ <div>
190
+ <label>最小金额</label>
191
+ <input id="minAmount" type="number" placeholder="例如 50" />
192
+ </div>
193
+ <div>
194
+ <label>最大金额</label>
195
+ <input id="maxAmount" type="number" placeholder="例如 300" />
196
+ </div>
197
+ <div>
198
+ <label>排序方式</label>
199
+ <select id="sortBy">
200
+ <option value="amountDesc">金额从高到低</option>
201
+ <option value="amountAsc">金额从低到高</option>
202
+ <option value="dateAsc">日期从早到晚</option>
203
+ <option value="dateDesc">日期从晚到早</option>
204
+ </select>
205
+ </div>
206
+ <div>
207
+ <button id="resetBtn" class="secondary">重置筛选</button>
208
+ </div>
209
+ </div>
210
+ <div class="hint">财务角度的小帮助:你可以先筛选高于 100 元的支出,更容易看到大头花费。</div>
211
+ </div>
212
+
213
+ <div class="table-wrap">
214
+ <table>
215
+ <thead>
216
+ <tr>
217
+ <th>日期</th>
218
+ <th>金额</th>
219
+ <th>类型</th>
220
+ <th>商户/事项</th>
221
+ <th>财务类别</th>
222
+ <th>备注</th>
223
+ </tr>
224
+ </thead>
225
+ <tbody id="tableBody"></tbody>
226
+ </table>
227
+ </div>
228
+
229
+ <div class="summary-list">
230
+ <div class="card">
231
+ <h3>类别汇总</h3>
232
+ <ul class="rank" id="categorySummary"></ul>
233
+ </div>
234
+ <div class="card">
235
+ <h3>商户/事项前五</h3>
236
+ <ul class="rank" id="merchantSummary"></ul>
237
+ </div>
238
+ </div>
239
+ </div>
240
+
241
+ <script>
242
+ const rawData = [
243
+ { date: '5月1日', amount: 38, type: '支出', merchant: '瑞幸咖啡', note: '早餐咖啡' },
244
+ { date: '5月1日', amount: 126, type: '支出', merchant: '盒马', note: '买菜' },
245
+ { date: '5月2日', amount: 42, type: '支出', merchant: '美团外卖', note: '午餐' },
246
+ { date: '5月2日', amount: 28, type: '支出', merchant: '地铁', note: '通勤' },
247
+ { date: '5月3日', amount: 299, type: '支出', merchant: '京东', note: '蓝牙耳机' },
248
+ { date: '5月4日', amount: 68, type: '支出', merchant: '滴滴', note: '晚上回家' },
249
+ { date: '5月5日', amount: 36, type: '支出', merchant: '瑞幸咖啡', note: '咖啡' },
250
+ { date: '5月6日', amount: 218, type: '支出', merchant: '山姆', note: '日用品' },
251
+ { date: '5月7日', amount: 88, type: '支出', merchant: '电影院', note: '周末娱乐' },
252
+ { date: '5月8日', amount: 49, type: '支出', merchant: '美团外卖', note: '晚餐' },
253
+ { date: '5月9日', amount: 199, type: '支出', merchant: '得到App', note: '课程' },
254
+ { date: '5月10日', amount: 35, type: '支出', merchant: '便利店', note: '零食' },
255
+ { date: '5月11日', amount: 520, type: '支出', merchant: '淘宝', note: '衣服' },
256
+ { date: '5月12日', amount: 45, type: '支出', merchant: '瑞幸咖啡', note: '咖啡' },
257
+ { date: '5月13日', amount: 168, type: '支出', merchant: '餐厅', note: '朋友聚餐' },
258
+ { date: '5月14日', amount: 25, type: '支出', merchant: '地铁', note: '通勤' },
259
+ { date: '5月15日', amount: 980, type: '支出', merchant: '体检', note: '健康检查' },
260
+ { date: '5月16日', amount: 58, type: '支出', merchant: '美团外卖', note: '午餐' },
261
+ { date: '5月17日', amount: 32, type: '支出', merchant: '未知消费', note: '备注不清' },
262
+ { date: '5月18日', amount: 260, type: '支出', merchant: '加油站', note: '出行' },
263
+ { date: '5月19日', amount: 39, type: '支出', merchant: '瑞幸咖啡', note: '咖啡' },
264
+ { date: '5月20日', amount: 399, type: '支出', merchant: '拼多多', note: '家居用品' },
265
+ ];
266
+
267
+ function getCategory(item) {
268
+ const merchant = item.merchant;
269
+ const note = item.note;
270
+ if (merchant.includes('瑞幸') || merchant.includes('美团外卖') || merchant.includes('餐厅') || note.includes('午餐') || note.includes('晚餐') || note.includes('咖啡')) return '餐饮';
271
+ if (merchant.includes('地铁') || merchant.includes('滴滴') || merchant.includes('加油站')) return '交通';
272
+ if (merchant.includes('淘宝') || merchant.includes('京东') || merchant.includes('拼多多') || merchant.includes('山姆') || merchant.includes('盒马') || merchant.includes('便利店')) return '购物';
273
+ if (merchant.includes('体检')) return '医疗健康';
274
+ if (merchant.includes('电影院')) return '娱乐';
275
+ if (merchant.includes('得到App')) return '学习成长';
276
+ return '其他';
277
+ }
278
+
279
+ const data = rawData.map((item, index) => ({
280
+ ...item,
281
+ category: getCategory(item),
282
+ day: Number(item.date.match(/5月(\d+)日/)[1]),
283
+ id: index + 1,
284
+ }));
285
+
286
+ const els = {
287
+ totalExpense: document.getElementById('totalExpense'),
288
+ totalCount: document.getElementById('totalCount'),
289
+ maxExpense: document.getElementById('maxExpense'),
290
+ avgExpense: document.getElementById('avgExpense'),
291
+ keyword: document.getElementById('keyword'),
292
+ categoryFilter: document.getElementById('categoryFilter'),
293
+ minAmount: document.getElementById('minAmount'),
294
+ maxAmount: document.getElementById('maxAmount'),
295
+ sortBy: document.getElementById('sortBy'),
296
+ resetBtn: document.getElementById('resetBtn'),
297
+ tableBody: document.getElementById('tableBody'),
298
+ categorySummary: document.getElementById('categorySummary'),
299
+ merchantSummary: document.getElementById('merchantSummary'),
300
+ };
301
+
302
+ function formatMoney(n) {
303
+ return '¥' + n.toFixed(0);
304
+ }
305
+
306
+ function fillCategoryOptions() {
307
+ const categories = [...new Set(data.map(item => item.category))];
308
+ categories.forEach(category => {
309
+ const option = document.createElement('option');
310
+ option.value = category;
311
+ option.textContent = category;
312
+ els.categoryFilter.appendChild(option);
313
+ });
314
+ }
315
+
316
+ function getFilteredData() {
317
+ const keyword = els.keyword.value.trim().toLowerCase();
318
+ const category = els.categoryFilter.value;
319
+ const minAmount = Number(els.minAmount.value || 0);
320
+ const maxAmount = els.maxAmount.value ? Number(els.maxAmount.value) : Infinity;
321
+
322
+ let result = data.filter(item => {
323
+ const matchKeyword = !keyword || [item.date, item.type, item.merchant, item.note, item.category].join(' ').toLowerCase().includes(keyword);
324
+ const matchCategory = !category || item.category === category;
325
+ const matchMin = item.amount >= minAmount;
326
+ const matchMax = item.amount <= maxAmount;
327
+ return matchKeyword && matchCategory && matchMin && matchMax;
328
+ });
329
+
330
+ const sortBy = els.sortBy.value;
331
+ result.sort((a, b) => {
332
+ if (sortBy === 'amountDesc') return b.amount - a.amount;
333
+ if (sortBy === 'amountAsc') return a.amount - b.amount;
334
+ if (sortBy === 'dateAsc') return a.day - b.day;
335
+ if (sortBy === 'dateDesc') return b.day - a.day;
336
+ return 0;
337
+ });
338
+ return result;
339
+ }
340
+
341
+ function renderTable(list) {
342
+ els.tableBody.innerHTML = '';
343
+ list.forEach(item => {
344
+ const tr = document.createElement('tr');
345
+ tr.innerHTML = `
346
+ <td>${item.date}</td>
347
+ <td>${formatMoney(item.amount)}</td>
348
+ <td>${item.type}</td>
349
+ <td>${item.merchant}</td>
350
+ <td><span class="tag">${item.category}</span></td>
351
+ <td>${item.note}</td>
352
+ `;
353
+ els.tableBody.appendChild(tr);
354
+ });
355
+ }
356
+
357
+ function renderStats(list) {
358
+ const total = list.reduce((sum, item) => sum + item.amount, 0);
359
+ const max = list.length ? Math.max(...list.map(item => item.amount)) : 0;
360
+ const avg = list.length ? total / list.length : 0;
361
+ els.totalExpense.textContent = formatMoney(total);
362
+ els.totalCount.textContent = list.length;
363
+ els.maxExpense.textContent = formatMoney(max);
364
+ els.avgExpense.textContent = formatMoney(avg);
365
+ }
366
+
367
+ function renderCategorySummary(list) {
368
+ const map = new Map();
369
+ list.forEach(item => {
370
+ map.set(item.category, (map.get(item.category) || 0) + item.amount);
371
+ });
372
+ const sorted = [...map.entries()].sort((a, b) => b[1] - a[1]);
373
+ els.categorySummary.innerHTML = sorted.map(([name, total]) => `<li><strong>${name}</strong>:${formatMoney(total)}</li>`).join('');
374
+ }
375
+
376
+ function renderMerchantSummary(list) {
377
+ const map = new Map();
378
+ list.forEach(item => {
379
+ map.set(item.merchant, (map.get(item.merchant) || 0) + item.amount);
380
+ });
381
+ const sorted = [...map.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5);
382
+ els.merchantSummary.innerHTML = sorted.map(([name, total]) => `<li><strong>${name}</strong>:${formatMoney(total)}</li>`).join('');
383
+ }
384
+
385
+ function render() {
386
+ const list = getFilteredData();
387
+ renderTable(list);
388
+ renderStats(list);
389
+ renderCategorySummary(list);
390
+ renderMerchantSummary(list);
391
+ }
392
+
393
+ [els.keyword, els.categoryFilter, els.minAmount, els.maxAmount, els.sortBy].forEach(el => {
394
+ el.addEventListener('input', render);
395
+ el.addEventListener('change', render);
396
+ });
397
+
398
+ els.resetBtn.addEventListener('click', () => {
399
+ els.keyword.value = '';
400
+ els.categoryFilter.value = '';
401
+ els.minAmount.value = '';
402
+ els.maxAmount.value = '';
403
+ els.sortBy.value = 'amountDesc';
404
+ render();
405
+ });
406
+
407
+ fillCategoryOptions();
408
+ render();
409
+ </script>
410
+ </body>
411
+ </html>