# MES CRUD 任务列表: {{Entity}}

## 全局约束

- 后端: `modules-center/{{module}}-center/{{module}}-service/`
- 前端: `implat-ui/src/`
- 数据库: Oracle
- 分支: `feature/{{entity}}-crud`

---

## 后端任务

### Task-001: 建表 SQL（Oracle）

- 文件: `sql/{{table_name}}.sql`
- 依赖: 无
- 描述: 创建数据库表，字段与提案中的字段清单对应
- 代码模板:

```sql
CREATE TABLE {{table_name}} (
  id                    NUMBER(19)      NOT NULL,
  -- 业务字段（根据提案补充）
  is_effect             NUMBER(1)       DEFAULT 1,
  created_by            VARCHAR2(64)    DEFAULT '',
  created_date          TIMESTAMP       DEFAULT SYSTIMESTAMP,
  last_updated_by       VARCHAR2(64)    DEFAULT '',
  last_updated_date     TIMESTAMP       DEFAULT SYSTIMESTAMP,
  CONSTRAINT pk_{{table_name}} PRIMARY KEY (id)
);
COMMENT ON TABLE {{table_name}} IS '{{table_comment}}';
```

- 验证: SQL 可在 Oracle 客户端执行

### Task-002: 创建 Entity 实体类

- 文件: `modules-center/{{module}}-center/{{module}}-service/src/main/java/com/twsz/mom/{{module}}/model/{{Entity}}.java`
- 依赖: Task-001
- 描述: 继承 `BaseModel`，声明业务字段。审计字段（createdBy 等）和主键（id）由 BaseModel 自动提供。
- 代码模板:

```java
package com.twsz.mom.{{module}}.model;

import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.twsz.mom.common.ds.model.BaseModel;
import lombok.Data;
import lombok.EqualsAndHashCode;

@Data
@EqualsAndHashCode(callSuper = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
@TableName("{{table_name}}")
public class {{Entity}} extends BaseModel {
    // 业务字段（审计字段由 BaseModel → TimeModel 提供）
    private Integer isEffect;
    // ... 根据提案中的字段清单补充
}
```

- 验证: 编译通过

### Task-003: 创建 Mapper 接口 + XML

- 文件:
  - `modules-center/{{module}}-center/{{module}}-service/src/main/java/com/twsz/mom/{{module}}/mapper/{{Entity}}Mapper.java`
  - `modules-center/{{module}}-center/{{module}}-service/src/main/resources/mapper/{{Entity}}Mapper.xml`
- 依赖: Task-002
- 描述: 继承 `BaseMapper<{{Entity}}>`，XML 包含标准的 Columns/Where/Joins 片段
- 代码模板（Mapper 接口）:

```java
package com.twsz.mom.{{module}}.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.twsz.mom.{{module}}.model.{{Entity}};
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;

@Mapper
public interface {{Entity}}Mapper extends BaseMapper<{{Entity}}> {
    IPage<{{Entity}}> pageSearch(Page<{{Entity}}> page, @Param("entity") {{Entity}} entity);
    List<{{Entity}}> list(@Param("entity") {{Entity}} entity);
}
```

- 代码模板（XML）: 参见 design.md 中的标准 XML 模板
- 验证: 编译通过，namespace 与 Mapper 接口全限定名匹配

### Task-004: 创建 Service 接口 + 实现

- 文件:
  - `modules-center/{{module}}-center/{{module}}-service/src/main/java/com/twsz/mom/{{module}}/service/{{Entity}}Service.java`
  - `modules-center/{{module}}-center/{{module}}-service/src/main/java/com/twsz/mom/{{module}}/service/impl/{{Entity}}ServiceImpl.java`
- 依赖: Task-003
- 描述: 继承 `IService<{{Entity}}>` / `ServiceImpl<Mapper, Entity>`，实现标准 CRUD 方法
- 代码模板: 参见 design.md 中的 Service 模板
- 验证: 编译通过

### Task-005: 创建 Controller

- 文件: `modules-center/{{module}}-center/{{module}}-service/src/main/java/com/twsz/mom/{{module}}/controller/{{Entity}}Controller.java`
- 依赖: Task-004
- 描述: `@RestController`，`@RequestMapping("/{{entity}}")`，返回 `ResponseWrapper<T>`
- 代码模板: 参见 design.md 中的 Controller 模板
- 验证: 编译通过，启动后可访问接口

---

## 前端任务

### Task-006: 创建 API 接口文件

- 文件: `implat-ui/src/api/{{domain}}/{{entity}}.js`
- 依赖: Task-005
- 描述: 封装 search/save/delete/list/export 五个标准方法
- 代码模板:

```js
import axios from '@/libs/request'
import { exportExcel } from '../file'

const apiPrefix = '/{{entity}}'

const search{{Entity}} = data =>
    axios.request({ url: `${apiPrefix}/search`, method: 'POST', data })

const save{{Entity}} = data => {
    const url = data.id ? `${apiPrefix}/update` : `${apiPrefix}/add`
    const method = data.id ? 'PUT' : 'POST'
    return axios.request({ url, method, data })
}

const delete{{Entity}} = ids =>
    axios.request({ url: `${apiPrefix}/delete`, method: 'DELETE', data: Array.isArray(ids) ? ids : [ids] })

const list{{Entity}} = data =>
    axios.request({ url: `${apiPrefix}/list`, method: 'POST', data })

const export{{Entity}} = data =>
    exportExcel(`${apiPrefix}/export`, data)

export default { search{{Entity}}, save{{Entity}}, delete{{Entity}}, list{{Entity}}, export{{Entity}} }
```

- 验证: 无语法错误

### Task-007: 创建列表页

- 文件: `implat-ui/src/views/{{domain}}/{{entity}}/index.vue`
- 依赖: Task-006
- 描述: 使用 `indexPage` mixin + `<search-table>` 组件，配置 option 对象和 tableColumns
- 代码模板: 参见 design.md 中的列表页模板
- 关键约定:
  - `mixins: [indexPage]` — 提供 showIndexPage/add/edit/view/refresh/triggerBack
  - `option.search.query` — 绑定 API search 方法
  - `option.delete.method` — 绑定 API delete 方法
  - `$t('key||中文')` — i18n 格式
- 验证: 页面可渲染，表格可加载数据

### Task-008: 创建表单页

- 文件: `implat-ui/src/views/{{domain}}/{{entity}}/{{entity}}-form.vue`
- 依赖: Task-006
- 描述: 使用 `<master-sub>` 组件 + `BaseMixin`，实现新增/编辑表单
- 代码模板: 参见 design.md 中的表单页模板
- 关键约定:
  - `mixins: [BaseMixin]` — 提供 loading/asyncLoading
  - `this.$refs.mform.validate()` — 表单验证
  - `this.$emit('on-success', data)` — 提交成功回调
  - `class="form"` — 自动两列布局
- 验证: 表单验证生效，提交成功返回列表

### Task-009: 菜单注册

- 文件: `sql/menu_{{entity}}.sql`
- 依赖: Task-008
- 描述: 向 `c_sys_resource` 表插入菜单和按钮权限记录
- 代码模板: 参见 menu-register.md
- 权限标识:
  - `{{module}}:{{entity}}:view` — 查看
  - `{{module}}:{{entity}}:add` — 新增
  - `{{module}}:{{entity}}:edit` — 修改
  - `{{module}}:{{entity}}:delete` — 删除
  - `{{module}}:{{entity}}:export` — 导出
- 验证: 执行 SQL 后刷新缓存，菜单可见

---

## 任务依赖图

```
Task-001 (建表)
  └─ Task-002 (Entity)
       └─ Task-003 (Mapper + XML)
            └─ Task-004 (Service)
                 └─ Task-005 (Controller)
                      └─ Task-006 (API 接口)
                           ├─ Task-007 (列表页)
                           └─ Task-008 (表单页)
                                └─ Task-009 (菜单注册)
```
