ワンクリックで
create-tool
为 EH-Tools 项目创建新工具的完整流程规范。当用户要求添加新工具、新功能页面、或提到"创建工具"、"添加工具"、"新建工具"时触发。涵盖工具注册、SVG 图标创建、页面组件编写、i18n 国际化、暗黑模式适配、首页展示配置等全部步骤。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
为 EH-Tools 项目创建新工具的完整流程规范。当用户要求添加新工具、新功能页面、或提到"创建工具"、"添加工具"、"新建工具"时触发。涵盖工具注册、SVG 图标创建、页面组件编写、i18n 国际化、暗黑模式适配、首页展示配置等全部步骤。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
| name | create-tool |
| description | 为 EH-Tools 项目创建新工具的完整流程规范。当用户要求添加新工具、新功能页面、或提到"创建工具"、"添加工具"、"新建工具"时触发。涵盖工具注册、SVG 图标创建、页面组件编写、i18n 国际化、暗黑模式适配、首页展示配置等全部步骤。 |
创建工具前,确认以下信息:
time | calc | text | image | lifeunit-converter在 src/static/icons/{icon-name}.svg 创建图标。
规范详见 svg-icon-guide.md。核心要求:
0 0 24 24,fill none#667eea2,细节 1.5参考模板: icon-template.svg
详见 tool-registry.md。按以下文件顺序修改:
2.1 src/types/tool.ts — 在 TOOLS 数组对应分类下添加:
{ id: '{tool-id}', name: '{中文名}', nameKey: 'tool.{camelCaseId}', icon: '{icon-name}', path: '/pages/{category}/{tool-id}/index', category: '{category}' }
2.2 src/pages.json — 在 pages 数组末尾添加路由
2.3 src/styles/variables.scss — 在对应分类的工具卡片渐变注释下添加:
$gradient-{icon-name}: linear-gradient(135deg, #色1 0%, #色2 100%);
2.4 src/components/common/ToolCard.vue — 在 TOOL_ICONS 和 TOOL_GRADIENTS 中添加映射
2.5 src/pages/index/index.vue — 在 TOOL_ICONS 中添加映射
3.1 src/i18n/zh.ts:
tool 对象中添加: {camelCaseId}: '{中文名}'title 字段3.2 src/i18n/en.ts:
在 src/pages/{category}/{tool-id}/index.vue 创建页面。
参考模板: page-template.vue,将 __TOOL_ID__ 替换为实际 tool-id,__CAMEL_ID__ 替换为 camelCase id。
样式规范详见 style-guide.md。核心要求:
:class="{ 'theme-dark': settingsStore.isDark }"<nav-bar :title="t('{camelCaseId}.title')" />
:show-back="false":visible="条件"var(--xxx)),不硬编码onShow 中调用 settingsStore.initTheme()(不需要手动设置导航栏标题,NavBar 组件会处理)t() 翻译函数@use '@/styles/variables.scss' as *⚠️ i18n 数组类型数据禁止使用 t() 获取
vue-i18n 的 t() 函数只能返回字符串,不能用于获取数组类型的翻译值(如星期名、星座名、生肖名等)。使用 t('key') 获取数组会导致运行时报错 Not found 'xxx' key in locale messages。
错误写法:
// ❌ 不要这样做 — t() 无法返回数组
const weekdays = t('ageCalculator.weekdays') as unknown as string[]
const zodiacNames = t('ageCalculator.zodiacNames') as unknown as string[]
正确写法: 将数组数据直接定义在组件中,不通过 i18n 获取:
// ✅ 直接在组件中定义数组常量
const weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
const zodiacNames = ['鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪']
适用场景: 星期名、月份名、星座名、生肖名、枚举选项列表等所有数组类型的本地化数据。i18n 翻译文件中可以保留这些数组定义作为参考,但页面组件中必须直接定义使用。
NavBar 组件说明 (位于 src/components/common/NavBar.vue):
<nav-bar
:title="t('toolName.title')" <!-- 标题,使用 i18n -->
:show-back="true" <!-- 是否显示返回按钮,默认 true -->
:visible="true" <!-- 是否显示导航栏,默认 true -->
:placeholder="true" <!-- 是否显示占位,默认 true -->
/>
每个新页面都必须配置微信系统分享功能,包括分享给好友和分享到朋友圈。
项目使用 Canvas 2D API 动态生成分享图,相关组件和工具:
| 组件/工具 | 位置 | 用途 |
|---|---|---|
ShareCanvas | src/components/common/ShareCanvas.vue | 工具分享图组件(通过 easycom 自动注册) |
ShareResult | src/components/common/ShareResult.vue | 结果分享图组件(带预览弹窗) |
shareCanvas.ts | src/utils/shareCanvas.ts | Canvas 绘制工具函数 |
⚠️ 重要:分享图图标禁止使用 emoji
分享图中的图标必须使用 Canvas 路径绘制,不要使用 emoji。shareCanvas.ts 中的 drawCategoryIcon() 函数已为每个工具类别实现了几何图标:
time: 时钟(圆圈 + 时针分针)calc: 计算符号(加号 + 减号 + 等号)text: 文档图标(带折角文档 + 文字线条)image: 图片框架(方框 + 山峰轮廓 + 太阳)life: 目标图标(三个同心圆 + 中心点)在页面模板中添加 <share-canvas> 组件:
<template>
<!-- 页面内容 -->
<!-- 工具分享图 Canvas -->
<share-canvas
canvas-id="{toolId}ShareCanvas"
:config="toolShareConfig"
@generated="onToolShareGenerated"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue'
// 工具分享图配置
const toolShareConfig = {
toolName: t('{camelCaseId}.title'),
category: '{category}' as const, // time | calc | text | image | life
subtitle: '工具描述' // 可选
}
// 分享图 URL
const toolShareImageUrl = ref('')
function onToolShareGenerated(url: string) {
toolShareImageUrl.value = url
}
</script>
配置项说明:
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
canvasId | string | 是 | Canvas 元素 ID,需唯一 |
config | ToolShareImageConfig | 是 | 分享图配置 |
width | number | 否 | 宽度,默认 600 |
height | number | 否 | 高度,默认 480 |
shareType | 'tool' | 'home' | 否 | 分享图类型,默认 'tool' |
ToolShareImageConfig 接口:
interface ToolShareImageConfig {
toolName: string // 工具名称
category?: string // 工具分类,用于图标绘制
subtitle?: string // 副标题/描述
primaryColor?: string // 主题色(可选,默认根据分类自动选择)
secondaryColor?: string // 渐变结束色
}
方式一: 使用 useShare composable(推荐,简单页面)
import { useShare } from '@/composables/useShare'
useShare({
title: t('{camelCaseId}.title'),
path: '/pages/{category}/{tool-id}/index'
})
方式二: 手动配置(需要动态分享图时)
import { onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app'
onShareAppMessage(() => {
return {
title: `EH Tools - ${t('{camelCaseId}.title')}`,
path: '/pages/{category}/{tool-id}/index',
imageUrl: toolShareImageUrl.value || '/static/eh-tools-logo.png'
}
})
onShareTimeline(() => {
return { title: `EH Tools - ${t('{camelCaseId}.title')}` }
})
对于 BMI、个税计算等需要分享计算结果的工具:
<template>
<!-- 分享按钮 -->
<button @click="showShareResult = true">分享结果</button>
<!-- 工具分享图 Canvas -->
<share-canvas
canvas-id="{toolId}ShareCanvas"
:config="toolShareConfig"
@generated="onToolShareGenerated"
/>
<!-- 结果分享图组件 -->
<share-result
v-model:visible="showShareResult"
:config="shareResultConfig"
@generated="onShareImageGenerated"
/>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
import type { ResultShareConfig } from '@/utils/shareCanvas'
import { getResultShareConfig } from '@/utils/share'
const showShareResult = ref(false)
const shareImageUrl = ref('')
// 结果分享图配置
const shareResultConfig = computed<ResultShareConfig>(() => ({
title: t('{camelCaseId}.title'),
resultLabel: '结果标签',
resultValue: '计算结果值',
resultUnit: '单位', // 可选
statusText: '状态文本', // 可选
statusColor: '#667eea', // 可选
subResults: [ // 可选,副结果列表
{ label: '身高', value: '170 cm' },
{ label: '体重', value: '60 kg' }
]
}))
function onShareImageGenerated(url: string) {
shareImageUrl.value = url
}
// 分享时优先使用结果图
onShareAppMessage(() => {
if (hasResult && shareImageUrl.value) {
return getResultShareConfig(
t('{camelCaseId}.title'),
'结果描述',
'/pages/{category}/{tool-id}/index',
shareImageUrl.value
)
}
return {
title: `EH Tools - ${t('{camelCaseId}.title')}`,
path: '/pages/{category}/{tool-id}/index',
imageUrl: toolShareImageUrl.value || '/static/eh-tools-logo.png'
}
})
</script>
ResultShareConfig 接口:
interface ResultShareConfig {
title: string // 标题
resultLabel: string // 结果标签
resultValue: string // 结果值
resultUnit?: string // 单位
statusText?: string // 状态文本(如"正常"、"偏高")
statusColor?: string // 状态颜色
subResults?: Array<{ // 副结果
label: string
value: string
}>
}
参考实现: src/pages/calc/bmi/index.vue
创建完成后逐项检查:
src/static/icons/,颜色为 #667eeasrc/types/tool.ts 中 TOOLS 数组已添加条目src/pages.json 中已注册路由src/styles/variables.scss 中已添加渐变色变量src/components/common/ToolCard.vue 中 TOOL_ICONS 和 TOOL_GRADIENTS 已添加src/pages/index/index.vue 中 TOOL_ICONS 已添加src/i18n/zh.ts 已添加工具名称和工具翻译对象src/i18n/en.ts 已添加对应英文翻译<nav-bar> 自定义导航栏组件t() 函数<share-canvas> 组件生成工具分享图onShareAppMessage 和 onShareTimeline 分享钩子