lanhu-code-2-el-vue
介绍
本 Skill 用于将静态 HTML 页面改造为 Vue 2 + Element UI 的数据驱动动态页面,执行时会直接生成 Custom.vue 文件。
前置 Skill:ui-ux-max-pro
当本 Skill 被触发时,必须先执行 ui-ux-max-pro,再继续执行当前 Skill:
- 先读取并遵守
ui-ux-max-pro的SKILL.md。 - 先完成
ui-ux-max-pro要求的 UI/UX 分析、布局判断、视觉一致性检查与可用性评估。 - 将
ui-ux-max-pro的结论作为后续静态页改动态页的设计约束,但不得违反本 Skill 的「唯一信息源」限制。 - 然后再继续执行当前
lanhu-code-2-el-vue的index.vue→Custom.vue改造流程。 - 若找不到
ui-ux-max-pro,必须告知用户并暂停,不得直接开始生成或改写Custom.vue。
When to Use This Skill
在以下场景触发本 Skill:
- 用户要求「静态改动态」「把 index.vue 改成 Custom.vue」「按改造规范改造页面」
- 将某视图文件夹下的静态页面改为 Vue 2 + Element UI 动态页面
- 需要循环渲染、Element UI 替换、统一 class 命名、像素级还原设计稿
不适用: 全新页面从零开发、非 Vue 2/Element UI 技术栈、不涉及「静态→动态」改造。
执行指令(核心)
当本 Skill 被触发时,必须按照以下步骤直接执行代码改造,生成 Custom.vue 文件,而不是仅提供指导文档。
唯一信息源(生成 Custom.vue 时必须遵守)
生成/改写 Custom.vue 时,只允许使用以下材料作为页面结构与样式的依据:
src/views/${folderName}/index.vue的源码(模板、脚本、内联样式)。- 由 index.vue 直接或间接引用的样式文件(例如
<style src="./assets/index.css">、@import、import等,按路径相对index.vue解析;若存在链式@import,仅沿该链读取,不得扩大范围)。 - 在上述 Vue/CSS 中出现的图片等资源路径(保留或转换为
Custom.vue所需写法即可;无需读取图片二进制内容作「设计参考」)。
禁止:
- 不得为拼页面而读取、对照或照搬本仓库其他文件的内容,包括但不限于:同目录或其他视图下的
Custom.vue、index.vue(非当前${folderName})、公共组件源码、create.md、路由配置、package.json等。 - 不得以「已有某页的 Custom.vue 写法」为模板生成当前页;每一页只认当前文件夹的
index.vue+ 其引用 CSS + 资源路径。
路由配置的例外(仅交付阶段): 在 Custom.vue 已写入磁盘之后,允许打开项目路由文件(如 src/router/index.js)仅用于登记或校验 index.vue / Custom.vue 的访问路径,使页面可通过 URL 打开。禁止把路由里其它页面的 path/name/meta 当作当前页的 UI 稿源或布局依据。详见 data/router-sync.md 第 5 节。
说明: 本 Skill 正文与 data/ 下的规范文档属于操作规则(如何命名、如何用 Element UI 等),不是「页面稿源」。页面稿源仍仅限上述 1~3 项。
步骤 1: 获取目标文件夹名称
从用户输入中提取 ${folderName}(如:kz、shushi 等)。
步骤 2: 验证源文件存在性(必须执行)
// 必须存在:
必须存在: src/views/${folderName}/index.vue
// 样式文件:以 index.vue 实际引用为准(常见为 ./assets/index.css,若引用多个则均需存在)
// 读取 index.vue 后解析其 style src / @import / import 路径并逐一验证存在
// 目标文件(将被创建或覆盖):
目标文件: src/views/${folderName}/Custom.vue
⚠️ 重要: 若 index.vue 不存在,或其所引用的样式文件缺失,必须告知用户并停止执行。验证通过后,仅读取 index.vue 与这些被引用的样式文件(及链式 @import),不打开其他工程文件。
步骤 3: 读取源文件(仅限唯一信息源)
- 使用 Read 工具读取
src/views/${folderName}/index.vue。 - 根据
index.vue中的引用,仅读取其指向的 CSS(及该 CSS 内@import的下一层样式,若需要完整样式表)。 - 不要读取
package.json、路由文件、其他视图的Custom.vue等作为模板/稿源/样式依据(见上文「唯一信息源」;路由仅在步骤 8 用于登记,见data/router-sync.md)。
步骤 4: 分析源文件结构
分析内容:
- 识别页面布局 - 确定是单栏、双栏还是多栏布局
- 识别重复结构 - 找出需要循环渲染的部分(使用 v-for)
- 识别交互元素 - 找出按钮、输入框、多选、单选等可替换为 Element UI 的元素(开关保留原生 DOM,不替换为 el-switch)
- 识别样式特征 - 记录关键样式值(颜色、尺寸、间距)
- 识别伪控件(必做) - 源页面常用 div+文案+图标模拟表单控件,须按「6.3.4 伪控件识别与替换」规则识别并替换为 el-select、el-checkbox、el-input;取色须按 点击后展开的下拉面板的形态(图1 / 图2) 选用
el-color-picker-extend或el-color-picker(不以触发区单独判断;见 6.3 映射表、6.3.11、data/el-color-picker-extend.md§「颜色选择:触发与下拉的共同结构」),避免漏改或错用组件。
步骤 5: 生成 Custom.vue 文件
⚠️ 必须使用 Write 工具直接生成文件,而不是返回代码给用户!
生成的 Custom.vue 必须包含以下结构:
<template>
<div class="[folderName]_page_container">
<!-- 改造后的动态页面内容 -->
<!-- 1. 将重复结构改为 v-for 循环渲染 -->
<!-- 2. 将原生的 input、button、checkbox、radio 等替换为 Element UI 组件(开关不替换,保留原生结构) -->
<!-- 3. 保留所有样式,确保像素级一致 -->
</div>
</template>
<script>
export default {
name: '[FolderName]Custom',
data() {
return {
// 所有 template 中使用的数据必须在此定义
// 包括:列表数据、表单数据、状态变量等
}
},
methods: {
// 所有 @click、@change 等事件处理方法必须在此实现
// 命名规范:handle + 功能名(如 handleSearch、handleSubmit)
}
}
</script>
<style scoped>
/* 所有样式必须在此定义,禁止引用外部 index.css */
/* 使用 scoped 避免样式污染 */
/* 对 Element UI 组件使用 ::v-deep 进行样式覆盖 */
</style>
步骤 6: 改造规范(必须遵守)
6.1 文件操作规范
| 规则 | 说明 |
|---|---|
| ❌ 禁止修改源文件 | index.vue 及其引用的样式文件只能读取,绝对不能修改 |
| ✅ 只操作目标文件 | 所有代码只写入 Custom.vue |
| ✅ 唯一稿源 | 结构与样式依据仅限当前 index.vue + 其引用 CSS + 资源路径;禁止参考其他视图/其他 Custom.vue/路由等工程文件生成页面内容 |
| ✅ 使用 scoped 样式 | 所有样式必须在 <style scoped> 中定义 |
| ✅ 完整单文件组件 | Custom.vue 必须包含 template、script、style 三部分 |
6.2 命名规范
- Class 名仅使用下划线
_连接,不得包含任何数字(0-9) - 序位、顺序用英文词表示(如
first、second、left、right) - 命名公式:
[folderName]_[功能]_[内容]_[特征]
✅ 正确示例:
kz_header_container
kz_list_item
kz_button_primary
kz_math_cell_first
❌ 错误示例:
group_1 // 含数字
kz_cell_2 // 含数字
box-1 // 使用连字符
headerBox // 使用驼峰
6.3 Element UI 替换要求
凡有按钮、多选、单选、输入、分页、弹窗等,须替换为 Element UI 组件。不替换:开关保留源页面原生 DOM(如 div + @click、原生 input 等),不使用 el-switch。
替换映射表:
| 原元素 | Element UI 组件 | 说明 |
|---|---|---|
| 按钮 | el-button | 可点击按钮须绑定 @click,并在 methods 中实现对应方法 |
| 多选 | el-checkbox-group + el-checkbox | |
| 单选 | el-radio-group + el-radio | 互斥多选一;样式与源页一致,激活态与选中项须为主题色,见「6.3.10 单选框识别与主题色规范」 |
| 输入框(单行) | el-input | 带外框的搜索框须同时满足「6.3.1 带外框搜索框样式规范」 |
| 多行文本 | el-input type="textarea" | 可配 show-word-limit、maxlength |
| 下拉选择 | el-select + el-option | |
| 分页 | el-pagination | 需定义 currentPage、pageSize、total,实现 size-change、current-change;替换时必须删除原始分页全部静态内容(共 xxx 条、静态页码、上下页、条数/页等),仅保留一个 el-pagination,见「6.3.9 分页替换与主题色规范」 |
| 弹窗 | el-dialog | 需定义 dialogVisible,实现关闭/确定/取消方法 |
| 日期输入 | el-date-picker | |
| 下拉菜单 | el-dropdown + el-dropdown-menu | 需实现 @command 处理方法 |
| 进度条 | el-progress | |
| 评分 | el-rate | 星星颜色、评分数值须与源页面一致,见「6.3.2 el-rate 注意事项」 |
| 取色 / 填充(展开后的下拉为 图1:预设色块矩阵 + Hex/RGB/不透明度 +「最近使用」+ 吸管等;或页内静态整区模拟该形态) | el-color-picker-extend | 触发区长什么样不决定选型,见 data/el-color-picker-extend.md §「颜色选择:触发与下拉的共同结构」;全局注册见 main.js |
| 取色(展开后的下拉为 图2:Element 默认面板,SV 面 + 右侧竖向色相条 + 底部 Hex +「清空」「确定」) | el-color-picker | 常见触发器为 字体颜色(A+下划线+箭头)→ 透明叠层;删除页内重复取色区见 6.3.11;细则见 data/el-color-picker-extend.md |
替换时必须:
- 先删除该区域原有 DOM 结构(含该控件的全部相关 DOM,见下方「下拉框」说明)
- 再写入 Element UI 组件
- 同时完成 template、data()、methods 三部分(禁止只写 template 不写 methods/data)
- 用
::v-deep覆盖 Element UI 默认样式,保持视觉一致 - 可点击按钮:页面中所有可点击区域(上传、预览、确定、取消、智能合成等)须在 template 中绑定
@click="handleXxx",并在 methods 中实现handleXxx,命名建议handle+ 功能名(如 handleUploadImage、handleDialogConfirm)
下拉框替换时须删除的 DOM(通用规则): 除「当前选中项 + 箭头」的触发区外,若 index.vue 中还有独立的下拉选项列表(如浮层、侧边列表、鼓点-1~鼓点-11 等静态列表),须一并删除。替换为 el-select 后,选项由 el-select 自带的 dropdown 展示,不得保留原静态选项列表 DOM,否则会出现「识别了下拉框但页面上仍有两套选项」的问题。
6.3.1 带外框的搜索框(el-input)样式规范
当搜索框被包在带边框、圆角的白底容器内(如「搜索资源标题、ID」「搜索你想要的单词」)时,须满足:
- 外层容器:固定高度(如 48px)、宽度(如 688px)、圆角、边框(须设
border,如1px solid)、背景色;display: flex、align-items: center、box-sizing: border-box、overflow: hidden,使内部输入框垂直居中且不撑高。容器在 hover 与 focus-within 时边框须为主题色(.xxx_search_wrapper:hover、.xxx_search_wrapper:focus-within设border-color为页面主题色),详见data/recognition-and-fix.md9.8。 - .el-input-group:通过
::v-deep对.el-input-group做样式覆盖:display: flex、flex: 1、height: 100%、min-width: 0、border: none、background: transparent,避免出现双重边框或额外外框。 - .el-input / .el-input__inner:
.el-input在容器内height: 100%、flex: 1;.el-input__inner去掉自带边框(border: none)、背景透明、高度略小于容器约 2px(如容器 48px 则 inner 约 46px)、line-height与高度一致、border-radius仅左侧与容器一致(若右侧为 append 按钮则设为12px 0 0 12px)、box-sizing: border-box、padding-left为前缀图标留足空间(如 44px),避免双边框与错位。 - 占位符:
::v-deep .el-input__inner::placeholder设置 placeholder 颜色与设计稿一致(如rgba(153, 153, 153, 1))。 - 前缀图标:
.el-input__prefix使用display: flex、align-items: center、height: 100%,left与设计一致(如 16px);自定义 prefix 插槽根节点用display: inline-flex、align-items: center,图标尺寸与设计一致(如 16×16px)。 - 命名:类名使用
[folderName]_search_wrapper、[folderName]_search_input等规范命名。同一项目内所有带外框的搜索框均按此规则实现。
自检:容器高度与设计一致;容器有 border,hover 与 focus-within 时边框为主题色(见 9.8);无双重边框;.el-input-group 已覆盖无边框且 flex 占满;前缀图标与文字垂直对齐;placeholder 颜色正确;无错位或溢出。
6.3.1.1 placeholder 垂直居中与页面溢出(必做)
- placeholder 垂直居中:
.el-input__inner高度与容器一致(或略小 1~2px),line-height与高度一致,上下 padding 为 0;.el-input、.el-input-group设display: flex、align-items: center,使输入区在容器内垂直居中;必要时对::v-deep .el-input__inner::placeholder设相同 line-height。 - 输入框/按钮不溢出页面:页面根容器设
overflow-x: hidden;主卡片、Tab 行、底栏、列表区使用width: 100%+max-width: [设计稿宽度]+min-width: 0+box-sizing: border-box;带外框搜索框容器在 flex 中设flex: 1、min-width: 0、max-width: [设计稿宽度];底栏中间文案将固定大margin-left改为margin-left: auto,避免窄屏下溢出。
详见 data/search-input-and-page-overflow.md(识别步骤、修复方法、需求文案与自检清单)。
6.3.2 el-rate 评分组件注意事项
- 星星颜色:选中/未选中颜色须与源页面一致(打开 index.vue 查看),不可默认用橙色而源页为黄色。
- 评分数值:每个维度显示的实心星数须与源页面一致(如色彩 5 星、构图 5 星、想象力 3 星),不得全部默认 5 星或 3 星。
- 文字样式:「超赞」等评分文字的颜色、大小、位置须与源页面一致,用开发者工具对比。
- 样式覆盖:星星、文字、间距等均通过
::v-deep精确匹配源样式。
6.3.4 伪控件识别与替换(下拉框、多选框、单选框、搜索框)
源页面常使用 div + 文案 + 图标模拟表单控件,没有原生 <select>、<input type="checkbox">、<input type="radio"> 或带外框的 <input type="text">,改造时容易漏识别。须按以下规则识别并替换:
| 控件类型 | 识别特征(index.vue / index.css) | 替换为 | 说明 |
|---|---|---|---|
| 下拉框 select | 小容器内为「当前选中文案 + 右侧下拉箭头图标」、或「标签 + 可切换项」;样式为带边框、圆角的盒子(如 66×28px) | el-select + el-option | 在 data 中定义选中值(如 selectedXxx),options 与同页列表/配置一致 |
| 多选框 checkbox | 左侧为勾选图标容器(含勾/未勾图或方框)+ 右侧说明文案(如「全选所有模块」「当前配置应用于所有页面」);多行结构相同 | el-checkbox | 每项对应 data 中一个布尔(如 checkedAllModules、applyToAllPages) |
| 纵向模块勾选列 | 易漏识别:左侧仅为 ~16×16 方框切图(image-wrapper + img),无「全选」类长说明;右侧或邻列为模块名(音标、释义、例句、词组等);多行纵向对齐成列;或左侧 flex-col 堆叠多个方框与右侧多行标题行对行对应 | el-checkbox(无内联文案时隐藏 label)+ 右侧内容区 v-show/v-if 联动 | data 中用对象(如 moduleFlags)或多项布尔;禁止保留静态勾图;样式见 6.3.4.1 与 data/recognition-and-fix.md §2.2.1、§3.2.1 |
| 横向工具条 / 尾行模块勾选 | 易漏识别:在横向 flex-row 中,模块标题(如英式音标、鼓点音频)左侧仍有 16×16 方框切图;或底部 「单词书写」 等行「左方框 + 标签 + 右侧预览」— 与纵列勾选同类语义,只是排在横排/尾行 | el-checkbox + 对 IPA 区、鼓点 el-select 与图标、书写预览等 v-show 联动 | 须纳入 「全选所有模块」 的同一批布尔;禁止纵列用组件、横条仍留 png;尺寸按 6.3.4.3 与 recognition-and-fix.md §2.2.2~§2.2.3、§3.2.2~§3.2.3 |
| 单选框 radio | 多个选项中仅能选一项(互斥);圆点/圆圈 + 文案,或 div 模拟的选项组;有「选中」与「未选中」两种视觉状态 | el-radio-group + el-radio | 在 data 中定义选中值(如 radioValue),样式与源页一致,选中/悬停为主题色,见 6.3.10 |
| 带外框搜索框 | 外层为白底/圆角/边框容器,内为「搜索图标 + 占位文字 + 右侧搜索/按钮」 | el-input + prefix/suffix 插槽 | 必须同时满足「6.3.1 带外框搜索框样式规范」 |
| 取色 / 填充面板(图1 形态) | 展开后的面板含:标题「填充」等 + 色块格矩阵、渐变/透明度滑条、#+hex、% 不透明、RGB 数字格、最近使用等(页内整区或弹层);触发区可为按钮或小入口 | el-color-picker-extend | data/el-color-picker-extend.md §「颜色选择:触发与下拉的共同结构」、§选型、§产品需求 |
| 取色(图2 形态) | 展开后为 SV 渐变方 + 竖向彩虹色相条 + 底栏 Hex +「清空」「确定」(Element UI 2 默认取色下拉);触发区常为 A+下划线+箭头 | el-color-picker | 6.3.11、data/el-color-picker-extend.md §对照清单、字体颜色触发器 |
识别步骤(通用):
- 在 index.vue 中搜索:带「选」「勾」「搜索」等语义的文案,或带下拉箭头、勾选图标的 div 结构。
- 在 index.css 中确认该区域样式:是否有边框、圆角、固定宽高(如 66×28、16×16 勾选区域)。
- 若符合上表特征,在 Custom.vue 中替换为对应 Element UI 组件,并补全 data、methods。
- 纵向模块勾选列(补充):在配置/预览区搜索多行「左列小方框图 + 右列模块标题」;若左列无说明性长文案、仅方框 png,须按上表「纵向模块勾选列」处理,详见
data/recognition-and-fix.md§2.2.1。 - 横向工具条 / 尾行(补充):除纵列外,扫描配置区所有横向行与底部尾行:是否存在「方框切图 + 模块名 + 业务区」;若 img 与纵列勾选同资源或同类,须同样改为
el-checkbox,详见 6.3.4.2、data/recognition-and-fix.md§2.2.2。
6.3.4.1 纵向模块勾选列(无内联文案的 el-checkbox)
- 结构:保留原
image-wrapper父级 class 与布局,内部替换为el-checkbox;模块标题仍为旁侧span,不要把标题塞进el-checkbox默认插槽(除非稿面即为一体标签)。 - 隐藏 label:
::v-deep .el-checkbox__label { display: none; width: 0; padding: 0; margin: 0; overflow: hidden; },避免 Element 为空白 label 留出间距导致与稿面不齐。 - 尺寸与视觉:
::v-deep .el-checkbox__inner的宽高须与 index.css 中负责方框视觉的一层一致(见 6.3.4.3);border-radius与稿一致;未选中边框浅灰,选中为白底 + 主题色边框与勾(与稿一致即可);hover、is-focus边框建议主题色,与 6.3.8 一致。 - 联动:每个布尔对应右侧一块内容
v-show;双勾(例句/译文)对应同一卡片内两个内容区的分别显示与中隔线条件显示。 - 禁止:保留原方框 png 冒充勾选态;仅改「全选」行而漏改纵向模块列。
6.3.4.2 横向工具条 / 尾行上的模块勾选与尺寸统一
- 识别:在顶部横向配置行(如英式音标、鼓点音频)或底部尾行(如单词书写)中,模块标题 span 之前的
image-wrapper+ 小 png,若与左侧纵列模块勾选**尺寸同级(约 16×16)**且语义为「是否展示该段能力」,即属模块勾选,不得仅替换纵列而保留此处静态图。 - 替换:删除切图,在原 wrapper 内放入与纵列同一 class 的
el-checkbox(如[folderName]_module_checkbox),保证全页共用同一套::v-deep规则。 - 联动:英式音标应对 IPA + 播放图标所在行
v-show;鼓点音频若左侧方框表示模块总开关,应对 el-select 及同组图标v-show;单词书写应对右侧预览词v-show。 - 全选:
handleSelectAll/ 同步selectAll的 keys 须包含上述布尔,与纵列模块字段合并为一套,避免逻辑分裂。 - 尺寸与勾形(与 6.3.8 配合):全页无文案模块勾选须 class 统一;覆盖
.el-checkbox根、.el-checkbox__input、.el-checkbox__inner、.el-checkbox__inner::after及选中态勾线色;inner 像素须按 6.3.4.3 从 index.css 读取,禁止默认臆断为 16×16。详见data/recognition-and-fix.md§3.2.2、§3.2.3。
需求文案(摘要)
- 配置区内凡「左方框 + 模块名」式开关,无论出现在纵列、横条还是尾行,均须
el-checkbox,禁止 png 与组件混用。 - 同一自定义 class + 完整深度样式(含 ::after);方框边长以 index.css 实测为准(常为外层槽位 16px + 内层切图 13px),「全选」须覆盖横条与尾行布尔。
6.3.4.3 多选框原始尺寸识别(wrapper / thumbnail 分层,必做)
稿面常见结构为:外层 image-wrapper_*(或 group_* / box_*)提供 16×16 对齐槽位,内层 thumbnail_* 的 img 为 13×13 且带 margin: 2px 0 0 2px——可见方框的物理像素往往等于 thumbnail 的 width/height,而非外层 wrapper 的 width/height。若将 el-checkbox__inner 一律写成 16×16,会较稿面偏大,与仍使用切图的行或设计稿对比时产生偏差。
识别步骤(须自 index.css / 稿源读取,禁止猜默认):
- 在 index.vue 中定位该勾选左侧的
image-wrapper_*+img.thumbnail_*(或仅带 background 的image-wrapper_*,其自身 width/height 即方框视觉尺寸)。 - 在 index.css 中同时打开
.image-wrapper_*与.thumbnail_*(若存在):- 槽位尺寸:wrapper 的
width、height(及margin-top等),用于el-checkbox根或.el-checkbox__input的占位与 flex 居中(常见 16×16)。 - 方框视觉尺寸:优先取
.thumbnail_*的width/height;若无 thumbnail 而 wrapper 本身即为切图区(如 13×13 的 background 盒),则取 该层 的 width/height。此数值用于::v-deep .el-checkbox__inner的 width/height(本页示例为 13×13)。
- 槽位尺寸:wrapper 的
- 将
el-checkbox根 设为display: inline-flex; align-items: center; justify-content: center,宽高等于槽位(如 16px),__input同槽位并 flex 居中,__inner为步骤 2 的方框视觉尺寸(如 13px),box-sizing: border-box。 ::after勾形:在 inner 边长确定后,按比例微调height、width、left、top、border-width,并在is-checked .el-checkbox__inner::after上设border-color(多为白),使勾与稿面比例接近。
禁止:未打开 index.css 即写死 16×16 inner;或仅看 wrapper 忽略 thumbnail 导致 inner 过大。
需求文案(摘要)
- 替换伪多选前须从当前页 index.css 读出槽位与方框两层尺寸;inner 对齐方框视觉层(多为 thumbnail),根/
__input对齐槽位(多为 wrapper) 并居中 inner。 - 勾形 ::after 须随 inner 边长缩放,并做选中态勾线色覆盖。
详见 data/recognition-and-fix.md §3.2.3。
下拉框替换时必须删除的 DOM(通用规则): 除「当前选中项 + 箭头」的触发区外,若 index.vue 中还有独立的下拉选项列表(如浮层、侧边列表、鼓点-1~鼓点-11 等静态列表),须一并删除。替换为 el-select 后,选项由 el-select 自带的 dropdown 展示,不得保留原静态选项列表 DOM。
修复已有 Custom.vue 时:
- 若发现「看起来像下拉/多选/搜索但仍是 div+img+span」:按上表替换,并补全绑定与样式覆盖。
- 若已用 el-select 但页面上仍保留原静态选项列表:删除该静态列表 DOM 及与之相关的 data/methods(如仅用于该列表的 handleXxx)。
- 搜索框样式异常:按「6.3.1」逐项检查容器高度、
.el-input-group无边框与 flex、el-input__inner 高度与无边框、padding-left、placeholder、prefix 对齐等。
详见 data/recognition-and-fix.md。
6.3.5 Element UI 样式覆盖方法
- 深度选择器:scoped 无法直接修改组件内部样式,须用深度选择器。Vue 2 推荐
::v-deep,兼容写法/deep/。 - 写法示例:给组件加父级 class(如
custom_search_input),再写父级class ::v-deep .el-input__inner { ... },避免影响其他页面。 - 查找 class:用开发者工具选中组件 DOM,在 Elements 面板查看内部 class(如
.el-input__inner、.el-pager li),再用::v-deep覆盖。 - 优先级:优先用「父级 class + ::v-deep + 组件 class」提高特异性;尽量避免
!important;需覆盖多种状态时写全:hover、:focus、.active等。 - 输入框示例:
父级 ::v-deep .el-input__inner设置 height、border、border-radius、padding、font-size;::v-deep .el-input__inner:focus设 focus 边框色;::v-deep .el-input__inner::placeholder设占位符颜色。 - 分页示例:
父级 ::v-deep .el-pagination__total设总数样式;::v-deep .el-pager li、::v-deep .el-pager li.active设页码与选中态;::v-deep .btn-prev, ::v-deep .btn-next设上下页按钮。 - 下拉框示例:小尺寸 select 用
父级 ::v-deep .el-input__inner设 height、line-height、border-radius、font-size、border-color 与设计一致;::v-deep .el-input__inner:focus、::v-deep .el-input.is-focus .el-input__inner设 focus 边框色为页面主题色。下拉选项选中/悬停须用popper-class+ 非 scoped 样式覆盖为主题色,见「6.3.7 下拉框样式与激活态主题色规范」。 - 多选框示例:
父级 ::v-deep .el-checkbox__label设颜色、字号;::v-deep .el-checkbox__inner的宽高取 方框视觉层(常为 thumbnail,见 6.3.4.3),圆角与设计一致。选中/悬停/焦点须为主题色:::v-deep .el-checkbox__input.is-checked .el-checkbox__inner、::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner的 background-color、border-color 设为主题色;::v-deep .el-checkbox__inner:hover、::v-deep .el-checkbox__input.is-focus .el-checkbox__inner的 border-color 设为主题色,见「6.3.8」「6.3.8.1」。 - 单选框示例:
父级 ::v-deep .el-radio__inner设尺寸、圆角、边框与设计一致;选中/悬停/焦点须为主题色:::v-deep .el-radio__input.is-checked .el-radio__inner的 border-color、background-color 设为主题色;::v-deep .el-radio__inner:hover、::v-deep .el-radio__input.is-focus .el-radio__inner的 border-color 设为主题色;并覆盖.el-radio:focus:not(.is-focus):not(:active):not(.is-disabled) .el-radio__inner的box-shadow,见「6.3.10」「6.3.8.1」。
6.3.6 按钮与列表内文字垂直居中规范
改造后若出现「按钮文字、列表 badge 数字、列表项文字」未垂直居中,或按钮在默认态与激活态(hover/active/focus/内容切换)下内容错位,须按以下方式修复并作为通用规则遵守:
| 场景 | 识别特征 | 修复方法 |
|---|---|---|
| el-button 默认与激活态 | 按钮有固定高度,文字或图标+文字偏上/偏下/偏左/偏右;或切换状态(hover/active/focus 或内容从「导入」变为「已导入」等)后内容错位 | 在按钮的自定义 class 上通过 ::v-deep 为默认态及 :hover、:active、:focus 统一设置 display: inline-flex; align-items: center; justify-content: center; line-height: 1;;按钮内文案(span 等)设 text-align: center; margin: 0;(或仅对称 margin),保证默认与激活态内容均水平垂直居中,切换状态时保持居中 |
| 按钮激活态/替换态 DOM | 状态切换后由非 button 的容器(如 div)展示内容,该容器内文字或图标未水平垂直居中 | 该容器使用 display: flex; align-items: center; justify-content: center;(或 inline-flex),内部文案与图标用 text-align: center; margin: 0; 或 flex 居中,与默认态一致 |
| 列表/步骤 badge 内文字 | 圆形或方形容器内为数字/序号,须水平垂直都居中 | badge 容器使用 display: flex; align-items: center; justify-content: center;;内部文字 text-align: center; margin: 0;,不保留左右 margin,实现水平垂直都居中 |
| 列表项内文字 | 列表行有固定高度(如 48px),左侧 badge、中间文字、右侧图标未整体垂直居中 | 列表行容器使用 display: flex; align-items: center;;所有子元素(badge、文字、图标)去掉垂直方向 margin(margin-top/margin-bottom 置为 0),由 flex 的 align-items: center 负责垂直居中 |
自检:el-button 在默认态与 hover/active/focus 及内容切换后,内容均在按钮内水平垂直居中;若有激活态/替换态容器,其内容也水平垂直居中;badge 内文字水平垂直都居中;列表项行内整体垂直居中。若源稿用 margin 实现视觉居中,改造时优先改为 flex 居中并去掉子元素垂直 margin。
6.3.6.1 el-button 根节点 class 与深度选择器(必做,易错)
当源稿容器 class写在 <el-button class="[同一容器 class]"> 上时,组件根节点即为 button.el-button.[容器class],不存在「容器在内、.el-button 在子级」的 DOM。禁止用「.容器class ::v-deep .el-button」为该按钮写样式——该选择器只匹配后代中的 .el-button,会导致整段样式不生效,页面仍呈现 Element 默认按钮(错误常见于筛选区「重置」「查询」等)。
| 环节 | 要求 |
|---|---|
| 识别 | DevTools 查看按钮根节点:若自定义 class 与 el-button 在同一 <button> 上,即属「class 在根节点」。 |
| 修复 | 方案 A:用「.容器class.el-button」及 :hover、:focus、:active 写全尺寸、padding、min-width、背景、边框、字色(必要时 !important)。慎用 type="text":el-button--text 强制透明底/边且三态常回退透明,与稿面「小框+描边/浅底」冲突时须改**默认 type(省略)**或 plain 再覆盖。type="primary" 须覆盖 默认与三态及字色。方案 B:外层再包 div,class 在 div 上,则用「父级 ::v-deep .el-button」。 |
| 子节点 | 按钮内 img / span 若沿用源稿 class,常带静态 flex 用的 margin(如 margin: 8px 0 0 16px),须在按钮内 margin: 0,布局交给根上 flex + align-items + justify-content(如主按钮图标+文案 space-between),与 6.3.6 一致。 |
| 并排间距 | 主题 .el-button + .el-button { margin-left: 10px } 会叠加稿面间距;须在父行取消或改写,再只用各按钮自身 margin-left 控制。 |
| 主按钮 | type="primary" 时须用「.自定义class.el-button--primary」等覆盖 hover / focus / active 背景、边框、字色,避免状态切换露默认样式。 |
需求文案(摘要):凡将可点击区改为 el-button 且把原稿容器 class 合并到按钮根上者,样式选择器必须与 DOM 一致;禁止误用「父级 ::v-deep .el-button」;带底/边的次要按钮勿用 type="text";并排按钮须处理默认 10px 相邻间距;子级 img/span 须去源稿 margin。
自检:样式表含 .容器class.el-button(或外层 ::v-deep);默认与 hover、focus、active 与源稿一致;无不当 type="text";并排无多余 10px;子级无破坏 flex 的 margin。
详见 data/el-button-root-and-deep.md(识别步骤、两种修复方案、需求全文、自检清单)。
6.3.7 下拉框样式与激活态主题色规范
- 触发器样式:el-select 的
.el-input__inner须用::v-deep设置与设计稿一致的 height、line-height、border-radius、font-size、border-color(默认态);focus 与 hover 态的边框色须使用当前页面主题色(从 index.css 或设计稿中取主色),不得使用 Element 默认蓝色。须同时覆盖:.el-input__inner:hover、.el-input__inner:focus、.el-input.is-focus .el-input__inner的border-color(Element 在 focus 时给 .el-input 加 .is-focus,漏写则 focus 边框可能仍为默认色)。详见data/recognition-and-fix.md9.7。 - 下拉选项激活态:下拉弹层挂载在 body,scoped 无法覆盖。须给 el-select 设置
popper-class="[folderName]_xxx_dropdown_popper",在 Custom.vue 中增加非 scoped 的<style>块,用该 class 覆盖:.popper-class名.el-select-dropdown .el-select-dropdown__item.selected:文字色、背景色为主题色/主题浅色(与设计一致);.popper-class名.el-select-dropdown .el-select-dropdown__item:hover:悬停态文字色、背景色为主题色/主题浅色。
- 主题色来源:从源页面 index.css 或设计稿中提取主色(如高亮边框、选中项背景、主按钮背景),统一用于 el-select 的 focus 边框、下拉选项 selected/hover,以及列表中选中项边框/文字色等,保证激活态与当前主题一致。
自检:el-select 触发器尺寸与设计一致;focus 与 hover 时边框色均为主题色(见 9.7);下拉选项选中/悬停为主题色,非 Element 默认蓝。
6.3.7.1 el-select 右侧箭头/后缀对齐(必做,易错)
静态稿常用 flex + justify-content: space-between 做「左文案 + 右箭头图」。改为 el-select 后,箭头在 .el-input__suffix(绝对定位) 内,不得把同一套 display:flex; justify-content:space-between 加在 el-select 根节点(与自定义 class 合并处),否则会干扰内部 el-input 布局,表现为右侧图标水平/垂直偏移。
另:仅把 .el-input__inner 改为小高度(如 28px)时,Element 默认 .el-input__icon 的 line-height 仍按大输入框(如 40px),箭头会上下不齐;须用 ::v-deep 将 .el-input__icon / .el-select__caret 的 line-height、height 与 inner 对齐,并设置 .el-input__suffix 的 right(对照 index.css 箭头距右缘)、校验 padding-right 避免文字与箭头重叠。
需求文案(摘要):el-select 触发器右侧箭头位置、垂直居中与右内边距须与稿一致;禁止为复刻静态 flex 在 el-select 根上使用 space-between;改小触发器高度必须同步后缀图标行高/高度与 suffix 定位。
自检:根节点无不当 flex+space-between;suffix right、icon line-height/height 与 inner 一致;文案与箭头不重叠。
详见 data/el-select-suffix-alignment.md(识别、根因、修复步骤、需求全文、自检清单)。
6.3.8 多选框激活态主题色规范
- 选中态:el-checkbox 默认选中为 Element 蓝色,须用页面主题色覆盖。在 checkbox 的自定义 class 下用
::v-deep设置:父级 ::v-deep .el-checkbox__input.is-checked .el-checkbox__inner、父级 ::v-deep .el-checkbox__input.is-indeterminate .el-checkbox__inner:background-color、border-color为页面主题色(与 6.3.7 主题色来源一致)。
- 悬停态:
父级 ::v-deep .el-checkbox__inner:hover的border-color设为主题色,与设计一致。 - 焦点态(必做):见 6.3.8.1;仅写
is-checked/:hover时,键盘聚焦或点击后仍可能露出 Element 默认主色蓝。 - 主题色:与 el-select、列表选中项等统一,从 index.css/设计稿取主色(如
rgba(255, 106, 106, 1));多主色稿面下须与该控件所在区块一致,见 6.3.8.1。
自检:多选框选中/半选时方框背景与边框为主题色;悬停时边框为主题色;焦点态(is-focus) 边框为主题色,非 Element 默认蓝。详见 6.3.8.1。
6.3.8.1 单选/多选主题色:稿面取色、焦点态与 Element 残留蓝(必做)
问题识别
- 只覆盖了选中与 hover,仍见「蓝框」:Element UI 2 在
.el-checkbox__input.is-focus .el-checkbox__inner、.el-radio__input.is-focus .el-radio__inner上使用$--checkbox-input-border-color-hover/$--radio-input-border-color-hover(即 Element 主题主色,常为#409EFF),与 Custom.vue 里为「稿面主题色」设置的is-checked/:hover不是同一套规则,表现为:点击或 Tab 聚焦后边框仍蓝。 - 单选独有:焦点环为蓝:
.el-radio:focus:not(.is-focus):not(:active):not(.is-disabled) .el-radio__inner带box-shadow: 0 0 2px 2px $--radio-input-border-color-hover,未覆盖时整圈仍为默认蓝。 - 主题色选错(多主色页面):同一
index.css中常并存 导航/Tab 高亮蓝(如rgba(0, 116, 252, 1))与 主按钮/设置区/勾选切图色(如rgba(4, 180, 182, 1))。将前者套到设置面板内的el-checkbox/el-radio会导致与静态勾选 PNG、邻近竖条(section_*)、主按钮不一致。
修复方法(在控件父级自定义 class 下 ::v-deep,与已写的 checked/hover 同色)
| 状态 | el-checkbox | el-radio |
|---|---|---|
焦点(键盘/点击后 input 带 .is-focus) | 父级 ::v-deep .el-checkbox__input.is-focus .el-checkbox__inner { border-color: [稿面主题色]; } | 父级 ::v-deep .el-radio__input.is-focus .el-radio__inner { border-color: [稿面主题色]; } |
| 单选:原生 focus 环 | — | 父级.el-radio:focus:not(.is-focus):not(:active):not(.is-disabled) ::v-deep .el-radio__inner { box-shadow: 0 0 2px 2px [稿面主题色半透明]; }(或与稿一致改为 none) |
稿面主题色怎么取(须自当前页 index.css,禁止抄其它页 Custom)
- 定位该控件在 index.vue 中对应的静态结构(原勾选/单选切图、或同一块卡片内的主按钮、标题竖条
background-color)。 - 在 index.css 中查
.thumbnail_*/.image-wrapper_*背景、同区主按钮、section_*装饰条 的background-color/border-color,取与交互控件一致的那一支作为主色。 - 同一页内
el-pagination、列表 Tab 若用蓝 A,设置区勾选若用青 B,则 checkbox/radio 须用 B,不得统一成 A。
需求文案(摘要)
- 替换
el-checkbox/el-radio后,选中、悬停、焦点(.is-focus)及单选box-shadow焦点环须全部使用该区块稿面主题色,不得残留 Element 默认蓝。 - 主题色须从当前文件夹
index.vue+index.css就近提取;多主色时表单控件与静态勾选/主按钮同色,不得误用仅用于列表或 Tab 的色值。
自检:DevTools 选中 .el-checkbox__input / .el-radio__input,手动切换 :focus、查看是否带 .is-focus,确认 inner 边框与(单选)box-shadow 均为稿面色;与 index 静态区主色对比一致。
详见 data/radio-checkbox-theme-and-focus.md(识别步骤、选择器对照、需求全文)。
6.3.9 分页(el-pagination)替换与主题色规范
- 替换时必须删除的 DOM:分页区域整块替换为单个
el-pagination时,须删除该区域内全部原始静态内容,包括「共 xxx 条」文案与图标、所有静态页码块(如 1、2、3…)、上一页/下一页的静态图标或按钮、「xx条/页」的静态或伪下拉。不得在 el-pagination 外再保留一份上述内容,否则会出现两套分页。 - layout:使用
layout="total, prev, pager, next, sizes",由组件自带展示总数、上下页、页码、每页条数。 - 样式:用
::v-deep对.el-pagination__total、.btn-prev/.btn-next、.el-pager li、.el-pagination__sizes .el-input__inner设置与设计一致的尺寸、边框、圆角、字号。上一页/下一页按钮须设padding: 0、display: inline-flex、align-items: center、justify-content: center使图标居中,并设默认态color,内部.el-icon设color: inherit(见 recognition-and-fix 9.6)。 - 激活态/主题色:当前页
.el-pager li.active的背景色、边框色须为页面主题色;上一页/下一页 hover 态须同时设边框色与图标色为主题色(须为.btn-prev:hover、.btn-next:hover设color,并为.btn-prev:hover .el-icon、.btn-next:hover .el-icon设color,见 9.5);页码.el-pager li:hover边框/文字色为主题色;每页条数 sizes 的 el-select 触发器(.el-input)须在 focus 与 hover 时边框均为主题色(须同时覆盖.el-input__inner:hover、.el-input__inner:focus、.el-input.is-focus .el-input__inner,见 9.7)。 - sizes 下拉主题色:el-pagination 内部的「每页条数」为 el-select,其下拉层挂载在 body 且无法单独设置 popper-class。须在 Custom.vue 中增加非 scoped 的
<style>,同时覆盖选中态(.selected)、键盘焦点态(.hover)、悬停态(:hover)及选中+悬停(.selected:hover、.selected.hover),对color、background-color使用!important;若 hover 仍不生效须使用双重 class 提高特异性(如.el-select-dropdown .el-select-dropdown__item.el-select-dropdown__item:hover)或body .el-select-dropdown .el-select-dropdown__item,使 sizes 下拉的选中项与悬停项与页面主题一致。详见data/recognition-and-fix.md第 3.4、9.4 节。
自检:已删除原始分页全部静态内容,仅保留一个 el-pagination;上一页/下一页 按钮图标居中、默认态与 hover 态颜色正确(见 9.6、9.5);sizes 的 el-select 触发器 focus 与 hover 时边框均为主题色(见 9.7);当前页、sizes 下拉选中/悬停均为主题色(见 9.4)。
6.3.10 单选框(el-radio)识别与主题色规范
- 识别:源页面存在「多选一」互斥选择(如多个选项中仅能选一项),包括原生
<input type="radio">或 div + 文案/图标模拟的单选区域,须替换为el-radio-group+el-radio。 - 替换:删除原单选区域全部 DOM,改为
<el-radio-group v-model="radioValue" class="[folderName]_radio_group">+<el-radio v-for="..." :label="..." :key="...">...</el-radio>;在 data 中定义选中值(如radioValue),在 methods 中实现@change处理(如handleRadioChange)。 - 样式与源页一致:用
::v-deep对.el-radio__inner、.el-radio__label等设置与 index.css/设计稿一致的尺寸、圆角、边框、字号、颜色;整体布局(横向/纵向、间距)与源页面一致。 - 激活态与选中项主题色:Element 默认选中为蓝色,须改为页面主题色。在单选框父级 class 下用
::v-deep设置:- 选中态:
父级 ::v-deep .el-radio__input.is-checked .el-radio__inner的border-color、background-color为页面主题色(与 6.3.7/6.3.8 主题色来源一致);父级 ::v-deep .el-radio__input.is-checked + .el-radio__label的文字色可设为主题色或与设计一致。 - 悬停态:
父级 ::v-deep .el-radio__inner:hover的border-color设为主题色。 - 焦点态与焦点环(必做):见 6.3.8.1(
.is-focus边框 +.el-radio:focus:not(...)的box-shadow)。
- 选中态:
- 主题色来源:从 index.css 或设计稿中取主色(如选中项背景、主按钮背景),与 el-select、el-checkbox 等统一;多主色稿面下与设置区静态控件一致,见 6.3.8.1。
自检:单选项已替换为 el-radio-group + el-radio;尺寸、布局、文字与源页一致;选中项与悬停态圆点/边框为主题色;焦点态与 focus 环为主题色,非 Element 默认蓝(见 6.3.8.1)。
6.3.10.1 筛选项折行与高度自适应(必做,适用时)
将横向筛选改为 el-radio-group 后,若在较窄宽度或选项较多时允许折行,须避免固定高度裁切与行间重叠。
| 环节 | 要求 |
|---|---|
| 筛选外层卡片 | 勿用固定 height 锁死整张筛选卡;改为 min-height: [设计稿高度] + height: auto,并设 padding-bottom,使多行选项撑开卡片。 |
| 筛选行(标签 + 选项组) | 行容器 flex-wrap: wrap,align-items: flex-start(或 align-content: flex-start),gap 控制换行后的纵向/横向间距;行宽在 max-width 与面板一致下可用 width: 100% 覆盖稿中过窄的固定 width。 |
| 左侧标签 | flex-shrink: 0;height: auto + min-height: [原行高],与选项首行对齐,避免固定 height 与折行冲突。 |
el-radio-group | flex: 1、min-width: 0、flex-wrap: wrap,row-gap / column-gap 统一选项间距;减少纯 margin-left 链,避免换行后首列/次行边距错乱。 |
.el-radio / __label | 使用 min-height 对齐设计行高,height: auto;必要时 padding + line-height,避免文字与背景 pill 上下被裁切。 |
| 名称行(标签 + 搜索) | 若与筛选区上下相邻,该行勿用固定 height 压过折行后的筛选区;改为 min-height + height: auto,必要时 flex-wrap + gap。 |
识别要点:在 Custom.vue 的 scoped 样式中搜索筛选相关容器的 height:;若筛选行已 flex-wrap: wrap 仍重叠,优先查外层卡片与子行是否仍为固定高度、选项组是否缺 min-width: 0、间距是否仅依赖 margin-left。
自检:缩小视口或增加选项后,筛选区自动增高,无与下一行筛选或列表重叠;选项多行时间距清晰;设计宽度下单行布局仍与稿面基本一致。
详见 data/filter-row-wrap.md(识别步骤、修复细则、需求文案、自检清单)。
取色组件选型(摘要):颜色选择均由 触发区 + 下拉面板 组成;以下拉面板的版式 判断图1 / 图2,不以触发区(色块、A 字条等)单独判断。图1(预设矩阵类「填充」面板等)→
el-color-picker-extend;图2(Element 默认取色下拉:SV + 竖色相条 + 清空/确定)→el-color-picker。替换后须 删除 原静态或重复的取色 DOM,避免两套 UI 并存。识别清单、需求文案与错配修复见data/el-color-picker-extend.md§「颜色选择:触发与下拉的共同结构」、§「图1 / 图2 对照与识别清单」、§「常见错配与修复」。
6.3.11 el-color-picker(图2)与页内静态「填充」删除;el-color-picker-extend(图1)集成注意(必做,适用时)
| 环节 | 要求 |
|---|---|
| 通用规则 | 触发与下拉:点击后展开的区域才是选型依据;图1、图2 的 触发区都可以是「颜色选择按钮」类控件,区别仅在 展开内容 是稿面定制填充面板还是 Element 默认面板。详见 data/el-color-picker-extend.md §「颜色选择:触发与下拉的共同结构」。 |
| 识别(稿面) | 图2:若展开 look 为 SV 大方块 + 右侧竖向色相条 + 底栏 Hex +「清空」「确定」 → el-color-picker;常见 触发 为「字体颜色」行 小框:A + 下划色条 + 箭头(静态多为 A + png + 绝对定位色条)→ 用 透明叠层 盖住触发区。图1:展开为 标题「填充」+ 色块矩阵 + 滑条 + #hex + % + RGB +「最近使用」 等(页内整区或弹层)→ el-color-picker-extend,并 删除 原静态切图/伪输入整段 DOM。 |
| 触发器样式 | 需与稿一致时:用 A(与 index.css 字号/字色一致)+ 横向色条(background-color 绑定 v-model 当前色,透明时用 transparent)+ 右侧三角(CSS border 或 8×8 内联图)。勿假设 Element UI 2.x 提供 #trigger 插槽(无)。 |
实现图2(el-color-picker) | 透明触发区覆盖:外层 position: relative,底层为 可见 自定义面(pointer-events: none),上层 el-color-picker 绝对定位铺满,对 ::v-deep .el-color-picker__trigger 设 宽高 100%、无边框、opacity: 0,保证点击落在官方触发器上;勿对根节点 .el-color-picker 整体 opacity: 0,否则 下拉面板 会被一并隐藏。popper-class 仍用于挂载到 body 的下拉样式。 |
实现图1(el-color-picker-extend) | 在页面中放置 <el-color-picker-extend v-model="fillColorRgba" recent-storage-key="..." />(工程内全局注册),删除 原页内填充区全部静态节点;父容器若在 index.css 中 固定高度,须改为 height: auto(或加修饰 class 覆盖),见 data/el-color-picker-extend.md。 |
| 删除页内块 | 已用 el-color-picker-extend 或 el-color-picker 承担取色后,须 删除 index 稿中 整块 原「填充」模拟区(多图色矩阵、独立渐变条图、#hex、RGB 行、静态「最近使用」色块行等),禁止在页面内再保留一套取色 UI;扩展组件内置「最近使用」时不得与静态切图并存。 |
| 多行相同控件 | 多条「字体颜色」行共用同一 v-model 即可;每行一个 el-color-picker(透明覆盖)或仅一行有 picker(另一行只读展示)按稿面二选一,避免重复逻辑分叉。 |
需求文案(摘要)
- 图2 字体颜色:A + 随当前色变化的下划线 + 下拉示意,用透明
el-color-picker覆盖点击;不得整页opacity: 0包住取色组件。 - 图1 填充区:用
el-color-picker-extend后:删除 原静态「填充」页内大面板(色格/滑条图、拼出来的 hex/rgb/最近使用等),不重复保留模拟弹层。
自检:工具条视觉与 index 一致;点击能打开官方取色下拉;下拉内操作正常;页面无第二套静态取色/最近使用切图。
详见 data/el-color-picker-extend.md §「字体颜色触发器(Element UI 2)」。
6.4 循环渲染规范
将重复的结构改为 v-for 循环:
<!-- ❌ 改造前(静态重复) -->
<div class="item">内容1</div>
<div class="item">内容2</div>
<div class="item">内容3</div>
<!-- ✅ 改造后(动态循环) -->
<div
v-for="(item, index) in itemList"
:key="item.id"
:class="['item', getItemClass(index)]"
>
{{ item.content }}
</div>
6.5 图片路径处理规范(⭐重要)
⚠️ 路径基准: Custom.vue 与 index.vue 同目录,位于视图文件夹根(如 src/views/shushi/),图片实际在 src/views/${folderName}/assets/img/。所有路径均相对于 Custom.vue 所在目录 解析。
| 场景 | 正确做法 | 错误做法 |
|---|---|---|
| Template 中的 <img> 标签 | :src="require('./assets/img/xxx.png')" 或 data 中 require('./assets/img/xxx.png') | :src="require('./img/xxx.png')" |
| Custom.vue 内 <style> 中的 background-image | url(./assets/img/xxx.png) | url(./img/xxx.png) |
| data() 中定义的图片路径 | img: require('./assets/img/xxx.png') | img: require('./img/xxx.png') |
为什么 Custom.vue 里 CSS 必须用 ./assets/img/?
- 源文件
assets/index.css在assets/下,其中url(./img/xxx)是相对于 assets 目录 的,指向assets/img/,在 index.css 中正确。 - 样式内联到 Custom.vue 后,构建时相对路径的基准是 Custom.vue 所在目录(视图文件夹根),
./img/会解析到不存在的视图文件夹/img/,导致图片 404。 - 因此写入 Custom.vue 的 CSS 中必须使用
url(./assets/img/xxx.png),才能正确指向视图文件夹/assets/img/。
识别与修复(通用流程):
-
识别(以稿源 CSS 为准)
- 在
${folderName}/assets/index.css(及其链式@import)中搜索:url(./img/、url("./img/、url('./img/(含单/双引号与无引号)background:/background-image:(定位所有背景图声明,包含 sprite/mergeImage)
- 在
index.vue中搜索:src="./assets/img/、src='./assets/img/、:src=(定位所有 <img> 引用)
- 在
-
写入 Custom.vue 时的规则(必须执行)
- Template / data():图片路径统一为
require('./assets/img/文件名')。 - <style scoped>:从 index.css 拷贝过来的背景图路径,凡
url(./img/xxx)一律改为url(./assets/img/xxx)。
- Template / data():图片路径统一为
-
修复已有 Custom.vue(问题排查顺序)
- 背景区域图片样式异常 / 背景图不显示:
- 在 Custom.vue 的
<style scoped>中搜索url(./img/,若存在则全局替换为url(./assets/img/。 - 检查是否误写成
url(@/...)或url(/...)(本 Skill 禁止),统一改为url(./assets/img/...)。 - 检查迁移时是否丢了
background的关键子属性:background-repeat、background-position、background-size(如源为background: url(...) 100% no-repeat; background-size: 100% 100%;),必须完整迁移,否则会表现为「背景拉伸不对/不铺满/位置偏移」。
- 在 Custom.vue 的
- <img> 不显示:检查是否为
require('./assets/img/xxx'),勿用require('./img/xxx')。
- 背景区域图片样式异常 / 背景图不显示:
修复自检清单:
- Custom.vue 的 style 中:不存在
url(./img/...),所有背景图均为url(./assets/img/...) - Custom.vue 的 template/data 中:不存在
require('./img/...),所有图片均为require('./assets/img/...) - 对每个背景块核对:
background四要素(image / repeat / position / size)与 index.css 一致
6.6 数据与方法同步生成
❌ 禁止分步执行:
<!-- 错误:只写 template,不写 data 和 methods -->
<template>
<el-input v-model="inputValue" @change="handleChange" />
</template>
<script>
export default {
// data 和 methods 稍后补充
}
</script>
✅ 必须同步完成:
<template>
<el-input v-model="inputValue" @change="handleChange" />
</template>
<script>
export default {
data() {
return {
inputValue: '' // ✅ template 中使用的数据必须定义
}
},
methods: {
handleChange() { // ✅ template 中的事件必须实现
// 处理逻辑
}
}
}
</script>
6.7 样式匹配标准(按元素重要性)
改造后视觉效果须与源文件一致,按元素类型采用不同匹配级别:
| 标准 | 适用场景 | 必须匹配的属性 |
|---|---|---|
| 完整匹配 | 列表项、卡片、主容器 | 盒模型 + 尺寸 + 布局 + 文字 + 边框 + 视觉效果 + 交互状态 |
| 简化匹配 | 筛选项、按钮、标签 | 尺寸 + 布局 + 文字 + 边框 + 视觉效果 + 交互状态 |
| 文字匹配 | 标题、描述文本 | font-family、font-size、color、font-weight、line-height |
| 尺寸匹配 | 图片、图标 | width、height、border、border-radius、box-shadow |
布局与验证:PC 端流式布局用 width: 100%、百分比宽度,优先 Flex/Grid;尺寸、颜色、字体、间距等用浏览器开发者工具对比 Computed 样式,误差不超过 1px,颜色精确到 rgba。若样式不一致,检查选择器优先级、是否需 ::v-deep 覆盖、是否有冲突样式。
6.8 列表项内容溢出规范(v-for 列表必做)
凡用 v-for 渲染的列表/卡片,其项内由数据驱动的文本(标题、作者、描述等)不得沿用 index.css 中该文本的固定 width/height,否则长文案会溢出。须按 data/list-item-overflow.md 执行:
- 列表项根节点:设
overflow: hidden、box-sizing: border-box;若项内有固定宽高的内容区(如 first-inner),也设overflow: hidden、min-width: 0。 - 动态文本节点:将固定
width/height改为 max-width(按内容区可用宽度取值),保留overflow-wrap: break-word,并加overflow: hidden、必要时min-width: 0(flex 子项)。不得为「与设计稿数值一致」保留会导致溢出的固定宽度。
详见 data/list-item-overflow.md(识别步骤、修复方法、需求文案、自检清单)。
6.9 文字竖排与横排识别(必做)
改造时须根据 index.css 与设计稿识别列表/卡片内标题、作者等为竖排还是横排,避免将竖版做成横版。识别规则见 data/text-direction-vertical-horizontal.md:
- 竖排:index.css 中该文本为窄宽高瘦(width 约 14px~24px、height 明显大于 width、line-height 与 width 接近),或设计语义为古诗词/传统竖版 → 在 Custom.vue 中为该节点设
writing-mode: vertical-rl(或 vertical-lr)、text-orientation: upright、display: inline-block(若为 span),并设与设计一致的 width、max-height、line-height、overflow: hidden。竖排下的复合文案(如「朝代·作者」)若设计为单列,须用单段拼接,不得用<br>(否则竖排会变多列),见 data/text-direction-vertical-horizontal.md 4.2。 - 横排:无上述特征或为常规 UI 文案 → 不设 writing-mode,按横排布局处理。
详见 data/text-direction-vertical-horizontal.md(识别步骤、修复方法、需求文案、自检清单)。
6.10 列表样式(单行不换行)(必做)
凡用 v-for 渲染且设计上为单行横向排布的列表/卡片项(如左装饰 + 内容 + 标题 + 作者 + 右装饰等),列表项根节点若为 flex 横向布局,须设 flex-wrap: nowrap,不得使用 flex-wrap: wrap,避免项内换行导致错位。列表项根节点须同时设 overflow: hidden、box-sizing: border-box(与 6.8 一致)。详见 data/list-style.md(识别步骤、修复方法、需求文案、自检清单)。
6.11 列表行高度与对齐规范(必做)
凡用 v-for 渲染的列表,其列表行(普通行、第一行、第二行等)必须满足以下要求,避免文字被截断和右侧列对齐问题:
- 高度修复:列表行使用
min-height而非仅固定height(如min-height: 23px; height: 23px;),确保行内文字(line-height与height一致)不被截断;行内元素需设置min-height与height一致(如min-height: 22px; height: 22px;)。 - 对齐修复:列表行内各列(如课包名、讲次信息、状态信息、更新信息)需设置固定宽度(从 index.css 中查找对应列的宽度,如
.image-text_4 { width: 134px; }),并设置flex-shrink: 0防止在 flex 布局中被压缩;各列的margin-left值需与 index.css 中的值完全一致(误差不超过 1px)。 - 溢出处理:列内文本(如课包名)可用
max-width+overflow: hidden+text-overflow: ellipsis防止溢出,但列容器本身需保持固定宽度。 - 多 rowKind 统一行高与列槽(表格形列表必做):若同一列表存在多种
rowKind(首行灰底、高亮行、普通双列、续讲无左列等),须 (1) 以静态稿最高行为统一min-height基准,列表项外层与内层行轨道共用align-items: center;(2) 设固定宽度课包列槽(宽度 = index.css 首行课包区宽度),normal与续讲行均经该槽对齐,续讲行用空槽占位,禁止单独使用超大整行margin-left顶替列槽;(3) 讲次列紧贴槽右缘用统一间距(如 20px),项间距仅用.list_item + .list_item(或统一 padding),禁止「仅某类行」的相邻兄弟外边距分叉;(4) 行内子元素垂直对齐以 flex 为主,margin-top置 0(绝对定位结构除外)。
详见 data/list-row-height-alignment.md(含第 8 节:多 rowKind 统一行高与列槽对齐;识别步骤、修复方法、需求文案、自检清单)。
6.12 双列列表左右数据源独立(必做,适用时)
若列表在语义上为左列 + 右列(如课包 + 讲次/状态/更新),且存在续讲等行左侧无单元格或两侧数据将来来自不同接口,须:
- 使用
packageList(左)与lectureList(右)等两套独立data,不得以单一合并对象为唯一数据源;v-for通常以右侧(明细)列表为主循环,左侧用packageList[index]对齐。 - 左侧无内容行:左列数据用
title: null(或等价),并设rowKind(如right_only、right_only_compact)走独立 template + 独立样式类,margin/width 对照 index.css 中单独 group,禁止用空字符串 + 普通双列行凑合。
详见 data/list-dual-column-independent.md(识别步骤、修复方法、需求文案、自检清单)。
步骤 7: 验证生成的代码
生成 Custom.vue 后,必须进行以下验证:
7.1 样式检查
- 尺寸与源文件一致(误差不超过 1px)
- 颜色完全一致(rgba 值相同)
- 字体、间距完全一致
- 视觉效果与源文件 100% 匹配
- 带外框的搜索框:容器高度与设计一致,容器有 border,hover 与 focus-within 时边框为主题色(见 9.8),无双重边框,前缀图标与文字垂直对齐,placeholder 与输入文字垂直居中,placeholder 颜色正确,无错位或溢出;容器设 max-width、min-width: 0,所在行设 min-width: 0,不溢出父级(见 6.3.1、6.3.1.1、data/search-input-and-page-overflow.md)
- 页面不横向溢出:主卡片/底栏/搜索框所在行使用 width:100%+max-width+min-width:0;底栏中间文案用 margin-left:auto;无横向滚动(见 6.3.1.1、data/search-input-and-page-overflow.md)
- 垂直居中:el-button 及 div+背景图+文字按钮内文字均水平与垂直都居中,文字节点 width: 100%、margin: 0、display: inline-flex + align/justify center,无单侧 margin 导致偏位;列表/步骤 badge 内文字水平垂直都居中;列表项内文字与图标均在容器内垂直居中(见 6.3.6、recognition-and-fix 9.2)
- el-button 与深度选择器:自定义 class 在按钮根上时,已用
.class.el-button或外层包裹 +::v-deep,未误用「.class ::v-deep .el-button」导致重置/查询等样式不生效(见 6.3.6.1、data/el-button-root-and-deep.md) - el-button 类型与三态:带底/边次要按钮未误用
type="text";已写全 :hover / :focus / :active;并排已处理.el-button + .el-button;子 img/span 无源稿静态 margin(见data/el-button-root-and-deep.md2.1~2.3) - 下拉框与激活态主题色:el-select 触发器 focus 与 hover 边框色均为主题色(须覆盖 :hover、:focus、.el-input.is-focus .el-input__inner,见 9.7),下拉选项选中/悬停为主题色;分页 sizes 等挂载 body 的下拉须用非 scoped 样式覆盖选中/悬停为主题色,未生效时用 !important(见 6.3.7、recognition-and-fix 9.1、9.7)
- el-select 右侧箭头对齐:未在
el-select根上误用flex+space-between;小高度触发器已同步.el-input__suffix/.el-input__icon(.el-select__caret)与padding-right(见 6.3.7.1、data/el-select-suffix-alignment.md) - 多选框激活态主题色:el-checkbox 选中/半选/悬停为主题色(见 6.3.8)
- 纵向模块勾选列:配置/预览区左列 16×16 方框列已改为 el-checkbox,已删方框切图;
moduleFlags(或等价)与右侧v-show联动;无内联文案时已隐藏.el-checkbox__label(见 6.3.4.1、recognition-and-fix.md§2.2.1、§3.2.1) - 横向工具条 / 尾行勾选:英式音标、鼓点音频、单词书写等横排/尾行左侧方框已改为 el-checkbox,无静态图残留;IPA 区、鼓点控件、书写预览等已
v-show联动;「全选所有模块」已包含上述布尔(见 6.3.4.2、recognition-and-fix.md§2.2.2) - 多选框尺寸全页统一:模块勾选共用同一 class 与同一套
::v-deep(根、__input、__inner、__inner::after、选中勾线色),与 index.css 方框一致,无混排(见 6.3.4.2、recognition-and-fix.md§3.2.2) - 多选框 inner 与槽位分层:已从 index.css 核对 wrapper 槽位 与 thumbnail(或内层 wrapper)方框视觉 宽高;
el-checkbox__inner与方框视觉层一致,__input/根与槽位一致并居中 inner,非笼统 16×16 inner(见 6.3.4.3、recognition-and-fix.md§3.2.3) - 单选框:已替换为 el-radio-group + el-radio;样式与源页一致;选中项与悬停态为主题色(见 6.3.10)
- 筛选折行:筛选项可折行时,筛选卡片与各筛选行使用 min-height + 自动增高,gap 控制间距,el-radio-group 具备 flex:1、min-width:0、flex-wrap,无行间/与列表重叠(见 6.3.10.1、data/filter-row-wrap.md)
- 分页:已删除原始分页全部静态内容,仅保留一个 el-pagination;sizes 的 el-select 触发器 focus 与 hover 时边框均为主题色(见 9.7);上一页/下一页 已设 padding:0、inline-flex、居中及默认态 color(见 9.6),hover 时边框与 .el-icon 均为主题色(见 9.5);sizes 下拉选中/悬停均为主题色,未生效时已用双重 class 或 body 前缀及 !important(见 6.3.9、recognition-and-fix 9.4、9.5、9.6、9.7)
- 列表项内容不溢出:v-for 列表项根节点已设 overflow: hidden、box-sizing: border-box;动态文本已用 max-width + overflow-wrap + overflow: hidden,无固定 width/height 导致溢出(见 6.8、data/list-item-overflow.md)
- 列表行高度与对齐:v-for 列表行(普通行、第一行、第二行等)已使用 min-height 而非仅固定 height,行内元素已设 min-height 确保文字不被截断;各列(如课包名、讲次、状态、更新)已设置固定宽度(从 index.css 查找)、flex-shrink: 0,各列 margin-left 值与 index.css 完全一致(误差不超过 1px);在浏览器中确认文字完整显示、右侧列位置与设计稿一致(见 data/list-row-height-alignment.md)
- 多 rowKind 统一行高与列槽:若存在多种 rowKind,列表项已统一 min-height 与行轨道 align-items:center;已设课包列槽 W_package,续讲行为空槽而非整行超大 margin-left;讲次列起点统一;项间距无「仅某类行」分叉(见 data/list-row-height-alignment.md 第 8 节)
- 双列列表左右独立:若为左列+右列表格形列表,已使用两套独立数据源(如 packageList + lectureList),续讲/无左列行已用 rowKind 与独立布局类,未用单对象合并左右字段或空 courseName + 普通行冒充(见 6.12、data/list-dual-column-independent.md)
- 文字竖排/横排与设计一致:已根据 index.css「窄宽高瘦」与设计语义识别竖排;竖排节点已设 writing-mode、text-orientation: upright、display: inline-block(若为 span)及 width/max-height/overflow;竖排复合文案(如朝代·作者)未用
<br>,作者区无塌陷错位(见 6.9、data/text-direction-vertical-horizontal.md) - 列表项单行不换行:单行设计的 v-for 列表项根节点已设 flex-wrap: nowrap、overflow: hidden、box-sizing: border-box,项内无换行错位(见 6.10、data/list-style.md)
7.2 功能检查
- 循环渲染正常工作
- Element UI 组件正常显示和交互
- 取色 / 填充:已按稿面 图1 / 图2 选用
el-color-picker-extend或el-color-picker(见data/el-color-picker-extend.md§选型),并已 删除 原静态/重复取色 DOM;图2「字体颜色」工具条已按 6.3.11 做 A+下划线+箭头;按该文档 自检 与 集成注意(如父级height: auto)逐项核对 - 每个组件使用的数据均在 data() 中定义,每个事件绑定(@click、@change、@size-change 等)均在 methods 中实现
- 所有可点击按钮均已绑定 @click 并实现对应 handleXxx 方法
- 所有点击事件有响应,数据绑定正确
7.3 代码质量检查
- Class 命名符合规范(无数字、无连字符、无驼峰)
- 所有数据在 data() 中定义
- 所有方法在 methods 中实现
- 没有未使用的变量
- 没有 console.log(除非必要)
搜索框样式异常时:按 6.3.1 带外框搜索框规范检查——外层容器 flex + align-items: center + box-sizing: border-box;el-input 高度 100%;el-input__inner 高度略小于容器、无重复边框、背景透明、border-radius 与容器一致;placeholder 用 ::v-deep .el-input__inner::placeholder 设置;el-input__prefix 与自定义图标垂直居中。
7.4 路由登记检查(交付必做)
- 已在路由文件中为
src/views/${folderName}/补充与项目约定一致的访问路径(常见:静态index.vue与 动态Custom.vue各一条,如/shushi与/shushi-custom)。 -
import路径指向真实文件,component与变量一致,无重复path/name。 - 本地访问新路径无 404,控制台无组件加载错误。
识别步骤、修复模板、需求文案与自检全文见 data/router-sync.md。
步骤 8: 路由登记与校验(Custom.vue 写入完成后)
在 Custom.vue 生成或更新已落盘 之后执行(可与步骤 7 并行收尾,但须在交付前完成):
- 读取项目路由入口(本仓库为
src/router/index.js)。 - 搜索
${folderName}与views/${folderName}/Custom.vue;对照仓库内已有视图(如gushi、yingyu)的 静态 + 动态 成对路由约定。 - 缺失则补全:
import两个组件(index.vue、Custom.vue),在routes中追加path/name/component,风格与现有条目一致。 - 自检:浏览器打开新 path,确认页面渲染且无报错。
禁止:根据路由反推当前页 UI;不得省略本步骤导致 Custom.vue 仅存在于磁盘却无法访问。
data/ 文档索引
详细规范说明请参考 data/ 目录下的文档:
| 分类 | 文件 | 主要内容 |
|---|---|---|
| 项目配置 | data/project-config.md | 文件路径、技术栈、改造目标、改造前后示例 |
| 核心规范 | data/style-consistency.md | 样式一致性、响应式布局、验证方法 |
| 核心规范 | data/class-naming.md | CSS 类命名规范 + Class 重命名强制要求 |
| 核心规范 | data/render.md | 循环渲染、v-for、图片路径、常见错误 |
| 核心规范 | data/element-ui-style.md | Element UI 替换规范、样式覆盖与深度选择器 |
| 核心规范 | data/style-match-standard.md | 按元素重要性的样式匹配标准 |
| 执行流程 | data/execution-flow.md | 执行前准备、开发原则、组件同步生成、验证流程 |
| 任务清单 | data/tasks.md | 任务 1~5 的步骤与验收标准 |
| 验证与验收 | data/validate.md | 最终验证清单:样式 / 功能 / 代码质量检查 |
| 常见问题 | data/faq-solutions.md | 样式、循环、图片、布局、交互等常见问题及解决方案 |
| 识别与修复 | data/recognition-and-fix.md | 下拉框、多选框、纵向模块勾选列(§2.2.1、§3.2.1)、横向/尾行(§2.2.2)、多选尺寸统一(§3.2.2)、多选尺寸读取 wrapper/thumbnail(§3.2.3)、单选框(含折行见 filter-row-wrap.md)、带外框搜索框、分页、背景区域图片样式 / 背景图不显示的识别与修复;按钮与列表内文字垂直居中的识别与修复(含自检清单) |
| 识别与修复 | data/search-input-and-page-overflow.md | 带外框搜索框 placeholder 垂直居中与输入框/底栏按钮不溢出页面的识别、修复与需求文案 |
| 识别与修复 | data/list-item-overflow.md | 列表项内容溢出:v-for 列表内动态文本的识别、修复(max-width/overflow)、需求文案与自检 |
| 识别与修复 | data/list-row-height-alignment.md | 列表行高度与对齐 + 多 rowKind 统一行高与列槽:min-height、固定列宽、flex-shrink;表格形多行类型列表的统一行高、课包列槽、续讲空槽、项间距与 flex 垂直居中;需求文案与自检(含第 8 节) |
| 识别与修复 | data/list-dual-column-independent.md | 双列列表左右独立:左列+右列数据源分离、续讲无左列行 rowKind 与独立布局、禁止单对象硬合并与空字段冒充 |
| 识别与修复 | data/text-direction-vertical-horizontal.md | 文字竖排与横排:根据 index.css 窄宽高瘦与设计语义识别竖排/横排,修复(writing-mode)、需求文案与自检 |
| 识别与修复 | data/list-style.md | 列表样式(单行不换行):v-for 列表项为单行横向排布时 flex-wrap: nowrap、overflow/box-sizing,识别、修复与自检 |
| 识别与修复 | data/filter-row-wrap.md | 筛选项折行与高度自适应:筛选卡/筛选行固定 height 裁切、el-radio-group 换行间距、gap 替代 margin 链;需求文案与自检 |
| 识别与修复 | data/el-button-root-and-deep.md | el-button:根 class 与 ::v-deep;勿用 type="text" 冒充带框次要按钮;相邻 10px;子 img/span 去 margin;三态与 primary 字色 |
| 识别与修复 | data/el-select-suffix-alignment.md | el-select 后缀箭头:禁止根节点 flex+space-between;小高度须同步 icon line-height、suffix right、padding-right |
| 识别与修复 | data/el-color-picker-extend.md | 触发与下拉共同结构、图1 / 图2 对照清单、选型/错配修复、需求文案(评审可粘贴)、el-color-picker-extend 与 el-color-picker 细则、字体颜色触发器、Props/事件、自检;与 6.3 / 6.3.4 / 6.3.11 交叉引用 |
| 交付与工程 | data/router-sync.md | 路由登记:Custom.vue 交付后登记 index/Custom 路由;识别 404/未 import、与稿源关系、自检清单 |
| 关键要求 | data/requirements.md | 文件操作、执行原则、代码规范、数据与方法完整性 |
| 流程总结 | data/workflow-summary.md | 完整开发流程、检查点、快速参考流程图 |
执行完成后
- 报告执行结果:告知用户
Custom.vue文件已生成,并说明主要改造内容 - 列出修改清单:说明完成了哪些改造(循环渲染、Element UI 替换等)
- 路由:说明是否已按
data/router-sync.md检查/更新路由,并给出可访问的 path(如/shushi-custom);若用户环境路由文件路径不同,注明需自行同步 - 打印模型信息:在回复最后打印本次执行所使用的 AI 模型名称与版本信息
快速参考:执行流程图
用户触发 Skill
↓
提取 folderName
↓
验证源文件存在(index.vue + index.vue 所引用的 CSS)
↓
读取源文件(仅上述文件,不读其他工程文件)
↓
分析页面结构(布局、重复结构、交互元素)
↓
生成 Custom.vue(Write 工具直接写入文件)
↓
验证代码质量(含 7.4 路由登记)
↓
登记/校验路由(步骤 8,见 data/router-sync.md)
↓
报告执行结果 + 可访问 path + 打印模型信息