lanhu-code-2-el-vue

将静态 Vue 页面(index.vue)改造为动态页面(Custom.vue);执行前必须先应用 ui-ux-max-pro 做 UI/UX 分析;稿源仅限 index.vue、其引用的 CSS 与资源路径,禁止参考仓库内其他文件。Invoke when user wants to transform a static Vue page into a dynamic data-driven page with Element UI components.

Audits

Pass

Install

openclaw skills install lanhu-code-2-el-vue

lanhu-code-2-el-vue

介绍

本 Skill 用于将静态 HTML 页面改造为 Vue 2 + Element UI 的数据驱动动态页面,执行时会直接生成 Custom.vue 文件。

前置 Skill:ui-ux-max-pro

当本 Skill 被触发时,必须先执行 ui-ux-max-pro,再继续执行当前 Skill:

  1. 先读取并遵守 ui-ux-max-proSKILL.md
  2. 先完成 ui-ux-max-pro 要求的 UI/UX 分析、布局判断、视觉一致性检查与可用性评估。
  3. ui-ux-max-pro 的结论作为后续静态页改动态页的设计约束,但不得违反本 Skill 的「唯一信息源」限制。
  4. 然后再继续执行当前 lanhu-code-2-el-vueindex.vueCustom.vue 改造流程。
  5. 若找不到 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 时,只允许使用以下材料作为页面结构与样式的依据:

  1. src/views/${folderName}/index.vue 的源码(模板、脚本、内联样式)。
  2. 由 index.vue 直接或间接引用的样式文件(例如 <style src="./assets/index.css">@importimport 等,按路径相对 index.vue 解析;若存在链式 @import,仅沿该链读取,不得扩大范围)。
  3. 在上述 Vue/CSS 中出现的图片等资源路径(保留或转换为 Custom.vue 所需写法即可;无需读取图片二进制内容作「设计参考」)。

禁止:

  • 不得为拼页面而读取、对照或照搬本仓库其他文件的内容,包括但不限于:同目录或其他视图下的 Custom.vueindex.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: 读取源文件(仅限唯一信息源)

  1. 使用 Read 工具读取 src/views/${folderName}/index.vue
  2. 根据 index.vue 中的引用,读取其指向的 CSS(及该 CSS 内 @import 的下一层样式,若需要完整样式表)。
  3. 不要读取 package.json路由文件、其他视图的 Custom.vue 等作为模板/稿源/样式依据(见上文「唯一信息源」;路由仅在步骤 8 用于登记,见 data/router-sync.md)。

步骤 4: 分析源文件结构

分析内容:

  1. 识别页面布局 - 确定是单栏、双栏还是多栏布局
  2. 识别重复结构 - 找出需要循环渲染的部分(使用 v-for)
  3. 识别交互元素 - 找出按钮、输入框、多选、单选等可替换为 Element UI 的元素(开关保留原生 DOM,不替换为 el-switch)
  4. 识别样式特征 - 记录关键样式值(颜色、尺寸、间距)
  5. 识别伪控件(必做) - 源页面常用 div+文案+图标模拟表单控件,须按「6.3.4 伪控件识别与替换」规则识别并替换为 el-select、el-checkbox、el-input;取色须按 点击后展开的下拉面板的形态(图1 / 图2) 选用 el-color-picker-extendel-color-picker不以触发区单独判断;见 6.3 映射表6.3.11data/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)
  • 序位、顺序用英文词表示(如 firstsecondleftright
  • 命名公式:[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

替换时必须:

  1. 先删除该区域原有 DOM 结构(含该控件的全部相关 DOM,见下方「下拉框」说明)
  2. 再写入 Element UI 组件
  3. 同时完成 template、data()、methods 三部分(禁止只写 template 不写 methods/data)
  4. ::v-deep 覆盖 Element UI 默认样式,保持视觉一致
  5. 可点击按钮:页面中所有可点击区域(上传、预览、确定、取消、智能合成等)须在 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: flexalign-items: centerbox-sizing: border-boxoverflow: hidden,使内部输入框垂直居中且不撑高。容器在 hover 与 focus-within 时边框须为主题色.xxx_search_wrapper:hover.xxx_search_wrapper:focus-withinborder-color 为页面主题色),详见 data/recognition-and-fix.md 9.8。
  • .el-input-group:通过 ::v-deep.el-input-group 做样式覆盖:display: flexflex: 1height: 100%min-width: 0border: nonebackground: 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-boxpadding-left 为前缀图标留足空间(如 44px),避免双边框与错位。
  • 占位符::v-deep .el-input__inner::placeholder 设置 placeholder 颜色与设计稿一致(如 rgba(153, 153, 153, 1))。
  • 前缀图标.el-input__prefix 使用 display: flexalign-items: centerheight: 100%left 与设计一致(如 16px);自定义 prefix 插槽根节点用 display: inline-flexalign-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-groupdisplay: flexalign-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: 1min-width: 0max-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.1data/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.3recognition-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-extenddata/el-color-picker-extend.md §「颜色选择:触发与下拉的共同结构」、§选型、§产品需求
取色(图2 形态)展开后SV 渐变方 + 竖向彩虹色相条 + 底栏 Hex +「清空」「确定」(Element UI 2 默认取色下拉);触发区常为 A+下划线+箭头el-color-picker6.3.11data/el-color-picker-extend.md §对照清单、字体颜色触发器

识别步骤(通用):

  1. 在 index.vue 中搜索:带「选」「勾」「搜索」等语义的文案,或带下拉箭头、勾选图标的 div 结构。
  2. 在 index.css 中确认该区域样式:是否有边框、圆角、固定宽高(如 66×28、16×16 勾选区域)。
  3. 若符合上表特征,在 Custom.vue 中替换为对应 Element UI 组件,并补全 data、methods。
  4. 纵向模块勾选列(补充):在配置/预览区搜索多行「左列小方框图 + 右列模块标题」;若左列无说明性长文案、仅方框 png,须按上表「纵向模块勾选列」处理,详见 data/recognition-and-fix.md §2.2.1
  5. 横向工具条 / 尾行(补充):除纵列外,扫描配置区所有横向行底部尾行:是否存在「方框切图 + 模块名 + 业务区」;若 img 与纵列勾选同资源或同类,须同样改为 el-checkbox,详见 6.3.4.2data/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 与稿一致;未选中边框浅灰,选中为白底 + 主题色边框与勾(与稿一致即可);hoveris-focus 边框建议主题色,与 6.3.8 一致。
  • 联动:每个布尔对应右侧一块内容 v-show;双勾(例句/译文)对应同一卡片内两个内容区的分别显示与中隔线条件显示。
  • 禁止:保留原方框 png 冒充勾选态;仅改「全选」行而漏改纵向模块列。

6.3.4.2 横向工具条 / 尾行上的模块勾选与尺寸统一

  • 识别:在顶部横向配置行(如英式音标、鼓点音频)或底部尾行(如单词书写)中,模块标题 span 之前image-wrapper + 小 png,若与左侧纵列模块勾选**尺寸同级(约 16×16)**且语义为「是否展示该段能力」,即属模块勾选,不得仅替换纵列而保留此处静态图。
  • 替换:删除切图,在原 wrapper 内放入与纵列同一 classel-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 / 稿源读取,禁止猜默认):

  1. 在 index.vue 中定位该勾选左侧的 image-wrapper_* + img.thumbnail_*(或仅带 background 的 image-wrapper_*,其自身 width/height 即方框视觉尺寸)。
  2. 在 index.css 中同时打开 .image-wrapper_*.thumbnail_*(若存在):
    • 槽位尺寸:wrapper 的 widthheight(及 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)。
  3. el-checkbox 设为 display: inline-flex; align-items: center; justify-content: center宽高等于槽位(如 16px),__input 同槽位并 flex 居中,__inner 为步骤 2 的方框视觉尺寸(如 13px),box-sizing: border-box
  4. ::after 勾形:在 inner 边长确定后,按比例微调 heightwidthlefttopborder-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__innerbox-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__innerborder-color(Element 在 focus 时给 .el-input 加 .is-focus,漏写则 focus 边框可能仍为默认色)。详见 data/recognition-and-fix.md 9.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__iconline-height 仍按大输入框(如 40px),箭头会上下不齐;须用 ::v-deep.el-input__icon / .el-select__caretline-heightheight 与 inner 对齐,并设置 .el-input__suffixright(对照 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__innerbackground-colorborder-color 为页面主题色(与 6.3.7 主题色来源一致)。
  • 悬停态父级 ::v-deep .el-checkbox__inner:hoverborder-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 残留蓝(必做)

问题识别

  1. 只覆盖了选中与 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 聚焦后边框仍蓝
  2. 单选独有:焦点环为蓝.el-radio:focus:not(.is-focus):not(:active):not(.is-disabled) .el-radio__innerbox-shadow: 0 0 2px 2px $--radio-input-border-color-hover,未覆盖时整圈仍为默认蓝。
  3. 主题色选错(多主色页面):同一 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-checkboxel-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)

  1. 定位该控件在 index.vue 中对应的静态结构(原勾选/单选切图、或同一块卡片内的主按钮、标题竖条 background-color)。
  2. index.css 中查 .thumbnail_* / .image-wrapper_* 背景同区主按钮section_* 装饰条background-color / border-color,取与交互控件一致的那一支作为主色。
  3. 同一页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: 0display: inline-flexalign-items: centerjustify-content: center 使图标居中,并设默认态 color,内部 .el-iconcolor: inherit(见 recognition-and-fix 9.6)。
  • 激活态/主题色当前页 .el-pager li.active 的背景色、边框色须为页面主题色;上一页/下一页 hover 态须同时设边框色与图标色为主题色(须为 .btn-prev:hover.btn-next:hovercolor,并为 .btn-prev:hover .el-icon.btn-next:hover .el-iconcolor,见 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),对 colorbackground-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__innerborder-colorbackground-color 为页面主题色(与 6.3.7/6.3.8 主题色来源一致);父级 ::v-deep .el-radio__input.is-checked + .el-radio__label 的文字色可设为主题色或与设计一致。
    • 悬停态父级 ::v-deep .el-radio__inner:hoverborder-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: wrapalign-items: flex-start(或 align-content: flex-start),gap 控制换行后的纵向/横向间距;行宽在 max-width 与面板一致下可用 width: 100% 覆盖稿中过窄的固定 width
左侧标签flex-shrink: 0height: auto + min-height: [原行高],与选项首行对齐,避免固定 height 与折行冲突。
el-radio-groupflex: 1min-width: 0flex-wrap: wraprow-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-extendel-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.vueindex.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-imageurl(./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.cssassets/ 下,其中 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/

识别与修复(通用流程):

  1. 识别(以稿源 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> 引用)
  2. 写入 Custom.vue 时的规则(必须执行)

    • Template / data():图片路径统一为 require('./assets/img/文件名')
    • <style scoped>:从 index.css 拷贝过来的背景图路径,凡 url(./img/xxx) 一律改为 url(./assets/img/xxx)
  3. 修复已有 Custom.vue(问题排查顺序)

    • 背景区域图片样式异常 / 背景图不显示
      1. 在 Custom.vue 的 <style scoped> 中搜索 url(./img/,若存在则全局替换为 url(./assets/img/
      2. 检查是否误写成 url(@/...)url(/...)(本 Skill 禁止),统一改为 url(./assets/img/...)
      3. 检查迁移时是否丢了 background 的关键子属性:background-repeatbackground-positionbackground-size(如源为 background: url(...) 100% no-repeat; background-size: 100% 100%;),必须完整迁移,否则会表现为「背景拉伸不对/不铺满/位置偏移」。
    • <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: hiddenbox-sizing: border-box;若项内有固定宽高的内容区(如 first-inner),也设 overflow: hiddenmin-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: uprightdisplay: 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: hiddenbox-sizing: border-box(与 6.8 一致)。详见 data/list-style.md(识别步骤、修复方法、需求文案、自检清单)。

6.11 列表行高度与对齐规范(必做)

凡用 v-for 渲染的列表,其列表行(普通行、第一行、第二行等)必须满足以下要求,避免文字被截断和右侧列对齐问题:

  • 高度修复:列表行使用 min-height 而非仅固定 height(如 min-height: 23px; height: 23px;),确保行内文字(line-heightheight 一致)不被截断;行内元素需设置 min-heightheight 一致(如 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_onlyright_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.md 2.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.3recognition-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-extendel-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 并行收尾,但须在交付前完成):

  1. 读取项目路由入口(本仓库为 src/router/index.js)。
  2. 搜索 ${folderName}views/${folderName}/Custom.vue;对照仓库内已有视图(如 gushiyingyu)的 静态 + 动态 成对路由约定。
  3. 缺失则补全import 两个组件(index.vueCustom.vue),在 routes 中追加 path / name / component,风格与现有条目一致。
  4. 自检:浏览器打开新 path,确认页面渲染且无报错。

禁止:根据路由反推当前页 UI;不得省略本步骤导致 Custom.vue 仅存在于磁盘却无法访问。


data/ 文档索引

详细规范说明请参考 data/ 目录下的文档:

分类文件主要内容
项目配置data/project-config.md文件路径、技术栈、改造目标、改造前后示例
核心规范data/style-consistency.md样式一致性、响应式布局、验证方法
核心规范data/class-naming.mdCSS 类命名规范 + Class 重命名强制要求
核心规范data/render.md循环渲染、v-for、图片路径、常见错误
核心规范data/element-ui-style.mdElement 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.mdel-button:根 class 与 ::v-deep;勿用 type="text" 冒充带框次要按钮;相邻 10px;子 img/span 去 margin;三态与 primary 字色
识别与修复data/el-select-suffix-alignment.mdel-select 后缀箭头:禁止根节点 flex+space-between;小高度须同步 icon line-height、suffix right、padding-right
识别与修复data/el-color-picker-extend.md触发与下拉共同结构图1 / 图2 对照清单、选型/错配修复、需求文案(评审可粘贴)el-color-picker-extendel-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完整开发流程、检查点、快速参考流程图

执行完成后

  1. 报告执行结果:告知用户 Custom.vue 文件已生成,并说明主要改造内容
  2. 列出修改清单:说明完成了哪些改造(循环渲染、Element UI 替换等)
  3. 路由:说明是否已按 data/router-sync.md 检查/更新路由,并给出可访问的 path(如 /shushi-custom);若用户环境路由文件路径不同,注明需自行同步
  4. 打印模型信息:在回复最后打印本次执行所使用的 AI 模型名称与版本信息

快速参考:执行流程图

用户触发 Skill
    ↓
提取 folderName
    ↓
验证源文件存在(index.vue + index.vue 所引用的 CSS)
    ↓
读取源文件(仅上述文件,不读其他工程文件)
    ↓
分析页面结构(布局、重复结构、交互元素)
    ↓
生成 Custom.vue(Write 工具直接写入文件)
    ↓
验证代码质量(含 7.4 路由登记)
    ↓
登记/校验路由(步骤 8,见 data/router-sync.md)
    ↓
报告执行结果 + 可访问 path + 打印模型信息