32 KiB
ADDED Requirements
Requirement: Web 管理端以 Fresh Mint 规范为唯一视觉权威
web-admin 工程的界面实现 SHALL 以 docs/web-admin-ui-spec-fresh-mint.md 及其中引用的 docs/fresh-mint-green.html 为权威来源;主色链 SHALL 使用文档定义的 Mint 绿系(如 --primary #10b981 等),不得擅自替换为小程序品牌色。
Scenario: 新增列表页
- WHEN 在
web-admin新增标准列表/表单页 - THEN 页面结构 SHALL 对齐规范中的布局顺序(筛选 → 工具栏 → 列表 → 分页等)及模板页(如
#/demo/unit、#/demo/order)所体现的模式
Requirement: 小程序以三墙 Demo 体系为唯一视觉权威
miniprogram 工程的界面 SHALL 以 docs/miniprogram-ui-spec-sanqiang.md 及其中列出的 mobile-ui/sanqiang-*.html 为权威来源;品牌绿、大麦黄与中性色 SHALL 采用规范 §2 Token,不得直接复用 Web 端 Fresh Mint 色板作为主色。
Scenario: 新增小程序页面
- WHEN 新增客户端/供应商/配送端页面
- THEN 页面 SHALL 遵循规范中的统一骨架(Header 渐变、卡片圆角节奏、底部固定区等)及状态标签语义色
Requirement: 禁止跨端调色板混用
除非产品书面要求,Web 管理端 SHALL NOT 使用小程序规范中的 #0a9f6d 等作为主色;小程序 SHALL NOT 使用 #10b981 作为主色替代品牌绿。
Scenario: Code review
- WHEN PR 修改全局主题或主按钮色
- THEN 审查者 SHALL 对照对应端 UI 规范文档中的 Token 表拒绝跨端拷贝色值
Requirement: 树形主数据展示规则
涉及树形主数据(分类、库位、组织等)时,Web 端 SHALL 遵循:下拉/树节点展示本级名称,选中后在输入框、表格、导出与查看弹窗中展示全路径;路径分隔符 SHALL 与工程约定一致(当前为 /,见 web-admin/src/utils/tree-path.ts 与规范 §5.6)。
Scenario: 树选择与表格列
- WHEN 用户在树形选择器中选择末级节点
- THEN 表格与只读视图 SHALL 展示完整祖先路径而非仅末级名称
Requirement: 弹窗与遮罩
Web 管理端弹窗 SHALL 遵循规范:表单 label-position="top";遮罩 SHALL NOT 使用背景模糊(backdrop-filter: none 等与仓库既有策略一致)。
Scenario: 新增编辑弹窗
- WHEN 使用 Element Plus
el-dialog承载表单 - THEN 表单标签位置与遮罩样式 SHALL 符合
docs/web-admin-ui-spec-fresh-mint.md中el-dialog小节
Requirement: 小程序媒体与触控
小程序列表缩略图、轮播与详情图 SHALL 遵循 docs/miniprogram-ui-spec-sanqiang.md §7.0 的宽高比与 mode 约定;可点击控件 SHALL 满足最小触控区域(规范中的 44×44 等要求)。
Scenario: 商品列表缩略图
- WHEN 展示商品列表缩略图
- THEN 图片区域 SHALL 为 1:1 且使用
aspectFill(与规范 §7.0.1 一致)
Requirement: 列表面板主标题装饰
web-admin 中列表面板 panel-top 下的主标题(h2.title-bar-heading)SHALL 在标题文案前展示 主色竖条(与全局 app.scss 中 h2.title-bar-heading::before 一致);含「租户」「用户」等易歧义文案的标题 SHALL 通过 App.vue 中 panelTitleBarTextRules 显式纳入竖条样式,避免子串误匹配为其它图标。
重要:App.vue 中 panelTitleBarTextRules 是标题竖条样式的唯一触发入口。新增任何包含 panel-top > h2 标题的页面时,开发者 SHALL 将该标题文案追加到 panelTitleBarTextRules 正则表达式的 | 分隔列表中。遗漏将导致标题无绿色竖条而显示为无样式或错误图标。
Scenario: 租户列表标题
- WHEN 打开
#/system/tenant租户管理页 - THEN 「租户列表」标题 SHALL 显示绿色竖条装饰,且 SHALL NOT 因「租户」含「用户」子串而显示用户类图标
Scenario: 新增页面标题竖条
- WHEN 新增包含
panel-top > h2标题的列表页(如标题为"XXX列表") - THEN 开发者 SHALL 在
App.vue的panelTitleBarTextRules正则中追加该标题文案(用|分隔) - THEN 标题 SHALL 显示绿色竖条装饰
Scenario: Code review 新页面标题
- WHEN PR 包含新增页面的
panel-top > h2标题 - THEN 审查者 SHALL 确认
App.vue的panelTitleBarTextRules已同步更新
Requirement: 弹窗与面板内子区域标题装饰
web-admin 中弹窗(el-dialog)和面板内的子区域标题(如「选择部门」「已选用户」「基本信息」「参数配置」等区块标题)SHALL 在文字左侧展示主色竖条装饰(border-left: 3px solid #10b981,padding-left: 10px),与列表面板主标题的竖条风格保持一致。子区域标题与字段标签(el-form-item label 或 dt)SHALL 形成明显视觉区分:子区域标题使用深色文字 + 竖条,字段标签使用辅助灰色、无竖条。
此规则适用于以下场景的区块标题:
- 弹窗内分组标题:如编辑弹窗中的「基本信息」「参数配置」等将表单字段分组的标题。
- 多栏选择器的列标题:如「选择部门」「选择用户」等
data-scope-col-title类标题。 - 已选摘要的分组标题:如「已选部门」「已选用户」等
data-scope-summary-heading类标题。 - 查看弹窗的区块标题:
SystemViewDialog的 section title(h3)。 - 设计器/工具面板的分组标题:如「节点类型」「属性」等
panel-section-title类标题。
Scenario: 新增弹窗包含子区域分组
- WHEN 新增编辑弹窗内使用
section-title、col-title、summary-heading等类名作为区块标题 - THEN 标题 SHALL 使用
border-left: 3px solid #10b981+padding-left: 10px展示主色竖条
Scenario: Code review 弹窗子区域标题
- WHEN PR 包含弹窗内新增或修改的区块标题样式
- THEN 审查者 SHALL 确认标题包含主色竖条装饰,且与字段标签有明确视觉区分
Requirement: 新增与编辑弹窗布局与视口留白
使用 Element Plus el-dialog 承载新增/编辑表单时,系统 SHALL 满足:
- 水平栅格:默认使用 两列 栅格(
.form-grid-2,grid-template-columns: repeat(2, minmax(0, 1fr)),gap: 12px 20px);字段较多时 SHALL 通过加宽width并选用.form-grid-3、.form-grid-4或.form-grid-5扩展列数,列数上限为 5;跨整行长字段 SHALL 使用.form-col-span-2(grid-column: 1 / -1)。 - 窄屏回退:视口或表单区过窄时,栅格 SHALL 回退为更少列或单列(与全局
app.scss中@media (max-width: 900px)、(max-width: 560px)规则一致)。 - 定位:弹窗 SHALL 相对视口水平与垂直居中(依赖
ElConfigProvider的dialog.alignCenter及 Element Plus 默认遮罩层居中行为)。 - 高度与滚动:使用
.dialog-form-layout类名的弹窗壳层 SHALLmax-height: calc(100vh - 100px),保证相对视口上下各 至少约 50px 可视留白;弹窗 SHALL NOT 以固定高度占满视口;当内容超出时 仅.el-dialog__body区域出现纵向滚动条,页头与底栏固定不滚动。
Scenario: 租户新增弹窗
- WHEN 在租户管理页打开新增或编辑租户弹窗
- THEN 表单 SHALL 以两列栅格展示常规字段、备注跨两列;弹窗 SHALL 带
dialog-form-layout且正文区在内容过多时可滚动
Scenario: 高字段数弹窗
- WHEN 某业务弹窗字段超过两列舒适排布
- THEN 实现 SHALL 增加
el-dialog的width并选用form-grid-3至form-grid-5之一,且 SHALL NOT 使用超过 5 列的栅格类
Requirement: 图标组件使用 Element Plus 图标
web-admin 中的图标 SHALL 优先使用 Element Plus 内置图标(@element-plus/icons-vue),通过 ArtSvgIcon 组件的 EP 图标映射(src/utils/ui/ep-icon-map.ts)渲染;SHALL NOT 在新增代码中直接使用 Iconify 远程图标名(如 ri:xxx、fluent:xxx)。仅在 Element Plus 无等价图标时,方可保留 Iconify 图标名作为例外。
Scenario: 新增菜单路由
- WHEN 在
src/router/modules/中新增路由并设置meta.icon - THEN
icon值 SHALL 使用ep-icon-map.ts中已注册的名称(如setting、grid),SHALL NOT 使用ri:前缀的 Iconify 名
Scenario: 新增界面图标
- WHEN 在页面或组件中新增图标
- THEN SHALL 使用
<ArtSvgIcon icon="ep-icon-name" />或<el-icon><XxxIcon /></el-icon>,SHALL NOT 使用<ArtSvgIcon icon="ri:xxx" />除非 Element Plus 无等价图标
Scenario: 新增 Element Plus 图标
- WHEN Element Plus 提供了新的所需图标但
ep-icon-map.ts尚未注册 - THEN 开发者 SHALL 先在
ep-icon-map.ts中注册映射条目,再在业务代码中使用
Requirement: 表格操作列固定在右侧
web-admin 中所有业务列表页(系统管理、业务模块等,不含 Demo 参考页)的 el-table 操作列 SHALL 使用 fixed="right" 固定在表格右侧。宽度规则:2 个按钮时 width="260",3 个按钮时 width="320",4 个及以上按钮时 width="400"。全局 CSS 通过 .el-table-fixed-column--right 选择器(注意:Element Plus 使用单短横线,非双下划线)提供固定列样式。
Scenario: 新增系统管理列表页
- WHEN 在系统管理模块下新增列表页面(如用户管理、角色管理等)
- THEN 表格操作列 SHALL 设置
fixed="right",宽度按按钮数设置:≤ 2 按钮用width="260",3 按钮用width="320",≥ 4 按钮用width="400"
Scenario: Code review 表格列
- WHEN PR 包含新增或修改的
el-table-column且label="操作" - THEN 审查者 SHALL 确认该列包含
fixed="right"属性,且宽度与按钮数量匹配(2 按钮 260px,3+ 按钮 320px)
Requirement: 侧边栏菜单图标层级规则
web-admin 左侧菜单区域的图标展示 SHALL 遵循以下层级规则:
- 一级菜单(顶层菜单项)SHALL 在菜单名称前展示图标(
meta.icon)。 - 二级及以下菜单(子菜单项)SHALL NOT 展示图标,仅展示文字名称。
- 双列菜单模式(
DualMenu)左侧一级图标栏 SHALL 为每个一级菜单项渲染图标,与侧边栏一级规则一致。 - 水平菜单(
HorizontalMenu)和混合菜单(MixedMenu)如使用图标,SHALL 与侧边栏保持相同的层级规则。
Scenario: 侧边栏一级菜单图标
- WHEN 用户打开
web-admin主页,查看左侧菜单区域的一级菜单项 - THEN 每个一级菜单项 SHALL 在文字名称左侧展示其
meta.icon对应的图标
Scenario: 侧边栏二级菜单无图标
- WHEN 用户展开某个一级菜单,查看其下的二级(及更深层级)菜单项
- THEN 二级及以下菜单项 SHALL NOT 展示任何图标,仅显示菜单文字名称
Scenario: Code review 菜单图标
- WHEN PR 修改了
SidebarSubmenu.vue或其他菜单组件中图标渲染逻辑 - THEN 审查者 SHALL 确认
level === 0条件判断保持不变,仅一级菜单渲染图标
Requirement: 标签页(WorkTab)不展示图标
web-admin 顶部标签页区域(WorkTab strip)的每个标签 SHALL 仅展示文字标题,SHALL NOT 展示图标。路由 meta.icon 仅用于侧边栏菜单,SHALL NOT 传递到标签页渲染。
Scenario: 标签页仅显示文字
- WHEN 用户打开任意页面,顶部标签页区域出现对应标签
- THEN 标签 SHALL 仅展示页面标题文字,SHALL NOT 在标题前展示任何图标
Scenario: Code review 标签页图标
- WHEN PR 修改了
art-work-tab/index.vue或utils/navigation/worktab.ts - THEN 审查者 SHALL 确认标签页组件不渲染图标,且
setWorktab不向openTab传递icon字段
Requirement: 表单字段注释格式
web-admin 中弹窗表单(el-form-item)如需对某字段添加辅助说明文字(如"数值越小越靠前"),该注释 SHALL 以小字形式直接显示在 label 文字后方,SHALL NOT 放置在输入控件旁边或下方。实现方式为使用 el-form-item 的 #label 插槽,在 label 文字后追加 <span class="form-label-tip">注释内容</span>。样式类 form-label-tip 定义在全局 app.scss 中(字号 12px、font-weight: 400、使用 --mint-text-muted 颜色)。
Scenario: 排序字段注释
- WHEN 弹窗表单中包含排序字段(
orderNum) - THEN label SHALL 显示为"排序",其后紧跟小字注释"数值越小越靠前",使用
.form-label-tip样式类,SHALL NOT 使用.sort-field+.form-tip的旧模式
Scenario: 新增带注释的表单字段
- WHEN 新增弹窗表单中的某字段需要辅助说明
- THEN SHALL 使用
<template #label>字段名<span class="form-label-tip">注释内容</span></template>格式,SHALL NOT 将注释放在输入控件旁
Requirement: 列表行查看弹窗(按钮 + 双击)
web-admin 中所有系统管理与业务列表页(含标准列表、树形列表)的 el-table SHALL 提供只读「查看」弹窗能力,实现规则如下:
- 操作列「查看」按钮:操作列 SHALL 在首位包含一个「查看」按钮(
<el-icon><View /></el-icon>查看),点击后弹出只读查看弹窗。 - 行双击触发:
el-tableSHALL 监听@row-dblclick事件,双击任意行时触发与「查看」按钮相同的弹窗(即调用同一handleView(row)函数)。 - 弹窗样式:查看弹窗 SHALL 使用
SystemViewDialog共享组件(src/components/business/system-view-dialog/index.vue),样式对齐待办中心「查看详情」弹窗(无标题栏、hero 渐变头图 + 图标、KV grid 字段展示、关闭按钮)。 - 字段内容:查看弹窗 SHALL 展示该行记录的所有业务字段(含状态映射、字典翻译),不展示
id、del_flag等技术字段。长文本/备注字段 SHALL 使用span: true跨两列展示。 - 区块标题样式:查看弹窗中各区块标题(
SystemViewDialog的 section title,渲染为h3)SHALL 与字段标签(dt)形成明显视觉区分。区块标题 SHALL 使用深色文字(#1e293b)配合左侧主色竖条装饰(border-left: 3px solid #10b981),字号 14px、font-weight: 600;字段标签 SHALL 保持为辅助灰色(#64748b)、font-weight: 500。区块标题样式 SHALL NOT 与字段标签使用相同颜色或相近字重。
Scenario: 新增系统管理列表页
- WHEN 在系统管理模块下新增标准列表页面
- THEN 操作列首位 SHALL 包含「查看」按钮,且
el-tableSHALL 绑定@row-dblclick="handleView"事件 - THEN 点击「查看」按钮或双击行 SHALL 打开同一
SystemViewDialog弹窗
Scenario: 现有页面补充查看弹窗
- WHEN 为现有列表页补充查看弹窗
- THEN SHALL 同时添加操作列「查看」按钮与
@row-dblclick双击事件,两者调用同一个handleView函数
Scenario: Code review 查看弹窗
- WHEN PR 修改列表页面且页面包含
el-table - THEN 审查者 SHALL 确认
el-table绑定了@row-dblclick事件,且操作列包含「查看」按钮
Requirement: 查看弹窗中编码字段展示为可读标签
web-admin 中所有只读查看弹窗(SystemViewDialog 及类似组件)中,存储为编码(code / value)的字段 SHALL 展示为对应的人类可读标签(label),SHALL NOT 直接展示原始编码值。这包括但不限于:字典编码→字典标签、状态编码→状态文本、站点类型编码→类型名称等。
对于多值编码字段(如逗号分隔的编码串),SHALL 逐个编码转换为标签后以顿号(、)连接展示;无匹配标签时 SHALL 回退展示原始编码值。
Scenario: 站点管理查看弹窗
- WHEN 用户点击站点管理列表中某行的「查看」按钮
- THEN 「经营范围」字段 SHALL 展示为编码对应的标签文本(如"蔬菜、水果"),SHALL NOT 展示原始编码串(如"1,2")
Scenario: 新增包含字典编码字段的查看弹窗
- WHEN 新增列表页的查看弹窗中包含字典编码、状态编码等字段
- THEN 实现 SHALL 使用对应字典选项(
businessScopeOptions、statusOptions等)将编码翻译为标签后展示
Scenario: Code review 查看弹窗编码展示
- WHEN PR 修改查看弹窗中涉及编码类字段的展示
- THEN 审查者 SHALL 确认字段值已翻译为可读标签,SHALL NOT 出现原始编码值
Requirement: 排序字段不在界面默认展示
web-admin 中所有列表页的表格列、新增弹窗表单、编辑弹窗表单 SHALL NOT 默认包含排序字段(sortOrder、orderNum、排序等)。排序字段仅在产品明确要求时按需添加,不应作为默认 UI 元素。
Scenario: 新增标准列表页
- WHEN 新增标准 CRUD 列表页(含新增/编辑弹窗)
- THEN 表格列和弹窗表单中 SHALL NOT 包含排序相关字段,除非产品需求明确要求
Scenario: Code review 排序字段
- WHEN PR 新增列表页或弹窗中包含排序字段
- THEN 审查者 SHALL 确认产品需求中有明确排序要求,否则 SHALL 要求移除
Requirement: 附件上传卡片化布局
web-admin 中弹窗表单的附件上传区域 SHALL 使用卡片化布局:上传触发器与已上传附件在同一行 flex 容器中排列,上传卡片作为第一个元素始终可见。具体规则:
- 上传卡片样式:上传触发器 SHALL 渲染为与附件卡片等尺寸的卡片(宽 120px、高 96px),使用虚线边框(
border: 1px dashed #a7f3d0)、浅绿背景(background: #f0fdf4),居中显示Plus图标(size 28)与"上传附件"文字(12px#10b981)。hover 时边框变实线(border-color: #10b981)、背景加深(background: #ecfdf5)。 - 同行排列:上传卡片与已上传附件卡片 SHALL 放在同一个
display: flex; flex-wrap: wrap; gap: 12px容器内,上传卡片为第一个子元素。容器 SHALL 始终可见(不受附件数量影响)。 - 附件卡片样式:已上传附件卡片 SHALL 为 120px 宽、96px 预览区高度,带实线边框(
border: 1px solid #e2e8f0)。图片文件显示缩略图(object-fit: cover),视频文件显示紫色视频图标,其他文件显示蓝色文档图标。卡片底部显示文件名(11px,最多 2 行省略)与操作按钮(下载、删除,居中排列)。 - 上传中状态:正在上传的附件卡片 SHALL 设置
opacity: 0.6且pointer-events: none,预览区显示Loading图标。 - 提示文案:格式说明文字(如"支持图片、视频、PDF...,单文件不超过 20MB")SHALL 显示在卡片行下方,作为独立的
11px灰色小字(color: #94a3b8)。 - 颜色约束:上传卡片与附件卡片 SHALL 使用 Fresh Mint 色板(
#10b981、#a7f3d0、#f0fdf4、#ecfdf5),SHALL NOT 使用小程序品牌色#0a9f6d。
标准写法示例
<el-form-item label="协议附件" class="form-col-span-2">
<div class="attachment-upload">
<div class="attachment-list">
<!-- 上传卡片始终在第一个 -->
<el-upload
ref="attachmentUploadRef"
:auto-upload="false"
:show-file-list="false"
:multiple="true"
accept="image/*,video/*,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.zip,.rar"
@change="handleAttachmentChange"
>
<div class="upload-card">
<el-icon :size="28" color="#10b981"><Plus /></el-icon>
<span class="upload-card-text">上传附件</span>
</div>
</el-upload>
<!-- 已上传附件卡片 -->
<div v-for="(file, index) in formData.attachments" :key="file.id || index"
class="attachment-item" :class="{ 'is-uploading': file._uploading }">
<div class="attachment-preview">
<!-- 图片缩略图 / 视频图标 / 文档图标 -->
</div>
<div class="attachment-footer">
<span class="attachment-name">{{ file.fileName }}</span>
<div class="attachment-actions">
<el-icon class="action-btn" title="下载" @click="handleDownload(file)"><Download /></el-icon>
<el-icon class="action-btn action-btn--danger" title="删除" @click="removeAttachment(index)"><Delete /></el-icon>
</div>
</div>
</div>
</div>
<span class="upload-hint">支持图片、视频、PDF、Word、Excel等文件,单文件不超过 20MB</span>
</div>
</el-form-item>
.upload-card {
width: 120px;
height: 96px;
border: 1px dashed #a7f3d0;
border-radius: 8px;
background: #f0fdf4;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 6px;
cursor: pointer;
transition: border-color 0.15s, background 0.15s;
&:hover {
border-color: #10b981;
border-style: solid;
background: #ecfdf5;
}
}
.upload-card-text {
font-size: 12px;
color: #10b981;
font-weight: 500;
line-height: 1;
}
.upload-hint {
display: block;
font-size: 11px;
color: #94a3b8;
line-height: 1;
margin-top: 8px;
}
.attachment-list {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
.attachment-item {
width: 120px;
border: 1px solid #e2e8f0;
border-radius: 8px;
background: #fff;
overflow: hidden;
transition: border-color 0.15s, box-shadow 0.15s;
&:hover {
border-color: #10b981;
box-shadow: 0 2px 8px rgba(16, 185, 129, 0.1);
}
&.is-uploading {
opacity: 0.6;
pointer-events: none;
}
}
.attachment-preview {
width: 120px;
height: 96px;
display: flex;
align-items: center;
justify-content: center;
background: #f8fafc;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
}
.attachment-footer {
padding: 6px 8px;
position: relative;
}
.attachment-name {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
font-size: 11px;
color: #334155;
line-height: 1.4;
word-break: break-all;
}
.attachment-actions {
display: flex;
justify-content: center;
gap: 8px;
margin-top: 4px;
}
Scenario: 新增弹窗包含附件上传
- WHEN 在弹窗表单中新增附件上传功能
- THEN 上传触发器 SHALL 渲染为卡片样式(120×96px,虚线边框),与附件卡片在同一 flex 行中排列
- THEN 容器 SHALL 始终可见(上传卡片始终显示),提示文案在卡片行下方
Scenario: 附件卡片预览
- WHEN 用户上传图片文件
- THEN 附件卡片预览区 SHALL 显示图片缩略图(
object-fit: cover),点击可预览大图 - WHEN 用户上传视频文件
- THEN 预览区 SHALL 显示紫色视频图标(
background: #ede9fe; color: #7c3aed) - WHEN 用户上传其他类型文件
- THEN 预览区 SHALL 显示蓝色文档图标(
background: #e0f2fe; color: #0284c7)
Scenario: 附件上传中状态
- WHEN 文件正在上传到服务器
- THEN 对应附件卡片 SHALL 显示为半透明(
opacity: 0.6)且不可操作(pointer-events: none),预览区显示 Loading 图标
Scenario: Code review 附件上传组件
- WHEN PR 包含新增或修改的附件上传区域
- THEN 审查者 SHALL 确认使用卡片化布局(上传卡片 + 附件卡片同行),SHALL NOT 使用独立的上传按钮行或 Element Plus 默认文件列表
Requirement: 按钮须携带图标
web-admin 中所有带文字标签的 el-button(或 ElButton)SHALL 在文字前方包含 <el-icon> 子元素,使用 @element-plus/icons-vue 提供的图标组件;SHALL NOT 出现仅有文字而无图标的按钮。图标的引入方式为在文件 <script setup> 中显式 import 所需图标组件(@element-plus/icons-vue 不属于 auto-import 范围)。
常用按钮图标映射
| 按钮语义 | 图标组件 | 适用场景 |
|---|---|---|
| 新增 | Plus |
工具栏「新增 XXX」按钮 |
| 搜索 | Search |
筛选区「搜索」按钮 |
| 重置 | RefreshLeft |
筛选区「重置」按钮 |
| 确定 / 确认 / 提交 / 保存 | Check |
弹窗确认类按钮 |
| 取消 / 关闭 | Close |
弹窗取消、关闭按钮 |
| 编辑 / 修改 | Edit |
操作列「编辑」按钮 |
| 删除 / 批量删除 | Delete |
操作列、工具栏「删除」按钮 |
| 查看 / 详情 / 查看详情 | View |
操作列「查看」「详情」按钮 |
| 审批 / 审核 | EditPen |
操作列「审批」按钮 |
| 配置 / 设置 | Setting 或 SetUp |
操作列「配置」按钮 |
| 导入 / 上传 | Upload |
工具栏「导入」、表单「上传」按钮 |
| 折叠 / 展开 | ArrowDown / ArrowUp |
工具栏「展开/收起」按钮 |
Scenario: 新增列表页工具栏按钮
- WHEN 在列表页筛选区添加「搜索」和「重置」按钮
- THEN 按钮 SHALL 包含
<el-icon><Search /></el-icon>和<el-icon><RefreshLeft /></el-icon>,SHALL NOT 仅有文字
Scenario: 新增弹窗底部按钮
- WHEN 在
el-dialog的#footer插槽中添加「取消」和「确定」按钮 - THEN 取消按钮 SHALL 包含
<el-icon><Close /></el-icon>,确定按钮 SHALL 包含<el-icon><Check /></el-icon>
Scenario: 新增表格操作列按钮
- WHEN 在表格操作列添加「编辑」「删除」「查看」等操作按钮
- THEN 每个按钮 SHALL 包含对应的
<el-icon>子元素(如<el-icon><Edit /></el-icon>),SHALL NOT 仅有文字
Scenario: 新增工具栏主操作按钮
- WHEN 在列表工具栏添加「新增 XXX」主操作按钮
- THEN 按钮 SHALL 包含
<el-icon><Plus /></el-icon>
Scenario: Code review 按钮图标
- WHEN PR 包含新增或修改的
el-button - THEN 审查者 SHALL 确认该按钮包含
<el-icon>子元素,且图标组件已从@element-plus/icons-vue显式导入
标准写法示例
<!-- 工具栏 -->
<el-button class="btn-main" type="primary" @click="handleAdd">
<el-icon><Plus /></el-icon>
新增单位
</el-button>
<!-- 筛选区 -->
<el-button class="btn-ghost" @click="handleReset">
<el-icon><RefreshLeft /></el-icon>重置
</el-button>
<el-button class="btn-main" type="primary" @click="handleSearch">
<el-icon><Search /></el-icon>搜索
</el-button>
<!-- 操作列 -->
<el-button class="btn-op-item primary" @click="handleEdit(row)">
<el-icon><Edit /></el-icon>编辑
</el-button>
<el-button class="btn-op-item" @click="handleDelete(row)">
<el-icon><Delete /></el-icon>删除
</el-button>
<!-- 弹窗底部 -->
<el-button class="btn-ghost" @click="dialogVisible = false">
<el-icon><Close /></el-icon>取消
</el-button>
<el-button class="btn-main" type="primary" @click="handleSubmit">
<el-icon><Check /></el-icon>确定
</el-button>
// <script setup> 中显式导入
import { Plus, Close, Check, Search, RefreshLeft, Edit, Delete, View } from '@element-plus/icons-vue'
Requirement: 状态、结论与类型字段使用 Tag 标签展示
web-admin 中所有列表表格和查看弹窗中的状态、结论、类型等枚举类字段 SHALL 使用 Element Plus <el-tag> 组件以彩色标签形式展示,SHALL NOT 以纯文本形式展示。具体规则如下:
1. 表格列中的 Tag 展示
el-table 中所有状态/结论/类型列 SHALL 在 <template #default="{ row }"> 内使用 <el-tag> 渲染,并通过 :type 属性区分语义色。SHALL NOT 使用自定义 <span class="tag"> 或纯文本。
标准写法:
<el-table-column prop="status" label="状态" width="90" align="center">
<template #default="{ row }">
<el-tag :type="row.status === '1' ? 'success' : 'info'" size="small">
{{ row.status === '1' ? '正常' : '停用' }}
</el-tag>
</template>
</el-table-column>
多状态映射标准写法(使用辅助函数):
<el-table-column prop="workOrderStatus" label="状态" width="100" align="center">
<template #default="{ row }">
<el-tag :type="statusTagType(row.workOrderStatus)" size="small">
{{ statusLabel(row.workOrderStatus) }}
</el-tag>
</template>
</el-table-column>
function statusTagType(s: string): string {
const m: Record<string, string> = { ywc: 'success', ypz: 'warning', dpz: 'info' }
return m[s] || 'info'
}
2. 查看弹窗(SystemViewDialog)中的 Tag 展示
使用 SystemViewDialog 组件(src/components/business/system-view-dialog/index.vue)时,状态/结论/类型字段 SHALL 在 ViewField 定义中传入 tagType 属性。组件检测到 tagType 后自动以 <el-tag> 渲染该字段值。
ViewField 接口扩展(已实现):
export type TagType = 'success' | 'warning' | 'danger' | 'info' | '' | 'primary'
export interface ViewField {
label: string
value: string | number | boolean | null | undefined
span?: boolean
/** 传入后以 el-tag 渲染,值为 el-tag 的 type 属性 */
tagType?: TagType
}
标准写法:
const viewSections = computed<ViewSection[]>(() => [
{
title: '任务信息',
fields: [
{ label: '任务号', value: d.taskNo },
{ label: '状态', value: statusLabel(d.status), tagType: d.status === 'ywc' ? 'success' : d.status === 'jxz' ? 'warning' : 'info' },
{ label: '检测结论', value: conclusionLabel(d.conclusion), tagType: d.conclusion === 'tg' ? 'success' : d.conclusion === 'btg' ? 'danger' : 'info' },
// 普通字段不加 tagType,仍以纯文本展示
{ label: '备注', value: d.remark || '—', span: true },
]
}
])
3. 自定义查看弹窗中的 Tag 展示
不使用 SystemViewDialog 的自定义查看弹窗(如 ProtocolViewDialog、DonationViewDialog 等)中的状态/结论字段 SHALL 同样使用 <el-tag> 展示。
标准写法:
<dd>
<el-tag :type="row.acceptConclusion === 'js' ? 'success' : 'danger'" size="small">
{{ acceptConclusionLabel(row.acceptConclusion) }}
</el-tag>
</dd>
4. Tag 类型语义色映射规范
| Tag Type | 颜色 | 适用语义 | 示例 |
|---|---|---|---|
success |
绿色 | 正常、启用、已完成、生效中、通过 | 正常/启用/已完成/接收/通过 |
warning |
橙色 | 进行中、待确认、已过期、预警 | 进行中/已排配/已过期/待确认 |
danger |
红色 | 异常、停用、已作废、拒绝、不通过 | 异常/已作废/拒绝/不通过 |
info |
灰色 | 待执行、待生效、未知、默认 | 待执行/待生效/停用/无结论 |
primary |
蓝色 | 特殊分类、来源类型、转出 | 转科研/转细胞存储/来源类型/菜单类型 |
对于启用/停用的状态字段,SHALL 使用 success(启用)和 info(停用),SHALL NOT 使用 danger 表示停用状态。
5. 公共标签映射函数
多个页面复用的状态标签映射 SHALL 抽取为公共工具函数(如 utils/protocol-payment-labels.ts、utils/qc-labels.ts),同时提供 xxxLabel(文本)和 xxxTagType(tag type)两个配套函数。仅单个页面使用的状态标签 SHALL 在页面 <script setup> 中定义。
Scenario: 新增列表页包含状态列
- WHEN 新增列表页的表格中包含状态、结论或类型字段
- THEN 该列 SHALL 使用
<el-tag>渲染,通过:type绑定语义色,SHALL NOT 使用纯文本或自定义<span class="tag">
Scenario: 新增查看弹窗包含状态字段
- WHEN 新增
SystemViewDialog查看弹窗,且 fields 中包含状态/结论/类型字段 - THEN 该字段 SHALL 传入
tagType属性,组件自动以<el-tag>渲染
Scenario: Code review Tag 展示
- WHEN PR 修改列表页或查看弹窗中的状态/结论/类型字段展示
- THEN 审查者 SHALL 确认使用
<el-tag>组件(表格列)或tagType属性(SystemViewDialog),SHALL NOT 出现纯文本状态展示或自定义<span class="tag">