前端交互规范(Web 端)

70 阅读3分钟

前端交互规范(Web 端)

适用于基于 Vue + Element Plus 的中后台管理系统,共 20 条交互规范。


一、布局与展示

1. Table 列表页一屏显示

列表页不允许出现页面级竖向滚动条,筛选区 + 表格必须在一屏内完整展示。

const filterFormRef = ref<HTMLElement>()
const tableHeight = ref(0)
​
function calcTableHeight() {
  const filterH = filterFormRef.value?.offsetHeight ?? 0
  // 根据实际布局减去 header、padding 等固定高度
  tableHeight.value = window.innerHeight - filterH - OTHER_FIXED_HEIGHT
}
​
onMounted(() => {
  calcTableHeight()
  window.addEventListener('resize', calcTableHeight)
})
​
onUnmounted(() => {
  window.removeEventListener('resize', calcTableHeight)
})
<el-table :data="tableData" :height="tableHeight">
  <!-- columns -->
</el-table>

18. 表格操作列固定右侧

操作列使用 fixed="right",横向滚动时操作按钮始终可见。

<el-table-column label="操作" fixed="right" width="200">
  <template #default="{ row }">
    <el-button link type="primary" @click="handleEdit(row)">编辑</el-button>
    <el-button link type="danger" @click="handleDelete(row)">删除</el-button>
  </template>
</el-table-column>

19. 长文本省略 + Tooltip

表格单元格长文本使用 show-overflow-tooltip,保持列宽整齐,悬浮可查看完整内容。

<el-table-column prop="remark" label="备注" show-overflow-tooltip />

二、弹窗与表单

2. 弹窗禁止点击遮罩层关闭

所有弹窗必须设置 close-on-click-modal="false",防止用户误触遮罩层导致数据丢失。

<el-dialog
  v-model="dialogVisible"
  title="新增数据"
  :close-on-click-modal="false"
  width="600px"
>
  <!-- form content -->
</el-dialog>

9. 弹窗表单提交前必须校验

提交前调用 formRef.validate(),校验不通过不发起请求。

async function handleSubmit() {
  const valid = await formRef.value?.validate().catch(() => false)
  if (!valid) return
  // 发起请求
}

15. 弹窗打开时重置表单

弹窗每次打开必须重置表单数据和校验状态,避免上次数据残留。

function openDialog(row?: RowType) {
  nextTick(() => {
    formRef.value?.resetFields()
    if (row) {
      Object.assign(formData, row)
    }
  })
  dialogVisible.value = true
}

11. 弹窗关闭前变更确认

弹窗内表单有修改时,关闭前弹出二次确认"是否放弃修改?"。

function handleDialogClose(done: () => void) {
  if (isFormDirty.value) {
    ElMessageBox.confirm('表单已修改,确定放弃当前编辑内容吗?', '提示', {
      type: 'warning',
    }).then(() => done()).catch(() => {})
  } else {
    done()
  }
}
<el-dialog :before-close="handleDialogClose">

三、防重复提交

3. 流程操作函数节流 + 确认弹窗拦截

新增、完成等流程操作使用 throttle 防止多次点击生成重复数据。

方式一:throttle 节流

import { throttle } from 'lodash'

const handleSubmit = throttle(() => {
  // 业务逻辑
}, 1000, { trailing: false })

方式二:$confirm + beforeClose 模式(推荐用于关键流程操作)

function handleConfirm() {
  ElMessageBox.confirm(
    '确认执行此操作?一旦确认将不可撤回',
    '提示',
    {
      type: 'warning',
      beforeClose: (action, instance, done) => {
        if (action === 'confirm') {
          instance.confirmButtonLoading = true
          instance.confirmButtonText = '执行中...'
          submitApi().finally(() => {
            setTimeout(() => {
              instance.confirmButtonLoading = false
              done()
            }, 300)
          })
        } else {
          done()
        }
      },
    }
  ).then(() => {
    getList()
    ElMessage.success('操作成功')
  }).catch(() => {})
}

10. 提交按钮 Loading 状态

提交/保存按钮在请求期间设为 loading,请求完成后恢复,给用户明确的视觉反馈。

<el-button type="primary" :loading="submitLoading" @click="handleSubmit">
  确 定
</el-button>
const submitLoading = ref(false)

async function handleSubmit() {
  submitLoading.value = true
  try {
    await submitApi(formData)
    ElMessage.success('提交成功')
    dialogVisible.value = false
    getList()
  } finally {
    submitLoading.value = false
  }
}

四、输入与筛选

4. 下拉框必须支持搜索过滤

所有 el-select 加上 filterable 属性,当选项较多时允许用户键入关键字快速定位。

<el-select v-model="formData.type" filterable placeholder="请选择" clearable>
  <el-option
    v-for="item in options"
    :key="item.value"
    :label="item.label"
    :value="item.value"
  />
</el-select>

5. 输入框过滤空格

输入框使用 .trim 修饰符或手动 trim(),避免空格导致查询/提交异常。

<!-- 方式一:v-model.trim -->
<el-input v-model.trim="queryParams.keyword" placeholder="请输入关键字" />

<!-- 方式二:@blur 时手动 trim -->
<el-input v-model="formData.name" @blur="formData.name = formData.name.trim()" />

6. 支持回车触发查询

筛选表单支持按 Enter 键直接触发查询,减少鼠标操作。

<el-form @submit.prevent="handleQuery">
  <el-input
    v-model.trim="queryParams.keyword"
    placeholder="请输入关键字"
    @keyup.enter="handleQuery"
    clearable
  />
</el-form>

16. 数字输入框限制

数字输入框限制输入类型,禁止输入非法字符。

<el-input
  v-model="formData.amount"
  placeholder="请输入金额"
  @input="formData.amount = formData.amount.replace(/[^\d.]/g, '')"
/>

<!-- 或使用 el-input-number -->
<el-input-number v-model="formData.quantity" :min="0" :max="99999" :precision="0" />

17. 日期选择范围限制

日期选择器通过 disabled-date 限制可选范围,避免选择无效日期。

<el-date-picker
  v-model="formData.date"
  type="date"
  placeholder="请选择日期"
  :disabled-date="disabledDate"
/>
function disabledDate(time: Date) {
  return time.getTime() > Date.now()
}

五、加载与状态反馈

7. Table 加载 Loading 状态

数据加载时必须显示 loading,避免空白页面让用户困惑。

<el-table :data="tableData" :height="tableHeight" v-loading="tableLoading">
  <!-- columns -->
</el-table>
const tableLoading = ref(false)

async function getList() {
  tableLoading.value = true
  try {
    const res = await fetchListApi(queryParams)
    tableData.value = res.data.rows
    total.value = res.data.total
  } finally {
    tableLoading.value = false
  }
}

8. 列表空状态提示

列表无数据时显示空状态组件,区分"加载中"与"确实没有数据"。

<el-table :data="tableData" :height="tableHeight" v-loading="tableLoading">
  <!-- columns -->
  <template #empty>
    <el-empty description="暂无数据" />
  </template>
</el-table>

12. 操作成功消息反馈

增删改操作成功后统一使用 ElMessage.success 提示,让用户明确知道操作已完成。

ElMessage.success('新增成功')
ElMessage.success('修改成功')
ElMessage.success('删除成功')

六、危险操作保护

13. 删除等危险操作二次确认

删除、重置等不可逆操作必须使用 ElMessageBox.confirm 二次确认。

async function handleDelete(row: RowType) {
  await ElMessageBox.confirm(
    `确认删除「${row.name}」吗?删除后将无法恢复`,
    '警告',
    { type: 'warning' }
  )
  await deleteApi(row.id)
  ElMessage.success('删除成功')
  getList()
}

七、分页与批量操作

14. 分页状态保持

编辑/删除后保持当前页码;新增后跳转第一页;删除当前页最后一条时自动回退上一页。

function afterEdit() {
  getList() // 保持当前 queryParams.pageNum
}

function afterAdd() {
  queryParams.pageNum = 1
  getList()
}

function afterDelete() {
  if (tableData.value.length === 1 && queryParams.pageNum > 1) {
    queryParams.pageNum--
  }
  getList()
}

20. 批量操作前校验选中状态

批量操作前必须校验是否已选中数据,未选中时给出提示。

function handleBatchDelete() {
  if (selectedRows.value.length === 0) {
    ElMessage.warning('请至少选择一条数据')
    return
  }
  ElMessageBox.confirm(
    `确认删除选中的 ${selectedRows.value.length} 条数据吗?`,
    '警告',
    { type: 'warning' }
  ).then(async () => {
    const ids = selectedRows.value.map(row => row.id)
    await batchDeleteApi(ids)
    ElMessage.success('批量删除成功')
    getList()
  }).catch(() => {})
}

速查清单

#规范关键配置 / API
1列表一屏显示:height="tableHeight" 动态计算
2弹窗禁止遮罩关闭:close-on-click-modal="false"
3流程操作防重复throttle / beforeClose 模式
4下拉框可搜索filterable
5输入框去空格v-model.trim
6回车查询@keyup.enter
7表格 Loadingv-loading
8空状态提示<el-empty>
9提交前校验formRef.validate()
10按钮 Loading:loading="submitLoading"
11关闭前确认:before-close
12成功消息ElMessage.success()
13删除二次确认ElMessageBox.confirm()
14分页保持条件判断 pageNum
15表单重置formRef.resetFields()
16数字输入限制replace / el-input-number
17日期范围限制:disabled-date
18操作列固定fixed="right"
19长文本省略show-overflow-tooltip
20批量操作校验选中数量判断