en un clic
code-style
提供项目代码风格指南,或根据代码风格审查/重构代码。每当需要把控【代码风格】时,请主动使用该技能。
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Menu
提供项目代码风格指南,或根据代码风格审查/重构代码。每当需要把控【代码风格】时,请主动使用该技能。
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Basé sur la classification professionnelle SOC
使用 Nitro v3 框架和 H3 编写服务端 API 的技能。适用于后端接口开发、Mock 数据迁移到 Neon 数据库、以及编写符合 Drizzle ORM 标准的查询逻辑。当需要开发新的 CRUD 接口或修复现有后端逻辑时使用此技能。
规范类型项目(apps/type)的代码组织方式、导出语法和文件结构。用于解决类型导出冲突、创建统一导出入口、处理重复导出等问题。适用于类型项目开发、类型错误修复、代码规范实施场景。在处理类型项目的代码写法时,请使用本技能。
当你修改数据库结构或种子生成脚本时,请务必阅读并遵循此指南,以防止性能问题、数据一致性崩溃和部署失败。新 Schema 应在 apps/type 中创建。
数据库 Schema 变更时的全项目同步检查清单。当修改 apps/type 中 schema.ts 的表字段、新增数据库表、或删除表时,使用此技能确保类型项目、数据库迁移、后端接口、前端页面、种子数据和技能文档全部同步更新,避免遗漏。
当用户要求在 bug 已经定位并修复后,记录排错经验、事故结论、AI 记忆更新、复盘摘要或本地 MCP 记忆时使用。这个技能只负责沉淀"发生了什么、为什么会发生、如何修好、以后要记住什么",不要把它用于实际修复 bug。
新建公共组件规范专家 - 指导在 src/components/common 目录下创建符合项目规范的公共组件,包括文件结构、TypeScript 类型、Vue 组件、文档和测试页面。 触发条件(满足任意一项即触发): - 任务包含"新建组件"、"公共组件"、"common 组件"、"创建组件"等关键词 - 需要在 src/components/common 目录下创建新组件 - 需要创建可复用的业务组件(如表单分区标题、操作按钮组、信息展示卡片) - 需要编写组件的 TypeScript 类型定义 - 需要编写组件使用文档(index.md) - 需要创建组件测试页面(src/pages/test-use/) - 用户提及"组件规范"、"组件文档"、"组件测试"等关键词 必须协同的技能: - beautiful-component-design(组件美化时)- 图标、响应式设计、表单分区标题 - component-migration(从旧组件迁移时)- ColorUI → wot-design-uni - use-wd-form(组件内包含表单时)- 表单结构、wd-picker、校验规则 禁止事项: - 禁止在 components 目录外创建公共组件 - 禁止不编写组件文档(index.md) - 禁止不提供使用示例和测试页面 - 禁止组件命名不规范(必须使用短横线命名法) - 禁止不定义 TypeScript 类型(types.ts) - 禁止在组件文件顶部不添加说明注释 - 禁止不使用 withDefaults 设置 props 默认值 覆盖场景:所有需要跨页面复用的业务组件,包括表单分区标题(FormSectionTitle)、操作按钮组(ActivityActions)、信息展示卡片(ActivityInfo)、加载状态组件(ZPagingLoading)等。
| name | code-style |
| description | 提供项目代码风格指南,或根据代码风格审查/重构代码。每当需要把控【代码风格】时,请主动使用该技能。 |
在你为本项目生成代码时,请遵守以下的代码风格与要求:
在执行该代理时,请不要运行任何格式化命令。
生成的代码尽可能使用 jsdoc 注释风格。
// 业务配置
/** 业务配置 */
就比如 element-plus 组件库的按钮组件,你应该生成 <ElButton> 而不是 <el-button>
<el-button type="warning" :icon="useRenderIcon('ep:edit')" @click="handleEditEmployee(row)">
{{ transformI18n($t("common.buttons.edit")) }}
</el-button>
<ElButton type="warning" @click="handleEdit(row)">
{{ transformI18n($t("common.buttons.edit")) }}
</ElButton>
<ElButton> 的代码风格根据不同的业务操作行为,生成不同的按钮 type 样式,针对写死的,给定的业务按钮,其类型是固定的。如下要求:
新增按钮用 primary 类型。
<template>
<ElButton type="primary"> {{ transformI18n($t("common.buttons.add")) }} </ElButton>
</template>
修改按钮用 warning 类型。
<template>
<ElButton type="warning"> {{ transformI18n($t("common.buttons.edit")) }} </ElButton>
</template>
删除按钮用 danger 类型。
<template>
<ElButton type="danger"> {{ transformI18n($t("common.buttons.del")) }} </ElButton>
</template>
如果需要写实现具体业务的按钮,就使用 info 类型。
<template>
<ElButton type="info">
{{ transformI18n($t("propertyManage_communityManage.house-decoration.decorationOk")) }}
</ElButton>
<ElButton type="info" @click="gotoHouseDecorationPage(row)">
{{ transformI18n($t("propertyManage_communityManage.house-decoration.trackingRecord")) }}
</ElButton>
</template>
按钮组件不允许增加多余的配置属性。在没有得到明确的指令时,默认执行本子代理时,不应该为按钮组件增加多余的属性配置。
<template>
<ElButton type="primary" size="small" link @click="handleDelete(row)">
{{ transformI18n($t("common.buttons.add")) }}
</ElButton>
</template>
<template>
<ElButton type="primary" @click="handleDelete(row)"> {{ transformI18n($t("common.buttons.add")) }} </ElButton>
</template>
你不应该增加冗余的配置。就应该保留唯一的 type 属性。其余诸如 size 和 link 这样的属性,都不应该配置。
<template>
<ElButton type="primary" @click="openDialog({ mode: 'add' })">
<template #icon>
<IconifyIcon icon="ep:plus" />
</template>
{{ transformI18n($t("common.buttons.add")) }}
</ElButton>
</template>
不应该使用 icon 插槽来配置任何形式的按钮。
<template>
<ElButton type="primary" @click="openDialog({ mode: 'add' })">
{{ transformI18n($t("common.buttons.add")) }}
</ElButton>
</template>
不允许私自使用 icon 装饰。
大部分模块是全局导入的,不需要你专门处置。特别是某些模块,不需要你手动写导入语句。
其中,getRouteRank 函数不需要你手动导入。
导入语句必须在 definePage 页面宏的下方。不要写在 definePage 的上面。
import { ref } from "vue";
import { getRouteRank } from "@/router/rank/getRouteRank";
definePage({
meta: {
title: "系统配置",
icon: "f7:menu",
roles: ["开发团队"],
rank: getRouteRank("settingManage.systemManage.systemConfig"),
},
});
definePage 宏的下方。getRouteRank 函数。definePage({
meta: {
title: "系统配置",
icon: "f7:menu",
roles: ["开发团队"],
rank: getRouteRank("settingManage.systemManage.systemConfig"),
},
});
import { ref } from "vue";
几乎全部的组件,都不需要你设置 size 配置。除了模板内已经有的 size 写法依以外,其他的组件都不需要你主动设置组件的尺寸大小。
我们生成的模板代码,要尽可能满足 i18n 的需求。
按钮的命名必须严格的使用 i18n 工具,不要自己直接写中文。对于常用的按钮来说,绝大多数的名称都已经准备好了,不需要你写中文名称。
这是全部的 i18n 翻译文本,你应该积极地阅读现有的 i18n 配置文件,学会复用现存的 i18n 配置文本。
请读取以下目录:
apps\admin\locales
我们的目的是套模板,不要生成多余的 i18n 文本配置文件。在你根据图片识别业务的字段名称时,你应该直接使用其中文名,不要去新建专门的业务用 i18n 配置文件。
在你处理 i18n 文本时,请不要新增冗余的按钮文本。比如新增、修改、删除按钮这些文本。这些公共的文本已经在以下的配置文件内准备就绪了。
请你阅读下面的翻译文本,并确保不要新建任何冗余的按钮文本。
apps\admin\locales\en\common.yamlapps\admin\locales\zh-CN\common.yamltransformI18n 函数尽管我们项目使用了全局导入,可是 transformI18n 函数往往在 vue 模板内直接使用,因此该函数需要你手动导入。
/** 导入语句 */
import { transformI18n } from "@/plugins/i18n";
在你使用 i18n 的模板插值语法时,请你使用以下代码写法来完成翻译。
import { useI18n } from "vue-i18n";
const { t } = useI18n();
请你用组合式 api 提供的 t 函数来使用模板插值语法。
针对 apps/admin/locales/en/*.yaml 和 apps/admin/locales/zh-CN/*.yaml 的 i18n 文本配置文件,满足以下规则的文本,都应该用双引号括起来。
冒号也作为文本的一部分,为了避免出现 yaml 的语法识别错误,应该连同冒号也一同放在双引号内部。
titleCharCount: Title characters:
titleCharCount: "Title characters:"
为了防止前缀的括号造成 yaml 语法错误,这里应该连同整行文本都纳入双引号内。
operationSuccess: {operation} successful
operationSuccess: "{operation} successful"
你应该使用正确的 i18n key。
错误例子:
<template>
<ElButton>
{{ transformI18n($t("common.buttons.view")) }}
</ElButton>
</template>
我们是不存在错误的 common.buttons.view key 的,请不要识别错误。
正确例子:
<template>
<ElButton>
{{ transformI18n($t("common.buttons.info")) }}
</ElButton>
</template>
正确的 key 是 common.buttons.info 。这是你常见的错误,请不要使用错误的 key 。
apps/admin/src/plugins/i18n.ts 已经实现了当前项目真实生效的 i18n 加载规则。你在页面里编写 i18n key 时,必须以运行时是否真的能被解析为准,不要只看 key 的命名像不像正确。
transformI18n 或 i18n.global.t 解析到。apps/admin/locales 和 apps/admin/src/plugins/i18n.ts 确认实际可用路径。当前项目的 locale 加载器会先根据文件名挂载命名空间,并对文件名中的 -、_ 做 camelCase 规整。同时,它兼容本项目历史上已经存在的“文件名一层,内容再包一层命名空间”的旧写法。
dev-team.yaml 这类文件,运行时命名空间会按 devTeam 解析。setting-manage_organize-manage.yaml 这类文件,如果内容顶层是 settingManage,那么运行时可以解析出 settingManage.organizeManage.*。foo-bar.yaml 里却写 baz.xxx 这种跨命名空间的内容,这会让页面极易出现 raw key。示例:
# 文件:apps/admin/locales/zh-CN/dev-team.yaml
devTeam:
menuManage:
catalog:
pageTitle: 菜单目录
<template>
<span>{{ transformI18n($t("devTeam.menuManage.catalog.pageTitle")) }}</span>
</template>
common.buttons 先复用,再补齐按钮文案优先复用 common.buttons.*。如果确实缺少通用按钮 key,并且该按钮会在多个页面复用,那么应该补到公共词典,而不是在业务 yaml 里重复造词。
apps/admin/locales/zh-CN/common.yamlapps/admin/locales/en/common.yamlcommon.buttons.addcommon.buttons.editcommon.buttons.delcommon.buttons.infocommon.buttons.detailcommon.buttons.exportcommon.buttons.enablecommon.buttons.disablecommon.buttons.documentcommon.buttons.filecommon.buttons.resetPasswordcommon.buttons.permissionConfigcommon.buttons.associateUnitcommon.buttons.associateEmployeecommon.buttons.batchAuditcommon.buttons.batchReprintcommon.buttons.view 依然是错误 key。不要再生成这个 key。common.buttons.info 或 common.buttons.detail,但不要新造 view。transformI18n 与 useI18n 的分工transformI18n($t("..."))。const { t } = useI18n()。useI18n,也不能绕过 key 校验。你传给 t 的 key 仍然必须是 apps/admin/locales 中真实存在、且能被当前加载器正确解析的 key。正确例子:
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const dialogTitle = t("settingManage.organizeManage.staffInfo.pageTitle");
transformI18n 的唯一职责,与动态配置的正确刷新方式transformI18n 是当前后台项目唯一的基础翻译入口,负责把 i18n key 解析成当前语言文本。renderI18n 不再是推荐能力。不要再在页面、表单、弹窗内新建本地 renderI18n helper。computed(...)、withLocale(...)、函数型 title / footerButtons.label 这些响应式结构,而不是额外包一层本地翻译函数。transformI18n($t("..."))。useI18n().t(...) 或 i18n.global.t(...),不要再发明新的 helper。模板示例:
<ElButton type="primary">
{{ transformI18n($t("common.buttons.add")) }}
</ElButton>
脚本配置示例:
const columns = withLocale<TableColumnList>(() => [
{
headerRenderer: createHeaderRenderer(transformI18n($t("common.table.operation"))),
slot: "operation",
},
]);
use-i18n-config当你在 apps/admin/src/pages/**/index.vue、form.vue、dialog.ts 里实现 i18n 时,默认应该优先使用:
import { useI18nConfig } from "@/composables/use-i18n-config";
这套组合式 API 专门用于处理“需要跟随语言切换而动态刷新”的配置对象。它的核心用途如下:
computed 配置对象、表格列头渲染器、弹窗标题工厂等。use-i18n-config 内部二次封装 $t,也不要在组件里调用 tLabel("xxx")、t("xxx") 这类二次包装函数来读取 key。$t("...")为了让 VSCode 的 i18n Ally、pure-admin 相关阅读体验和键值映射提示正常工作,组件里必须直接出现 $t("xxx.xxx")。
错误示例:
const { tLabel } = useI18nConfig();
const title = computed(() => tLabel("devTeam.configManage.center.pageTitle"));
正确示例:
const title = computed(() => transformI18n($t("devTeam.configManage.center.pageTitle")));
再强调一次:
use-i18n-config 处理“配置对象要跟随语言切换刷新”的结构性问题。$t("...")。$t 包进新的 helper 再从组件里调用,否则 VSCode 插件无法稳定映射中文含义。definePage.meta.title 改成 i18n key 后,要补一行中文注释当你把页面 definePage({ meta: { title } }) 从中文标题改成 i18n key 时,不要直接把中文删掉。必须在 title 上方补一行中文注释,保留这个页面原本的人类可读标题,方便后续维护者快速识别页面语义。
错误示例:
definePage({
meta: {
title: "devTeam.menuManage.group.pageTitle",
icon: "mdi:group",
roles: ["开发团队"],
rank: getRouteRank("devTeam.menuManage.group"),
},
});
正确示例:
definePage({
meta: {
// 菜单组
title: "devTeam.menuManage.group.pageTitle",
icon: "mdi:group",
roles: ["开发团队"],
rank: getRouteRank("devTeam.menuManage.group"),
},
});
补充要求:
title 的正上方,不要挪到 meta 外层。headerRenderer表格列头需要支持运行时切换语言时,不要继续写静态 label。
错误示例:
const columns = ref<TableColumnList>([
{
label: transformI18n($t("devTeam.configManage.item.fields.configName")),
prop: "configName",
},
{
label: transformI18n($t("common.table.operation")),
slot: "operation",
},
]);
正确示例:
const { createHeaderRenderer, withLocale } = useI18nConfig();
const columns = withLocale<TableColumnList>(() => [
{
headerRenderer: createHeaderRenderer(transformI18n($t("devTeam.configManage.item.fields.configName"))),
prop: "configName",
},
{
headerRenderer: createHeaderRenderer(transformI18n($t("common.table.operation"))),
slot: "operation",
},
]);
特别注意:
headerRenderer。headerRenderer。computed,不要继续堆静态 ref以下这些配置对象,默认应该写成 computed:
columnspureTableBarPropsplusSearchColumnsplusSearchPropsplusFormColumnsplusFormRules错误示例:
const pureTableBarProps = ref<PureTableBarProps>({
title: transformI18n($t("devTeam.configManage.item.pageTitle")),
columns: columns.value,
});
正确示例:
const pureTableBarProps = computed<PureTableBarProps>(() => ({
title: transformI18n($t("devTeam.configManage.item.pageTitle")),
columns: columns.value,
}));
原因:
ref({ ...静态字符串 }) 只会在初始化时求值一次。computed/withLocale + transformI18n/createHeaderRenderer。ref 对象。form.vue 里表单配置必须转成 computed在 form.vue 里,以下内容不要继续用静态 ref:
plusFormColumnsplusFormRules推荐写法:
const translatedStatusOptions = computed(() =>
statusOptions.map((option) => ({
...option,
label: transformI18n($t(`xxx.form.options.status.${option.value}`)),
})),
);
const plusFormColumns = computed<PlusColumn[]>(() => [
{
label: transformI18n($t("xxx.fields.status")),
prop: "status",
valueType: "select",
options: translatedStatusOptions.value,
},
]);
const plusFormRules = computed<PlusFormRules>(() => ({
status: [
{
required: true,
message: transformI18n($t("xxx.form.validation.selectStatus")),
trigger: "change",
},
],
}));
ReDialog 现在已经支持函数型 title 和 footerButtons.label。凡是弹窗打开后仍然需要跟随语言切换更新文案的地方,都应该写成函数。
错误示例:
addDialog({
title: `${modeText.value}${transformI18n($t("devTeam.configManage.item.pageTitle"))}`,
footerButtons: [{ label: transformI18n($t("common.buttons.cancel")) }],
});
正确示例:
addDialog({
title: () => `${modeText.value}${transformI18n($t("devTeam.configManage.item.pageTitle"))}`,
footerButtons: [
{ label: () => transformI18n($t("common.buttons.cancel")) },
{ label: () => transformI18n($t("common.buttons.reset")) },
{ label: () => transformI18n($t("common.buttons.submit")) },
],
});
很多 @01s-11comm/type 导出的 options 内部仍然是静态中文 label。页面内不能直接拿来渲染,否则切换英文后,下拉框还是中文。
正确做法是在页面或表单内用 computed 包一层,再用 transformI18n($t(...)) 重新映射 label:
const translatedConfigTypeOptions = computed(() =>
configTypeOptions.map((option) => ({
...option,
label: transformI18n($t(`devTeam.configManage.item.form.options.${option.value}`)),
})),
);
改造一个页面时,默认按以下顺序做:
zh-CN 与 en。useI18nConfig。columns、搜索配置、表单配置改成 computed。label 改成 headerRenderer。title、footerButtons.label 改成函数。$t("key")本节前面如果出现任何 tLabel("key")、t("key")、ht("key")、dialogTitleT(...) 之类“由 use-i18n-config 二次封装 $t”的旧示例,全部以本小节为准覆盖。
强制规则:
$t("xxx.xxx")。use-i18n-config 只能处理结构层复用,不能再包装 $t 去读取 key。createHeaderRenderer 只能接收“已经翻译好的文本”,不能接收 i18n key。searchProps 只能接收组件内已经翻译好的 searchText、resetText。i18n Ally、pure-admin 代码阅读映射,依赖组件内直接出现 $t("key")。useI18nConfig().plusSearchButtonTexts,它只服务 PlusSearch 的 searchText/resetText,不扩展成任意 key helper。推荐写法:
const { locale, withLocale, createHeaderRenderer, searchProps } = useI18nConfig();
const columns = withLocale<TableColumnList>(() => [
{
headerRenderer: createHeaderRenderer(transformI18n($t("devTeam.configManage.item.fields.configName"))),
prop: "configName",
},
{
headerRenderer: createHeaderRenderer(transformI18n($t("common.table.operation"))),
slot: "operation",
},
]);
const plusSearchProps = searchProps(plusSearchDefaultValues);
PlusSearch 的按钮文案现在还可以直接复用 useI18nConfig 导出的固定 computed:
const { plusSearchButtonTexts } = useI18nConfig();
<PlusSearch
:key="locale"
:search-text="plusSearchButtonTexts.searchText"
:reset-text="plusSearchButtonTexts.resetText"
/>
这个导出只负责 common.buttons.search 和 common.buttons.reset 两个稳定公共文案。
不要据此继续向 use-i18n-config 添加任意 key 的读取函数。
额外强调:
renderI18n 已经不再是推荐写法,旧代码里如仍存在,应优先清理。computed、withLocale、函数型弹窗文案,而不是本地 helper。ref 对象的写法,都是当前项目必须主动纠正的误区。禁止写法:
const { tLabel, t, ht, valueT, optionText, dialogTitleT } = useI18nConfig();
.vscode/i18n-ally-custom-framework.yml 的配置目的与动态维护规范.vscode/i18n-ally-custom-framework.yml 是 VSCode i18n Ally 插件识别本项目 i18n 写法的工程配置文件。
它的目的只有三个:
i18n Ally 在 .vue、.ts、.js 文件里正确识别 key 的使用位置。当前文件如下:
languageIds:
- javascript
- typescript
- vue
usageMatchRegex:
- "[^\\w\\d]\\$t\\(['\"`]({key})['\"`]"
- "transformI18n\\(\\s*\\$t\\(['\"`]({key})['\"`]\\s*\\)"
这几项分别表示:
languageIds:指定需要扫描的语言类型。usageMatchRegex[0]:匹配组件或脚本里直接写出来的 $t("xxx.xxx")。usageMatchRegex[1]:匹配模板和脚本里常见的 transformI18n($t("xxx.xxx"))。维护这份文件时,必须遵守以下规则:
$t("key")”,那这里就应该优先只保留 $t(...) 和 transformI18n($t(...))。tLabel("key")、ht("key")、dialogTitleT("key"),就必须同步删除对应 regex。usageMatchRegex。动态维护策略:
.vscode/i18n-ally-custom-framework.yml。.vue 模板里的 transformI18n($t("...")) 仍可识别。<script setup> 里的 $t("...") 仍可识别。本项目当前的硬规则是:
.vscode/i18n-ally-custom-framework.yml 应该怎么写。也就是说:
$t("devTeam.configManage.center.pageTitle"),那 usageMatchRegex 就围绕 $t(...) 维护。transformI18n($t("common.buttons.add")),那就保留 transformI18n($t(...)) 的匹配。i18n Ally 无法直接映射,就应该改组件代码,而不是继续扩 regex。错误方向:
.vscode/i18n-ally-custom-framework.yml 里叠加 wrapper regex。tLabel("key"),却继续保留它的识别规则。正确方向:
.vscode/i18n-ally-custom-framework.yml 精确匹配这些正式写法。