@tomako/tools-runtime 0.1.1 → 0.1.2
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.
- package/package.json +13 -4
- package/src/components/tools/workspace/tool-workspace-layout.tsx +1 -1
- package/src/constants/related-tools.ts +4 -0
- package/src/features/tools/app-icon-resizer/app-icon-resizer.container.tsx +15 -2
- package/src/features/tools/app-icon-resizer/app-icon-resizer.spec.ts +1 -1
- package/src/features/tools/app-icon-resizer/widget/app-icon-resizer.tsx +54 -11
- package/src/features/tools/app-icon-resizer/widget/platform-icons.tsx +2 -5
- package/src/features/tools/mrr-calculator/mrr-calculator.container.tsx +23 -0
- package/src/features/tools/mrr-calculator/mrr-calculator.spec.ts +15 -0
- package/src/features/tools/mrr-calculator/widget/calculations.ts +74 -0
- package/src/features/tools/mrr-calculator/widget/index.ts +1 -0
- package/src/features/tools/mrr-calculator/widget/mrr-calculator.tsx +581 -0
- package/src/features/tools/registry.ts +6 -0
- package/src/features/tools/runtime-registry.ts +4 -0
- package/src/features/tools/shared/create-standard-landing-container.tsx +35 -5
- package/src/features/tools/shared/tool-page-shell.tsx +4 -4
- package/src/features/tools/shared/tool-standard-landing-sections.tsx +262 -52
- package/src/features/tools/spec-registry.ts +2 -0
- package/src/features/tools/widget-registry.ts +2 -0
- package/src/i18n/messages/en/tools/app-icon-resizer.ts +90 -62
- package/src/i18n/messages/en/tools/index.ts +2 -0
- package/src/i18n/messages/en/tools/mrr-calculator.ts +202 -0
- package/src/i18n/messages/en/tools-ui.ts +3 -2
- package/src/i18n/messages/zh/page/tools.ts +2 -3
- package/src/i18n/messages/zh/tools/app-icon-resizer.ts +90 -62
- package/src/i18n/messages/zh/tools/index.ts +2 -0
- package/src/i18n/messages/zh/tools/mrr-calculator.ts +112 -0
- package/src/i18n/messages/zh/tools-ui.ts +3 -2
- package/src/i18n/messages/zh-tw/tools/app-icon-resizer.ts +90 -62
- package/src/i18n/messages/zh-tw/tools/index.ts +2 -0
- package/src/i18n/messages/zh-tw/tools/mrr-calculator.ts +52 -0
- package/src/i18n/messages/zh-tw/tools-ui.ts +3 -2
- package/src/lib/tools/resolve-tool-locale-copy.ts +7 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
const appIconResizer = {
|
|
2
2
|
meta: {
|
|
3
|
-
title: "App Icon
|
|
3
|
+
title: "App Icon 尺寸生成器:iOS 与 Android",
|
|
4
4
|
description:
|
|
5
|
-
"
|
|
6
|
-
intro: "
|
|
5
|
+
"上传方形 App Icon,在浏览器本地生成 Xcode AppIcon、Google Play 512 和 Android launcher 图标包,预览后下载 ZIP。",
|
|
6
|
+
intro: "上传 1024px+ 方形源图,本地生成 Xcode AppIcon、Google Play 图标和 Android legacy launcher 文件。",
|
|
7
7
|
category: "App 上架工具",
|
|
8
8
|
keywords: [
|
|
9
9
|
"app icon 切图",
|
|
@@ -19,48 +19,61 @@ const appIconResizer = {
|
|
|
19
19
|
guide: {
|
|
20
20
|
heroVisualAlt:
|
|
21
21
|
"App Icon 资源包视觉图,展示一个源图标导出为商店提交图标、Xcode 资源和 Android launcher 文件。",
|
|
22
|
-
workspaceHeading: "App Icon
|
|
22
|
+
workspaceHeading: "App Icon 尺寸包生成器",
|
|
23
23
|
workspaceHint:
|
|
24
|
-
"
|
|
24
|
+
"一张源图,本地生成商店与工程图标 ZIP。",
|
|
25
25
|
workspaceBadge: "PNG + ZIP",
|
|
26
26
|
standard: {
|
|
27
27
|
benefits: {
|
|
28
|
-
title: "
|
|
28
|
+
title: "为什么用这个工具",
|
|
29
29
|
cards: [
|
|
30
30
|
{
|
|
31
|
-
title: "
|
|
32
|
-
body: "
|
|
31
|
+
title: "一次生成交付文件",
|
|
32
|
+
body: "不用逐张建画板和导出。一次生成 Xcode AppIcon、Google Play 512 和 Android legacy launcher 文件。",
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
|
-
title: "
|
|
36
|
-
body: "
|
|
35
|
+
title: "目录和命名已整理",
|
|
36
|
+
body: "商店上传图、Xcode 资源和 Android 工程文件按用途分组,下载后不用自己建目录或逐张改名。",
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
|
-
title: "
|
|
40
|
-
body: "
|
|
39
|
+
title: "先预览再下载",
|
|
40
|
+
body: "检查透明背景、裁切方式和文件体积风险后再下载。切图和 ZIP 打包都在当前浏览器完成。",
|
|
41
41
|
},
|
|
42
42
|
],
|
|
43
43
|
},
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
44
|
+
outputPreview: {
|
|
45
|
+
eyebrow: "示例输出",
|
|
46
|
+
title: "下载包里有什么",
|
|
47
|
+
intro: "选择双平台后,文件会按真实交付位置分组。下面展示的是当前工具会生成的目录和文件,不是抽象功能说明。",
|
|
48
|
+
inputLabel: "示例输入",
|
|
49
|
+
input: "一张 1024 × 1024 方形 PNG,选择 Apple + Google Play / Android",
|
|
50
|
+
outputLabel: "ZIP 主要内容",
|
|
51
|
+
fields: [
|
|
52
|
+
{
|
|
53
|
+
label: "Apple/AppIcon.appiconset",
|
|
54
|
+
body: "iPhone、iPad 与 ios-marketing 兼容尺寸,附 Contents.json。",
|
|
55
55
|
},
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
{
|
|
57
|
+
label: "Apple/AppStoreIcon-1024.png",
|
|
58
|
+
body: "供团队在上架前检查主体、留白和品牌一致性的 1024px 副本。",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
label: "GooglePlay/app-icon-512.png",
|
|
62
|
+
body: "Play Console store listing 使用的 512 × 512 PNG。",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
label: "Android/res/mipmap-*",
|
|
66
|
+
body: "mdpi 到 xxxhdpi 的 legacy launcher PNG;不含 Adaptive Icon 图层。",
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
imageTextSections: [
|
|
58
71
|
{
|
|
59
72
|
id: "platform-scope",
|
|
60
|
-
title: "
|
|
73
|
+
title: "下载后怎么使用",
|
|
61
74
|
body: [
|
|
62
|
-
"
|
|
63
|
-
"
|
|
75
|
+
"把 Apple/AppIcon.appiconset 导入 Xcode asset catalog,再随 build 提交;GooglePlay/app-icon-512.png 用于 Play Console store listing。",
|
|
76
|
+
"Android/res/mipmap-* 是 legacy launcher 工程资源。如果项目使用 Adaptive Icon,仍需在 Android Studio 中配置前景、背景和可选的 monochrome 图层。",
|
|
64
77
|
],
|
|
65
78
|
image: {
|
|
66
79
|
src: "/tools/app-icon-resizer-section-variation-8bit-v3.webp",
|
|
@@ -69,10 +82,10 @@ const appIconResizer = {
|
|
|
69
82
|
},
|
|
70
83
|
{
|
|
71
84
|
id: "handoff-review",
|
|
72
|
-
title: "
|
|
85
|
+
title: "使用前需要知道",
|
|
73
86
|
body: [
|
|
74
|
-
"
|
|
75
|
-
"
|
|
87
|
+
"非方形图片会居中裁成方形,不会拉伸。正式交付优先使用方形满版源图,并且不要预先添加圆角或外阴影。",
|
|
88
|
+
"图片读取、缩放和 ZIP 打包都在浏览器本地完成。正式发布前仍需复核平台最新规则、品牌版权以及浅色和深色背景下的识别度。",
|
|
76
89
|
],
|
|
77
90
|
image: {
|
|
78
91
|
src: "/tools/app-icon-resizer-section-support-8bit-v3.webp",
|
|
@@ -82,31 +95,56 @@ const appIconResizer = {
|
|
|
82
95
|
},
|
|
83
96
|
],
|
|
84
97
|
generation: {
|
|
85
|
-
title: "
|
|
98
|
+
title: "三步完成",
|
|
86
99
|
imageAlt: "上传 App Icon 后选择平台、裁切预览并导出 ZIP 的 8bit 流程图",
|
|
87
100
|
ctaLabel: "生成图标资源包",
|
|
88
101
|
steps: [
|
|
89
102
|
{
|
|
90
|
-
title: "
|
|
91
|
-
body: "
|
|
103
|
+
title: "上传并选择平台",
|
|
104
|
+
body: "上传 PNG、JPG 或 WebP,再选择 Apple、Google Play / Android 或双平台。Apple 包需要源图短边至少 1024px。",
|
|
92
105
|
},
|
|
93
106
|
{
|
|
94
|
-
title: "
|
|
95
|
-
body: "
|
|
107
|
+
title: "本地生成尺寸包",
|
|
108
|
+
body: "浏览器完成裁切、缩放、命名和目录整理,同时生成 PNG、Contents.json 与 README。",
|
|
96
109
|
},
|
|
97
110
|
{
|
|
98
|
-
title: "
|
|
99
|
-
body: "
|
|
111
|
+
title: "预览并下载 ZIP",
|
|
112
|
+
body: "在结果区筛选平台、检查透明网格和体积风险,然后下载完整 ZIP 或单个 PNG。",
|
|
100
113
|
},
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
referenceTable: {
|
|
117
|
+
title: "实际输出与使用位置",
|
|
118
|
+
intro: "现代 Xcode 可以从单张 1024px 图标生成较小变体;Tomako 仍提供完整兼容型 AppIcon.appiconset,方便接入现有工程和团队交付。",
|
|
119
|
+
mobileHint: "表格可左右滑动,查看完整文件去向。",
|
|
120
|
+
columns: ["输出组", "包含内容", "当前用途", "使用位置"],
|
|
121
|
+
rows: [
|
|
101
122
|
{
|
|
102
|
-
|
|
103
|
-
|
|
123
|
+
label: "Xcode AppIcon",
|
|
124
|
+
cells: ["20–1024px 兼容尺寸,附 Contents.json", "iOS / iPadOS 工程图标", "Xcode asset catalog"],
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
label: "Apple 1024 副本",
|
|
128
|
+
cells: ["Apple/AppStoreIcon-1024.png", "团队视觉复核,不是另一套固定上传流程", "上架前检查主体与留白"],
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
label: "Google Play",
|
|
132
|
+
cells: ["GooglePlay/app-icon-512.png", "512 × 512 PNG;超过 1024KB 时提示", "Play Console store listing"],
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
label: "Android legacy launcher",
|
|
136
|
+
cells: ["48 / 72 / 96 / 144 / 192px", "兼容型 launcher PNG", "Android/res/mipmap-*"],
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
label: "交付说明",
|
|
140
|
+
cells: ["README.txt", "目录用途与边界说明", "设计、研发与 ASO 交接"],
|
|
104
141
|
},
|
|
105
142
|
],
|
|
143
|
+
note: "Google Play 图标需同时满足平台的 PNG、文件大小和内容规范。当前不生成 Android Adaptive Icon 的 foreground、background 或 monochrome 图层。",
|
|
106
144
|
},
|
|
107
145
|
faqIntro:
|
|
108
|
-
"
|
|
109
|
-
faqCtaLabel: "
|
|
146
|
+
"先确认源图要求和文件去向,再判断这套输出是否适合你的发布流程。",
|
|
147
|
+
faqCtaLabel: "回到工作台",
|
|
110
148
|
},
|
|
111
149
|
whatYouGetHeading: "生成后会得到什么",
|
|
112
150
|
valueVisualAlt: "整理好的 App Icon 文件包,包含 Xcode 资源目录、商店提交图标、Android 工程目录和 ZIP 下载包。",
|
|
@@ -192,44 +230,34 @@ const appIconResizer = {
|
|
|
192
230
|
faqHeading: "常见问题",
|
|
193
231
|
faqItems: [
|
|
194
232
|
{
|
|
195
|
-
question: "
|
|
233
|
+
question: "源图应该准备成什么格式和尺寸?",
|
|
196
234
|
answer:
|
|
197
|
-
"
|
|
235
|
+
"建议使用 1024 × 1024 或更大的方形 PNG。JPG 和 WebP 也支持;只生成 Google Play / Android 时,源图短边至少需要 512px。",
|
|
198
236
|
},
|
|
199
237
|
{
|
|
200
|
-
question: "
|
|
238
|
+
question: "上传的 App Icon 会保存到服务器吗?",
|
|
201
239
|
answer:
|
|
202
|
-
"
|
|
240
|
+
"不会。图片读取、canvas 切图和 ZIP 打包都在浏览器本地完成。刷新页面后文件状态会消失,源图不会上传服务器。",
|
|
203
241
|
},
|
|
204
242
|
{
|
|
205
|
-
question: "
|
|
243
|
+
question: "生成的图标能直接用于 App Store 和 Google Play 吗?",
|
|
206
244
|
answer:
|
|
207
|
-
"
|
|
245
|
+
"可以作为工程接入和商店上传素材,但正式发布前仍需复核。GooglePlay/app-icon-512.png 用于 Play Console;Apple/AppIcon.appiconset 应放入 Xcode,再随 build 提交到 App Store Connect。",
|
|
208
246
|
},
|
|
209
247
|
{
|
|
210
248
|
question: "为什么不自动加圆角或阴影?",
|
|
211
249
|
answer:
|
|
212
|
-
"
|
|
250
|
+
"不用提前添加。商店和系统会应用自己的遮罩、圆角或阴影,预先处理可能造成二次裁切或边缘不齐。",
|
|
213
251
|
},
|
|
214
252
|
{
|
|
215
|
-
question: "
|
|
253
|
+
question: "源图不是方形或带透明背景怎么办?",
|
|
216
254
|
answer:
|
|
217
|
-
"
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
question: "透明背景的图标会怎么处理?",
|
|
221
|
-
answer:
|
|
222
|
-
"工具会保留透明像素,并在结果预览里用透明网格展示。正式上架前建议确认图标在浅色、深色和平台遮罩下都能被清楚识别。",
|
|
255
|
+
"会居中裁成方形,不会拉伸图片。透明像素会保留;正式发布前仍要检查主体位置、裁切边缘和不同背景下的识别度。",
|
|
223
256
|
},
|
|
224
257
|
{
|
|
225
258
|
question: "这个工具会生成 Android adaptive icon 吗?",
|
|
226
259
|
answer:
|
|
227
|
-
"不会。当前输出 Google Play 512 和 legacy launcher mipmap PNG,不生成 adaptive icon 的 foreground/background XML
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
question: "图片太小会怎样?",
|
|
231
|
-
answer:
|
|
232
|
-
"选择 Apple 或双平台时,源图短边低于 1024px 会被拦截;只生成 Google Play / Android 时,短边低于 512px 会被拦截。Google Play 512 图标超过 1024KB 时会显示风险提示。",
|
|
260
|
+
"不会。当前输出 Google Play 512 和 legacy launcher mipmap PNG,不生成 adaptive icon 的 foreground/background XML。你需要在 Android 工程里另外配置。",
|
|
233
261
|
},
|
|
234
262
|
],
|
|
235
263
|
ctaPrimary: "继续做商店截图",
|
|
@@ -14,6 +14,7 @@ import kokoCodexAssistant from "./koko-codex-assistant";
|
|
|
14
14
|
import logoGenerator from "./logo-generator";
|
|
15
15
|
import marketForecastReport from "./market-forecast-report";
|
|
16
16
|
import millionUserGrowthTest from "./million-user-growth-test";
|
|
17
|
+
import mrrCalculator from "./mrr-calculator";
|
|
17
18
|
import ogImageGenerator from "./og-image-generator";
|
|
18
19
|
import productAgreementGenerator from "./product-agreement-generator";
|
|
19
20
|
import pitchDeckGenerator from "./pitch-deck-generator";
|
|
@@ -59,6 +60,7 @@ const toolsPages = {
|
|
|
59
60
|
logoGenerator,
|
|
60
61
|
marketForecastReport,
|
|
61
62
|
millionUserGrowthTest,
|
|
63
|
+
mrrCalculator,
|
|
62
64
|
ogImageGenerator,
|
|
63
65
|
appStoreScreenshotGenerator,
|
|
64
66
|
twitterGifDownloader,
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
const mrrCalculator = {
|
|
2
|
+
meta: {
|
|
3
|
+
title: "SaaS MRR 计算器|月度经常性收入计算",
|
|
4
|
+
description: "用客户数据计算 MRR 和 ARR,或根据公开网站流量、套餐价格和可调整假设估算 SaaS MRR。",
|
|
5
|
+
intro: "把月付、季付或年付订阅统一换算为月度经常性收入,也可以切换到公开数据估算模式。",
|
|
6
|
+
category: "SaaS 指标工具",
|
|
7
|
+
keywords: ["MRR 计算器", "月度经常性收入计算器", "MRR 公式", "如何计算 MRR", "MRR 转 ARR", "SaaS MRR 计算器"],
|
|
8
|
+
inputSignal: "客户与计费数据,或公开流量与套餐价格",
|
|
9
|
+
outputSignal: "MRR、ARR、月度 ARPA、增长率或公开数据估算",
|
|
10
|
+
boundarySignal: "浏览器本地计算;估算结果仅供方向判断,并非公司披露收入",
|
|
11
|
+
},
|
|
12
|
+
guide: {
|
|
13
|
+
workspaceHeading: "SaaS MRR 计算器",
|
|
14
|
+
workspaceHint: "用已知客户数据计算月度经常性收入,或切换到估算模式,用公开流量和套餐价格粗略判断 SaaS MRR。",
|
|
15
|
+
standard: {
|
|
16
|
+
benefits: {
|
|
17
|
+
title: "这个 MRR 计算器会返回什么",
|
|
18
|
+
cards: [
|
|
19
|
+
{ title: "同时得到 MRR 和 ARR", body: "无需制作表格,直接查看月度经常性收入、年度经常性收入和月度 ARPA。" },
|
|
20
|
+
{ title: "自动统一计费周期", body: "输入月付、季付或年付价格,计算器会先统一换算到每月口径。" },
|
|
21
|
+
{ title: "也能粗略评估竞品", body: "不知道客户数时,用公开流量、套餐价格和可调整假设得到明确标注的估算结果。" },
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
imageTextSections: [
|
|
25
|
+
{
|
|
26
|
+
id: "choose-the-right-mrr-method",
|
|
27
|
+
title: "选择正确的\nMRR 计算方式",
|
|
28
|
+
body: [
|
|
29
|
+
{ text: "想计算自己产品的 MRR 或 ARR 时,使用默认的“计算 MRR”。填写活跃付费客户数、每位客户的经常性金额和计费周期,工具会直接计算结果。", highlights: ["计算 MRR"] },
|
|
30
|
+
{ text: "想粗略了解竞品或其他 SaaS 的收入量级时,切换到“估算 SaaS MRR”。根据公开网站流量和套餐价格填写估算条件;结果只用于方向判断,不是对方披露的收入。", highlights: ["估算 SaaS MRR"] },
|
|
31
|
+
],
|
|
32
|
+
image: { src: "/tools/mrr-calculator-section-steps-8bit.webp", alt: "像素风工作台对比用客户数据计算 MRR 与用公开流量和套餐价格估算 SaaS MRR。" },
|
|
33
|
+
imageFirst: true,
|
|
34
|
+
hideImageOnMobile: true,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: "monthly-recurring-revenue-formula",
|
|
38
|
+
title: "如何计算\n月度经常性收入",
|
|
39
|
+
body: [
|
|
40
|
+
{ text: "月度经常性收入公式是:MRR = 活跃付费客户数 × 月度 ARPA。季付经常性金额先除以 3,年付金额先除以 12,再乘以客户数。", highlights: ["MRR = 活跃付费客户数 × 月度 ARPA"] },
|
|
41
|
+
"例如,12 位客户每年支付 1,200 美元,月度 ARPA 为 100 美元,MRR 为 1,200 美元,ARR 为 14,400 美元。若上月 MRR 为 1,000 美元,环比增长率是(1,200 − 1,000)÷ 1,000 = 20%。",
|
|
42
|
+
],
|
|
43
|
+
image: { src: "/tools/mrr-calculator-section-primary-8bit.webp", alt: "像素风 SaaS 账本把月付、季付和年付订阅统一换算成 MRR。" },
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: "estimate-saas-mrr",
|
|
47
|
+
title: "用公开数据\n估算 SaaS MRR",
|
|
48
|
+
body: [
|
|
49
|
+
"估算模式先用“访问量 × 可用于获客的访问占比 × 访问者转付费率”估算每月新增付费客户,再用平均付费周期估算活跃客户数,最后乘以统一到每月的套餐价格。",
|
|
50
|
+
"重复访问、现有客户、渠道结构、转化率、套餐结构和流失仍然未知。比较多个产品时应保持假设一致,业务模式不同时再调整;结果只适合方向判断。",
|
|
51
|
+
],
|
|
52
|
+
image: { src: "/tools/mrr-calculator-section-variation-8bit.webp", alt: "像素风公开流量图和套餐价格卡片进入明确标注的 SaaS MRR 估算结果。" },
|
|
53
|
+
imageFirst: true,
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
editorialSections: [
|
|
57
|
+
{
|
|
58
|
+
id: "what-counts-as-mrr",
|
|
59
|
+
title: "哪些收入应该计入月度经常性收入",
|
|
60
|
+
body: [
|
|
61
|
+
"MRR 是统一到单月口径的经常性订阅收入。应计入当前合同下持续发生的有效套餐收入,季付或年付金额需要先换算到每月。",
|
|
62
|
+
"不要计入一次性设置费、实施费、专业服务、硬件、税费和其他非经常性收款。如果涉及折扣、退款、用量计费、扩张、收缩或流失,应使用账单系统数据和更完整的收入模型。",
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: "common-mrr-calculation-mistakes",
|
|
67
|
+
title: "常见的 MRR 计算错误",
|
|
68
|
+
body: [
|
|
69
|
+
"不要把整笔年付收入全部放进一个月,也不要计入一次性收入,或把新增 MRR 当成公司总 MRR。涉及多个套餐时,应分别计算后相加,或使用加权平均月价,不要假设客户平均分布。",
|
|
70
|
+
"在估算模式中,不要把所有网站访问量或直接访问都当成新客户。流量可能包含回访者、现有客户、员工和重复会话,因此可用于获客的访问占比必须保持为明确假设。",
|
|
71
|
+
"最重要的是,不要把 Estimated MRR 场景写成竞品真实收入。公开流量和价格无法揭示真实客户数、折扣、留存和渠道结构。",
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
id: "use-mrr-and-arr-results",
|
|
76
|
+
title: "如何使用 MRR 和 ARR 结果",
|
|
77
|
+
body: [
|
|
78
|
+
"核对客户数、经常性金额和计费周期后,可以把计算 MRR 用于经营检查、月度汇报或套餐情景测试。填写上月 MRR 可以查看环比增长,把 MRR 转成 ARR 可以得到年度运行率视角。",
|
|
79
|
+
"估算 MRR 只适合竞品方向性比较。比较不同产品时保持同一组假设,记录结果依据,并在流量或价格变化后重新计算。",
|
|
80
|
+
"这些结果可以继续用于流失率、留存和 LTV:CAC 分析,但不属于会计报表、财务建议或估值意见。",
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
faqIntro: "补充回答多套餐、零分母、直接访问、估算边界和浏览器本地数据处理问题。",
|
|
85
|
+
faqCtaLabel: "使用计算器",
|
|
86
|
+
},
|
|
87
|
+
faqHeading: "MRR 计算器常见问题",
|
|
88
|
+
faqItems: [
|
|
89
|
+
{ question: "这个 MRR 计算器如何使用?", answer: "想计算自己产品的 MRR 或 ARR 时,保留默认的“计算 MRR”,填写活跃付费客户数、每位客户的经常性金额和计费周期。想粗略了解竞品或其他 SaaS 的收入量级时,切换到“估算 SaaS MRR”,根据公开网站流量和套餐价格填写估算条件。前者是基于你的输入直接计算;后者只是方向性估算。" },
|
|
90
|
+
{ question: "不同套餐可以一起计算吗?", answer: "V1 接收一个混合平均经常性金额。你可以分别计算各套餐后相加,或在知道套餐占比时先算出加权平均月价。" },
|
|
91
|
+
{ question: "上月 MRR 为零时怎么办?", answer: "工具仍会返回本月 MRR 和 ARR,但不会显示环比增长率,因为分母为零时百分比增长没有可靠含义。" },
|
|
92
|
+
{ question: "可以把直接访问流量当成新客户吗?", answer: "不可以。直接访问可能包含回访者、现有客户、员工、书签访问和无法归因的会话。估算时只应计入一部分可用于获客的访问量。" },
|
|
93
|
+
{ question: "SaaS MRR 估算有多准确?", answer: "它只适合方向判断,不是精确结果。是否有参考价值取决于流量、价格、转化率和付费周期假设是否接近被评估产品。" },
|
|
94
|
+
{ question: "这个估算属于财务建议或估值意见吗?", answer: "不属于。它只是基于公开输入和你的假设得到的场景,不应作为会计证据、公司收入事实、财务建议或估值结论。" },
|
|
95
|
+
{ question: "输入的数据会离开浏览器吗?", answer: "不会。当前版本在浏览器内完成计算,不上传输入值,也不需要注册账号。" },
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
widget: {
|
|
99
|
+
calculateMode: "计算 MRR", estimateMode: "估算 SaaS MRR", modeSwitchLabel: "切换计算与估算 MRR 模式",
|
|
100
|
+
calculateHint: "使用已知付费客户和订阅数据,得到计算结果。", estimateHint: "使用公开流量和价格进行粗略估算,并非公司披露收入。",
|
|
101
|
+
activeCustomers: "活跃付费客户数", recurringAmount: "每位客户的经常性金额", billingPeriod: "计费周期", previousMrr: "上月 MRR", optional: "可选", addPreviousMrr: "添加上月 MRR(可选)", currency: "币种",
|
|
102
|
+
monthlyVisits: "估算的网站月访问量", planPrice: "有代表性的公开套餐价格", showAssumptions: "调整估算假设", hideAssumptions: "收起估算假设",
|
|
103
|
+
assumptionNote: "这些只是起始假设,不是行业基准。请根据被评估产品进行调整。", eligibleVisitShare: "可用于获客的访问占比(%)", visitorToPaidRate: "访问者转付费率(%)", averagePaidLifetime: "平均付费周期(月)",
|
|
104
|
+
periods: { month: "月付", quarter: "季付", year: "年付" }, calculatedLabel: "计算结果", estimatedLabel: "估算结果",
|
|
105
|
+
calculatedResultTitle: "月度经常性收入", estimatedResultTitle: "SaaS 收入方向性估算", calculatedMrr: "计算 MRR", estimatedMrr: "估算 MRR", arr: "ARR", estimatedArr: "估算 ARR", monthlyArpa: "月度 ARPA", monthlyPlanPrice: "月度套餐价格", momGrowth: "MRR 环比增长", newPaidCustomers: "每月新增付费客户", activePaidCustomers: "估算活跃付费客户", formula: "算式检查", perMonth: "每月", assumptionsUsed: "本次使用的假设", notAvailable: "无法计算",
|
|
106
|
+
calculatedGuidance: "只计入经常性订阅收入,排除一次性费用、税费和非经常性服务。", estimateDisclaimer: "仅为公开数据估算。实际流量质量、转化率、套餐结构、流失和收入可能不同。",
|
|
107
|
+
copyResult: "复制结果", copied: "已复制", reset: "重置", fixInputsTitle: "检查标红的输入项", fixInputsBody: "输入有效数值后,结果会自动更新。",
|
|
108
|
+
errors: { nonNegative: "请输入零或正数。", positive: "请输入大于零的数值。", percent: "请输入 0 到 100 之间的百分比。" },
|
|
109
|
+
},
|
|
110
|
+
} as const;
|
|
111
|
+
|
|
112
|
+
export default mrrCalculator;
|
|
@@ -634,8 +634,9 @@ const toolsUi = {
|
|
|
634
634
|
downloadZip: "下载 ZIP",
|
|
635
635
|
selectedTitle: "选中图标",
|
|
636
636
|
downloadPng: "下载 PNG",
|
|
637
|
-
outputEmptyTitle: "
|
|
638
|
-
outputEmptyHint: "
|
|
637
|
+
outputEmptyTitle: "上传后在这里检查文件包",
|
|
638
|
+
outputEmptyHint: "当前平台选择会生成下面这些主要目录。上传源图并生成后,这里会切换为真实 PNG 预览和 ZIP 下载。",
|
|
639
|
+
outputExampleLabel: "app-icon-assets.zip 示例结构",
|
|
639
640
|
platforms: {
|
|
640
641
|
all: "App Store + Google Play",
|
|
641
642
|
apple: "Apple App Store / iOS",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
const appIconResizer = {
|
|
2
2
|
meta: {
|
|
3
|
-
title: "App Icon
|
|
3
|
+
title: "App Icon 尺寸產生器:iOS 與 Android",
|
|
4
4
|
description:
|
|
5
|
-
"
|
|
6
|
-
intro: "
|
|
5
|
+
"上傳方形 App Icon,在瀏覽器本地產生 Xcode AppIcon、Google Play 512 與 Android launcher 圖示包,預覽後下載 ZIP。",
|
|
6
|
+
intro: "上傳 1024px+ 方形原圖,本地產生 Xcode AppIcon、Google Play 圖示和 Android legacy launcher 檔案。",
|
|
7
7
|
category: "App 上架工具",
|
|
8
8
|
keywords: [
|
|
9
9
|
"app icon 切圖",
|
|
@@ -19,48 +19,61 @@ const appIconResizer = {
|
|
|
19
19
|
guide: {
|
|
20
20
|
heroVisualAlt:
|
|
21
21
|
"App Icon 資源包視覺圖,展示一個源圖標導出為商店提交圖標、Xcode 資源和 Android launcher 文件。",
|
|
22
|
-
workspaceHeading: "App Icon
|
|
22
|
+
workspaceHeading: "App Icon 尺寸包產生器",
|
|
23
23
|
workspaceHint:
|
|
24
|
-
"
|
|
24
|
+
"一張原圖,本地產生商店與工程圖示 ZIP。",
|
|
25
25
|
workspaceBadge: "PNG + ZIP",
|
|
26
26
|
standard: {
|
|
27
27
|
benefits: {
|
|
28
|
-
title: "
|
|
28
|
+
title: "為什麼用這個工具",
|
|
29
29
|
cards: [
|
|
30
30
|
{
|
|
31
|
-
title: "
|
|
32
|
-
body: "
|
|
31
|
+
title: "一次產生交付檔案",
|
|
32
|
+
body: "不用逐張建立畫板和匯出。一次產生 Xcode AppIcon、Google Play 512 與 Android legacy launcher 檔案。",
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
|
-
title: "
|
|
36
|
-
body: "
|
|
35
|
+
title: "目錄和命名已整理",
|
|
36
|
+
body: "商店上傳圖、Xcode 資源與 Android 工程檔案按用途分組,下載後不用自己建目錄或逐張改名。",
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
|
-
title: "
|
|
40
|
-
body: "
|
|
39
|
+
title: "先預覽再下載",
|
|
40
|
+
body: "先檢查透明背景、裁切方式和檔案大小風險。切圖和 ZIP 打包都在目前瀏覽器完成。",
|
|
41
41
|
},
|
|
42
42
|
],
|
|
43
43
|
},
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
44
|
+
outputPreview: {
|
|
45
|
+
eyebrow: "範例輸出",
|
|
46
|
+
title: "下載包裡有什麼",
|
|
47
|
+
intro: "選擇雙平台後,檔案會按實際交付位置分組。下面是目前工具會產生的目錄和檔案。",
|
|
48
|
+
inputLabel: "範例輸入",
|
|
49
|
+
input: "一張 1024 × 1024 方形 PNG,選擇 Apple + Google Play / Android",
|
|
50
|
+
outputLabel: "ZIP 主要內容",
|
|
51
|
+
fields: [
|
|
52
|
+
{
|
|
53
|
+
label: "Apple/AppIcon.appiconset",
|
|
54
|
+
body: "iPhone、iPad 與 ios-marketing 相容尺寸,附 Contents.json。",
|
|
55
55
|
},
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
{
|
|
57
|
+
label: "Apple/AppStoreIcon-1024.png",
|
|
58
|
+
body: "供團隊在上架前檢查主體、留白和品牌一致性的 1024px 副本。",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
label: "GooglePlay/app-icon-512.png",
|
|
62
|
+
body: "Play Console store listing 使用的 512 × 512 PNG。",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
label: "Android/res/mipmap-*",
|
|
66
|
+
body: "mdpi 到 xxxhdpi 的 legacy launcher PNG;不含 Adaptive Icon 圖層。",
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
imageTextSections: [
|
|
58
71
|
{
|
|
59
72
|
id: "platform-scope",
|
|
60
|
-
title: "
|
|
73
|
+
title: "下載後怎麼使用",
|
|
61
74
|
body: [
|
|
62
|
-
"
|
|
63
|
-
"
|
|
75
|
+
"把 Apple/AppIcon.appiconset 匯入 Xcode asset catalog,再隨 build 提交;GooglePlay/app-icon-512.png 用於 Play Console store listing。",
|
|
76
|
+
"Android/res/mipmap-* 是 legacy launcher 工程資源。如果專案使用 Adaptive Icon,仍需在 Android Studio 設定前景、背景和可選的 monochrome 圖層。",
|
|
64
77
|
],
|
|
65
78
|
image: {
|
|
66
79
|
src: "/tools/app-icon-resizer-section-variation-8bit-v3.webp",
|
|
@@ -69,10 +82,10 @@ const appIconResizer = {
|
|
|
69
82
|
},
|
|
70
83
|
{
|
|
71
84
|
id: "handoff-review",
|
|
72
|
-
title: "
|
|
85
|
+
title: "使用前需要知道",
|
|
73
86
|
body: [
|
|
74
|
-
"
|
|
75
|
-
"
|
|
87
|
+
"非方形圖片會置中裁成方形,不會拉伸。正式交付應優先使用方形滿版源圖,也不要預先加入圓角或外陰影。",
|
|
88
|
+
"圖片讀取、縮放和 ZIP 打包都在瀏覽器本地完成。正式發布前仍需複核平台最新規則、品牌版權,以及淺色和深色背景下的辨識度。",
|
|
76
89
|
],
|
|
77
90
|
image: {
|
|
78
91
|
src: "/tools/app-icon-resizer-section-support-8bit-v3.webp",
|
|
@@ -82,31 +95,56 @@ const appIconResizer = {
|
|
|
82
95
|
},
|
|
83
96
|
],
|
|
84
97
|
generation: {
|
|
85
|
-
title: "
|
|
98
|
+
title: "三步完成",
|
|
86
99
|
imageAlt: "上傳 App Icon 後選擇平臺、裁切預覽並導出 ZIP 的 8bit 流程圖",
|
|
87
100
|
ctaLabel: "生成圖標資源包",
|
|
88
101
|
steps: [
|
|
89
102
|
{
|
|
90
|
-
title: "
|
|
91
|
-
body: "
|
|
103
|
+
title: "上傳並選擇平台",
|
|
104
|
+
body: "上傳 PNG、JPG 或 WebP,再選擇 Apple、Google Play / Android 或雙平台。Apple 包需要原圖短邊至少 1024px。",
|
|
92
105
|
},
|
|
93
106
|
{
|
|
94
|
-
title: "
|
|
95
|
-
body: "
|
|
107
|
+
title: "本地生成尺寸包",
|
|
108
|
+
body: "瀏覽器完成裁切、縮放、命名和目錄整理,同時生成 PNG、Contents.json 與 README。",
|
|
96
109
|
},
|
|
97
110
|
{
|
|
98
|
-
title: "
|
|
99
|
-
body: "
|
|
111
|
+
title: "預覽並下載 ZIP",
|
|
112
|
+
body: "在結果區篩選平台、檢查透明網格和檔案大小風險,然後下載完整 ZIP 或單個 PNG。",
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
referenceTable: {
|
|
117
|
+
title: "實際輸出與使用位置",
|
|
118
|
+
intro: "現代 Xcode 可以從單張 1024px 圖示產生較小變體;Tomako 仍提供完整相容型 AppIcon.appiconset,方便接入現有專案和團隊交付。",
|
|
119
|
+
mobileHint: "表格可左右滑動,查看完整檔案去向。",
|
|
120
|
+
columns: ["輸出組", "包含內容", "目前用途", "使用位置"],
|
|
121
|
+
rows: [
|
|
122
|
+
{
|
|
123
|
+
label: "Xcode AppIcon",
|
|
124
|
+
cells: ["20–1024px 相容尺寸,附 Contents.json", "iOS / iPadOS 工程圖示", "Xcode asset catalog"],
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
label: "Apple 1024 副本",
|
|
128
|
+
cells: ["Apple/AppStoreIcon-1024.png", "團隊視覺複核,不是另一套固定上傳流程", "上架前檢查主體與留白"],
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
label: "Google Play",
|
|
132
|
+
cells: ["GooglePlay/app-icon-512.png", "512 × 512 PNG;超過 1024KB 時提示", "Play Console store listing"],
|
|
100
133
|
},
|
|
101
134
|
{
|
|
102
|
-
|
|
103
|
-
|
|
135
|
+
label: "Android legacy launcher",
|
|
136
|
+
cells: ["48 / 72 / 96 / 144 / 192px", "相容型 launcher PNG", "Android/res/mipmap-*"],
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
label: "交付說明",
|
|
140
|
+
cells: ["README.txt", "目錄用途與邊界說明", "設計、工程與 ASO 交接"],
|
|
104
141
|
},
|
|
105
142
|
],
|
|
143
|
+
note: "Google Play 圖示還需符合平台的 PNG、檔案大小和內容規範。目前不產生 Android Adaptive Icon 的 foreground、background 或 monochrome 圖層。",
|
|
106
144
|
},
|
|
107
145
|
faqIntro:
|
|
108
|
-
"
|
|
109
|
-
faqCtaLabel: "
|
|
146
|
+
"先確認原圖要求和檔案去向,再判斷這套輸出是否適合你的發布流程。",
|
|
147
|
+
faqCtaLabel: "回到工作台",
|
|
110
148
|
},
|
|
111
149
|
whatYouGetHeading: "生成後會得到什麼",
|
|
112
150
|
valueVisualAlt: "整理好的 App Icon 文件包,包含 Xcode 資源目錄、商店提交圖標、Android 工程目錄和 ZIP 下載包。",
|
|
@@ -192,44 +230,34 @@ const appIconResizer = {
|
|
|
192
230
|
faqHeading: "常見問題",
|
|
193
231
|
faqItems: [
|
|
194
232
|
{
|
|
195
|
-
question: "
|
|
233
|
+
question: "原圖應該準備成什麼格式和尺寸?",
|
|
196
234
|
answer:
|
|
197
|
-
"
|
|
235
|
+
"建議使用 1024 × 1024 或更大的方形 PNG。JPG 和 WebP 也支援;只生成 Google Play / Android 時,原圖短邊至少需要 512px。",
|
|
198
236
|
},
|
|
199
237
|
{
|
|
200
|
-
question: "
|
|
238
|
+
question: "上傳的 App Icon 會儲存到伺服器嗎?",
|
|
201
239
|
answer:
|
|
202
|
-
"
|
|
240
|
+
"不會。圖片讀取、canvas 切圖和 ZIP 打包都在瀏覽器本地完成。重新整理頁面後檔案狀態會消失,原圖不會上傳伺服器。",
|
|
203
241
|
},
|
|
204
242
|
{
|
|
205
|
-
question: "
|
|
243
|
+
question: "生成的圖示能直接用於 App Store 和 Google Play 嗎?",
|
|
206
244
|
answer:
|
|
207
|
-
"
|
|
245
|
+
"可以作為工程接入和商店上傳素材,但正式發布前仍需複核。GooglePlay/app-icon-512.png 用於 Play Console;Apple/AppIcon.appiconset 應放入 Xcode,再隨 build 提交到 App Store Connect。",
|
|
208
246
|
},
|
|
209
247
|
{
|
|
210
248
|
question: "為什麼不自動加圓角或陰影?",
|
|
211
249
|
answer:
|
|
212
|
-
"
|
|
213
|
-
},
|
|
214
|
-
{
|
|
215
|
-
question: "源圖不是方形怎麼辦?",
|
|
216
|
-
answer:
|
|
217
|
-
"當前會按中心裁成方形,不會拉伸圖片。正式交付建議回到設計源文件導出方形滿版圖,避免主體偏移或邊緣被裁掉。",
|
|
250
|
+
"不用提前加入。商店和系統會套用自己的遮罩、圓角或陰影,預先處理可能造成二次裁切或邊緣不齊。",
|
|
218
251
|
},
|
|
219
252
|
{
|
|
220
|
-
question: "
|
|
253
|
+
question: "原圖不是方形或帶透明背景怎麼辦?",
|
|
221
254
|
answer:
|
|
222
|
-
"
|
|
255
|
+
"會置中裁成方形,不會拉伸圖片。透明像素會保留;正式發布前仍要檢查主體位置、裁切邊緣和不同背景下的辨識度。",
|
|
223
256
|
},
|
|
224
257
|
{
|
|
225
258
|
question: "這個工具會生成 Android adaptive icon 嗎?",
|
|
226
259
|
answer:
|
|
227
|
-
"
|
|
228
|
-
},
|
|
229
|
-
{
|
|
230
|
-
question: "圖片太小會怎樣?",
|
|
231
|
-
answer:
|
|
232
|
-
"選擇 Apple 或雙平臺時,源圖短邊低於 1024px 會被攔截;只生成 Google Play / Android 時,短邊低於 512px 會被攔截。Google Play 512 圖標超過 1024KB 時會顯示風險提示。",
|
|
260
|
+
"不會。目前輸出 Google Play 512 和 legacy launcher mipmap PNG,不生成 adaptive icon 的 foreground/background XML。你需要在 Android 工程裡另外設定。",
|
|
233
261
|
},
|
|
234
262
|
],
|
|
235
263
|
ctaPrimary: "繼續做商店截圖",
|