vue2.md 8.8 KB

Tofly Vue2 约束

本文件为公司统一配置(L1)的语言约束部分,涵盖 Tofly Vue2 前端项目的专属约定和模板。 按需动态加载:当任务涉及 Vue 2 / Options API / Element UI 前端代码编写时加载本文件。

公共规范(格式、命名、API层组织、权限模式、CRUD架构、Lint流程)已在公司统一配置 §六 中定义,本文件不再重复。


一、代码库风格快照

本仓库前端有两种可见的风格集群:

  • Tofly 标准管理风格src/views/system/**src/views/monitor/** 等)

    • 高度标准化的 CRUD 模式
    • v-hasPermi 权限门控
    • dicts + dict-tag 字典渲染
    • Pagination + RightToolbar
    • 查询 + 表格 + 对话框结构
  • Flowable 业务页面src/views/function/**src/views/todo/**

    • 更灵活的风格,部分组件抽象
    • 一些命名/间距不一致
    • 仍基于 Vue2 + Element UI + request API 模块

规则:新模块优先使用 Tofly 标准 CRUD 风格;编辑遗留模块时遵循本地风格,除非要求重构否则不做大型重构。

模块边界

  • 前端业务页面/API 对接 HRM 业务端点(tolfy-hrm-business
  • 不围绕 tofly-system 内部实体设计新页面

二、技术栈约束

  • 使用 Vue 2 Options API(export default { data, created/mounted, methods }
  • 使用 Element UI 组件
  • 路径别名:@/src/
  • 使用 src/utils/request.js 封装的 axios
  • 禁止引入 Vue 3 / Composition API / TypeScript / Pinia

三、Vue2 专属规范

  • API 文件路径:优先 src/api/<module>/<entity>.js,已有的 views/**/api 可保留
  • Vue 组件 name:应使用 PascalCase;编辑遗留小写名称时保持兼容
  • API 命名模式(覆盖公司统一配置 §6.3):listX / getX / addX / updateX / delX
  • 后端字段不强制 camelCase
  • 导出使用 this.download(...)

四、请求与响应约定

  • 仅使用 src/utils/request.js
  • 定义 API 方法:request({ url, method, params/data })
  • 后端成功信封格式:{ code, msg, data, rows, total }
  • 列表页面:response.rows → 列表数据,response.total → 分页总数


五、UI/交互模式

Search + Table + Dialog

  • 搜索表单模型:queryParams
  • 日期范围:dateRange + this.addDateRange(queryParams, dateRange)
  • 选择行为:ids = selection.map(...) / single = selection.length !== 1 / multiple = !selection.length
  • 对话框:open 控制可见性,title 指示新增/编辑,reset() 初始化默认值

反馈

  • 成功:this.$modal.msgSuccess(...)this.$message.success(...),跟随本地文件风格
  • 确认删除/导出:this.$modal.confirm(...)this.$confirm(...),跟随本地文件风格

Vue2 CRUD 全局组件Pagination, RightToolbar, DictTag


六、权限与字典

  • 使用 v-hasPermi="['module:resource:action']" 添加操作级权限(参见公司统一配置 §6.5)
  • 使用字典 API/组件,不在页面逻辑中硬编码 label map(已有字典时)
  • 可配置的值放在后端 config/dict 中,而非前端常量

七、Flowable 页面

  • 前端应提交业务表单数据和任务变量
  • 审批路由决策属于 Flowable 模型配置,不在前端硬编码
  • 添加工作流交互时复用任务端点和 todo 页面模式
  • 编辑遗留 Flowable 页面时,先遵循本地风格,仅在需要时做最小清理

八、编辑前 Lint 流程

通用步骤见公司统一配置 §6.7,本节仅列出 Vue2 专属命令。

  • Lint 命令:npm run lint(在 tofly-ui 目录下)

九、新建页面脚手架清单

  1. 创建 API 模块:list/get/add/update/delete/export
  2. 按顺序构建页面区域:搜索表单 → 工具栏操作 → 表格 → 分页 → 新增/编辑对话框
  3. 为每个操作添加 v-hasPermi 权限指令
  4. 添加表单校验规则
  5. 添加 reset/query/list 方法(标准命名)
  6. 通过 this.download 添加导出

十、复用清单

  • 复用 src/utils/request.js 而非新建 HTTP 封装
  • 复用全局辅助函数(this.$modalthis.downloadparseTimeaddDateRange
  • 复用权限指令 v-hasPermi
  • 复用字典/配置 API,而非创建新常量
  • 不引入新的前端框架/运行时模式

十一、代码模板

标准 CRUD 页面模板

<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
      <el-form-item label="名称" prop="name">
        <el-input v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter.native="handleQuery" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['hr:entity:add']">新增</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="success" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate" v-hasPermi="['hr:entity:edit']">修改</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete" v-hasPermi="['hr:entity:remove']">删除</el-button>
      </el-col>
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
    </el-row>

    <el-table v-loading="loading" :data="entityList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="ID" prop="id" />
      <el-table-column label="名称" prop="name" />
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['hr:entity:edit']">修改</el-button>
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['hr:entity:remove']">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <pagination
      v-show="total > 0"
      :total="total"
      :page.sync="queryParams.pageNum"
      :limit.sync="queryParams.pageSize"
      @pagination="getList"
    />
  </div>
</template>

<script>
import { listEntity, getEntity, delEntity, addEntity, updateEntity } from '@/api/hr/entity'

export default {
  name: 'Entity',
  data() {
    return {
      loading: true,
      ids: [],
      single: true,
      multiple: true,
      showSearch: true,
      total: 0,
      entityList: [],
      open: false,
      title: '',
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        name: undefined
      },
      form: {},
      rules: {}
    }
  },
  created() {
    this.getList()
  },
  methods: {
    getList() {
      this.loading = true
      listEntity(this.queryParams).then(response => {
        this.entityList = response.rows
        this.total = response.total
        this.loading = false
      })
    },
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.id)
      this.single = selection.length !== 1
      this.multiple = !selection.length
    },
    handleQuery() {
      this.queryParams.pageNum = 1
      this.getList()
    },
    resetQuery() {
      this.resetForm('queryForm')
      this.handleQuery()
    },
    handleAdd() {},
    handleUpdate(row) {},
    handleDelete(row) {}
  }
}
</script>

Dialog 表单提交模板

submitForm() {
  this.$refs['form'].validate(valid => {
    if (!valid) return
    const action = this.form.id ? updateEntity(this.form) : addEntity(this.form)
    action.then(() => {
      this.$modal.msgSuccess(this.form.id ? '修改成功' : '新增成功')
      this.open = false
      this.getList()
    })
  })
}

Flowable 任务表单提交模板

import { completeTask } from '@/views/todo/api/processTaks'

methods: {
  submitTask(taskId) {
    const variables = {
      comment: this.form.comment,
      approveResult: this.form.approveResult
    }
    completeTask(taskId, variables).then(() => {
      this.$message.success('办理成功')
      this.$emit('done')
    })
  }
}

注意:

  • 审批路由/逻辑保持在 Flowable 模型中,不在前端硬编码
  • 仅提交业务字段 + 流程变量
  • 尽可能使用已有的 todo/task API 模块

最后更新:2026-04-22 版本:5.0.0(公共规范已提取至公司统一配置 §六)